├── .eslintignore ├── src ├── index.ts ├── images │ ├── acb-icon.png │ ├── bidc-icon.png │ ├── bidv-icon.png │ ├── cake-icon.png │ ├── cimb-icon.png │ ├── hsbc-icon.png │ ├── mbv-icon.png │ ├── msb-icon.png │ ├── ncb-icon.png │ ├── ocb-icon.png │ ├── scb-icon.png │ ├── shb-icon.png │ ├── timo-icon.png │ ├── uob-icon.png │ ├── vib-icon.png │ ├── vrb-icon.png │ ├── abbank-icon.png │ ├── cbbank-icon.png │ ├── gpbank-icon.png │ ├── hdbank-icon.png │ ├── ibkhcm-icon.png │ ├── ibkhn-icon.png │ ├── lpbank-icon.png │ ├── mbbank-icon.png │ ├── pgbank-icon.png │ ├── tpbank-icon.png │ ├── ubank-icon.png │ ├── vikki-icon.png │ ├── vpbank-icon.png │ ├── agribank-icon.png │ ├── bacabank-icon.png │ ├── banviet-icon.png │ ├── baoviet-icon.png │ ├── coopbank-icon.png │ ├── dbsbank-icon.png │ ├── dongabank-icon.png │ ├── eximbank-icon.png │ ├── kasikorn-icon.png │ ├── kookminhn-icon.png │ ├── liobank-icon.png │ ├── namabank-icon.png │ ├── nonghyup-icon.png │ ├── oceanbank-icon.png │ ├── pvcombank-icon.png │ ├── sacombank-icon.png │ ├── seabank-icon.png │ ├── vietabank-icon.png │ ├── vietbank-icon.png │ ├── wooribank-icon.png │ ├── kookminhcm-icon.png │ ├── publicbank-icon.png │ ├── saigonbank-icon.png │ ├── shinhanbank-icon.png │ ├── techcombank-icon.png │ ├── vietcombank-icon.png │ ├── vietinbank-icon.png │ ├── hongleongbank-icon.png │ ├── indovinabank-icon.png │ ├── kienlongbank-icon.png │ ├── lienvietpostbank-icon.png │ └── standardcharteredbank-icon.png ├── constants │ ├── index.ts │ ├── bank-code.ts │ ├── bank-key.ts │ ├── qr-pay.ts │ ├── bank-apps.ts │ └── banks.ts ├── utils.ts ├── crc16.ts └── qr-pay.ts ├── tsconfig.build.json ├── .eslintrc ├── test ├── test-airpay-qr.spec.ts ├── test-evn-qr.spec.ts ├── test-quick-gen-qr.spec.ts ├── test-vnpay-qr.spec.ts ├── test-vietqr.spec.ts ├── test-momo-zalopay.spec.ts ├── zalopay.svg └── momo.svg ├── .gitignore ├── tsconfig.json ├── LICENSE ├── package.json └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './qr-pay' 2 | export * from './constants/index' 3 | -------------------------------------------------------------------------------- /src/images/acb-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/acb-icon.png -------------------------------------------------------------------------------- /src/images/bidc-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/bidc-icon.png -------------------------------------------------------------------------------- /src/images/bidv-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/bidv-icon.png -------------------------------------------------------------------------------- /src/images/cake-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/cake-icon.png -------------------------------------------------------------------------------- /src/images/cimb-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/cimb-icon.png -------------------------------------------------------------------------------- /src/images/hsbc-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/hsbc-icon.png -------------------------------------------------------------------------------- /src/images/mbv-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/mbv-icon.png -------------------------------------------------------------------------------- /src/images/msb-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/msb-icon.png -------------------------------------------------------------------------------- /src/images/ncb-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/ncb-icon.png -------------------------------------------------------------------------------- /src/images/ocb-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/ocb-icon.png -------------------------------------------------------------------------------- /src/images/scb-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/scb-icon.png -------------------------------------------------------------------------------- /src/images/shb-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/shb-icon.png -------------------------------------------------------------------------------- /src/images/timo-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/timo-icon.png -------------------------------------------------------------------------------- /src/images/uob-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/uob-icon.png -------------------------------------------------------------------------------- /src/images/vib-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/vib-icon.png -------------------------------------------------------------------------------- /src/images/vrb-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/vrb-icon.png -------------------------------------------------------------------------------- /src/images/abbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/abbank-icon.png -------------------------------------------------------------------------------- /src/images/cbbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/cbbank-icon.png -------------------------------------------------------------------------------- /src/images/gpbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/gpbank-icon.png -------------------------------------------------------------------------------- /src/images/hdbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/hdbank-icon.png -------------------------------------------------------------------------------- /src/images/ibkhcm-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/ibkhcm-icon.png -------------------------------------------------------------------------------- /src/images/ibkhn-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/ibkhn-icon.png -------------------------------------------------------------------------------- /src/images/lpbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/lpbank-icon.png -------------------------------------------------------------------------------- /src/images/mbbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/mbbank-icon.png -------------------------------------------------------------------------------- /src/images/pgbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/pgbank-icon.png -------------------------------------------------------------------------------- /src/images/tpbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/tpbank-icon.png -------------------------------------------------------------------------------- /src/images/ubank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/ubank-icon.png -------------------------------------------------------------------------------- /src/images/vikki-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/vikki-icon.png -------------------------------------------------------------------------------- /src/images/vpbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/vpbank-icon.png -------------------------------------------------------------------------------- /src/images/agribank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/agribank-icon.png -------------------------------------------------------------------------------- /src/images/bacabank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/bacabank-icon.png -------------------------------------------------------------------------------- /src/images/banviet-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/banviet-icon.png -------------------------------------------------------------------------------- /src/images/baoviet-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/baoviet-icon.png -------------------------------------------------------------------------------- /src/images/coopbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/coopbank-icon.png -------------------------------------------------------------------------------- /src/images/dbsbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/dbsbank-icon.png -------------------------------------------------------------------------------- /src/images/dongabank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/dongabank-icon.png -------------------------------------------------------------------------------- /src/images/eximbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/eximbank-icon.png -------------------------------------------------------------------------------- /src/images/kasikorn-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/kasikorn-icon.png -------------------------------------------------------------------------------- /src/images/kookminhn-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/kookminhn-icon.png -------------------------------------------------------------------------------- /src/images/liobank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/liobank-icon.png -------------------------------------------------------------------------------- /src/images/namabank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/namabank-icon.png -------------------------------------------------------------------------------- /src/images/nonghyup-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/nonghyup-icon.png -------------------------------------------------------------------------------- /src/images/oceanbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/oceanbank-icon.png -------------------------------------------------------------------------------- /src/images/pvcombank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/pvcombank-icon.png -------------------------------------------------------------------------------- /src/images/sacombank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/sacombank-icon.png -------------------------------------------------------------------------------- /src/images/seabank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/seabank-icon.png -------------------------------------------------------------------------------- /src/images/vietabank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/vietabank-icon.png -------------------------------------------------------------------------------- /src/images/vietbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/vietbank-icon.png -------------------------------------------------------------------------------- /src/images/wooribank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/wooribank-icon.png -------------------------------------------------------------------------------- /src/images/kookminhcm-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/kookminhcm-icon.png -------------------------------------------------------------------------------- /src/images/publicbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/publicbank-icon.png -------------------------------------------------------------------------------- /src/images/saigonbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/saigonbank-icon.png -------------------------------------------------------------------------------- /src/images/shinhanbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/shinhanbank-icon.png -------------------------------------------------------------------------------- /src/images/techcombank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/techcombank-icon.png -------------------------------------------------------------------------------- /src/images/vietcombank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/vietcombank-icon.png -------------------------------------------------------------------------------- /src/images/vietinbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/vietinbank-icon.png -------------------------------------------------------------------------------- /src/images/hongleongbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/hongleongbank-icon.png -------------------------------------------------------------------------------- /src/images/indovinabank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/indovinabank-icon.png -------------------------------------------------------------------------------- /src/images/kienlongbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/kienlongbank-icon.png -------------------------------------------------------------------------------- /src/images/lienvietpostbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/lienvietpostbank-icon.png -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /src/images/standardcharteredbank-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuannghia/vietnam-qr-pay/HEAD/src/images/standardcharteredbank-icon.png -------------------------------------------------------------------------------- /src/constants/index.ts: -------------------------------------------------------------------------------- 1 | export * from './bank-code' 2 | export * from './bank-key' 3 | export * from './bank-apps' 4 | export * from './banks' 5 | export * from './qr-pay' 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "project": "./tsconfig.json" 4 | }, 5 | "extends": [ 6 | "plugin:@typescript-eslint/recommended" 7 | ], 8 | "rules": { 9 | "quotes": ["error", "single"], 10 | "semi": ["error", "never"], 11 | "indent": ["error", 2, { "SwitchCase": 1 }], 12 | "@typescript-eslint/strict-boolean-expressions": "off" 13 | } 14 | } -------------------------------------------------------------------------------- /test/test-airpay-qr.spec.ts: -------------------------------------------------------------------------------- 1 | 2 | import { QRPay } from '../src/qr-pay' 3 | 4 | test('AirPay', () => { 5 | const qrPay = new QRPay('00020101021126610013vn.airpay.www014000000201010100064185noC4efDjGKq0or5GbeBz5204581253037045910RESTAURANT6009HOCHIMINH5802VN6304DA5C') 6 | expect(qrPay.isValid).toBe(true) 7 | expect(qrPay.version).toBe('01') 8 | expect(qrPay.provider.name).toBeUndefined() 9 | expect(qrPay.provider.guid).toBe('vn.airpay.www') 10 | }) 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Dependency directories 9 | node_modules/ 10 | 11 | 12 | # Optional npm cache directory 13 | .npm 14 | 15 | # Optional eslint cache 16 | .eslintcache 17 | 18 | # Optional REPL history 19 | .node_repl_history 20 | 21 | # Yarn Integrity file 22 | .yarn-integrity 23 | 24 | # dotenv environment variables file 25 | .env 26 | 27 | # Misc 28 | .DS_Store 29 | Thumbs.db 30 | 31 | # Build 32 | dist/ -------------------------------------------------------------------------------- /test/test-evn-qr.spec.ts: -------------------------------------------------------------------------------- 1 | import { QRPay } from '../src/qr-pay' 2 | 3 | test('Test EVN QR', () => { 4 | const qrContent = '000201010211262400020001140100101114-0195204490053037045802VN5931EVN CONG TY DIEN LUC THANH XUAN6006Ha Noi62450302000613PD000000000000702000812TT tien dien6304DC30' 5 | const qrPay = new QRPay(qrContent) 6 | expect(qrPay.isValid).toBe(true) 7 | expect(qrPay.version).toBe('01') 8 | expect(qrPay.provider.fieldId).toBe('26') 9 | expect(qrPay.provider.guid).toBe('00') 10 | expect(qrPay.additionalData.customerLabel).toBe('PD00000000000') 11 | expect(qrPay.build()).toBe(qrContent) 12 | }) 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strictNullChecks": true, 10 | "target": "es2017", 11 | "sourceMap": false, 12 | "inlineSourceMap": false, 13 | "outDir": "./dist", 14 | "baseUrl": "./", 15 | "incremental": true, 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "allowJs": true, 20 | "skipLibCheck": true, 21 | "esModuleInterop": true, 22 | "declarationDir": "dist", 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) xuannghia (https://xuannghia.dev) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | export const stringToUint8Array = (content: string): Uint8Array => { 2 | if (typeof TextEncoder !== 'undefined') { 3 | const encoder = new TextEncoder() 4 | return encoder.encode(content) 5 | } 6 | // Polyfill for TextEncoder 7 | // This is a simplified implementation of the TextEncoder API 8 | // Source: https://gist.github.com/Yaffle/5458286 9 | const octets: number[] = [] 10 | const length = content.length 11 | let i = 0 12 | while (i < length) { 13 | const codePoint = content.codePointAt(i) as number 14 | let c = 0 15 | let bits = 0 16 | if (codePoint <= 0x0000007F) { 17 | c = 0 18 | bits = 0x00 19 | } else if (codePoint <= 0x000007FF) { 20 | c = 6 21 | bits = 0xC0 22 | } else if (codePoint <= 0x0000FFFF) { 23 | c = 12 24 | bits = 0xE0 25 | } else if (codePoint <= 0x001FFFFF) { 26 | c = 18 27 | bits = 0xF0 28 | } 29 | octets.push(bits | (codePoint >> c)) 30 | c -= 6 31 | while (c >= 0) { 32 | octets.push(0x80 | ((codePoint >> c) & 0x3F)) 33 | c -= 6 34 | } 35 | i += codePoint >= 0x10000 ? 2 : 1 36 | } 37 | return new Uint8Array(octets) 38 | } -------------------------------------------------------------------------------- /test/test-quick-gen-qr.spec.ts: -------------------------------------------------------------------------------- 1 | import { BanksObject } from '../src/constants' 2 | import { QRPay } from '../src/qr-pay' 3 | 4 | test('VietQR Static', () => { 5 | const qrPay = QRPay.initVietQR({ 6 | bankBin: BanksObject.acb.bin, 7 | bankNumber: '257678859', 8 | }) 9 | const content = qrPay.build() 10 | 11 | expect(qrPay.initMethod).toBe('11') 12 | expect(content).toBe('00020101021138530010A0000007270123000697041601092576788590208QRIBFTTA53037045802VN6304AE9F') 13 | }) 14 | 15 | test('VietQR Dynamic', () => { 16 | const qrPay = QRPay.initVietQR({ 17 | bankBin: BanksObject.acb.bin, 18 | bankNumber: '257678859', 19 | amount: '10000', 20 | purpose: 'Chuyen tien', 21 | }) 22 | const content = qrPay.build() 23 | 24 | expect(qrPay.initMethod).toBe('12') 25 | expect(content).toBe('00020101021238530010A0000007270123000697041601092576788590208QRIBFTTA53037045405100005802VN62150811Chuyen tien630453E6') 26 | }) 27 | 28 | test('VNPayQR', () => { 29 | const qrPay = QRPay.initVNPayQR({ 30 | merchantId: '0102154778', 31 | merchantName: 'TUGIACOMPANY', 32 | store: 'TU GIA COMPUTER', 33 | terminal: 'TUGIACO1', 34 | }) 35 | const content = qrPay.build() 36 | expect(content).toBe('00020101021126280010A0000007750110010215477853037045802VN5912TUGIACOMPANY62310315TU GIA COMPUTER0708TUGIACO16304DF44') 37 | }) -------------------------------------------------------------------------------- /src/constants/bank-code.ts: -------------------------------------------------------------------------------- 1 | export enum BankCode { 2 | ABBANK = 'ABB', 3 | ACB = 'ACB', 4 | AGRIBANK = 'AGRIBANK', 5 | BAC_A_BANK = 'BAB', 6 | BAOVIET_BANK = 'BAOVIETBANK', 7 | BANVIET = 'BVB', 8 | BIDC = 'BIDC', 9 | BIDV = 'BID', 10 | CAKE = 'CAKE', 11 | CBBANK = 'VNCB', 12 | CIMB = 'CIMB', 13 | COOP_BANK = 'COOPBANK', 14 | DBS_BANK = 'DBS', 15 | DONG_A_BANK = 'DONGABANK', 16 | EXIMBANK = 'EIB', 17 | GPBANK = 'GPBANK', 18 | HDBANK = 'HDB', 19 | HONGLEONG_BANK = 'HLB', 20 | HSBC = 'HSBC', 21 | IBK_HCM = 'IBKHCM', 22 | IBK_HN = 'IBKHN', 23 | INDOVINA_BANK = 'IVB', 24 | KASIKORN_BANK = 'KBANK', 25 | KIENLONG_BANK = 'KLB', 26 | KOOKMIN_BANK_HCM = 'KBHCM', 27 | KOOKMIN_BANK_HN = 'KBHN', 28 | LPBANK = 'LPB', 29 | LIOBANK = 'LIOBANK', 30 | MBBANK = 'MBB', 31 | MBV = 'MBV', 32 | MSB = 'MSB', 33 | NAM_A_BANK = 'NAB', 34 | NCB = 'NVB', 35 | NONGHYUP_BANK_HN = 'NONGHYUP', 36 | OCB = 'OCB', 37 | /** @deprecated Chuyển giao cho MBBank, đổi tên thành MBV */ 38 | OCEANBANK = 'OCEANBANK', 39 | PGBANK = 'PGB', 40 | PUBLIC_BANK = 'PBVN', 41 | PVCOM_BANK = 'PVCOMBANK', 42 | SACOMBANK = 'STB', 43 | SAIGONBANK = 'SGB', 44 | SCB = 'SCB', 45 | SEA_BANK = 'SSB', 46 | SHB = 'SHB', 47 | SHINHAN_BANK = 'SVB', 48 | STANDARD_CHARTERED_BANK = 'SC', 49 | TECHCOMBANK = 'TCB', 50 | TIMO = 'TIMO', 51 | TPBANK = 'TPB', 52 | UBANK = 'UBANK', 53 | UNITED_OVERSEAS_BANK = 'UOB', 54 | VIB = 'VIB', 55 | VIET_A_BANK = 'VAB', 56 | VIET_BANK = 'VBB', 57 | VIETCOMBANK = 'VCB', 58 | VIETINBANK = 'CTG', 59 | VIKKI = 'VIKKI', 60 | VPBANK = 'VPB', 61 | VRB = 'VRB', 62 | WOORI_BANK = 'WRB', 63 | } 64 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vietnam-qr-pay", 3 | "version": "1.5.0", 4 | "description": "Encode/Decode VietQR and VNPAY-QR", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "build": "rimraf dist && tsc -p tsconfig.build.json", 9 | "lint": "eslint --ext .ts .", 10 | "release": "yarn build && yarn publish", 11 | "test": "jest" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/xuannghia/vietnam-qr-pay.git" 16 | }, 17 | "keywords": [ 18 | "vietqr", 19 | "vnpayqr", 20 | "napas", 21 | "napas247", 22 | "qr-pay" 23 | ], 24 | "author": "xuannghia ", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/xuannghia/vietnam-qr-pay/issues" 28 | }, 29 | "homepage": "https://github.com/xuannghia/vietnam-qr-pay#readme", 30 | "files": [ 31 | "dist" 32 | ], 33 | "devDependencies": { 34 | "@types/jest": "^28.1.3", 35 | "@typescript-eslint/eslint-plugin": "^6.7.2", 36 | "@typescript-eslint/parser": "^6.7.2", 37 | "eslint": "^8.50.0", 38 | "jest": "^28.1.1", 39 | "qrto": "^0.0.3", 40 | "ts-jest": "^28.0.5", 41 | "ts-node": "^10.8.1", 42 | "typescript": "^4.7.4" 43 | }, 44 | "peerDependencies": {}, 45 | "dependencies": {}, 46 | "jest": { 47 | "moduleFileExtensions": [ 48 | "js", 49 | "json", 50 | "ts" 51 | ], 52 | "rootDir": "./", 53 | "testRegex": ".*\\.spec\\.ts$", 54 | "transform": { 55 | "^.+\\.(t|j)s$": "ts-jest" 56 | }, 57 | "testEnvironment": "node" 58 | }, 59 | "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" 60 | } 61 | -------------------------------------------------------------------------------- /src/constants/bank-key.ts: -------------------------------------------------------------------------------- 1 | export enum BankKey { 2 | ABBANK = 'abbank', 3 | ACB = 'acb', 4 | AGRIBANK = 'agribank', 5 | BAC_A_BANK = 'bacabank', 6 | BAOVIET_BANK = 'baoviet', 7 | BANVIET = 'banviet', 8 | BIDC = 'bidc', 9 | BIDV = 'bidv', 10 | CAKE = 'cake', 11 | CBBANK = 'cbbank', 12 | CIMB = 'cimb', 13 | COOP_BANK = 'coopbank', 14 | DBS_BANK = 'dbsbank', 15 | /** @deprecated - Chuyển giao cho HDBank, đổi tên thành Vikki Digital Bank */ 16 | DONG_A_BANK = 'dongabank', 17 | EXIMBANK = 'eximbank', 18 | GPBANK = 'gpbank', 19 | HDBANK = 'hdbank', 20 | HONGLEONG_BANK = 'hongleongbank', 21 | HSBC = 'hsbc', 22 | IBK_HCM = 'ibkhcm', 23 | IBK_HN = 'ibkhn', 24 | INDOVINA_BANK = 'indovinabank', 25 | KASIKORN_BANK = 'kasikorn', 26 | KIENLONG_BANK = 'kienlongbank', 27 | KOOKMIN_BANK_HCM = 'kookminhcm', 28 | KOOKMIN_BANK_HN = 'kookminhn', 29 | /** @deprecated Đổi tên thành Lộc Phát Việt Nam (LPBANK) */ 30 | LIENVIETPOST_BANK = 'lienvietpostbank', 31 | LPBANK = 'lpbank', 32 | LIOBANK = 'liobank', 33 | MBBANK = 'mbbank', 34 | MBV = 'mbv', 35 | MSB = 'msb', 36 | NAM_A_BANK = 'namabank', 37 | NCB = 'ncb', 38 | NONGHYUP_BANK_HN = 'nonghyup', 39 | OCB = 'ocb', 40 | /** @deprecated Chuyển giao cho MBBank, đổi tên thành MBV */ 41 | OCEANBANK = 'oceanbank', 42 | PGBANK = 'pgbank', 43 | PUBLIC_BANK = 'publicbank', 44 | PVCOM_BANK = 'pvcombank', 45 | SACOMBANK = 'sacombank', 46 | SAIGONBANK = 'saigonbank', 47 | SCB = 'scb', 48 | SEA_BANK = 'seabank', 49 | SHB = 'shb', 50 | SHINHAN_BANK = 'shinhanbank', 51 | STANDARD_CHARTERED_BANK = 'standardcharteredbank', 52 | TECHCOMBANK = 'techcombank', 53 | TIMO = 'timo', 54 | TPBANK = 'tpbank', 55 | UBANK = 'ubank', 56 | UNITED_OVERSEAS_BANK = 'uob', 57 | VIB = 'vib', 58 | VIET_A_BANK = 'vietabank', 59 | VIET_BANK = 'vietbank', 60 | VIETCOMBANK = 'vietcombank', 61 | VIETINBANK = 'vietinbank', 62 | VIKKI = 'vikki', 63 | VPBANK = 'vpbank', 64 | VRB = 'vrb', 65 | WOORI_BANK = 'wooribank', 66 | } 67 | -------------------------------------------------------------------------------- /test/test-vnpay-qr.spec.ts: -------------------------------------------------------------------------------- 1 | import { QRProvider, QRProviderGUID } from '../src/constants' 2 | import { QRPay } from '../src/qr-pay' 3 | 4 | test('VNPayQR', () => { 5 | const qrContent = '00020101021126280010A000000775011001087990425204597753037045802VN5909MYPHAMHER6005HANOI62260311MY PHAM HER0707MPHER0163041C50' 6 | const qrPay = new QRPay(qrContent) 7 | expect(qrPay.isValid).toBe(true) 8 | expect(qrPay.version).toBe('01') 9 | expect(qrPay.provider.name).toBe(QRProvider.VNPAY) 10 | expect(qrPay.provider.guid).toBe(QRProviderGUID.VNPAY) 11 | expect(qrPay.additionalData?.store).toBe('MY PHAM HER') 12 | expect(qrPay.additionalData?.terminal).toBe('MPHER01') 13 | expect(qrPay.crc).toBe('1C50') 14 | expect(qrPay.build()).toBe(qrContent) 15 | }) 16 | 17 | test('VNPayQR 2', () => { 18 | const qrContent = '00020101021126280010A000000775011001A80187905204549953037045802VN5907SUNFLY16005HaNoi62290313SUNFLY ONLINE0708SUNFLY016304AE6F' 19 | const qrPay = new QRPay(qrContent) 20 | expect(qrPay.isValid).toBe(true) 21 | expect(qrPay.version).toBe('01') 22 | expect(qrPay.provider.name).toBe(QRProvider.VNPAY) 23 | expect(qrPay.provider.guid).toBe(QRProviderGUID.VNPAY) 24 | expect(qrPay.additionalData?.store).toBe('SUNFLY ONLINE') 25 | expect(qrPay.additionalData?.terminal).toBe('SUNFLY01') 26 | expect(qrPay.crc).toBe('AE6F') 27 | expect(qrPay.build()).toBe(qrContent) 28 | }) 29 | 30 | test('Personal VNPayQR', () => { 31 | const qrPay = new QRPay('00020101021002020103069084010411VNPayWallet071003933571580809Lê Anh Tú09051000010037041107content63042678') 32 | expect(qrPay.provider).toBeDefined() 33 | expect(qrPay.isValid).toBe(true) 34 | expect(qrPay.version).toBe('01') 35 | expect(qrPay.provider.name).toBeUndefined() 36 | expect(qrPay.provider.guid).toBeUndefined() 37 | }) 38 | 39 | test('Invalid CRC VNPayQR', () => { 40 | const qrPay = new QRPay('00020101021126280010A000000775011001087990425204597753037045802VN5909MYPHAMHER6005HANOI62260311MY PHAM HER0707MPHER0163041C55') 41 | expect(qrPay.isValid).toBe(false) 42 | }) 43 | -------------------------------------------------------------------------------- /test/test-vietqr.spec.ts: -------------------------------------------------------------------------------- 1 | import { QRProvider, QRProviderGUID } from '../src/constants' 2 | import { QRPay } from '../src/qr-pay' 3 | 4 | test('VietQR', () => { 5 | const qrContent = '00020101021238530010A0000007270123000697041601092576788590208QRIBFTTA5303704540410005802VN62150811Chuyen tien6304BBB8' 6 | const qrPay = new QRPay(qrContent) 7 | expect(qrPay.isValid).toBe(true) 8 | expect(qrPay.version).toBe('01') 9 | expect(qrPay.provider.name).toBe(QRProvider.VIETQR) 10 | expect(qrPay.provider.guid).toBe(QRProviderGUID.VIETQR) 11 | expect(qrPay.consumer.bankBin).toBe('970416') 12 | expect(qrPay.consumer.bankNumber).toBe('257678859') 13 | expect(qrPay.amount).toBe('1000') 14 | expect(qrPay.build()).toBe(qrContent) 15 | }) 16 | 17 | test('CRC with three-byte', () => { 18 | const qrContent = '00020101021138580010A000000727012800069704070114190304136010180208QRIBFTTA53037045802VN63040283' 19 | const qrPay = new QRPay(qrContent) 20 | expect(qrPay.isValid).toBe(true) 21 | expect(qrPay.version).toBe('01') 22 | expect(qrPay.provider.name).toBe(QRProvider.VIETQR) 23 | expect(qrPay.provider.guid).toBe(QRProviderGUID.VIETQR) 24 | expect(qrPay.consumer.bankBin).toBe('970407') 25 | expect(qrPay.consumer.bankNumber).toBe('19030413601018') 26 | expect(qrPay.build()).toBe(qrContent) 27 | }) 28 | 29 | test('Invalid CRC VietQR ', () => { 30 | const qrPay = new QRPay('00020101021238530010A0000007270123000697041601092576788590208QRIBFTTA5303704540410005802VN62150811Chuyen tien6304BBB5') 31 | expect(qrPay.isValid).toBe(false) 32 | }) 33 | 34 | test('MBBank QR with lowercase CRC', () => { 35 | const qrContent = '00020101021138540010A00000072701240006970422011003523509170208QRIBFTTA53037045802VN630479db' 36 | const qrPay = new QRPay(qrContent) 37 | expect(qrPay.isValid).toBe(true) 38 | expect(qrPay.version).toBe('01') 39 | expect(qrPay.provider.name).toBe(QRProvider.VIETQR) 40 | expect(qrPay.provider.guid).toBe(QRProviderGUID.VIETQR) 41 | expect(qrPay.consumer.bankBin).toBe('970422') 42 | expect(qrPay.consumer.bankNumber).toBe('0352350917') 43 | expect(qrPay.build()?.slice(-4)).toBe(qrContent?.slice(-4).toUpperCase()) 44 | }) 45 | -------------------------------------------------------------------------------- /src/constants/qr-pay.ts: -------------------------------------------------------------------------------- 1 | export enum QRProvider { 2 | VIETQR = 'VIETQR', 3 | VNPAY = 'VNPAY', 4 | } 5 | 6 | export enum QRProviderGUID { 7 | VNPAY = 'A000000775', 8 | VIETQR = 'A000000727' 9 | } 10 | 11 | export enum FieldID { 12 | VERSION = '00', 13 | INIT_METHOD = '01', 14 | VNPAYQR = '26', 15 | VIETQR = '38', 16 | CATEGORY = '52', 17 | CURRENCY = '53', 18 | AMOUNT = '54', 19 | TIP_AND_FEE_TYPE = '55', 20 | TIP_AND_FEE_AMOUNT = '56', 21 | TIP_AND_FEE_PERCENT = '57', 22 | NATION = '58', 23 | MERCHANT_NAME = '59', 24 | CITY = '60', 25 | ZIP_CODE = '61', 26 | ADDITIONAL_DATA = '62', 27 | CRC = '63' 28 | } 29 | 30 | export type EVMCoFieldID = '65' | '66' | '67' | '68' | '69' | '70' | '71' | '72' | '73' | '74' | '75' | '76' | '77' | '78' | '79' 31 | export type UnreservedFieldID = '80' | '81' | '82' | '83' | '84' | '85' | '86' | '87' | '88' | '89' | '90' | '91' | '92' | '93' | '94' | '95' | '96' | '97' | '98' | '99' 32 | 33 | export enum ProviderFieldID { 34 | GUID = '00', 35 | DATA = '01', 36 | SERVICE = '02' 37 | } 38 | 39 | export enum VietQRService { 40 | BY_ACCOUNT_NUMBER = 'QRIBFTTA', // Dịch vụ chuyển nhanh NAPAS247 đến Tài khoản 41 | BY_CARD_NUMBER = 'QRIBFTTC' // Dịch vụ chuyển nhanh NAPAS247 đến Thẻ 42 | } 43 | 44 | export enum VietQRConsumerFieldID { 45 | BANK_BIN = '00', 46 | BANK_NUMBER = '01' 47 | } 48 | 49 | export enum AdditionalDataID { 50 | BILL_NUMBER = '01', // Số hóa đơn 51 | MOBILE_NUMBER = '02', // Số ĐT 52 | STORE_LABEL = '03', // Mã cửa hàng 53 | LOYALTY_NUMBER = '04', // Mã khách hàng thân thiết 54 | REFERENCE_LABEL = '05', // Mã tham chiếu 55 | CUSTOMER_LABEL = '06', // Mã khách hàng 56 | TERMINAL_LABEL = '07', // Mã số điểm bán 57 | PURPOSE_OF_TRANSACTION = '08', // Mục đích giao dịch 58 | ADDITIONAL_CONSUMER_DATA_REQUEST = '09' // Yêu cầu dữ liệu KH bổ sung 59 | } 60 | 61 | export class Provider { 62 | fieldId?: string 63 | name?: QRProvider 64 | guid?: string 65 | service?: string 66 | data?: string 67 | } 68 | 69 | export class AdditionalData { 70 | billNumber?: string 71 | mobileNumber?: string 72 | store?: string 73 | loyaltyNumber?: string 74 | reference?: string 75 | customerLabel?: string 76 | terminal?: string 77 | purpose?: string 78 | dataRequest?: string 79 | } 80 | 81 | export class Consumer { 82 | bankBin?: string 83 | bankNumber?: string 84 | } 85 | 86 | export class Merchant { 87 | id?: string 88 | name?: string 89 | } 90 | -------------------------------------------------------------------------------- /src/crc16.ts: -------------------------------------------------------------------------------- 1 | /* Source: https://github.com/alexgorbatchev/node-crc/blob/master/src/calculators/crc16ccitt.ts */ 2 | 3 | import { stringToUint8Array } from './utils' 4 | 5 | let TABLE: number[] | Int32Array = [ 6 | 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 7 | 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 8 | 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 9 | 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 10 | 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 11 | 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 12 | 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 13 | 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 14 | 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 15 | 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 16 | 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 17 | 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 18 | 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 19 | 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 20 | 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 21 | 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 22 | 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 23 | 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 24 | 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 25 | 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 26 | 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 27 | 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 28 | ] 29 | 30 | if (typeof Int32Array !== 'undefined') { 31 | TABLE = new Int32Array(TABLE) 32 | } 33 | 34 | export const crc16ccitt = (content: string): number => { 35 | const current = stringToUint8Array(content) 36 | let crc = 0xffff 37 | for (let index = 0; index < current.length; index++) { 38 | crc = (TABLE[((crc >> 8) ^ current[index]) & 0xff] ^ (crc << 8)) & 0xffff 39 | } 40 | return crc 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vietnam QR Pay 2 | 3 | Thư viện hỗ trợ encode/decode mã QR của VietQR (QR Ngân hàng, QR Đa năng Momo/ZaloPay) & VNPayQR 4 | 5 | [![npm](https://img.shields.io/npm/v/vietnam-qr-pay.svg)](https://www.npmjs.com/package/vietnam-qr-pay) 6 | [![download](https://img.shields.io/npm/dt/vietnam-qr-pay.svg)](https://www.npmjs.com/package/vietnam-qr-pay) 7 | [![bundlephobia](https://img.shields.io/bundlephobia/minzip/vietnam-qr-pay.svg)](https://bundlephobia.com/package/vietnam-qr-pay) 8 | 9 | ## Install 10 | 11 | ```bash 12 | npm install vietnam-qr-pay 13 | ``` 14 | 15 | 16 | ## Encode - Tạo mã QR 17 | 18 | ### VietQR Tĩnh 19 | ```javascript 20 | 21 | import { QRPay, BanksObject } from 'vietnam-qr-pay'; 22 | 23 | const qrPay = QRPay.initVietQR({ 24 | bankBin: BanksObject.acb.bin, 25 | bankNumber: '257678859', // Số tài khoản 26 | }) 27 | const content = qrPay.build() 28 | 29 | console.log(content) 30 | // 00020101021138530010A0000007270123000697041601092576788590208QRIBFTTA53037045802VN6304AE9F 31 | 32 | ``` 33 | 34 | ### VietQR Động 35 | 36 | ```javascript 37 | import { QRPay, BanksObject } from 'vietnam-qr-pay'; 38 | 39 | const qrPay = QRPay.initVietQR({ 40 | bankBin: BanksObject.acb.bin, 41 | bankNumber: '257678859', // Số tài khoản 42 | amount: '10000', // Số tiền 43 | purpose: 'Chuyen tien', // Nội dung chuyển tiền 44 | }) 45 | const content = qrPay.build() 46 | 47 | console.log(content) 48 | // 00020101021238530010A0000007270123000697041601092576788590208QRIBFTTA53037045405100005802VN62150811Chuyen tien630453E6 49 | 50 | ``` 51 | 52 | ### QR Đa năng của MoMo và ZaloPay 53 | 54 | Hiện tại, QR Đa năng của MoMo và ZaloPay đang thông qua Ngân hàng Bản Việt (BVBank) để nhận tiền. 55 | 56 | Mỗi tài khoản MoMo/ZaloPay sẽ được gán một STK tương ứng tại BVBank. Tiền chuyển đến STK này sẽ được chuyển tiếp đến ví MoMo/ZaloPay. 57 | 58 | Bạn có thể lấy STK này tại trang chi tiết của QR Nhận tiền trong ứng dụng MoMo/ZaloPay. 59 | 60 | #### MoMo 61 | 62 | ```javascript 63 | import { QRPay, BanksObject } from 'vietnam-qr-pay'; 64 | 65 | // Số tài khoản trong ví MoMo 66 | const accountNumber = '99MM24011M34875080' 67 | 68 | const momoQR = QRPay.initVietQR({ 69 | bankBin: BanksObject.banviet.bin, 70 | bankNumber: accountNumber, 71 | // amount: '10000', // Số tiền (không bắt buộc) 72 | // purpose: 'Chuyen tien', // Nội dung (không bắt buộc) 73 | }) 74 | 75 | // Trong mã QR của MoMo có chứa thêm 1 mã tham chiếu tương ứng với STK 76 | momoQR.additionalData.reference = 'MOMOW2W' + accountNumber.slice(10) 77 | 78 | // Mã QR của MoMo có thêm 1 trường ID 80 với giá trị là 3 số cuối của SỐ ĐIỆN THOẠI của tài khoản nhận tiền 79 | momoQR.setUnreservedField('80', '046') 80 | 81 | const content = momoQR.build() 82 | 83 | // 00020101021138620010A00000072701320006970454011899MM24011M348750800208QRIBFTTA53037045802VN62190515MOMOW2W3487508080030466304EBC8 84 | 85 | ``` 86 | 87 | 88 | 89 | #### ZaloPay 90 | 91 | > Trong mã QR của ZaloPay có chứa một số thông tin bổ sung ở trường ID 26. Tuy nhiên chưa rõ chức năng của các thông tin này (có thể là dùng để định danh từng mã QR đc tạo trên hệ thống của ZaloPay). Trong ví dụ dưới sẽ bỏ qua các thông tin này. 92 | 93 | ```javascript 94 | import { QRPay, BanksObject } from 'vietnam-qr-pay'; 95 | 96 | // Số tài khoản trong ví ZaloPay 97 | const accountNumber = '99ZP24009M07248267' 98 | 99 | const zaloPayQR = QRPay.initVietQR({ 100 | bankBin: BanksObject.banviet.bin, 101 | bankNumber: accountNumber, 102 | // amount: '10000', // Số tiền (không bắt buộc) 103 | // purpose: 'Chuyen tien', // Nội dung (không bắt buộc) 104 | }) 105 | 106 | const content = zaloPayQR.build() 107 | // 00020101021138620010A00000072701320006970454011899ZP24009M072482670208QRIBFTTA53037045802VN6304073C 108 | ``` 109 | 110 | 111 | 112 | 113 | ### VNPay 114 | 115 | ```javascript 116 | const qrPay = QRPay.initVNPayQR({ 117 | merchantId: '0102154778', 118 | merchantName: 'TUGIACOMPANY', 119 | store: 'TU GIA COMPUTER', 120 | terminal: 'TUGIACO1', 121 | }) 122 | const content = qrPay.build() 123 | console.log(content) 124 | // 00020101021126280010A0000007750110010531314453037045408210900005802VN5910CELLPHONES62600312CPSHN ONLINE0517021908061613127850705ONLHN0810CellphoneS63047685 125 | 126 | ``` 127 | 128 | 129 | ## Decode mã QR 130 | 131 | ### VietQR 132 | ```javascript 133 | import { QRPay } from 'vietnam-qr-pay'; 134 | 135 | const qrContent = '00020101021238530010A0000007270123000697041601092576788590208QRIBFTTA5303704540410005802VN62150811Chuyen tien6304BBB8' 136 | const qrPay = new QRPay(qrContent); 137 | console.log(qrPay.isValid) // true 138 | console.log(qrPay.provider.name) // VIETQR 139 | console.log(qrPay.consumer.bankBin) // 970416 140 | console.log(qrPay.consumer.bankNumber) // 257678859 141 | console.log(qrPay.amount) // 1000 142 | console.log(qrPay.additionalData.purpose) // Chuyen tien 143 | 144 | ``` 145 | 146 | ### VNPay 147 | ```javascript 148 | import { QRPay } from 'vietnam-qr-pay'; 149 | 150 | const qrContent = '00020101021126280010A0000007750110010531314453037045408210900005802VN5910CELLPHONES62600312CPSHN ONLINE0517021908061613127850705ONLHN0810CellphoneS63047685' 151 | const qrPay = new QRPay(qrContent); 152 | console.log(qrPay.isValid) // true 153 | console.log(qrPay.provider.name) // VNPAY 154 | console.log(qrPay.merchant.merchantId) // 0105313144 155 | console.log(qrPay.amount) // 21090000 156 | console.log(qrPay.additionalData.store) // CPSHN ONLINE 157 | console.log(qrPay.additionalData.terminal) // ONLHN 158 | console.log(qrPay.additionalData.purpose) // CellphoneS 159 | console.log(qrPay.additionalData.reference) // 02190806161312785 160 | 161 | ``` 162 | 163 | 164 | ## `QRPay` class 165 | 166 | 167 | ```javascript 168 | import { QRPay } from 'vietnam-qr-pay'; 169 | ``` 170 | 171 | | Name | Type | Description | 172 | | --- | --- | --- | 173 | | `isValid` | `boolean` | Kiểm tra tính hợp lệ của mã QR | 174 | | `initMethod` | `string` | Phương thức khởi tạo (`11` - QR Tĩnh, `12` - QR động) | 175 | | `provider` | `Provider` | Thông tin nhà cung cấp | 176 | | `merchant` | `Merchant` | Thông tin merchant | 177 | | `consumer` | `Consumer` | Thông tin người thanh toán | 178 | | `amount` | `string` | Số tiền giao dịch | 179 | | `currency` | `string` | Mã tiền tệ (VNĐ: 704) | 180 | | `nation` | `string` | Mã quốc gia | 181 | | `additionalData` | `AdditionalData` | Thông tin bổ sung | 182 | | `crc` | `string` | Mã kiểm tra | 183 | | `build()` | `method` | Tạo lại mã QR mới | 184 | 185 | ### `Provider` class 186 | 187 | Thông tin đơn vị cung cấp mã QR (VietQR, VNPay) 188 | 189 | 190 | | Name | Type | Description | 191 | | --- | --- | --- | 192 | | `guid` | `string` | Mã định danh toàn cầu | 193 | | `name` | `string` | Tên nhà cung cấp | 194 | 195 | ### `Merchant` class 196 | 197 | Thông tin merchant (Đơn vị chấp nhận thanh toán) 198 | 199 | | Name | Type | Description | 200 | | --- | --- | --- | 201 | | `id` | `string` | Mã định danh đơn vị CNTT | 202 | | `name` | `string` | Tên đơn vị CNTT | 203 | 204 | ### `Consumer` class 205 | 206 | Thông tin người thanh toán 207 | 208 | | Name | Type | Description | 209 | | --- | --- | --- | 210 | | `bankBin` | `string` | Mã ngân hàng | 211 | | `bankNumber` | `string` | Số tài khoản | 212 | 213 | ### `AdditionalData` class 214 | 215 | Thông tin bổ sung 216 | 217 | | Name | Type | Description | 218 | | --- | --- | --- | 219 | | `billNumber` | `string` | Số hóa đơn | 220 | | `mobileNumber` | `string` | Số điện thoại di động | 221 | | `store` | `string` | Tên cửa hàng | 222 | | `loyaltyNumber` | `string` | Mã khách hàng thân thiết | 223 | | `reference` | `string` | Mã Tham chiếu | 224 | | `customerLabel` | `string` | Mã khách hàng | 225 | | `terminal` | `string` | Tên điểm bản | 226 | | `purpose` | `string` | Nội dung giao dịch | 227 | 228 | ### `build()` method 229 | 230 | Trả về nội dung mã QR mới 231 | 232 | ```javascript 233 | import { QRPay } from 'vietnam-qr-pay'; 234 | 235 | 236 | const qrContent = '00020101021238530010A0000007270123000697041601092576788590208QRIBFTTA5303704540410005802VN62150811Chuyen tien6304BBB8' 237 | const qrPay = new QRPay(qrContent); 238 | 239 | // qrPay.amount === "10000" 240 | // qrPay.additionalData.purpose === "Chuyen tien" 241 | 242 | qrPay.amount = '999999'; 243 | qrPay.additionalData.purpose = 'Cam on nhe'; 244 | 245 | const newQRContent = qrPay.build(); 246 | /* 247 | 00020101021238530010A0000007270123000697041601092576788590208QRIBFTTA530370454069999995802VN62140810Cam on nhe6304E786 248 | */ 249 | 250 | ``` 251 | -------------------------------------------------------------------------------- /test/test-momo-zalopay.spec.ts: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs' 2 | import { toSVG } from 'qrto' 3 | 4 | import { BanksObject } from '../src' 5 | import { QRPay } from '../src/qr-pay' 6 | 7 | 8 | test('MoMo', () => { 9 | const accountNumber = '99MM24011M34875080' 10 | const momoQR = QRPay.initVietQR({ 11 | bankBin: BanksObject.banviet.bin, 12 | bankNumber: accountNumber, 13 | }) 14 | momoQR.additionalData.reference = 'MOMOW2W' + accountNumber.slice(10) 15 | momoQR.setUnreservedField('80', '046') 16 | // QR Content generated from MoMo app 17 | const content = momoQR.build() 18 | expect(content).toBe('00020101021138620010A00000072701320006970454011899MM24011M348750800208QRIBFTTA53037045802VN62190515MOMOW2W3487508080030466304EBC8') 19 | 20 | const svg = toSVG(content, { 21 | ecLevel: 'L', 22 | style: 'round', 23 | foregroundColor: { 24 | type: 'linear', 25 | colors: ['#d82f8b', '#a50064'] 26 | }, 27 | logo: { 28 | url: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAMAAADQmBKKAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAJcEhZcwAACxMAAAsTAQCanBgAAAL0UExURawgcKsdb/78/ffp8akYa6sgcKkZbP///6seb6sfb60gcaYTaLU4f9aRuOnD2PXm7+jA16sdbrlEh9KHsaoabLtJi64ndO3P4awhcKobbawfcKwfb/fo8asfcKscbqgWaqkXaqkZa6kabKocbawhcaobbrApdv/+/qsebqsbbagVact0pqoZbLQ1fvz3+qcTaP/+//79/blBhqkVaqoabfjr8rU4gN2kxfvz9/DW5a7Teaodbq4ldO/T47Eued6lxvz2+bMwe/rw9tKGsacUablDh7tJivHY5uvJ3LErd7Y6gOnC2L1OjrMyfLIveunF2qwgcd2iw60hca8odctxpMtypfjr89iWvOW30bQ0fdiVu/77/f37/Pry9q0jcq8nde7P4eCsysFYlNuewdWNtvHZ575Pjtyhw+OyzfPg6+S0z+KvzPb+x6cSZ/bm7/7+/t+ox/z4+/35+71Ki79RkKgXa9GEsK4kc+3R4evI27g/heW50tmZvvXk7cRfmMBXkrc9g7EteezM3sx1p815qvHZ5sluovHb6L9TkdiUu6ULY/jt8+3P4Prz97c7gqobbNygwul/6cpvo+nE2dB/rfPd6fTi7Nqav89+rtGBrq0jc8dpn8Ncl8hqn9SMtchroPPf6sltofjt9Pfr89aPuMVimsZmneW40uW609eUuue81KYPZee+1vz1+MZlnMZ9zrc+g8Zjm899rOOzz60hcuvK3btGiMdnnvLc6a8mdPbo8OKxze7S4vbl78x3qO3N39+pydaQuPbm7tudwM56qtSJs/Xj7rxLjOrH2+S20aweb7tHidWMtujA1r1NjdGBr/Lb6Mtxpea71O/V5bU3f814qcRgmfbq8fTh69ubwLpEiMBVkd+nx/nw9dSLtKkYasJblsNel9GFsc58q79UkaYRZ+vM3uCrycFalvnu9Kwdb/v1+NmZvfTi7deRudGDr6sgcaoYa+e91aoaa+Guy9SStqIGXsZrnaYVZqkfbejD2btRiyeeQ7cAAApSSURBVHja7Vp5VBRHHu5heoZu1IR2R53DmWHOnQEGFBDlcd+HglxCQILhVPRx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' 29 | } 30 | }) 31 | fs.writeFileSync(__dirname + '/momo.svg', svg) 32 | }) 33 | 34 | 35 | test('ZaloPay', () => { 36 | const accountNumber = '99ZP24009M07248267' 37 | const zaloPayQR = QRPay.initVietQR({ 38 | bankBin: BanksObject.banviet.bin, 39 | bankNumber: accountNumber, 40 | }) 41 | 42 | const content = zaloPayQR.build() 43 | expect(content).toBe('00020101021138620010A00000072701320006970454011899ZP24009M072482670208QRIBFTTA53037045802VN6304073C') 44 | 45 | const svg = toSVG(content, { 46 | ecLevel: 'L', 47 | marker: { 48 | style: { 49 | outer: 'round', 50 | inner: 'circle', 51 | } 52 | }, 53 | foregroundColor: { 54 | type: 'linear', 55 | colors: ['#0068ff', '#003e99'], 56 | }, 57 | logo: { 58 | url: 'data:image/png;base64,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' 59 | } 60 | }) 61 | fs.writeFileSync(__dirname + '/zalopay.svg', svg) 62 | }) 63 | -------------------------------------------------------------------------------- /src/constants/bank-apps.ts: -------------------------------------------------------------------------------- 1 | import { BankKey } from './bank-key' 2 | 3 | export interface BankApp { 4 | bank: BankKey 5 | scheme?: string 6 | packageId?: string 7 | appStoreId?: string 8 | supportVietQR?: boolean 9 | /** TRUE nếu ứng dụng có hỗ trợ mở deeplink trên web của VNPay */ 10 | supportVNPayQR?: boolean 11 | } 12 | 13 | // List app support VNPayQR deeplink https://sandbox.vnpayment.vn/apis/danh-sach-ngan-hang/ 14 | 15 | export const BankApps: BankApp[] = [ 16 | { 17 | bank: BankKey.ABBANK, 18 | scheme: 'abbankmobile', 19 | packageId: 'com.vnpay.abbank', 20 | appStoreId: 'id1137160023', 21 | supportVietQR: true, 22 | supportVNPayQR: true 23 | }, 24 | { 25 | bank: BankKey.ACB, 26 | scheme: 'acbapp', 27 | packageId: 'mobile.acb.com.vn', 28 | appStoreId: 'id950141024', 29 | supportVietQR: true, 30 | supportVNPayQR: false 31 | }, 32 | { 33 | bank: BankKey.AGRIBANK, 34 | scheme: 'agribankmobile', 35 | packageId: 'com.vnpay.Agribank3g', 36 | appStoreId: 'id935944952', 37 | supportVietQR: true, 38 | supportVNPayQR: true 39 | }, 40 | { 41 | bank: BankKey.BAC_A_BANK, 42 | packageId: 'com.bab.retailUAT', 43 | appStoreId: 'id1441408786', 44 | supportVietQR: false, 45 | supportVNPayQR: false 46 | }, 47 | { 48 | bank: BankKey.BAOVIET_BANK, 49 | scheme: 'baovietmobile', 50 | packageId: 'com.vnpay.bvbank', 51 | appStoreId: 'id1504422967', 52 | supportVietQR: true, 53 | supportVNPayQR: true 54 | }, 55 | { 56 | bank: BankKey.BIDC, 57 | scheme: 'bidcvnmobile', 58 | packageId: 'com.vnpay.bidc', 59 | appStoreId: 'id1043501726', 60 | supportVietQR: false, 61 | supportVNPayQR: true 62 | }, 63 | { 64 | bank: BankKey.BIDV, 65 | scheme: 'bidvsmartbanking', 66 | packageId: 'com.vnpay.bidv', 67 | appStoreId: 'id1061867449', 68 | supportVietQR: true, 69 | supportVNPayQR: true 70 | }, 71 | 72 | { 73 | bank: BankKey.CAKE, 74 | scheme: 'cake.vn', 75 | packageId: 'xyz.be.cake', 76 | appStoreId: 'id1551907051', 77 | supportVietQR: true, 78 | supportVNPayQR: false 79 | }, 80 | { 81 | bank: BankKey.CBBANK, 82 | packageId: 'cbbank.vn.mobile', 83 | appStoreId: 'id1531443181', 84 | supportVietQR: false, 85 | supportVNPayQR: false 86 | }, 87 | { 88 | bank: BankKey.CIMB, 89 | scheme: 'cimb', 90 | packageId: 'vn.cimbbank.octo', 91 | appStoreId: 'id1318127958', 92 | supportVietQR: true, 93 | supportVNPayQR: false 94 | }, 95 | { 96 | bank: BankKey.COOP_BANK, 97 | scheme: 'coopbankmobile', 98 | packageId: 'com.vnpay.coopbank', 99 | appStoreId: 'id1578445811', 100 | supportVietQR: true, 101 | supportVNPayQR: true 102 | }, 103 | { 104 | bank: BankKey.DBS_BANK, 105 | packageId: 'com.dbs.sg.dbsmbanking', 106 | appStoreId: 'id1068403826', 107 | supportVietQR: false, 108 | supportVNPayQR: false 109 | }, 110 | { 111 | bank: BankKey.DONG_A_BANK, 112 | packageId: 'com.dongabank.mobilenternet', 113 | appStoreId: 'id993124125', 114 | supportVietQR: false, 115 | supportVNPayQR: false 116 | }, 117 | { 118 | bank: BankKey.EXIMBANK, 119 | scheme: 'eximbankmobile', 120 | packageId: 'com.vnpay.eximbank', 121 | appStoreId: 'id1242260338', 122 | supportVietQR: true, 123 | supportVNPayQR: true 124 | }, 125 | { 126 | bank: BankKey.GPBANK, 127 | supportVietQR: false, 128 | supportVNPayQR: false 129 | }, 130 | { 131 | bank: BankKey.HDBANK, 132 | scheme: 'hdbankmobile', 133 | packageId: 'com.vnpay.hdbank', 134 | appStoreId: 'id1461658565', 135 | supportVietQR: true, 136 | supportVNPayQR: true 137 | }, 138 | { 139 | bank: BankKey.HONGLEONG_BANK, 140 | packageId: 'my.com.hongleongconnect.mobileconnect', 141 | appStoreId: 'id1446719260', 142 | supportVietQR: false, 143 | supportVNPayQR: false 144 | }, 145 | { 146 | bank: BankKey.HSBC, 147 | packageId: 'vn.hsbc.hsbcvietnam', 148 | appStoreId: 'id1472163155', 149 | supportVietQR: false, 150 | supportVNPayQR: false 151 | }, 152 | { 153 | bank: BankKey.IBK_HCM, 154 | scheme: 'ionebankglobal', 155 | packageId: 'com.ibk.neobanking.mini', 156 | appStoreId: 'id787064809', 157 | supportVietQR: true, 158 | supportVNPayQR: false 159 | }, 160 | { 161 | bank: BankKey.INDOVINA_BANK, 162 | scheme: 'ivbmobilebanking', 163 | packageId: 'com.vnpay.ivb', 164 | appStoreId: 'id1096963960', 165 | supportVietQR: true, 166 | supportVNPayQR: true 167 | }, 168 | { 169 | bank: BankKey.KASIKORN_BANK, 170 | packageId: 'com.kasikornbank.kplus.vn', 171 | appStoreId: 'id1586576195', 172 | supportVietQR: false, 173 | supportVNPayQR: false 174 | }, 175 | { 176 | bank: BankKey.KIENLONG_BANK, 177 | scheme: 'kienlongbankmobilebanking', 178 | packageId: 'com.sunshine.ksbank', 179 | appStoreId: 'id1562823941', 180 | supportVietQR: true, 181 | supportVNPayQR: true 182 | }, 183 | { 184 | bank: BankKey.KOOKMIN_BANK_HCM, 185 | packageId: 'com.kbstar.global', 186 | appStoreId: 'id1542727700', 187 | supportVietQR: false, 188 | supportVNPayQR: false 189 | }, 190 | { 191 | bank: BankKey.LIENVIETPOST_BANK, 192 | scheme: 'lv24h', 193 | packageId: 'vn.com.lpb.lienviet24h', 194 | appStoreId: 'id1488794748', 195 | supportVietQR: true, 196 | supportVNPayQR: false 197 | }, 198 | { 199 | bank: BankKey.LPBANK, 200 | scheme: 'lv24h', 201 | packageId: 'vn.com.lpb.lienviet24h', 202 | appStoreId: 'id1488794748', 203 | supportVietQR: true, 204 | supportVNPayQR: false 205 | }, 206 | { 207 | bank: BankKey.LIOBANK, 208 | scheme: 'lio', 209 | packageId: 'com.ocb.liobank', 210 | appStoreId: 'id6444787281', 211 | supportVietQR: true, 212 | supportVNPayQR: false 213 | }, 214 | { 215 | bank: BankKey.MBBANK, 216 | scheme: 'mbmobile', 217 | packageId: 'com.mbmobile', 218 | appStoreId: 'id1205807363', 219 | supportVietQR: true, 220 | supportVNPayQR: false 221 | }, 222 | { 223 | bank: BankKey.MBV, 224 | scheme: 'oceanbankmobilebanking', 225 | packageId: 'com.vnpay.ocean', 226 | appStoreId: 'id1469028843', 227 | supportVietQR: true, 228 | supportVNPayQR: true 229 | }, 230 | { 231 | bank: BankKey.MSB, 232 | scheme: 'msbmobile', 233 | packageId: 'vn.com.msb.smartBanking', 234 | appStoreId: 'id436134873', 235 | supportVietQR: false, 236 | supportVNPayQR: false 237 | }, 238 | { 239 | bank: BankKey.NAM_A_BANK, 240 | scheme: 'deeplinkapp', 241 | packageId: 'ops.namabank.com.vn', 242 | appStoreId: 'id1456997296', 243 | supportVietQR: true, 244 | supportVNPayQR: false 245 | }, 246 | { 247 | bank: BankKey.NCB, 248 | scheme: 'ncbizimobile', 249 | packageId: 'com.ncb.bank', 250 | appStoreId: 'id1465217154', 251 | supportVietQR: true, 252 | supportVNPayQR: false 253 | }, 254 | { 255 | bank: BankKey.NONGHYUP_BANK_HN, 256 | scheme: 'newnhsmartbanking', 257 | packageId: 'nh.smart.banking', 258 | appStoreId: 'id1444712671', 259 | supportVietQR: true, 260 | supportVNPayQR: false 261 | }, 262 | { 263 | bank: BankKey.OCB, 264 | scheme: 'omniapp', 265 | packageId: 'com.ocb.omniextra', 266 | appStoreId: 'id1358682577', 267 | supportVietQR: true, 268 | supportVNPayQR: false 269 | }, 270 | { 271 | bank: BankKey.OCEANBANK, 272 | scheme: 'oceanbankmobilebanking', 273 | packageId: 'com.vnpay.ocean', 274 | appStoreId: 'id1469028843', 275 | supportVietQR: true, 276 | supportVNPayQR: true 277 | }, 278 | { 279 | bank: BankKey.PGBANK, 280 | packageId: 'pgbankApp.pgbank.com.vn', 281 | appStoreId: 'id1537765475', 282 | supportVietQR: false, 283 | supportVNPayQR: false 284 | }, 285 | { 286 | bank: BankKey.PUBLIC_BANK, 287 | scheme: 'publicbankmobile', 288 | packageId: 'com.vnpay.publicbank', 289 | appStoreId: 'id1573736472', 290 | supportVietQR: true, 291 | supportVNPayQR: false 292 | }, 293 | { 294 | bank: BankKey.PVCOM_BANK, 295 | scheme: 'pvcombankapp', 296 | packageId: 'com.vsii.pvcombank', 297 | appStoreId: 'id957284067', 298 | supportVietQR: true, 299 | supportVNPayQR: false 300 | }, 301 | { 302 | bank: BankKey.SACOMBANK, 303 | scheme: 'sacombankmobile', 304 | packageId: 'src.com.sacombank', 305 | appStoreId: 'id885814869', 306 | supportVietQR: true, 307 | supportVNPayQR: false 308 | }, 309 | { 310 | bank: BankKey.SAIGONBANK, 311 | scheme: 'Sgbmobile', 312 | packageId: 'com.vnpay.sgbank', 313 | appStoreId: 'id1481832587', 314 | supportVietQR: true, 315 | supportVNPayQR: true 316 | }, 317 | { 318 | bank: BankKey.SCB, 319 | scheme: 'scbmobilebanking', 320 | packageId: 'com.vnpay.SCB', 321 | appStoreId: 'id954973621', 322 | supportVietQR: true, 323 | supportVNPayQR: true 324 | }, 325 | { 326 | bank: BankKey.SEA_BANK, 327 | scheme: 'seabankmobile', 328 | packageId: 'vn.com.seabank.mb1', 329 | appStoreId: 'id846407152', 330 | supportVietQR: true, 331 | supportVNPayQR: false 332 | }, 333 | { 334 | bank: BankKey.SHB, 335 | scheme: 'shbmobile', 336 | packageId: 'vn.shb.mbanking', 337 | appStoreId: 'id538278798', 338 | supportVietQR: true, 339 | supportVNPayQR: true 340 | }, 341 | { 342 | bank: BankKey.SHINHAN_BANK, 343 | scheme: 'shinhanglbvnbank', 344 | packageId: 'com.shinhan.global.vn.bank', 345 | appStoreId: 'id1071033810', 346 | supportVietQR: true, 347 | supportVNPayQR: true 348 | }, 349 | { 350 | bank: BankKey.STANDARD_CHARTERED_BANK, 351 | packageId: 'com.sc.mobilebanking.vn', 352 | appStoreId: 'id1146741999', 353 | supportVietQR: false, 354 | supportVNPayQR: false 355 | }, 356 | { 357 | bank: BankKey.TECHCOMBANK, 358 | scheme: 'tcb', 359 | packageId: 'vn.com.techcombank.bb.app', 360 | appStoreId: 'id1548623362', 361 | supportVietQR: true, 362 | supportVNPayQR: false 363 | }, 364 | { 365 | bank: BankKey.TIMO, 366 | scheme: 'plus', 367 | packageId: 'io.lifestyle.plus', 368 | appStoreId: 'id1521230347', 369 | supportVietQR: true, 370 | supportVNPayQR: false 371 | }, 372 | { 373 | bank: BankKey.TPBANK, 374 | scheme: 'tpbankmobile', 375 | packageId: 'com.tpbankquickpay', 376 | appStoreId: 'id1292194225', 377 | supportVietQR: false, 378 | supportVNPayQR: false 379 | }, 380 | { 381 | bank: BankKey.TPBANK, 382 | scheme: 'hydro', 383 | packageId: 'com.tpb.mb.gprsandroid', 384 | appStoreId: 'id450464147', 385 | supportVietQR: true, 386 | supportVNPayQR: false 387 | }, 388 | { 389 | bank: BankKey.UBANK, 390 | packageId: 'vn.vpbank.ubank', 391 | appStoreId: 'id1529056628', 392 | supportVietQR: false, 393 | supportVNPayQR: false 394 | }, 395 | { 396 | bank: BankKey.UNITED_OVERSEAS_BANK, 397 | scheme: 'mightyapp', 398 | packageId: 'com.uob.mightyvn', 399 | appStoreId: 'id1174327324', 400 | supportVietQR: true, 401 | supportVNPayQR: false 402 | }, 403 | { 404 | bank: BankKey.VIB, 405 | scheme: 'myvib2', 406 | packageId: 'com.vib.myvib2', 407 | appStoreId: 'id1626624790', 408 | supportVietQR: true, 409 | supportVNPayQR: false 410 | }, 411 | { 412 | bank: BankKey.VIET_A_BANK, 413 | scheme: 'vabmobilebanking', 414 | packageId: 'phn.com.vn.mb', 415 | appStoreId: 'id910897337', 416 | supportVietQR: true, 417 | supportVNPayQR: true 418 | }, 419 | { 420 | bank: BankKey.VIET_BANK, 421 | scheme: 'vietbankmobilebanking', 422 | packageId: 'com.vnpay.vietbank', 423 | appStoreId: 'id1461658565', 424 | supportVietQR: true, 425 | supportVNPayQR: true 426 | }, 427 | { 428 | bank: BankKey.BANVIET, 429 | scheme: 'bvbankdigimi', 430 | packageId: 'vn.banvietbank.mobilebanking', 431 | appStoreId: 'id1526444697', 432 | supportVietQR: true, 433 | supportVNPayQR: false 434 | }, 435 | { 436 | bank: BankKey.VIETCOMBANK, 437 | scheme: 'vietcombankmobile', 438 | packageId: 'com.VCB', 439 | appStoreId: 'id561433133', 440 | supportVietQR: true, 441 | supportVNPayQR: true 442 | }, 443 | { 444 | bank: BankKey.VIETINBANK, 445 | scheme: 'vietinbankmobile', 446 | packageId: 'com.vietinbank.ipay', 447 | appStoreId: 'id689963454', 448 | supportVietQR: true, 449 | supportVNPayQR: true 450 | }, 451 | { 452 | bank: BankKey.VIKKI, 453 | scheme: 'vikki', 454 | packageId: 'com.finx.vikki', 455 | appStoreId: 'id6471952024', 456 | supportVietQR: true, 457 | supportVNPayQR: false 458 | }, 459 | { 460 | bank: BankKey.VPBANK, 461 | scheme: 'vpbankneo', 462 | packageId: 'com.vnpay.vpbankonline', 463 | appStoreId: 'id1209349510', 464 | supportVietQR: true, 465 | supportVNPayQR: false 466 | }, 467 | { 468 | bank: BankKey.VRB, 469 | supportVietQR: false, 470 | supportVNPayQR: false 471 | }, 472 | { 473 | bank: BankKey.WOORI_BANK, 474 | scheme: 'wvbs', 475 | packageId: 'vn.com.woori.smart', 476 | appStoreId: 'id1501785125', 477 | supportVietQR: true, 478 | supportVNPayQR: false 479 | } 480 | ] 481 | -------------------------------------------------------------------------------- /src/qr-pay.ts: -------------------------------------------------------------------------------- 1 | import { FieldID, QRProvider, VietQRConsumerFieldID, Consumer, AdditionalDataID, Provider, AdditionalData, QRProviderGUID, ProviderFieldID, Merchant, VietQRService, UnreservedFieldID, EVMCoFieldID } from './constants/qr-pay' 2 | import { crc16ccitt } from './crc16' 3 | export class QRPay { 4 | isValid = true 5 | version: string 6 | initMethod: string 7 | provider: Provider 8 | merchant: Merchant 9 | consumer: Consumer 10 | category?: string 11 | currency?: string 12 | amount?: string 13 | tipAndFeeType?: string 14 | tipAndFeeAmount?: string 15 | tipAndFeePercent?: string 16 | nation?: string 17 | city?: string 18 | zipCode?: string 19 | additionalData: AdditionalData 20 | crc?: string 21 | 22 | EVMCo?: Record 23 | unreserved?: Record 24 | 25 | constructor(content?: string) { 26 | this.provider = new Provider() 27 | this.consumer = new Consumer() 28 | this.merchant = new Merchant() 29 | this.additionalData = new AdditionalData() 30 | this.parse(content ?? '') 31 | } 32 | 33 | public parse(content: string): void { 34 | if (content.length < 4) return this.invalid() 35 | // verify CRC 36 | const crcValid = QRPay.verifyCRC(content) 37 | if (!crcValid) return this.invalid() 38 | // parse content 39 | this.parseRootContent(content) 40 | } 41 | 42 | public build(): string { 43 | const version = QRPay.genFieldData(FieldID.VERSION, this.version ?? '01') 44 | const initMethod = QRPay.genFieldData(FieldID.INIT_METHOD, this.initMethod ?? '11') 45 | 46 | const guid = QRPay.genFieldData(ProviderFieldID.GUID, this.provider.guid) 47 | 48 | let providerDataContent = '' 49 | if (this.provider.guid === QRProviderGUID.VIETQR) { 50 | const bankBin = QRPay.genFieldData(VietQRConsumerFieldID.BANK_BIN, this.consumer.bankBin) 51 | const bankNumber = QRPay.genFieldData(VietQRConsumerFieldID.BANK_NUMBER, this.consumer.bankNumber) 52 | providerDataContent = bankBin + bankNumber 53 | } else if (this.provider.guid === QRProviderGUID.VNPAY) { 54 | providerDataContent = this.merchant.id ?? '' 55 | } else { 56 | providerDataContent = this.provider.data ?? '' 57 | } 58 | const provider = QRPay.genFieldData(ProviderFieldID.DATA, providerDataContent) 59 | const service = QRPay.genFieldData(ProviderFieldID.SERVICE, this.provider.service) 60 | const providerData = QRPay.genFieldData(this.provider.fieldId, guid + provider + service) 61 | 62 | const category = QRPay.genFieldData(FieldID.CATEGORY, this.category) 63 | const currency = QRPay.genFieldData(FieldID.CURRENCY, this.currency ?? '704') 64 | const amountStr = QRPay.genFieldData(FieldID.AMOUNT, this.amount) 65 | const tipAndFeeType = QRPay.genFieldData(FieldID.TIP_AND_FEE_TYPE, this.tipAndFeeType) 66 | const tipAndFeeAmount = QRPay.genFieldData(FieldID.TIP_AND_FEE_AMOUNT, this.tipAndFeeAmount) 67 | const tipAndFeePercent = QRPay.genFieldData(FieldID.TIP_AND_FEE_PERCENT, this.tipAndFeePercent) 68 | const nation = QRPay.genFieldData(FieldID.NATION, this.nation ?? 'VN') 69 | const merchantName = QRPay.genFieldData(FieldID.MERCHANT_NAME, this.merchant.name) 70 | const city = QRPay.genFieldData(FieldID.CITY, this.city) 71 | const zipCode = QRPay.genFieldData(FieldID.ZIP_CODE, this.zipCode) 72 | 73 | const buildNumber = QRPay.genFieldData(AdditionalDataID.BILL_NUMBER, this.additionalData.billNumber) 74 | const mobileNumber = QRPay.genFieldData(AdditionalDataID.MOBILE_NUMBER, this.additionalData.mobileNumber) 75 | const storeLabel = QRPay.genFieldData(AdditionalDataID.STORE_LABEL, this.additionalData.store) 76 | const loyaltyNumber = QRPay.genFieldData(AdditionalDataID.LOYALTY_NUMBER, this.additionalData.loyaltyNumber) 77 | const reference = QRPay.genFieldData(AdditionalDataID.REFERENCE_LABEL, this.additionalData.reference) 78 | const customerLabel = QRPay.genFieldData(AdditionalDataID.CUSTOMER_LABEL, this.additionalData.customerLabel) 79 | const terminal = QRPay.genFieldData(AdditionalDataID.TERMINAL_LABEL, this.additionalData.terminal) 80 | const purpose = QRPay.genFieldData(AdditionalDataID.PURPOSE_OF_TRANSACTION, this.additionalData.purpose) 81 | const dataRequest = QRPay.genFieldData(AdditionalDataID.ADDITIONAL_CONSUMER_DATA_REQUEST, this.additionalData.dataRequest) 82 | 83 | const additionalDataContent = buildNumber + mobileNumber + storeLabel + loyaltyNumber + reference + customerLabel + terminal + purpose + dataRequest 84 | const additionalData = QRPay.genFieldData(FieldID.ADDITIONAL_DATA, additionalDataContent) 85 | 86 | const EVMCoContent = Object.keys(this.EVMCo ?? {}).sort().map(key => QRPay.genFieldData(key, this.EVMCo?.[key])).join('') 87 | const unreservedContent = Object.keys(this.unreserved ?? {}).sort().map(key => QRPay.genFieldData(key, this.unreserved?.[key])).join('') 88 | 89 | const content = `${version}${initMethod}${providerData}${category}${currency}${amountStr}${tipAndFeeType}${tipAndFeeAmount}${tipAndFeePercent}${nation}${merchantName}${city}${zipCode}${additionalData}${EVMCoContent}${unreservedContent}${FieldID.CRC}04` 90 | const crc = QRPay.genCRCCode(content) 91 | return content + crc 92 | } 93 | 94 | public static initVietQR (options: { bankBin: string, bankNumber: string, amount?: string, purpose?: string, service?: VietQRService }): QRPay { 95 | const qr = new QRPay() 96 | qr.initMethod = options.amount ? '12' : '11' 97 | qr.provider.fieldId = FieldID.VIETQR 98 | qr.provider.guid = QRProviderGUID.VIETQR 99 | qr.provider.name = QRProvider.VIETQR 100 | qr.provider.service = options.service || VietQRService.BY_ACCOUNT_NUMBER 101 | qr.consumer.bankBin = options.bankBin 102 | qr.consumer.bankNumber = options.bankNumber 103 | qr.amount = options.amount 104 | qr.additionalData.purpose = options.purpose 105 | return qr 106 | } 107 | 108 | public static initVNPayQR (options: { 109 | merchantId: string, 110 | merchantName: string, 111 | store: string, 112 | terminal: string, 113 | // additional data 114 | amount?: string, 115 | purpose?: string, 116 | billNumber?: string 117 | mobileNumber?: string, 118 | loyaltyNumber?: string, 119 | reference?: string, 120 | customerLabel?: string, 121 | }): QRPay { 122 | const qr = new QRPay() 123 | qr.merchant.id = options.merchantId 124 | qr.merchant.name = options.merchantName 125 | qr.provider.fieldId = FieldID.VNPAYQR 126 | qr.provider.guid = QRProviderGUID.VNPAY 127 | qr.provider.name = QRProvider.VNPAY 128 | qr.amount = options.amount 129 | qr.additionalData.purpose = options.purpose 130 | qr.additionalData.billNumber = options.billNumber 131 | qr.additionalData.mobileNumber = options.mobileNumber 132 | qr.additionalData.store = options.store 133 | qr.additionalData.terminal = options.terminal 134 | qr.additionalData.loyaltyNumber = options.loyaltyNumber 135 | qr.additionalData.reference = options.reference 136 | qr.additionalData.customerLabel = options.customerLabel 137 | return qr 138 | } 139 | 140 | public setEVMCoField (id: EVMCoFieldID, value: string): void { 141 | if (!this.unreserved) this.unreserved = {} 142 | this.unreserved[id] = value 143 | } 144 | 145 | public setUnreservedField (id: UnreservedFieldID, value: string): void { 146 | if (!this.unreserved) this.unreserved = {} 147 | this.unreserved[id] = value 148 | } 149 | 150 | private parseRootContent (content: string): void { 151 | const { id, length, value, nextValue } = QRPay.sliceContent(content) 152 | if (value.length !== length) return this.invalid() 153 | switch (id) { 154 | case FieldID.VERSION: 155 | this.version = value 156 | break 157 | case FieldID.INIT_METHOD: 158 | this.initMethod = value 159 | break 160 | case FieldID.VIETQR: 161 | case FieldID.VNPAYQR: 162 | this.provider.fieldId = id 163 | this.parseProviderInfo(value) 164 | break 165 | case FieldID.CATEGORY: 166 | this.category = value 167 | break 168 | case FieldID.CURRENCY: 169 | this.currency = value 170 | break 171 | case FieldID.AMOUNT: 172 | this.amount = value 173 | break 174 | case FieldID.TIP_AND_FEE_TYPE: 175 | this.tipAndFeeType = value 176 | break 177 | case FieldID.TIP_AND_FEE_AMOUNT: 178 | this.tipAndFeeAmount = value 179 | break 180 | case FieldID.TIP_AND_FEE_PERCENT: 181 | this.tipAndFeePercent = value 182 | break 183 | case FieldID.NATION: 184 | this.nation = value 185 | break 186 | case FieldID.MERCHANT_NAME: 187 | this.merchant.name = value 188 | break 189 | case FieldID.CITY: 190 | this.city = value 191 | break 192 | case FieldID.ZIP_CODE: 193 | this.zipCode = value 194 | break 195 | case FieldID.ADDITIONAL_DATA: 196 | this.parseAdditionalData(value) 197 | break 198 | case FieldID.CRC: 199 | this.crc = value 200 | break 201 | default: 202 | const idNum = Number(id) 203 | if (idNum >= 65 && idNum <= 79) { 204 | if (!this.EVMCo) this.EVMCo = {} 205 | this.EVMCo[id] = value 206 | } else if (idNum >= 80 && idNum <= 99) { 207 | if (!this.unreserved) this.unreserved = {} 208 | this.unreserved[id] = value 209 | } 210 | break 211 | } 212 | if (nextValue.length > 4) this.parseRootContent(nextValue) 213 | } 214 | 215 | private parseProviderInfo (content: string): void { 216 | const { id, value, nextValue } = QRPay.sliceContent(content) 217 | switch (id) { 218 | case ProviderFieldID.GUID: 219 | this.provider.guid = value 220 | break 221 | case ProviderFieldID.DATA: 222 | if (this.provider.guid === QRProviderGUID.VNPAY) { 223 | this.provider.name = QRProvider.VNPAY 224 | this.merchant.id = value 225 | } else if (this.provider.guid === QRProviderGUID.VIETQR) { 226 | this.provider.name = QRProvider.VIETQR 227 | this.parseVietQRConsumer(value) 228 | } 229 | this.provider.data = value 230 | break 231 | case ProviderFieldID.SERVICE: 232 | this.provider.service = value 233 | break 234 | default: 235 | break 236 | } 237 | if (nextValue.length > 4) this.parseProviderInfo(nextValue) 238 | } 239 | 240 | private parseVietQRConsumer (content: string): void { 241 | const { id, value, nextValue } = QRPay.sliceContent(content) 242 | switch (id) { 243 | case VietQRConsumerFieldID.BANK_BIN: 244 | this.consumer.bankBin = value 245 | break 246 | case VietQRConsumerFieldID.BANK_NUMBER: 247 | this.consumer.bankNumber = value 248 | break 249 | default: 250 | break 251 | } 252 | if (nextValue.length > 4) this.parseVietQRConsumer(nextValue) 253 | } 254 | 255 | private parseAdditionalData (content: string): void { 256 | const { id, value, nextValue } = QRPay.sliceContent(content) 257 | switch (id) { 258 | case AdditionalDataID.BILL_NUMBER: 259 | this.additionalData.billNumber = value 260 | break 261 | case AdditionalDataID.MOBILE_NUMBER: 262 | this.additionalData.mobileNumber = value 263 | break 264 | case AdditionalDataID.STORE_LABEL: 265 | this.additionalData.store = value 266 | break 267 | case AdditionalDataID.LOYALTY_NUMBER: 268 | this.additionalData.loyaltyNumber = value 269 | break 270 | case AdditionalDataID.REFERENCE_LABEL: 271 | this.additionalData.reference = value 272 | break 273 | case AdditionalDataID.CUSTOMER_LABEL: 274 | this.additionalData.customerLabel = value 275 | break 276 | case AdditionalDataID.TERMINAL_LABEL: 277 | this.additionalData.terminal = value 278 | break 279 | case AdditionalDataID.PURPOSE_OF_TRANSACTION: 280 | this.additionalData.purpose = value 281 | break 282 | case AdditionalDataID.ADDITIONAL_CONSUMER_DATA_REQUEST: 283 | this.additionalData.dataRequest = value 284 | break 285 | default: 286 | break 287 | } 288 | if (nextValue.length > 4) this.parseAdditionalData(nextValue) 289 | } 290 | 291 | private static verifyCRC (content: string): boolean { 292 | const checkContent = content.slice(0, -4) 293 | const crcCode = content.slice(-4).toUpperCase() 294 | 295 | const genCrcCode = QRPay.genCRCCode(checkContent) 296 | return crcCode === genCrcCode 297 | } 298 | 299 | public static genCRCCode (content: string): string { 300 | const crcCode: string = crc16ccitt(content).toString(16).toUpperCase() 301 | return `0000${crcCode}`.slice(-4) 302 | } 303 | 304 | private static sliceContent (content: string): { id: string, length: number, value: string, nextValue: string } { 305 | const id = content.slice(0, 2) 306 | const length = Number(content.slice(2, 4)) 307 | const value = content.slice(4, 4 + length) 308 | const nextValue = content.slice(4 + length) 309 | return { id, length, value, nextValue } 310 | } 311 | 312 | private invalid (): void { 313 | this.isValid = false 314 | } 315 | 316 | private static genFieldData (id?: string, value?: string): string { 317 | const fieldId = id ?? '' 318 | const fieldValue = value ?? '' 319 | const idLen = fieldId.length 320 | if (idLen !== 2 || fieldValue.length <= 0) return '' 321 | const length = `00${fieldValue.length}`.slice(-2) 322 | return `${fieldId}${length}${fieldValue}` 323 | } 324 | } 325 | -------------------------------------------------------------------------------- /src/constants/banks.ts: -------------------------------------------------------------------------------- 1 | import { BankCode } from './bank-code' 2 | import { BankKey } from './bank-key' 3 | 4 | export interface Bank { 5 | key: BankKey 6 | code: BankCode 7 | name: string 8 | shortName: string 9 | bin: string 10 | vietQRStatus: number 11 | lookupSupported?: number 12 | swiftCode?: string | null 13 | keywords?: string 14 | deprecated?: boolean 15 | } 16 | 17 | export enum VietQRStatus { 18 | NOT_SUPPORTED = -1, 19 | RECEIVE_ONLY = 0, 20 | TRANSFER_SUPPORTED = 1 21 | } 22 | 23 | export const BanksObject: Record = { 24 | [BankKey.ABBANK]: { 25 | key: BankKey.ABBANK, 26 | code: BankCode.ABBANK, 27 | name: 'Ngân hàng TMCP An Bình', 28 | bin: '970425', 29 | shortName: 'AB Bank', 30 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 31 | lookupSupported: 1, 32 | swiftCode: 'ABBKVNVX', 33 | keywords: 'anbinh' 34 | }, 35 | [BankKey.ACB]: { 36 | key: BankKey.ACB, 37 | code: BankCode.ACB, 38 | name: 'Ngân hàng TMCP Á Châu', 39 | bin: '970416', 40 | shortName: 'ACB', 41 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 42 | lookupSupported: 1, 43 | swiftCode: 'ASCBVNVX', 44 | keywords: 'achau' 45 | }, 46 | [BankKey.AGRIBANK]: { 47 | key: BankKey.AGRIBANK, 48 | code: BankCode.AGRIBANK, 49 | name: 'Ngân hàng Nông nghiệp và Phát triển Nông thôn Việt Nam', 50 | bin: '970405', 51 | shortName: 'Agribank', 52 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 53 | lookupSupported: 1, 54 | swiftCode: 'VBAAVNVX', 55 | keywords: 'nongnghiep, nongthon, agribank, agri' 56 | }, 57 | [BankKey.BAC_A_BANK]: { 58 | key: BankKey.BAC_A_BANK, 59 | code: BankCode.BAC_A_BANK, 60 | name: 'Ngân hàng TMCP Bắc Á', 61 | bin: '970409', 62 | shortName: 'BacA Bank', 63 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 64 | lookupSupported: 1, 65 | swiftCode: 'NASCVNVX', 66 | keywords: 'baca, NASB' 67 | }, 68 | [BankKey.BAOVIET_BANK]: { 69 | key: BankKey.BAOVIET_BANK, 70 | code: BankCode.BAOVIET_BANK, 71 | name: 'Ngân hàng TMCP Bảo Việt', 72 | bin: '970438', 73 | shortName: 'BaoViet Bank', 74 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 75 | lookupSupported: 1, 76 | swiftCode: 'BVBVVNVX', 77 | keywords: 'baoviet, BVB' 78 | }, 79 | [BankKey.BANVIET]: { 80 | key: BankKey.BANVIET, 81 | code: BankCode.BANVIET, 82 | name: 'Ngân hàng TMCP Bản Việt', 83 | bin: '970454', 84 | shortName: 'BVBank', 85 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 86 | lookupSupported: 1, 87 | swiftCode: 'VCBCVNVX', 88 | keywords: 'banviet, vietcapitalbank' 89 | }, 90 | [BankKey.BIDC]: { 91 | key: BankKey.BIDC, 92 | code: BankCode.BIDC, 93 | name: 'Ngân hàng TMCP Đầu tư và Phát triển Campuchia', 94 | bin: '', 95 | shortName: 'BIDC', 96 | vietQRStatus: VietQRStatus.NOT_SUPPORTED 97 | }, 98 | [BankKey.BIDV]: { 99 | key: BankKey.BIDV, 100 | code: BankCode.BIDV, 101 | name: 'Ngân hàng TMCP Đầu tư và Phát triển Việt Nam', 102 | bin: '970418', 103 | shortName: 'BIDV', 104 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 105 | lookupSupported: 1, 106 | swiftCode: 'BIDVVNVX' 107 | }, 108 | [BankKey.CAKE]: { 109 | key: BankKey.CAKE, 110 | code: BankCode.CAKE, 111 | name: 'Ngân hàng số CAKE by VPBank - Ngân hàng TMCP Việt Nam Thịnh Vượng', 112 | bin: '546034', 113 | shortName: 'CAKE by VPBank', 114 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 115 | lookupSupported: 1, 116 | swiftCode: null 117 | }, 118 | [BankKey.CBBANK]: { 119 | key: BankKey.CBBANK, 120 | code: BankCode.CBBANK, 121 | name: 'Ngân hàng Thương mại TNHH MTV Xây dựng Việt Nam', 122 | bin: '970444', 123 | shortName: 'CB Bank', 124 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 125 | lookupSupported: 1, 126 | swiftCode: 'GTBAVNVX', 127 | keywords: 'xaydungvn, xaydung' 128 | }, 129 | [BankKey.CIMB]: { 130 | key: BankKey.CIMB, 131 | code: BankCode.CIMB, 132 | name: 'Ngân hàng TNHH MTV CIMB Việt Nam', 133 | bin: '422589', 134 | shortName: 'CIMB Bank', 135 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 136 | lookupSupported: 1, 137 | swiftCode: 'CIBBVNVN', 138 | keywords: 'cimbvn' 139 | }, 140 | [BankKey.COOP_BANK]: { 141 | key: BankKey.COOP_BANK, 142 | code: BankCode.COOP_BANK, 143 | name: 'Ngân hàng Hợp tác xã Việt Nam', 144 | bin: '970446', 145 | shortName: 'Co-op Bank', 146 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 147 | lookupSupported: 1, 148 | swiftCode: null, 149 | keywords: 'hoptacxa, coop' 150 | }, 151 | [BankKey.DBS_BANK]: { 152 | key: BankKey.DBS_BANK, 153 | code: BankCode.DBS_BANK, 154 | name: 'NH TNHH MTV Phát triển Singapore - Chi nhánh TP. Hồ Chí Minh', 155 | bin: '796500', 156 | shortName: 'DBS Bank', 157 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 158 | lookupSupported: 0, 159 | swiftCode: 'DBSSVNVX', 160 | keywords: 'dbshcm' 161 | }, 162 | [BankKey.DONG_A_BANK]: { 163 | key: BankKey.DONG_A_BANK, 164 | code: BankCode.DONG_A_BANK, 165 | name: 'Ngân hàng TMCP Đông Á', 166 | bin: '970406', 167 | shortName: 'DongA Bank', 168 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 169 | lookupSupported: 1, 170 | swiftCode: 'EACBVNVX', 171 | keywords: 'donga, DAB' 172 | }, 173 | [BankKey.EXIMBANK]: { 174 | key: BankKey.EXIMBANK, 175 | code: BankCode.EXIMBANK, 176 | name: 'Ngân hàng TMCP Xuất Nhập khẩu Việt Nam', 177 | bin: '970431', 178 | shortName: 'Eximbank', 179 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 180 | lookupSupported: 1, 181 | swiftCode: 'EBVIVNVX' 182 | }, 183 | [BankKey.GPBANK]: { 184 | key: BankKey.GPBANK, 185 | code: BankCode.GPBANK, 186 | name: 'Ngân hàng Thương mại TNHH MTV Dầu Khí Toàn Cầu', 187 | bin: '970408', 188 | shortName: 'GPBank', 189 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 190 | lookupSupported: 1, 191 | swiftCode: 'GBNKVNVX', 192 | keywords: 'daukhi' 193 | }, 194 | [BankKey.HDBANK]: { 195 | key: BankKey.HDBANK, 196 | code: BankCode.HDBANK, 197 | name: 'Ngân hàng TMCP Phát triển TP. Hồ Chí Minh', 198 | bin: '970437', 199 | shortName: 'HDBank', 200 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 201 | lookupSupported: 1, 202 | swiftCode: 'HDBCVNVX' 203 | }, 204 | [BankKey.HONGLEONG_BANK]: { 205 | key: BankKey.HONGLEONG_BANK, 206 | code: BankCode.HONGLEONG_BANK, 207 | name: 'Ngân hàng TNHH MTV Hong Leong Việt Nam', 208 | bin: '970442', 209 | shortName: 'HongLeong Bank', 210 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 211 | lookupSupported: 1, 212 | swiftCode: 'HLBBVNVX', 213 | keywords: 'HLBVN' 214 | }, 215 | [BankKey.HSBC]: { 216 | key: BankKey.HSBC, 217 | code: BankCode.HSBC, 218 | name: 'Ngân hàng TNHH MTV HSBC (Việt Nam)', 219 | bin: '458761', 220 | shortName: 'HSBC Vietnam', 221 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 222 | lookupSupported: 1, 223 | swiftCode: 'HSBCVNVX' 224 | }, 225 | [BankKey.IBK_HCM]: { 226 | key: BankKey.IBK_HCM, 227 | code: BankCode.IBK_HCM, 228 | name: 'Ngân hàng Công nghiệp Hàn Quốc - Chi nhánh TP. Hồ Chí Minh', 229 | bin: '970456', 230 | shortName: 'IBK HCM', 231 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 232 | lookupSupported: 0, 233 | swiftCode: null, 234 | keywords: 'congnghiep' 235 | }, 236 | [BankKey.IBK_HN]: { 237 | key: BankKey.IBK_HN, 238 | code: BankCode.IBK_HN, 239 | name: 'Ngân hàng Công nghiệp Hàn Quốc - Chi nhánh Hà Nội', 240 | bin: '970455', 241 | shortName: 'IBK HN', 242 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 243 | lookupSupported: 0, 244 | swiftCode: null, 245 | keywords: 'congnghiep' 246 | }, 247 | [BankKey.INDOVINA_BANK]: { 248 | key: BankKey.INDOVINA_BANK, 249 | code: BankCode.INDOVINA_BANK, 250 | name: 'Ngân hàng TNHH Indovina', 251 | bin: '970434', 252 | shortName: 'Indovina Bank', 253 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 254 | lookupSupported: 1, 255 | swiftCode: null 256 | }, 257 | [BankKey.KASIKORN_BANK]: { 258 | key: BankKey.KASIKORN_BANK, 259 | code: BankCode.KASIKORN_BANK, 260 | name: 'Ngân hàng Đại chúng TNHH KASIKORNBANK - CN TP. Hồ Chí Minh', 261 | bin: '668888', 262 | shortName: 'Kasikornbank', 263 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 264 | lookupSupported: 1, 265 | swiftCode: 'KASIVNVX' 266 | }, 267 | [BankKey.KIENLONG_BANK]: { 268 | key: BankKey.KIENLONG_BANK, 269 | code: BankCode.KIENLONG_BANK, 270 | name: 'Ngân hàng TMCP Kiên Long', 271 | bin: '970452', 272 | shortName: 'KienlongBank', 273 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 274 | lookupSupported: 1, 275 | swiftCode: 'KLBKVNVX' 276 | }, 277 | [BankKey.KOOKMIN_BANK_HCM]: { 278 | key: BankKey.KOOKMIN_BANK_HCM, 279 | code: BankCode.KOOKMIN_BANK_HCM, 280 | name: 'Ngân hàng Kookmin - Chi nhánh TP. Hồ Chí Minh', 281 | bin: '970463', 282 | shortName: 'Kookmin Bank HCM', 283 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 284 | lookupSupported: 0, 285 | swiftCode: null 286 | }, 287 | [BankKey.KOOKMIN_BANK_HN]: { 288 | key: BankKey.KOOKMIN_BANK_HN, 289 | code: BankCode.KOOKMIN_BANK_HN, 290 | name: 'Ngân hàng Kookmin - Chi nhánh Hà Nội', 291 | bin: '970462', 292 | shortName: 'Kookmin Bank HN', 293 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 294 | lookupSupported: 0, 295 | swiftCode: null 296 | }, 297 | [BankKey.LIENVIETPOST_BANK]: { 298 | key: BankKey.LIENVIETPOST_BANK, 299 | code: BankCode.LPBANK, 300 | name: 'Ngân hàng TMCP Bưu Điện Liên Việt', 301 | bin: '970449', 302 | shortName: 'LienVietPostBank', 303 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 304 | lookupSupported: 1, 305 | swiftCode: 'LVBKVNVX', 306 | keywords: 'lienvietbank', 307 | deprecated: true 308 | }, 309 | [BankKey.LPBANK]: { 310 | key: BankKey.LPBANK, 311 | code: BankCode.LPBANK, 312 | name: 'Ngân hàng TMCP Lộc Phát Việt Nam', 313 | bin: '970449', 314 | shortName: 'LPBank', 315 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 316 | lookupSupported: 1, 317 | swiftCode: 'LVBKVNVX', 318 | keywords: 'lienvietbank, loc phat', 319 | }, 320 | [BankKey.LIOBANK]: { 321 | key: BankKey.LIOBANK, 322 | code: BankCode.LIOBANK, 323 | name: 'Ngân hàng số Liobank - Ngân hàng TMCP Phương Đông', 324 | bin: '963369', 325 | shortName: 'Liobank', 326 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 327 | lookupSupported: 1, 328 | swiftCode: null 329 | }, 330 | [BankKey.MBBANK]: { 331 | key: BankKey.MBBANK, 332 | code: BankCode.MBBANK, 333 | name: 'Ngân hàng TMCP Quân đội', 334 | bin: '970422', 335 | shortName: 'MB Bank', 336 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 337 | lookupSupported: 1, 338 | swiftCode: 'MSCBVNVX' 339 | }, 340 | [BankKey.MBV]: { 341 | key: BankKey.MBV, 342 | code: BankCode.MBV, 343 | name: 'Ngân hàng TNHH MTV Việt Nam Hiện Đại', 344 | bin: '970414', 345 | shortName: 'MBV', 346 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 347 | lookupSupported: 1, 348 | swiftCode: 'OCBKUS3M', 349 | keywords: 'daiduong, mbv', 350 | }, 351 | [BankKey.MSB]: { 352 | key: BankKey.MSB, 353 | code: BankCode.MSB, 354 | name: 'Ngân hàng TMCP Hàng Hải', 355 | bin: '970426', 356 | shortName: 'MSB', 357 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 358 | lookupSupported: 1, 359 | swiftCode: 'MCOBVNVX', 360 | keywords: 'hanghai' 361 | }, 362 | [BankKey.NAM_A_BANK]: { 363 | key: BankKey.NAM_A_BANK, 364 | code: BankCode.NAM_A_BANK, 365 | name: 'Ngân hàng TMCP Nam Á', 366 | bin: '970428', 367 | shortName: 'Nam A Bank', 368 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 369 | lookupSupported: 1, 370 | swiftCode: 'NAMAVNVX', 371 | keywords: 'namabank' 372 | }, 373 | [BankKey.NCB]: { 374 | key: BankKey.NCB, 375 | code: BankCode.NCB, 376 | name: 'Ngân hàng TMCP Quốc Dân', 377 | bin: '970419', 378 | shortName: 'NCB Bank', 379 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 380 | lookupSupported: 1, 381 | swiftCode: 'NVBAVNVX', 382 | keywords: 'quocdan' 383 | }, 384 | [BankKey.NONGHYUP_BANK_HN]: { 385 | key: BankKey.NONGHYUP_BANK_HN, 386 | code: BankCode.NONGHYUP_BANK_HN, 387 | name: 'Ngân hàng Nonghyup - Chi nhánh Hà Nội', 388 | bin: '801011', 389 | shortName: 'Nonghyup Bank', 390 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 391 | lookupSupported: 0, 392 | swiftCode: null 393 | }, 394 | [BankKey.OCB]: { 395 | key: BankKey.OCB, 396 | code: BankCode.OCB, 397 | name: 'Ngân hàng TMCP Phương Đông', 398 | bin: '970448', 399 | shortName: 'OCB Bank', 400 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 401 | lookupSupported: 1, 402 | swiftCode: 'ORCOVNVX', 403 | keywords: 'phuongdong' 404 | }, 405 | [BankKey.OCEANBANK]: { 406 | key: BankKey.OCEANBANK, 407 | code: BankCode.OCEANBANK, 408 | name: 'Ngân hàng Thương mại TNHH MTV Đại Dương', 409 | bin: '970414', 410 | shortName: 'Ocean Bank', 411 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 412 | lookupSupported: 1, 413 | swiftCode: 'OCBKUS3M', 414 | keywords: 'daiduong', 415 | deprecated: true 416 | }, 417 | [BankKey.PGBANK]: { 418 | key: BankKey.PGBANK, 419 | code: BankCode.PGBANK, 420 | name: 'Ngân hàng TMCP Xăng dầu Petrolimex', 421 | bin: '970430', 422 | shortName: 'PG Bank', 423 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 424 | lookupSupported: 1, 425 | swiftCode: 'PGBLVNVX' 426 | }, 427 | [BankKey.PUBLIC_BANK]: { 428 | key: BankKey.PUBLIC_BANK, 429 | code: BankCode.PUBLIC_BANK, 430 | name: 'Ngân hàng TNHH MTV Public Việt Nam', 431 | bin: '970439', 432 | shortName: 'Public Bank Vietnam', 433 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 434 | lookupSupported: 1, 435 | swiftCode: 'VIDPVNVX', 436 | keywords: 'publicvn' 437 | }, 438 | [BankKey.PVCOM_BANK]: { 439 | key: BankKey.PVCOM_BANK, 440 | code: BankCode.PVCOM_BANK, 441 | name: 'Ngân hàng TMCP Đại Chúng Việt Nam', 442 | bin: '970412', 443 | shortName: 'PVcomBank', 444 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 445 | lookupSupported: 1, 446 | swiftCode: 'WBVNVNVX', 447 | keywords: 'daichung' 448 | }, 449 | [BankKey.SACOMBANK]: { 450 | key: BankKey.SACOMBANK, 451 | code: BankCode.SACOMBANK, 452 | name: 'Ngân hàng TMCP Sài Gòn Thương Tín', 453 | bin: '970403', 454 | shortName: 'Sacombank', 455 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 456 | lookupSupported: 1, 457 | swiftCode: 'SGTTVNVX' 458 | }, 459 | [BankKey.SAIGONBANK]: { 460 | key: BankKey.SAIGONBANK, 461 | code: BankCode.SAIGONBANK, 462 | name: 'Ngân hàng TMCP Sài Gòn Công Thương', 463 | bin: '970400', 464 | shortName: 'SaigonBank', 465 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 466 | lookupSupported: 1, 467 | swiftCode: 'SBITVNVX', 468 | keywords: 'saigoncongthuong, saigonbank' 469 | }, 470 | [BankKey.SCB]: { 471 | key: BankKey.SCB, 472 | code: BankCode.SCB, 473 | name: 'Ngân hàng TMCP Sài Gòn', 474 | bin: '970429', 475 | shortName: 'SCB', 476 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 477 | lookupSupported: 1, 478 | swiftCode: 'SACLVNVX', 479 | keywords: 'saigon' 480 | }, 481 | [BankKey.SEA_BANK]: { 482 | key: BankKey.SEA_BANK, 483 | code: BankCode.SEA_BANK, 484 | name: 'Ngân hàng TMCP Đông Nam Á', 485 | bin: '970440', 486 | shortName: 'SeABank', 487 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 488 | lookupSupported: 1, 489 | swiftCode: 'SEAVVNVX' 490 | }, 491 | [BankKey.SHB]: { 492 | key: BankKey.SHB, 493 | code: BankCode.SHB, 494 | name: 'Ngân hàng TMCP Sài Gòn - Hà Nội', 495 | bin: '970443', 496 | shortName: 'SHB', 497 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 498 | lookupSupported: 1, 499 | swiftCode: 'SHBAVNVX', 500 | keywords: 'saigonhanoi, sghn' 501 | }, 502 | [BankKey.SHINHAN_BANK]: { 503 | key: BankKey.SHINHAN_BANK, 504 | code: BankCode.SHINHAN_BANK, 505 | name: 'Ngân hàng TNHH MTV Shinhan Việt Nam', 506 | bin: '970424', 507 | shortName: 'Shinhan Bank', 508 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 509 | lookupSupported: 1, 510 | swiftCode: 'SHBKVNVX' 511 | }, 512 | [BankKey.STANDARD_CHARTERED_BANK]: { 513 | key: BankKey.STANDARD_CHARTERED_BANK, 514 | code: BankCode.STANDARD_CHARTERED_BANK, 515 | name: 'Ngân hàng TNHH MTV Standard Chartered Bank Việt Nam', 516 | bin: '970410', 517 | shortName: 'Standard Chartered Vietnam', 518 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 519 | lookupSupported: 1, 520 | swiftCode: 'SCBLVNVX' 521 | }, 522 | [BankKey.TECHCOMBANK]: { 523 | key: BankKey.TECHCOMBANK, 524 | code: BankCode.TECHCOMBANK, 525 | name: 'Ngân hàng TMCP Kỹ thương Việt Nam', 526 | bin: '970407', 527 | shortName: 'Techcombank', 528 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 529 | lookupSupported: 1, 530 | swiftCode: 'VTCBVNVX' 531 | }, 532 | [BankKey.TIMO]: { 533 | key: BankKey.TIMO, 534 | code: BankCode.TIMO, 535 | name: 'Ngân hàng số Timo by Bản Việt Bank', 536 | bin: '963388', 537 | shortName: 'Timo', 538 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 539 | lookupSupported: 0, 540 | swiftCode: null, 541 | keywords: 'banviet' 542 | }, 543 | [BankKey.TPBANK]: { 544 | key: BankKey.TPBANK, 545 | code: BankCode.TPBANK, 546 | name: 'Ngân hàng TMCP Tiên Phong', 547 | bin: '970423', 548 | shortName: 'TPBank', 549 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 550 | lookupSupported: 1, 551 | swiftCode: 'TPBVVNVX', 552 | keywords: 'tienphong' 553 | }, 554 | [BankKey.UBANK]: { 555 | key: BankKey.UBANK, 556 | code: BankCode.UBANK, 557 | name: 'Ngân hàng số Ubank by VPBank - Ngân hàng TMCP Việt Nam Thịnh Vượng', 558 | bin: '546035', 559 | shortName: 'Ubank by VPBank', 560 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 561 | lookupSupported: 1, 562 | swiftCode: null 563 | }, 564 | [BankKey.UNITED_OVERSEAS_BANK]: { 565 | key: BankKey.UNITED_OVERSEAS_BANK, 566 | code: BankCode.UNITED_OVERSEAS_BANK, 567 | name: 'Ngân hàng United Overseas Bank Việt Nam', 568 | bin: '970458', 569 | shortName: 'United Overseas Bank Vietnam', 570 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 571 | lookupSupported: 1, 572 | swiftCode: null 573 | }, 574 | [BankKey.VIB]: { 575 | key: BankKey.VIB, 576 | code: BankCode.VIB, 577 | name: 'Ngân hàng TMCP Quốc tế Việt Nam', 578 | bin: '970441', 579 | shortName: 'VIB', 580 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 581 | lookupSupported: 1, 582 | swiftCode: 'VNIBVNVX', 583 | keywords: 'quocte' 584 | }, 585 | [BankKey.VIET_A_BANK]: { 586 | key: BankKey.VIET_A_BANK, 587 | code: BankCode.VIET_A_BANK, 588 | name: 'Ngân hàng TMCP Việt Á', 589 | bin: '970427', 590 | shortName: 'VietABank', 591 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 592 | lookupSupported: 1, 593 | swiftCode: 'VNACVNVX' 594 | }, 595 | [BankKey.VIET_BANK]: { 596 | key: BankKey.VIET_BANK, 597 | code: BankCode.VIET_BANK, 598 | name: 'Ngân hàng TMCP Việt Nam Thương Tín', 599 | bin: '970433', 600 | shortName: 'VietBank', 601 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 602 | lookupSupported: 1, 603 | swiftCode: 'VNTTVNVX', 604 | keywords: 'vietnamthuongtin, vnthuongtin' 605 | }, 606 | [BankKey.VIETCOMBANK]: { 607 | key: BankKey.VIETCOMBANK, 608 | code: BankCode.VIETCOMBANK, 609 | name: 'Ngân hàng TMCP Ngoại Thương Việt Nam', 610 | bin: '970436', 611 | shortName: 'Vietcombank', 612 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 613 | lookupSupported: 1, 614 | swiftCode: 'BFTVVNVX' 615 | }, 616 | [BankKey.VIETINBANK]: { 617 | key: BankKey.VIETINBANK, 618 | code: BankCode.VIETINBANK, 619 | name: 'Ngân hàng TMCP Công thương Việt Nam', 620 | bin: '970415', 621 | shortName: 'VietinBank', 622 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 623 | lookupSupported: 1, 624 | swiftCode: 'ICBVVNVX', 625 | keywords: 'viettin' // Some users may use this keyword 626 | }, 627 | [BankKey.VIKKI]: { 628 | key: BankKey.VIKKI, 629 | code: BankCode.VIKKI, 630 | name: 'Ngân hàng TNHH MTV Số Vikki', 631 | bin: '970406', 632 | shortName: 'Vikki Bank', 633 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 634 | lookupSupported: 1, 635 | swiftCode: 'EACBVNVX', 636 | keywords: 'vikki, dongabank, dong a', 637 | }, 638 | [BankKey.VPBANK]: { 639 | key: BankKey.VPBANK, 640 | code: BankCode.VPBANK, 641 | name: 'Ngân hàng TMCP Việt Nam Thịnh Vượng', 642 | bin: '970432', 643 | shortName: 'VPBank', 644 | vietQRStatus: VietQRStatus.TRANSFER_SUPPORTED, 645 | lookupSupported: 1, 646 | swiftCode: 'VPBKVNVX', 647 | keywords: 'vnthinhvuong' 648 | }, 649 | [BankKey.VRB]: { 650 | key: BankKey.VRB, 651 | code: BankCode.VRB, 652 | name: 'Ngân hàng Liên doanh Việt - Nga', 653 | bin: '970421', 654 | shortName: 'VietNgaBank', 655 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 656 | lookupSupported: 1, 657 | swiftCode: null, 658 | keywords: 'vietnam-russia, vrbank' 659 | }, 660 | [BankKey.WOORI_BANK]: { 661 | key: BankKey.WOORI_BANK, 662 | code: BankCode.WOORI_BANK, 663 | name: 'Ngân hàng TNHH MTV Woori Việt Nam', 664 | bin: '970457', 665 | shortName: 'Woori Bank', 666 | vietQRStatus: VietQRStatus.RECEIVE_ONLY, 667 | lookupSupported: 1, 668 | swiftCode: null 669 | } 670 | } 671 | 672 | export const Banks: Bank[] = Object.values(BanksObject) 673 | -------------------------------------------------------------------------------- /test/zalopay.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/momo.svg: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------