Acceptarea plăților prin QR MIA
Acceptarea plăților prin QR MIA are câteva avantaje semnificative:
- QR poate fi plătit prin aplicația oricărei instituții financiare din RM
- Plata este creditată imediat în contul comerciantului în regim 24*7
Procesul de plată constă din mai multe etape:
- Comerciantul contactează Bpay pentru a genera un cod QR, furnizând toate informațiile necesare despre plată
- Bpay înregistrează codul QR în MIA și trimite comerciantului un identificator unic al acestui cod
- Comerciantul generează QR din identificatorul primit și îl arată cumpărătorului pentru plată (acesta poate fi un pre-check sau orice alt tip de suport)
- Cumpărătorul scanează codul QR cu aplicația sa (a oricărei instituții financiare), aplicația contactează MIA și primește de acolo datele despre plată. Cumpărătorul efectuează plata
- Comerciantul contactează BPAY pentru a confirma faptul plății
Pentru a începe integrarea, este necesar să contactați Bpay și să obțineți:
- Identificatorul unic al comerciantului merchantId
- Cheia secretă secretKey pentru semnarea mesajelor
Între timp, unele lucrări pot fi efectuate înainte de a primi aceste date (vezi secțiunea Testare)
Tipuri de coduri QR
- Cod QR static (STAT)
- Cod QR dinamic (DYNM)
- Cod QR hibrid (HYBR)
Tipuri de sume QR
- Suma liberă (Free amount):
Codul QR nu conține informații despre sumă, iar clientul poate plăti orice sumă - Suma fixă (Fixed amount):
Plătitorul poate plăti exact suma specificată în cod. - Suma controlată (Controlled amount):
Plătitorul poate avea o anumită libertate în alegerea sumei, dar limitată de anumite limite. Suma controlată oferă posibilitatea:- Să limiteze suma minimă de plată
- Să limiteze suma maximă de plată
- Să limiteze ambele sume menționate anterior
- Să specifice opțional o sumă implicită
Modelul codului QR
Codul QR constă din două părți: antetul (header) și extensiile (extensions).
Antetul poate fi considerat „partea principală” a codului QR. Fiecare cod QR are unul și doar un antet.
Extensiile pot fi considerate „partea secundară”. Codul QR poate:
- Să nu conțină nicio extensie (HYBR). În acest caz, nu poate fi plătit.
- Să conțină una și doar una extensie (DYNM)
- Să conțină una sau mai multe extensii (STAT, HYBR)
Rețineți că pentru un anumit cod QR poate fi activă o singură extensie per moment. Fiecare extensie nou creată cu succes face ca extensia anterioară să devină invalidă.
Tipul codului QR (DYNM, STAT sau HYBR) și tipul sumei (Free, Fixed, Controlled) sunt stabilite la nivelul antetului.
Detaliile beneficiarului, precum și suma și durata de valabilitate a codului QR (dacă este cazul) sunt stabilite la nivelul extensiei.
Atât antetul, cât și extensia au propriile identificatoare (UUID) și statusuri.
Datele de plată realizate prin codul QR sunt legate de extensia corespunzătoare. Extensia poate:
- Să nu conțină date despre plată (codul QR nu a fost plătit niciodată)
- Să fie asociată cu datele doar unei singure plăți (de exemplu, pentru DYNM sau HYBR plătite corect)
- Să fie asociată cu datele mai multor plăți (de exemplu, pentru STAT care a fost plătit de mai multe ori).
Caracteristicile codului QR dinamic
- Este destinat pentru o singură plată, deși poate fi afișat plătitorului de mai multe ori.
- Poate avea suma fixă sau suma controlată
- Are una și doar una extensie.
- Are o durată de valabilitate limitată, stabilită ca ttl (timp de viață), după care codul QR expiră și devine invalid.
- Necesită un suport dinamic, cum ar fi un ecran digital sau un pre-check
Caracteristicile codului QR static
- Este destinat pentru plăți multiple.
- Poate avea suma liberă, suma controlată sau chiar suma fixă.
- Are o durată de viață infinită, adică nu are termen de expirare.
- Poate fi plasat pe un suport static, cum ar fi o etichetă.
Caracteristicile codului QR hibrid
- La fel ca QR-ul static, QR-ul hibrid nu necesită un suport dinamic și poate fi plasat pe o etichetă.
- Permite asocierea unei noi extensii la antet pentru plată în orice moment.
- Este convenabil în cazurile în care comerciantul are un sistem informatic, dar are probleme cu afișarea dinamică a codului QR (nu există monitoare, pre-check-uri etc.).
Formatul codului QR
În QR este codificat un link de formatul următor: https://mia-qr.bnm.md/1/m/BNM/BNM6bb781617b6a417fac071c4cf316b0c4,
unde în bold este evidențiat identificatorul unic al antetului codului QR
Fiecare mesaj al comerciantului trebuie să fie semnat. Pentru a genera semnătura, este necesar să utilizați cheia secretă (secretKey) emisă de Bpay la înregistrarea comerciantului, pentru a calcula hash-ul SHA256 al unui șir format din anumiți parametri. În descrierea fiecărei metode API vor fi enumerați parametrii din care se va forma semnătura. De exemplu, {dateTime}{merchantId}{amount}{description} va însemna că pentru a forma semnătura, trebuie să concatenați valorile celor patru parametri: dateTime, merchantId, amount, description și să aplicați hashing-ul SHA256 cu cheia secretă.
Semnătura obținută este transmisă în antetul X-HMAC-Signature al cererii http corespunzătoare.
Mai jos este prezentat codul în mai multe limbi de programare pentru această operațiune
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();
}
Producție: https://qr-merchant.bpay.md
Test: https://qr-test.bpay.md
În cazul nostru, va fi generat un cod QR dinamic cu o sumă fixă de plată. Pentru aceasta, trebuie să trimiteți datele de plată către Bpay printr-o cerere GET GET /api/Qr/CreateMerchantQr
Parametrii cererii:
Parametru | Obligatoriu | Tip | Descriere | Exemplu |
---|---|---|---|---|
datetime | da | text | Data generării QR în formatul yyyy-MM-ddTHH:mm:ss | 2024-04-30T00:00:00 |
merchantId | da | text | Identificatorul comerciantului, emis de administratorul sistemului de plată | qrtest |
pointId | da | text | Identificatorul punctului de vânzare al comerciantului (în cazul în care există mai multe puncte de vânzare). Atribuit în mod arbitrar de către comerciant (dacă există un singur punct de vânzare, folosim „1”). |
1 |
amount | da | decimal | Suma în lei | 10.00 |
description | da | text | Descrierea produsului/serviciului | test description |
getPaid | nu | bool | Indicatorul dacă QR-ul trebuie plătit imediat după crearea acestuia. Utilizat doar în mediul de testare! |
false |
Anteturi ale cererii:
Antet | Obligatoriu | Tip | Descriere | Exemplu |
---|---|---|---|---|
X-TraceReference | da | text (lungime maximă 35) |
Identificator unic al cererii. Varianta preferată – uuid fără cratime |
e3a1b8d93a2b48e583c1c6b7a0d5e2f4 |
X-HMAC-Signature | da | text | HMAC SHA 256 semnătură a șirului {dateTime}{merchantId}{amount}{description} | gdhlgtx41wggqztdwsxwiaoo5qt4fihaf0rggpk99m0= |
Exemplu de răspuns de succes
{
"qrHeaderUUID": "f56212dd-7b6e-47a3-95f6-fb900aafc555",
"qrExtensionUUID": "7c39841f-09e8-46da-bd23-6833bc218b7e",
"qrAsText": "https://mia-qr.bnm.md/1/m/BNM/BNMf56212dd7b6e47a395f6fb900aafc555"
}
Pentru a genera un QR hibrid, trebuie mai întâi să generați antetul acestuia, apoi să generați extensia asociată cu acest antet
Generarea antetului QR hibrid
POST /api/Qr/CreateMerchantHybridQrHeader
Parametrii cererii:
Parametru | Obligatoriu | Tip | Descriere | Exemplu |
---|---|---|---|---|
datetime | da | text | Data generării QR în formatul yyyy-MM-ddTHH:mm:ss | 2024-04-30T00:00:00 |
merchantId | da | text | Identificatorul comerciantului, emis de administratorul sistemului de plată | qrtest |
pointId | da | text | Identificatorul punctului de vânzare al comerciantului (în cazul în care există mai multe puncte de vânzare). Atribuit în mod arbitrar de către comerciant (dacă există un singur punct de vânzare, folosim „1”). | 1 |
Anteturi ale cererii:
Antet | Obligatoriu | Tip | Descriere | Exemplu |
---|---|---|---|---|
X-TraceReference | da | text (lungime maximă 35) |
Identificator unic al cererii. Varianta preferată – uuid fără cratime |
e3a1b8d93a2b48e583c1c6b7a0d5e2f4 |
X-HMAC-Signature | da | text | HMAC SHA 256 semnătură a șirului {dateTime}{merchantId}{pointId} | gdhlgtx41wggqztdwsxwiaof0rggpk99m0= |
Generarea extensiei QR hibrid
POST /api/Qr/CreateMerchantHybridQrExtension
Parametrii cererii:
Parametru | Obligatoriu | Tip | Descriere | Exemplu |
---|---|---|---|---|
datetime | da | text | Data generării extensiei în formatul yyyy-MM-ddTHH:mm:ss | 2024-04-30T00:00:00 |
merchantId | da | text | Identificatorul comerciantului, emis de administratorul sistemului de plată | qrtest |
headerId | da | text | Identificatorul antetului QR la care va fi asociată extensia. | 1 |
amount | da | decimal | Suma în lei | 10.00 |
description | da | text | Descrierea produsului/serviciului | descriere de test |
getPaid | da | bool | Indicatorul dacă QR-ul trebuie plătit imediat după crearea acestuia. Utilizat doar în mediul de testare! |
false |
orderId | da | text | Identificatorul comenzii în sistemul intern de contabilitate al comerciantului | 1 |
Anteturi ale cererii:
Antet | Obligatoriu | Tip | Descriere | Exemplu |
---|---|---|---|---|
X-TraceReference | da | text (lungime maximă 35) |
Identificator unic al cererii. Varianta preferată – uuid fără cratime |
e3a1b8d93a2b48e583c1c6b7a0d5e2f4 |
X-HMAC-Signature | da | text | HMAC SHA 256 semnătură a șirului {dateTime}{merchantId}{headerId}{amount}{description} | gdhlgtx41wggqztdwsxwiaof0rggpk99m0= |
Anularea extensiei active a QR hibrid
DELETE /api/Qr/CancelMerchantActiveHybridExtension
Parametrii cererii:
Parametru | Obligatoriu | Tip | Descriere | Exemplu |
---|---|---|---|---|
datetime | da | text | Data generării anulării în formatul yyyy-MM-ddTHH:mm:ss | 2024-04-30T00:00:00 |
merchantId | da | text | Identificatorul comerciantului, emis de administratorul sistemului de plată | qrtest |
headerId | da | text | Identificatorul antetului QR la care aparține extensia anulată. | 1 |
Anteturi ale cererii:
Antet | Obligatoriu | Tip | Descriere | Exemplu |
---|---|---|---|---|
X-TraceReference | da | text (lungime maximă 35) |
Identificator unic al cererii. Varianta preferată – uuid fără cratime |
e3a1b8d93a2b48e583c1c6b7a0d5e2f4 |
X-HMAC-Signature | da | text | HMAC SHA 256 semnătură a șirului {dateTime}{merchantId}{headerId} | gdhlgtx41wggqztdwsxwiaof0rggpk99m0= |
GET https://qr.bpay.md/api/Qr/GetQrStatus
Parametrii cererii:
Parametru | Obligatoriu | Tip | Descriere | Exemplu |
---|---|---|---|---|
uuid | da | string guid fără cratime |
Identificatorul codului QR | e9f42bd72a4949a5a61403a50c50f125 |
datetime | da | text | Data generării cererii de verificare a statutului în formatul yyyy-MM-ddTHH:mm:ss | 2024-04-30T00:00:00 |
merchantId | da | text | Identificatorul comerciantului, emis de administratorul sistemului de plată | qrtest |
hybridQR | nu | bool | Indică faptul că se verifică plata unui QR hibrid. Ar trebui să fie TRUE doar în cazul verificării plății unui QR hibrid. | false |
Anteturi ale cererii:
Antet | Obligatoriu | Tip | Descriere | Exemplu |
---|---|---|---|---|
X-TraceReference | da | text (lungime maximă 35) |
Identificator unic al cererii. Varianta preferată – uuid fără cratime |
e3a1b8d93a2b48e583c1c6b7a0d5e2f4 |
X-HMAC-Signature | da | text | HMAC SHA 256 semnătură a șirului {uuid}{dateTime}{merchantId}. Uuid trebuie să fie în format fără cratime | gdhlgtx41wggqztdwsxwiaof0rggpk99m0= |
Informații despre chei în răspuns
Câmp | Tip | Descriere |
---|---|---|
isPaid | boolean | QR plătit sau nu. true – plătit, false – neplătit |
paymentDetails | object | Informații despre plată. Dacă nu există plată, atunci null |
receipt | string | Numărul chitanței |
state | Integer | Statutul plății. 100 – finalizat |
provAmount | decimal | Suma plății |
Exemplu de răspuns de succes
{
"isPaid": true,
"paymentDetails": {
"receipt": "105468532550586",
"state": 100,
"provAmount": 10.0000
}
}
Exemplu de răspuns nereușit
{
"isPaid": false,
"paymentDetails": null
}
Verificarea plății poate fi realizată nu doar prin apeluri periodice ale metodei de verificare a plății, ci și prin utilizarea callback, adică în momentul acceptării plății în adresa comerciantului Bpay va apela o metodă API furnizată de comerciant.
În cazul în care este necesară utilizarea callback, trebuie să trimiteți o cerere corespunzătoare la ecomm@bpay.md
DELETE CancelMerchantQr
Parametrii cererii:
Parametru | Obligatoriu | Tip | Descriere | Exemplu |
---|---|---|---|---|
datetime | da | text | Data generării cererii de anulare în formatul yyyy-MM-ddTHH:mm:ss | 2024-04-30T00:00:00 |
merchantId | da | text | Identificatorul comerciantului, emis de administratorul sistemului de plată | qrtest |
headerId | da | guid | Identificatorul antetului codului QR | e9f42bd72a4949a5a61403a50c50f125 |
Anteturi ale cererii:
Antet | Obligatoriu | Tip | Descriere | Exemplu |
---|---|---|---|---|
X-TraceReference | da | text (lungime maximă 35) |
Identificator unic al cererii. Varianta preferată – uuid fără cratime |
e3a1b8d93a2b48e583c1c6b7a0d5e2f4 |
X-HMAC-Signature | da | text | HMAC SHA 256 semnătură a șirului {dateTime}{merchantId}{headerId} | gdhlgtx22wggqztdwsxwiaof0rggpk99m0= |
POST ReversePayment
Parametrii cererii:
Parametru | Obligatoriu | Tip | Descriere | Exemplu |
---|---|---|---|---|
datetime | da | text | Data generării cererii de verificare a statutului în formatul yyyy-MM-ddTHH:mm:ss | 2024-04-30T00:00:00 |
merchantId | da | text | Identificatorul comerciantului, emis de administratorul sistemului de plată | qrtest |
receiptNr | da | text | Numărul chitanței obținute în timpul verificării statutului plății | 105468532550586 |
amount | da | decimal | Suma de returnare | 10.15 |
description | da | text | Motivul returnării | Cererea plătitorului |
Anteturi ale cererii:
Antet | Obligatoriu | Tip | Descriere | Exemplu |
---|---|---|---|---|
X-TraceReference | da | text (lungime maximă 35) |
Identificator unic al cererii. Varianta preferată – uuid fără cratime |
e3a1b8d93a2b48e583c1c6b7a0d5e2f4 |
X-HMAC-Signature | da | text | HMAC SHA 256 semnătură a șirului {dateTime}{merchantId}{receiptNr}{amount}{description} | gdhlgtx22wggqztdwsxwiaof0rggpk99m0= |
Dezactivarea verificării semnăturii HMAC
- În scopuri de testare, puteți dezactiva verificarea HMAC la generarea QR
- Dacă parametrii sunt setați la valorile implicite datetime=”2024-04-30T00:00:00″, merchantId=”qrtest”, amount=10, description=”test description”, HMAC nu va fi verificat
Plata QR
- Împreună cu generarea QR, puteți efectua plata acestuia în scopuri de testare
- Pentru aceasta, la apelarea /api/Qr/CreateMerchantQr, trebuie să setați parametrul getPaid la valoarea true
Colecție pentru Postman (deschide în Postman):
- Conține cereri pentru testarea: generării QR, anularea acestuia și verificarea plății
- În parametrul de mediu MerchantId, schimbați identificatorul comerciantului cu cel primit la înregistrarea comerciantului
- În variabila de mediu SecretKey, trebuie să introduceți cheia secretă primită la înregistrarea comerciantului (nu este necesar să schimbați alte variabile ale colecției)
- Parametrii cererilor se pot schimba după dorință (pentru toate este de obicei specificată descrierea și aspectele importante ale utilizării)
- La trimiterea cererii, parametrul dateTime va fi generat automat, la fel vor fi generate automat anteturile X-TraceReference și X-HMAC-Signature. Valorile reale ale acestora, care vor fi trimise către server, le puteți găsi în consolă sau le puteți afișa în scriptul PreRequest folosind console.log()
Instrumente suplimentare:
- Generarea HMAC în format hex https://emn178.github.io/online-tools/sha256.html
- Conversia hex în base64 https://base64.guru/converter/encode/hex