Протокол обмена данными

Общие сведения

Протокол пакетного обмена создан для удобства одновременного проведения большого количества платежей, а также для повышения удобства реализации клиентского ПО, за счет переноса части клиентской логики на сервер.

Запросы должны отправляться на следующий URL: https://188.133.220.43/term2/term2/xml.jsp

Процедура обмена включает следующие этапы:

Шаг 1. Опрос баланса

Отправка запросов на сервер осуществляется по HTTP протоколу, методом POST.

Пример запроса баланса:
<?xml version="1.0" encoding="utf-8"?>
<request>
	<protocol-version>4.00</protocol-version>
	<request-type>3</request-type>
	<terminal-id>123</terminal-id>
	<extra name="login">S1</extra>
	<extra name="sign-md5">S2</extra>
</request>
Описание:

Параметры запроса помещаются в элемент <request>.
Тег <request> включает в себя следующие теги:

  • <protocol-version> – данный тег содержит номер версии протокола обмена;
  • <request-type> – тип запроса 3;
  • <terminal-id> – идентификатор, с которого осуществляется платеж;
  • <extra> – тег описывает данные авторизации: S1 – логин пользователя (кассира), S2 – Хэш-подпись пакета на отправку (см. Приложение А).
Ответ сервера:
<response requestTimeout="60">
	<extra name="balance">6.5600</extra>
	<extra name="overdraft">0.0000</extra>
</response
Описание:
  • requestTimeout – рекомендуемый сервером интервал запроса статуса платежей в секундах. Вы можете использовать это число для отсчета времени (в секундах) перед запросом статуса. К указанному времени все платежи, посланные на обработку, должны быть проведены.
  • extra описывает составные части баланса: balance – баланс агента, overdraft – выставленный кредитный лимит. Общий баланс равен balance+overdraft.

Шаг 2. Онлайн проверка платежа

Пример запроса онлайн проверки:
<?xml version="1.0" encoding="utf-8"?>
<request>
	<protocol-version>4.00</protocol-version>
	<request-type>10</request-type>
	<terminal-id>123</terminal-id>
	<extra name="login">S1</extra>
	<extra name="sign-md5">S2</extra>
	<check count="1" to-amount="50">
		<payment>
			<transaction-number>123456789</transaction-number>
			<to>
				<amount>50</amount>
				<service-id>2</service-id>
				<account-number>1234567890</account-number>
			</to>
		</payment>
	</check>
</request>
Описание:

Параметры запроса помещаются в элемент <request>.

Тег <request> включает в себя следующие теги:

  • <protocol-version> – данный тег содержит номер версии протокола обмена;
  • <request-type> – тип запроса 3;
  • <terminal-id> – идентификатор, с которого осуществляется платеж;
  • <extra> – тег описывает данные авторизации: S1 – логин пользователя (кассира), S2 – хэш-подпись пакета на отправку (см. Приложение А).

Тег <check> содержит перечень платежей на проверку и включает в себя следующие теги:

  • <payment> – тег, содержащий данные о платеже
<request>
...
	<check>
		<payment>
			...
		</payment>
	</check >
</request>

Тег <payment> описывает конкретные платежи и включает в себя следующие теги:

  • <transaction-number> – номер транзакции на терминале. Пара номер транзакции + номер терминала должны быть всегда уникальны;
  • <to> – информация о платеже: сумма, номер счета, идентификатор провайдера. Тег содержит дочерние теги:

- <amount> – сумма к зачислению на счет;
- <service-id> – идентификатор сервиса, на который производится зачисление средств (идентификатор провайдера).
- <account-number> – идентификатор абонента в информационной системе провайдера (номер сотового телефона или номер лицевого счета);

  • <receipt> – информация о выданном чеке. Тег содержит дочерние теги:

- <datetime> – дата распечатки чека в формате yyyymmddhhnnss;
- <receipt-number> – номер чека – число 0..999999 последовательно закольцовано;

Ответ сервера:
<response>
	<request-type>1</request-type>
	<status-id>30</status-id>
	<extra name="disp1">Иванов Иван Иванович</extra>
</response>
Описание:
  • <status-id> – код результата онлайн проверки: 30 – успешная проверка, 28 не успешная;
  • <extra> описывает составные части онлайн проверки: disp1 – текстовый результат проверки.

Шаг 3. Отправка запроса на проведение платежей

Пример запроса баланса:
<?xml version="1.0" encoding="utf-8"?>
<request>
	<protocol-version>4.00</protocol-version>
	<request-type>10</request-type>
	<terminal-id>123</terminal-id>
	<extra name="login">S1</extra>
	<extra name="sign-md5">S2</extra>
	<auth>
		<payment>
			<transaction-number>N1</transaction-number>
			<to>
				<amount>N3</amount>
				<service-id>N4</service-id>
				<account-number>N5</account-number>
			</to>
			<fields>
				<field id="1">N7</field>
				<field id="2">N8</field>
			</fields>
			<receipt>
				<datetime>D1</datetime>
				<receipt -number>N6</receipt-number>
			</receipt>
			<extra name="S1">S2</extra>
		</payment>
	</auth>
</request>
Описание:

Параметры запроса помещаются в элемент <request>. Тег <request> включает в себя следующие теги:

  • <protocol-version> – данный тег содержит номер версии протокола обмена;
  • <request-type> – тип запроса;
  • <terminal-id> – идентификатор, с которого осуществляется платеж;
  • <extra> – тег описывает данные авторизации: S1 – логин пользователя (кассира), S2 - хэш-подпись пакета на отправку (см. Приложение А).

Тег <auth> содержит перечень платежей на отправку и включает в себя следующие теги:

  • <payment> – тег, содержащий данные о платеже
<request>
	...
	<auth>
		<payment>
			...
		</payment>
		<payment>
			...
		</payment>
		<payment>
			...
		</payment>
	</auth>
</request>

Тег <payment> описывает конкретные платежи и включает в себя следующие теги:

  • <transaction-number> – номер транзакции на терминале. Пара номер транзакции + номер терминала должны быть всегда уникальны;
  • <to> – информация о платеже: сумма, номер счета, идентификатор провайдера. Тег содержит дочерние теги:

- <amount> – сумма к зачислению на счет;
- <service-id> – идентификатор сервиса, на который производится зачисление средств (идентификатор провайдера);
- <account-number> – идентификатор абонента в информационной системе провайдера (номер сотового телефона или номер лицевого счета);

  • <fields> – информация о дополнительных полях для проведения платежа. Тег содержит дочерние теги:

- <field id=«1»> – дополнительное поле 1;
- < field id=«N»> – дополнительное поле N;

  • <receipt> – информация о выданном чеке. Тег содержит дочерние теги:

- <datetime> – дата распечатки чека в формате yyyymmddhhnnss;
- <receipt-number> – номер чека – число 0..999999 последовательно закольцовано;

  • <extra> – служебные поля, например, комментарий: <extra name=«comment»>это комментарий</extra>
Ответ сервера:

После отправки запроса на сервер, в ответ приходит пакет с результатами добавления транзакций в базу:

<response requestTimeout=N1>
	<payment status =N2 transaction-number=N3 result-code=N4>
		...
	</payment>
	...
</response>
Описание:
  • requestTimeout – рекомендуемый сервером интервал запроса статуса платежей в секундах. Вы можете использовать это число для отсчета времени (в секундах) перед запросом статуса . К указанному времени все платежи, посланные на обработку, должны быть проведены.
  • status – статус транзакции после добавления в базу. Нормальным результатом добавления транзакции считается статус 25. Все остальные статусы могут возникать в результате исключительных ситуаций и по вопросам их возникновения необходимо обращаться в службу поддержки.

В случае если добавление транзакции завершилось со статусом отличным от 25, то необходимо проверить правильность формирования XML запроса и повторить отправку с другим номером транзакции

  • transaction-number – номер транзакции, добавленной в базу;
  • result-code – код обработки операции.

Шаг 4. Запрос о состоянии платежей

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

Пример запроса баланса:
<request>
	...
	<status>
		<payment>
			<transaction-number>1</transaction-number>
		</payment>
		<payment>
			<transaction-number>2</transaction-number>
		</payment>
		<payment>
			<transaction-number>3</transaction-number>
		</payment>
	</status>
</request
Описание:
  • <status> – содержит транзакции, по которым нужно узнать статус;
  • <payment> – информация о платеже. Тег содержит дочерний тег: - <transaction-number> – номер транзакции, по которой необходимо узнать текущее состояние.
Ответ сервера:

После отправки запроса на сервер, в ответ приходит пакет с результатами обработки запрашиваемых транзакций:

<response>
	<payment transaction-number="N1" status="N2" result-code="N3" final-status="B1" fatal-error="B2">
	...
	</payment>
	...
</response>
Описание:
  • transaction-number – номер транзакции, для которой указан статус
  • status – код текущего статуса транзакции;
  • result-code – код завершения операции;
  • final-status:

- false – статус промежуточный и обработка транзакции продолжается, необходим повторный запрос статуса для этой транзакции;
- true – статус является окончательным. Обработка транзакции прекращена сервером.

  • fatal-error:

- false – если значение final-status – true (сервер прекратил обработку платежа), повторная отправка этого платежа на сервер, но с другим номером транзакции, даст другой результат (возможно платеж пройдет);
- true – обработка платежа завершена в результате фатальной ошибки, повторная отправка платежа с другим номером транзакции приведет к повторению той же ошибки.

ПРИЛОЖЕНИЕ А: АВТОРИЗАЦИЯ С ПОМОЩЬЮ ПОДПИСИ

Для обеспечения большей безопасности, при пересылке платежных пакетов вы можете использовать авторизацию с помощью специальной подписи (элемент sign-md5), которая формируется по следующему алгоритму:

  1. Каждый элемент transaction-number складывается с MD5 от пароля: transaction-number+password-md5
  2. Осуществляется MD5 хеширование результирующей строки. В результате будет получена строка MD5 последовательности из 32 байт: md5(transaction-number+password-md5))
  3. Все полученные MD5 последовательности (для каждого элемента transaction-number) необходимо перевести в битовые массивы, соответствующие шестнадцатеричным кодам, и сложить по модулю 2 (XOR): сумма_транзакций=сумма_ транзакций XOR md5(transaction-number+password-md5))
  4. Преобразовать полученный в результате всех операций битовый массив в строку, содержащую 32 символа шестнадцатеричных.
  5. Полученную строку (длиной 32 символа) необходимо сложить с логином, номером терминала, номером запроса, MD5 от пароля: login+password-md5+terminal-id+request-type +сумма_транзакций
  6. Осуществляется MD5 хеширование результирующей строки: sign-md5=md5(login+password_md5+terminal-id+request-type+сумма_транзакций)
  7. Полученная последовательность записывается в элемент <extra name=«sign-md5»>.

Например:

<extra name="sign-md5">81164E9C056CEF02F90E671559D6D4BF</extra>

Пример 1. Пример формирования подписи на JAVA

/* *
*	Function for getting OSMP sign-md5 from Document (Represents source XML)
*	@param doc Документ, сформированный из подписываемой XML
*	@param login Логин пользователя
*	@param passMD5 md5 от пароля пользователя
*	@return Подпись пакета
*	@throws NoSuchAlgorithmException
*/
private String getSign(Document doc , String login, String passMD5) throws NoSuchAlgorithmException { 
//	Получаем id терминала
//	Получаем тип запроса
//	Получаем суммы транзакций
//	Формируем подпись из строки
return md5(login + passMD5 + termin al_id + request_type + txn_sum);
}
/**
*	Функция получения общей суммы md5 подписей номеров транзакций
*	@param doc Документ, сформированный из подписываемой XML
*	@param passMD5 Документ, сформированный из подписываемой XML
*	@return Строка с md5 подписью номеров
*	@throws NoSuchAlgorithmException
*/
private String getSignTxnSum (Document doc, String passMD5) throws NoSuchAlgorithmException {
	NodeList requestNodeList = doc.getElementsByTagName("request");
	NodeList nl = ((Element) requestNodeList.item(0)).getElementsByTagName ("payment");

	byte[] sum = new byte[16];
	for (int i = 0; i < sum.length; i++)
	{
		sum[i]=0;
	}

	MessageDigest md = MessageDigest.getInstance("MD5");
	if (nl.getLength()== 0)
		return "";

	//Проходим по всем номерам транзакций.
	for (int i = 0; i < nl.getLength(); i++)
	{
		String txn_id = getTextNode(nl.item(i), "transaction-number");
		//	код ошибки (0 - все ОК)
		if (txn_id!=null & & txn_id.length ()>0)
		{
			//Берем md5 подпись от номера транзакции + пароль пользователя
			byte[] buf = md.digest((txn_id + passMD5) .getBytes()); //Полученный байтовый массив суммируем
			sum = xorArray (sum, buf);
		}
	}

	StringBuffer sb = new StringBuffer();

	//	Преобразуем полученный массив в строковое представление в hex 
	for (byte aSum : sum) 
	{
		String hex = "00" + Integer.toHexString(aSum); 
		sb.append(hex.substring(hex.length() - 2));
	}
	return sb.toString().toUpperCase();
}

//Функция суммирования массивов.
private byte [] xorArray(byte [] a, byte [] b)
{
	if(b.length != a.length) throw new IllegalArgumentException("length of byte [] b must be >= byte [] a");
	byte [] c = new byte[a.length];
	for(int i =0;i< a.length;i++)
	{
		c[i] = (byte)(a[i] ^ b[i]);
	}
	return c;
}

//Функция получения строкового представления md5 от строки 
public static String md5(String passw) {
	try
	{
		MessageDigest md = MessageDigest.getInstance("MD5"); byte[] buf = md.digest(passw.getBytes()); StringBuffer sb = new StringBuffer();
		for (byte aBuf : buf) 
		{
			String hex = "00" + Integer.toHexString(aBuf); sb.append(hex.substring(hex.length() - 2));
		}
		return sb.toString().toUpperCase();
	}
	catch (NoSuchAlgorithmException e)
	{
		return null;
	}
}

//	Функция получения текстового элемента их xml документа 
public static String getTextNode(Node node, String tagName)
{
	NodeList nl = null;
	if (node instanceof Element)
		nl = ((Element) node).getElementsByTagName(tagName); 
	else if (node instanceof Document)
		nl = ((Document) node).getElementsByTagName(tagName); 
	if (nl == null) return null;
	if (nl.getLength() < 1 ) return 
	null; Node n = nl.item(0);
	if (!n.hasChildNodes()) return 
	null; n = n.getFirstChild();
	if (n instanceof Text) return n.getNodeValue(); 
	return null;
}

ПРИЛОЖЕНИЕ B: СТАТУСЫ ПЛАТЕЖЕЙ

Возможные значения поля status:

Значение Описение
10 Платеж принят
25 В процессе
51 Успешно проведен
160 Платеж отлонен

ПРИЛОЖЕНИЕ С: КОДЫ ОШИБОК

Возможные значения поля result-code:

0 Успешно обработан
3 Техническая ошибка, нельзя отправить запрос провайдеру
4 Неверная сумма платежа
5 Провайдер временно недоступен
90 Проведение платежа не окончено
111 Прием платежа запрещен, обратитесь в техподдержку
130 Работа с данным провайдером не реализована
150 Ошибка авторизации
151 Ошибка при обработке входящего xml
215 Транзакция с таким номером уже есть в базе
220 Недостаточно средств для проведения платежа