Сбербанк эквайринг на php

19 Августа 2019 23:25 (Редактировано: 12 Ноября 2019 00:57)

Подключать будем обычную одностадийную оплату без возможности возврата средств (это, возможно, добавлю позже если будет время или заказы). Алгоритм заключается в следующем:

  1. Клиент заключает договор со Сбером. Ему выдают данные для работы на тестовой среде. Данные, которые нам понадобятся:
    • Логин;
    • Пароль;
    • Api token;
    • Ссылка для отправки запросов на тестовой среде. Для всех клиентов она, по сути, одна - 
    • Набор карт для тестирования с разными статусами работы (с ошибками, с оплатой и т.д.)
  2. Далее нам необходимо написать скрипт, который будет отправлять запрос Сберу на регистрацию заказа со следующими параметрами:
    • token (или логин и пароль, как удобнее. Но используем что-либо одно - либо токен, либо пару логин и пароль, все вместе нельзя, вернется ошибка);
    • orderNumber - номер заказа, который генерируется в интернет-магазине. По сути, любое число.
    • amount - цена заказа. Здесь необходимо цену умножать на 100 т.к. Сбер все считает в копейках и если, например, стоимость заказа 19 450 руб. то Сбер это поймет как 194 рубля 50 копеек т.е. отодвинет запятую на 2 знака справа;
    • returnUrl - адрес возврата клиента после оплаты. Здесь передаем url, например, "http://unreal-stuff.ru/payments/". На этой странице можно разместить информацию об успешной оплате и передать номер заказа.
  3. Тестируем оплату. Для начала, это можно делать обычными запросами через curl, чтобы проверить, что клиент нам предоставил корректные данные. Пример скрипта:
<?php
$data = array(
    'userName' => 'testlogin-api',
    'password' => 'Password%2a1',
    'orderNumber' => '4223',
    'amount' => '19450',
    'returnUrl' => 'http://unreal-stuff.ru/payments/'
);
$curl = curl_init();
curl_setopt_array($curl,
    array(
        CURLOPT_URL => 'https://3dsec.sberbank.ru/payment/rest/register.do',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query($data)
    )

);
$response = curl_exec($curl);
$out = json_decode($response, true);
curl_close($curl);

echo "<pre>";
print_r($out);
echo "</pre>";

Далее, если все хорошо, Сбер отдаст нам массив со следующими данными:

Это означает, что все ок и мы можем редиректить клиента по ссылке, указанной в formUrl. Как только мы полностью напишем скрипт и он будет редиректить по указанной ссылке то мы будем попадать на такую страницу:

Примечание. Здесь мы не умножили цену на 100, поэтому результат получился такой, каким я описывал его ранее!

На этой странице можно поигратсья с картами и посмотреть на реакцию сервиса на различные карты (в которые зашиты определенные ошибки типа не хватает средств и т.д.) . После проведения оплаты на этой странице, Сбер редиректнет нас на страницу, которую мы указали ранее - http://unreal-stuff.ru/payments/

Перевод на боевую среду заключается лишь в изменении логина, пароля и ссылки для отправки запроса. url должен будет выглядет уже следующим образом:

CURLOPT_URL => 'https://securepayments.sberbank.ru/payment/rest/register.do'

Важно, чтобы клиент, с которым вы работаете, сменил пароль. В моем случае клиент этого не сделал и мне возвращалась 5 ошибка:

Такое происходит в случаях если:

  • Не была проведена процедура смены транспортного пароля Password*1 на постоянный
  • Происходит обращение с парой логин/пароль, предназначенной для тестовой среды, к боевой среде

Как писать скрипт - личное дело каждого. Все зависит от CMS, с которой вы работаете! Я припиливал этот функционал на modx к уже существующему модулю оплат.

Вот пример скрипта, который дает сам Сбербанк:

<?php

/**
 * ДАННЫЕ ДЛЯ ПОДКЛЮЧЕНИЯ К ПЛАТЕЖНОМУ ШЛЮЗУ
 *
 * USERNAME             Логин магазина, полученный при подключении.
 * PASSWORD             Пароль магазина, полученный при подключении.
 * GATEWAY_URL  Адрес платежного шлюза.
 * RETURN_URL   Адрес, на который надо перенаправить пользователя 
 *                              в случае успешной оплаты.
 */
define('TOKEN', 'test-tokent')
define('USERNAME', 'test-api');
define('PASSWORD', 'testpass');
define('GATEWAY_URL', 'https://3dsec.sberbank.ru/payment/invoice/index.html?token=' . TOKEN);
define('RETURN_URL', '***');

/**
 * ФУНКЦИЯ ДЛЯ ВЗАИМОДЕЙСТВИЯ С ПЛАТЕЖНЫМ ШЛЮЗОМ
 * 
 * Для отправки POST запросов на платежный шлюз используется
 * стандартная библиотека cURL.
 *
 * ПАРАМЕТРЫ
 *              method          Метод из API.
 *              data            Массив данных.
 *
 * ОТВЕТ
 *              response        Ответ.
 */
function gateway($method, $data) {
        $curl = curl_init(); // Инициализируем запрос
        curl_setopt_array($curl, array(
            CURLOPT_URL => GATEWAY_URL.$method, // Полный адрес метода
            CURLOPT_RETURNTRANSFER => true, // Возвращать ответ
            CURLOPT_POST => true, // Метод POST
            CURLOPT_POSTFIELDS => http_build_query($data) // Данные в запросе
        ));
        $response = curl_exec($curl); // Выполненяем запрос
        
        $response = json_decode($response, true); // Декодируем из JSON в массив
        curl_close($curl); // Закрываем соединение
        return $response; // Возвращаем ответ
}

/**
 * ВЫВОД ФОРМЫ НА ЭКРАН
 */
if ($_SERVER['REQUEST_METHOD'] == 'GET' && !isset($_GET['orderId'])) {
        echo '
                <form method="post" action="/rest.php">
                        <label>Order number</label><br />
                        <input type="text" name="orderNumber" /><br />
                        <label>Amount</label><br />
                        <input type="text" name="amount" /><br />
                        <button type="submit">Submit</button>
                </form>
        ';
}

/**
 * ОБРАБОТКА ДАННЫХ ИЗ ФОРМЫ
 */
else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
        $data = array(
                'userName' => USERNAME,
                'password' => PASSWORD,
                'orderNumber' => urlencode($_POST['orderNumber']), 
                'amount' => urlencode($_POST['amount']),
                'returnUrl' => RETURN_URL
        );

        /**
         * ЗАПРОС РЕГИСТРАЦИИ ОДНОСТАДИЙНОГО ПЛАТЕЖА В ПЛАТЕЖНОМ ШЛЮЗЕ
         *              register.do
         * 
         * ПАРАМЕТРЫ
         *              userName                        Логин магазина.
         *              password                        Пароль магазина.
         *              orderNumber                     Уникальный идентификатор заказа в магазине.
         *              amount                          Сумма заказа.
         *              returnUrl                       Адрес, на который надо перенаправить пользователя в случае успешной оплаты.
         *
         * ОТВЕТ
         *              В случае ошибки:
         *                      errorCode               Код ошибки. Список возможных значений приведен в таблице ниже.
         *                      errorMessage    Описание ошибки.
         *
         *              В случае успешной регистрации:
         *                      orderId                 Номер заказа в платежной системе. Уникален в пределах системы.
         *                      formUrl                 URL платежной формы, на который надо перенаправить браузер клиента.
         *
         *      Код ошибки              Описание
         *              0                       Обработка запроса прошла без системных ошибок.
         *              1                       Заказ с таким номером уже зарегистрирован в системе.
         *              3                       Неизвестная (запрещенная) валюта.
         *              4                       Отсутствует обязательный параметр запроса.
         *              5                       Ошибка значения параметра запроса.
         *              7                       Системная ошибка.
         */
        $response = gateway('register.do', $data);
        
        /**
         * ЗАПРОС РЕГИСТРАЦИИ ДВУХСТАДИЙНОГО ПЛАТЕЖА В ПЛАТЕЖНОМ ШЛЮЗЕ
         *              registerPreAuth.do
         *
         * Параметры и ответ точно такие же, как и в предыдущем методе.
         * Необходимо вызывать либо register.do, либо registerPreAuth.do.
         */
//      $response = gateway('registerPreAuth.do', $data);
        
        if (isset($response['errorCode'])) { // В случае ошибки вывести ее
                echo 'Ошибка #' . $response['errorCode'] . ': ' . $response['errorMessage'];
        } else { // В случае успеха перенаправить пользователя на плетжную форму
                header('Location: ' . $response['formUrl']);
                die();
        }
} 

/**
 * ОБРАБОТКА ДАННЫХ ПОСЛЕ ПЛАТЕЖНОЙ ФОРМЫ
 */
else if ($_SERVER['REQUEST_METHOD'] == 'GET' && isset($_GET['orderId'])){
        $data = array(
                'userName' => USERNAME,
                'password' => PASSWORD,
                'orderId' => $_GET['orderId']
        );
        
        /**
         * ЗАПРОС СОСТОЯНИЯ ЗАКАЗА
         *              getOrderStatus
         *
         * ПАРАМЕТРЫ
         *              userName                        Логин магазина.
         *              password                        Пароль магазина.
         *              orderId                         Номер заказа в платежной системе. Уникален в пределах системы.
         * 
         * ОТВЕТ
         *              ErrorCode                       Код ошибки. Список возможных значений приведен в таблице ниже.
         *              OrderStatus                     По значению этого параметра определяется состояние заказа в платежной системе. 
         *                                                      Список возможных значений приведен в таблице ниже. Отсутствует, если заказ не был найден.
         *
         *      Код ошибки              Описание
         *              0                       Обработка запроса прошла без системных ошибок.
         *              2                       Заказ отклонен по причине ошибки в реквизитах платежа.
         *              5                       Доступ запрещён;
         *                                      Пользователь должен сменить свой пароль;
         *                                      Номер заказа не указан.
         *              6                       Неизвестный номер заказа.
         *              7                       Системная ошибка.
         *
         *      Статус заказа   Описание
         *              0                       Заказ зарегистрирован, но не оплачен.
         *              1                       Предавторизованная сумма захолдирована (для двухстадийных платежей).
         *              2                       Проведена полная авторизация суммы заказа.
         *              3                       Авторизация отменена.
         *              4                       По транзакции была проведена операция возврата.
         *              5                       Инициирована авторизация через ACS банка-эмитента.
         *              6                       Авторизация отклонена.
         */
        $response = gateway('getOrderStatus.do', $data);
        
        // Вывод кода ошибки и статус заказа
        echo '
                <b>Error code:</b> ' . $response['ErrorCode'] . '<br />
                <b>Order status:</b> ' . $response['OrderStatus'] . '<br />
        ';
}

?>

Также, для Сбера может понадобиться, чтобы на сайте были выполнены определенные условия, а именно:

  1. Чтобы на сайте была отображения информация о доставке и оплате;
  2. Необходимо, чтобы информация о доставке и оплате была на видном месте (например, в качестве пунктов в горизонтальном меню);
  3. Реквизиты организации в контактах или, также, в пункте меню. Можно сделать кнопку в контактах, по нажатию на которую появится всплываха с реквизитами:
    • Организация
    • ИНН
    • ОГРН
    • Юридический адрес

Вложения

1. Документация по подключению к платежному шлюзу

2. Тестовые карты