Заявка на подключение
Для магазинов: 
agents

VK Pay How To

  1. Что такое VK Pay?
  2. Что нужно, чтобы начать принимать платежи через VK Pay?
  3. Регистрация в платёжной системе
  4. VK Pay в сервисе VK Apps
  5. VK Pay на Вашем сайте
  6. VK Pay в офлайне
  7. Как работает платёжная форма?
  8. API платёжной формы
    8.1. Методы для вызова платёжной формы
    8.2. Синтаксис params
    8.3. Синтаксис data
    8.4. Подпись продавца
    8.5. Подпись приложения
    8.6. Как отслеживать статус платежа?
    8.7. Как работать с сообщениями?
    8.8. Возможные ошибки
  9. API продавца
    9.1. Серверное платёжное уведомление
    9.2. Возврат средств покупателю
    9.3 Статус транзакции
  10. Тестирование работы с платежами
  11. Платежи физическим лицам
1. Что такое VK Pay?

VK Pay — это платформа социальной коммерции ВКонтакте. Мы предлагаем пользователям новый способ оплаты товаров и услуг: в приложениях, на внешних сайтах и в офлайн-магазинах.

Пользователь привязывает свою банковскую карту (или несколько) к кошельку VK Pay, а затем расплачивается в сервисах — без ввода реквизитов и дополнительных шагов.

Провайдером платёжных операций VK Pay выступает РНКО «Деньги.Мэйл.Ру». Более подробную информацию о расчетной организации Вы можете найти (здесь).

VK Pay доступен для пользователей в основном меню мобильных приложений и веб-версии ВКонтакте.

На главной странице мы предлагаем каталог приложений с товарами и услугами, в которых действуют акции и спецпредложения.

2. Что нужно, чтобы начать принимать платежи через VK Pay?

Вы можете принимать оплату через VK Pay за товары и услуги тремя способами:

  • В Вашем сервисе VK Apps внутри ВКонтакте
  • На сайте Вашего интернет-магазина
  • С помощью QR-кода в офлайне

Для начала работы Вам нужно зарегистрироваться в платёжной системе — то есть, заключить договор с расчётной организацией, затем создать сервис VK Apps или добавить кнопку оплаты на Ваш сайт. После этого Вы можете принимать платежи от пользователей.

3. Регистрация в платёжной системе

Для проведения платежей через VK Pay Вам нужен идентификатор продавца. Этот идентификатор присваивается продавцу со стороны РНКО «Деньги.Мэйл.Ру» после заключения договора о присоединении к условиям приема платежей.

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

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

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

4. VK Pay в сервисе VK Apps

Создайте свой сервис на платформе VK Apps, в котором пользователи смогут оплачивать товары услуги с помощью VK Pay.

VK Apps — это платформа веб-приложений, которые открываются внутри официального мобильного клиента, умеют работать с API ВКонтакте и устройства пользователя. Приложения VK Apps создаются с помощью наших библиотек:

  • VK UI — компоненты интерфейса, чтобы сервис на мобильном устройстве выглядел привычно для пользователя;
  • VK Connect — методы для общения сервиса с официальным приложением ВКонтакте, чтобы всё работали быстро и без лишний действий для Вашего клиента;
  • VK Icons — иконки на все случаи жизни, чтобы интерфейс был привлекательным и аккуратным.

Посмотреть на примеры сервисов можно здесь или в пункте «Сервисы» официального приложения ВКонтакте на Вашем телефоне.

О разработке сервисов VK Apps мы подробно рассказываем в специальном сообществе и в документации API.

Наши специалисты проконсультируют Вас по всем этапам разработки.

Важно! Функциональность и внешний вид сервиса Вы определяете сами, но для попадания в каталог приложение должно соответствовать нашим рекомендациям.
5. VK Pay на Вашем сайте

Добавьте новый способ оплаты товаров и услуг на сайт Вашего магазина.

Вы можете разместить кнопку VK Pay на Вашем сайте и принимать платежи от пользователей ВКонтакте.

Важно! Мы просим придерживаться наших рекомендаций по размещению кнопки для оплаты через VK Pay и логотипа VK Pay на Вашем сайте и в любых маркетинговых материалах.
6. VK Pay в офлайне

Распечатайте QR-коды для оплаты или генерируйте их в специальном приложении — покупателю достаточно навести камеру телефона для оплаты покупки в Вашем магазине.

Свяжитесь с нами, чтобы узнать подробнее о возможностях VK Pay для офлайн-продавцов.

7. Как работает платёжная форма?

С точки зрения пользователя платёжная форма VK Pay — это всплывающее окно внутри ВКонтакте, в котором указана сумма платежа, комментарий к платежу и данные продавца. Если Вы принимаете оплату на своём сайте, всплывающее окно будет отображено поверх содержимого самого сайта. Оно выглядит так:

Если на балансе пользователя недостаточно средств, в этом же окне мы предложим ему пополнить счёт, чтобы продолжить оплату:

После успешной оплаты или отмены платежа окно закроется, и пользователь вернётся в Ваш сервис или на Ваш сайт.

А если у пользователя ещё нет VK Pay?

Вместо формы оплаты во всплывающем окне он увидит предложение зарегистрироваться и после этого сможет продолжить покупку.

А если пользователь не авторизован ВКонтакте, когда заходит на мой сайт?

В этом случае мы предложим ему авторизоваться — в том же всплывающем окне. После авторизации он увидит платёжную форму. Впрочем, для рунета это скорее исключение из правил.

С точки зрения разработчика платёжная форма — это URL с параметрами продавца и приложения (сервиса VK Apps или сайта). Ваша задача — правильно сформировать этот URL с помощью методов VK Connect (для VK Apps) или Open API (для внешнего сайта) и отследить результат действий пользователя, связав его с бизнес-логикой магазина.

В схеме оплаты участвуют 4 стороны:

  • Service Frontend — клиентская часть Вашего приложения ВКонтакте или сайта, на котором Вы хотите принимать платежи через VK Pay;
  • Service Backend — серверная часть Вашего приложения или сайта;
  • VK Pay — приложение-кошелек, размещенное ВКонтакте;
  • DMR — Деньги@mail.ru, платежная система.

Service Frontend формирует вызов платёжного окна VK Pay с заданными параметрами. Чтобы параметры платёжного окна не могли быть скомпрометированы на стороне клиента и в качестве гарантии, что продавец готов к получению оплаты, среди параметров передаются подписи приложения и продавца.

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

VK Pay валидирует подпись приложения, переданную среди параметров вызова. Если подпись корректная, открывается предзаполненное платёжное окно. После того, как пользователь нажал кнопку «Оплатить», VK Pay формирует платёжный запрос к системе DMR.

DMR валидирует подпись продавца, переданную в платёжном окне. Если подпись корректная, средства с кошелька пользователя переводятся на расчётный счет мерчанта в платёжной системе. Service Backend получает платёжное уведомление с данными транзакции от DMR.

Service Frontend получает клиентское событие от VK Pay о статусе платежного окна.

Если пользователи получают кешбэк за покупки в Вашем магазине, данные о сумме и времени начисления передаются из Service Frontend вместе с другими параметрами платёжного окна и участвуют в формировании подписи продавца. Распоряжение на списание указанной суммы кешбэка в указанное время формируется в момент транзакции и не может быть изменено за исключением случаев отмены покупки (возврата средств пользователю).

Важно! Размер и срок зачисления кешбэка передаётся в момент вызова платёжной формы. Продавец обязан произвести расчёт суммы кешбэка ещё до факта оплаты пользователем.
8. API платёжной формы

8.1. Методы для вызова платёжной формы

Чтобы вызвать платёжное окно VK Pay, используйте один из этих методов.

  • В сервисе VK Apps (с помощью VK Connect):
    connect.send("VKWebAppOpenPayForm", {"app_id": YOUR_API_ID, "action": "pay-to-service", "params": {}});
  • На Вашем сайте (с помощью Open API):
    VK.App.open('vkpay', params);
  • В приложении сообщества (с помощью Javascript SDK):
    VK.callMethod('openExternalApp', 'vkpay', params);

Здесь params – JSON-объект, содержащий параметры платежа. Синтаксис params во всех этих случаях одинаков.

8.2. Синтаксис params

Пример значения:

{
	"amount": 1.5,
	"data": {
		"currency": "RUB",
		"merchant_data": "eyJvcmRlcl9pZCI6IjI1NTMxIiwidHMiOiIxNTM5MzI5NzcwIiwiYW1vdW50IjoxLjUsImN1cnJlbmN5IjoiUlVCIn0=",
		"merchant_sign": "63d5dce9d2c9d29198ba12ba3f8e270e6606a221",
                "order_id": "25531",
		"ts": "1539329770"	
        },
	"description": "Test Payment",
	"action": "pay-to-service",
	"merchant_id": 617001,
"version": 2, "sign": "6e3122aeb06771b9625ea8075f6b9d5"
}
Пример генерации параметров на JS можно найти здесь.

Описание полей

  • amount (integer|number|string) — сумма платежа. Минимальная сумма — 1?. Поле может быть передано как целое число, число с плавающей точкой (не более двух знаков после запятой, среди них незначащие нули недопустимы) или строка (не более двух знаков после запятой, незначащие нули допустимы). Поле amount участвует в формировании merchant_data для подписи продавца.
  • data (object) — служебные данные платежа. В этом JSON-объекте Вы передаёте обязательные поля для валидации оплаты платёжной системой, и можете передать любое количество произвольных полей, которые хотите видеть в серверном платёжном уведомлении. Синтаксис data.
  • description (string) — описание платежа для пользователя. Текст, который будет показан в платёжном окне.
  • action (string) — тип платежа. Всегда передавайте значение"pay-to-service" для платежей в пользу юридического лица.
  • merchant_id (integer) — идентификатор продавца. Это Ваш ID в платёжной системе, полученный после заключения договора вместе с приватным ключом продавца.
  • version (integer) — версия платёжной формы. Актуальная версия — 2.
  • sign (string) — подпись приложения ВКонтакте, вызвавшего платежное окно. См. описание поля sign ниже.

8.3. Синтаксис data

Пример значения

{
	"currency": "RUB",
	"merchant_data": "eyJvcmRlcl9pZCI6IjI1NTMxIiwidHMiOiIxNTM5MzI5NzcwIiwiYW1vdW50IjoxLjUsImN1cnJlbmN5IjoiUlVCIn0=",
	"merchant_sign": "63d5dce9d2c9d29198ba12ba3f8e270e6606a221",
        "order_id": "25531",
	"ts": "1539329770"
 }

data — это JSON-объект с набором полей для валидации платежа (например, номер заказа и подпись продавца), а также любыми произвольными полями, которые могут быть нужны продавцу для обработки заказа (например, данные о способе доставки). Названия полей внутри data должны быть отсортированы по алфавиту.

Содержимое data возвращается в серверном платёжном уведомлении на Ваш callback URL в поле merchant_params.

Описание полей

  • order_id (integer|string) — идентификатор заказа в контексте продавца. Для каждого платёжного окна должен быть уникальным. Повторный запрос с уже обработанным order_id будет проигнорирован. Поле order_id участвует в формировании merchant_data для подписи продавца.
  • ts (integer) — время формирования заказа в Unixtime. Поле ts участвует в формировании merchant_data для подписи продавца. Время ts не может быть раньше, чем за час до поднятия платёжного окна.
  • cashback (object) — данные о кэшбеке. Объект, который содержит поля:
    — pay_time (integer) — время зачисления кэшбека в Unixtime (время должно быть больше или равно времени платежа).
    — amount_percent (integer) — размер кешбэка в процентах от суммы (если не передан amount). Максимальное значение: 30.
    amount (number) — размер кешбэка в деньгах (если не передан amount_percent). Максимальный размер — 30% от суммы платежа.
    Поле cashback участвует в формировании merchant_data для подписи продавца. Если Вы не используете механику с кешбэками, передавать поле cashback не нужно.
  • currency (string) — валюта. Сейчас поддерживается только RUB. Поле currency участвует в формировании merchant_data для подписи продавца.

Защищенный ключ приложения и ключ продавца.

Важно! Следует различать защищенный ключ приложения (app secure key) и прватный ключ продавца (merchant private key).
Ключ продавца (merchant private key) вы получаете в одноразовой ссылке по почте или в личных сообщениях (только для тестовых продавцов).
Ключ приложения (app secure key) уникален для каждого отдельного приложения. Защищенный ключ Вы можете найти в разделе настроек приложения, по этой ссылке (подраздел «настройки», поле «Защищённый ключ:»).
Стрелкой обозначен app secure key.

8.4. Подпись продавца

Важно! Этот этап работы приложения нужно делать на стороне Service Backend. Иначе приватный ключ продавца может быть скомпрометирован.

Подпись продавца merchant_sign передаётся как поле внутри JSON-объекта data и гарантирует, что платёжное окно было сформировано с ведома продавца и он готов к получению платежа с указанной суммой и номером заказа, а также к начислению кешбэка в указанное время и в указанном размере.

merchant_sign — это sha1-хэш от конкатенации строк merchant_data и merchant_private_key (приватный ключ продавца — этот ключ Вы получаете после заключения договора с платёжной системой):

$merchant_sign = sha1($merchant_data.$merchant_private_key);

merchant_data — base64-строка от JSON-объекта, включающего в себя поля из описанных выше параметров платёжного окна, а именно amount, cashback, currency, order_id и ts. Других параметров в merchant_data быть не должно.

Формирование подписи продавца

  • Собираем JSON для merchant_data:
    {"order_id":"1554384451.84747666","cashback":{"pay_time":1554384571,"amount_percent":"30"},"ts":1554384451,"amount":"1","currency":"RUB"}
  • Берём от него base64: eyJvcmRlcl9pZCI6IjE1NTQzODQ0NTEuODQ3NDc2NjYiLCJjYXNoYmFjayI6eyJwYXlfdGltZSI6MTU1NDM4NDU3MSwiYW1vdW50X3BlcmNlbnQiOiIzMCJ9LCJ0cyI6MTU1NDM4NDQ1MSwiYW1vdW50IjoiMSIsImN1cnJlbmN5IjoiUlVCIn0=
  • Конкатенируем с приватным ключом продавца(merchant private key):
    eyJvcmRlcl9pZCI6IjE1NTQzODQ0NTEuODQ3NDc2NjYiLCJjYXNoYmFjayI6eyJwYXlfdGltZSI6MTU1NDM4NDU3MSwiYW1vdW50X3BlcmNlbnQiOiIzMCJ9LCJ0cyI6MTU1NDM4NDQ1MSwiYW1vdW50IjoiMSIsImN1cnJlbmN5IjoiUlVCIn0=627fdbfa24232a5b62f9c295baa93f7db9752873
  • Берём от конкатенации sha-1 хэш и получаем merchant_sign:
    86ebbd9e89f81e62db6e724707ace59b27fc4756

Поля merchant_data и merchant_sign передаются внутри объекта data среди параметров платёжного окна.

8.5. Подпись приложения

Важно! Этот этап работы приложения нужно делать на стороне Service Backend. Иначе секретный ключ приложения может быть скомпрометирован.

Подпись приложения sign передаётся как поле в JSON-объекте params и гарантирует, что параметры платёжной формы не были подменены на стороне клиента.

sign — это md5-хэш от конкатенации строки с параметрами платёжной формы и секретного ключа Вашего приложения ВКонтакте.

Формирование подписи приложения

  • Собираем строку параметров платёжной формы. Строка параметров представляет собой конкатенацию пар параметр = значение, при этом названия параметров отсортированы в алфавитном порядке (в том числе названия полей внутри JSON-объекта data(canonical json), как и в параметрах платёжного окна). Обратите внимание — параметр action нужно исключить из этой строки. Строковые значения передаются без кавычек. Если data содержит поле cashback, поля внутри этого объекета тоже должны быть отсортированы.
    amount=1.5data={"currency":"RUB","merchant_data":"eyJvcmRlcl9pZCI6IjI1NTMxIiwidHMiOiIxNTM5MzI5NzcwIiwiYW1vdW50IjoxLjUsImN1cnJlbmN5IjoiUlVCIn0=","merchant_sign":"63d5dce9d2c9d29198ba12ba3f8e270e6606a221","order_id":"25531","ts":"1539329770"}description=Test Paymentmerchant_id=617001version=2
  • Конкатенируем полученную строку с защищенным ключом Вашего приложения ВКонтакте (app secure key).
    amount=1.5data={"currency":"RUB","merchant_data":"eyJvcmRlcl9pZCI6IjI1NTMxIiwidHMiOiIxNTM5MzI5NzcwIiwiYW1vdW50IjoxLjUsImN1cnJlbmN5IjoiUlVCIn0=","merchant_sign":"63d5dce9d2c9d29198ba12ba3f8e270e6606a221","order_id":"25531","ts":"1539329770"}description=Test Paymentmerchant_id=617001version=2ug3CQvCkfRyI6svLVpC
  • Берём md5-хэш от этой конкатенации и получаем sign:
    e657ca99614a456f368f84f3d70aa567

Поле sign передаётся в JSON-объекте params среди других параметров платёжного окна.

8.6. Как отслеживать статус платежа?

После того, как пользователь закрыл платёжную форму, мы сообщим Вам о платеже со стороны сервера — отправив на Ваш callback URL специальное платёжное уведомление. И пришлём результат вызова платёжной формы со стороны клиента:

  • В сервисе VK Apps — событие VKWebAppOpenPayFormResult в VK Connect
  • На внешнем сайте — событиеapp.done в Open API.
  • В приложении сообщества — событие onExternalAppDone в Javascript SDK.

В любом из этих событий Вы получите данные платежа:

  • status (boolean) — статус платежа (true — платеж успешный, false — платеж неуспешный).
  • transaction_id (string) — идентификатор транзакции в платежной системе.
  • amount (string) — сумма платежа.
  • extra (string) — дополнительные данные продавца. Содержит данные поля data.

Если пользователь закрыл платёжную форму, не оплачивая покупку, мы пришлём отдельные события:

  • На внешнем сайте — app.closed в Open API.
  • В приложении сообщества — onExternalAppClosed в Javascript SDK.
Важно! Клиентские события не стоит рассматривать как гарантию успешной оплаты. Используйте их только для отображения экрана успеха в интерфейсе или другой некритической логики. Решение о предоставлении товара/услуги должно осуществляться только на основании серверсайдного платежного уведомления, доставленного на Ваш callback URL и подписанного ключом платёжной системы.

Кроме того, для приложений сообществ и VK Apps в Ваше сообщество ВКонтакте придёт сообщение от пользователя, оплатившего покупку, со сниппетом платежа:

С помощью Callback API ВКонтакте Вы можете подписаться на специальное событие vkpay_transaction, чтобы отслеживать такие сообщения от пользователей в Вашем сообществе.

8.7. Как работать с сообщениями?

ВКонтакте удобно общаться с Вашими клиентами через сообщения сообществ. Например, присылать подробные данные и статус заказа, уточнять информацию о доставке или реагировать на обратную связь. Узнать подробнее о том, как их использовать, Вы можете в документации.

Если Вы принимаете оплату через VK Pay внутри ВКонтакте (в сервисе VK Apps или в приложении сообщества), после платежа от имени пользователя в Ваше сообщество отправляется сообщение со сниппетом — данными платежа. Это даёт Вашему сообществу автоматическое разрешение на отправку ответных сообщений пользователю — Вам не нужно отдельно запрашивать у него права.

Важно! Отправка сниппета с платежом работает только после добавления Вашего приложения в каталог VK Apps или VK Pay. Нужно учитывать это при тестировании — если Вы общаетесь с пользователем в сообщениях сообщества, до размещения в каталоге Вам необходимо запрашивать права для отправки ему первого сообщения или написать в сообщения группы от имени этого пользователя.

8.8 Возможные ошибки

Если Вы допустили ошибку при вызове платёжного окна, в консоли браузера появится одна из этих ошибок:

  • Bad sign — неверно сформирована подпись приложения.
    Проверьте защищённый ключ приложения (app secure key). Игнорируется ли поле action?
    Следует проверить равенство строк для подписи, которые формируются на стороне vkpay и на стороне serverside Вашего приложения. Для тестовых мерчантов в консоли браузера в описании ошибки можно увидеть, как должна выглядеть строка для подписи приложения перед конкатенацией с защищенным ключом приложения. Важно! Следует учесть, что браузер экранирует двойные кавычки. Они не должны экранироваться при формировании подписи.
    Пример:
Верхняя стрелка указывает на место, с которого начинается строка для подписи параметров платежного окна. Нижняя — на код ошибки.
  • Параметры запроса и параметры партнёра отличаются — неверно сформирована подпись продавца.
  • Invalid parameter: ts — некорректное значение ts (больше часа назад или из далекого будущего).
  • Invalid parameter: cashback — некорректное значение кешбэка. Сумма кешбэка может составлять не более 30% от суммы платежа.
  • Invalid_parameter: amount
    Проверьте, не забыли ли Вы добавить параметр amount в merchant_data?
  • Не удалось найти получателя по заданным параметрам — неверно указан merchant_id.
9. 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) — полезная нагрузка. Синтаксис зависит от запроса.

9.1. Серверное платёжное уведомление

Уведомление отправляется по факту совершения платежа в пользу продавца на callback URL, который Вы указали при заключении договора с платёжной системой, или по факту списания средств с расчётного счёта продавца (например, при возврате). При необходимости Вы можете задать несколько адресов.

Уведомление будет отправлено и в случае возврата платежа с кэшбеком. Сначала с пользователя спишется сумма кэшбека. Эта сумма будет зачислена на счет мерчанта и ДМР отправит уведомление об отмене кэшбека. И после произойдет возврат средств пользователю по указанной транзакции. Пример уведомления о возврате кэшбека.

На уведомление нужно ответить — иначе мы продолжим присылать его снова и снова, предполагая, что продавец не обработал платёж. Если во время обработки уведомления произошла ошибка, нужно вернуть её в ответе — смотрите описание возможных ошибок в разделе 9.1.7.

Важно! Ответ на уведомление не может повлиять на статус транзакции
Важно! Рекомендуется организовать хранение уведомлений на стороне Service Backend. Это может потребоваться для проведения возвратов по неуспешным транзакциям или для аналитики.

9.1.1 Пример 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": "Внутренние переводы в рублях (кошелек-мерчант)"
}

9.1.2 Пример body для ответа на уведомление

{
	"transaction_id": "EEEAF322-10BD-11E8-93DF-CBAA984D4FFF",
	"notify_type": "TRANSACTION_STATUS"
}

9.1.3 Описание полей body для уведомления

  • transaction_id — идентификатор транзакции. Это поле (с тем же значением) необходимо передавать в ответе на уведомление.
  • notify_type — тип платёжного уведомления (всегда содержит "TRANSACTION_STATUS"). Это поле (с тем же значением) необходимо передавать в ответе на уведомление.
  • amount — сумма платежа. Сумма может быть отрицательной (например, при возврате средств покупателю).
  • status — статус транзакции (всегда содержит paid).
  • 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 — наименование платёжного метода.

9.1.4 Проверка подписи уведомления

Подпись платёжного уведомления (поле 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-----

9.1.5 Пример проверки подписи уведомления на PHP

$verify_res = openssl_verify($input['data'], base64_decode($input['signature']), $public_key);
if (!$verify_res) {  
  die 'Can\'t verify notification signature';
}

9.1.6 Подпись ответа на платёжное уведомление

Подпись ответа платёжного уведомления (поле signature) это строка в base64 — SHA1-хэш в HEX-представлении от конкатенации поля data и приватного ключа продавца.

Формирование подписи ответа на уведомление

  • Собираем data — JSON-объект с заголовком и телом запроса:
{
  "body": {
    "transaction_id": "49488FFC-D5D6-11E8-A1A6-C9407A00CD62",
    "notify_type": "TRANSACTION_STATUS"
  },
  "header": {
    "status": "OK",
    "ts": 1540197702,
    "client_id": "749514"
  }
}
  • Берём от него base64:
    eyJib2R5Ijp7InRyYW5zYWN0aW9uX2lkIjoiNDk0ODhGRkMtRDVENi0xMUU4LUExQTYtQzk0MDdBMDBDRDYyIiwibm90aWZ5X3R5cGUiOiJUUkFOU0FDVElPTl9TVEFUVVMifSwiaGVhZGVyIjp7InN0YXR1cyI6Ik9LIiwidHMiOjE1NDAxOTc3MDIsImNsaWVudF9pZCI6Ijc0OTUxNCJ9fQ==
  • Конкатенируем с приватным ключом продавца:
    eyJib2R5Ijp7InRyYW5zYWN0aW9uX2lkIjoiNDk0ODhGRkMtRDVENi0xMUU4LUExQTYtQzk0MDdBMDBDRDYyIiwibm90aWZ5X3R5cGUiOiJUUkFOU0FDVElPTl9TVEFUVVMifSwiaGVhZGVyIjp7InN0YXR1cyI6Ik9LIiwidHMiOjE1NDAxOTc3MDIsImNsaWVudF9pZCI6Ijc0OTUxNCJ9fQ==32224b236d226c8298ea62f976f5bc457afaca8f
  • Берём от полученной конкатенации SHA-1 хэш в HEX:
    10e9d4ce7984f5e9b767b3669cf1c811d6385741

Конечный результат:

{"version":"2-03","data":"eyJib2R5Ijp7InRyYW5zYWN0aW9uX2lkIjoiNDk0ODhGRkMtRDVENi0xMUU4LUExQTYtQzk0MDdBMDBDRDYyIiwibm90aWZ5X3R5cGUiOiJUUkFOU0FDVElPTl9TVEFUVVMifSwiaGVhZGVyIjp7InN0YXR1cyI6Ik9LIiwidHMiOjE1NDAxOTc3MDIsImNsaWVudF9pZCI6Ijc0OTUxNCJ9fQo=","signature":"7625c1d2030f2b45545c42baf2cce14d56e7fb55"}

9.1.7 Ошибки обработки уведомлений

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

{
	"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 уже обработано. Уведомления будут остановлены.

9.2. Возврат средств покупателю

Для полного или частичного возврата средств за покупку нужно отправить запрос к API продавца по следующему URL:

https://api-spare.money.mail.ru/money/2-04/transaction/refund

9.2.1 Пример curl запроса:

curl -v -X POST -d
'version=2-04&data=eyJoZWFkZXIiOnsidHMiOjE1NDQyOTU5NTgsImNsaWVudF9pZCI6IjU0Mzk0MSJ9LCJib2R5Ijp7InRyYW5zYWN0aW9uX2lkIjoiNjY4RjlGNUMtRkIwMC0xMUU4LUI1MEYtMDI1QTBFNEZEM0I4IiwiYW1vdW50IjoiMS4wMSIsImN1cnJlbmN5IjoiUlVCIiwicmVhc29uIjoiSnVzdCByZWZ1bmQifX0%3D&signature=fe476a9d66e96ab38fc65ee10a46d9ded546381c'
https://api-spare.money.mail.ru/money/2-04/transaction/refund

9.2.2 Пример body для запроса на возврат средств

{
	"transaction_id": "EEEAF322-10BD-11E8-93DF-CBAA984D4FFF",
	"amount": "1.50",
	"currency": "RUB",
	"reason": "Just refund"
}

9.2.3 Описание полей body для запроса на возврат средств

  • transaction_id (string) — идентификатор транзакции, по которой нужно сделать возврат.
  • amount (string) — сумма возврата. По умолчанию — полная сумма транзакции.
  • currency (string)— валюта платежа (всегда содержит RUB).
  • reason (string) — причина возврата.
  • merchant_param (string) — дополнительные данные продавца (для получения в платёжном уведомлении). Опциональное поле.
  • pay_method_info (string) — дополнительные данные платёжной системы. Опциональное поле.

9.2.4 Пример body для ответа на запрос возврата средств

{
	"transaction_id": "EEEAF322-10BD-11E8-93DF-CA984DA4FFBF",
	"action": "stop",
	"action_param": {
		"status": "success"
	}
}

9.2.5 Описание полей body для ответа на запрос возврата средств

  • transaction_id (string) — идентификатор транзакции возврата.
  • action (string) — действия для продолжения. Содержит одно из значений:
    — "wait" — необходимо запросить статус транзакции запросом transaction/status
    — "stop" — статус транзакции конечный и содержится в action_param.
  • action_param (object) — дополнительные данные. Для action = "stop" содержит поле status со статусом транзакции.

9.2.6 Подпись запроса на возврат средств

Подпись запроса формируется аналогично подписи ответа на платёжное уведомление, с единственным отличием — на третьем этапе, при конкатенации data и приватного ключа продавца, в начало строки необходимо добавить относительный URI запроса:

/money/2-04/transaction/refund

9.2.7 Возможные ошибки

В ответе на запрос может вернуться одна из следующих ошибок:

  • 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»

9.3 Статус транзакции

В случае, если запрос на возврат средств поле action имеет значение wait, вам следует «поллить» статус транзакции.

https://api-spare.money.mail.ru/money/2-04/transaction/status

9.3.1 Пример curl запроса:

curl -v -X POST -d
'version=2-04&data=eyJoZWFkZXIiOnsidHMiOjE1NTA4MzA3NjAsImNsaWVudF9pZCI6IjU0Mzk0MSJ9LCJib2R5Ijp7InRyYW5zYWN0aW9uX2lkIjoiNjY4RjlGNUMtRkIwMC0xMUU4LUI1MEYtMDI1QTBFNEZEM0I4In19Cg%3D%3D&signature=fe476a9d66e96ab38fc65ee10a46d9ded546381c'
https://api-spare.money.mail.ru/money/2-04/transaction/refund

9.3.2 Пример body для запроса

{
"transaction_id":"668F9F5C-FB00-11E8-B50F-025A0E4FD3B8"
}

9.3.3 Описание полей body для запроса статуса транзакции

  • transaction_id (string) — идентификатор транзакции возврата

9.3.4 Пример body для ответа на запрос статуса транзакции

{
'action_param': {
'status': 'success'
},
'transaction_id': '668F9F5C-FB00-11E8-B50F-025A0E4FD3B8',
'action': 'stop'
}

9.3.5 Описание полей body для ответа на запрос статуса транзакции

  • transaction_id — идентификатор транзакции
  • action — Идентификатор сценария дальнейших
    действий по оплате возможные значенияpy (stop|wait)
  • action_param — набор параметров для action (значение
    может быть пустым)
    status дополнительное уточнение статуса для
    action=stop (success|fail)

9.3.6 Подпись запроса на статус транзакции

Подпись запроса формируется аналогично подписи ответа на платёжное уведомление, с единственным отличием — на третьем этапе, при конкатенации data и приватного ключа продавца, в начало строки необходимо добавить относительный URI запроса:

/money/2-04/transaction/status

9.3.7 Возможные ошибки

  • ERR_NOT_FOUND — запрошенная транзакция не найдена
10. Тестирование работы с платежами

Для тестирования API платёжного окна и API продавца мы предоставим Вам данные тестового продавца — идентификатор продавца, приватный ключ продавца и публичный ключ платёжной системы. Для начала работы Вам нужно создать приложение ВКонтакте и сообщить нам адрес callback URL для отправки серверных платёжных уведомлений.

Напоминаем, что для корректной работы с логикой сообщений сообщества в период тестирования необходимо разрешать доступ к отправке сообщений пользователю. После размещения в каталоге это будет происходить автоматически.

К сожалению, мы не предоставляем кошельки для тестирования. Платежи в адрес тестовых продавцов автоматически возвращаются получателям в течение суток. Мы рекомендуем использовать для тестирования небольшие значения amount — например, 1 рубль.

Важно! У тестового продавца нет логотипа и названия в платёжной системе, поэтому Вы не увидите их в платёжном окне. После заключения договора при переходе на боевые данные, будут использованы указанные Вами логотип и название продавца.
Пользователь не может совершить платеж в пользу тестового продавца с 23.00 до 0.30. Это ограничение связано с возвратами тестовых платежей.
В течение этого времени можно поднять платежное окно, но произвести оплату нельзя.

Если Вы разрабатываете приложение сообщества с приёмом платежей через VK Pay, рекомендуем к чтению этот документ.

11. Платежи физическим лицам

Возможные значения action для платежа физическому лицу:

  • pay-to-group
  • pay-to-user

Документацию можно найти здесь.

Переводы физическим лицам доступны только идентифицированным пользователям. Это требование закона — мы не можем переводить деньги с анонимных кошельков.

По всем вопросам обращайтесь money@corp.mail.ru