thai_promptpay 0.3.0 copy "thai_promptpay: ^0.3.0" to clipboard
thai_promptpay: ^0.3.0 copied to clipboard

Pure-Dart PromptPay (Thai EMVCo QR) toolkit: build and parse the QR payload for mobile, National ID / Tax ID, e-Wallet and Bill Payment, with amount and CRC validation.

thai_promptpay #

pub package CI

ชุดเครื่องมือ PromptPay (Thai EMVCo QR) แบบ pure Dart — สร้างและถอดรหัส payload ของ QR สำหรับเบอร์มือถือ / เลขบัตรประชาชน-ภาษี / e-Wallet พร้อมจำนวนเงินและตรวจ CRC

A pure-Dart PromptPay (Thai EMVCo QR) toolkit — build and parse the QR payload string for a mobile number, National ID / Tax ID or e-Wallet, with amount and CRC validation.

  • Pure Dart, no Flutter, one dependency (thainum, for phone normalization + National-ID MOD-11 validation). Works in back-end / CLI (generate a QR for an invoice server-side) and Flutter.
  • Encode and decode. Most PromptPay libraries only generate — this one also parses a payload back into structured data and verifies the CRC.
  • It returns the payload string, not an image. Render it with any QR package you like (qr_flutter, qr, barcode, …).
  • Exact money. Amounts are integer satang (1 baht = 100 satang) — no double, no rounding surprises.

The output is verified byte-for-byte against the canonical PromptPay references (dtinth/promptpay-qr and the promptpay Python library).

dart pub add thai_promptpay

Encode #

import 'package:thai_promptpay/thai_promptpay.dart';

// To a mobile number (accepts 0812345678, 081-234-5678, +66812345678, …):
promptPayMobile('0812345678');
// 00020101021129370016A0000006770101110113006681234567853037645802TH6304823E

// With an amount (100.00 baht = 10000 satang) → a one-time "dynamic" QR:
promptPayMobile('0812345678', amountSatang: 10000);

// To a 13-digit National ID / personal Tax ID (validated with a MOD-11 checksum):
promptPayNationalId('1101700230708', amountSatang: 25075); // 250.75 baht

// To a 15-digit e-Wallet ID:
promptPayEWallet('004999000000001');

Then render the returned string as a QR with any package, e.g. qr_flutter:

QrImageView(data: promptPayMobile('0812345678', amountSatang: 10000));

Decode #

final p = decodePromptPay(
  '00020101021229370016A0000006770101110113006681234567853037645406100.005802TH6304F142',
);
p.target.type;    // PromptPayType.mobile
p.target.value;   // '0812345678'
p.amountSatang;   // 10000  (100.00 baht)
p.isDynamic;      // true   (one-time QR)

// Non-throwing variant — returns null on a bad payload / CRC mismatch:
tryDecodePromptPay('not a promptpay qr'); // null

decodePromptPay verifies the CRC and throws a PromptPayException (which implements FormatException) on any malformed payload, CRC mismatch, or unknown proxy. tryDecodePromptPay returns null instead.

Bill Payment (EMVCo tag 30) #

Besides the personal transfer above (tag 29), this package also builds and parses Bill Payment QR codes — the ones printed on Thai invoices/utilities/tax forms. They pay a registered Biller ID with Ref1 / Ref2 reference numbers:

// Encode a bill-payment QR (biller + Ref1, optional Ref2 + amount):
encodeBillPayment(
  billerId: '010553609264101',   // 13- or 15-digit Biller ID (Tax ID [+ suffix])
  ref1: '000002201649894',
  ref2: 'INV0001',               // optional
  amountSatang: 25075,           // optional → 250.75 baht, one-time "dynamic" QR
);

// Decode it back:
final b = decodeBillPayment(payload);
b.billerId; b.ref1; b.ref2; b.amountSatang; b.isDynamic;

tryDecodeBillPayment('bad'); // null instead of throwing

Don't know which kind a payload is? decodeAny returns a sealed union so the switch is exhaustive:

switch (decodeAny(payload)) {
  case PromptPayPayload p:    print('personal → ${p.target}');
  case BillPaymentPayload b:  print('bill → ${b.billerId} / ${b.ref1}');
}

decodePromptPay stays personal-only (it throws on a tag-30 payload). The bill-payment output is verified byte-for-byte against the community references maythiwat/promptparse and mrwan2546/promptparse-go.

Slip Verify (Mini-QR) #

The small QR printed on a Thai transfer slip is not a payable QR — it is a receipt-verification code (Slip Verify Mini-QR). This package decodes it offline (no bank API call) into its own sealed SlipData type:

import 'package:thai_promptpay/thai_promptpay.dart';

// A bank slip:
final slip = decodeSlip(
  '004100060000010103014022000111222233344ABCD125102TH910417DF',
);
switch (slip) {
  case BankSlip s:
    s.sendingBankCode;  // '014'
    s.bank?.nameEn;     // 'Siam Commercial Bank'
    s.bank?.nameTh;     // 'ธนาคารไทยพาณิชย์'
    s.transRef;         // '00111222233344ABCD12'
    s.countryCode;      // 'TH'
  case TrueMoneySlip s:
    s.eventType;        // e.g. 'P2P'
    s.transactionId;
    s.date;             // 'DDMMYYYY'
}

// Non-throwing variant — returns null on a bad payload / CRC mismatch:
tryDecodeSlip('not a slip qr'); // null

decodeSlip verifies the CRC and throws a PromptPayException on a malformed payload or CRC mismatch; an unknown bank code never throws (bank is simply null). Look up a bank code directly with thaiBankByCode('014')ThaiBank?.

The slip TLV structure and test vectors are ported from maythiwat/promptparse (MIT) and cross-checked with SCB's mini-QR documentation — see NOTICE.md.

Notes #

  • Money is handled in integer satang end to end (amountSatang). Pair it with thainum if you want the baht text.
  • Validation: mobile numbers are normalized/validated, National IDs are checked with the 13-digit MOD-11 checksum, e-Wallet IDs are length-checked.
  • Scope: personal PromptPay (EMVCo tag 29) — mobile / National ID / e-Wallet — and Bill Payment (tag 30). The tag-62 additional-data block (Ref3) is tolerated on decode but not generated.
  • crc16ccitt(String) (CRC-16/CCITT-FALSE) is exported for convenience.

License #

MIT © 2026 MaIII (ultramcu)

0
likes
160
points
170
downloads

Documentation

API reference

Publisher

verified publisher10v3n4m.cc

Weekly Downloads

Pure-Dart PromptPay (Thai EMVCo QR) toolkit: build and parse the QR payload for mobile, National ID / Tax ID, e-Wallet and Bill Payment, with amount and CRC validation.

Repository (GitHub)
View/report issues

Topics

#promptpay #thai #qr #payment #emvco

License

MIT (license)

Dependencies

thainum

More

Packages that depend on thai_promptpay