const UserError = require('vn-loopback/util/user-error'); const base64url = require('base64url'); module.exports = Self => { Self.remoteMethod('confirm', { description: 'Confirms electronic payment transaction', accessType: 'WRITE', accepts: [ { arg: 'Ds_SignatureVersion', type: 'string', required: false, }, { arg: 'Ds_MerchantParameters', type: 'string', required: true, }, { arg: 'Ds_Signature', type: 'string', required: true, } ], returns: { type: 'Boolean', root: true }, http: { path: `/confirm`, verb: 'POST' } }); Self.confirm = async(signatureVersion, merchantParameters, signature) => { const $ = Self.app.models; let transaction; try { const decodedParams = JSON.parse( base64url.decode(merchantParameters, 'utf8')); const params = {}; for (const param in decodedParams) params[param] = decodeURIComponent(decodedParams[param]); const orderId = params['Ds_Order']; if (!orderId) throw new UserError('Order id not provided'); transaction = await Self.findById(orderId, {fields: ['id']}); if (!transaction) throw new UserError('Order not found'); await transaction.updateAttributes({ merchantParameters, signature, signatureVersion, }); const merchantId = parseInt(params['Ds_MerchantCode']); if (!merchantId) throw new UserError('Merchant id not provided'); const merchant = await $.TpvMerchant.findById(merchantId, { fields: ['id', 'secretKey'] }); if (!merchant) throw new UserError('Merchant not found'); const base64hmac = Self.createSignature( orderId, merchant.secretKey, merchantParameters ); if (base64hmac !== base64url.toBase64(signature)) throw new UserError('Invalid signature'); await Self.rawSql( 'CALL hedera.tpvTransaction_confirm(?, ?, ?, ?, ?, ?)', [ params['Ds_Amount'], orderId, merchantId, params['Ds_Currency'], params['Ds_Response'], params['Ds_ErrorCode'] ]); return true; } catch (err) { if (transaction) await transaction.updateAttribute('responseError', err.message); else console.error(err); throw err; } }; };