From 810f44071b91a0c2cea9ee7991dc5a101746d2e5 Mon Sep 17 00:00:00 2001 From: RcleydsonR Date: Fri, 4 Nov 2022 01:09:33 -0300 Subject: [PATCH] generate qr code from pix function implementation can't use the qrcode-pix library because of a broken dependency based on crc v4.1.1, so, needed to use a previous version from crc --- package.json | 2 ++ src/utils/QrCodePix.ts | 80 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 src/utils/QrCodePix.ts diff --git a/package.json b/package.json index cb1e2d1..ba8dd5a 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,8 @@ "dependencies": { "@headlessui/vue": "^1.7.3", "@heroicons/vue": "^2.0.12", + "crc": "^3.8.0", + "qrcode": "^1.5.1", "vue": "^3.2.41", "vue-router": "^4.1.5" }, diff --git a/src/utils/QrCodePix.ts b/src/utils/QrCodePix.ts new file mode 100644 index 0000000..c1d46d6 --- /dev/null +++ b/src/utils/QrCodePix.ts @@ -0,0 +1,80 @@ +import qrcode from 'qrcode'; +import type {QRCodeToDataURLOptions} from 'qrcode'; +import { crc16ccitt } from 'crc'; + +interface PixParams { + pixKey: string; + merchantCity: string; + merchantName: string; + value?: number; + transactionId?: string; + message?: string; + cep?: string; + currency?: number; + countryCode?: string; +} + +const Pix = ({ + pixKey, + merchantCity, + merchantName, + value, + message, + cep, + transactionId = '', + currency = 986, + countryCode = 'BR', +}: PixParams) => { + const payloadKeyString = generatePixKey(pixKey, message); + + const payload: string[] = [ + formatEMV('00', '01'), //Payload Format Indicator + formatEMV('26', payloadKeyString), // Merchant Account Information + formatEMV('52', '0000'), //Merchant Category Code + formatEMV('53', String(currency)), // Transaction Currency + ]; + + if (String(value) === '0') { + value = undefined; + } + if (value) { + payload.push(formatEMV('54', value.toFixed(2))); + } + + payload.push(formatEMV('58', countryCode.toUpperCase())); // Country Code + payload.push(formatEMV('59', merchantName)); // Merchant merchantName + payload.push(formatEMV('60', merchantCity)); // Merchant merchantCity + + if (cep) { + payload.push(formatEMV('61', cep)); // Postal Code + } + + payload.push(formatEMV('62', formatEMV('05', transactionId))); // Additional Data Field Template + + payload.push('6304'); + + const stringPayload = payload.join(''); + const crcResult = crc16ccitt(stringPayload).toString(16).toUpperCase().padStart(4, '0'); + + const payloadPIX = `${stringPayload}${crcResult}`; + + return { + payload: (): string => payloadPIX, + base64QrCode: (options?: QRCodeToDataURLOptions): Promise => qrcode.toDataURL(payloadPIX, options), + }; +} + +const generatePixKey = (pixKey: string, message?: string): string => { + const payload: string[] = [formatEMV('00', 'BR.GOV.BCB.PIX'), formatEMV('01', pixKey)]; + if (message) { + payload.push(formatEMV('02', message)); + } + return payload.join(''); +} + +const formatEMV = (id: string, param: string): string => { + const len = param.length.toString().padStart(2, '0'); + return `${id}${len}${param}`; +} + +export {type PixParams, Pix }; \ No newline at end of file