МойСклад QRPay API
В приложении Касса Мойсклад можно оплатить покупки по QR-коду. Оплата по QR-коду может быть через эквайринговый pos-терминал, а может быть с помощью решения в Каталоге решений МоегоСклада.
Под QR оплатой понимается любой способ оплаты на кассе, для оплаты которого покупателю необходимо отсканировать QR-код и оплатить по ссылке. Например, СБП, сервисы оплаты по QR (Плати QR, Мульти QR) и любые другие.
Мы предоставляем публичный API QRPay, которое позволяет реализовать второй вариант оплаты по QR. Через API веб-приложение МойСклад сможет запрашивать данные для оплаты у решения. Решение будет обращаться в платёжный сервис через его API. Одновременно может быть подключено только одно решение оплаты по QR.
Путь пользователя
- Администратор аккаунта устанавливает решение для оплаты по QR в Каталоге решений.
- Включает на Точке продаж оплату по QR.
- Настраивает решение (Если необходимо, указывает логины, пароли, токены и другие идентификаторы для взаимодействия с платежным сервисом).
- Продавец на кассе вызывает данный способ оплаты.
- Касса посылает запрос на генерацию QR-кода по API в МойСклад.
- МойСклад передает запрос в установленное Решение.
- Решение передает запрос в платежный сервис.
- Далее в обратном порядке QR-код передает на кассу.
- Клиент сканирует QR-код, оплачивает.
- Касса получает статус, что оплата прошла, далее фискализирует чек.
Как поддержать интеграцию
Подключение оплаты по QR-коду в сервисе МойСклад происходит через решение, которое необходимо разработать и опубликовать в нашем каталоге решений. Для этого вам нужно:
- Получить доступ к Личному кабинету разработчика.
- Создать черновик серверного решения с указанием
блока
<qrPayApi/>в дескрипторе. - Используя эту документацию имплементировать QRPay API на сервере.
- Протестировать и отправить решение на публикацию.
Как заполнить дескриптор
В дескрипторе решения нужно указать блок
<qrPayApi/>, который представляет собой массив элементов <paymentProvider/>.
Важно: В дескрипторе можно указать больше одного элемента paymentProvider, но в данный момент запросы будут
осуществляться по адресу указанному в первом элементе.
Атрибуты paymentProvider
- name
string- Название способа оплатыНеобходимое - qrType,
enum[string]- Тип QR-кодаНеобходимое - endpointBase
string- Базовый URL на стороне разработчика с имплементацией QRPay APIНеобходимое
Возможные значения qrType
| Значение | Поддерживается | Описание |
|---|---|---|
MERCHANT_GENERATED_DYNAMIC |
Да | QR-код создаётся на каждую операцию |
MERCHANT_GENERATED_STATIC |
Нет | Статический QR-код |
CUSTOMER_GENERATED |
Нет | QR-код, который показывает покупатель, продавец его сканирует |
Пример заполнения дескриптора
<ServerApplication xmlns="https://apps-api.moysklad.ru/xml/ns/appstore/app/v2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://apps-api.moysklad.ru/xml/ns/appstore/app/v2
https://apps-api.moysklad.ru/xml/ns/appstore/app/v2/application-v2.xsd">
<vendorApi>
<endpointBase>https://example.com/dummy-app</endpointBase>
</vendorApi>
<qrPayApi>
<paymentProvider>
<name>Some vendor's first payment provider</name>
<qrType>MERCHANT_GENERATED_DYNAMIC</qrType>
<endpointBase>https://some-vendor.ru/api/1/root</endpointBase>
</paymentProvider>
<paymentProvider>
<name>Some vendor's second payment provider</name>
<qrType>MERCHANT_GENERATED_DYNAMIC</qrType>
<endpointBase>https://some-vendor.ru/api/2/root</endpointBase>
</paymentProvider>
</qrPayApi>
<access>
<resource>https://online.moysklad.ru/api/remap/1.2</resource>
<scope>admin</scope>
</access>
</ServerApplication>
Описание QRPay API
Обработка ошибок
Если возникла ошибка при обработке запроса, то она должна приходить с HTTP-кодом из диапазона 4xx.
Структура ошибок
Ошибки представляют собой массив errors, содержащий объекты error, каждый из которых описывает отдельную ошибку.
Структура объекта error
- error
string- Заголовок ошибкиНеобходимое - code
number- Код ошибкиНеобходимое - errorMessage
string- Сообщение, прилагаемое к ошибке
Response
412 (application/json)
{
"errors": [
{
"error": "Не указан обязательный параметр",
"code": 999,
"errorMessage": "Не указана сумма возврата"
}
]
}
Аутентификация запросов
Каждый запрос к API подписывается одноразовым токеном, сформированным с использованием RSA-ключа.
- Токен - это JWT, содержащий:
- Заголовок
kid- уникальный идентификатор ключа, использованного для подписи токена id- уникальный идентификатор токенаexp- срок действия токена в форматеUNIX timestampiat- время формирования токена в форматеUNIX timestampiss- идентификатор сервиса выпустившего токен. Должно содержать значениеhttps://moysklad.ru
- Заголовок
- Подпись выполняется приватным ключом отправителя по алгоритму
RS256. - Публичный ключ для проверки подписи необходимо получать из JWKS по следующему URL: https://pay-qr.moysklad.ru/.well-known/jwks.json
- При обработке запроса сервер должен:
- Получить актуальный набор ключей из JWKS.
- Найти в ответе ключ соответствующий полю
kidв заголовке токена. - Проверить корректность подписи токена.
- Убедиться, что
idтокена ранее не использовался. - Проверить, что
expне истёк на момент валидации.
Важно: Токен одноразовый и становится недействительным сразу после успешной проверки.
Создать QR-код
Запрос на создание нового QR-кода.
Атрибуты запроса
- amount
number- Сумма к оплате за покупку, в копейкахНеобходимое - operationId
string- Идентификатор операции, формируемый клиентом в формате UUIDНеобходимое - accountId
string- Идентификатор аккаунта в МС в формате UUIDНеобходимое - retailStoreId
string- Идентификатор точки продаж в МС в формате UUIDНеобходимое
Атрибуты ответа
- operationId
string- Идентификатор операции, формируемый клиентом в формате UUIDНеобходимое - data
string- Данные, которые будут отображены в виде QR-кода на кассеНеобходимое
POST/payment/qrRequest
Headers
Content-Type:application/json
Authorization:Bearer <токен>
Body
{
"amount": 100,
"operationId": "3ce94dac-5584-464a-9a03-194b799341bc",
"accountId": "3066cc26-67ca-11f0-0a83-147100000002",
"retailStoreId": "3238f1cc-67ca-11f0-0a80-0383000000be"
}
Response
200 (application/json)Body
{
"operationId": "f1c50d66-55b9-4448-a617-e030ff3e9bd1",
"data": "https://qr.nspk.ru/BD1000140UGULHTI8TFB015KNF1ORSCR?type=02&bank=100000000004&sum=20000&cur=RUB&crc=C736"
}
Получить статус оплаты
Запрос статуса оплаты.
Атрибуты запроса
- amount
number- Сумма к оплате за покупку, в копейкахНеобходимое - operationId
string- Идентификатор операции, формируемый клиентом в формате UUIDНеобходимое - accountId
string- Идентификатор аккаунта в МС в формате UUIDНеобходимое - retailStoreId
string- Идентификатор точки продаж в МС в формате UUIDНеобходимое
Атрибуты ответа
- operationId
string- Идентификатор операции, формируемый клиентом в формате UUIDНеобходимое - status
enum[string]- Статус транзакцииНеобходимое
Возможные значения status
| Значение | Описание |
|---|---|
IN_PROGRESS |
Оплата ещё не завершена |
DONE |
Оплата произведена успешно |
REJECTED |
Оплата отклонена банком (например, недостаточно средств) |
POST/payment/stateRequest
Headers
Content-Type:application/json
Authorization:Bearer <токен>
Body
{
"amount": 100,
"operationId": "3ce94dac-5584-464a-9a03-194b799341bc",
"accountId": "3066cc26-67ca-11f0-0a83-147100000002",
"retailStoreId": "3238f1cc-67ca-11f0-0a80-0383000000be"
}
Response
200 (application/json)Body
{
"operationId": "f1c50d66-55b9-4448-a617-e030ff3e9bd1",
"status": "DONE"
}
Отмена/возврат оплаты
Запрос отмены оплаты.
Атрибуты запроса
- amount
number- Сумма к возврату, в копейкахНеобходимое - operationId
string- Идентификатор операции, формируемый клиентом в формате UUIDНеобходимое - accountId
string- Идентификатор аккаунта в МС в формате UUIDНеобходимое - retailStoreId
string- Идентификатор точки продаж в МС в формате UUIDНеобходимое
POST/payment/cancelRequest
Headers
Content-Type:application/json
Authorization:Bearer <токен>
Body
{
"amount": 100,
"operationId": "3ce94dac-5584-464a-9a03-194b799341bc",
"accountId": "3066cc26-67ca-11f0-0a83-147100000002",
"retailStoreId": "3238f1cc-67ca-11f0-0a80-0383000000be"
}
Response
200 (application/json)