5.1 KiB
PayMV QR Format
Documents the decimal TLV QR format used by the PayMV/Favara payment network in the Maldives — both generation (to receive payment) and parsing (to initiate a transfer by scanning).
Encoding
PayMV QRs use a decimal TLV encoding — not binary BER-TLV. Every field is represented as ASCII text:
<2-digit decimal tag><2-digit decimal length><value>...
Example — tag 59, value "AHMED ALI" (9 chars):
5909AHMED ALI
Tags and lengths are always exactly 2 decimal digits. Fields are concatenated directly with no separator.
Root-Level Tags
| Tag | Field | Notes |
|---|---|---|
00 |
Format indicator | Always "01" |
01 |
Point-of-initiation method | "11" = static QR, "12" = dynamic QR |
26 |
Merchant account information | Container — see sub-tags below |
35 |
BML/gateway merchant info | Container — present in combined EMV+BML QRs only |
52 |
Merchant category code | "0000" (generic) |
53 |
Transaction currency | "462" = MVR (ISO 4217 numeric) |
54 |
Transaction amount | Decimal string (e.g. "1.50"); absent for open-amount QRs |
58 |
Country code | "MV" |
59 |
Merchant / recipient name | Max 25 characters |
62 |
Additional data field | Container — see sub-tags below |
63 |
CRC | 6304 prefix + 4-char hex checksum — always last |
80 |
Supplementary data | Container — timestamp and domain |
Merchant Account Info — Tag 26 Sub-Tags
| Sub-Tag | Field | Example value |
|---|---|---|
00 |
Domain | "mv.favara.mpqr" |
01 |
Acquirer BIC | "MALBMVMV" (see table below) |
02 |
Acquirer BIC (repeated) | Same as 01 |
03 |
Account number | Beneficiary account number |
05 |
Mobile number | E.164 format (e.g. "+9607654321"); optional |
10 |
Network indicator | "IPAY" |
Acquirer BIC Mapping
| Bank | Acquirer BIC |
|---|---|
| BML | MALBMVMV |
| MIB | MADVMVMV |
| Fahipay | FAHIMVMV |
Additional Data — Tag 62 Sub-Tags
| Sub-Tag | Field | Notes |
|---|---|---|
05 |
Reference / bill number | 9 random uppercase alphanumeric characters |
08 |
Payment purpose | Free-form text entered by the payee |
Supplementary Data — Tag 80 Sub-Tags
| Sub-Tag | Field | Notes |
|---|---|---|
00 |
Domain | "mv.favara.mpqr" |
01 |
Timestamp | ISO 8601 format: "yyyy-MM-dd'T'HH:mm:ss.00000" |
CRC-16
The checksum uses CRC-16/CCITT-FALSE (polynomial 0x1021, initial value 0xFFFF). The CRC is computed over the entire payload string up to and including "6304", then the 4-digit uppercase hex result is appended.
def crc16(data: str) -> str:
crc = 0xFFFF
for c in data:
crc ^= (ord(c) & 0xFF) << 8
for _ in range(8):
if crc & 0x8000:
crc = ((crc << 1) & 0xFFFF) ^ 0x1021
else:
crc = (crc << 1) & 0xFFFF
return format(crc, '04X')
Generating a Receive-Payment QR
To create a QR that others can scan to pay you:
00 02 01 ← Format indicator
01 02 11 ← Static QR
26 <len> ← Merchant account info
00 15 mv.favara.mpqr
01 08 MALBMVMV ← Acquirer BIC (BML example)
02 08 MALBMVMV ← Repeated
03 <len> <accountNumber>
05 <len> <+960XXXXXXX> ← Optional phone
10 04 IPAY
52 04 0000 ← MCC
53 03 462 ← MVR
54 <len> <amount> ← Omit tag entirely if open-amount
58 02 MV
59 <len> <name up to 25 chars>
62 <len>
05 09 <9 random alphanum chars> ← Reference
08 <len> <purpose text>
80 <len>
00 15 mv.favara.mpqr
01 <len> <yyyy-MM-dd'T'HH:mm:ss.00000> ← Timestamp
6304<CRC>
Parsing a PayMV QR (Incoming Scan)
When scanning a QR code, extract the relevant fields:
| Field | TLV path | Used for |
|---|---|---|
| Account number | root→26→03 |
Transfer destination |
| Amount | root→54 |
Pre-fill transfer amount (may be absent) |
| Merchant name | root→59 |
Display recipient name |
| Purpose | root→62→08 |
Pre-fill transfer remarks |
Extracting a BML Gateway URL from a Combined QR
Combined QRs (e.g. Fahipay card QRs that embed a BML gateway payment URL) encode the BML URL at a fixed TLV path:
root tag 35 → sub-tag 20 → sub-sub-tag 01
The value at sub-sub-tag 01 is a full https://pay.bml.com.mv/app/... URL. Extract it and hand off to the BML QR Payment flow.
Plain BML QR codes (not combined) start with https://pay.bml.com.mv/app/ directly.
Example Payload
Static QR for account 7700000000123, holder "AHMED ALI", open amount, purpose "Rent":
000201010211268...520400005303462
5802MV5909AHMED ALI6225050912345ABCDEF0804Rent
80...63044A2B
(values abbreviated for clarity — actual tags are concatenated with no whitespace)