Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/xendit/xendit-node
Browse files Browse the repository at this point in the history
  • Loading branch information
dharmasatrya committed Nov 8, 2022
2 parents 2a4eacb + c99636d commit 2ceccc8
Show file tree
Hide file tree
Showing 13 changed files with 472 additions and 0 deletions.
66 changes: 66 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ For PCI compliance to be maintained, tokenization of credit cards info should be
- [Set Callback URL](#set-callback-url)
- [Create transfers](#create-transfers)
- [Create fee rules](#create-fee-rules)
- [Refund Services](#refund-services)
- [Create refund](#create-refund-1)
- [List refunds](#list-refunds)
- [Get refund details by ID](#get-refund-details-by-id)
- [Contributing](#contributing)

<!-- tocstop -->
Expand Down Expand Up @@ -1599,6 +1603,68 @@ p.createFeeRule(data: {
})
```
### Refund Services
Instanitiate Refund service using constructor that has been injected with Xendit keys
```js
const { Refund } = x;
const r = new Refund();
```
Example: Create a refund
```js
r.createRefund({
invoice_id: 'your-invoice-id',
reason: 'FRAUDULENT',
amount: 1000,
}).then(({ id }) => {
console.log(`refund created with ID: ${id}`);
});
```
Refer to [Xendit API Reference](https://developers.xendit.co/api-reference/#refunds) for more info about methods' parameters
#### Create refund
```ts
r.createRefund(data: {
payment_request_id?: string;
reference_id?: string;
invoice_id?: string;
currency?: string;
amount?: number;
reason: RefundReasons;
metadata?: object;
idempotencty_key?: string;
for_user_id?: string;
})
```
#### List refunds
```ts
r.listRefunds(data: {
payment_request_id?: string;
invoice_id?: string;
payment_method_type?: string;
channel_code?: string;
limit?: number;
after_id?: string;
before_id?: string;
for_user_id?: string;
})
```
#### Get refund details by ID
```ts
r.getRefundById(data: {
id: string;
})
```
## Contributing
Running test suite
Expand Down
28 changes: 28 additions & 0 deletions examples/with_async/refund.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const x = require('../xendit');

const { Refund } = x;
const r = new Refund({});

(async function() {
try {
let refund = await r.createRefund({
invoice_id: '63676ed0eb10cf38ce0550b7',
reason: 'OTHERS',
amount: 1,
});
console.log('created refund', refund); // eslint-disable-line no-console

const refundDetails = await r.getRefundById({ id: refund.id });
// eslint-disable-next-line no-console
console.log('retrieved refund', refundDetails);

const refundList = await r.listRefunds({});
// eslint-disable-next-line no-console
console.log('list of refunds', refundList);

process.exit(0);
} catch (e) {
console.error(e); // eslint-disable-line no-console
process.exit(1);
}
})();
34 changes: 34 additions & 0 deletions examples/with_promises/refund.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const x = require('../xendit');

const Refund = x.Refund;
const ref = new Refund();

ref
.createRefund({
invoice_id: '63676ed0eb10cf38ce0550b7',
reason: 'OTHERS',
amount: 1,
})
.then(r => {
// eslint-disable-next-line no-console
console.log('refund created:', r);
return r;
})
.then(({ id }) => ref.getRefundById({ id }))
.then(r => {
// eslint-disable-next-line no-console
console.log('refund details:', r);
return r;
})
.then(() => {
return ref.listRefunds({});
})
.then(r => {
// eslint-disable-next-line no-console
console.log(':', r);
return r;
})
.catch(e => {
console.error(e); // eslint-disable-line no-console
process.exit(1);
});
1 change: 1 addition & 0 deletions integration_test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Promise.all([
require('./direct_debit.test')(),
require('./report.test')(),
require('./transaction.test')(),
// require('./refund.test')() //test disabled until refunds endpoint is fixed
])
.then(() => {
Promise.all([require('./regional_retail_outlet.test')()]).then(() =>
Expand Down
28 changes: 28 additions & 0 deletions integration_test/refund.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const x = require('./xendit.test');

const { Refund } = x;
const r = new Refund({});

module.exports = function() {
return r
.createRefund({
invoice_id: '63676ed0eb10cf38ce0550b7',
reason: 'FRAUDULENT',
amount: 1,
})
.then(id => {
r.getRefundById({ id });
})
.then(() => {
r.listRefunds({});
})
.then(() => {
// eslint-disable-next-line no-console
console.log('QR Code integration test done...');
})
.catch(e => {
throw new Error(
`Recurring integration tests failed with error: ${e.message}`,
);
});
};
3 changes: 3 additions & 0 deletions src/refund/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import RefundService from './refund';

export { RefundService };
3 changes: 3 additions & 0 deletions src/refund/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const RefundService = require('./refund');

module.exports = { RefundService };
39 changes: 39 additions & 0 deletions src/refund/refund.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
enum RefundReasons {
Fraudulent = 'FRAUDULENT',
Duplicate = 'DUPLICATE',
RequestedByCustomer = 'REQUESTED_BY_CUSTOMER',
Cancellation = 'CANCELLATION',
Others = 'OTHERS',
}

export = class Refund {
constructor({});
static _constructorWithInjectedXenditOpts: (
opts: XenditOptions,
) => typeof Refund;

createRefund(data: {
payment_request_id?: string;
reference_id?: string;
invoice_id?: string;
currency?: string;
amount?: number;
reason: RefundReasons;
metadata?: object;
idempotencty_key?: string;
for_user_id?: string;
}): Promise<object>;

listRefunds(data: {
payment_request_id?: string;
invoice_id?: string;
payment_method_type?: string;
channel_code?: string;
limit?: number;
after_id?: string;
before_id?: string;
for_user_id?: string;
}): Promise<object>;

getRefundById(data: { id: string }): Promise<object>;
};
128 changes: 128 additions & 0 deletions src/refund/refund.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
const {
promWithJsErr,
Validate,
fetchWithHTTPErr,
Auth,
queryStringWithoutUndefined,
} = require('../utils');

const REFUND_PATH = '/refunds';

function Refund(options) {
let aggOpts = options;
if (Refund._injectedOpts && Object.keys(Refund._injectedOpts).length > 0) {
aggOpts = Object.assign({}, options, Refund._injectedOpts);
}

this.opts = aggOpts;
this.API_ENDPOINT = this.opts.xenditURL + REFUND_PATH;
}

Refund._injectedOpts = {};
Refund._constructorWithInjectedXenditOpts = function(options) {
Refund._injectedOpts = options;
return Refund;
};

Refund.prototype.createRefund = function(data) {
return promWithJsErr((resolve, reject) => {
Validate.rejectOnMissingFields(['reason', 'amount'], data, reject);

let headers = {
Authorization: Auth.basicAuthHeader(this.opts.secretKey),
'Content-Type': 'application/json',
};

if (data && data.for_user_id) {
headers['for-user-id'] = data.for_user_id;
}

if (data && data.idempotency_key) {
headers['idempotency-key'] = data.idempotency_key;
}

fetchWithHTTPErr(`${this.API_ENDPOINT}`, {
method: 'POST',
headers,
body: JSON.stringify({
payment_request_id: data.payment_request_id,
reference_id: data.reference_id,
invoice_id: data.invoice_id,
currency: data.currency,
amount: data.amount,
reason: data.reason,
metadata: data.metadata,
}),
})
.then(resolve)
.catch(reject);
});
};

Refund.prototype.getRefundById = function(data) {
return promWithJsErr((resolve, reject) => {
Validate.rejectOnMissingFields(['id'], data, reject);

let headers = {
Authorization: Auth.basicAuthHeader(this.opts.secretKey),
'Content-Type': 'application/json',
};

if (data && data.for_user_id) {
headers['for-user-id'] = data.forUserID;
}

if (data && data.idempotency_key) {
headers['idempotency-key'] = data.idempotency_key;
}

fetchWithHTTPErr(`${this.API_ENDPOINT}/${data.id}`, {
method: 'GET',
headers,
})
.then(resolve)
.catch(reject);
});
};

Refund.prototype.listRefunds = function(data) {
return promWithJsErr((resolve, reject) => {
Validate.rejectOnMissingFields([], data, reject);

let headers = {
Authorization: Auth.basicAuthHeader(this.opts.secretKey),
'Content-Type': 'application/json',
};

if (data && data.for_user_id) {
headers['for-user-id'] = data.for_user_id;
}

const queryStr = data
? queryStringWithoutUndefined({
payment_request_id: data.payment_request_id
? data.payment_request_id
: undefined,
invoice_id: data.invoice_id ? data.invoice_id : undefined,
payment_method_id: data.payment_method_id
? data.payment_method_id
: undefined,
channel_code: data.channel_code ? data.channel_code : undefined,
limit: data.limit ? data.limit : undefined,
after_id: data.after_id ? data.after_id : undefined,
before_id: data.before_id ? data.before_id : undefined,
})
: '';

const queryStrWithQuestionMark = queryStr ? `?${queryStr}` : '';

fetchWithHTTPErr(`${this.API_ENDPOINT}${queryStrWithQuestionMark}`, {
method: 'GET',
headers,
})
.then(resolve)
.catch(reject);
});
};

module.exports = Refund;
2 changes: 2 additions & 0 deletions src/xendit.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { CustomerService } from './customer';
import { DirectDebitService } from './direct_debit';
import { ReportService } from './report';
import { TransactionService } from './transaction';
import { RefundService } from './refund';

declare class Xendit {
constructor(opts: XenditOptions);
Expand All @@ -37,5 +38,6 @@ declare class Xendit {
DirectDebit: typeof DirectDebitService;
Report: typeof ReportService;
Transaction: typeof TransactionService;
Refund: typeof RefundService;
}
export = Xendit;
2 changes: 2 additions & 0 deletions src/xendit.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const { DirectDebitService } = require('./direct_debit');
const { RegionalRetailOutletService } = require('./regional_retail_outlet');
const { ReportService } = require('./report');
const { TransactionService } = require('./transaction');
const { RefundService } = require('./refund');
const Errors = require('./errors');

function Xendit(options) {
Expand Down Expand Up @@ -57,6 +58,7 @@ function Xendit(options) {
this.Transaction = TransactionService._constructorWithInjectedXenditOpts(
this.opts,
);
this.Refund = RefundService._constructorWithInjectedXenditOpts(this.opts);
}

Xendit.Errors = Errors;
Expand Down
Loading

0 comments on commit 2ceccc8

Please sign in to comment.