МойСклад 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 timestamp
iat
- время формирования токена в форматеUNIX timestamp
iss
- идентификатор сервиса выпустившего токен. Должно содержать значение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)