vietqrjs
v1.1.3
Published
Support generate VietQR Code
Downloads
43
Maintainers
Readme
Overview
This library be implemented follow the VietQR specified document from NAPAS on vietqr.net
Vietqrjs library supports some features:
- Create QR string|code from data: account number, account name, bank ID, bank name, transaction amount, description ...
- Decrypt an QR string (string read from QR code image) to get information for payment.(from v1.1.0)
Vietqrjs supports 4 service types:
Cash withdraw service (QRCASH)
Products payment service (QRPUSH)
transfer by account number (QRIBFTTA)
transfer by card number (QRIBFTTC)
Buy me a coffee
If you feel my lib is useful, buy me a coffee, thanks! MoMo Wallet transfer QR code:
Change Logs:
v1.1.3
- Update donation information :)
v1.1.2
- Add the 2nd parameter for VietQrV1Decryptor decrypt function to support return lean|full decrypted QR data object
- Set the setmerchantCategoryCode and getQrCodeString function in VietQRV1Builder class is deprecated, instead by setMerchantCategoryCode and getQrString function
- Update function generateQR of VietQRV1Builder class
- Update docs on README
v1.1.1
- Fixed some bugs related to function check valid CRC code of QR string in Decryptor class
v1.1.0
- Add VietQrV1Decryptor to support decrypt QR string to get Merchant/Consumer information.
- Update Unit tests for VietQRV1Builder and VietQrV1Decryptor functions
v1.0.2
- Add new service codes: QRPUSH and QRCASH
Installation
npm i --save vietqrjs
Interfaces
interface IVietQrDataV1
interface IVietQrDataV1 {
version: VietQrVersion; // ID 00
initMethod: VietQrInitiateMethod; // ID 01
merchantAccInfo: IMerchantAccountInfo; // ID = 38
merchantCategoryCode?: MerchantCategoryCode | string | null | undefined; // ID 52
txnCurrency: number; // ID 53
txnAmount?: string; // ID 54
tipConvenienceIndicator?: TipOrConvenienceIndicatorType | string | null | undefined; // ID 55
convenienceFeeFixed?: StringOrNot; // ID 56
convenienceFeePercentage?: StringOrNot; // ID 57
countryCode: string; // ID 58
merchantName?: StringOrNot; // ID 59
merchantCity?: StringOrNot; // ID 60
postalCode?: StringOrNot; // ID 61
additionalData?: IAdditionalData | null | undefined; // ID 62
languageTemplate?: ILanguageTemplate | null | undefined; // ID 64
crcCode: string; // ID 63
}
interface IBasicVietQrData
interface IBasicVietQrData {
acquierId: BankBIN; // ID DVCNTT
merchantId: string; // Tài khoản/Số thẻ thụ hưởng
serviceCode?: ServiceCode;
amount?: number;
txnDescription?: string;
}
interface IMerchantAccountInfo
interface IMerchantAccountInfo {
guid?: GUID | string; // ID 38 - 00 (Required Field)
beneficiaryOrg: IBeneficiaryOrganiation; // ID 38 - 01 (Required Field)
serviceCode?: ServiceCode; // ID 38 - 02 (Conditional Field)
}
interface IBeneficiaryOrganiation
interface IBeneficiaryOrganiation {
acquierId: BankBIN | string; // ID 38 - 01 - 00 (Required Field)
merchantId: string; // ID 38 - 01 - 01 (Required Field)
}
interface IAdditionalData
interface IAdditionalData {
billNumber?: StringOrNot; // ID 62 - 01 (Conditional Field)
mobileNumber?: StringOrNot; // ID 62 - 02 (Conditional Field)
storeLabel?: StringOrNot; // ID 62 - 03 (Optional Field)
loyaltyNumber?: StringOrNot; // ID 62 - 04 (Optional Field)
referenceLabel?: StringOrNot; // ID 62 - 05 (Conditional Field)
customerLabel?: StringOrNot; // ID 62 - 06 (Conditional Field)
terminalLabel?: StringOrNot; // ID 62 - 07 (Optional Field)
purposeOfTxn?: StringOrNot; // ID 62 - 08 (Conditional Field)
additionalConsumerDataReq?: StringOrNot; // ID 62 - 09 (Optional Field)
}
interface ILanguageTemplate
interface ILanguageTemplate {
preference: string; // ID 64 - 00 (Required Field)
merchantName: string; // ID 64 - 01 (Required Field)
merchantCity?: StringOrNot; // ID 64 - 02 (Optional Field)
}
interface IDecryptedQrDataOptions
interface IDecryptedQrDataOptions {
/**
* Remove all decrypted data object fields is optional and have value is empty or undefined
* @default true
*/
lean?: boolean;
}
interface
interface IGenerateQROptions {
logo?: string; // path to image file or base64 image string, if null will be render vietQR logo
margin?: number; // margin of QR code and image frame. default is 4
width?: number; // width of canvas object to draw QR code // default is 250
bgColor?: string; // background color of QR code - default is '#ffffff'
color?: string; // color of QR code - default is '#000000'
errorCorrectionLevel?: 'L' | 'M' | 'Q' | 'H'; // default is 'H'
}
Usage
VietQRV1Builder
Functions:
- quickBuild(data; IBasicVietQrData): VietQRV1Builder; // quick build QR string from minimum required VietQR data
- getQrString(): string; // Get the result of quickbuild or build function from builder
- build(): VietQRV1Builder; // build the QR string after set some VietQR data
- refresh(): VietQRV1Builder; // Refresh VietQR data of builder to initialization
- getQrCodeString(): string; // (deprecated) // Get the result of quickbuild or build function from builder
- generateQR(options?: IGenerateQROptions): string; // generate base64 QR image
- setMerchantAccountInfo(data: IMerchantAccountInfo): VietQRV1Builder;
- setMerchantName(merchantName: string): VietQRV1Builder;
- setMerchantCity(merchantCity: string): VietQRV1Builder;
- setTxnCurrency(currencyCode: number): VietQRV1Builder;
- setTxnCountry(countryCode: string): VietQRV1Builder;
- setMerchantCategoryCode(mcc: string): VietQRV1Builder;
- setAdditionalData(data: IAdditionalData): VietQRV1Builder;
- setLanguageTemplate(template: ILanguageTemplate): VietQRV1Builder;
- setTxnDescription(description: string): VietQRV1Builder;
- setTxnAmount(amount: number): VietQRV1Builder;
- setPostalCode(postalCode: string): VietQRV1Builder;
Quick generate QR string
Example:
import {VietQRV1Builder, BankBIN, ServiceCode} from 'vietqrjs';
const builder = new VietQRV1Builder();
const qrDataString = builder.quickBuild({ // IBasicVietQrData
acquierId: BankBIN.VIETINBANK, // ID DVCNTT
merchantId: '', // Account number
serviceCode: ServiceCode.BY_ACCOUNT_NUMBER,
}).getQrString();
Build an QR string to render static QR code with account number
Example:
import {VietQRV1Builder, BankBIN, ServiceCode} from 'vietqrjs';
const builder = new VietQRV1Builder();
const qrDataStr = builder.setMerchantAccountInfo({
// IMerchantAccountInfo
beneficiaryOrg: { // IBeneficiaryOrganiation
acquierId: BankBIN.VIETCOMBANK,
merchantId: '03123445xxx', // account number
},
serviceCode: ServiceCode.BY_ACCOUNT_NUMBER,
})
.build()
.getQrString();
Build an QR string to render static QR code with card number
Example:
import {VietQRV1Builder, BankBIN, ServiceCode} from 'vietqrjs';
const builder = new VietQRV1Builder();
const qrString = builder.setMerchantAccountInfo({
beneficiaryOrg: {
acquierId: BankBIN.ACB,
merchantId: '040812344454xxx', // card number
},
serviceCode: ServiceCode.BY_CARD_NUMBER,
})
.build()
.getQrString();
Build an QR string to render QR code to cash withdrawl
Example:
import {VietQRV1Builder, BankBIN, ServiceCode} from 'vietqrjs';
const vietqr = new VietQRV1Builder();
const qrString = vietqr.setMerchantAccountInfo({
beneficiaryOrg: {
acquierId: BankBIN.ACB,
merchantId: '12345678', // ATM ID
},
serviceCode: ServiceCode.BY_CASH_WITHDRAWL_SERVICE,
})
.setMerchantName('NGUYEN VAN A')
.setMerchantCity('HA NOI')
.setTxnCurrency()
.setTxnCountry()
.setMerchantCategoryCode(MerchantCategoryCode.FINANCIAL_INSTITUTIONS_WITH_CASH_DISBURSEMENTS)
.setAdditionalData({
referenceLabel: '201901091557142283847',
terminalLabel: '00001111',
}).build()
.getQrString();
console.log(qrString);
// expect
// 00020101021138500010A000000727012200069704160108123456780206QRCASH5204601153037045802VN5912NGUYEN VAN A6006HA NOI6237052120190109155714228384707080000111163049CE4
Build an QR string to render dynamic QR code with account number
Example:
import {VietQRV1Builder, BankBIN, ServiceCode} from 'vietqrjs';
const builder = new VietQRV1Builder();
const qrDataStr = builder.setMerchantAccountInfo({
beneficiaryOrg: {
acquierId: BankBIN.MB_BANK,
merchantId: '03123445xxx', // account number
},
serviceCode: ServiceCode.BY_ACCOUNT_NUMBER,
})
.setTxnAmount(86000)
.setMerchantName('Cua hang tien loi') // optional
.setMerchantCity('NANOI') // optional
.setPostalCode('10000') // optional
.setTxnDescription('Thanh toan hoa don') // optional
.setAdditionalData({ // optional
billNumber: 'B123456',
storeLabel: 'NPS124',
})
.build()
.getQrString();
Build QR code from payment account information
Example:
import {VietQRV1Builder, BankBIN, ServiceCode} from 'vietqrjs';
const builder = new VietQRV1Builder();
const qrBase64Image = await builder
.quickBuild({
acquierId: BankBIN.TP_BANK, // ID DVCNTT
merchantId: '123456789', // Tài khoản/Số thẻ thụ hưởng
serviceCode: ServiceCode.BY_ACCOUNT_NUMBER,
})
.generateQR({
width: 300,
margin: 2,
color: '#555555',
bgColor: '#EEEEEE',
});
console.log(qrBase64Image);
// data:image/png;base64,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
VietQrV1Decryptor (supported from v1.1.0)
Decrypt QR string to get information for payment.
Check CRC checksum of QR string
isValidChecksum(qrString: string): boolean;
Example:
import { VietQrV1Decryptor } from 'vietqrjs';
const decryptor = new VietQrV1Decryptor();
const isValid = decryptor.isValidChecksum('00020101021238500010A000000727012200069704030108123456780206QRCASH5204601153037045802VN5915NGUYEN HUU HUAN6005HANOI6105100006237052120190109155714228384707080000111164260002en0107shop vn0205Hanoi63047611');
console.log(isValid) // false
Decrypt QR string to get information for payment
decrypt(qrString: string, options?: IDecryptedQrDataOptions): IVietQrDataV1
Example:
import { VietQrV1Decryptor } from 'vietqrjs';
const decryptor = new VietQrV1Decryptor();
// decrypt QR string and get full fields QR data
const qrData = decryptor.decrypt(
'00020101021238500010A000000727012200069704030108123456780206QRCASH5204601153037045802VN5915NGUYEN HUU HUAN6005HANOI6105100006237052120190109155714228384707080000111164260002en0107shop vn0205Hanoi630476DA',
{ lean: false },
);
console.log(qrData);
// {
// version: '01',
// initMethod: '12',
// merchantAccInfo: {
// guid: 'A000000727',
// beneficiaryOrg: {
// acquierId: '970403',
// merchantId: '12345678'
// },
// serviceCode: 'QRCASH'
// },
// merchantCategoryCode: '6011',
// txnCurrency: 704,
// txnAmount: undefined,
// tipConvenienceIndicator: undefined,
// convenienceFeeFixed: undefined,
// convenienceFeePercentage: undefined,
// countryCode: 'VN',
// merchantName: 'NGUYEN HUU HUAN',
// merchantCity: 'HANOI',
// postalCode: '10000',
// additionalData: {
// billNumber: undefined,
// mobileNumber: undefined,
// storeLabel: undefined,
// loyaltyNumber: undefined,
// referenceLabel: '201901091557142283847',
// customerLabel: undefined,
// terminalLabel: '00001111',
// purposeOfTxn: undefined,
// additionalConsumerDataReq: undefined
// },
// languageTemplate: {
// preference: 'en',
// merchantName: 'shop vn',
// merchantCity: 'Hanoi',
// },
// crcCode: '76DA'
// }
const leanQrData = decryptor.decrypt(
'00020101021238500010A000000727012200069704030108123456780206QRCASH5204601153037045802VN5915NGUYEN HUU HUAN6005HANOI6105100006237052120190109155714228384707080000111164260002en0107shop vn0205Hanoi630476DA',
);
console.log(leanQrData);
// {
// version: '01',
// initMethod: '12',
// merchantAccInfo: {
// guid: 'A000000727',
// beneficiaryOrg: {
// acquierId: '970403',
// merchantId: '12345678'
// },
// serviceCode: 'QRCASH'
// },
// merchantCategoryCode: '6011',
// txnCurrency: 704,
// countryCode: 'VN',
// merchantName: 'NGUYEN HUU HUAN',
// merchantCity: 'HANOI',
// postalCode: '10000',
// additionalData: {
// referenceLabel: '201901091557142283847',
// terminalLabel: '00001111',
// },
// languageTemplate: {
// preference: 'en',
// merchantName: 'shop vn',
// merchantCity: 'Hanoi',
// },
// crcCode: '76DA'
// }