liopay/vietqr

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

Installs: 1

Dependents: 0

Suggesters: 0

Security: 0

Stars: 2

Watchers: 1

Forks: 0

Open Issues: 0

pkg:composer/liopay/vietqr

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

This package is auto-updated.

Last update: 2025-12-24 04:53:26 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.