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

    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 и эквайринг я подключал впервые. Свою задачу, описанную в вопросе, я закрыл.
    Ответ написан
    Комментировать