• Как прикрутить эквайринг от Сбера на сайт?

    imhateb
    @imhateb Автор вопроса
    В общем у меня всё получилось. Спасибо всем кто пытался помочь.
    На случай, если вдруг у кого-то возникнет похожая задача, я напишу как я её решил. Потому как от поддержки Сбера толку как с козла молока. Те ещё уроды. Постоянно отсылают к справке по API, где на мой вопрос тупо нет ответа.

    Сразу оговорюсь, мой способ может показаться дико костыльным, но он работает. Я в первый раз прикручивал эту оплату к готовому проекту. На правильность и идеальность решения не претендую. Просто хочу помочь таким же как я.

    Собственно сабж описан выше в вопросе. И мои домыслы были верны лишь отчасти. А именно, я не могу передать в запросе к банку информацию о заказе (наименование курса, данные покупателя: ФИО, телефон, email, город), и потом получить их обратно, чтобы отправить заявку. Можно передать эту информацию через &jsonParams= {"Имя":"Параметр"}, но она потом обратно не вернётся. Эти параметры могут быть использованы только в личном кабинете как доп. информация о транзакции.

    Так вот.
    Информацию о заказе надо где-то сохранить перед отправкой запроса в банк, а потом, после ответа, найти и использовать для отправки сообщения. Я решил использовать для этого текстовый файл, который создаётся при формировании запроса и имеет имя = ID заказа. В файл кладём всю нужную информацию, а потом по возвращении после оплаты, достаём и отправляем письмо.

    Собственно код обработчика формы. Точнее лишь та часть, которая отправляет запрос в банк.
    $timestamp = date('dmYHis');  // это у нас будет номер заказа 
    // $pre_order - это сумма, которую надо заплатить. Берётся из формы. 
    $pre_order = str_replace(' ', '', $pre_order); // Надо убрать пробел разделяющий разряды (ну типа 1 000 -> 1000)
    $pre_order = $pre_order*100; // и умножить на сто, т.к. в запросе в банк надо указывать сумму в копейках.
            
    // Отправляем запрос в банк
    $myCurl = curl_init();
    curl_setopt_array($myCurl, array(
        CURLOPT_URL => 'https://securepayments.sberbank.ru/payment/rest/register.do?userName=XXXXXXXXXXXXX-api&password=XXXXXXXXXXXXX&amount='.$pre_order.'&language=ru&orderNumber='.$timestamp.'&returnUrl=https://yoursite.com/send',   
    // Вот эта строка и есть запрос в банк. Тут нужно указать только свой userName, password, сумму и номер заказа, а так же returnUrl= адрес страницы куда мы вернёмся после оплаты. 
    // Сюда же можно добавить &jsonParams= {"Имя":"Параметр"}, о котором я писал выше. Но это такое...
    // Вообще в справке там много всяких доп. параметров описано, но я там ничего особо полезного не нашёл.  
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query(array(''))
    ));
    $response = curl_exec($myCurl);
    curl_close($myCurl);
    // Всё. Запрос отправлен. В ответ мы получаем строку с ID заказа и ссылкой на оплату.
    // Если выполнить echo $response, то можно эту строку увидеть.
    // Теперь нам надо из этой строки, полученной в ответ от банка, получить отдельно ID заказа, отдельно ссылку на оплату
    // Обрезаем ответ, чтобы получить url
    $url = strstr($response, 'https:');
    $url = strstr($url, '"', true);
    // Обрезаем ответ, чтобы получить id заказа
    $orderid = strstr($response, '","formUrl"', true);
    $orderid = mb_substr($orderid, 12); 
    
    // Создаём файл с именем = id заказа. Именно так, потому что потом мы по этому id этот файл и будем находить.
    $myfile='../orders/'.$orderid.'.txt';   
     
    // Заполняем его данными из формы
    $text .= $familiya.";";
    $text .= $imya.";";
    $text .= $otchestvo.";";
    $text .= $tel.";";
    $text .= $email.";";
    $text .= $city.";";
    $text .= $course_info.";";
    $text .= $price.";";
    $text .= $pre_order."";
        
    $file=fopen($myfile,'x+');
    fputs($file,$text);
    fclose($file);
        
    // Переходим на страницу оплаты. $url мы получили из ответа от банка
    header('Location: '.$url);

    Вот это всё я разместил в обработчике формы в том месте, где раньше была функция mail(), отправляющая письмо. Что получилось в результате? Теперь после заполнения формы и нажатия кнопки "Отправить", человек попадает на страницу оплаты. А после успешной оплаты, возвращается обратно на адрес указанный в returnUrl. Только к адресу будет добавлен тот самый ID заказа, который поможет нам найти нужный текстовый файл.

    На странице возврата (в примере это https://yoursite.com/send) нам надо подготовить ещё одну форму, которая уже будет отправлять заявку на почту.
    <form action="forms/send_mail.php" method="post" id="send_page">
            <input type="text" name="familiya" value="" >
            <input type="text" name="imya" value="" >
            <input type="text" name="otchestvo" value="" >
            <input type="tel" name="tel" value="" >
            <input type="email" name="email" value="" >
            <input type="text" name="city" value="" >
            <input type="text" name="course_info" value="" >
            <input type="text" name="pre_order" value="" >
            <input type="text" name="price" value="" >
    </form>

    Тут нам кнопка отправки не нужна, будем отправлять скриптом, после того как скриптом же заполним все поля. Делаем эту форму невидимой, чтобы не мельтешила при загрузке страницы.

    Скрипт, который находит нужный текстовый файл и заполняет поля формы:
    var url = document.location.href; // Палим урл страницы
    url = url.slice(url.indexOf('=')+1, url.lastIndexOf('&')); // режем его и получаем orderID, который отдал нам банк. Он нам нужен, чтобы найти соответствующий текстовый документ
    
    // Обращаемся к конкретному текстовому документу
    fetch('/orders/'+url+'.txt').then(response => response.text()).then((data) => {  
        var vars = ['familiya', 'imya', 'otchestvo', 'tel', 'email', 'city', 'course_info', 'price', 'pre_order'], // создаём массив с именами импутов
        info, i=0;            
        info = data.split(';'); // создаём массив со значениями, которые берём из текстового документа
                
        for (i; i<vars.length; i++) {  // перебираем массив и заполняем инпуты
            if (vars[i] == 'pre_order') {info[i] = info[i]/100;} // сумма оплаты у нас записана в копейках, поэтому надо привести к рублям
                $('.send_page').find('input[name='+vars[i]+']').attr('value', info[i]); // заполняем инпуты
            }
        });
    
    // отправляем форму спустя 300мс, чтобы инпуты успели заполниться
    setTimeout(function(){$("#send_page").submit()},300);

    Всё. Инпуты заполнены, форма отправилась простым обработчиком send_mail.php

    Буду рад, если мой тяжкий опыт будет кому-то полезен. Ощущаю, что метод очень костыльный, но, повторюсь я вообще не силён в PHP и эквайринг я подключал впервые. Свою задачу, описанную в вопросе, я закрыл.
    Ответ написан
    Комментировать
  • Как подружить Windows 10 + Docker + PhpStorm + Xdebug?

    @MKMatriX
    Дело в том как устроена сеть для докера под виндой, увы нужно указать айпишник виртуального адаптера докера, иначе никакого дебага.
    https://devilbox.readthedocs.io/en/latest/intermed...
    Как пример
    Ответ написан
    Комментировать
  • Как подружить Windows 10 + Docker + PhpStorm + Xdebug?

    denisbondar
    @denisbondar
    Python, PHP developer
    Добрый день.
    Я у себя в блоге недавно в деталях описал весь этот процесс. Работает гарантировано.
    Добро пожаловать!

    https://blog.denisbondar.com/post/phpstorm_docker_...
    Ответ написан
    5 комментариев
  • Можно ли давать в IT 100ю гарантию на что-либо?

    @StepEv
    Том ДеМарко, Тимоти Листер, "Вальсируя с медведями" объясняет почему нет и что с этим сделать. Как один из примеров.

    Ещё полезно задавать вопрос "А зачем?". Точно ли вашим зазказчикам нужны 100% гарантии? Или хватит 90% или даже 85%? Такие Service Level Agreements давать можно.

    В нашей области нельзя давать обещаний, можно давать прогнозы. Где-то, где у вас стабильная система и накопленно достаточно данных, можно давать достаточно точные прогнозы используя достаточно простые методы. Но часто система не стабильна в той или иной степени. И не всегда с этим можно что-то сделать. Чем точнее нужен прогноз, тем дороже его давать.

    Этой теме уделяет большое внимание Kanban метод.
    Ответ написан
    Комментировать
  • Как вернуть мотивацию к обучению?

    railsfun
    @railsfun
    Web Developer
    А никак ее не вернуть. Просто не думайте что все завязано на мотивацию.
    По моему высший пилотаж, и то к чему я стремлюсь сам в жизни (и это получается) - даже без мотивации что-то делать. Просто потому что нужно. Потому что так решил.
    Потому что, как говорить о мотивации если у человека все переменчиво? Аппетит, настроение, состояние здоровья. Да тысяча факторов.
    Это просто проблема нашего времени что внушается людям совершенно определенный пакет бреда, а именно:

    1. Вы не сможете чего-то достичь если не будете "мотивированы"
    2. Вы не сможете что-то сделать если "не в настроении".

    Осмелюсь сказать - это вранье. Все вы сможете. И дело даже не в затасканном слове "хотеть". Вот человек пишет ну нет мотивации. Не хочет, может. Настроение упало. И тд и тп.

    Если дело это действительно _его_ по нутру, он даже если не хочет найдет в себе силы продолжать.

    Секретов тут нет никаких. Просто делай и все. Или не делай. )

    А те кто добились в чем-то успеха могут вас многим грузить. Какими-то своими привычками, "секретами успеха" и прочей чушью. Или длинными реляциями о мотивации...

    Забейте на это. Есть вы и ваше дело. И ваше решение. И все. И никто не имеет права Вам здесь диктовать. Даже если это якобы делается из благих побуждений ("дать ему мотивацию", "научить мотивации"). Если это вас делает слабым, привязанным к слову "мотивация". Если заставляет забыть что вы так или иначе в состоянии сделать задуманное, мотивированы вы или нет - грош цена таким советам сразу говорю.

    Удачи автору и не менее удачи комментаторам )
    Ответ написан
    Комментировать
  • POS-периферия понятным языком?

    Svininykh
    @Svininykh
    OpenSource разработчик POS-систем
    Из универсальных стандартов, охватывающих все типы оборудования, на сегодня существует два:
    • если ведёте разработку на Java, то это JavaPOS;
    • если ведёте разработку для Windows, то это OPOS.

    Но есть ещё стандарты, которые стали де-факто универсальными для отдельного типа устройств. Например, ESC/POS для чеков принтеров и дисплеев покупателя. При этом у каждого производителя оборудования есть набор собственных команд, универсальных для всего выпускаемого модельного ряда устройств. Например, это протоколы Атол и Штрих-М для фискальных регистраторов.

    Если вы владеете Java, то могу порекомендовать посмотреть мой проект https://github.com/nordpos В нём по торговому оборудованию есть отдельный пакет кода https://github.com/nordpos/nordpos/tree/master/src... в котором собраны примеры для чековых и этикет принтеров, дисплеев покупателя, фискальных регистраторов, весов, ККМ и т.п. Посмотрите, попробуйте, может станет понятней.
    Ответ написан
    Комментировать
  • POS-периферия понятным языком?

    JhaoDa
    @JhaoDa
    LaravelRUS Team
    Я понимаю, что это некрофилия, но если вдруг кто заглянет в этот вопрос :)

    Во-первых, есть единые комплексы из системника, фискального регистратора (ФР), монитора и, возможно, чего-то ещё, собранное в одном корпусе или в общих модулях. Ставятся на учет в налоговую единым куском. И есть сборная солянка из чего угодно, на учет ставится только один ФР. Хотя опять же, деление зачастую весьма условно…

    Основные разновидности периферии и интерфейсов, применяемые в точках продаж (АРМ кассира):
    • программируемые клавиатуры, интерфейсы PS/2 и USB-HID;
    • ридеры магнитных и бесконтактных карт;
    • сканеры штрих-кода: светодиодные (надёжность топора, но дальность считывания едва ли пара сантиметров), лазерные (из-за точной механики средней силы удар может оказаться смертельным — сбивается юстировка зеркала, дальность считывания… ну 10-15 см точно можно получить), интерфейсы PS/2, COM, USB-HID, USB-COM (последние два как проводные, так и беспроводные — Wi-Fi, Bluetooth);
    • различные термо- и матричные принтеры, сюда же отнесём ФР, интерфейсы LPT, COM, USB, USB-VCOM, Bluetooth, Wi-Fi, Ethernet
    • дисплеи покупателя, LCD и VFD, последние более популярны, интерфейсы COM, USB-VCOM

    Производителей оборудования много, но особо выделяется Posiflex, производящий всё, вплоть до звонков на кухню.

    Украинская POSUA делает весьма приятные клавиатуры и ридеры карт.

    ChipherLab, Metroligic, Honeywell делают хорошие сканеры ШК.

    Некоторые протоколы стандартизованы, в частности OPOS, JPOS. Другие протоколы уже устоялись за годы как неофициальные стандарты.
    Ответ написан
    Комментировать
  • Что выбрать, Yii2 или Laravel?

    SamDark
    @SamDark
    Yii2 core team
    Как новичку вам будет очень полезно понять, что у фреймворка внутри и как он работает. Если залезть во внутренности Yii, вы увидите, что там документирован каждый метод, каждый класс, абстракции минимум, всё делается настолько просто, насколько это вообще возможно. Изучить именно как что работает просто.

    Если залезть в Laravel, там всё очень слоёно. Комментариев нет. Чтобы понять, как работает метод нужно частенько пролезть через 3—5 слоёв абстракции в нескольких классах.

    В документации по Laravel, кстати, использован крутой трюк. Описана лишь часть того, что вообще даёт фреймворк. Это делает доку очень компактной, лёгкой и приятной, но за остальным — либо код без комментариев читать, либо Laracasts смотреть.
    Ответ написан
    13 комментариев
  • Стоит ли начинать заниматься программированием в 30+ если до этого не программировал?

    opium
    @opium
    Просто люблю качественно работать
    Вы так говорите как будто в 30 лет у вас нет рук и ног и вывалился глаз.
    Берите и делайте и меньше задавайте глупых вопросов на тостере.
    Ответ написан
    5 комментариев
  • Зачем нужны таск менеджеры GULP и GRUNT?

    Мне кажется тут не хватает образного примера:

    Вот купили вы стул. До ужаса дешевый, а потому без инструкции по сборке. Помучились час другой, но собрали. И тут выясняется, что ваша подруга купила такой же стул, а собрать ума не хватает, и просит она вас. Вы уже опытный - за пол часа управились. Вы бы и быстрее управились, но все никак не могли найти куда присобачить последний шуруп.
    Потом случилось страшное - почти вся ваша родня узнала о дешевых стульях, и помчалась их покупать, а за советом как собирать их, как вы уже догадались, обращается к вам. Конечно разъезжать из дома в дом по столь неуважительной причине вам не с руки, вот тогда вы написали инструкцию и разослали ее всем по факсу.
    Время шло, город слухами полнился, и вот уже совершенно незнакомые люди обращаются к вам с просьбой какой либо предмет мебели. До поры до времени инструкции спасали, но потом нахлынула толпа бабушек, которым ваши каракули как пергамент на древнеегипетском...
    На этом этапе вы решили уволиться с основной работы и открыть собственное дело по производству роботов-сборщиков (не путайте с роботами-сгибателями). Вам звонят бабушки, а вы им высылаете свои агрегаты, подчас загружая в них инструкцию по строительству дома.

    Вот и сказочке конец, а кто слушал, тот и gulp.

    Простите - пятница.
    Ответ написан
    Комментировать
  • Что такое селекторы и делегаты в Objective-C?

    deleted-mezhevikin
    @deleted-mezhevikin
    Вы какую-то сложную и ненужную книгу читаете, открывайте оф. документацию и изучаете на примерах.

    Простыми словами:
    Селектор - это метод который обработает какое-то действие

    Например: у нас есть кнопка и мы указываем селектор с методом myButtonWasPressed, этот метод будет вызван по нажатию на кнопку.

    [myButton addTarget:self
                 action:@selector(myButtonWasPressed)
       forControlEvents:UIControlEventTouchUpInside];
    
    - (void)myButtonWasPressed {
        // Do something about it
    }


    Делегат - это когда один класс работает внутри другого класса. Например у нас есть таблица UITableView и мы хотим чтобы она отображалась в контроллере MainViewController, мы устанавливаем для таблицы делегат MainViewController и теперь методы делегаты для построения ячейки таблицы будут вызываться в MainViewController
    Ответ написан
    2 комментария
  • Что должен знать и делать ведущий разработчик?

    @totosarg
    Проверял? Проверял. Работает? Работает. Не трогай!
    Могу поделиться своим американским опытом, я тимлид, у нас в компании 5 команд. Каждый тимлид, в том числе и я должны:

    Работать с менеджерами по проектам (которые формулируют задачи в целом)
    Распределять работу внутри команды
    Следить за своевременным исполнением работы
    Проверять качество кода младших разработчиков
    Нести ответственность за свою команду (спрашивать будут именно с тимлида)
    Составлять тонны всяких отчетов
    Тимлид отчитывается перед менеджером по разработке.

    Кстати, у нас в компании тимлиды программируют не меньше остальных, а спрос с тимлида больше.
    Тимлид не обязан знать больше чем члены его команды, однако он как правило спец в своей области.
    Тимлид во многом администратор. Однако, он и программист. Тимлид принимает решения по поводу
    тех или иных подходов к решению поставленных задач. Я бы сказал что тимлид это самая первая
    ступень на менеджерском пути.
    Ответ написан
    4 комментария