UNPKG

@adriantombu/paybox-system

Version:

A simple implementation of the Paybox System payment solution

163 lines (162 loc) 6.2 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Paybox = void 0; const querystring_1 = __importDefault(require("querystring")); const axios_1 = __importDefault(require("axios")); const crypto_1 = __importDefault(require("crypto")); const errors_1 = __importDefault(require("./errors")); __exportStar(require("./types"), exports); class Paybox { constructor(params) { this.sandbox = params.payboxSandbox; this.request = { PBX_SITE: params.payboxSite, PBX_RANG: params.payboxRang, PBX_IDENTIFIANT: params.payboxIdentifiant, PBX_ARCHIVAGE: this.archivage(), PBX_HMAC: params.payboxHmac, PBX_TOTAL: this.formatAmount(params.amount), PBX_DEVISE: '978', PBX_CMD: params.reference, PBX_PORTEUR: params.email, PBX_RETOUR: this.setReturnVars(), PBX_RUF1: 'POST', PBX_TIME: this.getTime(), PBX_HASH: 'SHA512', PBX_EFFECTUE: params.payboxEffectue, PBX_REFUSE: params.payboxRefuse, PBX_ANNULE: params.payboxAnnule, PBX_ATTENTE: params.payboxAttente, PBX_REPONDRE_A: params.payboxRepondreA, }; this.computeHMAC(); } static create(params) { return new Paybox(params); } static getError(code) { if (code.startsWith('001')) { return 'Paiement refusé par le centre d’autorisation'; } if (code in errors_1.default) { return errors_1.default[code]; } return `Erreur ${code}`; } static isValid(result, amount) { return (!!result.authorizationId && result.error === '00000' && parseInt(result.amount, 10) === amount && this.signatureIsValid(result)); } static signatureIsValid(result) { const signature = new Buffer(result.signature || '', 'base64'); delete result.signature; if (signature.length !== 128) { return false; } const message = querystring_1.default.stringify(result); const publicKey = crypto_1.default.createPublicKey(payboxPublicKey); return crypto_1.default.createVerify('SHA1').update(message).verify(publicKey, signature); } async form() { return { url: await this.getUrl(), method: this.request.PBX_RUF1, form: this.getFormElements() .map((e) => `<input type="hidden" name="${e.name}" value="${e.value}" />`) .join(''), elements: this.getFormElements(), }; } archivage() { return Date.now().toString().substr(-12); } formatAmount(amount) { return `${parseInt(amount.toString(), 10)}`.padStart(10, '0'); } setReturnVars() { let vars = ''; for (const key of Object.keys(returnVars)) { vars += `${returnVars[key]}:${key};`; } return vars; } getTime() { const now = new Date(); const day = now.getDay().toString().padStart(2, '0'); const month = (now.getMonth() + 1).toString().padStart(2, '0'); const year = now.getFullYear(); const hour = now.getHours().toString().padStart(2, '0'); const minute = now.getMinutes().toString().padStart(2, '0'); const second = now.getSeconds().toString().padStart(2, '0'); return `${day}${month}${year}${hour}${minute}${second}`; } computeHMAC() { if (this.request.PBX_HMAC) { const elements = this.getFormElements(); const hmac = Buffer.from(this.request.PBX_HMAC, 'hex'); const chain = elements .filter((e) => e.name !== 'PBX_HMAC') .map((e) => `${e.name}=${e.value}`) .join('&'); this.request.PBX_HMAC = crypto_1.default.createHmac('sha512', hmac).update(chain).digest('hex').toUpperCase(); } } async getUrl() { const urls = this.sandbox ? baseUrls.sandbox : baseUrls.prod; const res = await axios_1.default.get(`${urls.main}/load.html`); return `${res.data.includes('>OK<') ? urls.main : urls.fallback}/cgi/MYchoix_pagepaiement.cgi`; } getFormElements() { const elements = []; for (const key of Object.keys(this.request)) { elements.push({ name: key, value: this.request[key], }); } return elements; } } exports.Paybox = Paybox; const returnVars = { M: 'amount', R: 'paymentId', T: 'transactionId', A: 'authorizationId', P: 'cardType', N: 'cardNumber', D: 'cardExpiration', E: 'error', S: 'payboxRef', K: 'signature', }; const baseUrls = { prod: { main: 'https://tpeweb.paybox.com', fallback: 'https://tpeweb1.paybox.com', }, sandbox: { main: 'https://preprod-tpeweb.paybox.com', fallback: 'https://preprod-tpeweb.paybox.com', }, }; const payboxPublicKey = '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe+hkicNP7ROHUssGNtHwiT2Ew\nHFrSk/qwrcq8v5metRtTTFPE/nmzSkRnTs3GMpi57rBdxBBJW5W9cpNyGUh0jNXc\nVrOSClpD5Ri2hER/GcNrxVRP7RlWOqB1C03q4QYmwjHZ+zlM4OUhCCAtSWflB4wC\nKa1g88CjFwRw/PB9kwIDAQAB\n-----END PUBLIC KEY-----';