В системе EasyPay предусмотрена возможность оперативного информирования Поставщика товаров и услуг о совершаемых пользователями платежах.
Типы Уведомлений:
Уведомление Поставщика об оплатах осуществляется по протоколу HTTP (HTTPS) в виде специальных сообщений, отсылаемых POST-запросом. Подлежат уведомлению счета, которые были приняты в обработку, оплачены и не были отменены. Каждый такой счет-заказ подтверждается одним сообщением.
При необходимости формируется ежесуточный реестр платежей и отправляется по HTTP (HTTPS) в виде XML-документа.
Каждое сообщение подписывается электронной подписью, которая имеет вид строки md5-хэша, являющейся объединением всех полей счета-заказа и секретного ключа. Чтобы получить ключ, обратитесь в службу технической поддержки EasyPay.
Запрос с Уведомлением Поставщика о совершенном платеже будет отсылаться до тех пор, пока Поставщик его не примет, то есть до получения ответа с кодом "HTTP/1.0 200 OK".
В случае, если сайт Поставщика (по техническим или другим причинам) не может обработать запрос, он должен сгенерировать ответ с любым кодом ошибки, например "HTTP/1.0 400 Bad Request". Недопустимо отвечать кодом "HTTP/1.0 200 OK" на необработанное уведомление.
Уведомления отсылаются по специальному расписанию, но не более n раз, где n = 10 (задается EasyPay). Если сервер Поставщика после n-го запроса не дает положительного ответа, то на электронный адрес Поставщика отсылается письмо с предупреждением о сбое.
Расписание отправки уведомлений:
Процессинговый центр формирует и отправляет сообщение об оплате, подписанное секретным ключом web_key, Поставщику. Ключ известен обеим сторонам, но в запросе не передается.
Поставщик проверяет электронную подпись и сверяет данные заказа.
Поставщик проверяет (одним или несколькими способами) оплату заказа:
Последний шаг не является обязательным, но его рекомендуется использовать как способ удостовериться в подлинности уведомления. Дополнительно Поставщик может установить проверку по доменному имени или по IP-адресу.
Для реализации уведомлений при подключении Поставщика к EasyPay задаются следующие параметры:
web_key – ключ (случайная последовательность символов), участвующий в электронной подписи сообщения.
При формировании каждого сообщения, которое отсылается POST-запросом на соответствующий URL, используются следующие поля:
| Название полей | Формат полей | Описание полей |
|---|---|---|
| order_mer_code | от 1 до 20 алфавитно-цифровых символов | уникальный номер электронного счета. Формируется Поставщиком. Должен быть уникальным в течении всего периода работы с EasyPay |
| sum | число больше нуля | сумма в белорусских рублях |
| mer_no | 6 алфавитно-цифровых символов вида okXXXX, где X – число от 0 до 9 | номер Поставщика в EasyPay. Выдается Администратором EasyPay при регистрации |
| card | PT_CARD для банковских карт, PT_ERIP для счетов ЕРИП, PT_EPOS для счетов E-POS | способ оплаты |
| purch_date | ГГГГ-ММ-ДД ЧЧ:ММ:СС | дата и время оплаты счета |
| notify_signature | 32 алфавитно-цифровых символов | электронная подпись электронного счета |
| xml_data | От 0 до 64 килобайта текстовой информации в произвольной форме | дополнительный XML или другие текстовые данные |
При формировании реестра платежей за предыдущие сутки создается XML-документ, который передается в поле ep_notify_register:
<?xml version="1.0" encoding="windows-1251"?> <easypay function="ep_notify_register" date="2006-09-11"> <invoices count="2" total_sum="300.00"> <invoice> <order_mer_code>1000</order_mer_code> <sum>100.00</sum> <mer_no>ok6666</mer_no> <card>PT_ERIP</card> <purch_date>2006-09-11 22:45:21</purch_date> <xml_data>text</xml_data> </invoice> <invoice> <order_mer_code>1001</order_mer_code> <sum>200.00</sum> <mer_no>ok6666</mer_no> <card>PT_CARD</card> <purch_date>2006-09-11 21:44:20</purch_date> <xml_data>text</xml_data> </invoice> </invoices> </easypay>
В случае подтверждения счета, электронная подпись формируется с участием полей order_mer_code, sum, mer_no, card, purch_date, web_key, следующих в указанном порядке по алгоритму: notify_signature = md5 (order_mer_code . sum . mer_no . card . purch_date . web_key)
При получении уведомления Поставщик проверяет подлинность этого сообщения по его электронной подписи.
<?php
/*
Пример на PHP обработчика одиночных уведомлений (для реестра платежей аналогично)
Принимает и логирует уведомления EasyPay, но ничего с ними не делает
Поставщик осуществляет обработку уведомлений
в соответствии с особенностями своей работы
*/
$logfilepath = '/test/logs/notify.log'; //путь к файлу логирования
$web_key = 'dh48djklhgl5893j'; //ключ, участвующий в электронной подписи сообщения
//Если у Вас нет ключа, то обратитесь в службу технической поддержки EasyPay
$post_params = array (
'order_mer_code' =>
isset($_POST['order_mer_code']) ? $_POST['order_mer_code'] : '',
'sum' =>
isset($_POST['sum']) ? $_POST['sum'] : '',
'mer_no' =>
isset($_POST['mer_no']) ? $_POST['mer_no'] : '',
'card' =>
isset($_POST['card']) ? $_POST['card'] : '',
'purch_date' =>
isset($_POST['purch_date']) ? $_POST['purch_date'] : '',
'notify_signature' =>
isset($_POST['notify_signature']) ? $_POST['notify_signature'] : '',
'xml_data' =>
isset($_POST['xml_data']) ? $_POST['xml_data'] : '',
);
main ($logfilepath, $web_key, $post_params);
function main($logfilepath, $web_key, $post_params) {
// пример обработки ежесуточного реестра платежей
if (isset($_POST['ep_notify_register'])) { // обработка реестра платежей
$processed = ProcessDailyNotify($_POST['ep_notify_register']);
if ($processed) { //реестр обработан
$status = 'OK | the register is processed'; // статус обработки
header("HTTP/1.0 200 OK"); // генерация HTTP-заголовка
print $status; // формирование контента
} else { //реестр не обработан
$status = 'FAILED | the register is not processed';
header("HTTP/1.0 400 Bad Request");
print $status;
}
} else { // обработка уведомления
//вычисляем электронную подпись и сравниваем с переданной
$notify_signature = CreateAuthorizationKey ($web_key, $post_params);
if($notify_signature == $post_params['notify_signature']) {
//осуществляем обработку уведомления и логирование как пример
$processed = ProcessNotify($post_params);
if ($processed) { //уведомление обработано
$status = 'OK | the notice is processed'; //статус обр.
header("HTTP/1.0 200 OK"); // генерация HTTP-заголовка
print $status; // формирование контента
} else { //уведомление не обработано
$status = 'FAILED | the notice is not processed';
header("HTTP/1.0 400 Bad Request");
print $status;
}
} else { //неверная электронная подпись
$status = 'FAILED | incorrect digital signature';
header("HTTP/1.0 400 Bad Request");
print $status;
}
//подготовка параметров для логирования
$params_line = '';
foreach ($post_params as $key=>$value) {
$params_line .= "$key=$value; ";
}
CreateLog($status, $params_line); //логирование
}
}
function CreateAuthorizationKey ($web_key, $post_params) {//функция вычисления эл. подписи
// правило вычисления:
// notify_signature = md5(order_mer_code. sum. mer_no. card. purch_date. web_key)
$hash = md5($post_params['order_mer_code'].$post_params['sum'].
$post_params['mer_no'].$post_params['card'].$post_params['purch_date'].$web_key);
return $hash;
}
function ProcessNotify($post_params) { // функция реализует логику обработки уведомлений
// Поставщик осуществляет обработку уведомлений
// в соответствии с особенностями своей работы
// обработка xml_data
// дополнительная проверка оплаты счета через SOAP для безопасности
$soap_check = SOAPIsInvoicePaid($post_params['order_mer_code']);
// 1 - уведомление обработано, 0 - уведомление не обработано
return 1;
}
fucntion SOAPIsInvoicePaid($order_mer_code) { //функция проверки оплаты счета через SOAP
// Поставщик дополнительно осуществляет проверку оплаты счёта по SOAP
// функцией EP_IsInvoicePaid
// https://ssl.easypay.by/soap/
// 1 - счет оплачен, 0 - счет не оплачен
return 1;
}
function ProcessDailyNotify($post_params) { // функция реализует логику обработки реестра
// Поставщик осуществляет обработку реестра
// в соответствии с особенностями своей работы
// 1 - ежесуточный реестр обработан, 0 - не обработан
return 1;
}
function CreateLog ($status, $request) { //функция добавления записи в логфайл
global $logfilepath;
$date = date("d.m.Y H:i:s");
$str = $date."\t".$status."\n\t"."ORDER_INFORMATION: ".$request."\n";
$log = fopen($logfilepath, 'a');
if($log) {
fwrite($log, $str);
fclose($log);
}
}
?>