UNPKG

ts-midtrans-client

Version:

This library is an UNOFFICIAL TypeScript version of the Midtrans Client - Node.js.

316 lines (315 loc) 13 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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const crypto = __importStar(require("crypto")); const snapBiApiRequestor_1 = __importDefault(require("./snapBiApiRequestor")); const snapBiConfig_1 = __importDefault(require("./snapBiConfig")); class SnapBi { constructor(paymentMethod) { this.paymentMethod = paymentMethod; this.apiPath = ''; this.accessTokenHeader = {}; this.transactionHeader = {}; this.body = {}; this.accessToken = ''; this.deviceId = ''; this.debugId = ''; this.timeStamp = new Date().toISOString(); this.timeout = null; this.signature = ''; this.notificationUrlPath = ''; this.notificationPayload = {}; } static directDebit() { return new SnapBi('directDebit'); } static va() { return new SnapBi('va'); } static qris() { return new SnapBi('qris'); } static notification() { return new SnapBi(''); } withAccessTokenHeader(headers) { this.accessTokenHeader = Object.assign(Object.assign({}, this.accessTokenHeader), headers); return this; } withTransactionHeader(headers) { this.transactionHeader = Object.assign(Object.assign({}, this.transactionHeader), headers); return this; } withAccessToken(accessToken) { this.accessToken = accessToken; return this; } withBody(body) { this.body = body; return this; } withSignature(signature) { this.signature = signature; return this; } withTimeStamp(timeStamp) { this.timeStamp = timeStamp; return this; } withNotificationPayload(notificationPayload) { this.notificationPayload = notificationPayload; return this; } withNotificationUrlPath(notificationUrlPath) { this.notificationUrlPath = notificationUrlPath; return this; } withPrivateKey(privateKey) { snapBiConfig_1.default.snapBiPrivateKey = privateKey; return this; } withClientId(clientId) { snapBiConfig_1.default.snapBiClientId = clientId; return this; } withClientSecret(clientSecret) { snapBiConfig_1.default.snapBiClientSecret = clientSecret; return this; } withPartnerId(partnerId) { snapBiConfig_1.default.snapBiPartnerId = partnerId; return this; } withChannelId(channelId) { snapBiConfig_1.default.snapBiChannelId = channelId; return this; } withDeviceId(deviceId) { this.deviceId = deviceId; return this; } withDebugId(debugId) { this.debugId = debugId; return this; } withTimeout(timeout) { this.timeout = timeout; return this; } createPayment(externalId) { return __awaiter(this, void 0, void 0, function* () { this.apiPath = this.setupCreatePaymentApiPath(this.paymentMethod); return yield this.createConnection(externalId); }); } cancel(externalId) { return __awaiter(this, void 0, void 0, function* () { this.apiPath = this.setupCancelApiPath(this.paymentMethod); return yield this.createConnection(externalId); }); } refund(externalId) { return __awaiter(this, void 0, void 0, function* () { this.apiPath = this.setupRefundApiPath(this.paymentMethod); return yield this.createConnection(externalId); }); } getStatus(externalId) { return __awaiter(this, void 0, void 0, function* () { this.apiPath = this.setupGetStatusApiPath(this.paymentMethod); return yield this.createConnection(externalId); }); } isWebhookNotificationVerified() { if (snapBiConfig_1.default.snapBiPublicKey == null) { throw new Error("The public key is null, You need to set the public key from SnapBiConfig.'\n" + "For more details, contact support at support@midtrans.com if you have any questions."); } const notificationHttpMethod = "POST"; const minifiedNotificationBodyJsonString = JSON.stringify(this.notificationPayload); const hashedNotificationBodyJsonString = crypto .createHash("sha256") .update(minifiedNotificationBodyJsonString) .digest("hex") .toLowerCase(); const rawStringDataToVerifyAgainstSignature = notificationHttpMethod + ":" + this.notificationUrlPath + ":" + hashedNotificationBodyJsonString + ":" + this.timeStamp; const verifier = crypto.createVerify("SHA256"); verifier.update(rawStringDataToVerifyAgainstSignature, "utf8"); const isSignatureVerified = verifier.verify(snapBiConfig_1.default.snapBiPublicKey, this.signature, "base64"); return isSignatureVerified; } getAccessToken() { return __awaiter(this, void 0, void 0, function* () { const snapBiAccessTokenHeader = this.buildAccessTokenHeader(this.timeStamp); const openApiPayload = { grant_type: 'client_credentials', }; return yield snapBiApiRequestor_1.default.remoteCall(snapBiConfig_1.default.getBaseUrl() + SnapBi.ACCESS_TOKEN, snapBiAccessTokenHeader, openApiPayload, this.timeout); }); } createConnection() { return __awaiter(this, arguments, void 0, function* (externalId = null) { if (!this.accessToken) { const accessTokenResponse = yield this.getAccessToken(); if (!accessTokenResponse.accessToken) { return accessTokenResponse; } this.accessToken = accessTokenResponse.accessToken; } const snapBiTransactionHeader = this.buildSnapBiTransactionHeader(externalId, this.timeStamp); return yield snapBiApiRequestor_1.default.remoteCall(snapBiConfig_1.default.getBaseUrl() + this.apiPath, snapBiTransactionHeader, this.body, this.timeout); }); } static getSymmetricSignatureHmacSh512(accessToken, requestBody, method, path, clientSecret, timeStamp) { const minifiedBody = JSON.stringify(requestBody); const hashedBody = crypto.createHash('sha256').update(minifiedBody).digest('hex').toLowerCase(); const payload = `${method.toUpperCase()}:${path}:${accessToken}:${hashedBody}:${timeStamp}`; const hmac = crypto.createHmac('sha512', clientSecret).update(payload).digest('base64'); return hmac; } static getAsymmetricSignatureSha256WithRsa(clientId, xTimeStamp, privateKey) { const stringToSign = clientId + "|" + xTimeStamp; return crypto.sign('RSA-SHA256', Buffer.from(stringToSign), privateKey).toString("base64"); } buildSnapBiTransactionHeader(externalId, timeStamp) { let snapBiTransactionHeader = { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-PARTNER-ID': snapBiConfig_1.default.snapBiPartnerId, 'X-EXTERNAL-ID': externalId !== null && externalId !== void 0 ? externalId : '', 'X-DEVICE-ID': this.deviceId, 'CHANNEL-ID': snapBiConfig_1.default.snapBiChannelId, 'debug-id': this.debugId, 'Authorization': `Bearer ${this.accessToken}`, 'X-TIMESTAMP': timeStamp, 'X-SIGNATURE': SnapBi.getSymmetricSignatureHmacSh512(this.accessToken, this.body, 'post', this.apiPath, snapBiConfig_1.default.snapBiClientSecret, timeStamp), }; if (this.transactionHeader) { snapBiTransactionHeader = Object.assign(Object.assign({}, snapBiTransactionHeader), this.transactionHeader); } return snapBiTransactionHeader; } buildAccessTokenHeader(timeStamp) { let snapBiAccessTokenHeader = { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-CLIENT-KEY': snapBiConfig_1.default.snapBiClientId, 'X-SIGNATURE': SnapBi.getAsymmetricSignatureSha256WithRsa(snapBiConfig_1.default.snapBiClientId, timeStamp, snapBiConfig_1.default.snapBiPrivateKey), 'X-TIMESTAMP': timeStamp, 'debug-id': this.debugId, }; if (this.accessTokenHeader) { snapBiAccessTokenHeader = Object.assign(Object.assign({}, snapBiAccessTokenHeader), this.accessTokenHeader); } return snapBiAccessTokenHeader; } setupCreatePaymentApiPath(paymentMethod) { switch (paymentMethod) { case 'va': return SnapBi.CREATE_VA; case 'qris': return SnapBi.QRIS_PAYMENT; case 'directDebit': return SnapBi.PAYMENT_HOST_TO_HOST; default: throw new Error(`Payment method not implemented: ${paymentMethod}`); } } setupRefundApiPath(paymentMethod) { switch (paymentMethod) { case 'qris': return SnapBi.QRIS_REFUND; case 'directDebit': return SnapBi.DEBIT_REFUND; default: throw new Error(`Payment method not implemented: ${paymentMethod}`); } } setupCancelApiPath(paymentMethod) { switch (paymentMethod) { case 'va': return SnapBi.VA_CANCEL; case 'qris': return SnapBi.QRIS_CANCEL; case 'directDebit': return SnapBi.DEBIT_CANCEL; default: throw new Error(`Payment method not implemented: ${paymentMethod}`); } } setupGetStatusApiPath(paymentMethod) { switch (paymentMethod) { case 'va': return SnapBi.VA_STATUS; case 'qris': return SnapBi.QRIS_STATUS; case 'directDebit': return SnapBi.DEBIT_STATUS; default: throw new Error(`Payment method not implemented: ${paymentMethod}`); } } } SnapBi.ACCESS_TOKEN = '/v1.0/access-token/b2b'; SnapBi.PAYMENT_HOST_TO_HOST = '/v1.0/debit/payment-host-to-host'; SnapBi.CREATE_VA = '/v1.0/transfer-va/create-va'; SnapBi.DEBIT_STATUS = '/v1.0/debit/status'; SnapBi.DEBIT_REFUND = '/v1.0/debit/refund'; SnapBi.DEBIT_CANCEL = '/v1.0/debit/cancel'; SnapBi.VA_STATUS = '/v1.0/transfer-va/status'; SnapBi.VA_CANCEL = '/v1.0/transfer-va/delete-va'; SnapBi.QRIS_PAYMENT = '/v1.0/qr/qr-mpm-generate'; SnapBi.QRIS_STATUS = '/v1.0/qr/qr-mpm-query'; SnapBi.QRIS_REFUND = '/v1.0/qr/qr-mpm-refund'; SnapBi.QRIS_CANCEL = '/v1.0/qr/qr-mpm-cancel'; exports.default = SnapBi;