├── .eslintrc.js ├── .github └── workflows │ ├── pr.yml │ └── publish.yml ├── .gitignore ├── .prettierrc ├── CHANGELOG.md ├── LICENSE ├── README.md ├── jestconfig.json ├── package-lock.json ├── package.json ├── src ├── apple │ ├── README.md │ ├── apple.ts │ └── interface.ts ├── bulkcharge │ ├── bulkcharge.ts │ └── interface.ts ├── charge │ ├── README.md │ ├── charge.ts │ └── interface.ts ├── customer │ ├── README.md │ ├── customer.ts │ └── interface.ts ├── dedicated │ ├── dedicated.ts │ ├── index.ts │ └── interface.ts ├── index.ts ├── interface.ts ├── invoice │ ├── interface.ts │ └── invoice.ts ├── payment │ ├── interface.ts │ └── payment.ts ├── paystack.ts ├── plan │ ├── README.md │ ├── index.ts │ ├── interface.ts │ └── plan.ts ├── product │ ├── index.ts │ ├── interface.ts │ └── product.ts ├── recipient │ ├── interface.ts │ └── recipient.ts ├── refund │ ├── interface.ts │ └── refund.ts ├── settlement │ ├── interface.ts │ └── settlement.ts ├── split │ ├── interface.ts │ └── split.ts ├── subaccounts │ ├── interface.ts │ └── subaccount.ts ├── subscription │ ├── index.ts │ ├── interface.ts │ └── subscription.ts ├── transaction │ ├── README.md │ ├── interface.ts │ └── transaction.ts ├── transfer │ ├── control.ts │ ├── interface.ts │ └── transfer.ts └── verification │ ├── interface.ts │ └── verification.ts ├── test.ts ├── tsconfig.json └── tslint.json /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended" 9 | ], 10 | "parser": "@typescript-eslint/parser", 11 | "parserOptions": { 12 | "ecmaVersion": 14, 13 | "sourceType": "module" 14 | }, 15 | "plugins": [ 16 | "@typescript-eslint" 17 | ], 18 | "rules": { 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | name: PR Build 2 | on: [pull_request] 3 | jobs: 4 | size: 5 | runs-on: ubuntu-latest 6 | env: 7 | CI_JOB_NUMBER: 1 8 | steps: 9 | - uses: actions/checkout@v3 10 | - name: setup node 11 | uses: actions/setup-node@v3 12 | with: 13 | node-version: 16 14 | - name: install dependencies 15 | run: | 16 | npm install 17 | CI=true npm run build 18 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Package 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | - uses: actions/setup-node@v3 13 | with: 14 | node-version: '16.x' 15 | registry-url: https://registry.npmjs.org/ 16 | 17 | - name: gitconfig 18 | run: | 19 | git config --global user.email "${{github.actor}}@users.noreply.github.com" 20 | git config --global user.name "${{github.actor}}" 21 | 22 | - run: npm install 23 | - run: npm version ${{ github.event.release.tag_name }} 24 | - name: Create .env with github secrets and run script 25 | run: | 26 | touch .env 27 | echo GITHUB_TOKEN=$GITHUB_TOKEN >> .env 28 | echo NODE_AUTH_TOKEN=$NODE_AUTH_TOKEN >> .env 29 | npm publish --access public 30 | env: 31 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | test.js 106 | 107 | yarn.lock 108 | .DS_Store -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "trailingComma": "all", 4 | "singleQuote": true 5 | } 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | #### 1.0.4 (2021-12-06) 2 | 3 | ##### Other Changes 4 | 5 | * **plan:** added methods for plan ([d68ff371](https://github.com/en1tan/paystack-node/commit/d68ff371a90b363ea087bbd5d7cfbece14ca216b)) 6 | 7 | #### 1.0.3 (2021-12-06) 8 | 9 | ##### Other Changes 10 | 11 | * **transactions:** added initialize transaction, verify transaction, list transactions ([73c85a83](https://github.com/en1tan/paystack-node/commit/73c85a83b1ae52b4be63e3d77b8c8ff64588b8e2)) 12 | * **charge:** compeleted the endpoints, what remains is custom validtion and comments ([cc3165ce](https://github.com/en1tan/paystack-node/commit/cc3165ce772ac574cdfbcda082ff22f67e9c8945)) 13 | 14 | #### 1.0.3 (2021-12-06) 15 | 16 | ##### Other Changes 17 | 18 | * **charge:** compeleted the endpoints, what remains is custom validtion and comments ([cc3165ce](https://github.com/en1tan/paystack-node/commit/cc3165ce772ac574cdfbcda082ff22f67e9c8945)) 19 | 20 | - ✍🏻 UPDATE(charge): compeleted the endpoints, what remains is custom validtion and comments 21 | - 1.0.3 22 | - ✍🏻 UPDATE(charge): compeleted the endpoints, what remains is custom validtion and comments 23 | - 1.0.2 24 | - 🐞 FIX(main entry file): 25 | - 1.0.1 26 | - ✍🏻 UPDATE(travis): for automated builds 27 | - 🐞 FIX(main entry file): 28 | - 📦 NEW(set up sdk): 29 | - Initial commit 30 | 31 | ## [Unreleased] 32 | - Expose `bulkcharge` module 33 | - Add `verification` module 34 | 35 | ### Added 36 | - Automatic publish 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Asaju Enitan Michael 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Paystack SDK 2 | 3 | #### Why Another [Paystack](https://paystack.com) Package? 4 | 5 | Existing Paystack libraries are either outdated, lack modern features, or fail to support TypeScript. This package addresses these gaps by providing: 6 | - Full TypeScript support for type safety and better developer experience. 7 | - A modern, actively maintained library aligned with Paystack’s latest API updates. 8 | - Clean, intuitive APIs designed for ease of use. 9 | 10 | ### Installation 11 | 12 | For Yarn 13 | `yarn add paystack-sdk` 14 | 15 | For NPM 16 | `npm install paystack-sdk` 17 | 18 | ### Usage 19 | 20 | For Typescript 21 | 22 | ```typescript 23 | import {Paystack} from 'paystack-sdk'; 24 | 25 | const paystack = new Paystack("secret_key"); 26 | ``` 27 | 28 | For Javscript 29 | 30 | ```javascript 31 | const Paystack = require('paystack-sdk').Paystack; 32 | const paystack = new Paystack('secret_key'); 33 | ``` 34 | 35 | OR 36 | 37 | ```javascript 38 | const { Paystack } = require('paystack-sdk'); 39 | const paystack = new Paystack('secret_key'); 40 | ``` 41 | 42 | All methods use promise meaning you can either use the `async...await` or `then...catch` or `try...catch` 43 | 44 | ### Modules 45 | 46 | - [x] Charge 47 | - [x] Customers 48 | - [x] Plans 49 | - [x] Products 50 | - [x] Subscriptions 51 | - [x] Transactions 52 | - [x] Transfers 53 | - [x] Dedicated Virtual Accounts 54 | - [x] Apple Pay 55 | - [x] Subaccounts 56 | - [x] Transaction Splits 57 | - [x] Settlements 58 | - [x] Invoices 59 | - [x] Transaction Recipients 60 | - [x] Transfers Control 61 | - [x] Bulk Charges 62 | - [ ] Control Panel 63 | - [ ] Disputes 64 | - [x] Refunds 65 | - [x] Verification 66 | - [ ] Miscellaneous 67 | 68 | ## CONTRIBUTING 69 | 70 | If you notice a missing function, or maybe a bug. Please feel free to submit 71 | a PR. I will take a look at it. 72 | You will need to fork the repo and create a PR against it with your changes. 73 | Thank you :smile: 74 | -------------------------------------------------------------------------------- /jestconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "transform": { 3 | "^.+\\.ts?$": "ts-jest" 4 | }, 5 | "testEnvironment": "node", 6 | "testRegex": "/tests/.*\\.(test|spec)?\\.(ts|.tsx)$", 7 | "moduleFileExtensions": ["ts", "tsx", "json", "js", "jsx", "node"] 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "paystack-sdk", 3 | "version": "2.5.24", 4 | "description": "Paystack SDK written in Typescript", 5 | "main": "dist/index.js", 6 | "author": "Tech Priest", 7 | "license": "MIT", 8 | "private": false, 9 | "scripts": { 10 | "build": "tsc", 11 | "format": "prettier --write \"src/**/*.ts\"", 12 | "lint": "tslint -p tsconfig.json", 13 | "prepare": "npm run build", 14 | "prepublishOnly": "npm run lint", 15 | "preversion": "npm run lint", 16 | "version": "npm run format && git add -A src", 17 | "postversion": "git push && git push --tags" 18 | }, 19 | "devDependencies": { 20 | "@types/node": "16.11.11", 21 | "@typescript-eslint/eslint-plugin": "5.36.2", 22 | "@typescript-eslint/parser": "5.36.2", 23 | "eslint": "8.6.0", 24 | "prettier": "2.5.1", 25 | "ts-node": "10.4.0", 26 | "tslint": "6.1.3", 27 | "tslint-config-prettier": "1.18.0", 28 | "typescript": "4.5.2", 29 | "typescript-eslint": "0.0.1-alpha.0" 30 | }, 31 | "dependencies": { 32 | "axios": "^1.6.7" 33 | }, 34 | "files": [ 35 | "dist/**/*" 36 | ], 37 | "keywords": [ 38 | "Paystack", 39 | "Typescript", 40 | "payment", 41 | "node" 42 | ], 43 | "repository": { 44 | "type": "git", 45 | "url": "git+https://github.com/tekpriest/paystack-node.git" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/apple/README.md: -------------------------------------------------------------------------------- 1 | # Apple Pay 2 | 3 | The Apple Pay API allows you register your application's top-level domain or subdomain 4 | -------------------------------------------------------------------------------- /src/apple/apple.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { BadRequest } from '../interface'; 3 | import { 4 | DomainRegisterResponse, 5 | ListDomainsResponse, 6 | UnregisterDomainRegisterResponse, 7 | } from './interface'; 8 | 9 | export class ApplePay { 10 | private http: Axios; 11 | constructor(http: Axios) { 12 | this.http = http; 13 | } 14 | 15 | async registerDomain( 16 | domainName: string, 17 | ): Promise { 18 | return await this.http.post( 19 | '/apple-pay/domain', 20 | JSON.stringify({ domainName }), 21 | ); 22 | } 23 | 24 | async listDomains(): Promise { 25 | return await this.http.get('/apple-pay'); 26 | } 27 | 28 | async unregisterDomain( 29 | domainName: string, 30 | ): Promise { 31 | return await this.http.delete('/apple-pay', { 32 | params: { domainName }, 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/apple/interface.ts: -------------------------------------------------------------------------------- 1 | export interface Response { 2 | status: boolean; 3 | message: string; 4 | } 5 | 6 | export type DomainRegisterResponse = Response; 7 | export type UnregisterDomainRegisterResponse = Response; 8 | 9 | export interface ListDomainsResponse extends Response { 10 | data: { 11 | domainNames: string[]; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /src/bulkcharge/bulkcharge.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { BadRequest, QueryParams, Response } from '../interface'; 3 | import { 4 | FetchBulkBatchChargeResponse, 5 | FetchChargesInBatchResponse, 6 | InitiateBulkCharge, 7 | InitiateBulkChargeResponse, 8 | ListBulkChargeBatchesResponse, 9 | QueryBatchChargesParams, 10 | } from './interface'; 11 | 12 | export class BulkCharge { 13 | http: Axios; 14 | constructor(http: Axios) { 15 | this.http = http; 16 | } 17 | 18 | async initiate( 19 | data: InitiateBulkCharge[], 20 | ): Promise { 21 | return await this.http.post('/bulkcharge', JSON.stringify(data)); 22 | } 23 | 24 | async list( 25 | queryParams?: QueryParams, 26 | ): Promise { 27 | return await this.http.get('/bulkcharge', { params: { ...queryParams } }); 28 | } 29 | 30 | async fetchBulkCharge( 31 | id: string, 32 | ): Promise { 33 | return await this.http.get(`/bulkcharge/${id}`); 34 | } 35 | 36 | async fetchBatchChrges( 37 | id: string, 38 | queryParams?: QueryBatchChargesParams, 39 | ): Promise { 40 | return await this.http.get(`/bulkcharge/${id}/charges`, { 41 | params: { ...queryParams }, 42 | }); 43 | } 44 | 45 | async pause(batchCode: string): Promise { 46 | return await this.http.get(`/bulkcharge/pause/${batchCode}`); 47 | } 48 | 49 | async resume(batchCode: string): Promise { 50 | return await this.http.get(`/bulkcharge/resume/${batchCode}`); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/bulkcharge/interface.ts: -------------------------------------------------------------------------------- 1 | import { Charge } from '../charge/interface'; 2 | import { Meta, QueryParams, Response } from '../interface'; 3 | 4 | export interface InitiateBulkCharge { 5 | authorization: string; 6 | amount: number; 7 | reference: string; 8 | } 9 | 10 | export interface BulkCharge { 11 | id: number; 12 | domain: string; 13 | batch_code: string; 14 | status: 'active' | 'paused' | 'complete'; 15 | integration?: number; 16 | reference?: string; 17 | total_charges?: number; 18 | pending_charges?: number; 19 | createdAt: Date; 20 | updatedAt: Date; 21 | } 22 | 23 | export interface ListBulkChargeBatchesResponse extends Response { 24 | data: BulkCharge[]; 25 | meta: Meta; 26 | } 27 | 28 | export interface InitiateBulkChargeResponse extends Response { 29 | data: BulkCharge; 30 | } 31 | 32 | export interface FetchBulkBatchChargeResponse extends Response { 33 | data: BulkCharge; 34 | } 35 | 36 | export interface FetchChargesInBatchResponse extends Response { 37 | data: Charge; 38 | } 39 | 40 | export interface QueryBatchChargesParams extends QueryParams { 41 | status: 'pending' | 'success' | 'failed'; 42 | } 43 | -------------------------------------------------------------------------------- /src/charge/README.md: -------------------------------------------------------------------------------- 1 | # Charge 2 | Import the package 3 | For Typescript 4 | ``` 5 | import Paystack from 'paystack-sdk' 6 | const paystack = new Paystack("secret_key); 7 | ``` 8 | 9 | For Javscript 10 | ``` 11 | const Paystack = require('paystack-sdk'); 12 | const paystack = new Paystack("secret_key") 13 | ``` 14 | 15 | ### Full Example 16 | _Using bank details, a birthday and two OTPs_ 17 | ``` 18 | paystack.charge 19 | .create({ 20 | amount: 2000, 21 | email: 'john@doe.com', 22 | bank: { 23 | account_number: '0000000000', 24 | code: '057', 25 | }, 26 | }) 27 | .then(async (charge) => { 28 | if (charge.data.status === 'send_birthday') { 29 | const response = await paystack.charge.submitBirthday({ 30 | birthday: '1961-09-21', 31 | reference: charge.data.reference, 32 | }); 33 | if (response.data.status === 'send_otp') { 34 | try { 35 | const result = await paystack.charge.submitOTP({ 36 | otp: '123456', 37 | reference: charge.data.reference, 38 | }); 39 | paystack.charge 40 | .submitOTP({ 41 | otp: '123456', 42 | reference: charge.data.reference, 43 | }) 44 | .then((payment) => console.log(payment)); 45 | } catch (err) { 46 | console.error(err); 47 | } 48 | } 49 | } 50 | }); 51 | ``` 52 | 53 | ### Create Charge 54 | ``` 55 | paystack.charge 56 | .create({ 57 | amount: 2000, 58 | email: 'john@doe.com', 59 | }) 60 | .then((charge) => console.log(charge)); 61 | ``` 62 | ### Submit PIN 63 | ``` 64 | paystack.charge 65 | .submitPIN({ 66 | pin: '1234', 67 | reference: '5bwib5v6anhe9xa', 68 | }) 69 | .then((charge) => console.log(charge)); 70 | ``` 71 | 72 | ### Submit OTP 73 | ``` 74 | paystack.charge 75 | .submitOTP({ 76 | otp: '123456', 77 | reference: '5bwib5v6anhe9xa', 78 | }) 79 | .then((charge) => console.log(charge)); 80 | ``` 81 | 82 | ### Submit Phone 83 | ``` 84 | paystack.charge 85 | .submitPhone({ 86 | phone: '08012345678', 87 | reference: '5bwib5v6anhe9xa', 88 | }) 89 | .then((charge) => console.log(charge)); 90 | ``` 91 | 92 | ### Submit Birthday 93 | ``` 94 | paystack.charge 95 | .submitBirthday({ 96 | birthday: '1961-09-21', 97 | reference: '5bwib5v6anhe9xa', 98 | }) 99 | .then((charge) => console.log(charge)); 100 | ``` 101 | 102 | ### Submit Address 103 | ``` 104 | paystack.charge 105 | .submitAddress({ 106 | address: '140 N 2ND ST', 107 | city: 'Stroudsburg', 108 | state: 'PA', 109 | zip_code: '18360', 110 | }) 111 | .then((charge) => console.log(charge)); 112 | ``` 113 | 114 | ### Check Pending Charge 115 | ``` 116 | paystack.charge 117 | .checkPending('5bwib5v6anhe9xa') 118 | .then((charge) => console.log(charge)); 119 | ``` 120 | -------------------------------------------------------------------------------- /src/charge/charge.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { 3 | ChargeCreatedWithAddressResponse, 4 | ChargeCreatedWithBirthdayResponse, 5 | ChargeCreatedWithOTPResponse, 6 | ChargeCreatedWithPendingResponse, 7 | ChargeCreatedWithPhoneResponse, 8 | } from './interface'; 9 | import { 10 | ChargeCreatedResponse, 11 | ChargeCreatedWithPinResponse, 12 | CreateCharge, 13 | SubmitAddress, 14 | SubmitBirthday, 15 | SubmitOTP, 16 | SubmitPhone, 17 | SubmitPIN, 18 | } from './interface'; 19 | 20 | interface BadRequest { 21 | status: boolean; 22 | message: string; 23 | } 24 | 25 | export class Charge { 26 | private http: Axios; 27 | constructor(http: Axios) { 28 | this.http = http; 29 | } 30 | async create( 31 | data: CreateCharge, 32 | ): Promise { 33 | return await this.http.post('/charge', JSON.stringify(data)); 34 | } 35 | 36 | async submitPIN( 37 | data: SubmitPIN, 38 | ): Promise { 39 | return await this.http.post('/charge/submit_pin', JSON.stringify(data)); 40 | } 41 | 42 | async submitOTP( 43 | data: SubmitOTP, 44 | ): Promise { 45 | return await this.http.post('/charge/submit_otp', JSON.stringify(data)); 46 | } 47 | 48 | async submitPhone( 49 | data: SubmitPhone, 50 | ): Promise { 51 | return await this.http.post('/charge/submit_phone', JSON.stringify(data)); 52 | } 53 | 54 | async submitBirthday( 55 | data: SubmitBirthday, 56 | ): Promise { 57 | return await this.http.post( 58 | '/charge/submit_birthday', 59 | JSON.stringify(data), 60 | ); 61 | } 62 | 63 | async submitAddress( 64 | data: SubmitAddress, 65 | ): Promise { 66 | return await this.http.post('/charge/submit_address', JSON.stringify(data)); 67 | } 68 | 69 | async checkPending( 70 | reference: string, 71 | ): Promise { 72 | return await this.http.get('/charge/submit_address', { 73 | params: { reference }, 74 | }); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/charge/interface.ts: -------------------------------------------------------------------------------- 1 | import { Customer } from '../customer/interface'; 2 | import { Response } from '../interface'; 3 | import { Transaction } from '../transaction/interface'; 4 | 5 | export interface Charge { 6 | amount: number; 7 | currency: string; 8 | transaction_date: string; 9 | status: string; 10 | reference: string; 11 | domain: string; 12 | metadata?: Record; 13 | gateway_response: string; 14 | message: string; 15 | channel: string; 16 | ip_address: string; 17 | log?: unknown; 18 | fees: number; 19 | authorization: Authorization; 20 | customer: Customer; 21 | transaction?: Transaction; 22 | display_text: string; 23 | plan: unknown; 24 | fees_split?: string; 25 | paid_at: Date; 26 | } 27 | 28 | // export type ChargeCreatedResponse = 29 | // | ChargeCreated 30 | // | ChargeCreatedWithOTP 31 | // | ChargeCreatedWithPending 32 | // | ChargeCreatedWithAddress 33 | // | ChargeCreatedWithBankAuth 34 | // | ChargeCreatedWithPin 35 | // | ChargeCreatedWithPhone 36 | // | ChargeCreatedWithBirthday 37 | // | ChargeCreatedWithUSSD 38 | // | ChargeCreatedWithMobileMoney 39 | // | ChargeFailed; 40 | 41 | export interface CreateCharge { 42 | email: string; 43 | amount: string; 44 | bank?: { 45 | code: string; 46 | account_number: string; 47 | }; 48 | authorization_code?: string; 49 | pin?: string; 50 | metadata?: Record; 51 | reference?: string; 52 | ussd?: string; 53 | mobile_money?: string; 54 | device_id?: string; 55 | birthday?: string; 56 | } 57 | export interface SubmitPIN { 58 | reference: string; 59 | pin: string; 60 | } 61 | export interface SubmitOTP { 62 | reference: string; 63 | otp: string; 64 | } 65 | 66 | export interface SubmitPhone { 67 | reference: string; 68 | phone: string; 69 | } 70 | 71 | export interface SubmitBirthday { 72 | reference: string; 73 | birthday: Date; 74 | } 75 | 76 | export interface SubmitAddress { 77 | reference: string; 78 | address: string; 79 | city: string; 80 | state: string; 81 | zip_code: string; 82 | } 83 | 84 | export interface ChargeCreatedResponse extends Response { 85 | data: Charge; 86 | } 87 | 88 | export interface ChargeCreatedWithPendingResponse extends Response { 89 | data: { 90 | reference: string; 91 | status: string; 92 | }; 93 | } 94 | 95 | export interface ChargeCreatedWithAddressResponse extends Response { 96 | data: { 97 | display_text: string; 98 | reference: string; 99 | status: string; 100 | country_code: string; 101 | }; 102 | } 103 | 104 | export interface ChargeCreatedWithMobileMoneyResponse extends Response { 105 | data: Charge; 106 | } 107 | 108 | export interface ChargeCreatedWithUSSDResponse extends Response { 109 | data: { 110 | reference: string; 111 | status: string; 112 | display_text: string; 113 | ussd_code: string; 114 | }; 115 | } 116 | 117 | export interface ChargeCreatedWithBirthdayResponse extends Response { 118 | data: { 119 | reference: string; 120 | status: string; 121 | display_text: string; 122 | }; 123 | } 124 | 125 | export interface ChargeCreatedWithBankAuthResponse extends Response { 126 | data: { 127 | refernce: string; 128 | uri: string; 129 | status: string; 130 | }; 131 | } 132 | 133 | export interface ChargeCreatedWithOTPResponse extends Response { 134 | data: { 135 | refernce: string; 136 | status: string; 137 | display_text: string; 138 | }; 139 | } 140 | 141 | export interface ChargeCreatedWithPinResponse extends Response { 142 | data: { 143 | refernce: string; 144 | status: string; 145 | }; 146 | } 147 | 148 | export interface ChargeCreatedWithPhoneResponse extends Response { 149 | data: { 150 | refernce: string; 151 | status: string; 152 | display_text: string; 153 | }; 154 | } 155 | export interface ChargeFailedResponse extends Response { 156 | data: { 157 | refernce: string; 158 | message: string; 159 | status: string; 160 | }; 161 | } 162 | 163 | export interface Authorization { 164 | authorization_code: string; 165 | card_type: string; 166 | bank: string; 167 | bin: string; 168 | brand: string; 169 | channel: string; 170 | country_code: string; 171 | exp_month: string; 172 | exp_year: string; 173 | last4: string; 174 | reusable: boolean; 175 | signature: string; 176 | account_name: string; 177 | } 178 | -------------------------------------------------------------------------------- /src/customer/README.md: -------------------------------------------------------------------------------- 1 | # Customer 2 | 3 | The Customers API allows you create and manage customers on your integration. 4 | -------------------------------------------------------------------------------- /src/customer/customer.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { BadRequest, Response } from '../interface'; 3 | import { ListCustomersResponse } from './interface'; 4 | import { 5 | CreateCustomer, 6 | CustomerCreated, 7 | FetchCustomerResponse, 8 | ListCustomerQueryParams, 9 | SetRiskAction, 10 | UpdateCustomer, 11 | ValidateCustomer, 12 | } from './interface'; 13 | 14 | /** 15 | * # Customers 16 | * The Customers API allows you create and manage 17 | * customers on your integration 18 | */ 19 | export class Customer { 20 | private http: Axios; 21 | constructor(http: Axios) { 22 | this.http = http; 23 | } 24 | 25 | /** 26 | * ## Create Customer 27 | * Create a customer on your integration 28 | * @param {CreateCustomer} data 29 | */ 30 | async create(data: CreateCustomer): Promise { 31 | return await this.http.post('/customer', JSON.stringify(data)); 32 | } 33 | 34 | /** 35 | * ## List Customers 36 | * List customers available on your integration 37 | */ 38 | async list( 39 | queryParams?: ListCustomerQueryParams, 40 | ): Promise { 41 | return await this.http.get('/customer', { 42 | params: { ...queryParams }, 43 | }); 44 | } 45 | 46 | /** 47 | * ## Fetch Customer 48 | * Get details of a customer on your integration 49 | * @param {String} email_or_code 50 | */ 51 | async fetch(emailCode: string): Promise { 52 | return await this.http.get(`/customer/${emailCode}`); 53 | } 54 | 55 | /** 56 | * ## Update CUstomer 57 | * Update a customer's details on your integration 58 | */ 59 | async update( 60 | code: string, 61 | data: UpdateCustomer, 62 | ): Promise { 63 | return await this.http.put(`/customer/${code}`, JSON.stringify(data)); 64 | } 65 | 66 | /** 67 | * ## Validate Customer 68 | * Validate a customer's identity 69 | */ 70 | async validate( 71 | customerCode: string, 72 | data: ValidateCustomer, 73 | ): Promise { 74 | return await this.http.post( 75 | `/customer/${customerCode}/identification`, 76 | JSON.stringify(data), 77 | ); 78 | } 79 | 80 | /** 81 | * ## Whitelist/Blacklist Customer 82 | * Whitelist or black a customer on your integration 83 | */ 84 | async setRiskAction( 85 | data: SetRiskAction, 86 | ): Promise { 87 | return await this.http.post( 88 | '/customer/set_risk_action', 89 | JSON.stringify(data), 90 | ); 91 | } 92 | 93 | /** 94 | * ## Deactivate Authorization 95 | * Deactivate an authorization when the card needs to be forgotten 96 | */ 97 | async deactivateAutorization(authorizationCode: string): Promise { 98 | return await this.http.post( 99 | '/customer/deactivate_authorization', 100 | JSON.stringify({ authorizaion_code: authorizationCode }), 101 | ); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/customer/interface.ts: -------------------------------------------------------------------------------- 1 | import { Authorization } from '../charge/interface'; 2 | import { Meta } from '../interface'; 3 | import { SubAccount } from '../subaccounts/subaccount'; 4 | import { Subscription } from '../subscription/interface'; 5 | import { Transaction } from '../transaction/interface'; 6 | 7 | export interface CreateCustomer { 8 | email: string; 9 | first_name: string; 10 | last_name: string; 11 | phone?: string; 12 | metadata?: Record; 13 | } 14 | 15 | export interface Response { 16 | status: boolean; 17 | message: string; 18 | } 19 | 20 | export interface Customer { 21 | id: number; 22 | transactions: Transaction[]; 23 | subscriptions: Subscription[]; 24 | authorizations: Authorization[]; 25 | first_name: string; 26 | last_name: string; 27 | email: string; 28 | phone?: string; 29 | metadata?: Record; 30 | domain: string; 31 | customer_code: string; 32 | risk_action: string; 33 | international_format_phone?: string; 34 | integration: number; 35 | createdAt: Date; 36 | updatedAt: Date; 37 | identified: boolean; 38 | identifications: CustomerIdentification[]; 39 | dedicated_account: DedicatedAccount[]; 40 | } 41 | 42 | export interface CustomerCreated extends Response { 43 | data: Customer; 44 | } 45 | 46 | export interface FetchCustomerResponse extends Response { 47 | data: Customer; 48 | } 49 | 50 | export interface ListCustomersResponse extends Response { 51 | data: Customer[]; 52 | meta: Meta; 53 | } 54 | 55 | export interface ListCustomerQueryParams { 56 | /** 57 | * Specify how many records you want to retrieve per page. 58 | * If not specify we use a default value of 50. 59 | */ 60 | perPage?: number; 61 | /** 62 | * Specify exactly what page you want to retrieve. 63 | * If not specify we use a default value of 1. 64 | */ 65 | page?: number; 66 | /** 67 | * Specify an ID for the customer whose transactions 68 | * you want to retrieve 69 | */ 70 | customer?: number; 71 | /** 72 | * Filter transactions by status ('failed', 'success', 'abandoned') 73 | */ 74 | status?: string; 75 | /** 76 | * A timestamp from which to start listing transaction 77 | * e.g `2021-10-25T00.00.05.000z`, `2021-12-25` 78 | */ 79 | from?: Date; 80 | /** 81 | * A timestamp from which to stop listing transaction 82 | * e.g `2021-10-25T00.00.05.000z`, `2021-12-25` 83 | */ 84 | to?: Date; 85 | } 86 | 87 | export interface SplitConfig { 88 | id: number; 89 | name: string; 90 | type: string; 91 | currency: string; 92 | integration: number; 93 | domain: string; 94 | split_code: string; 95 | active: boolean; 96 | bearer_type: string; 97 | bearer_subaccount: string | null; 98 | createdAt: Date; 99 | updatedAt: Date; 100 | is_dynamic: boolean; 101 | subaccounts: CustomerSubAccount[]; 102 | total_subaccounts: number; 103 | } 104 | 105 | export interface CustomerSubAccount { 106 | subaccount: SubAccount; 107 | share: number; 108 | } 109 | 110 | export interface CustomerIdentification { 111 | country: string; 112 | type: string; 113 | value: string; 114 | } 115 | 116 | export interface DedicatedAccount { 117 | bank: { 118 | name: string; 119 | id: number; 120 | slug: string; 121 | }; 122 | id: number; 123 | account_name: string; 124 | account_number: string; 125 | created_at: Date; 126 | updated_at: Date; 127 | currency: string; 128 | split_config: SplitConfig; 129 | active: boolean; 130 | assigned: boolean; 131 | assignment: { 132 | assignee_id: number; 133 | assignee_type: string; 134 | account_type: string; 135 | integration: number; 136 | }; 137 | } 138 | 139 | export interface UpdateCustomer { 140 | first_name: string; 141 | last_name: string; 142 | email: string; 143 | phone?: string; 144 | metadata?: Record; 145 | } 146 | 147 | export interface SetRiskAction { 148 | customer: string; 149 | risk_action: RiskAction; 150 | } 151 | 152 | export interface ValidateCustomer { 153 | first_name: string; 154 | last_name: string; 155 | type: ValidationType; 156 | value: string; 157 | country: string; 158 | bvn: string; 159 | bank_code: string; 160 | account_number: string; 161 | } 162 | 163 | enum RiskAction { 164 | default, 165 | allow, 166 | deny, 167 | } 168 | 169 | enum ValidationType { 170 | bvn, 171 | bank_account, 172 | } 173 | 174 | export interface ICustomer { 175 | integration: number; 176 | first_name: string; 177 | last_name: string; 178 | email: string; 179 | phone: string | null; 180 | dedicated_account: DedicatedAccount | null; 181 | identified: boolean; 182 | identifications: CustomerIdentification[] | null; 183 | metadata: Record | null; 184 | domain: string; 185 | customer_code: string; 186 | id: string; 187 | transactions: Transaction[]; 188 | subscriptions: Subscription[]; 189 | authorizations: Authorization[]; 190 | createdAt: Date; 191 | updatedAt: Date; 192 | } 193 | -------------------------------------------------------------------------------- /src/dedicated/dedicated.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { 3 | CreateDedicatedVirtualAccount, 4 | DeactivateDedicatedAccountResponse, 5 | DedicatedAccountCreatedResponse, 6 | FetchBankProvidersResponse, 7 | FetchDedicatedVirtualAccountResponse, 8 | ListDedicatedVirtualAccountsQueryParams, 9 | ListDedicatedVirtualAccountsResponse, 10 | RemoveSplitDedicatedAccountResponse, 11 | SplitDedicatedAccountTransaction, 12 | SplitDedicatedAccountTransactionResponse, 13 | } from './interface'; 14 | 15 | interface BadRequest { 16 | status: boolean; 17 | message: string; 18 | } 19 | 20 | export class DedicatedAccount { 21 | http: Axios; 22 | constructor(http: Axios) { 23 | this.http = http; 24 | } 25 | 26 | async create( 27 | data: CreateDedicatedVirtualAccount, 28 | ): Promise { 29 | return await this.http.post('/dedicated_account', JSON.stringify(data)); 30 | } 31 | 32 | async list( 33 | queryParams: ListDedicatedVirtualAccountsQueryParams, 34 | ): Promise { 35 | return await this.http.get('/dedicated_account', { 36 | params: { ...queryParams }, 37 | }); 38 | } 39 | 40 | async fetch( 41 | dedicatedAccountId: string, 42 | ): Promise { 43 | return await this.http.get(`/dedicated_account/${dedicatedAccountId}`); 44 | } 45 | 46 | async deactivate( 47 | dedicatedAccountId: string, 48 | ): Promise { 49 | return await this.http.delete(`/dedicated_account/${dedicatedAccountId}`); 50 | } 51 | 52 | async splitTransaction( 53 | data: SplitDedicatedAccountTransaction, 54 | ): Promise { 55 | return await this.http.post( 56 | '/dedicated_account/split', 57 | JSON.stringify(data), 58 | ); 59 | } 60 | 61 | async removeSplit( 62 | accountNumber: string, 63 | ): Promise { 64 | return await this.http.delete('/dedicated_account/split', { 65 | data: { account_number: accountNumber }, 66 | }); 67 | } 68 | 69 | async providers(): Promise { 70 | return await this.http.get('/dedicated_account/available_providers'); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/dedicated/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tekpriest/paystack-node/204012baf6881a8f09ef7625fdf4b9d227c680ef/src/dedicated/index.ts -------------------------------------------------------------------------------- /src/dedicated/interface.ts: -------------------------------------------------------------------------------- 1 | import { Authorization } from '../charge/interface'; 2 | import { Meta } from '../interface'; 3 | import { Subscription } from '../subscription'; 4 | import { Response } from '../interface'; 5 | import { Transaction } from '../transaction/interface'; 6 | import { Customer } from '../customer/interface'; 7 | 8 | export interface DedicatedAccountData { 9 | id: number; 10 | account_name: string; 11 | account_number: string; 12 | assigned: boolean; 13 | currency: string; 14 | metadata?: Record; 15 | active: boolean; 16 | split_config?: Record; 17 | bank: Bank; 18 | slug: string; 19 | created_at: string; 20 | updated_at: string; 21 | assignment: Assignment; 22 | customer: Customer; 23 | } 24 | 25 | export interface CreateDedicatedVirtualAccount { 26 | customer: string; 27 | preferred_bank: string; 28 | subaccount?: string; 29 | split_code?: string; 30 | first_name?: string; 31 | last_name?: string; 32 | phone?: string; 33 | } 34 | 35 | export interface ListDedicatedVirtualAccountsQueryParams { 36 | active: boolean; 37 | currency: string; 38 | provider_slug?: string; 39 | bank_id?: string; 40 | customer?: string; 41 | } 42 | 43 | export interface SplitDedicatedAccountTransaction { 44 | customer: string; 45 | subaccount?: string; 46 | split_code?: string; 47 | preferred_bank?: string; 48 | } 49 | 50 | export interface ListDedicatedVirtualAccountsResponse extends Response { 51 | data: DedicatedAccountData[]; 52 | meta: Meta; 53 | } 54 | 55 | export interface DedicatedAccountCreatedResponse extends Response { 56 | data: DedicatedAccountData; 57 | } 58 | 59 | export interface FetchDedicatedVirtualAccountResponse extends Response { 60 | data: { 61 | transactions: Transaction[]; 62 | subscriptions: Subscription[]; 63 | authorizations: Authorization[]; 64 | first_name: string; 65 | last_name: string; 66 | email: string; 67 | phone: string; 68 | metadata?: Record; 69 | domain: string; 70 | customer_code: string; 71 | risk_action: string; 72 | id: number; 73 | integration: number; 74 | createdAt: Date; 75 | updatedAt: Date; 76 | created_at: Date; 77 | updated_at: Date; 78 | total_transactions: number; 79 | total_transaction_value: unknown[]; 80 | dedicated_account: { 81 | id: number; 82 | account_name: string; 83 | account_number: string; 84 | created_at: Date; 85 | updated_at: Date; 86 | currency: string; 87 | active: boolean; 88 | assigned: boolean; 89 | provider: { 90 | id: number; 91 | provider_slug: string; 92 | bank_id: number; 93 | bank_name: string; 94 | }; 95 | assignment: Assignment; 96 | }; 97 | }; 98 | } 99 | 100 | export interface DeactivateDedicatedAccountResponse { 101 | data: { 102 | bank: Bank; 103 | account_name: string; 104 | account_number: string; 105 | assigned: boolean; 106 | currency: string; 107 | metadata?: Record; 108 | active: boolean; 109 | id: number; 110 | created_at: Date; 111 | updated_at: Date; 112 | assignment: Assignment; 113 | }; 114 | } 115 | 116 | export interface SplitDedicatedAccountTransactionResponse extends Response { 117 | data: { 118 | id: number; 119 | account_name: string; 120 | account_number: string; 121 | assigned: boolean; 122 | currency: string; 123 | metadata?: Record; 124 | active: boolean; 125 | bank: Bank; 126 | assignment: Assignment; 127 | created_at: Date; 128 | updated_at: Date; 129 | split_config?: Record; 130 | customer: Customer; 131 | }; 132 | } 133 | 134 | export interface RemoveSplitDedicatedAccountResponse extends Response { 135 | data: { 136 | id: number; 137 | account_name: string; 138 | account_number: string; 139 | assigned: boolean; 140 | currency: string; 141 | split_config?: Record; 142 | active: boolean; 143 | createdAt: Date; 144 | updatedAt: Date; 145 | }; 146 | } 147 | 148 | export interface FetchBankProvidersResponse extends Response { 149 | data: { 150 | id: number; 151 | provider_slug: string; 152 | bank_id: number; 153 | bank_name: string; 154 | }[]; 155 | } 156 | 157 | interface Bank { 158 | id: number; 159 | name: string; 160 | slug: string; 161 | } 162 | 163 | interface Assignment { 164 | integration: number; 165 | assignee_id: number; 166 | assignee_type: string; 167 | expired: boolean; 168 | account_type: string; 169 | assigned_at: Date; 170 | expired_at: Date | null; 171 | } 172 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { Paystack } from './paystack'; 2 | -------------------------------------------------------------------------------- /src/interface.ts: -------------------------------------------------------------------------------- 1 | export interface Meta { 2 | total: number; 3 | skipped: number; 4 | perPage: number; 5 | page: number; 6 | pageCount: number; 7 | } 8 | 9 | export interface BadRequest { 10 | status: boolean; 11 | message: string; 12 | data: null; 13 | } 14 | 15 | export interface Response { 16 | status: boolean; 17 | message: string; 18 | } 19 | 20 | export interface QueryParams { 21 | /** 22 | * Specify how many records you want to retrieve per page. 23 | * If not specify we use a default value of 50. 24 | */ 25 | perPage?: number; 26 | /** 27 | * Specify exactly what page you want to retrieve. 28 | * If not specify we use a default value of 1. 29 | */ 30 | page?: number; 31 | /** 32 | * A timestamp from which to start listing subaccounts e.g. 2016-09-24T00:00:05.000Z, 2016-09-21 33 | */ 34 | from?: Date; 35 | /** 36 | * A timestamp at which to stop listing subaccounts e.g. 2016-09-24T00:00:05.000Z, 2016-09-21 37 | */ 38 | to?: Date; 39 | } 40 | 41 | /** 42 | * Paystack makes use of the ISO 4217 format for currency codes. 43 | * When sending an amount, it must be sent in the subunit of that currency. 44 | * 45 | * Sending an amount in subunits simply means multiplying the base amount by 100. 46 | * For example, if a customer is supposed to make a payment of NGN 100, 47 | * you would send 10000 = 100 * 100 in your request. 48 | */ 49 | export type Currency = 'NGN' | 'USD' | 'GHS' | 'ZAR' | 'KES'; 50 | -------------------------------------------------------------------------------- /src/invoice/interface.ts: -------------------------------------------------------------------------------- 1 | import { Customer } from '../customer/interface'; 2 | import { Meta, QueryParams, Response } from '../interface'; 3 | import { Transaction } from '../transaction/interface'; 4 | 5 | export interface CreateInvoice { 6 | /** Customer id or code */ 7 | customer: string; 8 | /** 9 | * Payment request amount. 10 | * It should be used when line items and tax values aren't specified. 11 | */ 12 | amount: number; 13 | /** ISO 8601 representation of request due date */ 14 | date_time?: Date; 15 | /** A short description of the payment request */ 16 | description?: string; 17 | /** 18 | * Array of line items int the format 19 | * [{"name":"item 1", "amount":2000, "quantity": 1}] 20 | */ 21 | line_items?: Record[]; 22 | /** 23 | * Array of taxes to be charged in the format 24 | * [{"name":"VAT", "amount":2000}] 25 | */ 26 | tax?: Record[]; 27 | /** 28 | * Specify the currency of the invoice. 29 | * Allowed values are `NGN`, `GHS`, `ZAR` and `USD`. Defaults to NGN 30 | */ 31 | currency?: string; 32 | /** 33 | * Indicates whether Paystack sends an email notification to customer. 34 | * Defaults to true 35 | */ 36 | send_notification?: boolean; 37 | /** 38 | * Indicate if request should be saved as draft. 39 | * Defaults to false and overrides send_notification 40 | */ 41 | draft?: boolean; 42 | /** 43 | * Set to true to create a draft invoice 44 | * (adds an auto incrementing invoice number if none is provided) 45 | * even if there are no line_items or tax passed 46 | */ 47 | has_invoice?: boolean; 48 | /** 49 | * Numeric value of invoice. 50 | * Invoice will start from 1 and auto increment from there. 51 | * This field is to help override whatever value Paystack decides. 52 | * Auto increment for subsequent invoices continue from this point. 53 | */ 54 | invoice_number?: number; 55 | /** The split code of the transaction split. e.g. SPL_98WF13Eb3w */ 56 | split_code?: string; 57 | } 58 | 59 | export interface InvoiceQueryParams extends QueryParams { 60 | /** Filter by customer ID */ 61 | customer?: string; 62 | /** Filter by invoice status */ 63 | status?: string; 64 | /** 65 | * Filter by currency. 66 | * Allowed values are NGN, GHS, ZAR and USD. 67 | */ 68 | currency?: string; 69 | /** Show archived invoices */ 70 | include_archive?: string; 71 | } 72 | 73 | export type UpdateInvoice = CreateInvoice; 74 | 75 | interface InvoiceLineItem { 76 | name: string; 77 | amount: number; 78 | quantity: number; 79 | } 80 | 81 | interface InvoiceTax { 82 | name: string; 83 | amount: number; 84 | } 85 | 86 | interface IInvoiceTotal { 87 | currency: string; 88 | amount: number; 89 | } 90 | 91 | export interface Invoice { 92 | id: number; 93 | domain: string; 94 | amount: number; 95 | discount?: unknown; 96 | currency: string; 97 | due_date: Date; 98 | has_invoice: boolean; 99 | invoice_number: number; 100 | description: string; 101 | line_items: InvoiceLineItem[]; 102 | tax: InvoiceTax[]; 103 | request_code: string; 104 | status: string; 105 | paid: boolean; 106 | paid_at?: Date; 107 | metadata?: Record; 108 | notifications: unknown[]; 109 | offline_reference: string; 110 | pdf_url?: string; 111 | transactions: Transaction[]; 112 | archived?: boolean; 113 | source?: string; 114 | payment_method?: unknown; 115 | note?: string; 116 | amount_paid?: unknown; 117 | integration: number; 118 | customer?: number | Customer; 119 | createdAt: Date; 120 | updatedAt: Date; 121 | pending_amount?: number; 122 | } 123 | 124 | export interface InvoiceTotal { 125 | pending: IInvoiceTotal[]; 126 | successful: IInvoiceTotal[]; 127 | total: IInvoiceTotal[]; 128 | } 129 | 130 | export interface InvoiceCreatedResponse extends Response { 131 | data: Invoice; 132 | } 133 | 134 | export interface ListInvoicesResponse extends Response { 135 | data: Invoice[]; 136 | meta: Meta; 137 | } 138 | 139 | export interface ViewInvoiceResponse extends Response { 140 | data: Invoice; 141 | } 142 | 143 | export interface VerifyInvoiceResponse extends Response { 144 | data: Invoice; 145 | } 146 | 147 | export interface InvoiceTotalResponse extends Response { 148 | data: InvoiceTotal; 149 | } 150 | -------------------------------------------------------------------------------- /src/invoice/invoice.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { BadRequest, Response } from '../interface'; 3 | import { 4 | CreateInvoice, 5 | InvoiceCreatedResponse, 6 | InvoiceQueryParams, 7 | InvoiceTotalResponse, 8 | ListInvoicesResponse, 9 | UpdateInvoice, 10 | ViewInvoiceResponse, 11 | } from './interface'; 12 | 13 | export class Invoice { 14 | private http: Axios; 15 | constructor(http: Axios) { 16 | this.http = http; 17 | } 18 | 19 | async create( 20 | data: CreateInvoice, 21 | ): Promise { 22 | return await this.http.post('/paymentrequest', JSON.stringify(data)); 23 | } 24 | 25 | async list( 26 | queryParams?: InvoiceQueryParams, 27 | ): Promise { 28 | return await this.http.get('/paymentrequest', { 29 | params: { ...queryParams }, 30 | }); 31 | } 32 | 33 | async view(id: string): Promise { 34 | return await this.http.get(`'/paymentrequest/${id}`); 35 | } 36 | 37 | async verify(code: string): Promise { 38 | return await this.http.get(`/paymentrequest/verify/${code}`); 39 | } 40 | 41 | async sendNotification(code: string): Promise { 42 | return await this.http.post(`/paymentrequest/notify/${code}`); 43 | } 44 | 45 | async total(): Promise { 46 | return await this.http.get('/paymentrequest/totals'); 47 | } 48 | 49 | async finalize(code: string): Promise { 50 | return await this.http.post(`/paymentrequest/finalize/${code}`); 51 | } 52 | 53 | async update( 54 | id: string, 55 | data: UpdateInvoice, 56 | ): Promise { 57 | return await this.http.put(`/paymentrequest/${id}`, JSON.stringify(data)); 58 | } 59 | 60 | async archive(code: string): Promise { 61 | return await this.http.post(`/paymentrequest/archive/${code}`); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/payment/interface.ts: -------------------------------------------------------------------------------- 1 | import { Meta, Response } from '../interface'; 2 | import { ProductCreated } from '../product/interface'; 3 | 4 | export interface CreatePage { 5 | /** 6 | * Name of page 7 | */ 8 | name: string; 9 | /** 10 | * A description for this page 11 | */ 12 | description?: string; 13 | /** 14 | * Amount should be in kobo if currency is `NGN`, pesewas, 15 | * if currency is `GHS`, and cents, if currency is `ZAR` 16 | */ 17 | amount?: number; 18 | /** 19 | * URL slug you would like to be associated with this page. 20 | * Page will be accessible at https://paystack.com/pay/[slug] 21 | */ 22 | slug?: string; 23 | /** 24 | * Extra data to configure the payment page including subaccount, 25 | * logo image, transaction charge 26 | */ 27 | metadata?: Record; 28 | /** 29 | * If you would like Paystack to redirect someplace upon successful payment, 30 | * specify the URL here. 31 | */ 32 | redirect_url?: string; 33 | /** 34 | * If you would like to accept custom fields, specify them here. 35 | */ 36 | custom_fields?: Record[]; 37 | } 38 | 39 | export interface UpdatePage { 40 | /** 41 | * Name of page 42 | */ 43 | name: string; 44 | /** 45 | * A description for this page 46 | */ 47 | description: string; 48 | /** 49 | * Amount should be in kobo if currency is `NGN`, pesewas, 50 | * if currency is `GHS`, and cents, if currency is `ZAR` 51 | */ 52 | amount?: number; 53 | /** 54 | * Set to false to deactivate page url 55 | */ 56 | active?: boolean; 57 | } 58 | 59 | export interface PaymentPageProduct { 60 | product_id: number; 61 | name: string; 62 | description: string; 63 | product_code: string; 64 | page: number; 65 | price: number; 66 | currency: string; 67 | quantity: number; 68 | type: string; 69 | features?: unknown; 70 | is_shippable: number; 71 | domain: string; 72 | integration: number; 73 | active: number; 74 | in_stock: number; 75 | } 76 | 77 | export interface PaymentPage { 78 | id: number; 79 | name: string; 80 | description?: string; 81 | integration: number; 82 | domain: string; 83 | slug: string; 84 | currency: string; 85 | type: string; 86 | redirect_url?: string; 87 | success_message?: string; 88 | collect_phone: boolean; 89 | active: boolean; 90 | published: boolean; 91 | migrate: boolean; 92 | notification_email?: string; 93 | metadata?: Record; 94 | split_code?: string; 95 | createdAt: Date; 96 | updatedAt: Date; 97 | products?: ProductCreated[]; 98 | } 99 | 100 | export interface PaymentPageCreatedFetchedUpdatedResponse extends Response { 101 | data: PaymentPage; 102 | } 103 | 104 | export interface ListPaymentPagesResponse extends Response { 105 | data: PaymentPage[]; 106 | meta?: Meta; 107 | } 108 | -------------------------------------------------------------------------------- /src/payment/payment.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { BadRequest, QueryParams } from '../interface'; 3 | import { 4 | CreatePage, 5 | ListPaymentPagesResponse, 6 | PaymentPageCreatedFetchedUpdatedResponse, 7 | UpdatePage, 8 | } from './interface'; 9 | 10 | export class PaymentPage { 11 | private http: Axios; 12 | constructor(http: Axios) { 13 | this.http = http; 14 | } 15 | 16 | async create( 17 | data: CreatePage, 18 | ): Promise { 19 | return await this.http.post('/page', JSON.stringify(data)); 20 | } 21 | 22 | async list( 23 | queryParams?: QueryParams, 24 | ): Promise { 25 | return await this.http.get('/page', { params: { ...queryParams } }); 26 | } 27 | 28 | async fetch( 29 | id: string, 30 | ): Promise { 31 | return await this.http.get(`/page/${id}`); 32 | } 33 | 34 | async update( 35 | id: string, 36 | data: UpdatePage, 37 | ): Promise { 38 | return await this.http.put(`/page/${id}`, JSON.stringify(data)); 39 | } 40 | 41 | async slugAvailable( 42 | slug: string, 43 | ): Promise { 44 | return await this.http.get(`/page/check_slug_availability/${slug}`); 45 | } 46 | 47 | async addProduct( 48 | id: number, 49 | products: number[], 50 | ): Promise { 51 | return await this.http.post( 52 | `/page/${id}/product`, 53 | JSON.stringify({ products }), 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/paystack.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { ApplePay } from './apple/apple'; 3 | import { Charge } from './charge/charge'; 4 | import { Customer } from './customer/customer'; 5 | import { DedicatedAccount } from './dedicated/dedicated'; 6 | import { Invoice } from './invoice/invoice'; 7 | import { PaymentPage } from './payment/payment'; 8 | import { Plan } from './plan'; 9 | import { Product } from './product/product'; 10 | import { Recipient } from './recipient/recipient'; 11 | import { Settlement } from './settlement/settlement'; 12 | import { TransactionSplit } from './split/split'; 13 | import { SubAccount } from './subaccounts/subaccount'; 14 | import { Subscription } from './subscription/subscription'; 15 | import { Transaction } from './transaction/transaction'; 16 | import { Transfer } from './transfer/transfer'; 17 | import { BulkCharge } from './bulkcharge/bulkcharge'; 18 | import { Verification } from './verification/verification'; 19 | import { Refund } from './refund/refund'; 20 | 21 | /** 22 | * Paystack SDK 23 | * @author Asaju Enitan <@tPriest> 24 | */ 25 | 26 | export class Paystack { 27 | private readonly http: Axios; 28 | public bulkcharge: BulkCharge; 29 | public charge: Charge; 30 | public customer: Customer; 31 | public dedicated: DedicatedAccount; 32 | public plan: Plan; 33 | public product: Product; 34 | public subscription: Subscription; 35 | public transaction: Transaction; 36 | public transfer: Transfer; 37 | public split: TransactionSplit; 38 | public applePay: ApplePay; 39 | public subAccount: SubAccount; 40 | public page: PaymentPage; 41 | public invoice: Invoice; 42 | public settlement: Settlement; 43 | public recipient: Recipient; 44 | public refund: Refund; 45 | public verification: Verification; 46 | constructor(private readonly key: string) { 47 | this.http = new Axios({ 48 | baseURL: 'https://api.paystack.co', 49 | headers: { 50 | Authorization: `Bearer ${this.key}`, 51 | 'Content-Type': 'application/json', 52 | }, 53 | }); 54 | this.http.interceptors.response.use( 55 | (response) => (response.data = JSON.parse(response.data)), 56 | ); 57 | 58 | this.bulkcharge = new BulkCharge(this.http); 59 | this.charge = new Charge(this.http); 60 | this.customer = new Customer(this.http); 61 | this.dedicated = new DedicatedAccount(this.http); 62 | this.plan = new Plan(this.http); 63 | this.product = new Product(this.http); 64 | this.split = new TransactionSplit(this.http); 65 | this.subscription = new Subscription(this.http); 66 | this.transaction = new Transaction(this.http); 67 | this.transfer = new Transfer(this.http); 68 | this.applePay = new ApplePay(this.http); 69 | this.subAccount = new SubAccount(this.http); 70 | this.page = new PaymentPage(this.http); 71 | this.invoice = new Invoice(this.http); 72 | this.settlement = new Settlement(this.http); 73 | this.recipient = new Recipient(this.http); 74 | this.refund = new Refund(this.http); 75 | this.verification = new Verification(this.http); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/plan/README.md: -------------------------------------------------------------------------------- 1 | # Plan 2 | Import the package 3 | For Typescript 4 | ``` 5 | import Paystack from 'paystack-sdk' 6 | const paystack = new Paystack("secret_key); 7 | ``` 8 | 9 | For Javscript 10 | ``` 11 | const Paystack = require('paystack-sdk'); 12 | const paystack = new Paystack("secret_key") 13 | ``` 14 | ### Create Plan 15 | ``` 16 | paystack.plan 17 | .create({ 18 | name: 'Test Plan', 19 | amount: 20000, 20 | interval: 'daily', 21 | }) 22 | .then((plan) => console.log(plan)); 23 | ``` 24 | ### List Plans 25 | ``` 26 | paystack.plan 27 | .list({ perPage: 2 }) 28 | .then((plans) => console.log(plans)); 29 | ``` 30 | ### Fetch Plan 31 | ``` 32 | paystack.plan 33 | .fetch(123456) 34 | .then((plan) => console.log(plan)); 35 | ``` 36 | ### Update Plan 37 | ``` 38 | paystack.plan 39 | .update(123456, { 40 | amount: 30000, 41 | }) 42 | .then((plan) => console.log(plan)); 43 | ``` 44 | -------------------------------------------------------------------------------- /src/plan/index.ts: -------------------------------------------------------------------------------- 1 | export * from './interface'; 2 | export * from './plan'; 3 | -------------------------------------------------------------------------------- /src/plan/interface.ts: -------------------------------------------------------------------------------- 1 | import { Meta } from '../interface'; 2 | import { Subscription } from '../subscription/interface'; 3 | 4 | export interface CreatePlan { 5 | /** 6 | * Name of plan 7 | */ 8 | name: string; 9 | /** 10 | * Amount should be in **kobo** if currency is 11 | * `NGN`, **pesewas**, if currency is `GHS`, and 12 | * **cents** if currency is `ZAR` 13 | */ 14 | amount: number; 15 | /** 16 | * Interval in words, 17 | * Valid intervals are `daily`,`weekly`,`monthly`,`biannually`,`annually` 18 | */ 19 | interval?: string; 20 | /** 21 | * A description for this plan 22 | */ 23 | description?: string; 24 | /** 25 | * Set to false if you don't want invoices to be sent 26 | * to your custmers 27 | */ 28 | send_invoices?: boolean; 29 | /** 30 | * Set to false if you don't want text messages to be sent 31 | * to your customers 32 | */ 33 | send_sms?: string; 34 | /** 35 | * Currency in which amount is set. Allowed values are 36 | * NGN, GHS, ZAR or USD 37 | */ 38 | currency?: string; 39 | /** 40 | * Number of invoices to raise during subscription to this plan. 41 | * Can be overridden by specifying an `invoice_limit` while subscribing 42 | */ 43 | invoice_limit?: number; 44 | } 45 | 46 | export interface PlanResponse { 47 | status: boolean; 48 | message: string; 49 | data: PlanCreated | Plan | Plans; 50 | meta?: Meta; 51 | } 52 | 53 | interface PlanCreated { 54 | name: string; 55 | amount: number; 56 | interval: string; 57 | integration: number; 58 | domain: string; 59 | plan_code: string; 60 | description: unknown; 61 | send_invoices: boolean; 62 | send_sms: boolean; 63 | hosted_page: boolean; 64 | hosted_page_url: unknown; 65 | hosted_page_summary: unknown; 66 | currency: string; 67 | migrate: boolean; 68 | is_archived: boolean; 69 | id: number; 70 | createdAt: Date; 71 | updatedAt: Date; 72 | } 73 | interface Plan extends PlanCreated { 74 | subscriptions: Subscription[]; 75 | is_deleted: boolean; 76 | pages_count: number; 77 | subscribers_count: number; 78 | subscriptions_count: number; 79 | active_subscriptions_count: number; 80 | total_revenue: number; 81 | subscribers: unknown[]; 82 | } 83 | interface Plans extends PlanCreated { 84 | subscriptions: Subscription[]; 85 | } 86 | []; 87 | 88 | export interface ListPlanQueryParams { 89 | /** 90 | * Specify how many records you want to retrieve per page. 91 | * If not specify we use a default value of 50. 92 | */ 93 | perPage?: number; 94 | /** 95 | * Specify exactly what page you want to retrieve. 96 | * If not specify we use a default value of 1. 97 | */ 98 | page?: number; 99 | /** 100 | * Filter transactions by status ('failed', 'success', 'abandoned') 101 | */ 102 | status?: string; 103 | /** 104 | * Filter transactions by amount. 105 | * Specify the amount (in **kobo** if currency is `NGN`, 106 | * **pesewas**, if currency is `GHS`, 107 | * and **cents**, if currency is `ZAR`) 108 | */ 109 | amount: number; 110 | /** 111 | * Filter list by plans with specified interval 112 | */ 113 | interval?: number; 114 | } 115 | export interface UpdatePlan { 116 | /** 117 | * Name of plan 118 | */ 119 | name: string; 120 | /** 121 | * Amount should be in `kobo` if currency is 122 | * NGN and `pesewas` for GHS 123 | */ 124 | amount: number; 125 | /** 126 | * Interval in words. Valid intervals are 127 | * `hourly`,`daily`,weekly`,`monthly`,`biannually`,`annually`. 128 | */ 129 | interval: string; 130 | /** 131 | * A description for this plan 132 | */ 133 | description?: string; 134 | /** 135 | * Set to false if you don't want invoices to be sent 136 | * to your custmers 137 | */ 138 | send_invoices?: boolean; 139 | /** 140 | * Set to false if you don't want text messages to be sent 141 | * to your customers 142 | */ 143 | send_sms?: string; 144 | /** 145 | * Currency in which amount is set. Allowed values are 146 | * NGN, GHS, ZAR or USD 147 | */ 148 | currency?: string; 149 | /** 150 | * Number of invoices to raise during subscription to this plan. 151 | * Can be overriden by specifying an `invoice_limit` while subscribing 152 | */ 153 | invoice_limit?: number; 154 | } 155 | 156 | export interface IPlan { 157 | domain: string; 158 | name: string; 159 | plan_code: string; 160 | description: string; 161 | amount: number; 162 | interval: string; 163 | send_invoices: boolean; 164 | send_sms: boolean; 165 | hosted_page: boolean; 166 | hosted_page_url: string; 167 | hosted_page_summary: string; 168 | currency: string; 169 | migrate: boolean; 170 | id: number; 171 | integration: number; 172 | is_archived: boolean; 173 | createdAt: Date; 174 | updatedAt: Date; 175 | } 176 | -------------------------------------------------------------------------------- /src/plan/plan.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { 3 | CreatePlan, 4 | ListPlanQueryParams, 5 | PlanResponse, 6 | UpdatePlan, 7 | } from './interface'; 8 | 9 | interface BadRequest { 10 | status: boolean; 11 | message: string; 12 | data: null; 13 | } 14 | 15 | /** 16 | * ## Plans 17 | * The Plans API allows you create and manage installment 18 | * payment options on your integration 19 | * @class Plan 20 | */ 21 | export class Plan { 22 | private http: Axios; 23 | constructor(http: Axios) { 24 | this.http = http; 25 | } 26 | /** 27 | * ### Create Plan 28 | * Create a plan on your integration 29 | * @param {CreatePlan} data Body Param 30 | * @returns {Promise} 31 | */ 32 | async create(data: CreatePlan): Promise { 33 | return await this.http.post('/plan', JSON.stringify(data)); 34 | } 35 | /** 36 | * ### List Plans 37 | * List plans available on your integration 38 | * @param queryParams Query Parameters 39 | * @returns {Promise} 40 | */ 41 | async list( 42 | queryParams?: ListPlanQueryParams, 43 | ): Promise { 44 | return await this.http.get('/plan', { 45 | params: { ...queryParams }, 46 | }); 47 | } 48 | /** 49 | * ### Fetch Plan 50 | * Get details of a plan on your integration 51 | * @param id The plan `ID` or `code` you want to fetch 52 | * @returns {Promise} 53 | */ 54 | async fetch(id: string): Promise { 55 | return await this.http.get(`/plan/${id}`); 56 | } 57 | /** 58 | * ### Update Plan 59 | * Update a plan details on your integration 60 | * @param id Plans's `ID` or `code` 61 | * @param {UpdatePlan} data Update Plan Data 62 | * @returns {Promise} 63 | */ 64 | async update( 65 | id: string, 66 | data: UpdatePlan, 67 | ): Promise { 68 | return await this.http.put(`/plan/${id}`, JSON.stringify(data)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/product/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tekpriest/paystack-node/204012baf6881a8f09ef7625fdf4b9d227c680ef/src/product/index.ts -------------------------------------------------------------------------------- /src/product/interface.ts: -------------------------------------------------------------------------------- 1 | import { Meta } from '../interface'; 2 | 3 | export interface CreateProduct { 4 | /** Name of product */ 5 | name: string; 6 | /** A description for this product */ 7 | description: string; 8 | /** 9 | * Price should be in *kobo* if currency is `NGN`, 10 | * *pesewas*, if currency is `GHS`, and *cents*, if currency is `ZAR` 11 | */ 12 | price: number; 13 | /** Currency in which price is set. Allowed values are: NGN, GHS, ZAR or USD */ 14 | currency: string; 15 | /** 16 | * Set to `true` if the product has unlimited stock. Leave as `false` if the product has limited stock 17 | */ 18 | unlimited?: boolean; 19 | /** Number of products in stock. Use if `unlimited` is `false` */ 20 | quantity?: number; 21 | } 22 | 23 | export interface Response { 24 | status: boolean; 25 | message: string; 26 | } 27 | 28 | export interface ProductCreated extends Response { 29 | data: Product; 30 | } 31 | 32 | export interface ListProducts extends Response { 33 | data: Product[]; 34 | meta: Meta; 35 | } 36 | 37 | export interface FetchProduct extends Response { 38 | data: Product; 39 | } 40 | 41 | export interface UpdateProduct extends Response { 42 | data: Product; 43 | } 44 | 45 | export interface ListProductQueryParams { 46 | /** 47 | * Specify how many records you want to retrieve per page. 48 | * If not specify we use a default value of 50. 49 | */ 50 | perPage?: number; 51 | /** 52 | * Specify exactly what page you want to retrieve. 53 | * If not specify we use a default value of 1. 54 | */ 55 | page?: number; 56 | /** 57 | * A timestamp from which to start listing transaction 58 | * e.g `2021-10-25T00.00.05.000z`, `2021-12-25` 59 | */ 60 | from?: Date; 61 | /** 62 | * A timestamp from which to stop listing transaction 63 | * e.g `2021-10-25T00.00.05.000z`, `2021-12-25` 64 | */ 65 | to?: Date; 66 | } 67 | 68 | interface Product { 69 | id: number; 70 | name: string; 71 | description: string; 72 | currency: string; 73 | price: number; 74 | quantity: number; 75 | image_path: string; 76 | file_path: string; 77 | is_shippable: boolean; 78 | unlimited: boolean; 79 | integration: number; 80 | domain: string; 81 | metadata: Record; 82 | slug: string; 83 | product_code: string; 84 | quantity_sold: number; 85 | type: string; 86 | shipping_fields: Record; 87 | active: boolean; 88 | in_stock: boolean; 89 | minimum_orderable: number; 90 | maximum_orderable: number; 91 | low_stock_alert: boolean; 92 | createdAt: Date; 93 | updatedAt: Date; 94 | } 95 | -------------------------------------------------------------------------------- /src/product/product.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { 3 | CreateProduct, 4 | FetchProduct, 5 | ListProductQueryParams, 6 | ListProducts, 7 | ProductCreated, 8 | UpdateProduct, 9 | } from './interface'; 10 | 11 | interface BadRequest { 12 | status: boolean; 13 | message: string; 14 | } 15 | 16 | /** 17 | * @class Product 18 | * # Producs 19 | * The products API allows you create and manage inventories 20 | * on your integration 21 | */ 22 | export class Product { 23 | http: Axios; 24 | constructor(http: Axios) { 25 | this.http = http; 26 | } 27 | 28 | async create(data: CreateProduct): Promise { 29 | return await this.http.post('/product', JSON.stringify(data)); 30 | } 31 | async list( 32 | queryParams?: ListProductQueryParams, 33 | ): Promise { 34 | return await this.http.get('/product', { 35 | params: { ...queryParams }, 36 | }); 37 | } 38 | async fetch(id: string): Promise { 39 | return await this.http.get(`/product/${id}`); 40 | } 41 | async update( 42 | id: string, 43 | data: CreateProduct, 44 | ): Promise { 45 | return await this.http.put(`/product/${id}`, JSON.stringify(data)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/recipient/interface.ts: -------------------------------------------------------------------------------- 1 | import { Meta, Response } from '../interface'; 2 | 3 | export interface CreateRecipient { 4 | /** 5 | * Recipient Type. 6 | * It could be one of: `nuban`, `mobile_money` or `basa` 7 | */ 8 | type: string; 9 | /** A name for the recipient */ 10 | name: string; 11 | /** Required if type is `nuban` or `basa` */ 12 | account_number: string; 13 | /** 14 | * Required if type is nuban or basa. 15 | * You can get the list of Bank Codes by calling the List Banks endpoint. 16 | */ 17 | bank_code: string; 18 | /** A description for this recipient */ 19 | description?: string; 20 | /** Currency for the account receiving the transfer */ 21 | currency?: string; 22 | /** An authorization code from a previous transaction */ 23 | authorization_code?: string; 24 | /** 25 | * Store additional information about your 26 | * recipient in a structured format, JSON 27 | */ 28 | metadata?: Record; 29 | } 30 | 31 | export interface UpdateRecipient { 32 | name: string; 33 | email?: string; 34 | } 35 | 36 | export interface Recipient { 37 | id: number; 38 | active: boolean; 39 | createdAt: Date; 40 | currency: string; 41 | description?: string; 42 | domain: string; 43 | email?: string; 44 | integration: number; 45 | metadata?: Record; 46 | name: string; 47 | recipient_code: string; 48 | type: string; 49 | updatedAt: Date; 50 | is_deleted: boolean; 51 | isDeleted: boolean; 52 | details: RecipientDetails; 53 | } 54 | 55 | export interface RecipientDetails { 56 | authorization_code?: string; 57 | account_number: string; 58 | account_name: string; 59 | bank_code: string; 60 | bank_name: string; 61 | } 62 | 63 | export interface ViewRecipientResponse extends Response { 64 | data: Recipient; 65 | } 66 | 67 | export interface RecipientCreatedResponse extends Response { 68 | data: Recipient; 69 | } 70 | 71 | export interface BulkRecipientsCreatedResponse extends Response { 72 | data: { 73 | success: Recipient[]; 74 | errors: Record[]; 75 | }; 76 | } 77 | 78 | export interface ListRecipientResponse extends Response { 79 | data: Recipient[]; 80 | meta: Meta; 81 | } 82 | -------------------------------------------------------------------------------- /src/recipient/recipient.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { BadRequest, QueryParams, Response } from '../interface'; 3 | import { 4 | CreateRecipient, 5 | ListRecipientResponse, 6 | RecipientCreatedResponse, 7 | UpdateRecipient, 8 | ViewRecipientResponse, 9 | } from './interface'; 10 | 11 | export class Recipient { 12 | private http: Axios; 13 | constructor(http: Axios) { 14 | this.http = http; 15 | } 16 | 17 | /** 18 | * Create multiple transfer recipients in batches. 19 | * A duplicate account number will lead to the retrieval of the existing record. 20 | * If you set `isBulk` to true, you must set the data as an array of recipients 21 | */ 22 | async create( 23 | data: CreateRecipient | CreateRecipient[], 24 | isBulk?: boolean, 25 | ): Promise { 26 | let body: unknown; 27 | let url = '/transferrecipient'; 28 | body = data; 29 | if (isBulk) { 30 | url += '/bulk'; 31 | body = { batch: data }; 32 | } 33 | 34 | return await this.http.post(url, JSON.stringify(body)); 35 | } 36 | 37 | async list( 38 | queryParams?: QueryParams, 39 | ): Promise { 40 | return await this.http.get('/transferrecipient', { 41 | params: { ...queryParams }, 42 | }); 43 | } 44 | 45 | async fetch(id: string): Promise { 46 | return await this.http.get(`/transferrecipient/${id}`); 47 | } 48 | 49 | async update( 50 | id: string, 51 | data: UpdateRecipient, 52 | ): Promise { 53 | return await this.http.put( 54 | `/transferrecipient/${id}`, 55 | JSON.stringify(data), 56 | ); 57 | } 58 | 59 | async delete(id: string): Promise { 60 | return await this.http.delete(`/transferrecipient/${id}`); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/refund/interface.ts: -------------------------------------------------------------------------------- 1 | import { Currency, QueryParams, Response } from '../interface'; 2 | import { Transaction } from '../transaction/interface'; 3 | 4 | export interface CreateRefund { 5 | /** 6 | * Transaction reference or id 7 | */ 8 | transaction: string; 9 | 10 | /** 11 | * Amount to be refunded to the customer. 12 | * Amount is optional(defaults to original transaction amount) 13 | * and cannot be more than the original transaction amount. 14 | */ 15 | amount?: number; 16 | 17 | /** 18 | * Any of the supported currency 19 | */ 20 | currency?: Currency; 21 | 22 | /** 23 | * Customer reason 24 | */ 25 | customer_note?: string; 26 | 27 | /** 28 | * Merchant reason 29 | */ 30 | merchant_note?: string; 31 | } 32 | 33 | export interface ListRefundQueryParams extends QueryParams { 34 | /** 35 | * Identifier for transaction to be refunded 36 | */ 37 | reference: string; 38 | 39 | /** 40 | * Any of the supported currency 41 | */ 42 | currency: Currency; 43 | } 44 | 45 | export interface ListRefundsResponse extends Response { 46 | data: Refund[]; 47 | } 48 | 49 | export interface RefundCreatedResponse extends Response { 50 | data: Refund; 51 | } 52 | 53 | export interface FetchRefundResponse extends Response { 54 | data: Refund; 55 | } 56 | 57 | export interface Refund { 58 | id: number; 59 | integration: number; 60 | domain: string; 61 | transaction: number | Transaction; 62 | dispute: number; 63 | amount: number; 64 | deducted_amount: number; 65 | currency: string; 66 | channel: string; 67 | fully_deducted: boolean; 68 | refunded_by: string; 69 | refunded_at?: string; 70 | expected_at: string; 71 | settlement: number; 72 | customer_note: string; 73 | merchant_note: string; 74 | createdAt: string; 75 | updatedAt: string; 76 | status: string; 77 | } 78 | -------------------------------------------------------------------------------- /src/refund/refund.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { 3 | FetchRefundResponse, 4 | CreateRefund, 5 | ListRefundQueryParams, 6 | ListRefundsResponse, 7 | RefundCreatedResponse, 8 | } from './interface'; 9 | import { BadRequest } from '../interface'; 10 | 11 | export class Refund { 12 | private http: Axios; 13 | constructor(http: Axios) { 14 | this.http = http; 15 | } 16 | 17 | /** 18 | * #### Create Refund 19 | * Initiate a refund on your integration 20 | */ 21 | async create( 22 | data: CreateRefund, 23 | ): Promise { 24 | return await this.http.post('/refund', JSON.stringify(data)); 25 | } 26 | 27 | /** 28 | * #### List Refunds 29 | * List refunds available on your integration 30 | */ 31 | async list( 32 | queryParams?: ListRefundQueryParams, 33 | ): Promise { 34 | return await this.http.get('/refund', { 35 | params: { ...queryParams }, 36 | }); 37 | } 38 | 39 | /** 40 | * #### Fetch Refund 41 | * Get details of a refund on your integration 42 | */ 43 | async fetch(reference: string): Promise { 44 | return await this.http.get(`/refund/${reference}`); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/settlement/interface.ts: -------------------------------------------------------------------------------- 1 | import { CustomerSubAccount } from '../customer/interface'; 2 | import { Meta, QueryParams, Response } from '../interface'; 3 | 4 | export interface SettlementQueryParams extends QueryParams { 5 | subaccount?: string; 6 | } 7 | 8 | export interface Settlement { 9 | integration: number; 10 | settled_by?: string; 11 | settlement_date: Date; 12 | domain: string; 13 | total_amount: number; 14 | status: string; 15 | id: number; 16 | createdAt: Date; 17 | updatedAt?: Date; 18 | subaccount: CustomerSubAccount; 19 | } 20 | 21 | export interface ListSettlementsResponse extends Response { 22 | data: Settlement[]; 23 | meta: Meta; 24 | } 25 | 26 | export interface SettlementTransaction { 27 | id: number; 28 | reference: string; 29 | amount: number; 30 | created_at: Date; 31 | paidAt: Date; 32 | currency: string; 33 | channel: string; 34 | domain: string; 35 | message?: string; 36 | gateway_response: string; 37 | fees: number; 38 | } 39 | 40 | export interface ListSettlementTransactionsResponse extends Response { 41 | data: SettlementTransaction[]; 42 | meta: Meta & { total_volume: number }; 43 | } 44 | -------------------------------------------------------------------------------- /src/settlement/settlement.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { BadRequest, QueryParams } from '../interface'; 3 | import { 4 | ListSettlementsResponse, 5 | ListSettlementTransactionsResponse, 6 | SettlementQueryParams, 7 | } from './interface'; 8 | 9 | export class Settlement { 10 | private http: Axios; 11 | constructor(http: Axios) { 12 | this.http = http; 13 | } 14 | 15 | async list( 16 | queryParams?: SettlementQueryParams, 17 | ): Promise { 18 | return await this.http.get('/settlement', { params: { ...queryParams } }); 19 | } 20 | 21 | async transactions( 22 | id: string, 23 | queryParams: QueryParams, 24 | ): Promise { 25 | return await this.http.get(`/settlement/$[id]/transactions`, { 26 | params: { ...queryParams }, 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/split/interface.ts: -------------------------------------------------------------------------------- 1 | import { Meta } from '../interface'; 2 | 3 | export type SplitCurrrencyType = 'GHS' | 'NGN' | 'ZAR' | 'USD'; 4 | export type SplitType = 'percentage' | 'flat'; 5 | 6 | interface SubAccount { 7 | id: number; 8 | subaccount_code: string; 9 | business_name: string; 10 | description: string; 11 | primary_contact_name?: string; 12 | primary_contact_email?: string; 13 | primary_contact_phone?: string; 14 | metadata?: Record; 15 | percentage_charge?: number; 16 | settlement_bank?: string; 17 | account_number?: string; 18 | } 19 | 20 | export interface SplitSubAccount { 21 | /** 22 | * This is the sub account code 23 | */ 24 | subaccount: string; 25 | share: number; 26 | } 27 | 28 | export interface CreateSplit { 29 | /** 30 | * Name of the transaction split 31 | */ 32 | name: string; 33 | /** 34 | * The type of transaction split you want to create. 35 | * You can use one of the following: percentage | flat 36 | */ 37 | type: SplitType; 38 | /** 39 | * Any of NGN, GHS, ZAR, or USD 40 | */ 41 | currency: SplitCurrrencyType; 42 | /** 43 | * A list of object containing subaccount code 44 | * and number of shares: [{subaccount: ‘ACT_xxxxxxxxxx’, share: xxx},{...}] 45 | */ 46 | subaccounts: SplitSubAccount[]; 47 | /** 48 | * Any of subaccount | account | all-proportional | all 49 | */ 50 | bearer_type: string; 51 | /** 52 | * Subaccount code 53 | */ 54 | bearer_subaccount: string; 55 | } 56 | 57 | export interface ListSplitQueryParams { 58 | /** 59 | * The name of the split 60 | */ 61 | name?: string; 62 | /** 63 | * Any of true or false 64 | */ 65 | active?: boolean; 66 | /** 67 | * Sort by name, defaults to createdAt dat 68 | */ 69 | sort_by?: string; 70 | /** 71 | * Number of splits per page. If not specify we use a default value of 50. 72 | */ 73 | perPage?: number; 74 | /** 75 | * Page number to view. If not specify we use a default value of 1. 76 | * @default 1 77 | */ 78 | page?: number; 79 | /** 80 | * A timestamp from which to start listing splits e.g. 2019-09-24T00:00:05.000Z, 2019-09-21 81 | */ 82 | from?: Date; 83 | /** 84 | * A timestamp at which to stop listing splits e.g. 2019-09-24T00:00:05.000Z, 2019-09-21 85 | */ 86 | to?: Date; 87 | } 88 | 89 | interface TransactionSplit { 90 | id: number; 91 | name: string; 92 | type: string; 93 | currency: SplitCurrrencyType; 94 | integration: number; 95 | domain: string; 96 | split_code: string; 97 | active: boolean; 98 | bearer_type: string; 99 | bearer_subaccount: number; 100 | createdAt: Date; 101 | updatedAt: Date; 102 | subaccounts: { 103 | subaccount: SubAccount; 104 | share: number; 105 | }[]; 106 | total_subaccounts?: number; 107 | } 108 | 109 | export interface UpdateTransactionSplit { 110 | name: string; 111 | active: boolean; 112 | bearer_type?: string; 113 | bearer_subaccount?: string; 114 | } 115 | 116 | // Responses 117 | export interface Response { 118 | status: boolean; 119 | message: string; 120 | } 121 | 122 | export interface SplitCreatedResponse extends Response { 123 | data: TransactionSplit; 124 | } 125 | 126 | export interface ListSplitsResponse extends Response { 127 | data: TransactionSplit[]; 128 | meta: Meta; 129 | } 130 | 131 | export interface TransactionSplitResponse extends Response { 132 | data: TransactionSplit; 133 | } 134 | 135 | export interface UpdateTransactionSplitResponse extends Response { 136 | data: TransactionSplit; 137 | } 138 | -------------------------------------------------------------------------------- /src/split/split.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { BadRequest } from '../interface'; 3 | import { 4 | CreateSplit, 5 | ListSplitQueryParams, 6 | ListSplitsResponse, 7 | Response, 8 | SplitCreatedResponse, 9 | SplitSubAccount, 10 | TransactionSplitResponse, 11 | UpdateTransactionSplit, 12 | UpdateTransactionSplitResponse, 13 | } from './interface'; 14 | 15 | /** 16 | * The Transaction Splits API enables merchants 17 | * split the settlement for a transaction across 18 | * their payout account, and one or more Subaccounts. 19 | */ 20 | export class TransactionSplit { 21 | private http: Axios; 22 | constructor(http: Axios) { 23 | this.http = http; 24 | } 25 | 26 | /** 27 | * Create a split payment on your integration 28 | */ 29 | async create(data: CreateSplit): Promise { 30 | return await this.http.request({ 31 | url: '/split', 32 | data: JSON.stringify(data), 33 | method: 'post', 34 | }); 35 | } 36 | 37 | /** 38 | * List/search for the transaction splits available on your integration. 39 | */ 40 | async list( 41 | queryParams?: ListSplitQueryParams, 42 | ): Promise { 43 | return await this.http.request({ 44 | url: '/split', 45 | params: { ...queryParams }, 46 | method: 'get', 47 | }); 48 | } 49 | 50 | /** 51 | * Get details of a split on your integration. 52 | */ 53 | async fetch(splitId: string): Promise { 54 | return await this.http.request({ 55 | url: `/split/${splitId}`, 56 | method: 'get', 57 | }); 58 | } 59 | 60 | /** 61 | * Update a transaction split details on your integration 62 | */ 63 | async update( 64 | splitId: string, 65 | data: UpdateTransactionSplit, 66 | ): Promise { 67 | return await this.http.request({ 68 | url: `/split/${splitId}`, 69 | data: JSON.stringify(data), 70 | method: 'put', 71 | }); 72 | } 73 | 74 | /** 75 | * Add a Subaccount to a Transaction Split, 76 | * or update the share of an existing Subaccount in a Transaction Split 77 | */ 78 | async add( 79 | splitId: string, 80 | data: SplitSubAccount, 81 | ): Promise { 82 | return await this.http.request({ 83 | url: `/split/${splitId}/subaccount/add`, 84 | data: JSON.stringify(data), 85 | method: 'post', 86 | }); 87 | } 88 | 89 | /** 90 | * Remove a subaccount from a transaction split 91 | */ 92 | async remove( 93 | splitId: string, 94 | subaccount: string, 95 | ): Promise { 96 | return await this.http.request({ 97 | url: `/split/${splitId}/subaccount/remove`, 98 | data: JSON.stringify({ subaccount }), 99 | method: 'post', 100 | }); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/subaccounts/interface.ts: -------------------------------------------------------------------------------- 1 | import { Response } from '../interface'; 2 | 3 | export interface CreateUpdateSubAccount { 4 | /** 5 | * Name of business for subaccount 6 | */ 7 | business_name: string; 8 | /** 9 | * Bank Code for the bank. 10 | * You can get the list of Bank Codes by calling the List Banks endpoint. 11 | */ 12 | settlement_bank: string; 13 | /** 14 | * Bank Account Number 15 | */ 16 | account_number: string; 17 | 18 | /** 19 | * The default percentage charged when 20 | * receiving on behalf of this subaccount 21 | */ 22 | percentage_charge: number; 23 | /** 24 | * A description for this subaccount 25 | */ 26 | description: string; 27 | /** 28 | * A name for the contact person for this subaccoun 29 | */ 30 | primary_contact_name?: string; 31 | /** 32 | * A contact email for the subaccount 33 | */ 34 | primary_contact_email?: string; 35 | /** 36 | * A phone number to call for this subaccount 37 | */ 38 | primary_contact_phone?: string; 39 | /** 40 | * Stringified JSON object. 41 | * Add a custom_fields attribute which has an 42 | * array of objects if you would like the 43 | * fields to be added to your transaction 44 | * when displayed on the dashboard. 45 | * Sample: 46 | * { 47 | * "custom_fields": [ 48 | * { 49 | * "display_name":"Cart ID", 50 | * "variable_name": "cart_id", 51 | * "value": "8393" 52 | * } 53 | * ] 54 | * } 55 | */ 56 | metadata?: string; 57 | } 58 | 59 | interface SubAccount { 60 | id: number; 61 | domain: string; 62 | subaccount_code: string; 63 | business_name: string; 64 | description?: string; 65 | primary_contact_name?: string; 66 | primary_contact_email?: string; 67 | primary_contact_phone?: string; 68 | metadata: Record; 69 | percentage_charge: number; 70 | is_verified: boolean; 71 | settlement_bank: string; 72 | account_number: string; 73 | settlement_schedule: string; 74 | active: boolean; 75 | migrate: boolean; 76 | integration: number; 77 | createdAt: Date; 78 | updatedAt: Date; 79 | currency: string; 80 | } 81 | 82 | export interface SubAccountCreatedUpdateResponse extends Response { 83 | data: SubAccount; 84 | } 85 | 86 | export interface ListSubAccountsResponse extends Response { 87 | data: SubAccount[]; 88 | } 89 | 90 | export interface FetchSubAccountResponse extends Response { 91 | data: SubAccount; 92 | } 93 | -------------------------------------------------------------------------------- /src/subaccounts/subaccount.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { BadRequest, QueryParams } from '../interface'; 3 | import { 4 | CreateUpdateSubAccount, 5 | FetchSubAccountResponse, 6 | ListSubAccountsResponse, 7 | SubAccountCreatedUpdateResponse, 8 | } from './interface'; 9 | 10 | export class SubAccount { 11 | private http: Axios; 12 | constructor(http: Axios) { 13 | this.http = http; 14 | } 15 | 16 | async create( 17 | data: CreateUpdateSubAccount, 18 | ): Promise { 19 | return await this.http.post('/subaccount', JSON.stringify(data)); 20 | } 21 | 22 | async list(queryParams?: QueryParams): Promise { 23 | return await this.http.get('/subaccount', { params: { ...queryParams } }); 24 | } 25 | 26 | async fetch(id: string): Promise { 27 | return await this.http.get(`/subaccount/${id}`); 28 | } 29 | 30 | async update( 31 | id: string, 32 | data: CreateUpdateSubAccount, 33 | ): Promise { 34 | return await this.http.put(`/subaccount/${id}`, JSON.stringify(data)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/subscription/index.ts: -------------------------------------------------------------------------------- 1 | export * from './interface'; 2 | -------------------------------------------------------------------------------- /src/subscription/interface.ts: -------------------------------------------------------------------------------- 1 | import { Authorization } from '../charge/interface'; 2 | import { Customer } from '../customer/interface'; 3 | import { Meta } from '../interface'; 4 | import { IPlan } from '../plan'; 5 | 6 | export interface CreateSubscription { 7 | /** 8 | * Customer's email address or customer code 9 | */ 10 | customer: string; 11 | /** 12 | * Plan code 13 | */ 14 | plan: string; 15 | /** 16 | * If customer has multiple authorizations, you can set the desired 17 | * authorization you wish to use for this subscription here. 18 | * If this is not supplied, the customer's most recent authorization would be used 19 | */ 20 | authorization?: string; 21 | /** 22 | * Set the date for the first debit. (ISO 8601 format) 23 | * e.g `2022-01-01T00:00:00+01:00` 24 | */ 25 | start_date?: Date; 26 | } 27 | 28 | export interface Response { 29 | status: boolean; 30 | message: string; 31 | } 32 | 33 | export interface SubscriptionCreated extends Response { 34 | data: Subscription; 35 | } 36 | 37 | export interface ListSubscriptions extends Response { 38 | data: Subscription[]; 39 | meta: Meta; 40 | } 41 | 42 | export interface FetchSubscription extends Response { 43 | data: { 44 | invoices: unknown[]; 45 | customer: Customer; 46 | plan: IPlan; 47 | integration: number; 48 | authorization: Authorization; 49 | domain: string; 50 | start: number; 51 | status: string; 52 | quantity: number; 53 | amount: number; 54 | subscription_code: string; 55 | email_token: string; 56 | easy_cron_id: string; 57 | cron_expression: string; 58 | next_payment_date: Date; 59 | open_invoice: string; 60 | id: number; 61 | createdAt: Date; 62 | updatedAt: Date; 63 | }; 64 | } 65 | 66 | export interface GenerateSubscriptionLink extends Response { 67 | data: { 68 | link: string; 69 | }; 70 | } 71 | 72 | export interface EnableOrDisableSubscription { 73 | code: string; 74 | token: string; 75 | } 76 | 77 | export interface Subscription { 78 | customer: Customer; 79 | plan: IPlan; 80 | integration: number; 81 | authorization: Authorization; 82 | domain: string; 83 | start: number; 84 | status: string; 85 | quantity: number; 86 | amount: number; 87 | subscription_code: string; 88 | email_token: string; 89 | easy_cron_id: string; 90 | cron_expression: string; 91 | next_payment_date: Date; 92 | open_invoice: string; 93 | id: number; 94 | createdAt: Date; 95 | updatedAt: Date; 96 | } 97 | 98 | export interface ListSubscriptionQueryParams { 99 | /** 100 | * Specify how many records you want to retrieve per page. 101 | * If not specify we use a default value of 50. 102 | */ 103 | perPage?: number; 104 | /** 105 | * Specify exactly what page you want to retrieve. 106 | * If not specify we use a default value of 1. 107 | */ 108 | page?: number; 109 | /** 110 | * Filter by Customer ID 111 | */ 112 | customer?: number; 113 | /** 114 | * Filter by Plan ID 115 | */ 116 | plan?: number; 117 | } 118 | -------------------------------------------------------------------------------- /src/subscription/subscription.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { 3 | CreateSubscription, 4 | EnableOrDisableSubscription, 5 | FetchSubscription, 6 | GenerateSubscriptionLink, 7 | ListSubscriptionQueryParams, 8 | ListSubscriptions, 9 | Response, 10 | SubscriptionCreated, 11 | } from './interface'; 12 | 13 | interface BadRequest { 14 | status: boolean; 15 | message: string; 16 | } 17 | 18 | export class Subscription { 19 | http: Axios; 20 | constructor(http: Axios) { 21 | this.http = http; 22 | } 23 | 24 | async create( 25 | data: CreateSubscription, 26 | ): Promise { 27 | return await this.http.post('/subscription', JSON.stringify(data)); 28 | } 29 | 30 | async list( 31 | queryParams?: ListSubscriptionQueryParams, 32 | ): Promise { 33 | return await this.http.get('/subscription', { params: { ...queryParams } }); 34 | } 35 | 36 | async fetch(idOrCode: string): Promise { 37 | return await this.http.get(`/subscription/${idOrCode}`); 38 | } 39 | 40 | async enable( 41 | data: EnableOrDisableSubscription, 42 | ): Promise { 43 | return await this.http.post('/subscription/enable', JSON.stringify(data)); 44 | } 45 | async disable( 46 | data: EnableOrDisableSubscription, 47 | ): Promise { 48 | return await this.http.post('/subscription/disable', JSON.stringify(data)); 49 | } 50 | 51 | async generateSubscriptionLink( 52 | code: string, 53 | ): Promise { 54 | return await this.http.get(`/subscription/${code}/manage/link`); 55 | } 56 | 57 | async sendUpdateSubscriptionLink( 58 | code: string, 59 | ): Promise { 60 | return await this.http.post(`/subscription/${code}/manage/email`); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/transaction/README.md: -------------------------------------------------------------------------------- 1 | # Transactions 2 | Import the package 3 | For Typescript 4 | ``` 5 | import Paystack from 'paystack-sdk' 6 | const paystack = new Paystack("secret_key); 7 | ``` 8 | For Javscript 9 | ``` 10 | const Paystack = require('paystack-sdk'); 11 | const paystack = new Paystack("secret_key") 12 | ``` 13 | ### Initialize Transaction 14 | ``` 15 | paystack.transaction 16 | .initialize({ 17 | amount: 2000, 18 | email: 'john@doe.com', 19 | }) 20 | .then((transaction) => console.log(transaction)); 21 | ``` 22 | -------------------------------------------------------------------------------- /src/transaction/interface.ts: -------------------------------------------------------------------------------- 1 | import { Authorization } from '../charge/interface'; 2 | import { Customer } from '../customer/interface'; 3 | import { Meta } from '../interface'; 4 | 5 | export interface InitializeTransaction { 6 | /** 7 | * Amount should be in **kobo** if currency 8 | * is `NGN`, **pesewas**, if the currency is `GHS` and 9 | * **cents**, if currency is `ZAR` 10 | */ 11 | amount: string; 12 | /** 13 | * Customer's email address 14 | */ 15 | email: string; 16 | /** 17 | * The transaction currency (NGN, GHS, ZAR or USD). 18 | * Defaults to your integration currency. 19 | */ 20 | currency?: string; 21 | /** 22 | * Unique transaction reference. Only `-`,`.`,`=` 23 | * and alphanumeric characters allowed 24 | */ 25 | reference?: string; 26 | /** 27 | * Fully qualified url, e.g. https://example.com/. 28 | * Use this to override the callback url provided on 29 | * the dashboard for this transaction 30 | */ 31 | callback_url?: string; 32 | /** 33 | * If transaction is to create a subscription to a predefined plan, 34 | * provide plan code here. This would invalidate the value provided 35 | * in `amount` 36 | */ 37 | plan?: string; 38 | /** 39 | * Number of times to charge customer during subscription to plan 40 | */ 41 | invoice_limit?: string; 42 | /** 43 | * Stringified JSON object of custom data. 44 | * Kindly check the [Metadata](https://paystack.com/docs/payments/metadata) 45 | * page for more information. 46 | */ 47 | metadata?: Record; 48 | /** 49 | * An array of payment channels to control what channels 50 | * you want to make available to the user to make a payment 51 | * with. 52 | * @example ['card','bank','ussd','qr','mobile_money','bank_transfer'] 53 | */ 54 | channels?: string[]; 55 | /** 56 | * The split code of the transaction split. 57 | * e.g `SPL_98WF13Eb3w` 58 | */ 59 | split_code?: string; 60 | /** 61 | * The code for the subaccount that owns the payment e.g `ACCT_8f4s1eq7m16rlzj` 62 | */ 63 | subaccount?: string; 64 | /** 65 | * A flat fee to charge the subaccount for this transaction (). 66 | * This overrides the split percentage set when the subaccount 67 | * was created. Ideally, you will need to use this if you are 68 | * splitting in flat rates (since subaccount creation only allows 69 | * for percentage split). e.g. `7000` for a 70 naira fiat fee. 70 | */ 71 | transaction_charge?: number; 72 | /** 73 | * Who bears Paystack charges? 74 | * `account` or `subaccount` (defaults to `account`) 75 | */ 76 | bearer?: string; 77 | } 78 | 79 | export interface Response { 80 | status: boolean; 81 | message: string; 82 | } 83 | 84 | export interface TransactionInitialized extends Response { 85 | data: { 86 | authorization_url: string; 87 | access_code: string; 88 | reference: string; 89 | }; 90 | } 91 | 92 | export interface Transaction { 93 | id: number; 94 | amount: number; 95 | currency: string; 96 | paid_at: Date; 97 | created_at: Date; 98 | status: string; 99 | reference: string; 100 | domain: string; 101 | metadata: Record; 102 | gateway_response: string; 103 | message?: string; 104 | channel: string; 105 | ip_address: string; 106 | log: [ 107 | { 108 | time_spent: number; 109 | attempt: number; 110 | authentication?: unknown; 111 | errors: number; 112 | success: boolean; 113 | mobile: boolean; 114 | input: []; 115 | channel: string; 116 | history: [ 117 | { 118 | type: string; 119 | message: string; 120 | time: number; 121 | }, 122 | ]; 123 | }, 124 | ]; 125 | fees: number; 126 | authorization: Authorization; 127 | customer: Customer; 128 | pin: string; 129 | requested_amount: number; 130 | } 131 | 132 | export interface GetTransactionResponse extends Response { 133 | data: Transaction; 134 | } 135 | 136 | export interface ListTransactions extends Response { 137 | data: Transaction[]; 138 | meta: Meta; 139 | } 140 | 141 | export interface Timeline extends Response { 142 | data: { 143 | time_spent: number; 144 | attempts: number; 145 | authentication?: unknown; 146 | errors: number; 147 | success: boolean; 148 | mobile: boolean; 149 | input: []; 150 | channel: string; 151 | history: [ 152 | { 153 | type: string; 154 | message: string; 155 | time: number; 156 | }, 157 | ]; 158 | }; 159 | } 160 | 161 | export interface ExportTransaction extends Response { 162 | data: { 163 | path: string; 164 | }; 165 | } 166 | 167 | export interface ListTransactionQueryParams { 168 | /** 169 | * Specify how many records you want to retrieve per page. 170 | * If not specify we use a default value of 50. 171 | */ 172 | perPage?: number; 173 | /** 174 | * Specify exactly what page you want to retrieve. 175 | * If not specify we use a default value of 1. 176 | */ 177 | page?: number; 178 | /** 179 | * Specify an ID for the customer whose transactions 180 | * you want to retrieve 181 | */ 182 | customer?: number; 183 | /** 184 | * Filter transactions by status ('failed', 'success', 'abandoned') 185 | */ 186 | status?: string; 187 | /** 188 | * A timestamp from which to start listing transaction 189 | * e.g `2021-10-25T00.00.05.000z`, `2021-12-25` 190 | */ 191 | from?: Date; 192 | /** 193 | * A timestamp from which to stop listing transaction 194 | * e.g `2021-10-25T00.00.05.000z`, `2021-12-25` 195 | */ 196 | to?: Date; 197 | /** 198 | * Filter transactions by amount. 199 | * Specify the amount (in **kobo** if currency is `NGN`, 200 | * **pesewas**, if currency is `GHS`, 201 | * and **cents**, if currency is `ZAR`) 202 | */ 203 | amount?: number; 204 | } 205 | 206 | export interface ChargeAuthorization { 207 | /** 208 | * Amount should be in kobo if currency is `NGN`, *pesewas*, 209 | * if currency is `GHS`, and cents, if currency is `ZAR` 210 | */ 211 | amount: string; 212 | /** 213 | * Customer's email address 214 | */ 215 | email: string; 216 | /** 217 | * Valid authorization code to charge 218 | */ 219 | authorization_code: string; 220 | /** 221 | * Unique transaction reference. Only `-`, `.`,`=` 222 | * and alphanumeric characters allowed 223 | */ 224 | reference?: string; 225 | /** 226 | * Currency in which amount shoud be charged. 227 | * Allowed values are: NGN,GHS,ZAR or USD 228 | */ 229 | currency?: string; 230 | /** 231 | * Stringified JSON object. Add a custom_fields attribute which has 232 | * an array of objects if you would like the fields to be added to your 233 | * transaction when displayed on the dashboard. 234 | * @example { 235 | * "custom_fields": [{"display_name": "Cart ID","variable_name": "cart_id","value": "8393"}]} 236 | */ 237 | metadata?: Record; 238 | /** 239 | * Send us 'card' or 'bank' or 'card','bank' as an array to specify what 240 | * options to show the user paying 241 | */ 242 | channels?: string[]; 243 | /** 244 | * The code for the subaccount that owns the payment. 245 | * @exmple ACCT_8f4s1eq7ml6rlzj 246 | */ 247 | subaccount?: string; 248 | /** 249 | * A flat fee to charge the subaccount for this transaction (in kobo if currency is NGN, 250 | * pesewas, if currency is GHS, and cents, if currency is ZAR). This overrides the split percentage 251 | * set when the subaccount was created. Ideally, you will need to use this if you are splitting in 252 | * flat rates (since subaccount creation only allows for 253 | */ 254 | transaction_charge?: number; 255 | /** 256 | * Who bears Paystack charges? `account` or `subaccount` (defaults to `account`). 257 | */ 258 | bearer?: string; 259 | /** 260 | * If you are making a scheduled charge call, it is a good idea to queue them so the processing 261 | * system does not get overloaded causing transaction processing errors. Send queue:true 262 | * to take advantage of our queued charging. 263 | */ 264 | queue?: boolean; 265 | } 266 | 267 | export interface CheckAuthorization { 268 | /** 269 | * Amount should be in kobo if currency is `NGN`, 270 | * pesewas, if currency is `GHS`, and cents, if currency is `ZAR` 271 | */ 272 | amount: string; 273 | /** 274 | * Customer's email address 275 | */ 276 | email: string; 277 | /** 278 | * Valid authorization code to charge 279 | */ 280 | authorization_code: string; 281 | /** 282 | * Currency in which amount should be charged. 283 | * Allowed values are: `NGN`, `GHS`, `ZAR` or `USD` 284 | */ 285 | currency?: string; 286 | } 287 | 288 | export interface PartialDebit { 289 | /** 290 | * Authorization Code 291 | */ 292 | authorization_code: string; 293 | /** 294 | * Specify the currency you want to debit. 295 | * Allowed values are `NGN`, `GHS`, `ZAR` or `USD`. 296 | */ 297 | currency: string; 298 | /** 299 | * Amount should be in *kobo* if currency is NGN, 300 | * pesewas, if *currency* is `GHS`, and *cents*, if currency is `ZAR` 301 | */ 302 | amount: string; 303 | /** 304 | * Customer's email address (attached to the authorization code) 305 | */ 306 | email: string; 307 | /** 308 | * Unique transaction reference. 309 | * Only `-`, `.`, `=` and alphanumeric characters allowed. 310 | */ 311 | reference: string; 312 | /** 313 | * Minimum amount to charge 314 | */ 315 | at_least: string; 316 | } 317 | 318 | export interface PartialDebitResponse extends Response { 319 | data: Record; 320 | } 321 | 322 | export interface CheckAuthorizationResponse extends Response { 323 | data: { 324 | amount: string; 325 | currency: string; 326 | }; 327 | } 328 | -------------------------------------------------------------------------------- /src/transaction/transaction.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { 3 | CheckAuthorizationResponse, 4 | ExportTransaction, 5 | ListTransactions, 6 | PartialDebitResponse, 7 | Timeline, 8 | GetTransactionResponse, 9 | } from './interface'; 10 | import { 11 | ChargeAuthorization, 12 | CheckAuthorization, 13 | InitializeTransaction, 14 | ListTransactionQueryParams, 15 | PartialDebit, 16 | TransactionInitialized, 17 | } from './interface'; 18 | 19 | interface BadRequest { 20 | status: boolean; 21 | message: string; 22 | data: null; 23 | } 24 | 25 | /** 26 | * # Tansactions 27 | * The transaction API allows you create and manage 28 | * payments on your integration 29 | */ 30 | export class Transaction { 31 | private http: Axios; 32 | constructor(http: Axios) { 33 | this.http = http; 34 | } 35 | /** 36 | * Initialize a transaction 37 | * @param {InitializeTransaction} data **Body Param** 38 | */ 39 | async initialize( 40 | data: InitializeTransaction, 41 | ): Promise { 42 | return await this.http.post( 43 | '/transaction/initialize', 44 | JSON.stringify(data), 45 | ); 46 | } 47 | async verify( 48 | reference: string, 49 | ): Promise { 50 | return await this.http.get(`/transaction/verify/${reference}`); 51 | } 52 | async list( 53 | queryParams?: ListTransactionQueryParams, 54 | ): Promise { 55 | return await this.http.get('/transaction', { 56 | params: { ...queryParams }, 57 | }); 58 | } 59 | 60 | async fetch(id: string): Promise { 61 | return await this.http.get(`/transaction/:${id}`); 62 | } 63 | 64 | async chargeAuthorization( 65 | data: ChargeAuthorization, 66 | ): Promise { 67 | return await this.http.post( 68 | '/transaction/charge_authorization', 69 | JSON.stringify(data), 70 | ); 71 | } 72 | 73 | async checkAuthorization( 74 | data: CheckAuthorization, 75 | ): Promise { 76 | return await this.http.post( 77 | '/transaction/check_authorization', 78 | JSON.stringify(data), 79 | ); 80 | } 81 | 82 | async viewTimeline(id: string): Promise { 83 | return await this.http.get(`/transaction/timeline/${id}`); 84 | } 85 | 86 | async total( 87 | queryParams: ListTransactionQueryParams, 88 | ): Promise { 89 | return await this.http.get('/transaction/totals', { 90 | params: { ...queryParams }, 91 | }); 92 | } 93 | 94 | async export( 95 | queryParams: ListTransactionQueryParams, 96 | ): Promise { 97 | return await this.http.get('/transaction/export', { 98 | params: { ...queryParams }, 99 | }); 100 | } 101 | 102 | async partialDebit( 103 | data: PartialDebit, 104 | ): Promise { 105 | return await this.http.post( 106 | '/transaction/partial_debit', 107 | JSON.stringify(data), 108 | ); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/transfer/control.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { BadRequest, Response } from '../interface'; 3 | import { 4 | CheckBalanceResponse, 5 | LedgerBalanceResponse, 6 | ResendTransferOTP, 7 | } from './interface'; 8 | 9 | export class Control { 10 | http: Axios; 11 | constructor(http: Axios) { 12 | this.http = http; 13 | } 14 | 15 | async balance(): Promise { 16 | return await this.http.get('/balance'); 17 | } 18 | 19 | async ledgerBalance(): Promise { 20 | return await this.http.get('/balance/ledger'); 21 | } 22 | 23 | async resendOTP(data: ResendTransferOTP): Promise { 24 | return await this.http.post('/transfer/resend_otp', JSON.stringify(data)); 25 | } 26 | 27 | async disableOTP(): Promise { 28 | return await this.http.post('/transfer/disable_otp'); 29 | } 30 | 31 | async finalizeDisableOTP(otp: string): Promise { 32 | return await this.http.post( 33 | '/transfer/disable_otp_finalize', 34 | JSON.stringify({ otp }), 35 | ); 36 | } 37 | 38 | async enableOTP(): Promise { 39 | return await this.http.post('/transfer/enable_otp'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/transfer/interface.ts: -------------------------------------------------------------------------------- 1 | import { Response } from '../interface'; 2 | 3 | export interface InitiateTransfer { 4 | /** 5 | * Where should we transfer from? Only `balance` for now 6 | */ 7 | source: string; 8 | /** Amount to transfer in *kobo* if currency is `NGN` 9 | * and *pesewas* if currency is `GHS`. 10 | */ 11 | amount: number; 12 | /** 13 | * Code for transfer recipient 14 | */ 15 | recipient: string; 16 | /** 17 | * The reason for the transfer 18 | */ 19 | reason?: string; 20 | /** 21 | * Specify the currency of the transfer. Defaults to NGN 22 | */ 23 | currency?: string; 24 | /** If specified, the field should be a unique identifier (in lowercase) 25 | * for the object. Only `-`,`_` and alphanumeric characters allowed. 26 | */ 27 | reference?: string; 28 | } 29 | 30 | export interface InitiateBulkTransfer { 31 | /** 32 | * Where should we transfer from? Only `balance` for now 33 | */ 34 | source: string; 35 | /** 36 | * A list of transfer object. Each object should contain `amount`, `recipient`, and `reference` 37 | */ 38 | transfers: { amount: number; recipient: string; reference: string }[]; 39 | } 40 | 41 | export interface ResendTransferOTP { 42 | transfer_code: string; 43 | reason: 'resend_otp' | 'transfer'; 44 | } 45 | 46 | export interface FinalizeTransfer extends Response { 47 | data: Transfer; 48 | } 49 | 50 | export interface TransferInitiated extends Response { 51 | data: Transfer; 52 | } 53 | 54 | export interface BulkTransferInitiated extends Response { 55 | data: Transfer[]; 56 | } 57 | 58 | export interface ListTransfers extends Response { 59 | data: Transfer[]; 60 | } 61 | 62 | export interface FetchTransfer extends Response { 63 | data: Transfer; 64 | } 65 | 66 | export interface VerifyTransfer extends Response { 67 | data: Transfer; 68 | } 69 | 70 | export interface ListTransferQueryParams { 71 | /** 72 | * Specify how many records you want to retrieve per page. 73 | * If not specify we use a default value of 50. 74 | */ 75 | perPage?: number; 76 | /** 77 | * Specify exactly what page you want to retrieve. 78 | * If not specify we use a default value of 1. 79 | */ 80 | page?: number; 81 | /** 82 | * Specify an ID for the customer whose transactions 83 | * you want to retrieve 84 | */ 85 | customer?: number; 86 | /** 87 | * A timestamp from which to start listing transaction 88 | * e.g `2021-10-25T00.00.05.000z`, `2021-12-25` 89 | */ 90 | from?: Date; 91 | /** 92 | * A timestamp from which to stop listing transaction 93 | * e.g `2021-10-25T00.00.05.000z`, `2021-12-25` 94 | */ 95 | to?: Date; 96 | } 97 | 98 | export interface Transfer { 99 | integration: number; 100 | domain: string; 101 | amount: number; 102 | source: string; 103 | source_details: string; 104 | reason: string; 105 | recipient: number | string | Record; 106 | status: string; 107 | failures: unknown; 108 | transfer_code: string; 109 | id: number; 110 | createdAt: Date; 111 | updatedAt: Date; 112 | } 113 | 114 | export interface LedgerBalance { 115 | id: number; 116 | integration: number; 117 | domain: string; 118 | balance: number; 119 | currency: string; 120 | difference: number; 121 | reason: string; 122 | model_responsible: string; 123 | model_row: number; 124 | createdAt: Date; 125 | updatedAt: Date; 126 | } 127 | 128 | export interface Balance { 129 | currency: string; 130 | balance: number; 131 | } 132 | 133 | export interface CheckBalanceResponse extends Response { 134 | data: Balance[]; 135 | } 136 | 137 | export interface LedgerBalanceResponse extends Response { 138 | data: LedgerBalance[]; 139 | } 140 | -------------------------------------------------------------------------------- /src/transfer/transfer.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { Control } from './control'; 3 | import { 4 | BulkTransferInitiated, 5 | FetchTransfer, 6 | FinalizeTransfer, 7 | InitiateBulkTransfer, 8 | InitiateTransfer, 9 | ListTransferQueryParams, 10 | ListTransfers, 11 | TransferInitiated, 12 | VerifyTransfer, 13 | } from './interface'; 14 | 15 | interface BadRequest { 16 | status: boolean; 17 | message: string; 18 | } 19 | 20 | export class Transfer { 21 | private http: Axios; 22 | public control: Control; 23 | constructor(http: Axios) { 24 | this.http = http; 25 | this.control = new Control(http); 26 | } 27 | 28 | /** 29 | * # Initiate Transfer 30 | * Status of transfer object returned will be `pending` if OTP is disabled. 31 | * In the event that an OTP is required, status will read `otp`. 32 | */ 33 | async initiate( 34 | data: InitiateTransfer, 35 | ): Promise { 36 | return await this.http.post('/transfer', JSON.stringify(data)); 37 | } 38 | 39 | /** 40 | * # Finalize Transfer 41 | * Finalize an initiated transfer 42 | */ 43 | async finalize( 44 | transferCode: string, 45 | otp: string, 46 | ): Promise { 47 | return await this.http.post( 48 | '/transfer/finalize_transfer', 49 | JSON.stringify({ transfer_code: transferCode, otp }), 50 | ); 51 | } 52 | 53 | async bulk( 54 | data: InitiateBulkTransfer, 55 | ): Promise { 56 | return await this.http.post('/transfer/bulk', JSON.stringify(data)); 57 | } 58 | 59 | async list( 60 | queryParams?: ListTransferQueryParams, 61 | ): Promise { 62 | return await this.http.get('/transfer', { 63 | params: { ...queryParams }, 64 | }); 65 | } 66 | 67 | async fetch(idOrCode: string): Promise { 68 | return await this.http.get(`/transfer/${idOrCode}`); 69 | } 70 | 71 | async verify(reference: string): Promise { 72 | return await this.http.get(`transfer/verify/${reference}`); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/verification/interface.ts: -------------------------------------------------------------------------------- 1 | import { Response } from '../interface'; 2 | 3 | export interface ResolveAccount { 4 | /** 5 | * Account Number 6 | */ 7 | account_number: string; 8 | 9 | /** 10 | * You can get the list of bank codes 11 | * by calling the List Banks endpoint 12 | */ 13 | bank_code: string; 14 | } 15 | 16 | export type AccountType = 'personal' | 'business'; 17 | 18 | export type DocumentType = 19 | | 'identityNumber' 20 | | 'passportNumber' 21 | | 'businessRegistrationNumber'; 22 | 23 | export interface AccountResolved extends Response { 24 | data: { 25 | /** 26 | * Verified Account Number 27 | */ 28 | account_number: string; 29 | 30 | /** 31 | * Verified Account Name 32 | */ 33 | account_name: string; 34 | }; 35 | } 36 | 37 | export interface ValidateAccount { 38 | /** 39 | * The bank code of the customer’s bank. 40 | * You can fetch the bank codes 41 | * by using our List Banks endpoint 42 | */ 43 | bank_code: string; 44 | 45 | /** 46 | * The two digit ISO code of the customer’s bank 47 | */ 48 | country_code: string; 49 | 50 | /** 51 | * Customer’s account number 52 | */ 53 | account_number: string; 54 | 55 | /** 56 | * Customer's first and last name registered with their bank 57 | */ 58 | account_name: string; 59 | 60 | /** 61 | * This can take one of: [ personal, business ] 62 | */ 63 | account_type: AccountType; 64 | 65 | /** 66 | * Customer’s mode of identity. 67 | * This could be one of: 68 | * [ identityNumber, passportNumber, businessRegistrationNumber ] 69 | */ 70 | document_type: DocumentType; 71 | 72 | /** 73 | * Customer’s mode of identity number 74 | */ 75 | document_number: string; 76 | } 77 | 78 | export interface AccountVerifiedResponse extends Response { 79 | data: { 80 | /** 81 | * Verification Status 82 | */ 83 | verified: boolean; 84 | 85 | /** 86 | * Verification Message 87 | */ 88 | verificationMessage: string; 89 | }; 90 | } 91 | 92 | export interface BinResolvedResponse extends Response { 93 | data: { 94 | bin: string; 95 | brand: string; 96 | sub_brand: string; 97 | country_code: string; 98 | country_name: string; 99 | card_type: string; 100 | bank: string; 101 | linked_bank_id: number; 102 | }; 103 | } 104 | -------------------------------------------------------------------------------- /src/verification/verification.ts: -------------------------------------------------------------------------------- 1 | import { Axios } from 'axios'; 2 | import { 3 | ResolveAccount, 4 | AccountResolved, 5 | ValidateAccount, 6 | AccountVerifiedResponse, 7 | BinResolvedResponse, 8 | } from './interface'; 9 | import { BadRequest } from '../interface'; 10 | 11 | /** 12 | * ## Verification 13 | * The Verification API allows you perform KYC processes. 14 | */ 15 | export class Verification { 16 | private http: Axios; 17 | constructor(http: Axios) { 18 | this.http = http; 19 | } 20 | 21 | /** 22 | * #### Resolve Account 23 | * Confirm an account belongs to the right customer 24 | * @param {ResolveAccount} data **Query Param** 25 | */ 26 | async resolveAccount( 27 | data: ResolveAccount, 28 | ): Promise { 29 | return await this.http.get('/bank/resolve', { params: { ...data } }); 30 | } 31 | 32 | /** 33 | * #### Validate Account 34 | * Confirm the authenticity of a customer's account number 35 | * before sending money 36 | * @param {ValidateAccount} data **Data Param** 37 | */ 38 | async validateAccount( 39 | data: ValidateAccount, 40 | ): Promise { 41 | return await this.http.post('/bank/validate', JSON.stringify(data)); 42 | } 43 | 44 | /** 45 | * #### Resolve Card BIN 46 | * Get more information about a customer's card 47 | * using the first 6 characters of the card 48 | * @param {string} bin **Path Param** 49 | */ 50 | async resolveCard(bin: number): Promise { 51 | return await this.http.get(`/decision/bin/${bin}`); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /test.ts: -------------------------------------------------------------------------------- 1 | import { Paystack } from './src/paystack'; 2 | 3 | const paystack = new Paystack( 4 | 'sk_test_aa82d43e2dd64b5188ab855cf1770c37198a0afc', 5 | ); 6 | 7 | // exports.listCustomers = paystack.customer 8 | // .list() 9 | // .then((c) => console.log(c.data.length)); 10 | // exports.createCustomer = paystack.customer 11 | // .create({ 12 | // email: 'j@j.com', 13 | // first_name: 'Jon', 14 | // last_name: 'Doe', 15 | // }) 16 | // .then((c) => console.log(c)); 17 | // paystack.transaction.list().then((t) => console.log(t.data.length)); 18 | 19 | /* 20 | Test by devFresher 21 | */ 22 | paystack.verification 23 | .resolveAccount({ 24 | account_number: '8101424375', 25 | bank_code: '999992', 26 | }) 27 | .then((resolved) => { 28 | console.log(resolved); 29 | }); 30 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "experimentalDecorators": true, 4 | "target": "es6", 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "declaration": true, 8 | "outDir": "./dist", 9 | "esModuleInterop": true, 10 | "strict": true, 11 | "checkJs": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strictNullChecks": false 14 | }, 15 | "include": ["src/**/*.ts"], 16 | "exclude": ["node_modules", "**/__tests__/*"] 17 | } 18 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint:recommended", "tslint-config-prettier"], 3 | "rules": { 4 | "no-empty-interface": false, 5 | "no-unused-expression": false, 6 | "no-implicity-any": false 7 | } 8 | } 9 | --------------------------------------------------------------------------------