Быстрый старт
Введение
Эта инструкция — о том, как организовать приём платежей через Payment Page. С тем, чтобы платёжная форма вызывалась из веб-сервиса и возвращала пользователей к нему. И чтобы при этом можно было использовать проверенные быстрые решения — с чёткими инструкциями, библиотеками и примерами кода И с использованием внутри программных решений на одном из трёх популярных языков программирования — PHP, Python или JavaScript.
Если вам актуально что-то другое, можно сориентироваться в вариантах.
- Если надо научиться делать платёжные ссылки для открытия Payment Page, можно разобраться с тем, как работать с ними вручную через Dashboard и автоматически через Gate.
- Если надо основательно разобраться со схемой и возможностями работы с Payment Page, можно пройти сюда.
- Если актуально что-то ещё, можно обратиться к другим разделам (например, начав здесь) и к специалистам ecommpay.
На этом с вводными всё. Можно переходить к делу.
Краткая теория
Проекты и ключи
Работу с платёжной платформой ecommpay можно сравнить с использованием услуг гостиницы. Так, для заселения в гостиницу обычно необходимо получить номер и ключ от него, а для начала работы с платформой надо получить... проект и ключ от него. И как с номерами в гостиницах, в платформе может предоставляться разное количество проектов для одного клиента — под разные цели и задачи — при этом для каждого проекта (как и для каждого гостиничного номера) необходим свой ключ.
Как правило, для работы достаточно одного тестового и одного рабочего проектов. Это типичный случай, и в рамках быстрого старта мы исходим из него. Если вам по какой-либо причине необходимо больше проектов, это стоит обсудить с курирующим менеджером, но начать всё также можно с одного тестового проекта.
Если у вас уже есть идентификатор тестового проекта (project_id
) и секретный ключ для него (secret_key
), можно приготовиться к их использованию и переходить дальше. Если же вы ещё не бронировали тестовый проект, самое время сделать это
через заявку на основном сайте компании и вернуться сюда.
Для начала работы с платформой следует получить проект и ключ от него. Если у вас уже есть идентификатор (project_id
) и ключ (secret_key
) тестового проекта, можно приготовиться к их использованию и переходить дальше. Если же вы ещё не оформляли тестовый проект, самое время это сделать
через заявку на основном сайте компании и вернуться сюда.
Схема работы
Чтобы корректно вызывать Payment Page, надо настроить сбор параметров, их подписывание и вызов формы. При этом подписывание данных (для которого необходим секретный ключ) важно выполнять в серверной части веб-сервиса, а вызов формы — в клиентской. Также для оперативного контроля результатов полезно настроить в серверной части приём оповещений от платёжной платформы.
В целом это выглядит так.
В клиентской части веб‑сервиса | В серверной части веб‑сервиса | В платёжной платформе | |
---|---|---|---|
1 | Формируем заказ. Фиксируем параметры платежа и передаём их в серверную часть (чтобы подписать) | – | – |
2 | – | Дополняем (если это актуально) и подписываем параметры платежа, после чего передаём информацию в клиентскую часть | – |
3 | Формируем и отправляем в платёжную платформу запрос на открытие Payment Page | – | – |
4 | – | – | Принимаем запрос, готовим и открываем форму пользователю, обрабатываем его действия и проводим платёж, после чего отправляем оповещение о результате платежа и возвращаем пользователя к веб-сервису |
5 | – | Принимаем оповещение о результате платежа и обновляем статус заказа | – |
6 | Отображаем пользователю информацию об оплате заказа и дальнейших действиях (если они необходимы, например для доставки товара) | – | – |
Реализовывать эту схему в клиентской и серверной частях веб-сервиса в общем случае можно самыми разными способами. Здесь, в рамках быстрого старта, для удобства и скорости запуска все необходимые процедуры описываются с максимальным использованием уже готовых компонентов (таких как SDK) и примеров кода. Но вы всегда можете варьировать наши готовые компоненты со своими решениями.
Параметры вызова формы
Чтобы открыть пользователю платёжную форму, в простейшем случае достаточно определиться с суммой и валютой платежа и добавить к этим двум параметрам три идентификатора: проекта, платежа и пользователя. Таким образом, обязательных параметров всего пять. (И технически к ним ещё обязательна подпись.)
Параметр | Описание |
---|---|
|
Идентификатор проекта. Его вместе с ключом выдаёт ecommpay и его важно точно указывать даже в тестовых запросах. Иначе… стоит ждать реакцию, как при попытке зайти в чужой гостиничный номер, от платёжной платформы. |
|
Идентификатор платежа. Он может быть произвольным, но каждый раз должен быть уникальным в рамках используемого проекта. Иначе стоит ждать ошибку вызова, от веб-сервиса. |
|
Сумма платежа. В тестовых запросах может быть произвольной, а в реальных должна точно соответствовать сумме заказа. Приводится, в дробных единицах валюты. |
|
Код валюты платежа. Приводится, в трёхбуквенном формате ISO 4217 alpha-3. В тестовых запросах могут использоваться любые из действующих кодов, а в реальных каждый раз должен использоваться код той валюты, в которой инициируется платёж. Для сверки можно использовать справочник валют. |
|
Идентификатор пользователя. Может быть произвольным и повторяемым в разных запросах, но для каждого реального пользователя должен быть однозначно сопоставляемым с его учётной записью в веб-сервисе и уникальным в рамках проекта. Иначе возможны различные коллизии, в том числе с отображением сохранённых данных платёжных инструментов одного пользователя другому. |
Как именно собирать эти параметры (и в том числе, какие из них задавать в клиентской части, а какие в серверной) — решать вам (с оглядкой на архитектуру вашего веб-сервиса и иные факторы). При этом для первых тестовых вызовов сбор параметров можно не автоматизировать вовсе, если что, этим можно заняться и после первичного тестирования работы с формой. Здесь же остаётся сказать, что в дополнение к обязательным параметрам можно использовать и другие, для управления видом и поведением платёжной формы, но поскольку с этими параметрами лучше разбираться после того, как настроен базовый вызов Payment Page, предметный разговор о них дальше.
Базовая реализация
Варианты работы
Реализовывать функции веб-сервиса для работы с платёжной формой и оповещениями можно по-разному, в том числе за счёт создания своих программных решений и за счёт применения CMS-модулей. В рамках быстрого старта мы рассматриваем два варианта реализации функций веб-сервиса для работы с платёжной формой и оповещениями:
- с применением в серверной части веб-сервиса SDK от ecommpay;
- с использованием в серверной части веб-сервиса готового кода от ecommpay
Различия между этими вариантами можно считать вкусовыми. С SDK может быть чуть проще, а также доступнее при работе с другими языками программирования (полный набор материалов о работе с SDK представлен в отдельном разделе). С примерами кода же может быть чуть прозрачнее и гибче в плане встраивания в свои решения (в том числе при работе с подписыванием данных). Но оба варианта достаточно быстры и полноценны, и вы можете выбрать любой из них.
Вместе с тем, независимо от варианта реализации серверных функций, в клиентской части веб-сервиса в рамках быстрого старта мы рассматриваем разные варианты вызова платёжной формы, в том числе с использованием библиотек от ecommpay. И в целом задачи реализации сводятся к следующим.
В серверной части | В клиентской части |
---|---|
|
|
Сбор и дополнение параметров, как и было сказано в теоретическом обзоре, могут выполняться разными способами (для первичного тестирования допустимо и вручную) и остаются за вами. Остальные действия разобраны далее.
Работа с SDK
Подключаем и настраиваем.
1 Подключаем SDK
- Если не делали этого ранее, загружаем, устанавливаем и настраиваем менеджер зависимостей Composer (https://getcomposer.org/).
- В командной строке операционной системы переходим в каталог с исходным кодом веб-сервиса и выполняем команду
composer require ecommpay/paymentpage-sdk
. - Подключаем скрипт
autoload.php
в исходном коде веб-сервиса.
// Подключение библиотек
require` __DIR__.'../../vendor.autoload.php';
2 Обеспечиваем подписывание данных
Когда для всех необходимых параметров определены их значения (и только в таком случае), можно собирать эти данные в серверной части веб-сервиса и формировать подпись и URL для вызова платёжной формы. Как это делать, можно разобрать на примере.
// Подписывание данных и формирование ссылки // создание объекта класса Payment и указание идентификаторов проекта и платежа $payment = new ecommpay Payment('57123', 'payment_443'); // указание других обязательных параметров $payment->setPaymentAmount(1815)->setPaymentCurrency('EUR'); // сумма и валюта платежа $payment->setCustomerId('customer_112'); // идентификатор пользователя // создание объекта класса Gate и указание секретного ключа $gate = new ecommpay\Gate('<secret_key>'); // формирование ссылки для вызова платёжной формы $url = $gate->getPurchasePaymentPageUrl($payment);
3 Настраиваем приём оповещений
Чтобы оперативно узнавать о результатах платежей и получать другую значимую информацию, следует настроить приём и обработку программных оповещений от платёжной платформы. Это делается в три шага:
- Определяем и задаём в платёжной платформе адрес для приёма веб-сервисом оповещений по проекту (сначала можно задать один общий адрес, а после — несколько, под разные события). Для этого открываем в интерфейсе Dashboard раздел Проекты и используем инструменты на вкладке Оповещения.
- Настраиваем проверку целостности и разбор оповещений, поступающих на указанный URL, с использованием SDK.
- Настраиваем отправку синхронных HTTP-ответов о приёме оповещений:
200 ОК
если подпись корректна и400 Bad Request
если подпись некорректна.
// Работа с оповещениями // создание объекта класса Gate и указание секретного ключа $gate = new ecommpay\Gate('<secret_key>'); // создание объекта класса Callback и указание JSON-строки с данными // из оповещения ($data), с проверкой целостности данных $callback = $gate->handleCallback($data); // использование методов для работы с оповещениями Callback::getPaymentId(); // получение идентификатора платежа Callback::getPaymentStatus(); // получение статуса платежа Callback::getPayment(); // получение всей информации из оповещения
Описания используемых статусов платежей можно найти в отдельном разделе, а описание оповещений и работы с ними — в отдельной статье. При этом важно помнить, что в случаях, когда пользователь не подтверждает оплату в платёжной форме, платёж не регистрируется (и статуса по нему тоже нет).
Извлечённую из оповещений информацию можно использовать для оперативного обновления статусов заказов в веб-сервисе, информирования пользователей и других целей — в соответствии с моделью работы вашего веб-сервиса.
1 Подключаем SDK
- Если не делали этого ранее, загружаем, устанавливаем и настраиваем систему управления пакетами pip (https://pip.pypa.io/en/stable/).
- В командной строке операционной системы переходим в каталог с исходным кодом веб-сервиса и выполняем команду
pip install ecommpay-sdk
. - Подключаем библиотеки из SDK в исходном коде веб-сервиса.
# Подключение библиотек from payment_page_sdk.gate import Gate from payment_page_sdk.payment import Payment
2 Обеспечиваем подписывание данных
Когда для всех необходимых параметров определены их значения (и только в таком случае), можно собирать эти данные в серверной части веб-сервиса и формировать подпись и URL для вызова платёжной формы. Как это делать, можно разобрать на примере.
# Подписывание данных и формирование ссылки # создание объекта класса Payment и указание идентификаторов проекта и платежа payment = Payment('57123', 'payment_443') # указание других обязательных параметров payment.payment_amount = 1815 # сумма платежа payment.payment_currency = 'EUR' # валюта платежа payment.customer_id = 'customer_112' # идентификатор пользователя # создание объекта класса Gate и указание секретного ключа gate = Gate('<secret_key>') # формированием ссылки для вызова платёжной формы payment_url = gate.get_purchase_payment_page_url(payment)
3 Настраиваем приём оповещений
Чтобы оперативно узнавать о результатах платежей и получать другую значимую информацию, следует настроить приём и обработку программных оповещений от платёжной платформы. Это делается в три шага:
- Определяем и задаём в платёжной платформе адрес для приёма веб-сервисом оповещений по проекту (сначала можно задать один общий адрес, а после — несколько, под разные события). Для этого открываем в интерфейсе Dashboard раздел Проекты и используем инструменты на вкладке Оповещения.
- Настраиваем проверку целостности и разбор оповещений, поступающих на указанный URL, с использованием SDK.
- Настраиваем отправку синхронных HTTP-ответов о приёме оповещений:
200 ОК
если подпись корректна и400 Bad Request
если подпись некорректна.
# Работа с оповещениями
# создание объекта класса Gate и указание секретного ключа
gate = Gate('<secret_key>')
# создание объекта класса Callback и указание JSON-строки с данными
# из оповещения (data), с проверкой целостности данных
callback = gate.handle_callback(data)
# использование методов для работы с оповещениями
callback.get_payment_id() # получение идентификатора платежа
callback.get_payment_status() # получение статуса платежа
callback.get_payment() # получение всей информации из оповещения
Описания используемых статусов платежей можно найти в отдельном разделе, а описание оповещений и работы с ними — в отдельной статье. При этом важно помнить, что в случаях, когда пользователь не подтверждает оплату в платёжной форме, платёж не регистрируется (и статуса по нему тоже нет).
Извлечённую из оповещений информацию можно использовать для оперативного обновления статусов заказов в веб-сервисе, информирования пользователей и других целей — в соответствии с моделью работы вашего веб-сервиса.
1 Подключаем SDK
- Если не делали этого ранее, загружаем, устанавливаем и настраиваем систему управления пакетами: Yarn (https://yarnpkg.com/en/docs/getting-started) или npm (https://www.npmjs.com/package/ecommpay).
- В командной строке операционной системы переходим в каталог с исходным кодом веб-сервиса и выполняем одну из команд:
yarn add ecommpay
илиnpm install ecommpay
. - Подключаем модули в исходном коде веб-сервиса.
const { Payment } = require('ecommpay'); const { Callback } = require('ecommpay');
2 Обеспечиваем подписывание данных
Когда для всех необходимых параметров определены их значения (и только в таком случае), можно собирать эти данные в серверной части веб-сервиса и формировать подпись и URL для вызова платёжной формы. Как это делать, можно разобрать на примере.
// Подписывание данных и формирование ссылки // создание объекта класса Payment и указание идентификатора проекта и секретного ключа const payment = new Payment('57123', 'payment_443'); // указание идентификатора платежа payment.paymentId = 'payment_443; // указание других обязательных параметров payment.paymentAmount = 1815 // сумма платежа payment.paymentCurrency = 'EUR' // валюта платежа payment.customerId = 'customer_112' // идентификатор пользователя // получение ссылки для вызова платёжной формы const url = payment.getUrl();
3 Настраиваем приём оповещений
Чтобы оперативно узнавать о результатах платежей и получать другую значимую информацию, следует настроить приём и обработку программных оповещений от платёжной платформы. Это делается в три шага:
- Определяем и задаём в платёжной платформе адрес для приёма веб-сервисом оповещений по проекту (сначала можно задать один общий адрес, а после — несколько, под разные события). Для этого открываем в интерфейсе Dashboard раздел Проекты и используем инструменты на вкладке Оповещения.
- Настраиваем проверку целостности и разбор оповещений, поступающих на указанный URL, с использованием SDK.
- Настраиваем отправку синхронных HTTP-ответов о приёме оповещений:
200 ОК
если подпись корректна и400 Bad Request
если подпись некорректна.
// Работа с оповещениями
// создние объекта класса Callback и указание секретного ключа
const callback = new Callback(<secret_key>, req.body);
// использование методов для работы с оповещениями
app.post('/payment/callback', function(req, res) {
const callback = new Callback(<secret_key>, req.body);
if (callback.isPaymentSuccess()) {
const paymentCont = callback.payment(); // получение всей информации о платеже
const paymentId = callback.getPaymentId(); // получение идентификатора платежа
// Здесь размещается исходный код для обработки оповещения проведённого платежа
}
});
Описания используемых статусов платежей можно найти в отдельном разделе, а описание оповещений и работы с ними — в отдельной статье. При этом важно помнить, что в случаях, когда пользователь не подтверждает оплату в платёжной форме, платёж не регистрируется (и статуса по нему тоже нет).
Извлечённую из оповещений информацию можно использовать для оперативного обновления статусов заказов в веб-сервисе, информирования пользователей и других целей — в соответствии с моделью работы вашего веб-сервиса.
Работа с кодом
Встраиваем и используем.
1 Обеспечиваем подписывание данных
// Кодирование алгоритма class Signer { const ALGORITHM = 'sha512'; const ITEMS_DELIMITER = ';'; /** * Generate signature * * @param array $params * @param string $secretKey * @param array $ignoreParamKeys * @param bool $doNotHash * * @return string */ public static function sign(array $params, string $secretKey, array $ignoreParamKeys = [], bool $doNotHash = false): string { $paramsPrepared = self::getParamsToSign($params, $ignoreParamKeys, 1, ''); $stringToSign = implode(self::ITEMS_DELIMITER, $paramsPrepared); return $doNotHash ? $stringToSign : base64_encode(hash_hmac(self::ALGORITHM, $stringToSign, $secretKey, true)); } /** * Get parameters to sign * * @param array $params * @param array $ignoreParamKeys * @param int $currentLevel * @param string $prefix * * @return array */ private static function getParamsToSign( array $params, array $ignoreParamKeys = [], int $currentLevel = 1, string $prefix = '' ): array { $paramsToSign = []; foreach ($params as $key => $value) { if (in_array($key, $ignoreParamKeys, true)) { continue; } $paramKey = ($prefix ? $prefix . ':' : '') . $key; if (is_object($value)) { $value = get_object_vars($value); } if (is_array($value)) { $subArray = self::getParamsToSign($value, $ignoreParamKeys, $currentLevel + 1, $paramKey); $paramsToSign = array_merge($paramsToSign, $subArray); } else { if (is_bool($value)) { $value = $value ? '1' : '0'; } else { $value = (string)$value; } $paramsToSign[$paramKey] = (string)$paramKey . ':' . $value; } } if ($currentLevel == 1) { ksort($paramsToSign, SORT_NATURAL); } return $paramsToSign; } // Пример использования // указание секретного ключа и параметров вызова платёжной формы $secretKey = "jwfbfjhewbrw33383kr3js9d987"; $params = [ 'project_id' => 57123, 'payment_amount' => 1815, 'payment_currency' => 'EUR', 'customer_id' => 'customer_112', 'payment_id' => 'payment_443', ]; // формирование подписи $params['signature'] = Signer::sign($params, $secretKey); // получение ссылки для вызова платёжной формы $uriParams = http_build_query($params); $link = implode('?', ['https://paymentpage.ecommpay.com/payment', $uriParams]);
2 Обеспечиваем приём оповещений
Чтобы оперативно узнавать о результатах платежей и получать другую значимую информацию, следует настроить приём и обработку программных оповещений от платёжной платформы. Это делается в три шага:
- Определяем и задаём в платёжной платформе адрес для приёма веб-сервисом оповещений по проекту (сначала можно задать один общий адрес, а после — несколько, под разные события). Для этого открываем в интерфейсе Dashboard раздел Проекты и используем инструменты на вкладке Оповещения.
- Настраиваем проверку целостности и разбор оповещений, поступающих на указанный URL, с использованием SDK.
- Настраиваем отправку синхронных HTTP-ответов о приёме оповещений:
200 ОК
если подпись корректна и400 Bad Request
если подпись некорректна.
// Работа с оповещениями. Пример сверки полученной подписи с расчётной require_once 'Signer.php'; $secretKey = '<secret_key>'; $requestBody = '{ "project_id": 57123, "payment": { "id": "payment_443", "type": "purchase", "status": "success", "date": "2022-03-03T10:50:29+0000", "method": "card", "sum": { "amount": 1815, "currency": "EUR" }, "description": "Test payment" }, "customer": { "id": "customer_112", "ip": "127.0.0.1", "phone": "60358490238", "email": "jane.doe@testmail.com" }, "operation": { "id": 15788000002076, "type": "sale", "status": "success", "date": "2022-03-03T10:50:29+0000", "sum_initial": { "amount": 1815, "currency": "EUR" }, "code": "0", "message": "Success" }, "signature": "zwoFECy7H+WZFziw9IgR9031Uu878TuIv3dhFyHvCuvzIdRAzDQA==" }'; $requestBodyArray = json_decode($requestBody, true); $actualSignature = $requestBodyArray['signature']; unset($requestBodyArray['signature']); $expectedSignature = Signer::sign($requestBodyArray, $secretKey); print_r('Actual signature: ' . $actualSignature . PHP_EOL); print_r('Expected signature: ' . $expectedSignature . PHP_EOL); if ($expectedSignature === $actualSignature) { print_r('Signatures are equal'); } else { print_r('Signatures are not equal'); } print_r(PHP_EOL);
Описания используемых статусов платежей можно найти в отдельном разделе, а описание оповещений и работы с ними — в отдельной статье. При этом важно помнить, что в случаях, когда пользователь не подтверждает оплату в платёжной форме, платёж не регистрируется (и статуса по нему тоже нет).
Извлечённую из оповещений информацию можно использовать для оперативного обновления статусов заказов в веб-сервисе, информирования пользователей и других целей — в соответствии с моделью работы вашего веб-сервиса.
1 Обеспечиваем подписывание данных
# Кодирование алгоритма import hmac import base64 import hashlib class Signer: def getSign(self, params, key): byteKey = key.encode() paramsPrepared = self.getParamsToSign(params) toSignString = ';'.join(paramsPrepared.values()) hmacObj = hmac.new(byteKey, toSignString.encode(), hashlib.sha512) return base64.b64encode(hmacObj.digest()) def getParamsToSign(self, params, currentLevel = 1, prefix = ''): paramsToSign = dict() for paramKey in params.keys(): newParamKey = (prefix + ':' if prefix else '') + paramKey if isinstance(params[paramKey], (dict)): subDict = self.getParamsToSign(params[paramKey], currentLevel + 1, newParamKey) paramsToSign.update(subDict) else: if isinstance(params[paramKey], (bool)): value = '1' if params[paramKey] == True else '0' else: value = str(params[paramKey]) paramsToSign[newParamKey] = str(newParamKey + ':' + value) sortedParams = dict() for key in sorted(paramsToSign.keys()): sortedParams[key] = paramsToSign[key] return sortedParams # Пример использования # указание параметров вызова платёжной формы и секретного ключа import urllib.parse import Signer params = { 'project_id': 57123, 'payment_amount': 1815, 'payment_currency': 'EUR', 'customer_id': 'customer_112', 'payment_id': 'payment_443', } # формирование подписи signer = Signer.Signer() params['signature'] = signer.getSign(params, '<secret_key>') print(params['signature']) # получение ссылки для вызова платёжной формы jointParams = urllib.parse.urlencode(params) link = '?'.join(['https://paymentpage.ecommpay.com/payment', jointParams])
2 Обеспечиваем приём оповещений
Чтобы оперативно узнавать о результатах платежей и получать другую значимую информацию, следует настроить приём и обработку программных оповещений от платёжной платформы. Это делается в три шага:
- Определяем и задаём в платёжной платформе адрес для приёма веб-сервисом оповещений по проекту (сначала можно задать один общий адрес, а после — несколько, под разные события). Для этого открываем в интерфейсе Dashboard раздел Проекты и используем инструменты на вкладке Оповещения.
- Настраиваем проверку целостности и разбор оповещений, поступающих на указанный URL, с использованием SDK.
- Настраиваем отправку синхронных HTTP-ответов о приёме оповещений:
200 ОК
если подпись корректна и400 Bad Request
если подпись некорректна.
# Работа с оповещениями. Пример сверки полученной подписи с расчётной from Signer import Signer import base64 secretKey = '<secret_key>' params = { "project_id": 57123, "payment": { "id": "payment_443", "type": "purchase", "status": "success", "date": "2022-03-03T10:50:29+0000", "method": "card", "sum": { "amount": 1815, "currency": "EUR" }, "description": "Gagarin set" }, "customer": { "id": "customer_112", "ip": "127.0.0.1", "phone": "60358490238", "email": "jane.doe@testmail.com" }, "operation": { "id": 15788000002076, "type": "sale", "status": "success", "date": "2022-03-03T10:50:29+0000", "sum_initial": { "amount": 1815, "currency": "EUR" }, "code": "0", "message": "Success" }, "signature": "zwoFECy7H+WZFziw9IgR90SEmC+o3qXD7OIaHqgQuqcSwBC09W6yQA==" } signer = Signer() actualSign = params['signature'] del params['signature'] expectedSign = signer.getSign(params, secretKey).decode() print('Actual signature:' + actualSign) print('Expected signature:' + expectedSign) if (expectedSign == actualSign): print('Signature is correct') else: print('Signature is incorrect')
Описания используемых статусов платежей можно найти в отдельном разделе, а описание оповещений и работы с ними — в отдельной статье. При этом важно помнить, что в случаях, когда пользователь не подтверждает оплату в платёжной форме, платёж не регистрируется (и статуса по нему тоже нет).
Извлечённую из оповещений информацию можно использовать для оперативного обновления статусов заказов в веб-сервисе, информирования пользователей и других целей — в соответствии с моделью работы вашего веб-сервиса.
1 Обеспечиваем подписывание данных
// Кодирование алгоритма import hmacSHA512 from 'crypto-js/hmac-sha512'; import encBase64 from 'crypto-js/enc-base64'; export class Signer { getSign(params, key) { const paramsPrepared = this.getParamsToSign(params, 1); const joinedString = Object.values(paramsPrepared).join(';'); const hash = hmacSHA512(joinedString, key); return hash.toString(encBase64); } getParamsToSign( params, prefix = '', ) { let paramsToSign = {}; let value = ''; let keys = Object.keys(params); let key = ''; for (let i = 0; i < keys.length; i++) { key = keys[i]; let paramKey = (prefix ? prefix + ':' : '') + key; if (typeof params[key] === 'object') { let subParams = this.getParamsToSign( params[key], paramKey, ); Object.assign(paramsToSign, subParams); } else { if (typeof params[key] === 'boolean') { value = params[key] === true ? '1' : '0'; } else { value = params[key].toString(); } paramsToSign[paramKey] = paramKey + ':' + value; } } let orderedKeys = Object.keys(paramsToSign).sort(); let ordered = {}; for (let k = 0; k < orderedKeys.length; k++) { ordered[orderedKeys[k]] = paramsToSign[orderedKeys[k]]; } return ordered; } } // Пример использования import { Signer } from './signer.js'; // указание параметров вызова платёжной формы и секретного ключа let params = { project_id: 57123, payment_amount: 1815, payment_currency: 'EUR', customer_id: 'customer_112', payment_id: 'payment_443', }; // формирование подписи params['signature'] = new signer().getSign(params, '<secret_key>'); // получение ссылки для вызова платёжной формы const uriParams = Object.keys(params) .sort() .reduce((paramsArray, key) => { paramsArray.push(key + '=' + encodeURIComponent(params[key])); return paramsArray; }, []); const link = [ 'https://paymentpage.ecommpay.com/payment', uriParams.join('&'), ].join('?');
2 Обеспечиваем приём оповещений
Чтобы оперативно узнавать о результатах платежей и получать другую значимую информацию, следует настроить приём и обработку программных оповещений от платёжной платформы. Это делается в три шага:
- Определяем и задаём в платёжной платформе адрес для приёма веб-сервисом оповещений по проекту (сначала можно задать один общий адрес, а после — несколько, под разные события). Для этого открываем в интерфейсе Dashboard раздел Проекты и используем инструменты на вкладке Оповещения.
- Настраиваем проверку целостности и разбор оповещений, поступающих на указанный URL, с использованием SDK.
- Настраиваем отправку синхронных HTTP-ответов о приёме оповещений:
200 ОК
если подпись корректна и400 Bad Request
если подпись некорректна.
// Работа с оповещениями. Пример сверки полученной подписи с расчётной import { Signer } from './Signer'; const secretKey = '<secret_key>'; const params = { "project_id": 57123, "payment": { "id": "payment_443", "type": "purchase", "status": "success", "date": "2022-03-03T10:50:29+0000", "method": "card", "sum": { "amount": 1815, "currency": "EUR" }, "description": "Gagarin set" }, "customer": { "id": "customer_112", "ip": "127.0.0.1", "phone": "60358490238", "email": "jane.doe@testmail.com" }, "operation": { "id": 15788000002076, "type": "sale", "status": "success", "date": "2022-03-03T10:50:29+0000", "sum_initial": { "amount": 1815, "currency": "EUR" }, "code": "0", "message": "Success" }, "signature": "zwoFECy7H+WZFziw9IgR90SHvCuvqXD7OIaHqgQuqcSwBC09W6yQA==" }; const actualSignature = params['signature']; delete params.signature; const expectedSignature = (new signer()).getSign(params, secretKey); console.log('Actual: ' + actualSignature); console.log('Expected: '+expectedSignature); if (actualSignature == expectedSignature) { console.log('Signatures is correct'); } else { console.log('Signature is incorrect'); }
Описания используемых статусов платежей можно найти в отдельном разделе, а описание оповещений и работы с ними — в отдельной статье. При этом важно помнить, что в случаях, когда пользователь не подтверждает оплату в платёжной форме, платёж не регистрируется (и статуса по нему тоже нет).
Извлечённую из оповещений информацию можно использовать для оперативного обновления статусов заказов в веб-сервисе, информирования пользователей и других целей — в соответствии с моделью работы вашего веб-сервиса.
Действия в клиентской части
Открывать Payment Page в клиентской части веб-сервиса можно по-разному, и для наглядности можно попробовать несколько способов даже в рамках быстрого старта.
Самый простой способ — открывать платёжную форму в отдельной вкладке браузера.
Чтобы открыть платёжную форму в виде отдельной HTML-страницы, следует использовать ссылку, полученную при подписывании данных. Это ссылка формата https://paymentpage.ecommpay.com/payment?<parameters>
, где <parameters>
— строка с названиями и значениями параметров вызова.
HTTP-запрос с применением метода GET в таком случае может выглядеть следующим образом:
GET
/payment?payment_currency=EUR&project_id=42&payment_amount=1000&
customer_id=123&payment_id=4438&signature=AE5hmtzdP0Dt7qGTg... HTTP/1.1
Host: https://paymentpage.ecommpay.com
Для использования других способов — с открытием платёжной формы в модальном окне и в элементе iframe — необходимо подключить две библиотеки: CSS для корректного отображения формы и JavaScript для вызова формы. Это делается через добавление ссылок на библиотеки в заголовочной части HTML-страницы.
<head> ... // подключение CSS-библиотеки <link rel="stylesheet" href="https://paymentpage.ecommpay.com/shared/merchant.css" /> // подключение JavaScript-библиотеки <script type="text/javascript" src="https://paymentpage.ecommpay.com/shared/merchant.js"> </script> ... </head>
Также для вызова платёжной формы с помощью JavaScript-библиотеки необходимо использовать подписанный набор параметров в виде JavaScript-объекта. Его можно формировать из ссылки, полученной при подписывании данных (в PHP для этого можно использовать функции parse_url
и parse_str
), или используя серверный код для формирования подписи (без составления ссылки) и добавляя подпись к остальным параметрам.
Подключив библиотеки и разобравшись с параметрами, можно пробовать.
Чтобы открыть Payment Page в модальном окне по щелчку кнопки на странице веб-сервиса, можно использовать метод bind
JavaScript-объекта EPayWidget
. При обращениях к этому объекту следует указывать идентификатор кнопки (pay_button_id
), объект с параметрами вызова Payment Page (configObj
) и HTTP-метод отправки запросов (method
):
EPayWidget.bind('pay_button_id', // идентификатор кнопки { payment_id: 'payment_443', // идентификатор платежа payment_amount: 1815, // сумма платежа payment_currency: 'EUR', // код валюты платежа project_id: 57123, // идентификатор проекта customer_id: 'customer_112', // идентификатор пользователя signature: 'YWb6Z20ByxpQ30hfTI' }, // подпись 'post') // HTTP-метод
Чтобы открыть Payment Page в элементе iframe по щелчку кнопки на странице веб-сервиса, как и в случае с модальным окном, можно использовать метод bind
JavaScript-объекта EPayWidget
. При обращениях к этому объекту следует указывать идентификатор кнопки (pay_button_id
), объект с параметрами вызова Payment Page (configObj
), идентификатор элемента, в котором необходимо отобразить платёжную форму (target_element
), и HTTP-метод отправки запросов (method
):
EPayWidget.bind('pay_button_id', // идентификатор кнопки { payment_id: 'payment_443', // идентификатор платежа payment_amount: 1815, // сумма платежа payment_currency: 'EUR', // код валюты платежа project_id: 57123, // идентификатор проекта customer_id: 'customer_112', // идентификатор пользователя signature: 'YWb6Z20ByxpQ30hfTI' }, // подпись target_element: 'widget-container', // идентификатор элемента 'post') // HTTP-метод
Для начального знакомства этих способов вызова и открытия может быть вполне достаточно. Если же необходима более тонкая настройка, можно обращаться к документации и к нашим специалистам.
Тестирование
Когда мы открываем платёжную форму в рабочем режиме, с ней работает пользователь. А в тестовом режиме можно почувствовать себя на его месте и протестировать разные сценарии оплаты с его позиции. Главный вопрос при этом — какие реквизиты указывать?
При работе с тестовым проектом можно использовать два вида платёжных реквизитов: специальные тестовые, позволяющие тестировать заданные сценарии работы, и произвольные реалистичные, позволяющие дополнительно проверить работу формы в разных случаях.
В базовом случае можно использовать следующие тестовые номера платёжных карт (для проведения платежей по заданным кратчайшим сценариям, без эмулирования аутентификации 3‑D Secure):
4000 0000 0000 0077
— для проведения оплаты;4111 1111 1111 1111
— для отклонения оплаты.
Для более масштабного тестирования можно использовать расширенный набор тестовых данных для карточных (в том числе с аутентификацией 3‑D Secure) и различных альтернативных платежей, а также произвольные данные, включая реквизиты реальных карт, кошельков и других платёжных инструментов. Это безопасно, поскольку для всех данных в тестовой среде обеспечивается тот же уровень защиты, что и в рабочей, но реальные платежи при этом не проводятся.
По итогам тестирования, убедившись в корректной работе с формой, можно считать реализованными базовые функции по проведению оплат и при желании переходить дальше — к различным дополнениям, которые могут быть полезны уже на первых порах работы с платёжной платформой, и к запуску решения в работу.
Дополнения
Контроль проведения платежей
После проведения нескольких тестовых платежей можно разобраться с тем, как контролировать общую ситуацию по платежам. Для этого следует открыть Dashboard и ознакомиться там с реестром и карточками платежей.
При возникновении вопросов по работе с этим интерфейсом, как и в иных случаях, можно обращаться к документации и к нашим специалистам.
Возврат средств
Если по какой-либо проведённой оплате необходимо выполнить возврат, для этого также можно использовать Dashboard. При тестировании работы с платёжной платформой можно попробовать выполнить полные и частичные возвраты из карточек платежей.
Для более глубокого освоения работы с возвратами, в том числе с массовыми, можно использовать отдельную статью. Кроме того, полезно иметь в виду возвраты через Gate.
Возможности управления формой
При работе с Payment Page можно оперировать различными возможностями, чтобы управлять видом и поведением формы, например, задавая подходящий язык, фильтруя методы оплаты или управляя способами возвращения пользователя к веб-сервису. Некоторые из таких возможностей требуют подключения через специалистов ecommpay, иные можно использовать без обращений к кому-либо, просто настроив их через Dashboard или передавая дополнительные параметры в запросах на открытие Payment Page.
При тестировании работы с Payment Page мы рекомендуем попробовать следующее:
- Настроить оформление платёжной формы с помощью конструктора.
Для этого следует перейти в раздел Проекты интерфейса Dashboard и воспользоваться инструментами вкладки Payment Page Designer (подробнее — в статье Индивидуальное оформление).
- Попробовать вызов платёжной формы на разных языках.
Чтобы открыть Payment Page на определённом языке, его код (в двухбуквенном формате ISO 639-1 alpha-2) следует передать в значении соответствующего параметра:
language_code
. Список поддерживаемых ecommpay языков можно найти здесь. - Возвращать пользователя к веб-сервису после проведения платежей.
После проведения платежей в зависимости от их результатов можно перенаправлять пользователей к разным страницам веб-сервиса. Адреса таких страниц можно задать в разделе Проекты интерфейса Dashboard (во вкладке Ссылки для перенаправления), либо передавать их в конкретных запросах в значении параметров
merchant_success_url
иmerchant_fail_url
. - И далее на ваш вкус.
Информацию о разных возможностях можно найти в общем обзоре и в специализированном разделе, а полный перечень параметров вызова — в отдельной статье. С вопросами же, как обычно, можно обращаться к нашим специалистам.
Запуск
После реализации базовых функций, тестирования разных возможностей и определения необходимых вам сценариев работы можно переходить к запуску рабочего проекта. Важно, чтобы к этому моменту были решены организационные вопросы. В таком случае вопросы технические сводятся к настройке свойств проекта на стороне платёжной платформы и к началу использования идентификатора и ключа рабочего проекта.
Успехов!