diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9daeeb2..593892c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,3 +26,4 @@ jobs: - run: npm run test:integration env: SECRET_KEY: xnd_development_chBDpzjQZEI8nncBLrWtwau5r7rgiuunCJ4JCqsd68rXemDd74BnRpdO0bIZAMK + SECRET_KEY_PH: xnd_development_Va7pPIfYxIo7letKqhZCkwniwggDGyjB0sAzmOUe1mMkED4k0nLh1TvtVi0raNne diff --git a/examples/with_async/regional_retail_outlet.js b/examples/with_async/regional_retail_outlet.js new file mode 100644 index 0000000..79011c3 --- /dev/null +++ b/examples/with_async/regional_retail_outlet.js @@ -0,0 +1,36 @@ +const x = require('../xendit'); + +const RegionalRetailOutlet = x.RegionalRetailOutlet; +const ro = new RegionalRetailOutlet({}); + +(async function() { + try { + const pmCode = await ro.createPaymentCode({ + referenceId: 'test_dharma_61', + channelCode: 'CEBUANA', + customerName: 'Dharma', + amount: 50, + currency: 'PHP', + market: 'PH' + }); + // eslint-disable-next-line no-console + console.log('fixed payment code created:', pmCode); + + const { id } = pmCode; + const retrievedPmCode = await ro.getPaymentCode({ id }); + // eslint-disable-next-line no-console + console.log('fixed payment code details:', retrievedPmCode); + + const updatedPmCode = await ro.updatePaymentCode({ + id, + customerName: "DharmaLain", + }); + // eslint-disable-next-line no-console + console.log('updated payment code details:', updatedPmCode); + + process.exit(0); + } catch (e) { + console.error(e); // eslint-disable-line no-console + process.exit(1); + } +})(); diff --git a/examples/with_promises/regional_retail_outlet.js b/examples/with_promises/regional_retail_outlet.js new file mode 100644 index 0000000..befcf14 --- /dev/null +++ b/examples/with_promises/regional_retail_outlet.js @@ -0,0 +1,39 @@ +const x = require('../xendit'); + +const RegionalRetailOutlet = x.RegionalRetailOutlet; +const ro = new RegionalRetailOutlet(); + +ro.createPaymentCode({ + referenceId: 'test_dharma_4', + channelCode: 'CEBUANA', + customerName: 'Dharma', + amount: 50, + currency: 'PHP', + market: 'PH' +}) + .then(r => { + // eslint-disable-next-line no-console + console.log('fixed payment code created:', r); + return r; + }) + .then(({ id }) => ro.getPaymentCode({ id })) + .then(r => { + // eslint-disable-next-line no-console + console.log('fixed payment code details:', r); + return r; + }) + .then(({ id }) => { + return ro.updatePaymentCode({ + id, + customerName: "DharmaLain", + }); + }) + .then(r => { + // eslint-disable-next-line no-console + console.log('updated payment code details:', r); + return r; + }) + .catch(e => { + console.error(e); // eslint-disable-line no-console + process.exit(1); + }); diff --git a/integration_test/index.js b/integration_test/index.js index 1126486..cc499a8 100644 --- a/integration_test/index.js +++ b/integration_test/index.js @@ -13,6 +13,7 @@ Promise.all([ require('./platform.test')(), require('./customer.test')(), require('./direct_debit.test')(), + require('./regional_retail_outlet.test')(), ]) .then(() => { // eslint-disable-next-line no-console diff --git a/integration_test/regional_retail_outlet.test.js b/integration_test/regional_retail_outlet.test.js new file mode 100644 index 0000000..33388a7 --- /dev/null +++ b/integration_test/regional_retail_outlet.test.js @@ -0,0 +1,27 @@ +const x = require('./xendit_ph.test'); + +const RegionalRetailOutlet = x.RegionalRetailOutlet; +const ro = new RegionalRetailOutlet({}); + +const dynamicReferenceId = Math.floor((Math.random() * 9999) + 1) + +module.exports = function() { + return ro + .createPaymentCode({ + referenceId: `test_dharma_${dynamicReferenceId}`, + channelCode: 'CEBUANA', + customerName: 'Dharma', + amount: 50, + currency: 'PHP', + market: 'PH' + }) + .then(({ id }) => ro.getPaymentCode({ id })) + .then(({ id }) => ro.updatePaymentCode({ id: id, customerName: "DharmaLain" })) + .then(() => { + // eslint-disable-next-line no-console + console.log('Regional Retail outlet integration test done...'); + }) + .catch(e => { + throw new Error(`Regional RO integration tests failed with error: ${e.message}`); + }); +}; diff --git a/integration_test/va.test.js b/integration_test/va.test.js index c62cc13..cdee1ad 100644 --- a/integration_test/va.test.js +++ b/integration_test/va.test.js @@ -11,7 +11,7 @@ module.exports = function () { .getVABanks() .then(banks => { return va.createFixedVA({ - externalID: 'VA-' + new Date().toLocaleString(), + externalID: 'VA-xendit-node-js998877', bankCode: banks[0].code, name: 'Stanley Nguyen', isClosed: true, @@ -23,10 +23,10 @@ module.exports = function () { return va.getFixedVA({ id }) }) .then(({ id }) => { + sleepFor(5000); return va.updateFixedVA({ id, - suggestedAmt: 10000, - expectedAmt: 10000, + expectedAmt: 12000, }); }) .then(() => { diff --git a/integration_test/xendit_ph.test.js b/integration_test/xendit_ph.test.js new file mode 100644 index 0000000..fe2d6cd --- /dev/null +++ b/integration_test/xendit_ph.test.js @@ -0,0 +1,12 @@ +// For actual usage, this should be require('xendit-node') +const Xendit = require('../src/xendit'); +const dotenv = require('dotenv'); + +dotenv.config(); + +const xph = new Xendit({ + secretKey: process.env.SECRET_KEY_PH, + xenditURL: process.env.XENDIT_URL, +}); + +module.exports = xph; diff --git a/package.json b/package.json index d03b6de..0fdc1f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xendit-node", - "version": "1.19.2", + "version": "1.19.3", "description": "NodeJS client for Xendit API", "main": "index.js", "types": "index.d.ts", diff --git a/src/regional_retail_outlet/index.d.ts b/src/regional_retail_outlet/index.d.ts new file mode 100644 index 0000000..3c47edf --- /dev/null +++ b/src/regional_retail_outlet/index.d.ts @@ -0,0 +1,3 @@ +import RegionalRetailOutletService from './regional_retail_outlet'; + +export { RegionalRetailOutletService }; diff --git a/src/regional_retail_outlet/index.js b/src/regional_retail_outlet/index.js new file mode 100644 index 0000000..c9ac636 --- /dev/null +++ b/src/regional_retail_outlet/index.js @@ -0,0 +1,3 @@ +const RegionalRetailOutletService = require('./regional_retail_outlet'); + +module.exports = { RegionalRetailOutletService }; diff --git a/src/regional_retail_outlet/regional_retail_outlet.d.ts b/src/regional_retail_outlet/regional_retail_outlet.d.ts new file mode 100644 index 0000000..4b42dbf --- /dev/null +++ b/src/regional_retail_outlet/regional_retail_outlet.d.ts @@ -0,0 +1,28 @@ +import { XenditOptions } from '../xendit_opts'; + +export = class RegionalRetailOutlet { + constructor({}); + static _constructorWithInjectedXenditOpts: ( + opts: XenditOptions, + ) => typeof RetailOutlet; + createPaymentCode(data: { + reference_id: string; + channel_code: string; + amount: number; + currency: number; + customer_name: string; + market: string; + payment_code?: string; + expires_at?: Date; + is_single_use?: boolean; + desciption?: string; + metadata?: object[]; + }): Promise; + updateFixedPaymentCode(data: { + id: string; + name?: string; + expectedAmt?: number; + expirationDate?: Date; + }): Promise; + getFixedPaymentCode(data: { id: string }): Promise; +}; diff --git a/src/regional_retail_outlet/regional_retail_outlet.js b/src/regional_retail_outlet/regional_retail_outlet.js new file mode 100644 index 0000000..d7d73c9 --- /dev/null +++ b/src/regional_retail_outlet/regional_retail_outlet.js @@ -0,0 +1,95 @@ +const { promWithJsErr, Validate, fetchWithHTTPErr, Auth } = require('../utils'); + +const REGIONAL_RETAIL_OUTLET_PATH = '/payment_codes'; + +function RegionalRetailOutlet(options) { + let aggOpts = options; + if ( + RegionalRetailOutlet._injectedOpts && + Object.keys(RegionalRetailOutlet._injectedOpts).length > 0 + ) { + aggOpts = Object.assign({}, options, RegionalRetailOutlet._injectedOpts); + } + + this.opts = aggOpts; + this.API_ENDPOINT = this.opts.xenditURL + REGIONAL_RETAIL_OUTLET_PATH; +} + +RegionalRetailOutlet._injectedOpts = {}; +RegionalRetailOutlet._constructorWithInjectedXenditOpts = function(options) { + RegionalRetailOutlet._injectedOpts = options; + return RegionalRetailOutlet; +}; + +RegionalRetailOutlet.prototype.createPaymentCode = function(data) { + return promWithJsErr((resolve, reject) => { + Validate.rejectOnMissingFields( + ['referenceId', 'channelCode', 'amount', 'currency', 'customerName', 'market'], + data, + reject, + ); + + fetchWithHTTPErr(`${this.API_ENDPOINT}`, { + method: 'POST', + headers: { + Authorization: Auth.basicAuthHeader(this.opts.secretKey), + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + reference_id: data.referenceId, + channel_code: data.channelCode, + amount: data.amount, + currency: data.currency, + customer_name: data.customerName, + market: data.market, + payment_code: data.paymentCode, + description: data.description, + metadata: data.metadata, + expires_at: data.expiresAt + ? data.expiresAt.toISOString() + : undefined, + is_single_use: data.isSingleUse, + }), + }) + .then(resolve) + .catch(reject); + }); +}; + +RegionalRetailOutlet.prototype.updatePaymentCode = function(data) { + return promWithJsErr((resolve, reject) => { + Validate.rejectOnMissingFields(['id'], data, reject); + + fetchWithHTTPErr(`${this.API_ENDPOINT}/${data.id}`, { + method: 'PATCH', + headers: { + Authorization: Auth.basicAuthHeader(this.opts.secretKey), + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + amount: data.amount, + currency: data.amount, + customer_name: data.customerName + }), + }) + .then(resolve) + .catch(reject); + }); +}; + +RegionalRetailOutlet.prototype.getPaymentCode = function(data) { + return promWithJsErr((resolve, reject) => { + Validate.rejectOnMissingFields(['id'], data, reject); + + fetchWithHTTPErr(`${this.API_ENDPOINT}/${data.id}`, { + method: 'GET', + headers: { + Authorization: Auth.basicAuthHeader(this.opts.secretKey), + }, + }) + .then(resolve) + .catch(reject); + }); +}; + +module.exports = RegionalRetailOutlet; diff --git a/src/xendit.js b/src/xendit.js index a1000dd..f980b84 100644 --- a/src/xendit.js +++ b/src/xendit.js @@ -11,6 +11,7 @@ const { QrCode } = require('./qr_code'); const { PlatformService } = require('./platform'); const { CustomerService } = require('./customer'); const { DirectDebitService } = require('./direct_debit'); +const { RegionalRetailOutletService } = require('./regional_retail_outlet'); const Errors = require('./errors'); function Xendit(options) { @@ -38,6 +39,9 @@ function Xendit(options) { this.RetailOutlet = RetailOutletService._constructorWithInjectedXenditOpts( this.opts, ); + this.RegionalRetailOutlet = RegionalRetailOutletService._constructorWithInjectedXenditOpts( + this.opts, + ); this.QrCode = QrCode._constructorWithInjectedXenditOpts(this.opts); this.Platform = PlatformService._constructorWithInjectedXenditOpts(this.opts); this.Customer = CustomerService._constructorWithInjectedXenditOpts(this.opts);