Приём платежей посредством QR MIA
Прием платежей при помощи QR MIA имеет несколько существенных преимуществ:
- QR может быть оплачен приложением любого финансового института RM
- Оплата моментально попадает на счет мерчанта в режиме 24*7
Процесс оплаты состоит из нескольких этапов:
- Мерчант обращается к Bpay для формирования QR кода, сообщая всю необходимую информацию об
оплате - Bpay регистирурет в MIA QR код и отправляет мерчанту уникальный идентификатор этого кода
- Мерчант генерирует QR из полученного идентификатора и показывает его покупателю для оплаты
(это может быть предчек или любой другой носитель) - Покупатель сканирует своим приложением (любого финансового института) QR код, приложение
обращается в MIA и получает оттуда данные об оплате. Покупатель осуществляет оплату - Мерчант обращается в BPAY для подтверждения факта оплаты
Для начала работ по интеграции необходимо обратиться в Bpay и получить:
- Уникальный идентификатор мерчанта merchantId
- Секретный ключ secretKey для подписания сообщений
При этом некоторые работы можно произвести до получения этих данных (см. раздел Тестирование)
Типы QR кодов
- Статический QR-код (STAT)
- Динамический QR-код (DYNM)
- Гибридный QR-код (HYBR)
Типы сумм QR-кодов
- Свободная сумма (Free amount):
QR-код не содержит информации о сумме, и клиент вправе оплатить любую сумму - Фиксированная сумма (Fixed amount):
плательщик может оплатить ровно ту сумму, что указана к коде. - Контролируемая сумма (Controlled amount):
плательщик может имеет опредленную свободу в выборе суммы, однако ограниченную определенными
лимитами. Контролируемая сумма предоставляет возможность:- ограничить минимальную сумму оплаты
- или ограничить максимальную сумму оплаты
- или ограничить обе вышеназванные
- и, опционально, указать сумму по умолчанию
Модель QR кода
QR-код состоит из двух частей: заголовка (header) и расширений (extensions).
Заголовок можно считать «ведущей» частью QR-кода. У каждого QR-кода есть один и только один заголовок.
Расширения можно считать «ведомой» частью. QR-код может:
- не содержать ни одного расширения (HYBR). ОДнако в этом случае его невозможно
оплатить. - содержать дно и только одно расширение (DYNM)
- содержать одно или несколько расширений (STAT, HYBR)
Обратите внимание, что для данного QR-кода в один момент времени может быть активно только одно расширение. Каждое новое успешно созданное расширение делает предыдущее
недействительным.
Тип QR-кода(DYNM, STAT или HYBR) и тип суммы (Free, Fixed, Controlled) устанавливаеются на уровне заголовка
Реквизиты получателя, а также сумма и срок действия QR-кода (если применимо) устанавливаются на уровне расширения.
И заголовок, и расширение имеют свои собственные идентификаторы (UUID) и статусы.
Данные платежа, выполненного по QR-коду, связаны с соответствующим расширением. Расширение может:
- не содержать данных о платеже (QR-код никогда не был оплачен)
- быть связано с даннными только об одном платеже (например, для нормально оплаченного DYNM или HYBR)
- быть свзяано с данными о нескольких платежах (например, для STAT, который уже был оплачен несколько раз).
Свойства динамического QR-кода
- Предназначен для однократной оплаты, хотя он может быть показан Плательщику более одного раза.
- Может быть с фиксированной суммой или контролируемой суммой
- Имеет одно и только одно расширение.
- Имеет ограниченный срок действия, который задается как ttl (время жизни), после чего QR-код истекает и становится недействительным.
- Требует динамического носителя, такого как цифровой экран или предчек
Свойства статического QR-кода
- Предназначен для многократной оплаты.
- Может быть с свободной суммой, контролируемой суммой или даже фиксированной суммой.
- Имеет бесконечный срок службы, то есть у него нет срока истечения.
- Может быть размещен на статическом носителе, например, на наклейке.
Свойства гибридного QR-кода
- Так же, как и статический, гибридный QR-код не требует динамического носителя и может быть размещен на наклейке.
- При этом позволяет в любой момент времени привязать к заголовку новое расширение для оплаты
- Удобен в случаях, когда у мерчанта есть информационная система, но есть проблема с динамическим отображением QR-кода (нет мониторов, предчеков и т.п.)
Формат QR-кода
В QR кодируется ссылка следующего формата: https://mia-qr.bnm.md/1/m/BNM/BNM6bb781617b6a417fac071c4cf316b0c4,
где жирным шрифтом выделен уникальный идентификатор заголовка QR кода
Каждое сообщение мерчанта должно быть подписано. Для генерации подписи необходимо при помощи секретного ключа (secretKey), выданного Bpay при регистрации мерчанта, вычислить SHA256 hash от строки, сформированной из некоторых параметров параметров. В описании каждого метода API будут перечислены параметры, из которых будет формироваться подпись. Например, {dateTime}{merchantId}{amount}{description} — будет значить, что для формирования подписи надо контантенировать значения четырех парамертов: dateTime, merchantId, amount, description и к ним применить SHA256 хэширование секретным ключом.
Полученная подпись передается в заголовке X-HMAC-Signature соотвествующего http запроса.
Ниже представлен код на нескольких языках программирования для этой операции
PHP
function calculateHMAC($key, $message) {
$hash = hash_hmac('sha256', $message, $key, true);
return strtolower(base64_encode($hash));
}
JAVA
function calculateHMAC(key, message) {
var key = CryptoJS.enc.Utf8.parse(key);
var message = CryptoJS.enc.Utf8.parse(message);
var hash = CryptoJS.HmacSHA256(message, key);
var hashInBase64 = CryptoJS.enc.Base64.stringify(hash).toLowerCase();
return hashInBase64;
}
C#
public string CalculateHMAC(string key, string message) {
var keyByte = Encoding.UTF8.GetBytes(key);
using var hmacsha256 = new HMACSHA256(keyByte);
var hashmessage = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(message));
return Convert.ToBase64String(hashmessage).ToLower();
}
Production: https://qr-merchant.bpay.md
Test: https://qr-test.bpay.md
В нашем случае будет формироваться динамический QR-код с фиксированной суммой оплаты. Для этого необходимо отправить в Bpay данные по оплате GET запросом GET /api/Qr/CreateMerchantQr
Параметры запроса:
Параметр | Обязательность | Тип | Описание | Пример |
---|---|---|---|---|
datetime | да | text | Дата формирования QR в формате yyyy-MM-ddTHH:mm:ss | 2024-04-30T00:00:00 |
merchantId | да | text | Идентификатор мерчанта, выдаётся администратором платёжной системы | qrtest |
pointId | да | text | Идентификатор точки мерчанта (в случае, когда у несколько точек продаж). Назначается произвольно самим мерчантом (если точка всего одна, то используем «1»). |
1 |
amount | да | decimal | Сумма в леях | 10.00 |
description | да | text | Описание товара/услуги | test description |
getPaid | нет | bool | Признак того, надо ли оплатить QR сразу после создания. Используется только в тестовой среде! |
false |
Заголовки запроса:
Заголовок | Обязательность | Тип | Описание | Пример |
---|---|---|---|---|
X-TraceReference | да | text (max lenght 35) |
Уникальный идентификатор запроса. Предпочтительный вариант – uuid без дефисов |
e3a1b8d93a2b48e583c1c6b7a0d5e2f4 |
X-HMAC-Signature | да | text | HMAC SHA 256 подпись от строки {dateTime}{merchantId}{amount}{description} | gdhlgtx41wggqztdwsxwiaoo5qt4fihaf0rggpk99m0= |
Пример успешного ответа
{
"qrHeaderUUID": "f56212dd-7b6e-47a3-95f6-fb900aafc555",
"qrExtensionUUID": "7c39841f-09e8-46da-bd23-6833bc218b7e",
"qrAsText": "https://mia-qr.bnm.md/1/m/BNM/BNMf56212dd7b6e47a395f6fb900aafc555"
}
Для того чтобы сформировать гибридный QR надо сначала сгенерировать его заголовок, затем сгенерировать расширение, привязанное к этому заголовку
Генерация заголовка гибридного QR
POST /api/Qr/CreateMerchantHybridQrHeader
Параметры запроса:
Параметр | Обязательность | Тип | Описание | Пример |
---|---|---|---|---|
datetime | да | text | Дата формирования QR в формате yyyy-MM-ddTHH:mm:ss | 2024-04-30T00:00:00 |
merchantId | да | text | Идентификатор мерчанта, выдаётся администратором платёжной системы | qrtest |
pointId | да | text | Идентификатор точки мерчанта (в случае, когда у несколько точек продаж). Назначается произвольно самим мерчантом (если точка всего одна, то используем «1»). | 1 |
Заголовки запроса:
Заголовок | Обязательность | Тип | Описание | Пример |
---|---|---|---|---|
X-TraceReference | да | text (max lenght 35) |
Уникальный идентификатор запроса. Предпочтительный вариант – uuid без дефисов |
e3a1b8d93a2b48e583c1c6b7a0d5e2f4 |
X-HMAC-Signature | да | text | HMAC SHA 256 подпись от строки {dateTime}{merchantId}{pointId} | gdhlgtx41wggqztdwsxwiaof0rggpk99m0= |
Генерация расширения гибридного QR
POST /api/Qr/CreateMerchantHybridQrExtension
Параметры запроса:
Параметр | Обязательность | Тип | Описание | Пример |
---|---|---|---|---|
datetime | да | text | Дата формирования расширения в формате yyyy-MM-ddTHH:mm:ss | 2024-04-30T00:00:00 |
merchantId | да | text | Идентификатор мерчанта, выдаётся администратором платёжной системы | qrtest |
headerId | да | text | Идентификатор заголовка QR-кода, к которому будет привязано расширение. | 1 |
amount | да | decimal | Сумма в леях | 10.00 |
description | да | text | Описание товара/услуги | test description |
getPaid | да | bool | Признак того, надо ли оплатить QR сразу после создания. Используется только в тестовой среде! |
false |
orderId | да | text | Идентификатор заказа во внутренней системе учета мерчанта | 1 |
Заголовки запроса:
Заголовок | Обязательность | Тип | Описание | Пример |
---|---|---|---|---|
X-TraceReference | да | text (max lenght 35) |
Уникальный идентификатор запроса. Предпочтительный вариант – uuid без дефисов |
e3a1b8d93a2b48e583c1c6b7a0d5e2f4 |
X-HMAC-Signature | да | text | HMAC SHA 256 подпись от строки {dateTime}{merchantId}{headerId}{amount}{description} | gdhlgtx41wggqztdwsxwiaof0rggpk99m0= |
Отмена активного расширения гибридного QR
DELETE /api/Qr/CancelMerchantActiveHybridExtension
Параметры запроса:
Параметр | Обязательность | Тип | Описание | Пример |
---|---|---|---|---|
datetime | да | text | Дата формирования отмены в формате yyyy-MM-ddTHH:mm:ss | 2024-04-30T00:00:00 |
merchantId | да | text | Идентификатор мерчанта, выдаётся администратором платёжной системы | qrtest |
headerId | да | text | Идентификатор заголовка QR-кода, к которому принадлежит отменяемое расширение. | 1 |
Заголовки запроса:
Заголовок | Обязательность | Тип | Описание | Пример |
---|---|---|---|---|
X-TraceReference | да | text (max lenght 35) |
Уникальный идентификатор запроса. Предпочтительный вариант – uuid без дефисов |
e3a1b8d93a2b48e583c1c6b7a0d5e2f4 |
X-HMAC-Signature | да | text | HMAC SHA 256 подпись от строки {dateTime}{merchantId}{headerId} | gdhlgtx41wggqztdwsxwiaof0rggpk99m0= |
GET https://qr.bpay.md/api/Qr/GetQrStatus
Параметры запроса:
Параметр | Обязательность | Тип | Описание | Пример |
---|---|---|---|---|
uuid | да | string guid без дефисов |
Идентификатор QR кода | e9f42bd72a4949a5a61403a50c50f125 |
datetime | да | text | Дата формирования запроса на проверку статуса в формате yyyy-MM-ddTHH:mm:ss | 2024-04-30T00:00:00 |
merchantId | да | text | Идентификатор мерчанта, выдаётся администратором платёжной системы | qrtest |
hybridQR | нет | bool | Признак того, что проверяется оплата гибридного QR. Должен быть TRUE только в случае проверки оплаты гибридного QR | false |
Заголовки запроса:
Заголовок | Обязательность | Тип | Описание | Пример |
---|---|---|---|---|
X-TraceReference | да | text (max lenght 35) |
Уникальный идентификатор запроса. Предпочтительный вариант – uuid без дефисов |
e3a1b8d93a2b48e583c1c6b7a0d5e2f4 |
X-HMAC-Signature | да | text | HMAC SHA 256 подпись от строки {uuid}{dateTime}{merchantId}. Uuid должен быть в формате без дефисов | gdhlgtx41wggqztdwsxwiaof0rggpk99m0= |
Информация о ключах в ответе
Поле | Тип | Описание |
---|---|---|
isPaid | boolean | Оплачен ли QR. true — оплачен, false — не оплачен |
paymentDetails | object | Информация об оплате. Если платежа нет, то null |
receipt | string | Номер чека |
state | Integer | Статус платежа. 100 — завершен |
provAmount | decimal | Сумма оплаты |
Пример успешного ответа
{
"isPaid":true,
"paymentDetails":{
"receipt":"105468532550586",
"state":100,
"provAmount":10.0000
}
}
Пример неудачного ответа
{
"isPaid": false,
"paymentDetails": null
}
Проверка оплаты может осуществляться не только периодическим вызовом метода проверки оплаты, но и при помощи использования callback, т.е. когда в момент приема платежа в адрес мерчанта Bpay вызовет какой метод API, предоставленного мерчантом.
В случае необходимости использования callback необходимо обратиться с соотвествующим запросом на ecomm@bpay.md
DELETE CancelMerchantQr
Параметры запроса:
Параметр | Обязательность | Тип | Описание | Пример |
---|---|---|---|---|
datetime | да | text | Дата формирования запроса на проверку статуса в формате yyyy-MM-ddTHH:mm:ss | 2024-04-30T00:00:00 |
merchantId | да | text | Идентификатор мерчанта, выдаётся администратором платёжной системы | qrtest |
headerId | да | guid | Идентификатор заголовка QR кода | e9f42bd72a4949a5a61403a50c50f125 |
Заголовки запроса:
Заголовок | Обязательность | Тип | Описание | Пример |
---|---|---|---|---|
X-TraceReference | да | text (max lenght 35) |
Уникальный идентификатор запроса. Предпочтительный вариант – uuid без дефисов |
e3a1b8d93a2b48e583c1c6b7a0d5e2f4 |
X-HMAC-Signature | да | text | HMAC SHA 256 подпись от строки {dateTime}{merchantId}{headerId} | gdhlgtx22wggqztdwsxwiaof0rggpk99m0= |
POST ReversePayment
Параметры запроса:
Параметр | Обязательность | Тип | Описание | Пример |
---|---|---|---|---|
datetime | да | text | Дата формирования запроса на проверку статуса в формате yyyy-MM-ddTHH:mm:ss | 2024-04-30T00:00:00 |
merchantId | да | text | Идентификатор мерчанта, выдаётся администратором платёжной системы | qrtest |
receiptNr | да | text | Номер чека, полученный в ходе проверки статуса платежа | 105468532550586 |
amount | да | decimal | Сумма отмены | 10.15 |
description | да | text | Основание для возврата | Требование плательщика |
Заголовки запроса:
Заголовок | Обязательность | Тип | Описание | Пример |
---|---|---|---|---|
X-TraceReference | да | text (max lenght 35) |
Уникальный идентификатор запроса. Предпочтительный вариант – uuid без дефисов |
e3a1b8d93a2b48e583c1c6b7a0d5e2f4 |
X-HMAC-Signature | да | text | HMAC SHA 256 подпись от строки {dateTime}{merchantId}{receiptNr}{amount}{description} | gdhlgtx22wggqztdwsxwiaof0rggpk99m0= |
Отключение проверки HMAC подписи
- Для метода api/Qr/CreateMerchantQr в тестовых целях можно отключить проверку HMAC при формировании QR.
- Если в качестве параметров указать дефолтные значения datetime=»2024-04-30T00:00:00″,
merchantId=»qrtest», amount=10, description=»test description», то HMAC проверяться не будет
Оплата QR
- Для метода api/Qr/CreateMerchantQr вместе с генерацией QR можно в тестовых целях осуществить его оплату
- Для этого при вызове /api/Qr/CreateMerchantQr необходимо для параметра
getPaid указать значение true
Коллекция для postman (открыть в Postman):
- Содержит запросы для тестирования как генерации QR, его отмены, так и для проверки оплаты
- В параметре окружения MerchantId меняем идентификатора мерчанта на полученный при регистрации мерчанта
- В переменной окружения SecretKey надо указать полученный при регистрации мерчанта секретный ключ (остальные переменные коллекции менять не надо)
- Параметры запросов меняются по желанию (для всех обычно указано его описание и важные аспекты использования)
- При отправке запроса параметр dateTime будет сгенерирован автоматически, так же автоматически будут сгенерированы заголовки X-TraceReference и X-HMAC-Signature. Реальные их значения, которые будут отправлен на сервер, вы сможете найти в console или вывести в PreRequest script при помощи console.log()
Дополнительные инструменты:
- Генерация HMAC в виде hex https://emn178.github.io/online-tools/sha256.html
- Конвертация hex в base64 https://base64.guru/converter/encode/hex