UNPKG

node-ecpay-aio

Version:

A production-ready ECPay AIO SDK for Node.js with TypeScript support.

193 lines (192 loc) 8.86 kB
"use strict"; 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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FundingReconDetailQuery = exports.TradeNoAioQuery = exports.TradeV2Query = exports.CreditCardPeriodInfoQuery = exports.PaymentInfoQuery = exports.TradeInfoQuery = exports.Query = void 0; const Error_1 = require("./Error"); const utils_1 = require("../utils"); const schema_1 = require("../schema"); const QUERY_RESULT_BASE_INT_FIELDS = [ 'TradeAmt', 'HandlingCharge', 'PaymentTypeChargeFee', 'PeriodAmount', 'TotalAmount', 'Frequency', 'ExecTimes', 'TotalSuccessTimes', 'TotalSuccessAmount', 'RtnCode', ]; const QUERY_ADDITIONAL_INT_FIELDS = ['RtnCode', 'gwsr', 'amount', 'clsamt']; const QUERY_EXTRAINFO_INT_FIELDS = [ 'stage', 'stast', 'staed', 'eci', 'red_dan', 'red_de_amt', 'red_ok_amt', 'red_yet', ]; class Query { constructor(merchant, params) { this.responseDataEncoding = 'utf8'; this.merchant = merchant; this.params = Object.assign({}, params); } _read() { return __awaiter(this, void 0, void 0, function* () { if (!this.apiUrl || !this.apiUrl.startsWith('https://')) throw new Error(`API url is not provided or infeasible for ${this.merchant.mode} mode.`); const { MerchantID, HashKey, HashIV } = this.merchant.config; // every query requires MerchantID and CheckMacValue const postParams = Object.assign({ MerchantID }, this._params); const CheckMacValue = (0, utils_1.generateCheckMacValue)(postParams, HashKey, HashIV); const _result = yield (0, utils_1.postRequest)({ apiUrl: this.apiUrl, params: Object.assign(Object.assign({}, postParams), { CheckMacValue }), responseEncoding: this.responseDataEncoding, }); const result = (0, utils_1.parseIntegerFileds)(_result, QUERY_RESULT_BASE_INT_FIELDS); return result; }); } } exports.Query = Query; class TradeInfoQuery extends Query { constructor(merchant, params) { super(merchant, params); schema_1.BaseQueryParamsSchema.validateSync(this.params); this.apiUrl = merchant.ecpayServiceUrls.TradeInfo[merchant.mode]; this._params = Object.assign(Object.assign({}, this.params), { TimeStamp: (0, utils_1.getCurrentUnixTimestampOffset)(120), PlatformID: this.merchant.config.PlatformID }); } read() { return __awaiter(this, void 0, void 0, function* () { const { HashKey, HashIV } = this.merchant.config; const _data = yield this._read(); const result = (0, utils_1.parseIntegerFileds)(_data, [ ...QUERY_ADDITIONAL_INT_FIELDS, ...QUERY_EXTRAINFO_INT_FIELDS, ]); if (!(0, utils_1.isValidReceivedCheckMacValue)(_data, HashKey, HashIV)) throw new Error_1.CheckMacValueError(`Invalid CheckMacValue in TradeInfoQuery response. MerchantTradeNo: ${this.params.MerchantTradeNo}.`, result); if (result.TradeStatus !== '0' && result.TradeStatus !== '1' && result.TradeStatus !== '10200095') { throw new Error_1.QueryError('Trade info query failed.', parseInt(result.TradeStatus), result); } return result; }); } } exports.TradeInfoQuery = TradeInfoQuery; class PaymentInfoQuery extends Query { constructor(merchant, params) { super(merchant, params); schema_1.BaseQueryParamsSchema.validateSync(this.params); this.apiUrl = merchant.ecpayServiceUrls.PaymentInfo[merchant.mode]; this._params = Object.assign(Object.assign({}, this.params), { TimeStamp: (0, utils_1.getCurrentUnixTimestampOffset)(120), PlatformID: this.merchant.config.PlatformID }); } read() { return __awaiter(this, void 0, void 0, function* () { const { HashKey, HashIV } = this.merchant.config; const data = yield this._read(); if (!(0, utils_1.isValidReceivedCheckMacValue)(data, HashKey, HashIV)) throw new Error_1.CheckMacValueError(`Invalid CheckMacValue in PaymentInfoQuery response. MerchantTradeNo: ${this.params.MerchantTradeNo}.`, data); // Check if RtnCode is successful if (data.PaymentType.startsWith('ATM') && data.RtnCode !== 2) throw new Error_1.QueryError(data.RtnMsg, data.RtnCode, data); else if ((data.PaymentType.startsWith('CVS') || data.PaymentType.startsWith('BARCODE')) && data.RtnCode !== 10100073) throw new Error_1.QueryError(data.RtnMsg, data.RtnCode, data); return data; }); } } exports.PaymentInfoQuery = PaymentInfoQuery; class CreditCardPeriodInfoQuery extends Query { constructor(merchant, params) { super(merchant, params); schema_1.BaseQueryParamsSchema.validateSync(this.params); this.apiUrl = merchant.ecpayServiceUrls.CreditCardPeriodInfo[merchant.mode]; this._params = Object.assign(Object.assign({}, this.params), { TimeStamp: (0, utils_1.getCurrentUnixTimestampOffset)(120), PlatformID: this.merchant.config.PlatformID }); } read() { return __awaiter(this, void 0, void 0, function* () { const _result = yield this._read(); const result = (0, utils_1.parseIntegerFileds)(_result, QUERY_ADDITIONAL_INT_FIELDS); if (result.RtnCode !== 1) throw new Error_1.QueryError('Credit card period info query failed or first authorization for this order was rejected.', result.RtnCode, result); if (Array.isArray(result.ExecLog)) { result.ExecLog.forEach((log, index) => { result.ExecLog[index] = (0, utils_1.parseIntegerFileds)(log, QUERY_ADDITIONAL_INT_FIELDS); }); } return result; }); } } exports.CreditCardPeriodInfoQuery = CreditCardPeriodInfoQuery; // note: 無測試環境可用, TBD: testing@production class TradeV2Query extends Query { // amount, clsamt // amount constructor(merchant, params) { super(merchant, params); schema_1.TradeV2QueryParamsSchema.validateSync(params); this.apiUrl = merchant.ecpayServiceUrls.TradeV2[merchant.mode]; this._params = Object.assign({}, this.params); } read() { return __awaiter(this, void 0, void 0, function* () { const result = yield this._read(); if (!result.RtnValue) { // RtnMsg: '' for success throw new Error_1.QueryError(result.RtnMsg, result.RtnValue, result); } return result; }); } } exports.TradeV2Query = TradeV2Query; class TradeNoAioQuery extends Query { constructor(merchant, params) { super(merchant, params); schema_1.TradeNoAioQueryParamsSchema.validateSync(params); this.apiUrl = merchant.ecpayServiceUrls.TradeNoAio[merchant.mode]; this.responseDataEncoding = (params === null || params === void 0 ? void 0 : params.CharSet) === '2' ? 'utf8' : 'Big5'; this._params = Object.assign({}, this.params); } read() { return __awaiter(this, void 0, void 0, function* () { return this._read(); }); } } exports.TradeNoAioQuery = TradeNoAioQuery; // note: 無測試環境可用, TBD: testing@production class FundingReconDetailQuery extends Query { constructor(merchant, params) { super(merchant, params); schema_1.FundingReconDetailQueryParamsSchema.validateSync(params); this.apiUrl = merchant.ecpayServiceUrls.FundingReconDetail[merchant.mode]; this.responseDataEncoding = (params === null || params === void 0 ? void 0 : params.CharSet) === '2' ? 'utf8' : 'Big5'; this._params = Object.assign({}, this.params); } read() { return __awaiter(this, void 0, void 0, function* () { return this._read(); }); } } exports.FundingReconDetailQuery = FundingReconDetailQuery;