Протокол взаимодействия с платежной системой — различия между версиями

Материал из doc.abonent.plus
Перейти к: навигация, поиск
(Ответ)
 
(не показаны 64 промежуточные версии 2 участников)
Строка 1: Строка 1:
== Протокол взаимодействия платежной системы и агента по приему платежей (Спецификация) ==
+
В данном документе описан регламент технического взаимодействия платежной системы «Абонент» с программным обеспечением агента по приему платежей по протоколу HTTP(S).
  
В данном документе описан регламент технического взаимодействия платежной системы «Абонент» с программным обеспечением агента по приему платежей по протоколу HTTP(S).
 
 
Документ предназначен для разработчиков программного обеспечения работающего на стороне агентов по приему платежей.
 
Документ предназначен для разработчиков программного обеспечения работающего на стороне агентов по приему платежей.
 +
 +
== Термины и определения ==
 +
'''Система''' – платежная система «Абонент».
 +
 +
'''Агент''' – организация, осуществляющая прием оплаты через платежную систему «Абонент».
 +
 +
'''Клиент''' - программное обеспечение Агента, реализующее клиентскую часть настоящего протокола.
 +
 +
== Общие принципы взаимодействия с Системой ==
 +
Взаимодействие с системой осуществляется в режиме запрос – ответ. Инициатором взаимодействия во всех случаях является Клиент.
 +
 +
=== Запрос ===
 +
Представляет собой текстовый блок данных, структурированных в соответствии с требованиями [https://ru.wikipedia.org/wiki/JSON формата JSON] и настоящего Протокола. Для успешной обработки Запроса в нем обязательно должна присутствовать следующая информация.
 +
 +
* '''Код клиента''' - уникальный в рамках Системы номер точки, необходимый для идентификации Агента и последующей привязки платежей. Код клиента сообщается сотрудником нашей компании либо уточняется Агентом самостоятельно, с использованием Web-интерфейса.
 +
 +
* '''Электронно-цифровая подпись'''.  Подпись выполняется на основании закрытого ключа, передаваемого Агенту перед началом программного взаимодействия. Ключ передается Агенту в виде сертификата - файла в формате [http://tools.ietf.org/html/rfc5280#section-4 X.509 версия 3]. <b>Запрещается передача этих сведений третьим лицам</b>.
 +
 +
Электронно-цифровая подпись (ЭЦП) представляет собой строку, полученную по следующему алгоритму.
 +
# Подписываемые данные, в виде [https://ru.wikipedia.org/wiki/JSON JSON]-строки преобразуются в массив байт в формате [https://ru.wikipedia.org/wiki/UTF-8 UTF-8].
 +
# По полученному массиву байт вычисляется хэш-функция SHA-256 и сохраняется как массив байтов.
 +
# По сохраненному массиву еще раз вычисляется хэш-функция пол алгоритму SHA1, т.е. в целом реализуется расчет вида SHA1(SHA256(<подписываемый блок данных>)).
 +
# Полученный массив байтов шифруется алгоритмом [https://ru.wikipedia.org/wiki/RSA RSA]. В качестве ключа используется закрытый ключ Агента из сертификата.
 +
# Полученный массив байтов преобразуется в строку [https://ru.wikipedia.org/wiki/Base64 Base64].
 +
 +
Запрос, представляет собой строку, полученную по следующему алгоритму.
 +
# Формируется содержательная часть Запроса (строка подписываемых данных), включающая в себя "Код клиента" (ClientId), "Входные параметры" (Data), "Код операции" (Operation). Данные оформляются в виде текстовой строки в формате [https://ru.wikipedia.org/wiki/JSON формата JSON].
 +
# Согласно алгоритму, приведенному выше, формируется ЭЦП.
 +
# Из полученной строки подписываемых данных, ЭЦП, а также некоторые дополнительных параметров ("Тип данных" и "Номер протокола") собираются окончательный Запрос.
 +
 +
Пример Запроса.
 +
 +
<syntaxhighlight lang="javascript">
 +
{
 +
  "DataFormat":0,
 +
  "ProtocolVersion":"v.1.0.0",
 +
  "SignedData":
 +
  {
 +
    "ClientId":468,
 +
    "Data":null,
 +
    "Operation":0
 +
  },
 +
  "Sign":"nPTR4MTSdrySDdqCXCWdXmlm0p1CxidxuYo="
 +
}
 +
</syntaxhighlight>
 +
 +
=== Ответ ===
 +
На каждый Запрос система возвращает результат выполнения запроса и описание результата выполнения (Ответ).
 +
Ответ также представляет собой текстовый блок, оформленный аналогично Запросу.
 +
 +
Пример Ответа.
 +
 +
<syntaxhighlight lang="javascript">
 +
{
 +
  "DataFormat":0, 
 +
  "ProtocolVersion": "v.1.0.0",
 +
  "SignedData":
 +
  {
 +
    "OperationResult":{"ResultCode":-3,"CodeDescription":"Произошла ошибка","Message":"Указан неверный код клиента"},
 +
    "Data":null
 +
  },
 +
  "Sign":"nIhserSefhisreeiSh7REgW33D34="
 +
}
 +
</syntaxhighlight>
 +
 +
В случае ошибки, система вернет также расширенное описание ошибки. Допустимы следующие результаты выполнения операций:
 +
*  0 – запрос успешно обработан;
 +
* -1 – некорректная подпись;
 +
* -2 – версия протокола не поддерживается;
 +
* -3 – произошла ошибка обработки запроса.
 +
 +
Данные Ответа, подписываются по тому же алгоритму, что и данные Запроса, однако в качестве ключа используется открытый ключ Агента. Это дает возможность проверить правильность полученных данных по следующему алгоритму.
 +
# Блок SignedData Ответа преобразуется в массив байт.
 +
# От полученного массива данных рассчитывается хэш-функция вида SHA1(SHA256(<подписываемый блок данных>)).
 +
# Значение в блоке Sign декодируется из Base64 в массив байтов и расшифровывается алгоритмом RSA с использование закрытого ключа Агента.
 +
# Полученные на предыдущих этапах массивы сравниваются. Ответ считается корректным только в том случае, если содержимое массивов идентично.
 +
 +
=== Алгоритм взаимодействия с системой ===
 +
В общем виде алгоритм взаимодействия с системой представляет собой последовательное выполнение следующих шагов.
 +
 +
# Формируется Запрос.
 +
# Сформированый Запрос отправляется для обработки Системе с помощью [https://ru.wikipedia.org/wiki/HTTP#POST метода POST HTTP-протокола]. Для взаимодействия с Системой используются следующие два адреса:
 +
http://beta-online.abonentplus.ru - адрес, используемый для разработки, отладки и тестирования Клиента;
 +
http://online.abonentplus.ru - адрес, используемый для регулярной работы с Системой.
 +
:3. В ответ на запрос Система формирует Ответ, который принимается клиентом и анализируется.
 +
 +
== Общее описание допустимых запросов к системе ==
 +
В рамках настоящего Протокола Клиенту доступны пять основных операций, каждой из которых присвоен условный код. При формирование Запроса данный код указывается в поле Operation блока основных (подписываемых) данных.
 +
 +
Список доступных операций следующий.
 +
# Проверить подключение (код '''0''').
 +
# Провести платеж (код '''1''').
 +
# Получить информацию по лицевому счету (код '''2''').
 +
# Проверить статус платежа (код '''3''').
 +
# Получить список доступных услуг (код '''4''').
  
 
Термины и определения
 
Система – платежная система «Абонент».
 
Агент  – организация, осуществляющая прием оплаты через платежную систему «Абонент».
 
Алгоритм взаимодействия с системой
 
Взаимодействие с системой осуществляется в режиме запрос – ответ. Инициатором связи является клиентское ПО агента.
 
Для начала взаимодействия с системой агентом должны быть получены сертификат цифровой подписи и код клиента по приему платежей. Эти данные выдаются при подключении к системе. Запрещается передача этих сведений третьим лицам.
 
Общее описание допустимых запросов к системе
 
В функционал программного обеспечения работающего на стороне агента по приему платежей входит:
 
• Возможность выполнения запроса проверки доступности системы.
 
• Возможность получения списка доступных услуг.
 
• Возможность получения информации по лицевому счету для проведения платежа.
 
• Возможность проведения оплаты по указанному лицевому счету и по указанной услуге.
 
На каждый запрос система возвращает результат выполнения запроса и описание результата выполнения. В случае ошибки, система вернет также расширенное описание ошибки.
 
Допустимы следующие результаты выполнения операций:
 
0 – запрос успешно обработан;
 
-1 – некорректная подпись;
 
-2 – версия протокола не поддерживается;
 
-3 – произошла ошибка обработки запроса.
 
 
Кроме того, по определенным типам запросов система может возвращать выходные параметры.  
 
Кроме того, по определенным типам запросов система может возвращать выходные параметры.  
 +
 
Набор входных и выходных параметров по каждому типу запроса описан в следующих разделах.
 
Набор входных и выходных параметров по каждому типу запроса описан в следующих разделах.
1. Проверить соединение
+
 
1. Входные параметры – код клиента.
+
=== Проверить соединение ===
2. Выходные параметры – отсутствуют.
+
# Входные параметры – код клиента.
2. Получить список услуг
+
# Выходные параметры – отсутствуют.
1. Входные параметры – код клиента.
+
 
2. Выходные параметры:
+
=== Получить список услуг ===
i. Код услуги или ресурса (в дальнейшем используется для формирования платежа).
+
# Входные параметры – код клиента.
ii. Наименование услуги или ресурса.
+
# Выходные параметры:
iii. Код организации, оказывающей услугу или поставляющей ресурс.
+
## Код услуги или ресурса (в дальнейшем используется для формирования платежа).
iv. Наименование организации, оказывающей услугу или поставляющей ресурс.
+
## Наименование услуги или ресурса.
v. Код типа лицевого счета, используемый для идентификации плательщика.
+
## Код организации, оказывающей услугу или поставляющей ресурс.
vi. Наименование типа лицевого счета, используемого для идентификации плательщика.
+
## Наименование организации, оказывающей услугу или поставляющей ресурс.
vii. Реквизиты организации для перечисления средств.
+
## Код типа лицевого счета, используемый для идентификации плательщика.
viii. Дополнительные поля для формирования платежа.
+
## Наименование типа лицевого счета, используемого для идентификации плательщика.
3. Получить данные по абоненту
+
## Реквизиты организации для перечисления средств.
1. Входные параметры:
+
## Дополнительные поля для формирования платежа.
i. Код типа лицевого счета.
+
 
ii. Лицевой счет.
+
=== Получить данные по абоненту ===
2. Выходные параметры:
+
# Входные параметры:
i. Код типа лицевого счета.
+
## Код типа лицевого счета.
ii. Лицевой счет абонента.
+
## Лицевой счет.
iii. Список альтернативных лицевых счетов абонента с указанием типа.
+
# Выходные параметры:
iv. Список услуг абонента с информацией для приема платежа (текущая задолженность, признак наличия счетчика, последние показания счетчика и дата их съема, текущий тариф).
+
## Код типа лицевого счета.
4. Зарегистрировать платеж
+
## Лицевой счет абонента.
1. Входные параметры:
+
## Список альтернативных лицевых счетов абонента с указанием типа.
i. Уникальный номер платежа (Guid).
+
## Список услуг абонента с информацией для приема платежа (текущая задолженность, признак наличия счетчика, последние показания счетчика и дата их съема, текущий тариф).
ii. Дата/время.
+
 
iii. Примечание.
+
=== Зарегистрировать платеж ===
iv. Другая информация.
+
# Входные параметры:
v. Зачисления - список сумм оплат, с разбивкой по услугам, с указанием для каждой услуги:
+
## Уникальный номер платежа (Guid).
Кода типа лицевого счета.
+
## Дата/время.
Лицевого счета.
+
## Примечание.
Кода услуги.
+
## Другая информация.
Суммы платежа.
+
## Зачисления - список сумм оплат, с разбивкой по услугам, с указанием для каждой услуги:
Дополнительные параметры (текущие показания счетчика, оплачиваемы объем и т.д.).
+
##* Кода типа лицевого счета.
2. Выходные параметры – результат обработки (поставлен в очередь, отклонен и т.д.)
+
##* Лицевого счета.
5. Проверить статус платежа
+
##* Кода услуги.
1. Входные параметры – уникальный номер платежа (Guid).
+
##* Суммы платежа.
2. Выходные параметры: список зачислений с указанием результатов обработки по каждому из зачислений (отправлено поставщику услуг/находится в очереди на обработку/ошибка и т.д.).
+
##* Дополнительные параметры (текущие показания счетчика, оплачиваемы объем и т.д.).
Общая структура взаимодействия
+
# Выходные параметры – результат обработки (поставлен в очередь, отклонен и т.д.)
 +
 
 +
=== Проверить статус платежа ===
 +
# Входные параметры – уникальный номер платежа (Guid).
 +
# Выходные параметры: список зачислений с указанием результатов обработки по каждому из зачислений (отправлено поставщику услуг/находится в очереди на обработку/ошибка и т.д.).
 +
 
 +
= Общая структура взаимодействия =
 
Инициатором обмена является ПО агента по приему платежей. Запросы посылаются через интернет, по протоколу HTTP(S) методом POST.
 
Инициатором обмена является ПО агента по приему платежей. Запросы посылаются через интернет, по протоколу HTTP(S) методом POST.
 
Данные передаются в JSON-формате.
 
Данные передаются в JSON-формате.
 
Каждый запрос обязательно должен быть подписан с помощью ЭЦП агента.
 
Каждый запрос обязательно должен быть подписан с помощью ЭЦП агента.
 +
 
Запрос должен содержать следующие поля:
 
Запрос должен содержать следующие поля:
1. ProtocolVersion – версия протокола, строка.
+
# ProtocolVersion – версия протокола, строка.
2. DataFormat- формат данных в поле Data. В настоящее время поддерживается только формат JSON, что соответствует значению 0 в данном поле.
+
# DataFormat- формат данных в поле Data. В настоящее время поддерживается только формат JSON, что соответствует значению 0 в данном поле.
3. SignedData – подписываемые данные, структура
+
# SignedData – подписываемые данные, структура
3.1. ClientId – код клиента платежной системы, целое. Данный код выдается при подключении к платежной системе.
+
## ClientId – код клиента платежной системы, целое. Данный код выдается при подключении к платежной системе.
3.2. Operation – тип операции, целое. Подробнее каждый тип операции будет рассмотрен ниже.
+
## Operation – тип операции, целое. Подробнее каждый тип операции будет рассмотрен ниже.
3.3. Data – данные для выполнения операции, объект в JSON-формате.
+
## Data – данные для выполнения операции, объект в JSON-формате.
4. Sign – электронно-цифровая подпись, строка base64.
+
# Sign – электронно-цифровая подпись, строка base64.
1. Библиотека для формирования запросов к системе
+
 
 +
== Библиотека для формирования запросов к системе ==
 
Для упрощения доступа к системе разработана специальная библиотека классов. Исходный код библиотеки на языке C# приведен в приложении к данному описанию.
 
Для упрощения доступа к системе разработана специальная библиотека классов. Исходный код библиотеки на языке C# приведен в приложении к данному описанию.
 +
 
Библиотека состоит из следующих основных классов.
 
Библиотека состоит из следующих основных классов.
Классы общего назначения:
 
AbonentPaysystemRequest – запрос к платежной системе;
 
AbonentPaysystemResponse – ответ от платежной системы;
 
ExchangeResult – результат выполнения операции;
 
RequestSignedData – входные данные для запроса;
 
ResponseSignedData – выходные данные;
 
RSASignHelper – класс, позволяющий подписывать данные с помощью сертификата.
 
Классы для проведения платежей:
 
  
Pay платеж;
+
<b>Классы общего назначения:</b>
Enlistment зачисление;
+
* AbonentPaysystemRequest – запрос к платежной системе;
 +
* AbonentPaysystemResponse – ответ от платежной системы;
 +
* ExchangeResult – результат выполнения операции;
 +
* RequestSignedData входные данные для запроса;
 +
* ResponseSignedData выходные данные;
 +
* RSASignHelper – класс, позволяющий подписывать данные с помощью сертификата.
  
Классы для получения информации по абоненту:
+
<b>Классы для проведения платежей:</b>
Abonent абонент;
+
* Pay платеж;
AbonentAccount сведения о лицевом счете абонента, с привязкой к поставщику услуг;
+
* Enlistment зачисление.
AbonentBalance – информация по услуге (долги, показания счетчика и т.д.)
 
  
Классы для получения списка услуг:
+
<b>Классы для получения информации по абоненту:</b>
PaymentDestination – услуга.
+
* Abonent – абонент;
 +
* AbonentAccount – сведения о лицевом счете абонента, с привязкой к поставщику услуг;
 +
* AbonentBalance – информация по услуге (долги, показания счетчика и т.д.).
 +
 
 +
<b>Классы для получения списка услуг:</b>
 +
* PaymentDestination – услуга.
 +
 
 +
== Подпись данных с помощью библиотеки ==
  
2. Подпись данных с помощью библиотеки
 
 
Пример исходного кода для подписи строки:
 
Пример исходного кода для подписи строки:
//Открываем файл сертификата
+
<syntaxhighlight lang="csharp">
var cert = new X509Certificate2(Path, Password);
+
// Открываем файл сертификата
//Создаем класс для выполнения подписи
+
var cert = new X509Certificate2(Path, Password);
var signHelper = new RSASignHelper(cert);
+
// Создаем класс для выполнения подписи
//Выполняем подпись с помощью класса-помощника
+
var signHelper = new RSASignHelper(cert);
var Sign = Convert.ToBase64String(signHelper.GetSign(Data));
+
// Выполняем подпись с помощью класса-помощника
3. Отправка запроса и получение результата
+
var Sign = Convert.ToBase64String(signHelper.GetSign(Data));
 +
</syntaxhighlight>
 +
 
 +
== Отправка запроса и получение результата ==
 
Пример исходного кода:
 
Пример исходного кода:
requestData – объект, содержащий исходные данные для выполнения запроса к системе;
+
* requestData – объект, содержащий исходные данные для выполнения запроса к системе;
response – результат, который возвращает система.
+
* response – результат, который возвращает система.
            //Отправляем запрос
+
 
            WebRequest webRequest = WebRequest.Create(url.Text);
+
<syntaxhighlight lang="csharp">
            webRequest.Method = "POST";
+
// Отправляем запрос
            webRequest.Timeout = 100000;
+
WebRequest webRequest = WebRequest.Create(url.Text);
            webRequest.ContentType = "application/json";
+
webRequest.Method = "POST";
            var sentData = Encoding.UTF8.GetBytes(requestData.ToJson());
+
webRequest.Timeout = 100000;
            webRequest.ContentLength = sentData.Length;
+
webRequest.ContentType = "application/json";
            var sendStream = webRequest.GetRequestStream();
+
var sentData = Encoding.UTF8.GetBytes(requestData.ToJson());
            sendStream.Write(sentData, 0, sentData.Length);
+
webRequest.ContentLength = sentData.Length;
            sendStream.Close();
+
var sendStream = webRequest.GetRequestStream();
            WebResponse res = webRequest.GetResponse();
+
sendStream.Write(sentData, 0, sentData.Length);
            //Получаем результаты
+
sendStream.Close();
            var ReceiveStream = res.GetResponseStream();
+
WebResponse res = webRequest.GetResponse();
            var sr = new StreamReader(ReceiveStream, Encoding.UTF8);
+
// Получаем результаты
            var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());
+
var ReceiveStream = res.GetResponseStream();
 +
var sr = new StreamReader(ReceiveStream, Encoding.UTF8);
 +
var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());
 +
</syntaxhighlight>
  
4. Запрос на проверку доступности платежной системы
+
== Запрос на проверку доступности платежной системы ==
Для проверки доступности платежной системы необходимо отправить запрос с Operation = 0 и с пустым полем Data на адрес платежной системы.
+
Для проверки доступности платежной системы необходимо отправить запрос с Operation = 0 и с пустым полем Data на адрес платежной системы. В данном примере приведены все операции – от формирования запроса, до его подписи и отправки в систему.
В данном примере приведены все операции – от формирования запроса, до его подписи и отправки в систему.
 
 
Пример исходного кода:
 
Пример исходного кода:
//Создаем запрос  
+
 
var request = new AbonentPaysystemRequest()
+
<syntaxhighlight lang="csharp">
 +
  // Создаем запрос  
 +
  var requestData = new AbonentPaysystemRequest()
 
             {
 
             {
 
                 SignedData = new RequestSignedData()
 
                 SignedData = new RequestSignedData()
Строка 142: Строка 236:
 
                 Sign = "",
 
                 Sign = "",
 
             };
 
             };
            //Подписываем
+
// Подписываем
            var cert = new X509Certificate2(Path, Password);
+
var cert = new X509Certificate2(Path, Password);
            var signHelper = new RSASignHelper(cert);
+
var signHelper = new RSASignHelper(cert);
            requestData.Sign = Convert.ToBase64String(signHelper.GetSign(requestData.SignedData.ToJson()));
+
requestData.Sign = Convert.ToBase64String(signHelper.GetSign(requestData.SignedData.ToJson()));
            //Отправляем запрос
+
// Отправляем запрос
            WebRequest webRequest = WebRequest.Create(url.Text);
+
WebRequest webRequest = WebRequest.Create(url.Text);
            webRequest.Method = "POST";
+
webRequest.Method = "POST";
            webRequest.Timeout = 100000;
+
webRequest.Timeout = 100000;
            webRequest.ContentType = "application/json";
+
webRequest.ContentType = "application/json";
            var sentData = Encoding.UTF8.GetBytes(requestData.ToJson());
+
var sentData = Encoding.UTF8.GetBytes(requestData.ToJson());
            webRequest.ContentLength = sentData.Length;
+
webRequest.ContentLength = sentData.Length;
            var sendStream = webRequest.GetRequestStream();
+
var sendStream = webRequest.GetRequestStream();
            sendStream.Write(sentData, 0, sentData.Length);
+
sendStream.Write(sentData, 0, sentData.Length);
            sendStream.Close();
+
sendStream.Close();
            WebResponse res = webRequest.GetResponse();
+
WebResponse res = webRequest.GetResponse();
            //Получаем результаты
+
// Получаем результаты
            var ReceiveStream = res.GetResponseStream();
+
var ReceiveStream = res.GetResponseStream();
            var sr = new StreamReader(ReceiveStream, Encoding.UTF8);
+
var sr = new StreamReader(ReceiveStream, Encoding.UTF8);
            var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());
+
var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());
 +
</syntaxhighlight>
  
5. Запрос на получение списка услуг
+
== Запрос на получение списка услуг ==
 
Пример исходного кода:
 
Пример исходного кода:
//Создаем запрос  
+
<syntaxhighlight lang="csharp">
var request = new AbonentPaysystemRequest()
+
// Создаем запрос  
 +
var request = new AbonentPaysystemRequest()
 
             {
 
             {
 
                 SignedData = new RequestSignedData()
 
                 SignedData = new RequestSignedData()
Строка 175: Строка 271:
 
                 Sign = "",
 
                 Sign = "",
 
             };
 
             };
            //Подписываем
+
// Подписываем
            …………
+
…………
            //Отправляем запрос
+
// Отправляем запрос
            …………
+
…………
            //Получаем результаты
+
// Получаем результаты
            var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());
+
var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());
            //Отображаем результаты
+
// Отображаем результаты
            var paymentDestinations = PaymentDestinations.FromJson(response.SignedData.Data);
+
var paymentDestinations = PaymentDestinations.FromJson(response.SignedData.Data);
 +
</syntaxhighlight>
  
6. Запрос на получение информации по лицевому счету
+
== Запрос на получение информации по лицевому счету ==
 
Пример исходного кода:
 
Пример исходного кода:
//Создаем запрос  
+
<syntaxhighlight lang="csharp">
var request = new AbonentPaysystemRequest()
+
// Создаем запрос  
 +
var request = new AbonentPaysystemRequest()
 
             {
 
             {
 
                 SignedData = new RequestSignedData()
 
                 SignedData = new RequestSignedData()
Строка 197: Строка 295:
 
                 Sign = "",
 
                 Sign = "",
 
             };
 
             };
//Формируем лицевой счет для запроса
+
// Формируем лицевой счет для запроса
var account = new AbonentAccount()
+
var account = new AbonentAccount()
 
             {
 
             {
 
                 Account = “00000000”,
 
                 Account = “00000000”,
 
                 SupplierId = 1,
 
                 SupplierId = 1,
 
             };
 
             };
//Передаем лицевой счет в запрос
+
// Передаем лицевой счет в запрос
            request.SignedData.Data = account.ToJson();
+
request.SignedData.Data = account.ToJson();
 +
 
 +
//Подписываем
 +
…………
 +
//Отправляем запрос
 +
…………
 +
//Получаем результаты
 +
var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());
 +
//Отображаем результаты
 +
var paymentDestinations = PaymentDestinations.FromJson(response.SignedData.Data);
 +
</syntaxhighlight>
  
            //Подписываем
+
== Запрос на проведение платежа ==
            …………
 
            //Отправляем запрос
 
            …………
 
            //Получаем результаты
 
            var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());
 
            //Отображаем результаты
 
            var paymentDestinations = PaymentDestinations.FromJson(response.SignedData.Data);
 
7. Запрос на проведение платежа
 
 
Пример исходного кода:
 
Пример исходного кода:
//Создаем запрос  
+
<syntaxhighlight lang="csharp">
var request = new AbonentPaysystemRequest()
+
// Создаем запрос  
 +
var request = new AbonentPaysystemRequest()
 
             {
 
             {
 
                 SignedData = new RequestSignedData()
 
                 SignedData = new RequestSignedData()
Строка 227: Строка 328:
 
                 Sign = "",
 
                 Sign = "",
 
             };
 
             };
//Формируем платеж
+
// Формируем платеж
var pay = new Pay
+
var pay = new Pay
 
             {
 
             {
 
                 Enlistments = new List<Enlistment>(),
 
                 Enlistments = new List<Enlistment>(),
 
                 Id = Guid.NewGuid(),
 
                 Id = Guid.NewGuid(),
 
             };
 
             };
            pay.PayDateTime = DateTime.Now;
+
pay.PayDateTime = DateTime.Now;
            pay.Enlistments.Add(new Enlistment()
+
pay.Enlistments.Add(new Enlistment()
 
             {
 
             {
 
                 Account = PayAccount.Text,
 
                 Account = PayAccount.Text,
Строка 242: Строка 343:
 
                 Id = Guid.NewGuid(),
 
                 Id = Guid.NewGuid(),
 
             });
 
             });
//Передаем платеж в запрос
+
// Передаем платеж в запрос
            request.SignedData.Data = pay.ToJson();
+
request.SignedData.Data = pay.ToJson();
 +
// Подписываем
 +
…………
 +
// Отправляем запрос
 +
…………
 +
// Получаем результаты
 +
var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());
 +
</syntaxhighlight>
  
            //Подписываем
+
== Запрос на проверку статуса платежа ==
            …………
 
            //Отправляем запрос
 
            …………
 
            //Получаем результаты
 
            var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());
 
8. Запрос на проверку статуса платежа
 
 
Пример исходного кода:
 
Пример исходного кода:
//Создаем запрос  
+
<syntaxhighlight lang="csharp">
var request = new AbonentPaysystemRequest()
+
// Создаем запрос  
 +
var request = new AbonentPaysystemRequest()
 
             {
 
             {
 
                 SignedData = new RequestSignedData()
 
                 SignedData = new RequestSignedData()
Строка 264: Строка 367:
 
                 Sign = "",
 
                 Sign = "",
 
             };
 
             };
//Передаем ID платежа в запрос
+
// Передаем ID платежа в запрос
            request.SignedData.Data = Id;
+
request.SignedData.Data = Id;
 +
//Подписываем
 +
…………
 +
//Отправляем запрос
 +
…………
 +
//Получаем результаты
 +
var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());
 +
</syntaxhighlight>
  
            //Подписываем
+
[[Категория:Протокол online-обмена данными с платежной системой]]
            …………
 
            //Отправляем запрос
 
            …………
 
            //Получаем результаты
 
            var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());
 

Текущая версия на 16:21, 1 сентября 2014

В данном документе описан регламент технического взаимодействия платежной системы «Абонент» с программным обеспечением агента по приему платежей по протоколу HTTP(S).

Документ предназначен для разработчиков программного обеспечения работающего на стороне агентов по приему платежей.  

Термины и определения

Система – платежная система «Абонент».

Агент – организация, осуществляющая прием оплаты через платежную систему «Абонент».

Клиент - программное обеспечение Агента, реализующее клиентскую часть настоящего протокола.

Общие принципы взаимодействия с Системой

Взаимодействие с системой осуществляется в режиме запрос – ответ. Инициатором взаимодействия во всех случаях является Клиент.

Запрос

Представляет собой текстовый блок данных, структурированных в соответствии с требованиями формата JSON и настоящего Протокола. Для успешной обработки Запроса в нем обязательно должна присутствовать следующая информация.

  • Код клиента - уникальный в рамках Системы номер точки, необходимый для идентификации Агента и последующей привязки платежей. Код клиента сообщается сотрудником нашей компании либо уточняется Агентом самостоятельно, с использованием Web-интерфейса.
  • Электронно-цифровая подпись. Подпись выполняется на основании закрытого ключа, передаваемого Агенту перед началом программного взаимодействия. Ключ передается Агенту в виде сертификата - файла в формате X.509 версия 3. Запрещается передача этих сведений третьим лицам.

Электронно-цифровая подпись (ЭЦП) представляет собой строку, полученную по следующему алгоритму.

  1. Подписываемые данные, в виде JSON-строки преобразуются в массив байт в формате UTF-8.
  2. По полученному массиву байт вычисляется хэш-функция SHA-256 и сохраняется как массив байтов.
  3. По сохраненному массиву еще раз вычисляется хэш-функция пол алгоритму SHA1, т.е. в целом реализуется расчет вида SHA1(SHA256(<подписываемый блок данных>)).
  4. Полученный массив байтов шифруется алгоритмом RSA. В качестве ключа используется закрытый ключ Агента из сертификата.
  5. Полученный массив байтов преобразуется в строку Base64.

Запрос, представляет собой строку, полученную по следующему алгоритму.

  1. Формируется содержательная часть Запроса (строка подписываемых данных), включающая в себя "Код клиента" (ClientId), "Входные параметры" (Data), "Код операции" (Operation). Данные оформляются в виде текстовой строки в формате формата JSON.
  2. Согласно алгоритму, приведенному выше, формируется ЭЦП.
  3. Из полученной строки подписываемых данных, ЭЦП, а также некоторые дополнительных параметров ("Тип данных" и "Номер протокола") собираются окончательный Запрос.

Пример Запроса.

{
  "DataFormat":0,
  "ProtocolVersion":"v.1.0.0",
  "SignedData":
  {
    "ClientId":468,
    "Data":null,
    "Operation":0
  },
  "Sign":"nPTR4MTSdrySDdqCXCWdXmlm0p1CxidxuYo="
}

Ответ

На каждый Запрос система возвращает результат выполнения запроса и описание результата выполнения (Ответ). Ответ также представляет собой текстовый блок, оформленный аналогично Запросу.

Пример Ответа.

{
  "DataFormat":0,  
  "ProtocolVersion": "v.1.0.0",
  "SignedData":
  {
    "OperationResult":{"ResultCode":-3,"CodeDescription":"Произошла ошибка","Message":"Указан неверный код клиента"},
    "Data":null
  },
  "Sign":"nIhserSefhisreeiSh7REgW33D34="
}

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

  • 0 – запрос успешно обработан;
  • -1 – некорректная подпись;
  • -2 – версия протокола не поддерживается;
  • -3 – произошла ошибка обработки запроса.

Данные Ответа, подписываются по тому же алгоритму, что и данные Запроса, однако в качестве ключа используется открытый ключ Агента. Это дает возможность проверить правильность полученных данных по следующему алгоритму.

  1. Блок SignedData Ответа преобразуется в массив байт.
  2. От полученного массива данных рассчитывается хэш-функция вида SHA1(SHA256(<подписываемый блок данных>)).
  3. Значение в блоке Sign декодируется из Base64 в массив байтов и расшифровывается алгоритмом RSA с использование закрытого ключа Агента.
  4. Полученные на предыдущих этапах массивы сравниваются. Ответ считается корректным только в том случае, если содержимое массивов идентично.

Алгоритм взаимодействия с системой

В общем виде алгоритм взаимодействия с системой представляет собой последовательное выполнение следующих шагов.

  1. Формируется Запрос.
  2. Сформированый Запрос отправляется для обработки Системе с помощью метода POST HTTP-протокола. Для взаимодействия с Системой используются следующие два адреса:
http://beta-online.abonentplus.ru - адрес, используемый для разработки, отладки и тестирования Клиента;
http://online.abonentplus.ru - адрес, используемый для регулярной работы с Системой.
3. В ответ на запрос Система формирует Ответ, который принимается клиентом и анализируется.

Общее описание допустимых запросов к системе

В рамках настоящего Протокола Клиенту доступны пять основных операций, каждой из которых присвоен условный код. При формирование Запроса данный код указывается в поле Operation блока основных (подписываемых) данных.

Список доступных операций следующий.

  1. Проверить подключение (код 0).
  2. Провести платеж (код 1).
  3. Получить информацию по лицевому счету (код 2).
  4. Проверить статус платежа (код 3).
  5. Получить список доступных услуг (код 4).

Кроме того, по определенным типам запросов система может возвращать выходные параметры.

Набор входных и выходных параметров по каждому типу запроса описан в следующих разделах.

Проверить соединение

  1. Входные параметры – код клиента.
  2. Выходные параметры – отсутствуют.

Получить список услуг

  1. Входные параметры – код клиента.
  2. Выходные параметры:
    1. Код услуги или ресурса (в дальнейшем используется для формирования платежа).
    2. Наименование услуги или ресурса.
    3. Код организации, оказывающей услугу или поставляющей ресурс.
    4. Наименование организации, оказывающей услугу или поставляющей ресурс.
    5. Код типа лицевого счета, используемый для идентификации плательщика.
    6. Наименование типа лицевого счета, используемого для идентификации плательщика.
    7. Реквизиты организации для перечисления средств.
    8. Дополнительные поля для формирования платежа.

Получить данные по абоненту

  1. Входные параметры:
    1. Код типа лицевого счета.
    2. Лицевой счет.
  2. Выходные параметры:
    1. Код типа лицевого счета.
    2. Лицевой счет абонента.
    3. Список альтернативных лицевых счетов абонента с указанием типа.
    4. Список услуг абонента с информацией для приема платежа (текущая задолженность, признак наличия счетчика, последние показания счетчика и дата их съема, текущий тариф).

Зарегистрировать платеж

  1. Входные параметры:
    1. Уникальный номер платежа (Guid).
    2. Дата/время.
    3. Примечание.
    4. Другая информация.
    5. Зачисления - список сумм оплат, с разбивкой по услугам, с указанием для каждой услуги:
      • Кода типа лицевого счета.
      • Лицевого счета.
      • Кода услуги.
      • Суммы платежа.
      • Дополнительные параметры (текущие показания счетчика, оплачиваемы объем и т.д.).
  2. Выходные параметры – результат обработки (поставлен в очередь, отклонен и т.д.)

Проверить статус платежа

  1. Входные параметры – уникальный номер платежа (Guid).
  2. Выходные параметры: список зачислений с указанием результатов обработки по каждому из зачислений (отправлено поставщику услуг/находится в очереди на обработку/ошибка и т.д.).

Общая структура взаимодействия

Инициатором обмена является ПО агента по приему платежей. Запросы посылаются через интернет, по протоколу HTTP(S) методом POST. Данные передаются в JSON-формате. Каждый запрос обязательно должен быть подписан с помощью ЭЦП агента.

Запрос должен содержать следующие поля:

  1. ProtocolVersion – версия протокола, строка.
  2. DataFormat- формат данных в поле Data. В настоящее время поддерживается только формат JSON, что соответствует значению 0 в данном поле.
  3. SignedData – подписываемые данные, структура
    1. ClientId – код клиента платежной системы, целое. Данный код выдается при подключении к платежной системе.
    2. Operation – тип операции, целое. Подробнее каждый тип операции будет рассмотрен ниже.
    3. Data – данные для выполнения операции, объект в JSON-формате.
  4. Sign – электронно-цифровая подпись, строка base64.

Библиотека для формирования запросов к системе

Для упрощения доступа к системе разработана специальная библиотека классов. Исходный код библиотеки на языке C# приведен в приложении к данному описанию.

Библиотека состоит из следующих основных классов.

Классы общего назначения:

  • AbonentPaysystemRequest – запрос к платежной системе;
  • AbonentPaysystemResponse – ответ от платежной системы;
  • ExchangeResult – результат выполнения операции;
  • RequestSignedData – входные данные для запроса;
  • ResponseSignedData – выходные данные;
  • RSASignHelper – класс, позволяющий подписывать данные с помощью сертификата.

Классы для проведения платежей:

  • Pay – платеж;
  • Enlistment – зачисление.

Классы для получения информации по абоненту:

  • Abonent – абонент;
  • AbonentAccount – сведения о лицевом счете абонента, с привязкой к поставщику услуг;
  • AbonentBalance – информация по услуге (долги, показания счетчика и т.д.).

Классы для получения списка услуг:

  • PaymentDestination – услуга.

Подпись данных с помощью библиотеки

Пример исходного кода для подписи строки:

 // Открываем файл сертификата
 var cert = new X509Certificate2(Path, Password);
 // Создаем класс для выполнения подписи
 var signHelper = new RSASignHelper(cert);
 // Выполняем подпись с помощью класса-помощника
 var Sign = Convert.ToBase64String(signHelper.GetSign(Data));

Отправка запроса и получение результата

Пример исходного кода:

  • requestData – объект, содержащий исходные данные для выполнения запроса к системе;
  • response – результат, который возвращает система.
 // Отправляем запрос
 WebRequest webRequest = WebRequest.Create(url.Text);
 webRequest.Method = "POST";
 webRequest.Timeout = 100000;
 webRequest.ContentType = "application/json";
 var sentData = Encoding.UTF8.GetBytes(requestData.ToJson());
 webRequest.ContentLength = sentData.Length;
 var sendStream = webRequest.GetRequestStream();
 sendStream.Write(sentData, 0, sentData.Length);
 sendStream.Close();
 WebResponse res = webRequest.GetResponse();
 // Получаем результаты
 var ReceiveStream = res.GetResponseStream();
 var sr = new StreamReader(ReceiveStream, Encoding.UTF8);
 var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());

Запрос на проверку доступности платежной системы

Для проверки доступности платежной системы необходимо отправить запрос с Operation = 0 и с пустым полем Data на адрес платежной системы. В данном примере приведены все операции – от формирования запроса, до его подписи и отправки в систему. Пример исходного кода:

  // Создаем запрос 
  var requestData = new AbonentPaysystemRequest()
            {
                SignedData = new RequestSignedData()
                {
                    ClientId = 1,
                    Operation = OperationType.Check,
                },
                ProtocolVersion = "v.1.0.0",
                Sign = "",
            };
 // Подписываем
 var cert = new X509Certificate2(Path, Password);
 var signHelper = new RSASignHelper(cert);
 requestData.Sign = Convert.ToBase64String(signHelper.GetSign(requestData.SignedData.ToJson()));
 // Отправляем запрос
 WebRequest webRequest = WebRequest.Create(url.Text);
 webRequest.Method = "POST";
 webRequest.Timeout = 100000;
 webRequest.ContentType = "application/json";
 var sentData = Encoding.UTF8.GetBytes(requestData.ToJson());
 webRequest.ContentLength = sentData.Length;
 var sendStream = webRequest.GetRequestStream();
 sendStream.Write(sentData, 0, sentData.Length);
 sendStream.Close();
 WebResponse res = webRequest.GetResponse();
 // Получаем результаты
 var ReceiveStream = res.GetResponseStream();
 var sr = new StreamReader(ReceiveStream, Encoding.UTF8);
 var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());

Запрос на получение списка услуг

Пример исходного кода:

 // Создаем запрос 
 var request = new AbonentPaysystemRequest()
            {
                SignedData = new RequestSignedData()
                {
                    ClientId = 1,
                    Operation = OperationType.GetPaymentDestinations,
                },
                ProtocolVersion = "v.1.0.0",
                Sign = "",
            };
 // Подписываем
 …………
 // Отправляем запрос
 …………
 // Получаем результаты
 var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());
 // Отображаем результаты
 var paymentDestinations = PaymentDestinations.FromJson(response.SignedData.Data);

Запрос на получение информации по лицевому счету

Пример исходного кода:

 // Создаем запрос 
 var request = new AbonentPaysystemRequest()
            {
                SignedData = new RequestSignedData()
                {
                    ClientId = 1,
                    Operation = OperationType.GetAccountInfo,
                },
                ProtocolVersion = "v.1.0.0",
                Sign = "",
            };
 // Формируем лицевой счет для запроса
 var account = new AbonentAccount()
            {
                Account = “00000000”,
                SupplierId = 1,
            };
 // Передаем лицевой счет в запрос
 request.SignedData.Data = account.ToJson();

 //Подписываем
 …………
 //Отправляем запрос
 …………
 //Получаем результаты
 var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());
 //Отображаем результаты
 var paymentDestinations = PaymentDestinations.FromJson(response.SignedData.Data);

Запрос на проведение платежа

Пример исходного кода:

 // Создаем запрос 
 var request = new AbonentPaysystemRequest()
            {
                SignedData = new RequestSignedData()
                {
                    ClientId = 1,
                    Operation = OperationType.GetAccountInfo,
                },
                ProtocolVersion = "v.1.0.0",
                Sign = "",
            };
 // Формируем платеж
 var pay = new Pay
            {
                Enlistments = new List<Enlistment>(),
                Id = Guid.NewGuid(),
            };
 pay.PayDateTime = DateTime.Now;
 pay.Enlistments.Add(new Enlistment()
            {
                Account = PayAccount.Text,
                PaymentDestinationId = 1,
                PAmmount = 0,
                CAmmount = 0,
                Id = Guid.NewGuid(),
            });
 // Передаем платеж в запрос
 request.SignedData.Data = pay.ToJson();
 // Подписываем
 …………
 // Отправляем запрос
 …………
 // Получаем результаты
 var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());

Запрос на проверку статуса платежа

Пример исходного кода:

 // Создаем запрос 
 var request = new AbonentPaysystemRequest()
            {
                SignedData = new RequestSignedData()
                {
                    ClientId = 1,
                    Operation = OperationType.GetAccountInfo,
                },
                ProtocolVersion = "v.1.0.0",
                Sign = "",
            };
 // Передаем ID платежа в запрос
 request.SignedData.Data = Id;
 //Подписываем
 …………
 //Отправляем запрос
 …………
 //Получаем результаты
 var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd());