Протокол взаимодействия с платежной системой — различия между версиями
Admin (обсуждение | вклад) |
Admin (обсуждение | вклад) (→Ответ) |
||
(не показаны 64 промежуточные версии 2 участников) | |||
Строка 1: | Строка 1: | ||
− | + | В данном документе описан регламент технического взаимодействия платежной системы «Абонент» с программным обеспечением агента по приему платежей по протоколу 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'''). | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
Кроме того, по определенным типам запросов система может возвращать выходные параметры. | Кроме того, по определенным типам запросов система может возвращать выходные параметры. | ||
+ | |||
Набор входных и выходных параметров по каждому типу запроса описан в следующих разделах. | Набор входных и выходных параметров по каждому типу запроса описан в следующих разделах. | ||
− | + | ||
− | + | === Проверить соединение === | |
− | + | # Входные параметры – код клиента. | |
− | + | # Выходные параметры – отсутствуют. | |
− | + | ||
− | + | === Получить список услуг === | |
− | + | # Входные параметры – код клиента. | |
− | + | # Выходные параметры: | |
− | + | ## Код услуги или ресурса (в дальнейшем используется для формирования платежа). | |
− | + | ## Наименование услуги или ресурса. | |
− | + | ## Код организации, оказывающей услугу или поставляющей ресурс. | |
− | + | ## Наименование организации, оказывающей услугу или поставляющей ресурс. | |
− | + | ## Код типа лицевого счета, используемый для идентификации плательщика. | |
− | + | ## Наименование типа лицевого счета, используемого для идентификации плательщика. | |
− | + | ## Реквизиты организации для перечисления средств. | |
− | + | ## Дополнительные поля для формирования платежа. | |
− | + | ||
− | + | === Получить данные по абоненту === | |
− | + | # Входные параметры: | |
− | + | ## Код типа лицевого счета. | |
− | + | ## Лицевой счет. | |
− | + | # Выходные параметры: | |
− | + | ## Код типа лицевого счета. | |
− | + | ## Лицевой счет абонента. | |
− | + | ## Список альтернативных лицевых счетов абонента с указанием типа. | |
− | + | ## Список услуг абонента с информацией для приема платежа (текущая задолженность, признак наличия счетчика, последние показания счетчика и дата их съема, текущий тариф). | |
− | + | ||
− | + | === Зарегистрировать платеж === | |
− | + | # Входные параметры: | |
− | + | ## Уникальный номер платежа (Guid). | |
− | + | ## Дата/время. | |
− | + | ## Примечание. | |
− | + | ## Другая информация. | |
− | + | ## Зачисления - список сумм оплат, с разбивкой по услугам, с указанием для каждой услуги: | |
− | + | ##* Кода типа лицевого счета. | |
− | + | ##* Лицевого счета. | |
− | + | ##* Кода услуги. | |
− | + | ##* Суммы платежа. | |
− | + | ##* Дополнительные параметры (текущие показания счетчика, оплачиваемы объем и т.д.). | |
− | Общая структура взаимодействия | + | # Выходные параметры – результат обработки (поставлен в очередь, отклонен и т.д.) |
+ | |||
+ | === Проверить статус платежа === | ||
+ | # Входные параметры – уникальный номер платежа (Guid). | ||
+ | # Выходные параметры: список зачислений с указанием результатов обработки по каждому из зачислений (отправлено поставщику услуг/находится в очереди на обработку/ошибка и т.д.). | ||
+ | |||
+ | = Общая структура взаимодействия = | ||
Инициатором обмена является ПО агента по приему платежей. Запросы посылаются через интернет, по протоколу HTTP(S) методом POST. | Инициатором обмена является ПО агента по приему платежей. Запросы посылаются через интернет, по протоколу HTTP(S) методом POST. | ||
Данные передаются в JSON-формате. | Данные передаются в JSON-формате. | ||
Каждый запрос обязательно должен быть подписан с помощью ЭЦП агента. | Каждый запрос обязательно должен быть подписан с помощью ЭЦП агента. | ||
+ | |||
Запрос должен содержать следующие поля: | Запрос должен содержать следующие поля: | ||
− | + | # ProtocolVersion – версия протокола, строка. | |
− | + | # DataFormat- формат данных в поле Data. В настоящее время поддерживается только формат JSON, что соответствует значению 0 в данном поле. | |
− | + | # SignedData – подписываемые данные, структура | |
− | + | ## ClientId – код клиента платежной системы, целое. Данный код выдается при подключении к платежной системе. | |
− | + | ## Operation – тип операции, целое. Подробнее каждый тип операции будет рассмотрен ниже. | |
− | + | ## Data – данные для выполнения операции, объект в JSON-формате. | |
− | + | # Sign – электронно-цифровая подпись, строка base64. | |
− | + | ||
+ | == Библиотека для формирования запросов к системе == | ||
Для упрощения доступа к системе разработана специальная библиотека классов. Исходный код библиотеки на языке C# приведен в приложении к данному описанию. | Для упрощения доступа к системе разработана специальная библиотека классов. Исходный код библиотеки на языке C# приведен в приложении к данному описанию. | ||
+ | |||
Библиотека состоит из следующих основных классов. | Библиотека состоит из следующих основных классов. | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | <b>Классы общего назначения:</b> | |
− | + | * AbonentPaysystemRequest – запрос к платежной системе; | |
+ | * AbonentPaysystemResponse – ответ от платежной системы; | ||
+ | * ExchangeResult – результат выполнения операции; | ||
+ | * RequestSignedData – входные данные для запроса; | ||
+ | * ResponseSignedData – выходные данные; | ||
+ | * RSASignHelper – класс, позволяющий подписывать данные с помощью сертификата. | ||
− | Классы для | + | <b>Классы для проведения платежей:</b> |
− | + | * Pay – платеж; | |
− | + | * Enlistment – зачисление. | |
− | |||
− | Классы для получения списка услуг: | + | <b>Классы для получения информации по абоненту:</b> |
− | PaymentDestination – услуга. | + | * Abonent – абонент; |
+ | * AbonentAccount – сведения о лицевом счете абонента, с привязкой к поставщику услуг; | ||
+ | * AbonentBalance – информация по услуге (долги, показания счетчика и т.д.). | ||
+ | |||
+ | <b>Классы для получения списка услуг:</b> | ||
+ | * PaymentDestination – услуга. | ||
+ | |||
+ | == Подпись данных с помощью библиотеки == | ||
− | |||
Пример исходного кода для подписи строки: | Пример исходного кода для подписи строки: | ||
− | //Открываем файл сертификата | + | <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)); | + | // Выполняем подпись с помощью класса-помощника |
− | + | var Sign = Convert.ToBase64String(signHelper.GetSign(Data)); | |
+ | </syntaxhighlight> | ||
+ | |||
+ | == Отправка запроса и получение результата == | ||
Пример исходного кода: | Пример исходного кода: | ||
− | requestData – объект, содержащий исходные данные для выполнения запроса к системе; | + | * requestData – объект, содержащий исходные данные для выполнения запроса к системе; |
− | response – результат, который возвращает система. | + | * response – результат, который возвращает система. |
− | + | ||
− | + | <syntaxhighlight lang="csharp"> | |
− | + | // Отправляем запрос | |
− | + | 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()); | ||
+ | </syntaxhighlight> | ||
− | + | == Запрос на проверку доступности платежной системы == | |
− | Для проверки доступности платежной системы необходимо отправить запрос с Operation = 0 и с пустым полем Data на адрес платежной системы. | + | Для проверки доступности платежной системы необходимо отправить запрос с Operation = 0 и с пустым полем Data на адрес платежной системы. В данном примере приведены все операции – от формирования запроса, до его подписи и отправки в систему. |
− | В данном примере приведены все операции – от формирования запроса, до его подписи и отправки в систему. | ||
Пример исходного кода: | Пример исходного кода: | ||
− | //Создаем запрос | + | |
− | var | + | <syntaxhighlight lang="csharp"> |
+ | // Создаем запрос | ||
+ | var requestData = new AbonentPaysystemRequest() | ||
{ | { | ||
SignedData = new RequestSignedData() | SignedData = new RequestSignedData() | ||
Строка 142: | Строка 236: | ||
Sign = "", | 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()); | |
+ | </syntaxhighlight> | ||
− | + | == Запрос на получение списка услуг == | |
Пример исходного кода: | Пример исходного кода: | ||
− | //Создаем запрос | + | <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 paymentDestinations = PaymentDestinations.FromJson(response.SignedData.Data); | |
+ | </syntaxhighlight> | ||
− | + | == Запрос на получение информации по лицевому счету == | |
Пример исходного кода: | Пример исходного кода: | ||
− | //Создаем запрос | + | <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(); | |
+ | |||
+ | //Подписываем | ||
+ | ………… | ||
+ | //Отправляем запрос | ||
+ | ………… | ||
+ | //Получаем результаты | ||
+ | var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd()); | ||
+ | //Отображаем результаты | ||
+ | var paymentDestinations = PaymentDestinations.FromJson(response.SignedData.Data); | ||
+ | </syntaxhighlight> | ||
− | + | == Запрос на проведение платежа == | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
Пример исходного кода: | Пример исходного кода: | ||
− | //Создаем запрос | + | <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.Enlistments.Add(new Enlistment() | |
{ | { | ||
Account = PayAccount.Text, | Account = PayAccount.Text, | ||
Строка 242: | Строка 343: | ||
Id = Guid.NewGuid(), | Id = Guid.NewGuid(), | ||
}); | }); | ||
− | //Передаем платеж в запрос | + | // Передаем платеж в запрос |
− | + | request.SignedData.Data = pay.ToJson(); | |
+ | // Подписываем | ||
+ | ………… | ||
+ | // Отправляем запрос | ||
+ | ………… | ||
+ | // Получаем результаты | ||
+ | var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd()); | ||
+ | </syntaxhighlight> | ||
− | + | == Запрос на проверку статуса платежа == | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
Пример исходного кода: | Пример исходного кода: | ||
− | //Создаем запрос | + | <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; | |
+ | //Подписываем | ||
+ | ………… | ||
+ | //Отправляем запрос | ||
+ | ………… | ||
+ | //Получаем результаты | ||
+ | var response = AbonentPaysystemResponse.FromJson(sr.ReadToEnd()); | ||
+ | </syntaxhighlight> | ||
− | + | [[Категория:Протокол online-обмена данными с платежной системой]] | |
− | |||
− | |||
− | |||
− | |||
− |
Текущая версия на 16:21, 1 сентября 2014
В данном документе описан регламент технического взаимодействия платежной системы «Абонент» с программным обеспечением агента по приему платежей по протоколу HTTP(S).
Документ предназначен для разработчиков программного обеспечения работающего на стороне агентов по приему платежей.
Содержание
- 1 Термины и определения
- 2 Общие принципы взаимодействия с Системой
- 3 Общее описание допустимых запросов к системе
- 4 Общая структура взаимодействия
- 4.1 Библиотека для формирования запросов к системе
- 4.2 Подпись данных с помощью библиотеки
- 4.3 Отправка запроса и получение результата
- 4.4 Запрос на проверку доступности платежной системы
- 4.5 Запрос на получение списка услуг
- 4.6 Запрос на получение информации по лицевому счету
- 4.7 Запрос на проведение платежа
- 4.8 Запрос на проверку статуса платежа
Термины и определения
Система – платежная система «Абонент».
Агент – организация, осуществляющая прием оплаты через платежную систему «Абонент».
Клиент - программное обеспечение Агента, реализующее клиентскую часть настоящего протокола.
Общие принципы взаимодействия с Системой
Взаимодействие с системой осуществляется в режиме запрос – ответ. Инициатором взаимодействия во всех случаях является Клиент.
Запрос
Представляет собой текстовый блок данных, структурированных в соответствии с требованиями формата JSON и настоящего Протокола. Для успешной обработки Запроса в нем обязательно должна присутствовать следующая информация.
- Код клиента - уникальный в рамках Системы номер точки, необходимый для идентификации Агента и последующей привязки платежей. Код клиента сообщается сотрудником нашей компании либо уточняется Агентом самостоятельно, с использованием Web-интерфейса.
- Электронно-цифровая подпись. Подпись выполняется на основании закрытого ключа, передаваемого Агенту перед началом программного взаимодействия. Ключ передается Агенту в виде сертификата - файла в формате X.509 версия 3. Запрещается передача этих сведений третьим лицам.
Электронно-цифровая подпись (ЭЦП) представляет собой строку, полученную по следующему алгоритму.
- Подписываемые данные, в виде JSON-строки преобразуются в массив байт в формате UTF-8.
- По полученному массиву байт вычисляется хэш-функция SHA-256 и сохраняется как массив байтов.
- По сохраненному массиву еще раз вычисляется хэш-функция пол алгоритму SHA1, т.е. в целом реализуется расчет вида SHA1(SHA256(<подписываемый блок данных>)).
- Полученный массив байтов шифруется алгоритмом RSA. В качестве ключа используется закрытый ключ Агента из сертификата.
- Полученный массив байтов преобразуется в строку Base64.
Запрос, представляет собой строку, полученную по следующему алгоритму.
- Формируется содержательная часть Запроса (строка подписываемых данных), включающая в себя "Код клиента" (ClientId), "Входные параметры" (Data), "Код операции" (Operation). Данные оформляются в виде текстовой строки в формате формата JSON.
- Согласно алгоритму, приведенному выше, формируется ЭЦП.
- Из полученной строки подписываемых данных, ЭЦП, а также некоторые дополнительных параметров ("Тип данных" и "Номер протокола") собираются окончательный Запрос.
Пример Запроса.
{
"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 – произошла ошибка обработки запроса.
Данные Ответа, подписываются по тому же алгоритму, что и данные Запроса, однако в качестве ключа используется открытый ключ Агента. Это дает возможность проверить правильность полученных данных по следующему алгоритму.
- Блок SignedData Ответа преобразуется в массив байт.
- От полученного массива данных рассчитывается хэш-функция вида SHA1(SHA256(<подписываемый блок данных>)).
- Значение в блоке Sign декодируется из Base64 в массив байтов и расшифровывается алгоритмом RSA с использование закрытого ключа Агента.
- Полученные на предыдущих этапах массивы сравниваются. Ответ считается корректным только в том случае, если содержимое массивов идентично.
Алгоритм взаимодействия с системой
В общем виде алгоритм взаимодействия с системой представляет собой последовательное выполнение следующих шагов.
- Формируется Запрос.
- Сформированый Запрос отправляется для обработки Системе с помощью метода POST HTTP-протокола. Для взаимодействия с Системой используются следующие два адреса:
http://beta-online.abonentplus.ru - адрес, используемый для разработки, отладки и тестирования Клиента; http://online.abonentplus.ru - адрес, используемый для регулярной работы с Системой.
- 3. В ответ на запрос Система формирует Ответ, который принимается клиентом и анализируется.
Общее описание допустимых запросов к системе
В рамках настоящего Протокола Клиенту доступны пять основных операций, каждой из которых присвоен условный код. При формирование Запроса данный код указывается в поле Operation блока основных (подписываемых) данных.
Список доступных операций следующий.
- Проверить подключение (код 0).
- Провести платеж (код 1).
- Получить информацию по лицевому счету (код 2).
- Проверить статус платежа (код 3).
- Получить список доступных услуг (код 4).
Кроме того, по определенным типам запросов система может возвращать выходные параметры.
Набор входных и выходных параметров по каждому типу запроса описан в следующих разделах.
Проверить соединение
- Входные параметры – код клиента.
- Выходные параметры – отсутствуют.
Получить список услуг
- Входные параметры – код клиента.
- Выходные параметры:
- Код услуги или ресурса (в дальнейшем используется для формирования платежа).
- Наименование услуги или ресурса.
- Код организации, оказывающей услугу или поставляющей ресурс.
- Наименование организации, оказывающей услугу или поставляющей ресурс.
- Код типа лицевого счета, используемый для идентификации плательщика.
- Наименование типа лицевого счета, используемого для идентификации плательщика.
- Реквизиты организации для перечисления средств.
- Дополнительные поля для формирования платежа.
Получить данные по абоненту
- Входные параметры:
- Код типа лицевого счета.
- Лицевой счет.
- Выходные параметры:
- Код типа лицевого счета.
- Лицевой счет абонента.
- Список альтернативных лицевых счетов абонента с указанием типа.
- Список услуг абонента с информацией для приема платежа (текущая задолженность, признак наличия счетчика, последние показания счетчика и дата их съема, текущий тариф).
Зарегистрировать платеж
- Входные параметры:
- Уникальный номер платежа (Guid).
- Дата/время.
- Примечание.
- Другая информация.
- Зачисления - список сумм оплат, с разбивкой по услугам, с указанием для каждой услуги:
- Кода типа лицевого счета.
- Лицевого счета.
- Кода услуги.
- Суммы платежа.
- Дополнительные параметры (текущие показания счетчика, оплачиваемы объем и т.д.).
- Выходные параметры – результат обработки (поставлен в очередь, отклонен и т.д.)
Проверить статус платежа
- Входные параметры – уникальный номер платежа (Guid).
- Выходные параметры: список зачислений с указанием результатов обработки по каждому из зачислений (отправлено поставщику услуг/находится в очереди на обработку/ошибка и т.д.).
Общая структура взаимодействия
Инициатором обмена является ПО агента по приему платежей. Запросы посылаются через интернет, по протоколу HTTP(S) методом POST. Данные передаются в JSON-формате. Каждый запрос обязательно должен быть подписан с помощью ЭЦП агента.
Запрос должен содержать следующие поля:
- ProtocolVersion – версия протокола, строка.
- DataFormat- формат данных в поле Data. В настоящее время поддерживается только формат JSON, что соответствует значению 0 в данном поле.
- SignedData – подписываемые данные, структура
- ClientId – код клиента платежной системы, целое. Данный код выдается при подключении к платежной системе.
- Operation – тип операции, целое. Подробнее каждый тип операции будет рассмотрен ниже.
- Data – данные для выполнения операции, объект в JSON-формате.
- 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());