API продавца
Для получения платёжных уведомлений на свой Callback URL и возврата средств пользователю вам необходимо использовать API продавца. Формат данных и синтаксис запросов отличаются от API ВКонтакте. Для взаимодействия с этим API вам нужно использовать идентификатор и приватный ключ продавца, полученные вами при заключении договора с платёжной системой.
Запросы, ответы и уведомления в API продавца всегда содержат три поля на верхнем уровне, закодированные urlencoded
:
- •
version
(string
) — версия API. - •
data
(string
) — JSON с данными в кодировке base64. - •
signature
string
— подпись данных. Принцип формирования подписи зависит от конкретного запроса или ответа.
Например:
version=2-07&data=eyJoZWFkZXIiOnsic3RhdHVzIjoiT0siLCJ0cyI6MTUyNzUxMTM0MiwiY2xpZW50X2lkIjo2NjIxMTh9LCJib2R5Ijp7InRyYW5zYWN0aW9uX2lkIjoiMEVFMzk5QzQtNjAwQi0xMUU4LUE5OUItMDQ1NzE2MzBGRTNDIiwibm90aWZ5X3R5cGUiOiJUUkFOU0FDVElPTl9TVEFUVVMifX0%3D&signature=fa01debe229aef71f262f09f8b9abcdbab3840d1
Можно представить эти данные в формате JSON:
{
"version": "2-07",
"data": "eyJoZWFkZXIiOnsic3RhdHVzIjoiT0siLCJ0cyI6MTUyNzUxMTM0MiwiY2xpZW50X2lkIjo2NjIxMTh9LCJib2R5Ijp7InRyYW5zYWN0aW9uX2lkIjoiMEVFMzk5QzQtNjAwQi0xMUU4LUE5OUItMDQ1NzE2MzBGRTNDIiwibm90aWZ5X3R5cGUiOiJUUkFOU0FDVElPTl9TVEFUVVMifX0=",
"signature": "fa01debe229aef71f262f09f8b9abcdbab3840d1"
}
Внутри JSON, закодированного в data
, в свою очередь, всегда содержатся два поля:
header
(object
) — обязательный заголовок. Содержит поля:
- •
client_id
(string
)— идентификатор продавца в платёжной системе (то же самое, что иmerchant_id
); - •
ts
(integer
) — время формирования вUnixtime
; - •
status
(string
)— статус ответа (OK
илиERROR
); - •
error
(object
) — данные об ошибке (опционально).
body
(object
) — полезная нагрузка. Синтаксис зависит от запроса.
Серверное платёжное уведомление
Уведомление отправляется по факту совершения платежа в пользу продавца на callback URL, который вы указали при заключении договора с платёжной системой, или по факту списания средств с расчётного счёта продавца (например, при возврате). При необходимости вы можете задать несколько адресов. Уведомление будет отправлено и в случае возврата платежа с кэшбеком. Сначала с пользователя спишется сумма кэшбека. Эта сумма будет зачислена на счет мерчанта и ДМР отправит уведомление об отмене кэшбека. И после произойдет возврат средств пользователю по указанной транзакции. Пример уведомления о возврате кэшбека. На уведомление нужно ответить — иначе мы продолжим присылать его снова и снова, предполагая, что продавец не обработал платёж. Если во время обработки уведомления произошла ошибка, нужно вернуть её в ответе — смотрите описание возможных ошибок в разделе Ошибки обработки уведомлений.
Уведомления будут отправляться из подсетей:
- •
95.213.29.0/24
,93.186.229.0/25
— для тестовых мерчантов - •
188.93.57.0/26
,188.93.57.192/26
— для боевых
Важно! Ответ на уведомление не может повлиять на статус транзакции.
Рекомендуется организовать хранение уведомлений на стороне Service Backend. Это может потребоваться для проведения возвратов по неуспешным транзакциям или для аналитики.
Пример body
для уведомления
{
"notify_type": "TRANSACTION_STATUS",
"transaction_id": "EEEAF322-10BD-11E8-93DF-CBAA984D4FFF",
"amount": "0.98",
"status": "PAID",
"added": "2018-02-13T16:01:02.000+03:00",
"paid": "2018-02-13T16:01:09.000+03:00",
"currency": "RUB",
"payee_amount": "1.50",
"pay_method": "internal_out",
"merchant_id": "617001",
"merchant_name": "Название компании",
"description": "Test payment",
"merchant_param": {
"currency": "RUB",
"merchant_data": "eyJvcmRlcl9pZCI6IjI1NTMxIiwidHMiOiIxNTM5MzI5NzcwIiwiYW1vdW50IjoxLjUsImN1cnJlbmN5IjoiUlVCIn0=",
"merchant_sign": "63d5dce9d2c9d29198ba12ba3f8e270e6606a221",
"order_id": "25531",
"ts": "1539329770"
},
"payment_info": {
"recipient": {
"client_id": "617001"
},
"sender": {
"user_id": "2314852"
}
},
"issuer_id": "blablabla",
"keep_uniq": "0",
"pay_system_name": "Внутренние переводы в рублях (кошелек-мерчант)"
}
Пример body
для ответа на уведомление
{
"transaction_id": "EEEAF322-10BD-11E8-93DF-CBAA984D4FFF",
"notify_type": "TRANSACTION_STATUS"
}
Описание полей body
для уведомления
- •
transaction_id
— идентификатор транзакции. Это поле (с тем же значением) необходимо передавать в ответе на уведомление. - •
notify_type
— тип платёжного уведомления (всегда содержит"TRANSACTION_STATUS"
). Это поле (с тем же значением) необходимо передавать в ответе на уведомление. - •
amount
— сумма платежа. Сумма может быть отрицательной (например, при возврате средств покупателю). - •
status
— статус транзакции:- •
PAID
— для обычных платежей; - •
HOLD
— для двухстадийных платежей.
- •
- •
added
— время создания транзакции. - •
paid
— время завершения транзакции. - •
currency
— валюта платежа (всегда содержит RUB). - •
payee_amount
— сумма зачисленных средств за вычетом комиссии платёжной системы. - •
pay_method
— платёжный метод (всегда содержитinternal_out
). - •
merchant_id
— идентификатор продавца. - •
merchant_name
— мазвание продавца. - •
description
— комментарий к платежу. - •
merchant_param
— данные продавца (содержимое поляdata
из параметров платёжного окна). - •
payment_info
— данные об участниках платежа:- •
recipient
— получатель. Содержит полеclient_id
с идентификатором продавца в платёжной системе. - •
sender
— отправитель. Содержит полеuser_id
с идентификатором пользователя ВКонтакте.
- •
- •
issuer_id
— идентификатор транзакции в платёжной системе. - •
keep_uniq
— служебный параметр. - •
pay_system_name
— наименование платёжного метода.
Проверка подписи уведомления
Подпись платёжного уведомления (поле signature
) это строка в base64 — RSA-SHA1-хэш поля data
.
Для проверки подписи необходимо использовать публичный ключ платёжной системы:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAukXD0MX64KKsWuiv2A4/
IEaXknvze019wZtvxYOIgGFjeWGp26CMa627cKpQS8TOT9TJ9OgbWuI+MWTK2dfP
yDzqfuPVHWbnBaM85O3tQ/Tv2mBwkvzP3z1gTZ+mYSuAfZG0H6vLG0GPDj2I79Zj
QSXcLSNWoS+7XNcLgDE5RCdAF+VLlSir+e1n/JWRb3XtIyyrDMF3VzfJsX6DVhxW
4FfhxqjX4JHiMhdDHHiuzMJ3zNaLOzS7ynaQ5OgCfp89ageNMgp1DbLpGbxlXlex
m4/CSuoVEY6NPrpytVAOJhiE0rwtBZPsMTGzXtBXpxv2NyO2Qdh0kjhB+qa3mmln
XwIDAQAB
-----END PUBLIC KEY-----
Пример проверки подписи уведомления на PHP:
$verify_res = openssl_verify($input['data'], base64_decode($input['signature']), $public_key);
if (!$verify_res) {
die 'Can\'t verify notification signature';
}
Подпись ответа на платёжное уведомление
Подпись ответа платёжного уведомления (поле signature
) это строка в base64 — SHA1-хэш в HEX-представлении от конкатенации поля data
и приватного ключа продавца.
Формирование подписи ответа на уведомление:
Шаг 1. Собираем data
— JSON-объект с заголовком и телом запроса:
{
"body": {
"transaction_id": "49488FFC-D5D6-11E8-A1A6-C9407A00CD62",
"notify_type": "TRANSACTION_STATUS"
},
"header": {
"status": "OK",
"ts": 1540197702,
"client_id": "749514"
}
}
Шаг 2. Берём от него base64:
eyJib2R5Ijp7InRyYW5zYWN0aW9uX2lkIjoiNDk0ODhGRkMtRDVENi0xMUU4LUExQTYtQzk0MDdBMDBDRDYyIiwibm90aWZ5X3R5cGUiOiJUUkFOU0FDVElPTl9TVEFUVVMifSwiaGVhZGVyIjp7InN0YXR1cyI6Ik9LIiwidHMiOjE1NDAxOTc3MDIsImNsaWVudF9pZCI6Ijc0OTUxNCJ9fQ==
Шаг 3. Конкатенируем с приватным ключом продавца:
eyJib2R5Ijp7InRyYW5zYWN0aW9uX2lkIjoiNDk0ODhGRkMtRDVENi0xMUU4LUExQTYtQzk0MDdBMDBDRDYyIiwibm90aWZ5X3R5cGUiOiJUUkFOU0FDVElPTl9TVEFUVVMifSwiaGVhZGVyIjp7InN0YXR1cyI6Ik9LIiwidHMiOjE1NDAxOTc3MDIsImNsaWVudF9pZCI6Ijc0OTUxNCJ9fQ==32224b236d226c8298ea62f976f5bc457afaca8f
Шаг 4. Берём от полученной конкатенации SHA-1 хэш в HEX:
10e9d4ce7984f5e9b767b3669cf1c811d6385741
Конечный результат:
{
"version": "2-03",
"data": "eyJib2R5Ijp7InRyYW5zYWN0aW9uX2lkIjoiNDk0ODhGRkMtRDVENi0xMUU4LUExQTYtQzk0MDdBMDBDRDYyIiwibm90aWZ5X3R5cGUiOiJUUkFOU0FDVElPTl9TVEFUVVMifSwiaGVhZGVyIjp7InN0YXR1cyI6Ik9LIiwidHMiOjE1NDAxOTc3MDIsImNsaWVudF9pZCI6Ijc0OTUxNCJ9fQo=",
"signature": "7625c1d2030f2b45545c42baf2cce14d56e7fb55"
}
Ошибки обработки уведомлений
Если при обработке уведомления произошла ошибка, необходимо вернуть данные о ней в ответе на уведомление:
{
"body": {
"transaction_id": "EEEAF322-10BD-11E8-93DF-CBAA984D4FFF",
"notify_type": "TRANSACTION_STATUS"
},
"header": {
"status": "ERROR",
"ts": "1438072029",
"client_id": "617001",
"error": {
"code": "ERR_DUPLICATE",
"message": "Error message"
}
}
}
Возможные значения error_code
:
- •
ERR_SYSTEM
— техническая ошибка на стороне продавца. Уведомление будет отправлено повторно; - •
ERR_ARGUMENTS
— ошибка обработки параметров уведомления. Уведомления будут приостановлены; - •
ERR_SIGNATURE
— ошибка проверки подписи уведомления. Уведомления будут приостановлены; - •
ERR_DUPLICATE
— уведомление с указаннымtransaction_id
уже обработано. Уведомления будут остановлены.
Возврат средств покупателю
Возврат средств может быть осуществлен в день платежа до 23:00 по московскому времени (отмена) или в любой другой день (возврат). Разница в запросах на отмену и возврат заключается в эндпоинте для отправки запроса к API. /vkpay/reverse
в отличие от /transaction/refund
возвращает средства пользователью полностью, вместе с комиссией ДМР, если возврат средств был осуществлен в день платежа до 23:00 по московскому времени. В другом случае, если возврат средств был осуществлен на следующий день или после 23:00, результат работы метода аналогичен полному возврату методом /transaction/refund
.
Для отмены покупки до 23:00 этого же дня нужно отправить запрос по следующему URL: https://api.money.mail.ru/money/2-04/vkpay/reverse
.
Важно! Частичный возврат с методом /vkpay/reverse
невозможен.
Для полного или частичного возврата средств спустя 23 часа после платежа нужно отправить запрос к API продавца по следующему URL: https://api.money.mail.ru/money/2-04/transaction/refund
.
Пример запроса (curl
)
$ curl -vL -X POST -d
'version=2-04&data=eyJoZWFkZXIiOnsidHMiOjE1NDQyOTU5NTgsImNsaWVudF9pZCI6IjU0Mzk0MSJ9LCJib2R5Ijp7InRyYW5zYWN0aW9uX2lkIjoiNjY4RjlGNUMtRkIwMC0xMUU4LUI1MEYtMDI1QTBFNEZEM0I4IiwiYW1vdW50IjoiMS4wMSIsImN1cnJlbmN5IjoiUlVCIiwicmVhc29uIjoiSnVzdCByZWZ1bmQifX0%3D&signature=fe476a9d66e96ab38fc65ee10a46d9ded546381c' https://api.money.mail.ru/money/2-04/transaction/refund
Пример body
для запроса на возврат/отмену средств
{
"transaction_id": "EEEAF322-10BD-11E8-93DF-CBAA984D4FFF",
"amount": "1.50",
"currency": "RUB",
"reason": "Just refund"
}
Описание полей body
для запроса на возврат/отмену средств
- •
transaction_id
(string
) — идентификатор транзакции, по которой нужно сделать возврат/отмену. - •
amount
(string
) — сумма возврата/отмены. По умолчанию — полная сумма транзакции (только для/transaction/refund
). - •
currency
(string
) — валюта платежа (всегда содержит RUB) (только для/transaction/refund
). - •
reason
(string
) — причина возврата/отмены.
Пример body
для ответа на запрос возврата/отмены средств
{
"transaction_id": "EEEAF322-10BD-11E8-93DF-CA984DA4FFBF",
"action": "stop",
"action_param": {
"status": "success"
}
}
Описание полей body
для ответа на запрос возврата/отмены средств
- •
transaction_id
(string
) — идентификатор транзакции возврата/отмены. - •
action
(string
) — действия для продолжения. Содержит одно из значений:- •
wait
— необходимо запросить статус транзакции запросом transaction/status; - •
stop
— статус транзакции конечный и содержится вaction_param
.
- •
- •
action_param
(object
) — набор параметров дляaction
(значение может быть пустым).status
— дополнительное уточнение статуса. Дляaction=stop
возможные значенияstatus
:success
,fail
Подпись запроса на возврат/отмену средств
Подпись запроса формируется аналогично подписи ответа на платёжное уведомление, с единственным отличием — на третьем этапе, при конкатенации data
и приватного ключа продавца, в начало строки необходимо добавить относительный URL запроса:
/money/2-04/transaction/refund
или
/money/2-04/vkpay/reverse
Возможные ошибки
В ответе на запрос может вернуться одна из следующих ошибок:
- •
ERR_TRANSACTION_NOT_FOUND
— транзакция с переданным идентификатором не найдена. - •
ERR_AMOUNT_GREATER_THAN_ALLOWED
— сумма возврата/отмены больше суммы платежа. - •
ERR_ALREADY_REFUNDED
— платеж уже полностью возвращён. - •
ERR_REFUND_FAILED
— возврат/отмена не удались. - •
ERR_NOMONEY
— на счёте продавца недостаточно средств для возврата. - •
ERR_ACCESS_DENIED
— нет доступа к указанной транзакции. - •
ERR_RATE_LIMIT
— превышено максимально допустимое число возвратов/отмен по одной транзакции. - •
ERR_COMMON
— возможно, ошибка в названииsignature
.
Статус транзакции
В случае, если запрос на возврат средств поле action
имеет значение wait
, вам следует «поллить» статус транзакции.
https://api.money.mail.ru/money/2-04/transaction/status
.
Пример запроса (curl
)
$ curl -X POST -d 'signature=2501667f7589a9d0991c1453de88a9c75e381239&data=eyJib2R5Ijp7InRyYW5zYWN0aW9uX2lkIjoiNjY4RjlGNUMtRkIwMC0xMUU4LUI1MEYtMDI1QTBFNEZEM0I4In0sImhlYWRlciI6eyJjbGllbnRfaWQiOjY5MTQ0NywidHMiOjE1Njg3OTc3MzF9fQ%3D%3D' https://api.money.mail.ru/money/2-03/transaction/status
Пример body
для запроса
{
"transaction_id": "668F9F5C-FB00-11E8-B50F-025A0E4FD3B8"
}
Описание полей body для запроса статуса транзакции
- •
transaction_id
(string
) — идентификатор транзакции возврата.
Пример body
для ответа на запрос статуса транзакции
{
"action_param": {
"status": "success"
},
"transaction_id": "668F9F5C-FB00-11E8-B50F-025A0E4FD3B8",
"action": "stop"
}
Описание полей body
для ответа на запрос статуса транзакции
- •
transaction_id
(string
) — идентификатор транзакции возврата. - •
action
(string
) — действия для продолжения. Содержит одно из значений:- •
wait
— необходимо запросить статус транзакции запросомtransaction
/status
; - •
stop
— статус транзакции конечный и содержится вaction_param
.
- •
- •
action_param
(object
) — набор параметров дляaction
(значение может быть пустым).status
— дополнительное уточнение статуса. Дляaction=stop
возможные значенияstatus
:success
,fail
Подпись запроса на статус транзакции
Подпись запроса формируется аналогично подписи ответа на платёжное уведомление, с единственным отличием — на третьем этапе, при конкатенации data
и приватного ключа продавца, в начало строки необходимо добавить относительный URI запроса:
/money/2-04/transaction/status
Возможные ошибки
- •
ERR_NOT_FOUND
— запрошенная транзакция не найдена
Тестирование работы с платежами
Для тестирования API платежной формы и API продавца мы предоставим вам данные тестового продавца — идентификатор продавца, приватный ключ продавца и публичный ключ платёжной системы. Для начала работы вам нужно создать приложение ВКонтакте и сообщить нам адрес callback URL для отправки серверных платёжных уведомлений. Напоминаем, что для корректной работы с логикой сообщений сообщества в период тестирования необходимо разрешать доступ к отправке сообщений пользователю. После размещения в каталоге это будет происходить автоматически.
К сожалению, мы не предоставляем кошельки для тестирования. Платежи в адрес тестовых продавцов автоматически возвращаются получателям в течение суток. Мы рекомендуем использовать для тестирования небольшие значения amount
— например, 1 рубль.
Важно! У тестового продавца нет логотипа и названия в платёжной системе, поэтому вы не увидите их в платёжном окне. После заключения договора при переходе на боевые данные, будут использованы указанные вами логотип и название продавца.
Пользователь не может совершить платеж в пользу тестового продавца с 23.00 до 0.30. Это ограничение связано с возвратами тестовых платежей.
В течение этого времени можно поднять платежное окно, но произвести оплату нельзя.