pix-utils
Version:
Set of tools to parse, generate and validate payments of Brazil Instant Payment System (Pix)
104 lines • 10.2 kB
JavaScript
import { computeCRC } from './crc';
import { PixElementType } from './types/pixElements';
import { EmvAdditionalDataSchema, EmvMaiSchema, EmvSchema, TagsWithSubTags, } from './types/pixEmvSchema';
import { normalizeCity, normalizeName } from './utils/textParser';
import zeroPad from './utils/zeroPad';
function generateEmvElement(elementId, value) {
if (!value)
return '';
const parsedElementId = zeroPad(elementId, 2);
const parsedLength = zeroPad(value.length, 2);
return `${parsedElementId}${parsedLength}${value}`;
}
function generateMAI(elements) {
if (elements.type === PixElementType.STATIC) {
return [
generateEmvElement(EmvMaiSchema.TAG_MAI_GUI, EmvMaiSchema.BC_GUI),
generateEmvElement(EmvMaiSchema.TAG_MAI_PIXKEY, elements.pixKey),
generateEmvElement(EmvMaiSchema.TAG_MAI_INFO_ADD, elements.infoAdicional),
generateEmvElement(EmvMaiSchema.TAG_MAI_FSS, elements.fss),
].join('');
}
else if (elements.type === PixElementType.DYNAMIC ||
elements.type === PixElementType.RECURRENCE) {
return [
generateEmvElement(EmvMaiSchema.TAG_MAI_GUI, EmvMaiSchema.BC_GUI),
generateEmvElement(EmvMaiSchema.TAG_MAI_URL, elements.url),
].join('');
}
return undefined;
}
function generateAdditionalData(txid) {
return generateEmvElement(EmvAdditionalDataSchema.TAG_TXID, txid || '***');
}
export function createEmv(elements) {
if (![
PixElementType.STATIC,
PixElementType.DYNAMIC,
PixElementType.RECURRENCE,
].includes(elements.type))
return 'INVALID';
const emvElements = [
generateEmvElement(EmvSchema.TAG_INIT, '01'),
generateEmvElement(EmvSchema.TAG_ONETIME, elements.oneTime ? '12' : ''),
generateEmvElement(EmvSchema.TAG_MAI, generateMAI(elements)),
generateEmvElement(EmvSchema.TAG_MCC, elements.merchantCategoryCode),
generateEmvElement(EmvSchema.TAG_TRANSACTION_CURRENCY, elements.transactionCurrency),
elements.type === PixElementType.STATIC
? generateEmvElement(EmvSchema.TAG_TRANSACTION_AMOUNT, elements.transactionAmount > 0
? elements.transactionAmount.toFixed(2)
: '')
: '',
generateEmvElement(EmvSchema.TAG_COUNTRY_CODE, elements.countryCode),
generateEmvElement(EmvSchema.TAG_MERCHANT_NAME, normalizeName(elements.merchantName)),
generateEmvElement(EmvSchema.TAG_MERCHANT_CITY, normalizeCity(elements.merchantCity)),
generateEmvElement(EmvSchema.TAG_ADDITIONAL_DATA, generateAdditionalData(elements.type === PixElementType.STATIC ? elements.txid : '')),
elements.urlRec
? generateEmvElement(EmvSchema.TAG_UNRESERVED_TEMPLATE, [
generateEmvElement(EmvMaiSchema.TAG_MAI_GUI, EmvMaiSchema.BC_GUI),
generateEmvElement(EmvMaiSchema.TAG_MAI_URL, elements.urlRec),
].join(''))
: '',
generateEmvElement(EmvSchema.TAG_CRC, '0000'),
];
const generatedEmv = emvElements.join('');
return generatedEmv.replace(/\w{4}$/, computeCRC(generatedEmv));
}
export function parseEmv({ emvCode, currentIndex = 0, currentData = {}, }) {
const tag = +emvCode.substring(currentIndex, currentIndex + 2);
const length = Number(emvCode.substring(currentIndex + 2, currentIndex + 4));
const value = emvCode.substring(currentIndex + 4, currentIndex + 4 + length);
if (!length || !value.length || length !== value.length) {
return {
isValid: false,
rawTags: currentData,
};
}
const newData = {
...currentData,
[tag]: {
tag: tag,
length: length,
value: value,
...(Object.values(TagsWithSubTags).includes(tag)
? { subTags: parseEmv({ emvCode: value }) }
: {}),
},
};
if (currentIndex + 4 + length === emvCode.length) {
return {
isValid: true,
rawTags: newData,
getTag: (tag) => newData?.[Number(tag)]?.value,
getSubTag: (tag, mainTag) => newData?.[Number(mainTag)]?.subTags?.getTag(Number(tag)),
};
}
else {
return parseEmv({
emvCode,
currentIndex: currentIndex + 4 + length,
currentData: newData,
});
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW12SGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9lbXZIYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxPQUFPLENBQUM7QUFDbkMsT0FBTyxFQUFlLGNBQWMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2xFLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsWUFBWSxFQUNaLFNBQVMsRUFFVCxlQUFlLEdBQ2hCLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFFLGFBQWEsRUFBRSxhQUFhLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsRSxPQUFPLE9BQU8sTUFBTSxpQkFBaUIsQ0FBQztBQUV0QyxTQUFTLGtCQUFrQixDQUFDLFNBQWlCLEVBQUUsS0FBYTtJQUMxRCxJQUFJLENBQUMsS0FBSztRQUFFLE9BQU8sRUFBRSxDQUFDO0lBQ3RCLE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDOUMsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDOUMsT0FBTyxHQUFHLGVBQWUsR0FBRyxZQUFZLEdBQUcsS0FBSyxFQUFFLENBQUM7QUFDckQsQ0FBQztBQUVELFNBQVMsV0FBVyxDQUFDLFFBQXFCO0lBQ3hDLElBQUksUUFBUSxDQUFDLElBQUksS0FBSyxjQUFjLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDNUMsT0FBTztZQUNMLGtCQUFrQixDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsWUFBWSxDQUFDLE1BQU0sQ0FBQztZQUNqRSxrQkFBa0IsQ0FBQyxZQUFZLENBQUMsY0FBYyxFQUFFLFFBQVEsQ0FBQyxNQUFNLENBQUM7WUFDaEUsa0JBQWtCLENBQUMsWUFBWSxDQUFDLGdCQUFnQixFQUFFLFFBQVEsQ0FBQyxhQUFhLENBQUM7WUFDekUsa0JB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