Search by

liopay / vietqr

Ngô Quốc Đạt

Production-ready PHP library for building and parsing VietQR (NAPAS FastFund 24/7 IBFT) QR codes compliant with EMVCo 1.5.2 specification.

v1.0.0 2025-11-13 01:44 UTC

This package is auto-updated.

Last update: 2026-09-24 06:40:40 UTC


README

Latest Version PHP Version License Total Downloads

English | Tiếng Việt

Production-ready PHP library for building and parsing VietQR (NAPAS FastFund 24/7 IBFT) QR codes compliant with EMVCo 1.5.2 specification.

Features

  • EMVCo 1.5.2 Compliant - Follows NAPAS QR Switching specification v1.5.2
  • Build QR Codes - Generate QR codes for all service types (PUSH/CASH/IBFT)
  • Parse QR Strings - Parse any VietQR string into structured data
  • Full Validation - Comprehensive validation per NAPAS specification
  • CRC16-CCITT - Automatic checksum calculation and verification
  • Zero Dependencies - No external runtime dependencies
  • PHP 7.4+ - Strict typing throughout
  • PSR-4 Autoloading - Modern PHP package structure

Installation

composer require liopay/vietqr

Quick Start

Build an Inter-Bank Fund Transfer QR Code

use Liopay\VietQR\Builder\QRIBFTBuilder;

$builder = new QRIBFTBuilder();

$qrString = $builder
    ->setPointOfInitiation('12') // Dynamic QR
    ->setBeneficiaryBankBin('970436')
    ->setConsumerId('1017595600')
    ->setIBFTToAccount()
    ->setAmount('180000')
    ->setPurposeOfTransaction('thanh toan don hang')
    ->build();

// Result: 00020101021238540010A00000072701240006970436011010175956000208QRIBFTTA530370454061800005802VN62230819thanh toan don hang630470FA

Parse a QR Code

use Liopay\VietQR\Parser\QRParser;

$parser = new QRParser();

$qrData = $parser->parse($qrString);

echo $qrData->getConsumerId(); // "1017595600"
echo $qrData->getAmount(); // "180000"
echo $qrData->getServiceCode(); // "QRIBFTTA"
echo $qrData->getPurposeOfTransaction(); // "thanh toan don hang"

Service Types

VietQR supports four service types:

1. QRIBFTTA - Inter-Bank Fund Transfer to Account

Peer-to-peer transfer to bank account.

$builder = new QRIBFTBuilder();
$qr = $builder
    ->setPointOfInitiation('12') // Dynamic
    ->setBeneficiaryBankBin('970436')
    ->setConsumerId('1017595600')
    ->setIBFTToAccount()
    ->setAmount('180000')
    ->setPurposeOfTransaction('thanh toan don hang')
    ->build();

2. QRIBFTTC - Inter-Bank Fund Transfer to Card

Peer-to-peer transfer to card number.

$builder = new QRIBFTBuilder();
$qr = $builder
    ->setPointOfInitiation('12') // Dynamic
    ->setBeneficiaryBankBin('970436')
    ->setConsumerId('9704361017595600')
    ->setIBFTToCard()
    ->setAmount('180000')
    ->build();

3. QRPUSH - Payment Service

Standard merchant payment QR codes.

$builder = new QRPushBuilder();
$qr = $builder
    ->setPointOfInitiation('12') // Dynamic
    ->setAcquirerBankBin('970436')
    ->setMerchantId('1017595600')
    ->setMerchantCategoryCode('5812')
    ->setAmount('180000')
    ->setMerchantName('NGO QUOC DAT')
    ->setMerchantCity('HANOI')
    ->build();

4. QRCASH - ATM Cash Withdrawal

QR codes for ATM cash withdrawal. Note: Reference Label and Terminal Label are mandatory.

$builder = new QRCashBuilder();
$qr = $builder
    ->setPointOfInitiation('12') // Must be dynamic
    ->setAcquirerBankBin('970436')
    ->setATMId('12345678')
    ->setCashService() // Sets service code to QRCASH
    ->setMerchantCategoryCode('6011')
    ->setMerchantName('NGO QUOC DAT')
    ->setMerchantCity('HANOI')
    ->setReferenceLabel('20190109155714228384') // Required
    ->setTerminalLabel('0000111') // Required
    ->build();

Specification Constants

Required Values

  • AID: A000000727 (NAPAS Application Identifier)
  • Currency: 704 (VND - Vietnamese Dong)
  • Country: VN (Vietnam)

Data Object IDs (Root Level)

ID Name Required
00 Payload Format Indicator ✓
01 Point of Initiation Optional
38 Merchant Account Information ✓
52 Merchant Category Code ✓
53 Transaction Currency ✓
54 Transaction Amount Conditional
58 Country Code ✓
59 Merchant Name ✓
60 Merchant City ✓
62 Additional Data Field Optional
63 CRC Checksum ✓

Point of Initiation Values

  • 11 - Static QR (reusable for multiple transactions)
  • 12 - Dynamic QR (single-use transaction)

TLV Encoding

VietQR uses TLV (Tag-Length-Value) encoding:

Format: ID (2 digits) + Length (2 digits) + Value (variable)
Example: "59" + "12" + "NGO QUOC DAT"
$tlvHelper = new TLVHelper();

// Encode
$encoded = $tlvHelper->encode('59', 'NGO QUOC DAT');
// Result: "5912NGO QUOC DAT"

// Decode
$decoded = $tlvHelper->decode($encoded);
// Result: ['59' => 'NGO QUOC DAT']

CRC Checksum

VietQR uses CRC16-CCITT False:

  • Polynomial: 0x1021
  • Init Value: 0xFFFF
  • Applied to all data including "6304" but excluding CRC value
$crcHelper = new CRCHelper();

// Calculate
$crc = $crcHelper->calculate($data);

// Verify
$isValid = $crcHelper->verify($qrString);

// Append to QR data
$completeQR = $crcHelper->append($qrData);

Validation

All builders perform automatic validation:

  • ✓ Field length constraints
  • ✓ Required field presence
  • ✓ Format validation (numeric, alphanumeric)
  • ✓ MCC code validation
  • ✓ Service code validation
  • ✓ CRC checksum calculation
  • ✓ Additional Data Field mandatory fields per QR type

Exception Handling

use Liopay\VietQR\Exception\{
    VietQRException,
    InvalidFormatException,
    InvalidCRCException,
    ValidationException,
    MissingRequiredFieldException
};

try {
    $qr = $builder->build();
} catch (MissingRequiredFieldException $e) {
    // Handle missing required field
} catch (ValidationException $e) {
    // Handle validation error
} catch (VietQRException $e) {
    // Handle general VietQR error
}

Value Objects

Immutable, validated value objects for type safety:

use Liopay\VietQR\ValueObject\{
    ServiceCode,
    PointOfInitiation
};

// Service Code
$serviceCode = new ServiceCode('QRPUSH');
$serviceCode->isPayment(); // true
$serviceCode->isIBFT(); // false

// Point of Initiation
$poi = PointOfInitiation::static();
$poi->isStatic(); // true
$poi->getValue(); // "11"

Testing

Run the test suite:

composer test

Run PHPStan static analysis:

composer phpstan

Check code style:

composer cs-check

Fix code style:

composer cs-fix

Requirements

  • PHP >= 7.4

Specification Compliance

This library implements:

  • NAPAS QR Switching Technical Specifications v1.5.2
  • EMVCo QR Code Specification for Payment Systems: Merchant-Presented Mode

License

MIT License. See LICENSE for details.

Credits

Developed by Liopay

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

For issues and questions, please use the GitHub issue tracker.