Skip to content

Commit

Permalink
Updated Readme
Browse files Browse the repository at this point in the history
Added JSDoc Comments for all public methods
Refactor Constructor to use an object instead of parameters
Refactor header generation strategy to make the code cleaner
  • Loading branch information
shahriar-shojib committed Dec 16, 2020
1 parent 0ad42f5 commit 3f3508e
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 33 deletions.
93 changes: 91 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,98 @@

Nodejs library to accept bkash payments on your backend application

## How to use
---

`Coming soon`
# How to use

## Initializing the library

### `javascript`

> file `bkash.js`
```javascript
const BkashGateway = require('bkash-payment-gateway');

const bkashConfig = {
baseURL: 'https://checkout.sandbox.bka.sh/v1.2.0-beta', //do not add a trailing slash
key: 'abcdxx2369',
username: 'bkashTest',
password: 'bkashPassword1',
secret: 'bkashSup3rS3cRet',
};

const bkash = new BkashGateway(config);
module.exports = bkash;
```

### `typescript`

> file `bkash.ts`
```typescript
import BkashGateway, { ICreatePayment } from 'bkash-payment-gatway';

const bkashConfig: ICreatePayment = {
//get intellisense here
baseURL: 'https://checkout.sandbox.bka.sh/v1.2.0-beta', //do not add a trailing slash
key: 'abcdxx2369',
username: 'bkashTest',
password: 'bkashPassword1',
secret: 'bkashSup3rS3cRet',
};

const bkash = new BkashGateway(config);
export default bkash;
```

---

## Create a payment

```javascript
const paymentRequest = {
amount: 1000,
orderID: 'ORD1020069',
intent: 'sale',
};

const result = await bkash.createPayment();
console.log(result);
```

---

## Execute a payment with payment ID

```javascript
const result = await bkash.executePayment('<Payment ID returned by bkash>');
```

---

## Query a payment with payment ID

```javascript
const result = await bkash.queryPayment('<Payment ID returned by bkash>');
```

---

### Contributing

- Please Follow the code style and use the prettier config and eslint config provided in the repository
- Feel free to open `issues` or `pull request` for any issues and bugfixes
- If you want to implement new features or write documentation about existing features feel free to do it as well
- To see a list of missing features or to-do's, please visit the `project` section of the github repository

---

### License

> MIT
> DISCLAIMER: This software comes with absolutely no warranty and is not affiliated with the company **`Bkash`** in any way. Use at your own risk. Author and Contributors are not responsible for any financial damages, outages etc.
### Author

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bkash-payment-gateway",
"version": "1.0.0",
"version": "1.1.0",
"description": "Bkash Payment Gateway Library to accept payments on your node.js backend",
"main": "dist",
"files": [
Expand Down
106 changes: 78 additions & 28 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import { get, post } from './utils/request';
import { diffSeconds } from './utils/diffSeconds';
import { IHeaders } from './interfaces/headers.interface';

import {
IBkashCreatePaymentResponse,
IBkashExecutePaymentResponse,
IBkashQueryPaymentResponse,
IBkashTokenResponse,
} from './interfaces/bkashResponse.interface';

import { BkashException } from './exceptions/bkashException';
import { ICreatePayment } from './interfaces/createPayment.interface';
import { IBkashConstructor } from './interfaces/main.interface';

/**
* Bkash Payment Gateway Main Entrypoint
*/
class BkashGateway {
private token: string;
private refreshToken: string;
Expand All @@ -18,8 +24,26 @@ class BkashGateway {
private readonly key: string;
private readonly baseURL: string;
private headers: IHeaders;
/**
*
* @param config config object required by the `bkash-payment-gateway` package
* @example
* ```
* const bkashConfig = {
* baseURL: 'https://checkout.sandbox.bka.sh/v1.2.0-beta/',
* key: 'abcdxx2369',
* username: 'bkashTest',
* password: 'bkashPassword1',
* secret: 'bkashSup3rS3cRet',
* }
* const bkash = new BkashGateway(config)
* ```
*
*/

constructor(config: IBkashConstructor) {
const { baseURL, key, password, secret, username } = config;

constructor(baseURL: string, key: string, secret: string, username: string, password: string) {
this.baseURL = baseURL;
this.key = key;
this.secret = secret;
Expand All @@ -29,8 +53,21 @@ class BkashGateway {
};
}

async createPayment(paymentDetails: ICreatePayment): Promise<IBkashCreatePaymentResponse> {
const token = await this.getToken();
/**
*
* @param paymentDetails Information required to start a payment flow
*
* @returns Promise of Bkash Create payment Response
* @example
* ```
* const result = await bkash.createPayment({
* amount: 1000,
* orderID: 'ORD1020069',
* intent: 'sale',
* });
* ```
*/
createPayment = async (paymentDetails: ICreatePayment): Promise<IBkashCreatePaymentResponse> => {
const { amount, intent, orderID, merchantAssociationInfo } = paymentDetails;

const payload = {
Expand All @@ -41,37 +78,49 @@ class BkashGateway {
merchantAssociationInfo: merchantAssociationInfo ?? '',
};

const headers = {
authorization: token,
'x-app-key': this.key,
};
const headers = await this.createTokenHeader();
return await post<IBkashCreatePaymentResponse>(`${this.baseURL}/checkout/payment/create`, payload, headers);
}

async executePayment(paymentID: string): Promise<IBkashExecutePaymentResponse> {
};

/**
* Execute a payment after an user has completed bkash auth flow
* @param paymentID - Payment ID to Execute
* @example
* ```
* const result = await bkash.executePayment(paymentID);
* ```
*/
executePayment = async (paymentID: string): Promise<IBkashExecutePaymentResponse> => {
try {
const token = await this.getToken();
const headers = {
authorization: token,
'x-app-key': this.key,
};

const headers = await this.createTokenHeader();
return await post<IBkashExecutePaymentResponse>(`${this.baseURL}/checkout/payment/execute/${paymentID}`, null, headers);
} catch (error) {
throw new BkashException('Timeout of 30 Seconds Exceeded While Executing Payment, Please Query the Payment');
}
}
};

/**
* Query Payment From Bkash
* @param paymentID - Payment ID to Query
*
* @example
* ```
* const result = await bkash.queryPayment(paymentID);
* ```
*/
queryPayment = async (paymentID: string): Promise<IBkashQueryPaymentResponse> => {
const headers = await this.createTokenHeader();
return await get<IBkashQueryPaymentResponse>(`${this.baseURL}/checkout/payment/query/${paymentID}`, headers);
};

async queryPayment(paymentID: string): Promise<IBkashQueryPaymentResponse> {
private createTokenHeader = async (): Promise<IHeaders> => {
const token = await this.getToken();
const headers = {
return {
authorization: token,
'x-app-key': this.key,
};
return await get<IBkashQueryPaymentResponse>(`${this.baseURL}/checkout/payment/query/${paymentID}`, headers);
}

async getToken(): Promise<string> {
};
private getToken = async (): Promise<string> => {
if (this.token) {
const diff = diffSeconds(this.tokenIssueTime);
if (diff > 3500) {
Expand Down Expand Up @@ -99,9 +148,9 @@ class BkashGateway {
this.tokenIssueTime = Date.now();
return this.token;
}
}
};

private getInitialToken(): Promise<IBkashTokenResponse> {
private getInitialToken = (): Promise<IBkashTokenResponse> => {
return post<IBkashTokenResponse>(
`${this.baseURL}/checkout/token/grant`,
{
Expand All @@ -110,9 +159,9 @@ class BkashGateway {
},
this.headers
);
}
};

private newToken(refresh: string): Promise<IBkashTokenResponse> {
private newToken = (refresh: string): Promise<IBkashTokenResponse> => {
return post<IBkashTokenResponse>(
`${this.baseURL}/checkout/token/refresh`,
{
Expand All @@ -122,6 +171,7 @@ class BkashGateway {
},
this.headers
);
}
};
}

export default BkashGateway;
7 changes: 7 additions & 0 deletions src/interfaces/main.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface IBkashConstructor {
baseURL: string;
key: string;
secret: string;
username: string;
password: string;
}
4 changes: 2 additions & 2 deletions src/utils/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ interface IPayload {
[key: string]: unknown;
}

export function get<T>(url: string, additionalHeaders: IHeaders, returnsJSON = true): Promise<T> {
export function get<T>(url: string, additionalHeaders: IHeaders): Promise<T> {
return fetch(url, {
method: 'GET',
headers: {
'content-type': 'application/json',
Accept: 'application/json',
...additionalHeaders,
},
}).then((r) => (returnsJSON ? r.json() : r.text()));
}).then((r) => r.json());
}

export async function post<T>(url: string, payload: IPayload = {}, additionalHeaders: IHeaders): Promise<T> {
Expand Down

0 comments on commit 3f3508e

Please sign in to comment.