├── .eslintrc ├── .github └── workflows │ └── test-and-deplyo.yml ├── .gitignore ├── .prettierrc ├── LICENSE.txt ├── README.md ├── jest.config.js ├── package-lock.json ├── package.json ├── src ├── GoCardlessException.ts ├── api │ ├── api.test.ts │ └── api.ts ├── client.ts ├── constants.ts ├── errors.ts ├── fixtures │ ├── gocardless_internal_error.json │ ├── idempotency_conflict.json │ ├── insufficent_permissions.json │ ├── invalid_api_usage.json │ ├── invalid_state.json │ ├── rate_limit_exceeded.json │ ├── unauthorized.json │ ├── validation_failed.json │ └── webhook_body.json ├── index.ts ├── services │ ├── balanceService.ts │ ├── bankAccountDetailService.ts │ ├── bankAuthorisationService.ts │ ├── bankDetailsLookupService.ts │ ├── billingRequestFlowService.ts │ ├── billingRequestService.ts │ ├── billingRequestTemplateService.ts │ ├── billingRequestWithActionService.ts │ ├── blockService.ts │ ├── creditorBankAccountService.ts │ ├── creditorService.ts │ ├── currencyExchangeRateService.ts │ ├── customerBankAccountService.ts │ ├── customerNotificationService.ts │ ├── customerService.ts │ ├── eventService.ts │ ├── exportService.ts │ ├── instalmentScheduleService.ts │ ├── institutionService.ts │ ├── logoService.ts │ ├── mandateImportEntryService.ts │ ├── mandateImportService.ts │ ├── mandatePdfService.ts │ ├── mandateService.ts │ ├── negativeBalanceLimitService.ts │ ├── outboundPaymentService.ts │ ├── payerAuthorisationService.ts │ ├── payerThemeService.ts │ ├── paymentService.ts │ ├── payoutItemService.ts │ ├── payoutService.ts │ ├── redirectFlowService.ts │ ├── refundService.ts │ ├── scenarioSimulatorService.ts │ ├── schemeIdentifierService.ts │ ├── subscriptionService.ts │ ├── taxRateService.ts │ ├── transferredMandateService.ts │ ├── verificationDetailService.ts │ └── webhookService.ts ├── types │ └── Types.ts ├── webhooks.test.ts └── webhooks.ts ├── tsconfig.json └── tslint.json /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "extends": ["plugin:@typescript-eslint/recommended"], 4 | "parserOptions": { "ecmaVersion": 2018, "sourceType": "module" }, 5 | "rules": { 6 | "no-irregular-whitespace": "error", 7 | "no-multiple-empty-lines": [ 8 | "error", 9 | {"max": 2} 10 | ], 11 | /* Allow empty types {} for Institution ID */ 12 | "@typescript-eslint/ban-types": [ 13 | "error", 14 | { 15 | "extendDefaults": true, 16 | "types": { 17 | "{}": false 18 | } 19 | } 20 | ] 21 | } 22 | } -------------------------------------------------------------------------------- /.github/workflows/test-and-deplyo.yml: -------------------------------------------------------------------------------- 1 | name: test & publish 2 | on: push 3 | 4 | jobs: 5 | test: 6 | runs-on: ubuntu-latest 7 | container: 8 | image: node:lts 9 | steps: 10 | - uses: actions/checkout@v3.3.0 11 | - run: npm install --save-dev jest typescript ts-jest @types/jest 12 | - run: npm test 13 | 14 | transpile: 15 | runs-on: ubuntu-latest 16 | container: 17 | image: node:lts 18 | needs: 19 | - test 20 | steps: 21 | - uses: actions/checkout@v3.3.0 22 | - run: npm install 23 | - run: npm install -g typescript 24 | - run: tsc -p . 25 | - uses: actions/upload-artifact@v4 26 | with: 27 | path: "dist" 28 | 29 | publish_to_npm: 30 | if: github.ref == 'refs/heads/master' 31 | runs-on: ubuntu-latest 32 | container: 33 | image: node:lts 34 | needs: 35 | - transpile 36 | env: 37 | DIST_FOLDER: "/dist/artifact" 38 | steps: 39 | - uses: actions/checkout@v3.3.0 40 | - uses: actions/download-artifact@v4 41 | with: 42 | path: "/dist" 43 | - run: cp package.json $DIST_FOLDER 44 | - run: cp README.md $DIST_FOLDER 45 | - run: npm install 46 | - name: Authenticate w/NPM. 47 | run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_AUTH_TOKEN }}" > .npmrc 48 | - name: Publish the library. 49 | run: npm publish $DIST_FOLDER 50 | -------------------------------------------------------------------------------- /.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 | 84 | # Gatsby files 85 | .cache/ 86 | # Comment in the public line in if your project uses Gatsby and not Next.js 87 | # https://nextjs.org/blog/next-9-1#public-directory-support 88 | # public 89 | 90 | # vuepress build output 91 | .vuepress/dist 92 | 93 | # Serverless directories 94 | .serverless/ 95 | 96 | # FuseBox cache 97 | .fusebox/ 98 | 99 | # DynamoDB Local files 100 | .dynamodb/ 101 | 102 | # TernJS port file 103 | .tern-port 104 | 105 | # Stores VSCode versions used for testing VSCode extensions 106 | .vscode-test 107 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "all", 4 | "singleQuote": true, 5 | "printWidth": 120, 6 | "tabWidth": 2 7 | } -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 GoCardless 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node.js client for the GoCardless API 2 | 3 | [![GoCardless](https://circleci.com/gh/gocardless/gocardless-nodejs.svg?style=svg)](https://github.com/gocardless/gocardless-nodejs/commits/master) [![npm version](https://badge.fury.io/js/gocardless-nodejs.svg)](https://badge.fury.io/js/gocardless-nodejs) 4 | 5 | A Node.js client for the GoCardless API. For full details of the GoCardless API, see the [API docs](https://developer.gocardless.com/). 6 | 7 | ## Installation 8 | 9 | ```bash 10 | $ npm i gocardless-nodejs 11 | ``` 12 | 13 | ## Usage 14 | 15 | ### Initialising the client 16 | 17 | To initialise the client, you must provide: 18 | 19 | - An [access token](https://developer.gocardless.com/getting-started/api/making-your-first-request/#creating-an-access-token). 20 | - The environment that this token is for (see [here](https://github.com/gocardless/gocardless-nodejs/blob/master/src/constants.ts) for a list of available environments). 21 | - Any additional options (see [here](#available-client-options) for a list of supported options). 22 | 23 | 24 | ```js 25 | const gocardless = require('gocardless-nodejs'); 26 | const constants = require('gocardless-nodejs/constants'); 27 | 28 | 29 | // Initialise the client. 30 | const client = gocardless( 31 | process.env.GC_ACCESS_TOKEN, 32 | constants.Environments.Sandbox, 33 | { raiseOnIdempotencyConflict: true }, 34 | ); 35 | ``` 36 | 37 | ### The Basics 38 | 39 | We'll illustrate the basic library usage by demonstrating on the [payment resource](https://developer.gocardless.com/api-reference/#core-endpoints-payments). 40 | 41 | For a full list of available resources, visit the [GoCardless API reference](https://developer.gocardless.com/api-reference/#core-endpoints). 42 | 43 | 44 | ```js 45 | const uuidv4 = require('uuid/v4'); 46 | 47 | // Create a new payment. 48 | const payment = await client.payments.create( 49 | { 50 | amount: 100, 51 | currency: "GBP", 52 | links: { mandate: "MD123" }, 53 | }, 54 | { uuidv4() }, 55 | ); 56 | 57 | // List the first three payments past a certain date. 58 | const payments = await client.payments.list({ 59 | limit: 3, 60 | created_at: { 61 | gt: '2020-01-01T17:01:06.000Z', 62 | }, 63 | }); 64 | 65 | // Get a payment. 66 | const payment = await client.payments.find('PM123'); 67 | 68 | // Update a payment. 69 | await client.payments.update('PM123', { amount: '22' }); 70 | 71 | // Cancel a payment. 72 | await client.payments.cancel('PM123'); 73 | ``` 74 | 75 | ### The `all` method 76 | 77 | All resources with a `list` method will also have an additional `*all` method. This method acts like the regular `list` method and accepts the same parameters, but instead returns an async generator. 78 | 79 | 80 | ```js 81 | for await (const payment of client.payments.all()) { 82 | console.log(payment.id); 83 | } 84 | ``` 85 | 86 | ### Available client options 87 | 88 | - `raiseOnIdempotencyConflict`: set to `true` to raise exceptions on [idempotency](https://developer.gocardless.com/api-reference/#making-requests-idempotency-keys) conflicts. Defaults to `false`. 89 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gocardless-nodejs", 3 | "version": "5.3.0", 4 | "description": "Node.js client for the GoCardless API - a powerful, simple solution for the collection of recurring bank-to-bank payments", 5 | "author": "GoCardless Ltd ", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/gocardless/gocardless-nodejs.git" 9 | }, 10 | "bugs": { 11 | "url": "https://github.com/gocardless/gocardless-nodejs/issues" 12 | }, 13 | "homepage": "https://github.com/gocardless/gocardless-nodejs#readme", 14 | "license": "MIT", 15 | "keywords": [ 16 | "gocardless", 17 | "payments", 18 | "rest", 19 | "api", 20 | "direct debit" 21 | ], 22 | "scripts": { 23 | "test": "jest", 24 | "lint": "eslint src/**/*.ts", 25 | "format": "prettier src --check --write && eslint src/**/*.ts --fix" 26 | }, 27 | "dependencies": { 28 | "got": "^11.8.6", 29 | "lodash": "^4.17.21", 30 | "uuid": "^9.0.0", 31 | "buffer-equal-constant-time": "1.0.1", 32 | "qs": "^6.11.1" 33 | }, 34 | "devDependencies": { 35 | "@types/jest": "^29.5.0", 36 | "@types/node": "^18.15.10", 37 | "@typescript-eslint/eslint-plugin": "^5.57.0", 38 | "@typescript-eslint/parser": "^5.57.0", 39 | "eslint": "^8.37.0", 40 | "eslint-config-prettier": "^8.8.0", 41 | "eslint-plugin-prettier": "^4.2.1", 42 | "jest": "^29.5.0", 43 | "nock": "^13.3.0", 44 | "prettier": "^2.8.7", 45 | "prettier-eslint": "^15.0.1", 46 | "prettier-eslint-cli": "^7.1.0", 47 | "ts-jest": "29.0.5", 48 | "typescript": "^5.0.2" 49 | }, 50 | "main": "index.js", 51 | "types": "types/Types.d.ts", 52 | "engines": { 53 | "node": ">=18.0" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/GoCardlessException.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export class GoCardlessException { 4 | private message: string; 5 | private errors: object; 6 | private documentationUrl: string; 7 | private type: string; 8 | private requestId: string; 9 | private code: string; 10 | private response: object; 11 | 12 | constructor(response) { 13 | const { 14 | body: { error }, 15 | } = response; 16 | const { 17 | message, 18 | errors, 19 | documentation_url: documentationUrl, 20 | type, 21 | request_id: requestId, 22 | code, 23 | } = error; 24 | 25 | this.response = response; 26 | this.message = message; 27 | this.errors = errors; 28 | this.documentationUrl = documentationUrl; 29 | this.type = type; 30 | this.requestId = requestId; 31 | this.code = code; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/api/api.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import os = require('os'); 4 | import process = require('process'); 5 | import _ = require('lodash'); 6 | import { v4 as uuidv4 } from 'uuid'; 7 | import * as url from 'url'; 8 | import got from 'got'; 9 | import qs from 'qs'; 10 | 11 | import { Environments, CLIENT_VERSION, API_VERSION } from '../constants'; 12 | import * as GoCardlessErrors from '../errors'; 13 | 14 | interface APIOptions { 15 | proxy?: object; 16 | raiseOnIdempotencyConflict?: boolean; 17 | } 18 | 19 | interface UrlParameter { 20 | key?: string; 21 | value?: string; 22 | } 23 | 24 | interface APIRequestParameters { 25 | path: string; 26 | method: string; 27 | urlParameters?: UrlParameter[]; 28 | requestParameters?: object; 29 | payloadKey?: string | null; 30 | idempotencyKey?: string; 31 | fetch?: (identity: string) => Promise | null; 32 | customHeaders?: object; 33 | } 34 | 35 | export class Api { 36 | private _token: string; 37 | private _environment: Environments; 38 | private _baseUrl: string; 39 | private _agent: object; 40 | private raiseOnIdempotencyConflict: boolean; 41 | 42 | private processVersion: string; 43 | private osRelease: string; 44 | private osPlatform; 45 | 46 | constructor(token: string, environment = Environments.Live, options: APIOptions) { 47 | this._token = token; 48 | this._environment = environment; 49 | 50 | this._baseUrl = 'https://api.gocardless.com'; 51 | if (this._environment === Environments.Sandbox) { 52 | this._baseUrl = 'https://api-sandbox.gocardless.com'; 53 | } 54 | 55 | this._agent = undefined; 56 | if (options.proxy) { 57 | this._agent = options.proxy; 58 | } 59 | 60 | this.raiseOnIdempotencyConflict = options.raiseOnIdempotencyConflict || false; 61 | 62 | this.processVersion = process.version; 63 | this.osPlatform = os.platform(); 64 | this.osRelease = os.release(); 65 | } 66 | 67 | async request({ 68 | path, 69 | method, 70 | urlParameters = [], 71 | requestParameters = {}, 72 | payloadKey = '', 73 | idempotencyKey = '', 74 | customHeaders = {}, 75 | fetch, 76 | }: APIRequestParameters) { 77 | urlParameters.forEach((urlParameter) => { 78 | path = path.replace(`:${urlParameter.key}`, urlParameter.value); 79 | }); 80 | 81 | // `got` adds a slash to the end of `prefix_url` so we don't want one at the 82 | // start of the path 83 | if (path[0] === '/') { 84 | path = path.slice(1); 85 | } 86 | 87 | const requestOptions = this.createRequestOptions( 88 | method, 89 | requestParameters, 90 | payloadKey, 91 | idempotencyKey, 92 | customHeaders, 93 | ); 94 | 95 | try { 96 | const response = await got(path, requestOptions); 97 | 98 | return { 99 | body: response.body, 100 | __response__: { 101 | headers: response.headers, 102 | statusCode: response.statusCode, 103 | statusMessage: response.statusMessage, 104 | url: response.url, 105 | }, 106 | }; 107 | } catch (e) { 108 | if (e instanceof got.ParseError) { 109 | throw new GoCardlessErrors.MalformedResponseError('Malformed JSON received from GoCardless API', e.response); 110 | } 111 | 112 | if (e instanceof got.HTTPError) { 113 | const err = GoCardlessErrors.ApiError.buildFromResponse(e.response); 114 | 115 | if (err instanceof GoCardlessErrors.IdempotentCreationConflictError && !this.raiseOnIdempotencyConflict) { 116 | return fetch(err.conflictingResourceId); 117 | } 118 | 119 | throw err; 120 | } 121 | 122 | throw e; 123 | } 124 | } 125 | 126 | private getHeaders(token, customHeaders = {}) { 127 | const mandatoryHeaders = { 128 | Accept: 'application/json', 129 | Authorization: `Bearer ${token}`, 130 | 'GoCardless-Version': `${API_VERSION}`, 131 | 'GoCardless-Client-Version': `${CLIENT_VERSION}`, 132 | 'GoCardless-Client-Library': 'gocardless-nodejs', 133 | 'User-Agent': `gocardless-nodejs/${CLIENT_VERSION} node/${this.processVersion} ${this.osPlatform}/${this.osRelease}`, 134 | }; 135 | 136 | return { ...customHeaders, ...mandatoryHeaders }; 137 | } 138 | 139 | private createRequestOptions( 140 | method = 'get', 141 | requestParameters = {}, 142 | payloadKey = '', 143 | idempotencyKey = '', 144 | customHeaders = {}, 145 | ) { 146 | const headers = this.getHeaders(this._token, customHeaders); 147 | const searchParams = 148 | method === 'get' ? new url.URLSearchParams(this.formatQueryParameters(requestParameters)) : undefined; 149 | 150 | // We want to always send POST requests with an idempotency key. If the user does not 151 | // specify one, we'll generate one for them. 152 | if (method.toLowerCase() === 'post') { 153 | headers['Idempotency-Key'] = idempotencyKey ? idempotencyKey : this.generateIdempotencyKey(); 154 | } 155 | 156 | const json = this.getRequestBody(method, requestParameters, payloadKey); 157 | return { 158 | agent: this._agent, 159 | prefixUrl: this._baseUrl, 160 | // tslint:disable-next-line:no-any 161 | method: method as any, 162 | responseType: 'json' as const, 163 | headers, 164 | searchParams, 165 | json, 166 | }; 167 | } 168 | 169 | private getRequestBody(method: string, requestParameters, payloadKey) { 170 | if ((method === 'post' || method === 'put') && requestParameters) { 171 | if (payloadKey) { 172 | return { 173 | [payloadKey]: requestParameters, 174 | }; 175 | } else { 176 | return { 177 | data: requestParameters, 178 | }; 179 | } 180 | } 181 | 182 | return undefined; 183 | } 184 | 185 | private generateIdempotencyKey() { 186 | return uuidv4(); 187 | } 188 | 189 | private formatQueryParameters(parameters) { 190 | return qs.stringify(parameters, { 191 | encode: false, 192 | indices: false, 193 | arrayFormat: 'comma', 194 | }); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | enum Environments { 4 | Live = 'LIVE', 5 | Sandbox = 'SANDBOX', 6 | } 7 | 8 | const CLIENT_VERSION = '5.3.0'; 9 | const API_VERSION = '2015-07-06'; 10 | 11 | export { Environments, CLIENT_VERSION, API_VERSION }; 12 | -------------------------------------------------------------------------------- /src/errors.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | class GoCardlessException extends Error {} 4 | 5 | class MalformedResponseError extends GoCardlessException { 6 | public response: object; 7 | public requestId: string; 8 | 9 | public constructor(message, response) { 10 | super(message); 11 | 12 | this.response = response; 13 | this.requestId = response.headers['x-request-id']; 14 | } 15 | } 16 | 17 | interface ErrorObject { 18 | message?: string; 19 | reason?: string; 20 | field?: string; 21 | links?: object; 22 | metadata?: object; 23 | request_pointer?: string; 24 | } 25 | 26 | class ApiError extends GoCardlessException { 27 | public message: string; 28 | public errors: Array; 29 | public documentationUrl: string; 30 | public errorType: string; 31 | public requestId: string; 32 | public code: string; 33 | public response: object; 34 | 35 | public constructor(response) { 36 | const { 37 | body: { error }, 38 | } = response; 39 | const { message, errors, documentation_url: documentationUrl, type, request_id: requestId, code } = error; 40 | 41 | super(message); 42 | 43 | this.response = response; 44 | this.message = message; 45 | this.errors = errors; 46 | this.documentationUrl = documentationUrl; 47 | this.errorType = type; 48 | this.requestId = requestId; 49 | this.code = code; 50 | } 51 | 52 | static buildFromResponse(response) { 53 | try { 54 | const { 55 | statusCode, 56 | body: { 57 | error: { type, errors }, 58 | }, 59 | } = response; 60 | 61 | // These statuses are for unique errors 62 | switch (statusCode) { 63 | case 401: 64 | return new AuthenticationError(response); 65 | case 403: 66 | return new PermissionsError(response); 67 | case 429: 68 | return new RateLimitError(response); 69 | default: 70 | //noop 71 | } 72 | 73 | // Whereas these errors have different meanings over the same codes 74 | switch (type) { 75 | case 'validation_failed': 76 | return new ValidationFailedError(response); 77 | case 'invalid_api_usage': 78 | return new InvalidApiUsageError(response); 79 | case 'invalid_state': 80 | for (const e of errors) { 81 | if (e.reason === 'idempotent_creation_conflict') { 82 | if (e.links && e.links.conflicting_resource_id) { 83 | return new IdempotentCreationConflictError(response, e.links.conflicting_resource_id); 84 | } 85 | 86 | return new MalformedResponseError( 87 | 'Idempotent Creation Conflict Error missing conflicting_resource_id', 88 | response, 89 | ); 90 | } 91 | } 92 | 93 | return new InvalidStateError(response); 94 | case 'gocardless': 95 | return new GoCardlessInternalError(response); 96 | default: 97 | return new ApiError(response); 98 | } 99 | } catch (err) { 100 | const failureResponse = { 101 | statusCode: 500, 102 | body: { 103 | error: { 104 | message: response.body, 105 | errors: [ 106 | { 107 | reason: 'internal_server_error', 108 | message: response.body, 109 | }, 110 | ], 111 | documentation_url: 'https://developer.gocardless.com/api-reference#internal_server_error', 112 | type: 'gocardless', 113 | request_id: response?.headers?.['x-request-id'] ?? null, 114 | code: 500, 115 | }, 116 | }, 117 | }; 118 | 119 | return new GoCardlessInternalError(failureResponse); 120 | } 121 | } 122 | 123 | public toString() { 124 | const messages = (this.errors || []).filter((e) => e.message !== this.message).map((e) => e.message); 125 | 126 | if (messages.length > 0) { 127 | return `${this.message} (${messages.join(', ')})`; 128 | } 129 | 130 | return this.message; 131 | } 132 | } 133 | 134 | class IdempotentCreationConflictError extends ApiError { 135 | public conflictingResourceId: string; 136 | 137 | public constructor(response, conflictingResourceId) { 138 | super(response); 139 | this.conflictingResourceId = conflictingResourceId; 140 | } 141 | } 142 | 143 | class ValidationFailedError extends ApiError { 144 | public toString() { 145 | const messages = (this.errors || []).filter((e) => e.field).map((e) => `${e.field} ${e.message}`); 146 | 147 | if (messages.length > 0) { 148 | return `${this.message} (${messages.join(', ')})`; 149 | } 150 | 151 | return this.message; 152 | } 153 | } 154 | 155 | class InvalidApiUsageError extends ApiError {} 156 | class InvalidStateError extends ApiError {} 157 | class GoCardlessInternalError extends ApiError {} 158 | class AuthenticationError extends ApiError {} 159 | class PermissionsError extends ApiError {} 160 | class RateLimitError extends ApiError {} 161 | 162 | export { 163 | GoCardlessException, 164 | MalformedResponseError, 165 | ApiError, 166 | IdempotentCreationConflictError, 167 | ValidationFailedError, 168 | InvalidApiUsageError, 169 | InvalidStateError, 170 | GoCardlessInternalError, 171 | AuthenticationError, 172 | PermissionsError, 173 | RateLimitError, 174 | }; 175 | -------------------------------------------------------------------------------- /src/fixtures/gocardless_internal_error.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "message": "Internal server error", 4 | "errors": [ 5 | { 6 | "reason": "internal_server_error", 7 | "message": "Internal server error" 8 | } 9 | ], 10 | "documentation_url": "https://developer.gocardless.com/api-reference#internal_server_error", 11 | "type": "gocardless", 12 | "request_id": "HARDCODED_REQUEST_ID", 13 | "code": 500 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/fixtures/idempotency_conflict.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "message": "A resource has already been created with this idempotency key", 4 | "errors": [ 5 | { 6 | "reason": "idempotent_creation_conflict", 7 | "message": "A resource has already been created with this idempotency key", 8 | "links": { 9 | "conflicting_resource_id": "PM1234" 10 | } 11 | } 12 | ], 13 | "documentation_url": "https://developer.gocardless.com/api-reference#idempotent_creation_conflict", 14 | "type": "invalid_state", 15 | "request_id": "HARDCODED_REQUEST_ID", 16 | "code": 409 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/fixtures/insufficent_permissions.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "documentation_url": "https://developer.gocardless.com/api-reference#insufficient_permissions", 4 | "type": "invalid_api_usage", 5 | "request_id": "HARDCODED_REQUEST_ID", 6 | "code": 403, 7 | "message": "Insufficient permissions", 8 | "errors": [ 9 | { 10 | "reason": "insufficient_permissions", 11 | "message": "Insufficient permissions" 12 | } 13 | ] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/fixtures/invalid_api_usage.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "message": "One of your parameters was incorrectly typed", 4 | "errors": [ 5 | { 6 | "message": "\"currency\" wasn't supplied.", 7 | "request_pointer": "/payments" 8 | } 9 | ], 10 | "documentation_url": "https://developer.gocardless.com/api-reference#invalid_type", 11 | "type": "invalid_api_usage", 12 | "request_id": "HARDCODED_REQUEST_ID", 13 | "code": 422 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/fixtures/invalid_state.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "message": "Payment cannot be cancelled", 4 | "documentation_url": "https://developer.gocardless.com/api-reference#cancellation_failed", 5 | "type": "invalid_state", 6 | "errors": [ 7 | { 8 | "message": "Payment cannot be cancelled", 9 | "reason": "cancellation_failed" 10 | } 11 | ], 12 | "request_id": "HARDCODED_REQUEST_ID", 13 | "code": 422 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/fixtures/rate_limit_exceeded.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "documentation_url": "https://developer.gocardless.com/api-reference#rate_limit_exceeded", 4 | "message": "Rate limit exceeded", 5 | "type": "invalid_api_usage", 6 | "code": 429, 7 | "errors": [ 8 | { 9 | "reason": "rate_limit_exceeded", 10 | "message": "Rate limit exceeded" 11 | } 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/fixtures/unauthorized.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "documentation_url": "https://developer.gocardless.com/api-reference#unauthorized", 4 | "message": "Unauthorized", 5 | "type": "invalid_api_usage", 6 | "errors": [ 7 | { 8 | "reason": "unauthorized", 9 | "message": "Unauthorized" 10 | } 11 | ], 12 | "code": 401, 13 | "request_id": "HARDCODED_REQUEST_ID" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/fixtures/validation_failed.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "message": "Validation failed", 4 | "errors": [ 5 | { 6 | "field": "amount", 7 | "message": "is greater than the permitted scheme maximum", 8 | "metadata": { 9 | "maximum_amount": 100000000 10 | }, 11 | "request_pointer": "/payments/amount" 12 | } 13 | ], 14 | "documentation_url": "https://developer.gocardless.com/api-reference#validation_failed", 15 | "type": "validation_failed", 16 | "request_id": "HARDCODED_REQUEST_ID", 17 | "code": 422 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/fixtures/webhook_body.json: -------------------------------------------------------------------------------- 1 | { 2 | "events": [ 3 | { 4 | "id": "EV00BD05S5VM2T", 5 | "created_at": "2018-07-05T09:13:51.404Z", 6 | "resource_type": "subscriptions", 7 | "action": "created", 8 | "links": { "subscription": "SB0003JJQ2MR06" }, 9 | "details": { 10 | "origin": "api", 11 | "cause": "subscription_created", 12 | "description": "Subscription created via the API." 13 | }, 14 | "metadata": {} 15 | }, 16 | { 17 | "id": "EV00BD05TB8K63", 18 | "created_at": "2018-07-05T09:13:56.893Z", 19 | "resource_type": "mandates", 20 | "action": "created", 21 | "links": { "mandate": "MD000AMA19XGEC" }, 22 | "details": { "origin": "api", "cause": "mandate_created", "description": "Mandate created via the API." }, 23 | "metadata": {} 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { GoCardlessClient } from './client'; 4 | 5 | const initialiser = function (token, envrionment, options = {}) { 6 | return new GoCardlessClient(token, envrionment, options); 7 | }; 8 | 9 | module.exports = initialiser; 10 | -------------------------------------------------------------------------------- /src/services/balanceService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface BalanceResponse extends Types.Balance, Types.APIResponse {} 7 | 8 | interface BalanceListResponse extends Types.APIResponse { 9 | balances: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface BalanceListRequest { 14 | // Cursor pointing to the start of the desired set. 15 | 16 | after?: string; 17 | 18 | // Cursor pointing to the end of the desired set. 19 | 20 | before?: string; 21 | 22 | // ID of a [creditor](#core-endpoints-creditors). 23 | 24 | creditor: string; 25 | 26 | // Number of records to return. 27 | 28 | limit?: string; 29 | } 30 | 31 | export class BalanceService { 32 | private api: Api; 33 | 34 | constructor(api) { 35 | this.api = api; 36 | } 37 | 38 | public async list( 39 | requestParameters: BalanceListRequest, 40 | customHeaders: Types.JsonMap = {}, 41 | ): Promise { 42 | const urlParameters = []; 43 | const requestParams = { 44 | path: '/balances', 45 | method: 'get', 46 | urlParameters, 47 | requestParameters, 48 | payloadKey: null, 49 | fetch: null, 50 | customHeaders, 51 | }; 52 | 53 | const response = await this.api.request(requestParams); 54 | const formattedResponse: BalanceListResponse = { 55 | ...response.body, 56 | __response__: response.__response__, 57 | }; 58 | 59 | return formattedResponse; 60 | } 61 | 62 | public async *all( 63 | requestParameters: BalanceListRequest, 64 | customHeaders: Types.JsonMap = {}, 65 | ): AsyncGenerator { 66 | let cursor = undefined; 67 | do { 68 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 69 | 70 | for (const balance of list.balances) { 71 | yield balance; 72 | } 73 | 74 | cursor = list.meta.cursors.after; 75 | } while (cursor); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/services/bankAccountDetailService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface BankAccountDetailResponse extends Types.BankAccountDetail, Types.APIResponse {} 7 | 8 | interface BankAccountDetailListResponse extends Types.APIResponse { 9 | bank_account_details: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | export class BankAccountDetailService { 14 | private api: Api; 15 | 16 | constructor(api) { 17 | this.api = api; 18 | } 19 | 20 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 21 | const urlParameters = [{ key: 'identity', value: identity }]; 22 | const requestParams = { 23 | path: '/bank_account_details/:identity', 24 | method: 'get', 25 | urlParameters, 26 | 27 | payloadKey: null, 28 | fetch: null, 29 | customHeaders, 30 | }; 31 | 32 | const response = await this.api.request(requestParams); 33 | const formattedResponse: BankAccountDetailResponse = { 34 | ...response.body['bank_account_details'], 35 | __response__: response.__response__, 36 | }; 37 | 38 | return formattedResponse; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/services/bankAuthorisationService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface BankAuthorisationResponse extends Types.BankAuthorisation, Types.APIResponse {} 7 | 8 | interface BankAuthorisationListResponse extends Types.APIResponse { 9 | bank_authorisations: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface BankAuthorisationCreateRequest { 14 | // Resources linked to this BankAuthorisation. 15 | links: Types.BankAuthorisationCreateRequestLinks; 16 | 17 | // URL that the payer can be redirected to after authorising the payment. 18 | // 19 | // On completion of bank authorisation, the query parameter of either 20 | // `outcome=success` or `outcome=failure` will be 21 | // appended to the `redirect_uri` to indicate the result of the bank 22 | // authorisation. If the bank authorisation is 23 | // expired, the query parameter `outcome=timeout` will be appended to the 24 | // `redirect_uri`, in which case you should 25 | // prompt the user to try the bank authorisation step again. 26 | // 27 | // Please note: bank authorisations can still fail despite an `outcome=success` 28 | // on the `redirect_uri`. It is therefore recommended to wait for the relevant 29 | // bank authorisation event, such as 30 | // [`BANK_AUTHORISATION_AUTHORISED`](#billing-request-bankauthorisationauthorised), 31 | // [`BANK_AUTHORISATION_DENIED`](#billing-request-bankauthorisationdenied), or 32 | // [`BANK_AUTHORISATION_FAILED`](#billing-request-bankauthorisationfailed) in 33 | // order to show the correct outcome to the user. 34 | // 35 | // The BillingRequestFlow ID will also be appended to the `redirect_uri` as 36 | // query parameter `id=BRF123`. 37 | // 38 | // Defaults to `https://pay.gocardless.com/billing/static/thankyou`. 39 | 40 | redirect_uri?: string; 41 | } 42 | 43 | export class BankAuthorisationService { 44 | private api: Api; 45 | 46 | constructor(api) { 47 | this.api = api; 48 | } 49 | 50 | public async create( 51 | requestParameters: BankAuthorisationCreateRequest, 52 | idempotencyKey = '', 53 | customHeaders: Types.JsonMap = {}, 54 | ): Promise { 55 | const urlParameters = []; 56 | const requestParams = { 57 | path: '/bank_authorisations', 58 | method: 'post', 59 | urlParameters, 60 | requestParameters, 61 | payloadKey: 'bank_authorisations', 62 | idempotencyKey, 63 | customHeaders, 64 | fetch: async (identity) => await this.find(identity), 65 | }; 66 | 67 | const response = await this.api.request(requestParams); 68 | const formattedResponse: BankAuthorisationResponse = { 69 | ...(response.body?.['bank_authorisations'] ?? response), 70 | __response__: response.__response__, 71 | }; 72 | 73 | return formattedResponse; 74 | } 75 | 76 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 77 | const urlParameters = [{ key: 'identity', value: identity }]; 78 | const requestParams = { 79 | path: '/bank_authorisations/:identity', 80 | method: 'get', 81 | urlParameters, 82 | 83 | payloadKey: null, 84 | fetch: null, 85 | customHeaders, 86 | }; 87 | 88 | const response = await this.api.request(requestParams); 89 | const formattedResponse: BankAuthorisationResponse = { 90 | ...response.body['bank_authorisations'], 91 | __response__: response.__response__, 92 | }; 93 | 94 | return formattedResponse; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/services/bankDetailsLookupService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface BankDetailsLookupResponse extends Types.BankDetailsLookup, Types.APIResponse {} 7 | 8 | interface BankDetailsLookupListResponse extends Types.APIResponse { 9 | bank_details_lookups: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface BankDetailsLookupCreateRequest { 14 | // The account holder name associated with the account number (if available). If 15 | // provided and the country code is GB, a payer name verification will be 16 | // performed. 17 | 18 | account_holder_name?: string; 19 | 20 | // Bank account number - see [local details](#appendix-local-bank-details) for 21 | // more information. Alternatively you can provide an `iban`. 22 | 23 | account_number?: string; 24 | 25 | // Bank code - see [local details](#appendix-local-bank-details) for more 26 | // information. Alternatively you can provide an `iban`. 27 | 28 | bank_code?: string; 29 | 30 | // Branch code - see [local details](#appendix-local-bank-details) for more 31 | // information. Alternatively you can provide an `iban`. 32 | 33 | branch_code?: string; 34 | 35 | // [ISO 36 | // 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) 37 | // alpha-2 code. Must be provided if specifying local details. 38 | 39 | country_code?: string; 40 | 41 | // International Bank Account Number. Alternatively you can provide [local 42 | // details](#appendix-local-bank-details). 43 | 44 | iban?: string; 45 | } 46 | 47 | export class BankDetailsLookupService { 48 | private api: Api; 49 | 50 | constructor(api) { 51 | this.api = api; 52 | } 53 | 54 | public async create( 55 | requestParameters: BankDetailsLookupCreateRequest, 56 | idempotencyKey = '', 57 | customHeaders: Types.JsonMap = {}, 58 | ): Promise { 59 | const urlParameters = []; 60 | const requestParams = { 61 | path: '/bank_details_lookups', 62 | method: 'post', 63 | urlParameters, 64 | requestParameters, 65 | payloadKey: 'bank_details_lookups', 66 | idempotencyKey, 67 | customHeaders, 68 | fetch: undefined, 69 | }; 70 | 71 | const response = await this.api.request(requestParams); 72 | const formattedResponse: BankDetailsLookupResponse = { 73 | ...(response.body?.['bank_details_lookups'] ?? response), 74 | __response__: response.__response__, 75 | }; 76 | 77 | return formattedResponse; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/services/billingRequestFlowService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface BillingRequestFlowResponse extends Types.BillingRequestFlow, Types.APIResponse {} 7 | 8 | interface BillingRequestFlowListResponse extends Types.APIResponse { 9 | billing_request_flows: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface BillingRequestFlowCreateRequest { 14 | // (Experimental feature) Fulfil the Billing Request on completion of the flow 15 | // (true by default). Disabling the auto_fulfil is not allowed currently. 16 | 17 | auto_fulfil?: boolean; 18 | 19 | // Identifies whether a Billing Request belongs to a specific customer 20 | 21 | customer_details_captured?: boolean; 22 | 23 | // URL that the payer can be taken to if there isn't a way to progress ahead in 24 | // flow. 25 | 26 | exit_uri?: string; 27 | 28 | // Sets the default language of the Billing Request Flow and the customer. [ISO 29 | // 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code. 30 | 31 | language?: string; 32 | 33 | // Resources linked to this BillingRequestFlow. 34 | links: Types.BillingRequestFlowCreateRequestLinks; 35 | 36 | // If true, the payer will not be able to change their bank account within the 37 | // flow. If the bank_account details are collected as part of bank_authorisation 38 | // then GC will set this value to true mid flow. 39 | // 40 | // You can only lock bank account if these have already been completed as a part 41 | // of the billing request. 42 | // 43 | 44 | lock_bank_account?: boolean; 45 | 46 | // If true, the payer will not be able to change their currency/scheme manually 47 | // within the flow. Note that this only applies to the mandate only flows - 48 | // currency/scheme can never be changed when there is a specified subscription 49 | // or payment. 50 | 51 | lock_currency?: boolean; 52 | 53 | // If true, the payer will not be able to edit their customer details within the 54 | // flow. If the customer details are collected as part of bank_authorisation 55 | // then GC will set this value to true mid flow. 56 | // 57 | // You can only lock customer details if these have already been completed as a 58 | // part of the billing request. 59 | // 60 | 61 | lock_customer_details?: boolean; 62 | 63 | // Bank account information used to prefill the payment page so your customer 64 | // doesn't have to re-type details you already hold about them. It will be 65 | // stored unvalidated and the customer will be able to review and amend it 66 | // before completing the form. 67 | prefilled_bank_account?: Types.BillingRequestFlowPrefilledBankAccount; 68 | 69 | // Customer information used to prefill the payment page so your customer 70 | // doesn't have to re-type details you already hold about them. It will be 71 | // stored unvalidated and the customer will be able to review and amend it 72 | // before completing the form. 73 | prefilled_customer?: Types.BillingRequestFlowPrefilledCustomer; 74 | 75 | // URL that the payer can be redirected to after completing the request flow. 76 | 77 | redirect_uri?: string; 78 | 79 | // If true, the payer will be able to see redirect action buttons on Thank You 80 | // page. These action buttons will provide a way to connect back to the billing 81 | // request flow app if opened within a mobile app. For successful flow, the 82 | // button will take the payer back the billing request flow where they will see 83 | // the success screen. For failure, button will take the payer to url being 84 | // provided against exit_uri field. 85 | 86 | show_redirect_buttons?: boolean; 87 | 88 | // If true, the payer will be able to see a redirect action button on the 89 | // Success page. This action button will provide a way to redirect the payer to 90 | // the given redirect_uri. This functionality is helpful when merchants do not 91 | // want payers to be automatically redirected or on Android devices, where 92 | // automatic redirections are not possible. 93 | 94 | show_success_redirect_button?: boolean; 95 | 96 | // If true, the payer will not be redirected to the success screen after 97 | // completing the flow. A redirect_uri needs to be provided for this parameter 98 | // to be taken into account. 99 | 100 | skip_success_screen?: boolean; 101 | } 102 | 103 | export class BillingRequestFlowService { 104 | private api: Api; 105 | 106 | constructor(api) { 107 | this.api = api; 108 | } 109 | 110 | public async create( 111 | requestParameters: BillingRequestFlowCreateRequest, 112 | idempotencyKey = '', 113 | customHeaders: Types.JsonMap = {}, 114 | ): Promise { 115 | const urlParameters = []; 116 | const requestParams = { 117 | path: '/billing_request_flows', 118 | method: 'post', 119 | urlParameters, 120 | requestParameters, 121 | payloadKey: 'billing_request_flows', 122 | idempotencyKey, 123 | customHeaders, 124 | fetch: undefined, 125 | }; 126 | 127 | const response = await this.api.request(requestParams); 128 | const formattedResponse: BillingRequestFlowResponse = { 129 | ...(response.body?.['billing_request_flows'] ?? response), 130 | __response__: response.__response__, 131 | }; 132 | 133 | return formattedResponse; 134 | } 135 | 136 | public async initialise(identity: string, customHeaders: Types.JsonMap = {}): Promise { 137 | const urlParameters = [{ key: 'identity', value: identity }]; 138 | const requestParams = { 139 | path: '/billing_request_flows/:identity/actions/initialise', 140 | method: 'post', 141 | urlParameters, 142 | 143 | payloadKey: null, 144 | fetch: null, 145 | customHeaders, 146 | }; 147 | 148 | const response = await this.api.request(requestParams); 149 | const formattedResponse: BillingRequestFlowResponse = { 150 | ...response.body['billing_request_flows'], 151 | __response__: response.__response__, 152 | }; 153 | 154 | return formattedResponse; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/services/billingRequestWithActionService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface BillingRequestWithActionResponse extends Types.BillingRequestWithAction, Types.APIResponse {} 7 | 8 | interface BillingRequestWithActionListResponse extends Types.APIResponse { 9 | billing_request_with_actions: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface BillingRequestWithActionCreateWithActionsRequest { 14 | // Action payloads 15 | actions?: Types.BillingRequestWithActionActions; 16 | 17 | // (Optional) If true, this billing request can fallback from instant payment to 18 | // direct debit. 19 | // Should not be set if GoCardless payment intelligence feature is used. 20 | // 21 | // See [Billing Requests: Retain customers with 22 | // Fallbacks](https://developer.gocardless.com/billing-requests/retain-customers-with-fallbacks/) 23 | // for more information. 24 | 25 | fallback_enabled?: boolean; 26 | 27 | // Resources linked to this BillingRequestWithAction. 28 | links?: Types.BillingRequestWithActionCreateWithActionsRequestLinks; 29 | 30 | // 31 | mandate_request?: Types.BillingRequestWithActionMandateRequest; 32 | 33 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 34 | // to 50 characters and values up to 500 characters. 35 | 36 | metadata?: Types.JsonMap; 37 | 38 | // 39 | payment_request?: Types.BillingRequestWithActionPaymentRequest; 40 | 41 | // Specifies the high-level purpose of a mandate and/or payment using a set of 42 | // pre-defined categories. Required for the PayTo scheme, optional for all 43 | // others. Currently `mortgage`, `utility`, `loan`, `dependant_support`, 44 | // `gambling`, `retail`, `salary`, `personal`, `government`, `pension`, `tax` 45 | // and `other` are supported. 46 | 47 | purpose_code?: Types.BillingRequestWithActionPurposeCode; 48 | } 49 | 50 | export class BillingRequestWithActionService { 51 | private api: Api; 52 | 53 | constructor(api) { 54 | this.api = api; 55 | } 56 | 57 | public async createWithActions( 58 | requestParameters: BillingRequestWithActionCreateWithActionsRequest, 59 | idempotencyKey = '', 60 | customHeaders: Types.JsonMap = {}, 61 | ): Promise { 62 | const urlParameters = []; 63 | const requestParams = { 64 | path: '/billing_requests/create_with_actions', 65 | method: 'post', 66 | urlParameters, 67 | requestParameters, 68 | payloadKey: 'billing_request_with_actions', 69 | idempotencyKey, 70 | customHeaders, 71 | fetch: undefined, 72 | }; 73 | 74 | const response = await this.api.request(requestParams); 75 | const formattedResponse: BillingRequestWithActionResponse = { 76 | ...(response.body?.['billing_request_with_actions'] ?? response), 77 | __response__: response.__response__, 78 | }; 79 | 80 | return formattedResponse; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/services/blockService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface BlockResponse extends Types.Block, Types.APIResponse {} 7 | 8 | interface BlockListResponse extends Types.APIResponse { 9 | blocks: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface BlockCreateRequest { 14 | // Shows if the block is active or disabled. Only active blocks will be used 15 | // when deciding 16 | // if a mandate should be blocked. 17 | 18 | active?: boolean; 19 | 20 | // Type of entity we will seek to match against when blocking the mandate. This 21 | // can currently be one of 'email', 'email_domain', 'bank_account', or 22 | // 'bank_name'. 23 | 24 | block_type?: Types.BlockBlockType; 25 | 26 | // This field is required if the reason_type is other. It should be a 27 | // description of 28 | // the reason for why you wish to block this payer and why it does not align 29 | // with the 30 | // given reason_types. This is intended to help us improve our knowledge of 31 | // types of 32 | // fraud. 33 | 34 | reason_description?: string; 35 | 36 | // The reason you wish to block this payer, can currently be one of 37 | // 'identity_fraud', 38 | // 'no_intent_to_pay', 'unfair_chargeback'. If the reason isn't captured by one 39 | // of the 40 | // above then 'other' can be selected but you must provide a reason description. 41 | 42 | reason_type?: Types.BlockReasonType; 43 | 44 | // This field is a reference to the value you wish to block. This may be the raw 45 | // value 46 | // (in the case of emails or email domains) or the ID of the resource (in the 47 | // case of 48 | // bank accounts and bank names). This means in order to block a specific bank 49 | // account 50 | // (even if you wish to block generically by name) it must already have been 51 | // created as 52 | // a resource. 53 | 54 | resource_reference?: string; 55 | } 56 | 57 | interface BlockListRequest { 58 | // Cursor pointing to the start of the desired set. 59 | 60 | after?: string; 61 | 62 | // Cursor pointing to the end of the desired set. 63 | 64 | before?: string; 65 | 66 | // ID of a [Block](#core-endpoints-blocks). 67 | 68 | block?: string; 69 | 70 | // Type of entity we will seek to match against when blocking the mandate. This 71 | // can currently be one of 'email', 'email_domain', 'bank_account', or 72 | // 'bank_name'. 73 | 74 | block_type?: Types.BlockBlockType; 75 | 76 | // The creation date of this Block. 77 | created_at?: Types.CreatedAtFilter; 78 | 79 | // Number of records to return. 80 | 81 | limit?: string; 82 | 83 | // The reason you wish to block this payer, can currently be one of 84 | // 'identity_fraud', 85 | // 'no_intent_to_pay', 'unfair_chargeback'. If the reason isn't captured by one 86 | // of the 87 | // above then 'other' can be selected but you must provide a reason description. 88 | 89 | reason_type?: Types.BlockReasonType; 90 | 91 | // Fixed [timestamp](#api-usage-dates-and-times), recording when this 92 | // resource was updated. 93 | 94 | updated_at?: string; 95 | } 96 | 97 | interface BlockBlockByRefRequest { 98 | // Shows if the block is active or disabled. Only active blocks will be used 99 | // when deciding 100 | // if a mandate should be blocked. 101 | 102 | active?: boolean; 103 | 104 | // This field is required if the reason_type is other. It should be a 105 | // description of 106 | // the reason for why you wish to block this payer and why it does not align 107 | // with the 108 | // given reason_types. This is intended to help us improve our knowledge of 109 | // types of 110 | // fraud. 111 | 112 | reason_description?: string; 113 | 114 | // The reason you wish to block this payer, can currently be one of 115 | // 'identity_fraud', 116 | // 'no_intent_to_pay', 'unfair_chargeback'. If the reason isn't captured by one 117 | // of the 118 | // above then 'other' can be selected but you must provide a reason description. 119 | 120 | reason_type?: Types.BlockReasonType; 121 | 122 | // Type of entity we will seek to get the associated emails and bank accounts to 123 | // create blocks from. This can currently be one of 'customer' or 'mandate'. 124 | 125 | reference_type?: Types.BlockReferenceType; 126 | 127 | // This field is a reference to the entity you wish to block based on its emails 128 | // and bank accounts. This may be the ID of a customer or a mandate. This means 129 | // in 130 | // order to block by reference the entity must have already been created as a 131 | // resource. 132 | 133 | reference_value?: string; 134 | } 135 | 136 | export class BlockService { 137 | private api: Api; 138 | 139 | constructor(api) { 140 | this.api = api; 141 | } 142 | 143 | public async create( 144 | requestParameters: BlockCreateRequest, 145 | idempotencyKey = '', 146 | customHeaders: Types.JsonMap = {}, 147 | ): Promise { 148 | const urlParameters = []; 149 | const requestParams = { 150 | path: '/blocks', 151 | method: 'post', 152 | urlParameters, 153 | requestParameters, 154 | payloadKey: 'blocks', 155 | idempotencyKey, 156 | customHeaders, 157 | fetch: async (identity) => await this.find(identity), 158 | }; 159 | 160 | const response = await this.api.request(requestParams); 161 | const formattedResponse: BlockResponse = { 162 | ...(response.body?.['blocks'] ?? response), 163 | __response__: response.__response__, 164 | }; 165 | 166 | return formattedResponse; 167 | } 168 | 169 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 170 | const urlParameters = [{ key: 'identity', value: identity }]; 171 | const requestParams = { 172 | path: '/blocks/:identity', 173 | method: 'get', 174 | urlParameters, 175 | 176 | payloadKey: null, 177 | fetch: null, 178 | customHeaders, 179 | }; 180 | 181 | const response = await this.api.request(requestParams); 182 | const formattedResponse: BlockResponse = { 183 | ...response.body['blocks'], 184 | __response__: response.__response__, 185 | }; 186 | 187 | return formattedResponse; 188 | } 189 | 190 | public async list( 191 | requestParameters: BlockListRequest, 192 | customHeaders: Types.JsonMap = {}, 193 | ): Promise { 194 | const urlParameters = []; 195 | const requestParams = { 196 | path: '/blocks', 197 | method: 'get', 198 | urlParameters, 199 | requestParameters, 200 | payloadKey: null, 201 | fetch: null, 202 | customHeaders, 203 | }; 204 | 205 | const response = await this.api.request(requestParams); 206 | const formattedResponse: BlockListResponse = { 207 | ...response.body, 208 | __response__: response.__response__, 209 | }; 210 | 211 | return formattedResponse; 212 | } 213 | 214 | public async *all( 215 | requestParameters: BlockListRequest, 216 | customHeaders: Types.JsonMap = {}, 217 | ): AsyncGenerator { 218 | let cursor = undefined; 219 | do { 220 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 221 | 222 | for (const block of list.blocks) { 223 | yield block; 224 | } 225 | 226 | cursor = list.meta.cursors.after; 227 | } while (cursor); 228 | } 229 | 230 | public async disable(identity: string, customHeaders: Types.JsonMap = {}): Promise { 231 | const urlParameters = [{ key: 'identity', value: identity }]; 232 | const requestParams = { 233 | path: '/blocks/:identity/actions/disable', 234 | method: 'post', 235 | urlParameters, 236 | 237 | payloadKey: null, 238 | fetch: null, 239 | customHeaders, 240 | }; 241 | 242 | const response = await this.api.request(requestParams); 243 | const formattedResponse: BlockResponse = { 244 | ...response.body['blocks'], 245 | __response__: response.__response__, 246 | }; 247 | 248 | return formattedResponse; 249 | } 250 | 251 | public async enable(identity: string, customHeaders: Types.JsonMap = {}): Promise { 252 | const urlParameters = [{ key: 'identity', value: identity }]; 253 | const requestParams = { 254 | path: '/blocks/:identity/actions/enable', 255 | method: 'post', 256 | urlParameters, 257 | 258 | payloadKey: null, 259 | fetch: null, 260 | customHeaders, 261 | }; 262 | 263 | const response = await this.api.request(requestParams); 264 | const formattedResponse: BlockResponse = { 265 | ...response.body['blocks'], 266 | __response__: response.__response__, 267 | }; 268 | 269 | return formattedResponse; 270 | } 271 | 272 | public async block_by_ref( 273 | requestParameters: BlockBlockByRefRequest, 274 | customHeaders: Types.JsonMap = {}, 275 | ): Promise { 276 | const urlParameters = []; 277 | const requestParams = { 278 | path: '/blocks/block_by_ref', 279 | method: 'post', 280 | urlParameters, 281 | requestParameters, 282 | payloadKey: null, 283 | fetch: null, 284 | customHeaders, 285 | }; 286 | 287 | const response = await this.api.request(requestParams); 288 | const formattedResponse: BlockListResponse = { 289 | ...response.body, 290 | __response__: response.__response__, 291 | }; 292 | 293 | return formattedResponse; 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /src/services/creditorBankAccountService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface CreditorBankAccountResponse extends Types.CreditorBankAccount, Types.APIResponse {} 7 | 8 | interface CreditorBankAccountListResponse extends Types.APIResponse { 9 | creditor_bank_accounts: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface CreditorBankAccountCreateRequest { 14 | // Name of the account holder, as known by the bank. Usually this is the same as 15 | // the name stored with the linked [creditor](#core-endpoints-creditors). This 16 | // field will be transliterated, upcased and truncated to 18 characters. 17 | 18 | account_holder_name: string; 19 | 20 | // Bank account number - see [local details](#appendix-local-bank-details) for 21 | // more information. Alternatively you can provide an `iban`. 22 | 23 | account_number?: string; 24 | 25 | // Bank account type. Required for USD-denominated bank accounts. Must not be 26 | // provided for bank accounts in other currencies. See [local 27 | // details](#local-bank-details-united-states) for more information. 28 | 29 | account_type?: Types.CreditorBankAccountAccountType; 30 | 31 | // Bank code - see [local details](#appendix-local-bank-details) for more 32 | // information. Alternatively you can provide an `iban`. 33 | 34 | bank_code?: string; 35 | 36 | // Branch code - see [local details](#appendix-local-bank-details) for more 37 | // information. Alternatively you can provide an `iban`. 38 | 39 | branch_code?: string; 40 | 41 | // [ISO 3166-1 alpha-2 42 | // code](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). 43 | // Defaults to the country code of the `iban` if supplied, otherwise is 44 | // required. 45 | 46 | country_code?: string; 47 | 48 | // [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. 49 | // Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are 50 | // supported. 51 | 52 | currency?: string; 53 | 54 | // International Bank Account Number. Alternatively you can provide [local 55 | // details](#appendix-local-bank-details). IBANs are not accepted for Swedish 56 | // bank accounts denominated in SEK - you must supply [local 57 | // details](#local-bank-details-sweden). 58 | 59 | iban?: string; 60 | 61 | // Resources linked to this CreditorBankAccount. 62 | links: Types.CreditorBankAccountCreateRequestLinks; 63 | 64 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 65 | // to 50 characters and values up to 500 characters. 66 | 67 | metadata?: Types.JsonMap; 68 | 69 | // Defaults to `true`. When this is set to `true`, it will cause this bank 70 | // account to be set as the account that GoCardless will pay out to. 71 | 72 | set_as_default_payout_account?: boolean; 73 | } 74 | 75 | interface CreditorBankAccountListRequest { 76 | // Cursor pointing to the start of the desired set. 77 | 78 | after?: string; 79 | 80 | // Cursor pointing to the end of the desired set. 81 | 82 | before?: string; 83 | 84 | // The creation date of this CreditorBankAccount. 85 | created_at?: Types.CreatedAtFilter; 86 | 87 | // Unique identifier, beginning with "CR". 88 | 89 | creditor?: string; 90 | 91 | // If `true`, only return enabled bank accounts. If `false`, only return 92 | // disabled bank accounts. 93 | 94 | enabled?: boolean; 95 | 96 | // Number of records to return. 97 | 98 | limit?: string; 99 | } 100 | 101 | export class CreditorBankAccountService { 102 | private api: Api; 103 | 104 | constructor(api) { 105 | this.api = api; 106 | } 107 | 108 | public async create( 109 | requestParameters: CreditorBankAccountCreateRequest, 110 | idempotencyKey = '', 111 | customHeaders: Types.JsonMap = {}, 112 | ): Promise { 113 | const urlParameters = []; 114 | const requestParams = { 115 | path: '/creditor_bank_accounts', 116 | method: 'post', 117 | urlParameters, 118 | requestParameters, 119 | payloadKey: 'creditor_bank_accounts', 120 | idempotencyKey, 121 | customHeaders, 122 | fetch: async (identity) => await this.find(identity), 123 | }; 124 | 125 | const response = await this.api.request(requestParams); 126 | const formattedResponse: CreditorBankAccountResponse = { 127 | ...(response.body?.['creditor_bank_accounts'] ?? response), 128 | __response__: response.__response__, 129 | }; 130 | 131 | return formattedResponse; 132 | } 133 | 134 | public async list( 135 | requestParameters: CreditorBankAccountListRequest, 136 | customHeaders: Types.JsonMap = {}, 137 | ): Promise { 138 | const urlParameters = []; 139 | const requestParams = { 140 | path: '/creditor_bank_accounts', 141 | method: 'get', 142 | urlParameters, 143 | requestParameters, 144 | payloadKey: null, 145 | fetch: null, 146 | customHeaders, 147 | }; 148 | 149 | const response = await this.api.request(requestParams); 150 | const formattedResponse: CreditorBankAccountListResponse = { 151 | ...response.body, 152 | __response__: response.__response__, 153 | }; 154 | 155 | return formattedResponse; 156 | } 157 | 158 | public async *all( 159 | requestParameters: CreditorBankAccountListRequest, 160 | customHeaders: Types.JsonMap = {}, 161 | ): AsyncGenerator { 162 | let cursor = undefined; 163 | do { 164 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 165 | 166 | for (const creditorbankaccount of list.creditor_bank_accounts) { 167 | yield creditorbankaccount; 168 | } 169 | 170 | cursor = list.meta.cursors.after; 171 | } while (cursor); 172 | } 173 | 174 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 175 | const urlParameters = [{ key: 'identity', value: identity }]; 176 | const requestParams = { 177 | path: '/creditor_bank_accounts/:identity', 178 | method: 'get', 179 | urlParameters, 180 | 181 | payloadKey: null, 182 | fetch: null, 183 | customHeaders, 184 | }; 185 | 186 | const response = await this.api.request(requestParams); 187 | const formattedResponse: CreditorBankAccountResponse = { 188 | ...response.body['creditor_bank_accounts'], 189 | __response__: response.__response__, 190 | }; 191 | 192 | return formattedResponse; 193 | } 194 | 195 | public async disable(identity: string, customHeaders: Types.JsonMap = {}): Promise { 196 | const urlParameters = [{ key: 'identity', value: identity }]; 197 | const requestParams = { 198 | path: '/creditor_bank_accounts/:identity/actions/disable', 199 | method: 'post', 200 | urlParameters, 201 | 202 | payloadKey: null, 203 | fetch: null, 204 | customHeaders, 205 | }; 206 | 207 | const response = await this.api.request(requestParams); 208 | const formattedResponse: CreditorBankAccountResponse = { 209 | ...response.body['creditor_bank_accounts'], 210 | __response__: response.__response__, 211 | }; 212 | 213 | return formattedResponse; 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /src/services/creditorService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface CreditorResponse extends Types.Creditor, Types.APIResponse {} 7 | 8 | interface CreditorListResponse extends Types.APIResponse { 9 | creditors: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface CreditorCreateRequest { 14 | // Prefix for the bank reference of payouts sent to this creditor. For instance, 15 | // if 16 | // the creditor's `bank_reference_prefix` was `ACME`, the bank reference of a 17 | // payout 18 | // sent to that creditor could be `ACME-8G7Q8`. 19 | // 20 | // This prefix is also used for refunds in EUR and GBP. 21 | // 22 | 23 | bank_reference_prefix?: string; 24 | 25 | // [ISO 3166-1 alpha-2 26 | // code.](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) 27 | 28 | country_code: string; 29 | 30 | // The type of business of the creditor. Currently, `individual`, `company`, 31 | // `charity`, `partnership`, and `trust` are supported. 32 | 33 | creditor_type: Types.CreditorCreditorType; 34 | 35 | // The creditor's trading name. 36 | 37 | name: string; 38 | } 39 | 40 | interface CreditorListRequest { 41 | // Cursor pointing to the start of the desired set. 42 | 43 | after?: string; 44 | 45 | // Cursor pointing to the end of the desired set. 46 | 47 | before?: string; 48 | 49 | // The creation date of this Creditor. 50 | created_at?: Types.CreatedAtFilter; 51 | 52 | // Number of records to return. 53 | 54 | limit?: string; 55 | } 56 | 57 | interface CreditorUpdateRequest { 58 | // The first line of the creditor's address. 59 | 60 | address_line1?: string; 61 | 62 | // The second line of the creditor's address. 63 | 64 | address_line2?: string; 65 | 66 | // The third line of the creditor's address. 67 | 68 | address_line3?: string; 69 | 70 | // Prefix for the bank reference of payouts sent to this creditor. For instance, 71 | // if 72 | // the creditor's `bank_reference_prefix` was `ACME`, the bank reference of a 73 | // payout 74 | // sent to that creditor could be `ACME-8G7Q8`. 75 | // 76 | // This prefix is also used for refunds in EUR and GBP. 77 | // 78 | 79 | bank_reference_prefix?: string; 80 | 81 | // The city of the creditor's address. 82 | 83 | city?: string; 84 | 85 | // [ISO 3166-1 alpha-2 86 | // code.](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) 87 | 88 | country_code?: string; 89 | 90 | // Resources linked to this Creditor. 91 | links?: Types.CreditorUpdateRequestLinks; 92 | 93 | // The creditor's trading name. 94 | 95 | name?: string; 96 | 97 | // The creditor's postal code. 98 | 99 | postal_code?: string; 100 | 101 | // The creditor's address region, county or department. 102 | 103 | region?: string; 104 | } 105 | 106 | export class CreditorService { 107 | private api: Api; 108 | 109 | constructor(api) { 110 | this.api = api; 111 | } 112 | 113 | public async create( 114 | requestParameters: CreditorCreateRequest, 115 | idempotencyKey = '', 116 | customHeaders: Types.JsonMap = {}, 117 | ): Promise { 118 | const urlParameters = []; 119 | const requestParams = { 120 | path: '/creditors', 121 | method: 'post', 122 | urlParameters, 123 | requestParameters, 124 | payloadKey: 'creditors', 125 | idempotencyKey, 126 | customHeaders, 127 | fetch: async (identity) => await this.find(identity), 128 | }; 129 | 130 | const response = await this.api.request(requestParams); 131 | const formattedResponse: CreditorResponse = { 132 | ...(response.body?.['creditors'] ?? response), 133 | __response__: response.__response__, 134 | }; 135 | 136 | return formattedResponse; 137 | } 138 | 139 | public async list( 140 | requestParameters: CreditorListRequest, 141 | customHeaders: Types.JsonMap = {}, 142 | ): Promise { 143 | const urlParameters = []; 144 | const requestParams = { 145 | path: '/creditors', 146 | method: 'get', 147 | urlParameters, 148 | requestParameters, 149 | payloadKey: null, 150 | fetch: null, 151 | customHeaders, 152 | }; 153 | 154 | const response = await this.api.request(requestParams); 155 | const formattedResponse: CreditorListResponse = { 156 | ...response.body, 157 | __response__: response.__response__, 158 | }; 159 | 160 | return formattedResponse; 161 | } 162 | 163 | public async *all( 164 | requestParameters: CreditorListRequest, 165 | customHeaders: Types.JsonMap = {}, 166 | ): AsyncGenerator { 167 | let cursor = undefined; 168 | do { 169 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 170 | 171 | for (const creditor of list.creditors) { 172 | yield creditor; 173 | } 174 | 175 | cursor = list.meta.cursors.after; 176 | } while (cursor); 177 | } 178 | 179 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 180 | const urlParameters = [{ key: 'identity', value: identity }]; 181 | const requestParams = { 182 | path: '/creditors/:identity', 183 | method: 'get', 184 | urlParameters, 185 | 186 | payloadKey: null, 187 | fetch: null, 188 | customHeaders, 189 | }; 190 | 191 | const response = await this.api.request(requestParams); 192 | const formattedResponse: CreditorResponse = { 193 | ...response.body['creditors'], 194 | __response__: response.__response__, 195 | }; 196 | 197 | return formattedResponse; 198 | } 199 | 200 | public async update( 201 | identity: string, 202 | requestParameters: CreditorUpdateRequest, 203 | customHeaders: Types.JsonMap = {}, 204 | ): Promise { 205 | const urlParameters = [{ key: 'identity', value: identity }]; 206 | const requestParams = { 207 | path: '/creditors/:identity', 208 | method: 'put', 209 | urlParameters, 210 | requestParameters, 211 | payloadKey: 'creditors', 212 | fetch: null, 213 | customHeaders, 214 | }; 215 | 216 | const response = await this.api.request(requestParams); 217 | const formattedResponse: CreditorResponse = { 218 | ...response.body['creditors'], 219 | __response__: response.__response__, 220 | }; 221 | 222 | return formattedResponse; 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /src/services/currencyExchangeRateService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface CurrencyExchangeRateResponse extends Types.CurrencyExchangeRate, Types.APIResponse {} 7 | 8 | interface CurrencyExchangeRateListResponse extends Types.APIResponse { 9 | currency_exchange_rates: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface CurrencyExchangeRateListRequest { 14 | // Cursor pointing to the start of the desired set. 15 | 16 | after?: string; 17 | 18 | // Cursor pointing to the end of the desired set. 19 | 20 | before?: string; 21 | 22 | // Number of records to return. 23 | 24 | limit?: string; 25 | 26 | // Source currency 27 | 28 | source?: string; 29 | 30 | // Target currency 31 | 32 | target?: string; 33 | } 34 | 35 | export class CurrencyExchangeRateService { 36 | private api: Api; 37 | 38 | constructor(api) { 39 | this.api = api; 40 | } 41 | 42 | public async list( 43 | requestParameters: CurrencyExchangeRateListRequest, 44 | customHeaders: Types.JsonMap = {}, 45 | ): Promise { 46 | const urlParameters = []; 47 | const requestParams = { 48 | path: '/currency_exchange_rates', 49 | method: 'get', 50 | urlParameters, 51 | requestParameters, 52 | payloadKey: null, 53 | fetch: null, 54 | customHeaders, 55 | }; 56 | 57 | const response = await this.api.request(requestParams); 58 | const formattedResponse: CurrencyExchangeRateListResponse = { 59 | ...response.body, 60 | __response__: response.__response__, 61 | }; 62 | 63 | return formattedResponse; 64 | } 65 | 66 | public async *all( 67 | requestParameters: CurrencyExchangeRateListRequest, 68 | customHeaders: Types.JsonMap = {}, 69 | ): AsyncGenerator { 70 | let cursor = undefined; 71 | do { 72 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 73 | 74 | for (const currencyexchangerate of list.currency_exchange_rates) { 75 | yield currencyexchangerate; 76 | } 77 | 78 | cursor = list.meta.cursors.after; 79 | } while (cursor); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/services/customerBankAccountService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface CustomerBankAccountResponse extends Types.CustomerBankAccount, Types.APIResponse {} 7 | 8 | interface CustomerBankAccountListResponse extends Types.APIResponse { 9 | customer_bank_accounts: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface CustomerBankAccountCreateRequest { 14 | // Name of the account holder, as known by the bank. This field will be 15 | // transliterated, upcased and truncated to 18 characters. This field is 16 | // required unless the request includes a [customer bank account 17 | // token](#javascript-flow-customer-bank-account-tokens). 18 | 19 | account_holder_name?: string; 20 | 21 | // Bank account number - see [local details](#appendix-local-bank-details) for 22 | // more information. Alternatively you can provide an `iban`. 23 | 24 | account_number?: string; 25 | 26 | // Bank account type. Required for USD-denominated bank accounts. Must not be 27 | // provided for bank accounts in other currencies. See [local 28 | // details](#local-bank-details-united-states) for more information. 29 | 30 | account_type?: Types.CustomerBankAccountAccountType; 31 | 32 | // Bank code - see [local details](#appendix-local-bank-details) for more 33 | // information. Alternatively you can provide an `iban`. 34 | 35 | bank_code?: string; 36 | 37 | // Branch code - see [local details](#appendix-local-bank-details) for more 38 | // information. Alternatively you can provide an `iban`. 39 | 40 | branch_code?: string; 41 | 42 | // [ISO 3166-1 alpha-2 43 | // code](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). 44 | // Defaults to the country code of the `iban` if supplied, otherwise is 45 | // required. 46 | 47 | country_code?: string; 48 | 49 | // [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. 50 | // Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are 51 | // supported. 52 | 53 | currency?: string; 54 | 55 | // International Bank Account Number. Alternatively you can provide [local 56 | // details](#appendix-local-bank-details). IBANs are not accepted for Swedish 57 | // bank accounts denominated in SEK - you must supply [local 58 | // details](#local-bank-details-sweden). 59 | 60 | iban?: string; 61 | 62 | // Resources linked to this CustomerBankAccount. 63 | links: Types.CustomerBankAccountCreateRequestLinks; 64 | 65 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 66 | // to 50 characters and values up to 500 characters. 67 | 68 | metadata?: Types.JsonMap; 69 | } 70 | 71 | interface CustomerBankAccountListRequest { 72 | // Cursor pointing to the start of the desired set. 73 | 74 | after?: string; 75 | 76 | // Cursor pointing to the end of the desired set. 77 | 78 | before?: string; 79 | 80 | // The creation date of this CustomerBankAccount. 81 | created_at?: Types.CreatedAtFilter; 82 | 83 | // Unique identifier, beginning with "CU". 84 | 85 | customer?: string; 86 | 87 | // Get enabled or disabled customer bank accounts. 88 | 89 | enabled?: boolean; 90 | 91 | // Number of records to return. 92 | 93 | limit?: string; 94 | } 95 | 96 | interface CustomerBankAccountUpdateRequest { 97 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 98 | // to 50 characters and values up to 500 characters. 99 | 100 | metadata?: Types.JsonMap; 101 | } 102 | 103 | export class CustomerBankAccountService { 104 | private api: Api; 105 | 106 | constructor(api) { 107 | this.api = api; 108 | } 109 | 110 | public async create( 111 | requestParameters: CustomerBankAccountCreateRequest, 112 | idempotencyKey = '', 113 | customHeaders: Types.JsonMap = {}, 114 | ): Promise { 115 | const urlParameters = []; 116 | const requestParams = { 117 | path: '/customer_bank_accounts', 118 | method: 'post', 119 | urlParameters, 120 | requestParameters, 121 | payloadKey: 'customer_bank_accounts', 122 | idempotencyKey, 123 | customHeaders, 124 | fetch: async (identity) => await this.find(identity), 125 | }; 126 | 127 | const response = await this.api.request(requestParams); 128 | const formattedResponse: CustomerBankAccountResponse = { 129 | ...(response.body?.['customer_bank_accounts'] ?? response), 130 | __response__: response.__response__, 131 | }; 132 | 133 | return formattedResponse; 134 | } 135 | 136 | public async list( 137 | requestParameters: CustomerBankAccountListRequest, 138 | customHeaders: Types.JsonMap = {}, 139 | ): Promise { 140 | const urlParameters = []; 141 | const requestParams = { 142 | path: '/customer_bank_accounts', 143 | method: 'get', 144 | urlParameters, 145 | requestParameters, 146 | payloadKey: null, 147 | fetch: null, 148 | customHeaders, 149 | }; 150 | 151 | const response = await this.api.request(requestParams); 152 | const formattedResponse: CustomerBankAccountListResponse = { 153 | ...response.body, 154 | __response__: response.__response__, 155 | }; 156 | 157 | return formattedResponse; 158 | } 159 | 160 | public async *all( 161 | requestParameters: CustomerBankAccountListRequest, 162 | customHeaders: Types.JsonMap = {}, 163 | ): AsyncGenerator { 164 | let cursor = undefined; 165 | do { 166 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 167 | 168 | for (const customerbankaccount of list.customer_bank_accounts) { 169 | yield customerbankaccount; 170 | } 171 | 172 | cursor = list.meta.cursors.after; 173 | } while (cursor); 174 | } 175 | 176 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 177 | const urlParameters = [{ key: 'identity', value: identity }]; 178 | const requestParams = { 179 | path: '/customer_bank_accounts/:identity', 180 | method: 'get', 181 | urlParameters, 182 | 183 | payloadKey: null, 184 | fetch: null, 185 | customHeaders, 186 | }; 187 | 188 | const response = await this.api.request(requestParams); 189 | const formattedResponse: CustomerBankAccountResponse = { 190 | ...response.body['customer_bank_accounts'], 191 | __response__: response.__response__, 192 | }; 193 | 194 | return formattedResponse; 195 | } 196 | 197 | public async update( 198 | identity: string, 199 | requestParameters: CustomerBankAccountUpdateRequest, 200 | customHeaders: Types.JsonMap = {}, 201 | ): Promise { 202 | const urlParameters = [{ key: 'identity', value: identity }]; 203 | const requestParams = { 204 | path: '/customer_bank_accounts/:identity', 205 | method: 'put', 206 | urlParameters, 207 | requestParameters, 208 | payloadKey: 'customer_bank_accounts', 209 | fetch: null, 210 | customHeaders, 211 | }; 212 | 213 | const response = await this.api.request(requestParams); 214 | const formattedResponse: CustomerBankAccountResponse = { 215 | ...response.body['customer_bank_accounts'], 216 | __response__: response.__response__, 217 | }; 218 | 219 | return formattedResponse; 220 | } 221 | 222 | public async disable(identity: string, customHeaders: Types.JsonMap = {}): Promise { 223 | const urlParameters = [{ key: 'identity', value: identity }]; 224 | const requestParams = { 225 | path: '/customer_bank_accounts/:identity/actions/disable', 226 | method: 'post', 227 | urlParameters, 228 | 229 | payloadKey: null, 230 | fetch: null, 231 | customHeaders, 232 | }; 233 | 234 | const response = await this.api.request(requestParams); 235 | const formattedResponse: CustomerBankAccountResponse = { 236 | ...response.body['customer_bank_accounts'], 237 | __response__: response.__response__, 238 | }; 239 | 240 | return formattedResponse; 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /src/services/customerNotificationService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface CustomerNotificationResponse extends Types.CustomerNotification, Types.APIResponse {} 7 | 8 | interface CustomerNotificationListResponse extends Types.APIResponse { 9 | customer_notifications: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | export class CustomerNotificationService { 14 | private api: Api; 15 | 16 | constructor(api) { 17 | this.api = api; 18 | } 19 | 20 | public async handle(identity: string, customHeaders: Types.JsonMap = {}): Promise { 21 | const urlParameters = [{ key: 'identity', value: identity }]; 22 | const requestParams = { 23 | path: '/customer_notifications/:identity/actions/handle', 24 | method: 'post', 25 | urlParameters, 26 | 27 | payloadKey: null, 28 | fetch: null, 29 | customHeaders, 30 | }; 31 | 32 | const response = await this.api.request(requestParams); 33 | const formattedResponse: CustomerNotificationResponse = { 34 | ...response.body['customer_notifications'], 35 | __response__: response.__response__, 36 | }; 37 | 38 | return formattedResponse; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/services/customerService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface CustomerResponse extends Types.Customer, Types.APIResponse {} 7 | 8 | interface CustomerListResponse extends Types.APIResponse { 9 | customers: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface CustomerCreateRequest { 14 | // The first line of the customer's address. 15 | 16 | address_line1?: string; 17 | 18 | // The second line of the customer's address. 19 | 20 | address_line2?: string; 21 | 22 | // The third line of the customer's address. 23 | 24 | address_line3?: string; 25 | 26 | // The city of the customer's address. 27 | 28 | city?: string; 29 | 30 | // Customer's company name. Required unless a `given_name` and `family_name` are 31 | // provided. For Canadian customers, the use of a `company_name` value will mean 32 | // that any mandate created from this customer will be considered to be a 33 | // "Business PAD" (otherwise, any mandate will be considered to be a "Personal 34 | // PAD"). 35 | 36 | company_name?: string; 37 | 38 | // [ISO 3166-1 alpha-2 39 | // code.](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) 40 | 41 | country_code?: string; 42 | 43 | // For Danish customers only. The civic/company number (CPR or CVR) of the 44 | // customer. Must be supplied if the customer's bank account is denominated in 45 | // Danish krone (DKK). 46 | 47 | danish_identity_number?: string; 48 | 49 | // Customer's email address. Required in most cases, as this allows GoCardless 50 | // to send notifications to this customer. 51 | 52 | email?: string; 53 | 54 | // Customer's surname. Required unless a `company_name` is provided. 55 | 56 | family_name?: string; 57 | 58 | // Customer's first name. Required unless a `company_name` is provided. 59 | 60 | given_name?: string; 61 | 62 | // [ISO 639-1](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code. Used 63 | // as the language for notification emails sent by GoCardless if your 64 | // organisation does not send its own (see [compliance 65 | // requirements](#appendix-compliance-requirements)). Currently only "en", "fr", 66 | // "de", "pt", "es", "it", "nl", "da", "nb", "sl", "sv" are supported. If this 67 | // is not provided, the language will be chosen based on the `country_code` (if 68 | // supplied) or default to "en". 69 | 70 | language?: string; 71 | 72 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 73 | // to 50 characters and values up to 500 characters. 74 | 75 | metadata?: Types.JsonMap; 76 | 77 | // [ITU E.123](https://en.wikipedia.org/wiki/E.123) formatted phone number, 78 | // including country code. 79 | 80 | phone_number?: string; 81 | 82 | // The customer's postal code. 83 | 84 | postal_code?: string; 85 | 86 | // The customer's address region, county or department. For US customers a 2 87 | // letter [ISO3166-2:US](https://en.wikipedia.org/wiki/ISO_3166-2:US) state code 88 | // is required (e.g. `CA` for California). 89 | 90 | region?: string; 91 | 92 | // For Swedish customers only. The civic/company number (personnummer, 93 | // samordningsnummer, or organisationsnummer) of the customer. Must be supplied 94 | // if the customer's bank account is denominated in Swedish krona (SEK). This 95 | // field cannot be changed once it has been set. 96 | 97 | swedish_identity_number?: string; 98 | } 99 | 100 | interface CustomerListRequest { 101 | // Cursor pointing to the start of the desired set. 102 | 103 | after?: string; 104 | 105 | // Cursor pointing to the end of the desired set. 106 | 107 | before?: string; 108 | 109 | // The creation date of this Customer. 110 | created_at?: Types.CreatedAtFilter; 111 | 112 | // [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. 113 | // Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are 114 | // supported. 115 | 116 | currency?: Types.CustomerCurrency; 117 | 118 | // Number of records to return. 119 | 120 | limit?: string; 121 | 122 | // The direction to sort in. 123 | // One of: 124 | //
    125 | //
  • `asc`
  • 126 | //
  • `desc`
  • 127 | //
128 | 129 | sort_direction?: Types.CustomerSortDirection; 130 | 131 | // Field by which to sort records. 132 | // One of: 133 | //
    134 | //
  • `name`
  • 135 | //
  • `company_name`
  • 136 | //
  • `created_at`
  • 137 | //
138 | 139 | sort_field?: Types.CustomerSortField; 140 | } 141 | 142 | interface CustomerUpdateRequest { 143 | // The first line of the customer's address. 144 | 145 | address_line1?: string; 146 | 147 | // The second line of the customer's address. 148 | 149 | address_line2?: string; 150 | 151 | // The third line of the customer's address. 152 | 153 | address_line3?: string; 154 | 155 | // The city of the customer's address. 156 | 157 | city?: string; 158 | 159 | // Customer's company name. Required unless a `given_name` and `family_name` are 160 | // provided. For Canadian customers, the use of a `company_name` value will mean 161 | // that any mandate created from this customer will be considered to be a 162 | // "Business PAD" (otherwise, any mandate will be considered to be a "Personal 163 | // PAD"). 164 | 165 | company_name?: string; 166 | 167 | // [ISO 3166-1 alpha-2 168 | // code.](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) 169 | 170 | country_code?: string; 171 | 172 | // For Danish customers only. The civic/company number (CPR or CVR) of the 173 | // customer. Must be supplied if the customer's bank account is denominated in 174 | // Danish krone (DKK). 175 | 176 | danish_identity_number?: string; 177 | 178 | // Customer's email address. Required in most cases, as this allows GoCardless 179 | // to send notifications to this customer. 180 | 181 | email?: string; 182 | 183 | // Customer's surname. Required unless a `company_name` is provided. 184 | 185 | family_name?: string; 186 | 187 | // Customer's first name. Required unless a `company_name` is provided. 188 | 189 | given_name?: string; 190 | 191 | // [ISO 639-1](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code. Used 192 | // as the language for notification emails sent by GoCardless if your 193 | // organisation does not send its own (see [compliance 194 | // requirements](#appendix-compliance-requirements)). Currently only "en", "fr", 195 | // "de", "pt", "es", "it", "nl", "da", "nb", "sl", "sv" are supported. If this 196 | // is not provided, the language will be chosen based on the `country_code` (if 197 | // supplied) or default to "en". 198 | 199 | language?: string; 200 | 201 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 202 | // to 50 characters and values up to 500 characters. 203 | 204 | metadata?: Types.JsonMap; 205 | 206 | // [ITU E.123](https://en.wikipedia.org/wiki/E.123) formatted phone number, 207 | // including country code. 208 | 209 | phone_number?: string; 210 | 211 | // The customer's postal code. 212 | 213 | postal_code?: string; 214 | 215 | // The customer's address region, county or department. For US customers a 2 216 | // letter [ISO3166-2:US](https://en.wikipedia.org/wiki/ISO_3166-2:US) state code 217 | // is required (e.g. `CA` for California). 218 | 219 | region?: string; 220 | 221 | // For Swedish customers only. The civic/company number (personnummer, 222 | // samordningsnummer, or organisationsnummer) of the customer. Must be supplied 223 | // if the customer's bank account is denominated in Swedish krona (SEK). This 224 | // field cannot be changed once it has been set. 225 | 226 | swedish_identity_number?: string; 227 | } 228 | 229 | export class CustomerService { 230 | private api: Api; 231 | 232 | constructor(api) { 233 | this.api = api; 234 | } 235 | 236 | public async create( 237 | requestParameters: CustomerCreateRequest, 238 | idempotencyKey = '', 239 | customHeaders: Types.JsonMap = {}, 240 | ): Promise { 241 | const urlParameters = []; 242 | const requestParams = { 243 | path: '/customers', 244 | method: 'post', 245 | urlParameters, 246 | requestParameters, 247 | payloadKey: 'customers', 248 | idempotencyKey, 249 | customHeaders, 250 | fetch: async (identity) => await this.find(identity), 251 | }; 252 | 253 | const response = await this.api.request(requestParams); 254 | const formattedResponse: CustomerResponse = { 255 | ...(response.body?.['customers'] ?? response), 256 | __response__: response.__response__, 257 | }; 258 | 259 | return formattedResponse; 260 | } 261 | 262 | public async list( 263 | requestParameters: CustomerListRequest, 264 | customHeaders: Types.JsonMap = {}, 265 | ): Promise { 266 | const urlParameters = []; 267 | const requestParams = { 268 | path: '/customers', 269 | method: 'get', 270 | urlParameters, 271 | requestParameters, 272 | payloadKey: null, 273 | fetch: null, 274 | customHeaders, 275 | }; 276 | 277 | const response = await this.api.request(requestParams); 278 | const formattedResponse: CustomerListResponse = { 279 | ...response.body, 280 | __response__: response.__response__, 281 | }; 282 | 283 | return formattedResponse; 284 | } 285 | 286 | public async *all( 287 | requestParameters: CustomerListRequest, 288 | customHeaders: Types.JsonMap = {}, 289 | ): AsyncGenerator { 290 | let cursor = undefined; 291 | do { 292 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 293 | 294 | for (const customer of list.customers) { 295 | yield customer; 296 | } 297 | 298 | cursor = list.meta.cursors.after; 299 | } while (cursor); 300 | } 301 | 302 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 303 | const urlParameters = [{ key: 'identity', value: identity }]; 304 | const requestParams = { 305 | path: '/customers/:identity', 306 | method: 'get', 307 | urlParameters, 308 | 309 | payloadKey: null, 310 | fetch: null, 311 | customHeaders, 312 | }; 313 | 314 | const response = await this.api.request(requestParams); 315 | const formattedResponse: CustomerResponse = { 316 | ...response.body['customers'], 317 | __response__: response.__response__, 318 | }; 319 | 320 | return formattedResponse; 321 | } 322 | 323 | public async update( 324 | identity: string, 325 | requestParameters: CustomerUpdateRequest, 326 | customHeaders: Types.JsonMap = {}, 327 | ): Promise { 328 | const urlParameters = [{ key: 'identity', value: identity }]; 329 | const requestParams = { 330 | path: '/customers/:identity', 331 | method: 'put', 332 | urlParameters, 333 | requestParameters, 334 | payloadKey: 'customers', 335 | fetch: null, 336 | customHeaders, 337 | }; 338 | 339 | const response = await this.api.request(requestParams); 340 | const formattedResponse: CustomerResponse = { 341 | ...response.body['customers'], 342 | __response__: response.__response__, 343 | }; 344 | 345 | return formattedResponse; 346 | } 347 | 348 | public async remove(identity: string, customHeaders: Types.JsonMap = {}): Promise { 349 | const urlParameters = [{ key: 'identity', value: identity }]; 350 | const requestParams = { 351 | path: '/customers/:identity', 352 | method: 'delete', 353 | urlParameters, 354 | 355 | payloadKey: null, 356 | fetch: null, 357 | customHeaders, 358 | }; 359 | 360 | const response = await this.api.request(requestParams); 361 | const formattedResponse: CustomerResponse = { 362 | ...response.body['customers'], 363 | __response__: response.__response__, 364 | }; 365 | 366 | return formattedResponse; 367 | } 368 | } 369 | -------------------------------------------------------------------------------- /src/services/eventService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface EventResponse extends Types.Event, Types.APIResponse {} 7 | 8 | interface EventListResponse extends Types.APIResponse { 9 | events: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface EventListRequest { 14 | // Limit to events with a given `action`. 15 | 16 | action?: string; 17 | 18 | // Cursor pointing to the start of the desired set. 19 | 20 | after?: string; 21 | 22 | // Cursor pointing to the end of the desired set. 23 | 24 | before?: string; 25 | 26 | // ID of a [billing request](#billing-requests-billing-requests). If specified, 27 | // this endpoint will return all events for the given billing request. 28 | 29 | billing_request?: string; 30 | 31 | // The creation date of this Event. 32 | created_at?: Types.CreatedAtFilter; 33 | 34 | // ID of an [creditor](#core-endpoints-creditors). If specified, this endpoint 35 | // will return all events for the given creditor. 36 | 37 | creditor?: string; 38 | 39 | // ID of an export. If specified, this endpoint will return all events for the 40 | // given export. 41 | 42 | export?: string; 43 | 44 | // Includes linked resources in the response. Must be used with the 45 | // `resource_type` parameter specified. The include should be one of: 46 | //
    47 | //
  • `billing_request`
  • 48 | //
  • `creditor`
  • 49 | //
  • `instalment_schedule`
  • 50 | //
  • `mandate`
  • 51 | //
  • `payer_authorisation`
  • 52 | //
  • `payment`
  • 53 | //
  • `payout`
  • 54 | //
  • `refund`
  • 55 | //
  • `scheme_identifier`
  • 56 | //
  • `subscription`
  • 57 | //
  • `outbound_payment`
  • 58 | //
59 | 60 | include?: Types.EventInclude; 61 | 62 | // ID of an [instalment schedule](#core-endpoints-instalment-schedules). If 63 | // specified, this endpoint will return all events for the given instalment 64 | // schedule. 65 | 66 | instalment_schedule?: string; 67 | 68 | // Number of records to return. 69 | 70 | limit?: string; 71 | 72 | // ID of a [mandate](#core-endpoints-mandates). If specified, this endpoint will 73 | // return all events for the given mandate. 74 | 75 | mandate?: string; 76 | 77 | // ID of an outbound_payment. If specified, this endpoint will return all events 78 | // for the given payment. 79 | 80 | outbound_payment?: string; 81 | 82 | // ID of an event. If specified, this endpoint will return all events whose 83 | // parent_event is the given event ID. 84 | 85 | parent_event?: string; 86 | 87 | // ID of a [payer authorisation](#core-endpoints-payer-authorisations). 88 | 89 | payer_authorisation?: string; 90 | 91 | // ID of a [payment](#core-endpoints-payments). If specified, this endpoint will 92 | // return all events for the given payment. 93 | 94 | payment?: string; 95 | 96 | // ID of a [payout](#core-endpoints-payouts). If specified, this endpoint will 97 | // return all events for the given payout. 98 | 99 | payout?: string; 100 | 101 | // ID of a [refund](#core-endpoints-refunds). If specified, this endpoint will 102 | // return all events for the given refund. 103 | 104 | refund?: string; 105 | 106 | // Type of resource that you'd like to get all events for. 107 | // Cannot be used together with the `billing_request`, `creditor`, 108 | // `export`,`instalment_schedule`, `mandate`, `payer_authorisation`, `payment`, 109 | // `payout`, `refund`, `scheme_identifier`, `subscription` or `outbound_payment` 110 | // parameters. 111 | // The type can be one of: 112 | //
    113 | //
  • `billing_requests`
  • 114 | //
  • `creditors`
  • 115 | //
  • `exports`
  • 116 | //
  • `instalment_schedules`
  • 117 | //
  • `mandates`
  • 118 | //
  • `payer_authorisations`
  • 119 | //
  • `payments`
  • 120 | //
  • `payouts`
  • 121 | //
  • `refunds`
  • 122 | //
  • `scheme_identifiers`
  • 123 | //
  • `subscriptions`
  • 124 | //
  • `outbound_payments`
  • 125 | //
126 | 127 | resource_type?: Types.EventResourceType; 128 | 129 | // ID of a [scheme identifier](#core-endpoints-scheme-identifiers). If 130 | // specified, this endpoint will return all events for the given scheme 131 | // identifier. 132 | 133 | scheme_identifier?: string; 134 | 135 | // ID of a [subscription](#core-endpoints-subscriptions). If specified, this 136 | // endpoint will return all events for the given subscription. 137 | 138 | subscription?: string; 139 | } 140 | 141 | export class EventService { 142 | private api: Api; 143 | 144 | constructor(api) { 145 | this.api = api; 146 | } 147 | 148 | public async list( 149 | requestParameters: EventListRequest, 150 | customHeaders: Types.JsonMap = {}, 151 | ): Promise { 152 | const urlParameters = []; 153 | const requestParams = { 154 | path: '/events', 155 | method: 'get', 156 | urlParameters, 157 | requestParameters, 158 | payloadKey: null, 159 | fetch: null, 160 | customHeaders, 161 | }; 162 | 163 | const response = await this.api.request(requestParams); 164 | const formattedResponse: EventListResponse = { 165 | ...response.body, 166 | __response__: response.__response__, 167 | }; 168 | 169 | return formattedResponse; 170 | } 171 | 172 | public async *all( 173 | requestParameters: EventListRequest, 174 | customHeaders: Types.JsonMap = {}, 175 | ): AsyncGenerator { 176 | let cursor = undefined; 177 | do { 178 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 179 | 180 | for (const event of list.events) { 181 | yield event; 182 | } 183 | 184 | cursor = list.meta.cursors.after; 185 | } while (cursor); 186 | } 187 | 188 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 189 | const urlParameters = [{ key: 'identity', value: identity }]; 190 | const requestParams = { 191 | path: '/events/:identity', 192 | method: 'get', 193 | urlParameters, 194 | 195 | payloadKey: null, 196 | fetch: null, 197 | customHeaders, 198 | }; 199 | 200 | const response = await this.api.request(requestParams); 201 | const formattedResponse: EventResponse = { 202 | ...response.body['events'], 203 | __response__: response.__response__, 204 | }; 205 | 206 | return formattedResponse; 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /src/services/exportService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface ExportResponse extends Types.Export, Types.APIResponse {} 7 | 8 | interface ExportListResponse extends Types.APIResponse { 9 | exports: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface ExportListRequest { 14 | // Cursor pointing to the start of the desired set. 15 | 16 | after?: string; 17 | 18 | // Cursor pointing to the end of the desired set. 19 | 20 | before?: string; 21 | 22 | // Number of records to return. 23 | 24 | limit?: string; 25 | } 26 | 27 | export class ExportService { 28 | private api: Api; 29 | 30 | constructor(api) { 31 | this.api = api; 32 | } 33 | 34 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 35 | const urlParameters = [{ key: 'identity', value: identity }]; 36 | const requestParams = { 37 | path: '/exports/:identity', 38 | method: 'get', 39 | urlParameters, 40 | 41 | payloadKey: null, 42 | fetch: null, 43 | customHeaders, 44 | }; 45 | 46 | const response = await this.api.request(requestParams); 47 | const formattedResponse: ExportResponse = { 48 | ...response.body['exports'], 49 | __response__: response.__response__, 50 | }; 51 | 52 | return formattedResponse; 53 | } 54 | 55 | public async list( 56 | requestParameters: ExportListRequest, 57 | customHeaders: Types.JsonMap = {}, 58 | ): Promise { 59 | const urlParameters = []; 60 | const requestParams = { 61 | path: '/exports', 62 | method: 'get', 63 | urlParameters, 64 | requestParameters, 65 | payloadKey: null, 66 | fetch: null, 67 | customHeaders, 68 | }; 69 | 70 | const response = await this.api.request(requestParams); 71 | const formattedResponse: ExportListResponse = { 72 | ...response.body, 73 | __response__: response.__response__, 74 | }; 75 | 76 | return formattedResponse; 77 | } 78 | 79 | public async *all( 80 | requestParameters: ExportListRequest, 81 | customHeaders: Types.JsonMap = {}, 82 | ): AsyncGenerator { 83 | let cursor = undefined; 84 | do { 85 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 86 | 87 | for (const exportdata of list.exports) { 88 | yield exportdata; 89 | } 90 | 91 | cursor = list.meta.cursors.after; 92 | } while (cursor); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/services/instalmentScheduleService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface InstalmentScheduleResponse extends Types.InstalmentSchedule, Types.APIResponse {} 7 | 8 | interface InstalmentScheduleListResponse extends Types.APIResponse { 9 | instalment_schedules: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface InstalmentScheduleCreateWithDatesRequest { 14 | // The amount to be deducted from each payment as an app fee, to be paid to the 15 | // partner integration which created the subscription, in the lowest 16 | // denomination for the currency (e.g. pence in GBP, cents in EUR). 17 | 18 | app_fee?: string; 19 | 20 | // [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. 21 | // Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are 22 | // supported. 23 | 24 | currency: Types.InstalmentScheduleCurrency; 25 | 26 | // An explicit array of instalment payments, each specifying at least an 27 | // `amount` and `charge_date`. See [create (with 28 | // dates)](#instalment-schedules-create-with-dates) 29 | 30 | instalments: Types.InstalmentScheduleInstalment[]; 31 | 32 | // Resources linked to this InstalmentSchedule. 33 | links: Types.InstalmentScheduleCreateWithDatesRequestLinks; 34 | 35 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 36 | // to 50 characters and values up to 500 characters. 37 | 38 | metadata?: Types.JsonMap; 39 | 40 | // Name of the instalment schedule, up to 100 chars. This name will also be 41 | // copied to the payments of the instalment schedule if you use schedule-based 42 | // creation. 43 | 44 | name: string; 45 | 46 | // An optional reference that will appear on your customer's bank statement. The 47 | // character limit for this reference is dependent on the scheme.
48 | // ACH - 10 characters
Autogiro - 11 49 | // characters
Bacs - 10 characters
50 | // BECS - 30 characters
BECS NZ - 12 51 | // characters
Betalingsservice - 30 characters
52 | // Faster Payments - 18 characters
PAD - 53 | // scheme doesn't offer references
PayTo - 18 54 | // characters
SEPA - 140 characters
Note that this 55 | // reference must be unique (for each merchant) for the BECS scheme as it is a 56 | // scheme requirement.

Restricted: 57 | // You can only specify a payment reference for Bacs payments (that is, when 58 | // collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise 60 | // packages.

Restricted: 61 | // You can not specify a payment reference for Faster Payments.

62 | 63 | payment_reference?: string; 64 | 65 | // On failure, automatically retry payments using [intelligent 66 | // retries](#success-intelligent-retries). Default is `false`.

Important: To be able to use intelligent 68 | // retries, Success+ needs to be enabled in [GoCardless 69 | // dashboard](https://manage.gocardless.com/success-plus).

70 | 71 | retry_if_possible?: boolean; 72 | 73 | // The total amount of the instalment schedule, defined as the sum of all 74 | // individual 75 | // payments, in the lowest denomination for the currency (e.g. pence in GBP, 76 | // cents in 77 | // EUR). If the requested payment amounts do not sum up correctly, a validation 78 | // error 79 | // will be returned. 80 | 81 | total_amount: string; 82 | } 83 | 84 | interface InstalmentScheduleCreateWithScheduleRequest { 85 | // The amount to be deducted from each payment as an app fee, to be paid to the 86 | // partner integration which created the subscription, in the lowest 87 | // denomination for the currency (e.g. pence in GBP, cents in EUR). 88 | 89 | app_fee?: string; 90 | 91 | // [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. 92 | // Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are 93 | // supported. 94 | 95 | currency: Types.InstalmentScheduleCurrency; 96 | 97 | // Frequency of the payments you want to create, together with an array of 98 | // payment 99 | // amounts to be collected, with a specified start date for the first payment. 100 | // See [create (with schedule)](#instalment-schedules-create-with-schedule) 101 | // 102 | instalments: Types.InstalmentScheduleInstalments; 103 | 104 | // Resources linked to this InstalmentSchedule. 105 | links: Types.InstalmentScheduleCreateWithScheduleRequestLinks; 106 | 107 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 108 | // to 50 characters and values up to 500 characters. 109 | 110 | metadata?: Types.JsonMap; 111 | 112 | // Name of the instalment schedule, up to 100 chars. This name will also be 113 | // copied to the payments of the instalment schedule if you use schedule-based 114 | // creation. 115 | 116 | name: string; 117 | 118 | // An optional reference that will appear on your customer's bank statement. The 119 | // character limit for this reference is dependent on the scheme.
120 | // ACH - 10 characters
Autogiro - 11 121 | // characters
Bacs - 10 characters
122 | // BECS - 30 characters
BECS NZ - 12 123 | // characters
Betalingsservice - 30 characters
124 | // Faster Payments - 18 characters
PAD - 125 | // scheme doesn't offer references
PayTo - 18 126 | // characters
SEPA - 140 characters
Note that this 127 | // reference must be unique (for each merchant) for the BECS scheme as it is a 128 | // scheme requirement.

Restricted: 129 | // You can only specify a payment reference for Bacs payments (that is, when 130 | // collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise 132 | // packages.

Restricted: 133 | // You can not specify a payment reference for Faster Payments.

134 | 135 | payment_reference?: string; 136 | 137 | // On failure, automatically retry payments using [intelligent 138 | // retries](#success-intelligent-retries). Default is `false`.

Important: To be able to use intelligent 140 | // retries, Success+ needs to be enabled in [GoCardless 141 | // dashboard](https://manage.gocardless.com/success-plus).

142 | 143 | retry_if_possible?: boolean; 144 | 145 | // The total amount of the instalment schedule, defined as the sum of all 146 | // individual 147 | // payments, in the lowest denomination for the currency (e.g. pence in GBP, 148 | // cents in 149 | // EUR). If the requested payment amounts do not sum up correctly, a validation 150 | // error 151 | // will be returned. 152 | 153 | total_amount: string; 154 | } 155 | 156 | interface InstalmentScheduleListRequest { 157 | // Cursor pointing to the start of the desired set. 158 | 159 | after?: string; 160 | 161 | // Cursor pointing to the end of the desired set. 162 | 163 | before?: string; 164 | 165 | // The creation date of this InstalmentSchedule. 166 | created_at?: Types.CreatedAtFilter; 167 | 168 | // ID of the associated [customer](#core-endpoints-customers). 169 | 170 | customer?: string; 171 | 172 | // Number of records to return. 173 | 174 | limit?: string; 175 | 176 | // ID of the associated [mandate](#core-endpoints-mandates) which the instalment 177 | // schedule will create payments against. 178 | 179 | mandate?: string; 180 | 181 | // At most five valid status values 182 | 183 | status?: Types.InstalmentScheduleStatus[]; 184 | } 185 | 186 | interface InstalmentScheduleUpdateRequest { 187 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 188 | // to 50 characters and values up to 500 characters. 189 | 190 | metadata?: Types.JsonMap; 191 | } 192 | 193 | export class InstalmentScheduleService { 194 | private api: Api; 195 | 196 | constructor(api) { 197 | this.api = api; 198 | } 199 | 200 | public async createWithDates( 201 | requestParameters: InstalmentScheduleCreateWithDatesRequest, 202 | idempotencyKey = '', 203 | customHeaders: Types.JsonMap = {}, 204 | ): Promise { 205 | const urlParameters = []; 206 | const requestParams = { 207 | path: '/instalment_schedules', 208 | method: 'post', 209 | urlParameters, 210 | requestParameters, 211 | payloadKey: 'instalment_schedules', 212 | idempotencyKey, 213 | customHeaders, 214 | fetch: async (identity) => await this.find(identity), 215 | }; 216 | 217 | const response = await this.api.request(requestParams); 218 | const formattedResponse: InstalmentScheduleResponse = { 219 | ...(response.body?.['instalment_schedules'] ?? response), 220 | __response__: response.__response__, 221 | }; 222 | 223 | return formattedResponse; 224 | } 225 | 226 | public async createWithSchedule( 227 | requestParameters: InstalmentScheduleCreateWithScheduleRequest, 228 | idempotencyKey = '', 229 | customHeaders: Types.JsonMap = {}, 230 | ): Promise { 231 | const urlParameters = []; 232 | const requestParams = { 233 | path: '/instalment_schedules', 234 | method: 'post', 235 | urlParameters, 236 | requestParameters, 237 | payloadKey: 'instalment_schedules', 238 | idempotencyKey, 239 | customHeaders, 240 | fetch: async (identity) => await this.find(identity), 241 | }; 242 | 243 | const response = await this.api.request(requestParams); 244 | const formattedResponse: InstalmentScheduleResponse = { 245 | ...(response.body?.['instalment_schedules'] ?? response), 246 | __response__: response.__response__, 247 | }; 248 | 249 | return formattedResponse; 250 | } 251 | 252 | public async list( 253 | requestParameters: InstalmentScheduleListRequest, 254 | customHeaders: Types.JsonMap = {}, 255 | ): Promise { 256 | const urlParameters = []; 257 | const requestParams = { 258 | path: '/instalment_schedules', 259 | method: 'get', 260 | urlParameters, 261 | requestParameters, 262 | payloadKey: null, 263 | fetch: null, 264 | customHeaders, 265 | }; 266 | 267 | const response = await this.api.request(requestParams); 268 | const formattedResponse: InstalmentScheduleListResponse = { 269 | ...response.body, 270 | __response__: response.__response__, 271 | }; 272 | 273 | return formattedResponse; 274 | } 275 | 276 | public async *all( 277 | requestParameters: InstalmentScheduleListRequest, 278 | customHeaders: Types.JsonMap = {}, 279 | ): AsyncGenerator { 280 | let cursor = undefined; 281 | do { 282 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 283 | 284 | for (const instalmentschedule of list.instalment_schedules) { 285 | yield instalmentschedule; 286 | } 287 | 288 | cursor = list.meta.cursors.after; 289 | } while (cursor); 290 | } 291 | 292 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 293 | const urlParameters = [{ key: 'identity', value: identity }]; 294 | const requestParams = { 295 | path: '/instalment_schedules/:identity', 296 | method: 'get', 297 | urlParameters, 298 | 299 | payloadKey: null, 300 | fetch: null, 301 | customHeaders, 302 | }; 303 | 304 | const response = await this.api.request(requestParams); 305 | const formattedResponse: InstalmentScheduleResponse = { 306 | ...response.body['instalment_schedules'], 307 | __response__: response.__response__, 308 | }; 309 | 310 | return formattedResponse; 311 | } 312 | 313 | public async update( 314 | identity: string, 315 | requestParameters: InstalmentScheduleUpdateRequest, 316 | customHeaders: Types.JsonMap = {}, 317 | ): Promise { 318 | const urlParameters = [{ key: 'identity', value: identity }]; 319 | const requestParams = { 320 | path: '/instalment_schedules/:identity', 321 | method: 'put', 322 | urlParameters, 323 | requestParameters, 324 | payloadKey: 'instalment_schedules', 325 | fetch: null, 326 | customHeaders, 327 | }; 328 | 329 | const response = await this.api.request(requestParams); 330 | const formattedResponse: InstalmentScheduleResponse = { 331 | ...response.body['instalment_schedules'], 332 | __response__: response.__response__, 333 | }; 334 | 335 | return formattedResponse; 336 | } 337 | 338 | public async cancel(identity: string, customHeaders: Types.JsonMap = {}): Promise { 339 | const urlParameters = [{ key: 'identity', value: identity }]; 340 | const requestParams = { 341 | path: '/instalment_schedules/:identity/actions/cancel', 342 | method: 'post', 343 | urlParameters, 344 | 345 | payloadKey: null, 346 | fetch: null, 347 | customHeaders, 348 | }; 349 | 350 | const response = await this.api.request(requestParams); 351 | const formattedResponse: InstalmentScheduleResponse = { 352 | ...response.body['instalment_schedules'], 353 | __response__: response.__response__, 354 | }; 355 | 356 | return formattedResponse; 357 | } 358 | } 359 | -------------------------------------------------------------------------------- /src/services/institutionService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface InstitutionResponse extends Types.Institution, Types.APIResponse {} 7 | 8 | interface InstitutionListResponse extends Types.APIResponse { 9 | institutions: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface InstitutionListRequest { 14 | // (Currently only supports UK sort-codes) The six-digit number that identifies 15 | // both the bank and the specific branch where an account is held, eg. '601234'. 16 | 17 | branch_code?: string; 18 | 19 | // [ISO 20 | // 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) 21 | // alpha-2 code. The country code of the institution. If nothing is provided, 22 | // institutions with the country code 'GB' are returned by default. 23 | 24 | country_code?: string; 25 | 26 | // The feature that institutions support. The available options include `pis`, 27 | // and `vrp_sweeping`. If nothing is provided, institutions supporting 'pis' are 28 | // returned by default. 29 | 30 | feature?: string; 31 | 32 | // The scheme that institutions support. The available options include 33 | // `faster_payments`, `sepa_credit_transfer`, and 34 | // `sepa_instant_credit_transfer`. If nothing is provided, institutions 35 | // supporting 'faster_payments' are returned by default. 36 | 37 | scheme?: string; 38 | } 39 | 40 | interface InstitutionListForBillingRequestRequest { 41 | // [ISO 42 | // 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) 43 | // alpha-2 code. The country code of the institution. If nothing is provided, 44 | // institutions with the country code 'GB' are returned by default. 45 | 46 | country_code: string; 47 | 48 | // ID(s) of the institution(s) to retrieve. More than one ID can be specified 49 | // using a comma-separated string. 50 | 51 | ids?: string[]; 52 | 53 | // Indicates whether to include temporarily disabled institutions in the 54 | // response. 55 | // If not provided or set to false, only enabled institutions will be returned. 56 | // 57 | 58 | include_disabled?: boolean; 59 | 60 | // A search substring for retrieving institution(s), based on the institution's 61 | // name. 62 | 63 | search?: string; 64 | } 65 | 66 | export class InstitutionService { 67 | private api: Api; 68 | 69 | constructor(api) { 70 | this.api = api; 71 | } 72 | 73 | public async list( 74 | requestParameters: InstitutionListRequest, 75 | customHeaders: Types.JsonMap = {}, 76 | ): Promise { 77 | const urlParameters = []; 78 | const requestParams = { 79 | path: '/institutions', 80 | method: 'get', 81 | urlParameters, 82 | requestParameters, 83 | payloadKey: null, 84 | fetch: null, 85 | customHeaders, 86 | }; 87 | 88 | const response = await this.api.request(requestParams); 89 | const formattedResponse: InstitutionListResponse = { 90 | ...response.body, 91 | __response__: response.__response__, 92 | }; 93 | 94 | return formattedResponse; 95 | } 96 | 97 | public async list_for_billing_request( 98 | requestParameters: InstitutionListForBillingRequestRequest, 99 | customHeaders: Types.JsonMap = {}, 100 | ): Promise { 101 | const urlParameters = []; 102 | const requestParams = { 103 | path: '/billing_requests/:identity/institutions', 104 | method: 'get', 105 | urlParameters, 106 | requestParameters, 107 | payloadKey: null, 108 | fetch: null, 109 | customHeaders, 110 | }; 111 | 112 | const response = await this.api.request(requestParams); 113 | const formattedResponse: InstitutionListResponse = { 114 | ...response.body, 115 | __response__: response.__response__, 116 | }; 117 | 118 | return formattedResponse; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/services/logoService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface LogoResponse extends Types.Logo, Types.APIResponse {} 7 | 8 | interface LogoListResponse extends Types.APIResponse { 9 | logos: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface LogoCreateForCreditorRequest { 14 | // Base64 encoded string. 15 | 16 | image: string; 17 | 18 | // Resources linked to this Logo. 19 | links?: Types.LogoCreateForCreditorRequestLinks; 20 | } 21 | 22 | export class LogoService { 23 | private api: Api; 24 | 25 | constructor(api) { 26 | this.api = api; 27 | } 28 | 29 | public async createForCreditor( 30 | requestParameters: LogoCreateForCreditorRequest, 31 | idempotencyKey = '', 32 | customHeaders: Types.JsonMap = {}, 33 | ): Promise { 34 | const urlParameters = []; 35 | const requestParams = { 36 | path: '/branding/logos', 37 | method: 'post', 38 | urlParameters, 39 | requestParameters, 40 | payloadKey: 'logos', 41 | idempotencyKey, 42 | customHeaders, 43 | fetch: undefined, 44 | }; 45 | 46 | const response = await this.api.request(requestParams); 47 | const formattedResponse: LogoResponse = { 48 | ...(response.body?.['logos'] ?? response), 49 | __response__: response.__response__, 50 | }; 51 | 52 | return formattedResponse; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/services/mandateImportEntryService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface MandateImportEntryResponse extends Types.MandateImportEntry, Types.APIResponse {} 7 | 8 | interface MandateImportEntryListResponse extends Types.APIResponse { 9 | mandate_import_entries: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface MandateImportEntryCreateRequest { 14 | // 15 | amendment?: Types.MandateImportEntryAmendment; 16 | 17 | // 18 | bank_account: Types.MandateImportEntryBankAccount; 19 | 20 | // 21 | customer: Types.MandateImportEntryCustomer; 22 | 23 | // Resources linked to this MandateImportEntry. 24 | links: Types.MandateImportEntryCreateRequestLinks; 25 | 26 | // 27 | mandate?: Types.MandateImportEntryMandate; 28 | 29 | // A unique identifier for this entry, which you can use (once the import has 30 | // been 31 | // processed by GoCardless) to identify the records that have been created. 32 | // Limited 33 | // to 255 characters. 34 | // 35 | 36 | record_identifier?: string; 37 | } 38 | 39 | interface MandateImportEntryListRequest { 40 | // Cursor pointing to the start of the desired set. 41 | 42 | after?: string; 43 | 44 | // Cursor pointing to the end of the desired set. 45 | 46 | before?: string; 47 | 48 | // Number of records to return. 49 | 50 | limit?: string; 51 | 52 | // Unique identifier, beginning with "IM". 53 | 54 | mandate_import: string; 55 | 56 | // One of: 57 | //
    58 | //
  • `sucessfully_processed`: the entry has been imported and the associated 59 | // records created.
  • 60 | //
  • `unsuccessfully_processed`: the entry could not be processed due to an 61 | // error, see the 'processing_errors' value
  • 62 | //
63 | 64 | status?: Types.MandateImportEntryStatus; 65 | } 66 | 67 | export class MandateImportEntryService { 68 | private api: Api; 69 | 70 | constructor(api) { 71 | this.api = api; 72 | } 73 | 74 | public async create( 75 | requestParameters: MandateImportEntryCreateRequest, 76 | idempotencyKey = '', 77 | customHeaders: Types.JsonMap = {}, 78 | ): Promise { 79 | const urlParameters = []; 80 | const requestParams = { 81 | path: '/mandate_import_entries', 82 | method: 'post', 83 | urlParameters, 84 | requestParameters, 85 | payloadKey: 'mandate_import_entries', 86 | idempotencyKey, 87 | customHeaders, 88 | fetch: undefined, 89 | }; 90 | 91 | const response = await this.api.request(requestParams); 92 | const formattedResponse: MandateImportEntryResponse = { 93 | ...(response.body?.['mandate_import_entries'] ?? response), 94 | __response__: response.__response__, 95 | }; 96 | 97 | return formattedResponse; 98 | } 99 | 100 | public async list( 101 | requestParameters: MandateImportEntryListRequest, 102 | customHeaders: Types.JsonMap = {}, 103 | ): Promise { 104 | const urlParameters = []; 105 | const requestParams = { 106 | path: '/mandate_import_entries', 107 | method: 'get', 108 | urlParameters, 109 | requestParameters, 110 | payloadKey: null, 111 | fetch: null, 112 | customHeaders, 113 | }; 114 | 115 | const response = await this.api.request(requestParams); 116 | const formattedResponse: MandateImportEntryListResponse = { 117 | ...response.body, 118 | __response__: response.__response__, 119 | }; 120 | 121 | return formattedResponse; 122 | } 123 | 124 | public async *all( 125 | requestParameters: MandateImportEntryListRequest, 126 | customHeaders: Types.JsonMap = {}, 127 | ): AsyncGenerator { 128 | let cursor = undefined; 129 | do { 130 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 131 | 132 | for (const mandateimportentry of list.mandate_import_entries) { 133 | yield mandateimportentry; 134 | } 135 | 136 | cursor = list.meta.cursors.after; 137 | } while (cursor); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/services/mandateImportService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface MandateImportResponse extends Types.MandateImport, Types.APIResponse {} 7 | 8 | interface MandateImportListResponse extends Types.APIResponse { 9 | mandate_imports: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface MandateImportCreateRequest { 14 | // Resources linked to this MandateImport. 15 | links?: Types.MandateImportCreateRequestLinks; 16 | 17 | // A bank payment scheme. Currently "ach", "autogiro", "bacs", "becs", 18 | // "becs_nz", "betalingsservice", "faster_payments", "pad", "pay_to" and 19 | // "sepa_core" are supported. 20 | 21 | scheme: Types.MandateImportScheme; 22 | } 23 | 24 | export class MandateImportService { 25 | private api: Api; 26 | 27 | constructor(api) { 28 | this.api = api; 29 | } 30 | 31 | public async create( 32 | requestParameters: MandateImportCreateRequest, 33 | idempotencyKey = '', 34 | customHeaders: Types.JsonMap = {}, 35 | ): Promise { 36 | const urlParameters = []; 37 | const requestParams = { 38 | path: '/mandate_imports', 39 | method: 'post', 40 | urlParameters, 41 | requestParameters, 42 | payloadKey: 'mandate_imports', 43 | idempotencyKey, 44 | customHeaders, 45 | fetch: async (identity) => await this.find(identity), 46 | }; 47 | 48 | const response = await this.api.request(requestParams); 49 | const formattedResponse: MandateImportResponse = { 50 | ...(response.body?.['mandate_imports'] ?? response), 51 | __response__: response.__response__, 52 | }; 53 | 54 | return formattedResponse; 55 | } 56 | 57 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 58 | const urlParameters = [{ key: 'identity', value: identity }]; 59 | const requestParams = { 60 | path: '/mandate_imports/:identity', 61 | method: 'get', 62 | urlParameters, 63 | 64 | payloadKey: null, 65 | fetch: null, 66 | customHeaders, 67 | }; 68 | 69 | const response = await this.api.request(requestParams); 70 | const formattedResponse: MandateImportResponse = { 71 | ...response.body['mandate_imports'], 72 | __response__: response.__response__, 73 | }; 74 | 75 | return formattedResponse; 76 | } 77 | 78 | public async submit(identity: string, customHeaders: Types.JsonMap = {}): Promise { 79 | const urlParameters = [{ key: 'identity', value: identity }]; 80 | const requestParams = { 81 | path: '/mandate_imports/:identity/actions/submit', 82 | method: 'post', 83 | urlParameters, 84 | 85 | payloadKey: null, 86 | fetch: null, 87 | customHeaders, 88 | }; 89 | 90 | const response = await this.api.request(requestParams); 91 | const formattedResponse: MandateImportResponse = { 92 | ...response.body['mandate_imports'], 93 | __response__: response.__response__, 94 | }; 95 | 96 | return formattedResponse; 97 | } 98 | 99 | public async cancel(identity: string, customHeaders: Types.JsonMap = {}): Promise { 100 | const urlParameters = [{ key: 'identity', value: identity }]; 101 | const requestParams = { 102 | path: '/mandate_imports/:identity/actions/cancel', 103 | method: 'post', 104 | urlParameters, 105 | 106 | payloadKey: null, 107 | fetch: null, 108 | customHeaders, 109 | }; 110 | 111 | const response = await this.api.request(requestParams); 112 | const formattedResponse: MandateImportResponse = { 113 | ...response.body['mandate_imports'], 114 | __response__: response.__response__, 115 | }; 116 | 117 | return formattedResponse; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/services/mandatePdfService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface MandatePdfResponse extends Types.MandatePdf, Types.APIResponse {} 7 | 8 | interface MandatePdfListResponse extends Types.APIResponse { 9 | mandate_pdfs: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface MandatePdfCreateRequest { 14 | // Name of the account holder, as known by the bank. Usually this matches the 15 | // name of the [customer](#core-endpoints-customers). This field cannot exceed 16 | // 18 characters. 17 | 18 | account_holder_name?: string; 19 | 20 | // Bank account number - see [local details](#appendix-local-bank-details) for 21 | // more information. Alternatively you can provide an `iban`. 22 | 23 | account_number?: string; 24 | 25 | // Bank account type. Required for USD-denominated bank accounts. Must not be 26 | // provided for bank accounts in other currencies. See [local 27 | // details](#local-bank-details-united-states) for more information. 28 | 29 | account_type?: Types.MandatePdfAccountType; 30 | 31 | // The first line of the customer's address. 32 | 33 | address_line1?: string; 34 | 35 | // The second line of the customer's address. 36 | 37 | address_line2?: string; 38 | 39 | // The third line of the customer's address. 40 | 41 | address_line3?: string; 42 | 43 | // Bank code - see [local details](#appendix-local-bank-details) for more 44 | // information. Alternatively you can provide an `iban`. 45 | 46 | bank_code?: string; 47 | 48 | // SWIFT BIC. Will be derived automatically if a valid `iban` or [local 49 | // details](#appendix-local-bank-details) are provided. 50 | 51 | bic?: string; 52 | 53 | // Branch code - see [local details](#appendix-local-bank-details) for more 54 | // information. Alternatively you can provide an `iban`. 55 | 56 | branch_code?: string; 57 | 58 | // The city of the customer's address. 59 | 60 | city?: string; 61 | 62 | // The customer's company name. Used to populate the "Customer Name or Company 63 | // name" field on the PDF. 64 | 65 | company_name?: string; 66 | 67 | // [ISO 68 | // 3166-1](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) 69 | // alpha-2 code. Required if providing local details. 70 | 71 | country_code?: string; 72 | 73 | // For Danish customers only. The civic/company number (CPR or CVR) of the 74 | // customer. Should only be supplied for Betalingsservice mandates. 75 | 76 | danish_identity_number?: string; 77 | 78 | // The customer's family name (i.e. last name). Used to populate the "Customer 79 | // Name or Company name" field on the PDF. Ignored if `company_name` is 80 | // provided. 81 | 82 | family_name?: string; 83 | 84 | // The customer's given name (i.e. first name). Used to populate the "Customer 85 | // Name or Company name" field on the PDF. Ignored if `company_name` is 86 | // provided. 87 | 88 | given_name?: string; 89 | 90 | // International Bank Account Number. Alternatively you can provide [local 91 | // details](#appendix-local-bank-details). IBANs cannot be provided for Autogiro 92 | // mandates. 93 | 94 | iban?: string; 95 | 96 | // Resources linked to this MandatePdf. 97 | links?: Types.MandatePdfCreateRequestLinks; 98 | 99 | // Unique 6 to 18 character reference. This may be left blank at the point of 100 | // signing. 101 | 102 | mandate_reference?: string; 103 | 104 | // For American customers only. IP address of the computer used by the customer 105 | // to set up the mandate. This is required in order to create compliant Mandate 106 | // PDFs according to the ACH scheme rules. 107 | 108 | payer_ip_address?: string; 109 | 110 | // The customer phone number. Should only be provided for BECS NZ mandates. 111 | 112 | phone_number?: string; 113 | 114 | // The customer's postal code. 115 | 116 | postal_code?: string; 117 | 118 | // The customer's address region, county or department. For US customers a 2 119 | // letter [ISO3166-2:US](https://en.wikipedia.org/wiki/ISO_3166-2:US) state code 120 | // is required (e.g. `CA` for California). 121 | 122 | region?: string; 123 | 124 | // Direct Debit scheme. Can be supplied or automatically detected from the bank 125 | // account details provided. If you do not provide a scheme, you must provide 126 | // either a mandate, an `iban`, or [local details](#appendix-local-bank-details) 127 | // including a `country_code`. 128 | 129 | scheme?: string; 130 | 131 | // If provided, a form will be generated with this date and no signature field. 132 | 133 | signature_date?: string; 134 | 135 | // For American customers only. Subscription amount being authorised by the 136 | // mandate. In the lowest denomination for the currency (cents in USD). Is 137 | // required if `subscription_frequency` has been provided. 138 | 139 | subscription_amount?: string; 140 | 141 | // For American customers only. Frequency of the subscription being authorised 142 | // by the mandate. One of `weekly`, `monthly` or `yearly`. Is required if 143 | // `subscription_amount` has been provided. 144 | 145 | subscription_frequency?: Types.MandatePdfSubscriptionFrequency; 146 | 147 | // For Swedish customers only. The civic/company number (personnummer, 148 | // samordningsnummer, or organisationsnummer) of the customer. Should only be 149 | // supplied for Autogiro mandates. 150 | 151 | swedish_identity_number?: string; 152 | } 153 | 154 | export class MandatePdfService { 155 | private api: Api; 156 | 157 | constructor(api) { 158 | this.api = api; 159 | } 160 | 161 | public async create( 162 | requestParameters: MandatePdfCreateRequest, 163 | idempotencyKey = '', 164 | customHeaders: Types.JsonMap = {}, 165 | ): Promise { 166 | const urlParameters = []; 167 | const requestParams = { 168 | path: '/mandate_pdfs', 169 | method: 'post', 170 | urlParameters, 171 | requestParameters, 172 | payloadKey: 'mandate_pdfs', 173 | idempotencyKey, 174 | customHeaders, 175 | fetch: undefined, 176 | }; 177 | 178 | const response = await this.api.request(requestParams); 179 | const formattedResponse: MandatePdfResponse = { 180 | ...(response.body?.['mandate_pdfs'] ?? response), 181 | __response__: response.__response__, 182 | }; 183 | 184 | return formattedResponse; 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/services/mandateService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface MandateResponse extends Types.Mandate, Types.APIResponse {} 7 | 8 | interface MandateListResponse extends Types.APIResponse { 9 | mandates: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface MandateCreateRequest { 14 | // This field is ACH specific, sometimes referred to as [SEC 15 | // code](https://www.moderntreasury.com/learn/sec-codes). 16 | // 17 | // This is the way that the payer gives authorisation to the merchant. 18 | // web: Authorisation is Internet Initiated or via Mobile Entry (maps to SEC 19 | // code: WEB) 20 | // telephone: Authorisation is provided orally over telephone (maps to SEC 21 | // code: TEL) 22 | // paper: Authorisation is provided in writing and signed, or similarly 23 | // authenticated (maps to SEC code: PPD) 24 | // 25 | 26 | authorisation_source?: Types.MandateAuthorisationSource; 27 | 28 | // Resources linked to this Mandate. 29 | links: Types.MandateCreateRequestLinks; 30 | 31 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 32 | // to 50 characters and values up to 500 characters. 33 | 34 | metadata?: Types.JsonMap; 35 | 36 | // For ACH customers only. Required for ACH customers. A string containing the 37 | // IP address of the payer to whom the mandate belongs (i.e. as a result of 38 | // their completion of a mandate setup flow in their browser). 39 | // 40 | // Not required for creating offline mandates where `authorisation_source` is 41 | // set to telephone or paper. 42 | // 43 | 44 | payer_ip_address?: string; 45 | 46 | // Unique reference. Different schemes have different length and [character 47 | // set](#appendix-character-sets) requirements. GoCardless will generate a 48 | // unique reference satisfying the different scheme requirements if this field 49 | // is left blank. 50 | 51 | reference?: string; 52 | 53 | // Bank payment scheme to which this mandate and 54 | // associated payments are submitted. Can be supplied or automatically detected 55 | // from the customer's bank account. 56 | 57 | scheme?: string; 58 | } 59 | 60 | interface MandateListRequest { 61 | // Cursor pointing to the start of the desired set. 62 | 63 | after?: string; 64 | 65 | // Cursor pointing to the end of the desired set. 66 | 67 | before?: string; 68 | 69 | // The creation date of this Mandate. 70 | created_at?: Types.CreatedAtFilter; 71 | 72 | // ID of a [creditor](#core-endpoints-creditors). If specified, this endpoint 73 | // will return all mandates for the given creditor. Cannot be used in 74 | // conjunction with `customer` or `customer_bank_account` 75 | 76 | creditor?: string; 77 | 78 | // ID of a [customer](#core-endpoints-customers). If specified, this endpoint 79 | // will return all mandates for the given customer. Cannot be used in 80 | // conjunction with `customer_bank_account` or `creditor` 81 | 82 | customer?: string; 83 | 84 | // ID of a [customer bank account](#core-endpoints-customer-bank-accounts). If 85 | // specified, this endpoint will return all mandates for the given bank account. 86 | // Cannot be used in conjunction with `customer` or `creditor` 87 | 88 | customer_bank_account?: string; 89 | 90 | // Number of records to return. 91 | 92 | limit?: string; 93 | 94 | // Mandate type 95 | 96 | mandate_type?: string; 97 | 98 | // Unique reference. Different schemes have different length and [character 99 | // set](#appendix-character-sets) requirements. GoCardless will generate a 100 | // unique reference satisfying the different scheme requirements if this field 101 | // is left blank. 102 | 103 | reference?: string; 104 | 105 | // Scheme you'd like to retrieve mandates for 106 | 107 | scheme?: string[]; 108 | 109 | // At most four valid status values 110 | 111 | status?: Types.MandateStatus[]; 112 | } 113 | 114 | interface MandateUpdateRequest { 115 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 116 | // to 50 characters and values up to 500 characters. 117 | 118 | metadata?: Types.JsonMap; 119 | } 120 | 121 | interface MandateCancelRequest { 122 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 123 | // to 50 characters and values up to 500 characters. 124 | 125 | metadata?: Types.JsonMap; 126 | } 127 | 128 | interface MandateReinstateRequest { 129 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 130 | // to 50 characters and values up to 500 characters. 131 | 132 | metadata?: Types.JsonMap; 133 | } 134 | 135 | export class MandateService { 136 | private api: Api; 137 | 138 | constructor(api) { 139 | this.api = api; 140 | } 141 | 142 | public async create( 143 | requestParameters: MandateCreateRequest, 144 | idempotencyKey = '', 145 | customHeaders: Types.JsonMap = {}, 146 | ): Promise { 147 | const urlParameters = []; 148 | const requestParams = { 149 | path: '/mandates', 150 | method: 'post', 151 | urlParameters, 152 | requestParameters, 153 | payloadKey: 'mandates', 154 | idempotencyKey, 155 | customHeaders, 156 | fetch: async (identity) => await this.find(identity), 157 | }; 158 | 159 | const response = await this.api.request(requestParams); 160 | const formattedResponse: MandateResponse = { 161 | ...(response.body?.['mandates'] ?? response), 162 | __response__: response.__response__, 163 | }; 164 | 165 | return formattedResponse; 166 | } 167 | 168 | public async list( 169 | requestParameters: MandateListRequest, 170 | customHeaders: Types.JsonMap = {}, 171 | ): Promise { 172 | const urlParameters = []; 173 | const requestParams = { 174 | path: '/mandates', 175 | method: 'get', 176 | urlParameters, 177 | requestParameters, 178 | payloadKey: null, 179 | fetch: null, 180 | customHeaders, 181 | }; 182 | 183 | const response = await this.api.request(requestParams); 184 | const formattedResponse: MandateListResponse = { 185 | ...response.body, 186 | __response__: response.__response__, 187 | }; 188 | 189 | return formattedResponse; 190 | } 191 | 192 | public async *all( 193 | requestParameters: MandateListRequest, 194 | customHeaders: Types.JsonMap = {}, 195 | ): AsyncGenerator { 196 | let cursor = undefined; 197 | do { 198 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 199 | 200 | for (const mandate of list.mandates) { 201 | yield mandate; 202 | } 203 | 204 | cursor = list.meta.cursors.after; 205 | } while (cursor); 206 | } 207 | 208 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 209 | const urlParameters = [{ key: 'identity', value: identity }]; 210 | const requestParams = { 211 | path: '/mandates/:identity', 212 | method: 'get', 213 | urlParameters, 214 | 215 | payloadKey: null, 216 | fetch: null, 217 | customHeaders, 218 | }; 219 | 220 | const response = await this.api.request(requestParams); 221 | const formattedResponse: MandateResponse = { 222 | ...response.body['mandates'], 223 | __response__: response.__response__, 224 | }; 225 | 226 | return formattedResponse; 227 | } 228 | 229 | public async update( 230 | identity: string, 231 | requestParameters: MandateUpdateRequest, 232 | customHeaders: Types.JsonMap = {}, 233 | ): Promise { 234 | const urlParameters = [{ key: 'identity', value: identity }]; 235 | const requestParams = { 236 | path: '/mandates/:identity', 237 | method: 'put', 238 | urlParameters, 239 | requestParameters, 240 | payloadKey: 'mandates', 241 | fetch: null, 242 | customHeaders, 243 | }; 244 | 245 | const response = await this.api.request(requestParams); 246 | const formattedResponse: MandateResponse = { 247 | ...response.body['mandates'], 248 | __response__: response.__response__, 249 | }; 250 | 251 | return formattedResponse; 252 | } 253 | 254 | public async cancel( 255 | identity: string, 256 | requestParameters: MandateCancelRequest, 257 | customHeaders: Types.JsonMap = {}, 258 | ): Promise { 259 | const urlParameters = [{ key: 'identity', value: identity }]; 260 | const requestParams = { 261 | path: '/mandates/:identity/actions/cancel', 262 | method: 'post', 263 | urlParameters, 264 | requestParameters, 265 | payloadKey: null, 266 | fetch: null, 267 | customHeaders, 268 | }; 269 | 270 | const response = await this.api.request(requestParams); 271 | const formattedResponse: MandateResponse = { 272 | ...response.body['mandates'], 273 | __response__: response.__response__, 274 | }; 275 | 276 | return formattedResponse; 277 | } 278 | 279 | public async reinstate( 280 | identity: string, 281 | requestParameters: MandateReinstateRequest, 282 | customHeaders: Types.JsonMap = {}, 283 | ): Promise { 284 | const urlParameters = [{ key: 'identity', value: identity }]; 285 | const requestParams = { 286 | path: '/mandates/:identity/actions/reinstate', 287 | method: 'post', 288 | urlParameters, 289 | requestParameters, 290 | payloadKey: null, 291 | fetch: null, 292 | customHeaders, 293 | }; 294 | 295 | const response = await this.api.request(requestParams); 296 | const formattedResponse: MandateResponse = { 297 | ...response.body['mandates'], 298 | __response__: response.__response__, 299 | }; 300 | 301 | return formattedResponse; 302 | } 303 | } 304 | -------------------------------------------------------------------------------- /src/services/negativeBalanceLimitService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface NegativeBalanceLimitResponse extends Types.NegativeBalanceLimit, Types.APIResponse {} 7 | 8 | interface NegativeBalanceLimitListResponse extends Types.APIResponse { 9 | negative_balance_limits: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface NegativeBalanceLimitListRequest { 14 | // Cursor pointing to the start of the desired set. 15 | 16 | after?: string; 17 | 18 | // Cursor pointing to the end of the desired set. 19 | 20 | before?: string; 21 | 22 | // Unique identifier, beginning with "CR". 23 | 24 | creditor?: string; 25 | 26 | // [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. 27 | // Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are 28 | // supported. 29 | 30 | currency?: Types.NegativeBalanceLimitCurrency; 31 | 32 | // Number of records to return. 33 | 34 | limit?: string; 35 | } 36 | 37 | export class NegativeBalanceLimitService { 38 | private api: Api; 39 | 40 | constructor(api) { 41 | this.api = api; 42 | } 43 | 44 | public async list( 45 | requestParameters: NegativeBalanceLimitListRequest, 46 | customHeaders: Types.JsonMap = {}, 47 | ): Promise { 48 | const urlParameters = []; 49 | const requestParams = { 50 | path: '/negative_balance_limits', 51 | method: 'get', 52 | urlParameters, 53 | requestParameters, 54 | payloadKey: null, 55 | fetch: null, 56 | customHeaders, 57 | }; 58 | 59 | const response = await this.api.request(requestParams); 60 | const formattedResponse: NegativeBalanceLimitListResponse = { 61 | ...response.body, 62 | __response__: response.__response__, 63 | }; 64 | 65 | return formattedResponse; 66 | } 67 | 68 | public async *all( 69 | requestParameters: NegativeBalanceLimitListRequest, 70 | customHeaders: Types.JsonMap = {}, 71 | ): AsyncGenerator { 72 | let cursor = undefined; 73 | do { 74 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 75 | 76 | for (const negativebalancelimit of list.negative_balance_limits) { 77 | yield negativebalancelimit; 78 | } 79 | 80 | cursor = list.meta.cursors.after; 81 | } while (cursor); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/services/outboundPaymentService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface OutboundPaymentResponse extends Types.OutboundPayment, Types.APIResponse {} 7 | 8 | interface OutboundPaymentListResponse extends Types.APIResponse { 9 | outbound_payments: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface OutboundPaymentCreateRequest { 14 | // Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents 15 | // in EUR). 16 | 17 | amount: number; 18 | 19 | // A human-readable description of the outbound payment 20 | 21 | description?: string; 22 | 23 | // A future date on which the outbound payment should be sent. 24 | // If not specified, the payment will be sent as soon as possible. 25 | 26 | execution_date?: string; 27 | 28 | // Resources linked to this OutboundPayment. 29 | links: Types.OutboundPaymentCreateRequestLinks; 30 | 31 | // Key-value store of custom data. Up to 3 keys are permitted, with 32 | // key names up to 50 characters and values up to 500 characters. 33 | 34 | metadata?: Types.JsonMap; 35 | 36 | // Bank payment scheme to process the outbound payment. Currently only 37 | // "faster_payments" (GBP) is supported. 38 | 39 | scheme: string; 40 | } 41 | 42 | interface OutboundPaymentWithdrawRequest { 43 | // Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents 44 | // in EUR). 45 | 46 | amount: number; 47 | 48 | // A human-readable description of the outbound payment 49 | 50 | description?: string; 51 | 52 | // A future date on which the outbound payment should be sent. 53 | // If not specified, the payment will be sent as soon as possible. 54 | 55 | execution_date?: string; 56 | 57 | // Resources linked to this OutboundPayment. 58 | links?: Types.OutboundPaymentWithdrawRequestLinks; 59 | 60 | // Key-value store of custom data. Up to 3 keys are permitted, with 61 | // key names up to 50 characters and values up to 500 characters. 62 | 63 | metadata?: Types.JsonMap; 64 | 65 | // Bank payment scheme to process the outbound payment. Currently only 66 | // "faster_payments" (GBP) is supported. 67 | 68 | scheme: string; 69 | } 70 | 71 | interface OutboundPaymentCancelRequest { 72 | // Key-value store of custom data. Up to 3 keys are permitted, with 73 | // key names up to 50 characters and values up to 500 characters. 74 | 75 | metadata?: Types.JsonMap; 76 | } 77 | 78 | interface OutboundPaymentListRequest { 79 | // Cursor pointing to the start of the desired set. 80 | 81 | after?: string; 82 | 83 | // Cursor pointing to the end of the desired set. 84 | 85 | before?: string; 86 | 87 | // The beginning of query period 88 | 89 | created_from?: string; 90 | 91 | // The end of query period 92 | 93 | created_to?: string; 94 | 95 | // Number of records to return. 96 | 97 | limit?: string; 98 | 99 | // One of: 100 | //
    101 | //
  • `verifying`: The payment has been 102 | // [created](#outbound-payments-create-an-outbound-payment) and the verification 103 | // process has begun.
  • 104 | //
  • `pending_approval`: The payment is awaiting 105 | // [approval](#outbound-payments-approve-an-outbound-payment).
  • 106 | //
  • `scheduled`: The payment has passed verification & 107 | // [approval](#outbound-payments-approve-an-outbound-payment), but processing 108 | // has not yet begun.
  • 109 | //
  • `executing`: The execution date has arrived and the payment has been 110 | // placed in queue for processing.
  • 111 | //
  • `executed`: The payment has been accepted by the scheme and is now on its 112 | // way to the recipient.
  • 113 | //
  • `cancelled`: The payment has been 114 | // [cancelled](#outbound-payments-cancel-an-outbound-payment) or was not 115 | // [approved](#outbound-payments-approve-an-outbound-payment) on time.
  • 116 | //
  • `failed`: The payment was not sent, usually due to an error while or 117 | // after executing.
  • 118 | //
119 | 120 | status?: Types.OutboundPaymentStatus; 121 | } 122 | 123 | interface OutboundPaymentUpdateRequest { 124 | // Key-value store of custom data. Up to 3 keys are permitted, with 125 | // key names up to 50 characters and values up to 500 characters. 126 | 127 | metadata?: Types.JsonMap; 128 | } 129 | 130 | export class OutboundPaymentService { 131 | private api: Api; 132 | 133 | constructor(api) { 134 | this.api = api; 135 | } 136 | 137 | public async create( 138 | requestParameters: OutboundPaymentCreateRequest, 139 | idempotencyKey = '', 140 | customHeaders: Types.JsonMap = {}, 141 | ): Promise { 142 | const urlParameters = []; 143 | const requestParams = { 144 | path: '/outbound_payments', 145 | method: 'post', 146 | urlParameters, 147 | requestParameters, 148 | payloadKey: 'outbound_payments', 149 | idempotencyKey, 150 | customHeaders, 151 | fetch: async (identity) => await this.find(identity), 152 | }; 153 | 154 | const response = await this.api.request(requestParams); 155 | const formattedResponse: OutboundPaymentResponse = { 156 | ...(response.body?.['outbound_payments'] ?? response), 157 | __response__: response.__response__, 158 | }; 159 | 160 | return formattedResponse; 161 | } 162 | 163 | public async withdraw( 164 | identity: string, 165 | requestParameters: OutboundPaymentWithdrawRequest, 166 | customHeaders: Types.JsonMap = {}, 167 | ): Promise { 168 | const urlParameters = []; 169 | const requestParams = { 170 | path: '/outbound_payments/withdrawal', 171 | method: 'post', 172 | urlParameters, 173 | requestParameters, 174 | payloadKey: null, 175 | fetch: null, 176 | customHeaders, 177 | }; 178 | 179 | const response = await this.api.request(requestParams); 180 | const formattedResponse: OutboundPaymentResponse = { 181 | ...response.body['outbound_payments'], 182 | __response__: response.__response__, 183 | }; 184 | 185 | return formattedResponse; 186 | } 187 | 188 | public async cancel( 189 | identity: string, 190 | requestParameters: OutboundPaymentCancelRequest, 191 | customHeaders: Types.JsonMap = {}, 192 | ): Promise { 193 | const urlParameters = [{ key: 'identity', value: identity }]; 194 | const requestParams = { 195 | path: '/outbound_payments/:identity/actions/cancel', 196 | method: 'post', 197 | urlParameters, 198 | requestParameters, 199 | payloadKey: null, 200 | fetch: null, 201 | customHeaders, 202 | }; 203 | 204 | const response = await this.api.request(requestParams); 205 | const formattedResponse: OutboundPaymentResponse = { 206 | ...response.body['outbound_payments'], 207 | __response__: response.__response__, 208 | }; 209 | 210 | return formattedResponse; 211 | } 212 | 213 | public async approve(identity: string, customHeaders: Types.JsonMap = {}): Promise { 214 | const urlParameters = [{ key: 'identity', value: identity }]; 215 | const requestParams = { 216 | path: '/outbound_payments/:identity/actions/approve', 217 | method: 'post', 218 | urlParameters, 219 | 220 | payloadKey: null, 221 | fetch: null, 222 | customHeaders, 223 | }; 224 | 225 | const response = await this.api.request(requestParams); 226 | const formattedResponse: OutboundPaymentResponse = { 227 | ...response.body['outbound_payments'], 228 | __response__: response.__response__, 229 | }; 230 | 231 | return formattedResponse; 232 | } 233 | 234 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 235 | const urlParameters = [{ key: 'identity', value: identity }]; 236 | const requestParams = { 237 | path: '/outbound_payments/:identity', 238 | method: 'get', 239 | urlParameters, 240 | 241 | payloadKey: null, 242 | fetch: null, 243 | customHeaders, 244 | }; 245 | 246 | const response = await this.api.request(requestParams); 247 | const formattedResponse: OutboundPaymentResponse = { 248 | ...response.body['outbound_payments'], 249 | __response__: response.__response__, 250 | }; 251 | 252 | return formattedResponse; 253 | } 254 | 255 | public async list( 256 | requestParameters: OutboundPaymentListRequest, 257 | customHeaders: Types.JsonMap = {}, 258 | ): Promise { 259 | const urlParameters = []; 260 | const requestParams = { 261 | path: '/outbound_payments', 262 | method: 'get', 263 | urlParameters, 264 | requestParameters, 265 | payloadKey: null, 266 | fetch: null, 267 | customHeaders, 268 | }; 269 | 270 | const response = await this.api.request(requestParams); 271 | const formattedResponse: OutboundPaymentListResponse = { 272 | ...response.body, 273 | __response__: response.__response__, 274 | }; 275 | 276 | return formattedResponse; 277 | } 278 | 279 | public async *all( 280 | requestParameters: OutboundPaymentListRequest, 281 | customHeaders: Types.JsonMap = {}, 282 | ): AsyncGenerator { 283 | let cursor = undefined; 284 | do { 285 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 286 | 287 | for (const outboundpayment of list.outbound_payments) { 288 | yield outboundpayment; 289 | } 290 | 291 | cursor = list.meta.cursors.after; 292 | } while (cursor); 293 | } 294 | 295 | public async update( 296 | identity: string, 297 | requestParameters: OutboundPaymentUpdateRequest, 298 | customHeaders: Types.JsonMap = {}, 299 | ): Promise { 300 | const urlParameters = [{ key: 'identity', value: identity }]; 301 | const requestParams = { 302 | path: '/outbound_payments/:identity', 303 | method: 'put', 304 | urlParameters, 305 | requestParameters, 306 | payloadKey: 'outbound_payments', 307 | fetch: null, 308 | customHeaders, 309 | }; 310 | 311 | const response = await this.api.request(requestParams); 312 | const formattedResponse: OutboundPaymentResponse = { 313 | ...response.body['outbound_payments'], 314 | __response__: response.__response__, 315 | }; 316 | 317 | return formattedResponse; 318 | } 319 | } 320 | -------------------------------------------------------------------------------- /src/services/payerAuthorisationService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface PayerAuthorisationResponse extends Types.PayerAuthorisation, Types.APIResponse {} 7 | 8 | interface PayerAuthorisationListResponse extends Types.APIResponse { 9 | payer_authorisations: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface PayerAuthorisationCreateRequest { 14 | // All details required for the creation of a 15 | // [Customer Bank Account](#core-endpoints-customer-bank-accounts). 16 | bank_account: Types.PayerAuthorisationBankAccount; 17 | 18 | // All details required for the creation of a 19 | // [Customer](#core-endpoints-customers). 20 | customer: Types.PayerAuthorisationCustomer; 21 | 22 | // All details required for the creation of a 23 | // [Mandate](#core-endpoints-mandates). 24 | mandate: Types.PayerAuthorisationMandate; 25 | } 26 | 27 | interface PayerAuthorisationUpdateRequest { 28 | // All details required for the creation of a 29 | // [Customer Bank Account](#core-endpoints-customer-bank-accounts). 30 | bank_account: Types.PayerAuthorisationBankAccount; 31 | 32 | // All details required for the creation of a 33 | // [Customer](#core-endpoints-customers). 34 | customer: Types.PayerAuthorisationCustomer; 35 | 36 | // All details required for the creation of a 37 | // [Mandate](#core-endpoints-mandates). 38 | mandate: Types.PayerAuthorisationMandate; 39 | } 40 | 41 | export class PayerAuthorisationService { 42 | private api: Api; 43 | 44 | constructor(api) { 45 | this.api = api; 46 | } 47 | 48 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 49 | const urlParameters = [{ key: 'identity', value: identity }]; 50 | const requestParams = { 51 | path: '/payer_authorisations/:identity', 52 | method: 'get', 53 | urlParameters, 54 | 55 | payloadKey: null, 56 | fetch: null, 57 | customHeaders, 58 | }; 59 | 60 | const response = await this.api.request(requestParams); 61 | const formattedResponse: PayerAuthorisationResponse = { 62 | ...response.body['payer_authorisations'], 63 | __response__: response.__response__, 64 | }; 65 | 66 | return formattedResponse; 67 | } 68 | 69 | public async create( 70 | requestParameters: PayerAuthorisationCreateRequest, 71 | idempotencyKey = '', 72 | customHeaders: Types.JsonMap = {}, 73 | ): Promise { 74 | const urlParameters = []; 75 | const requestParams = { 76 | path: '/payer_authorisations', 77 | method: 'post', 78 | urlParameters, 79 | requestParameters, 80 | payloadKey: 'payer_authorisations', 81 | idempotencyKey, 82 | customHeaders, 83 | fetch: async (identity) => await this.find(identity), 84 | }; 85 | 86 | const response = await this.api.request(requestParams); 87 | const formattedResponse: PayerAuthorisationResponse = { 88 | ...(response.body?.['payer_authorisations'] ?? response), 89 | __response__: response.__response__, 90 | }; 91 | 92 | return formattedResponse; 93 | } 94 | 95 | public async update( 96 | identity: string, 97 | requestParameters: PayerAuthorisationUpdateRequest, 98 | customHeaders: Types.JsonMap = {}, 99 | ): Promise { 100 | const urlParameters = [{ key: 'identity', value: identity }]; 101 | const requestParams = { 102 | path: '/payer_authorisations/:identity', 103 | method: 'put', 104 | urlParameters, 105 | requestParameters, 106 | payloadKey: 'payer_authorisations', 107 | fetch: null, 108 | customHeaders, 109 | }; 110 | 111 | const response = await this.api.request(requestParams); 112 | const formattedResponse: PayerAuthorisationResponse = { 113 | ...response.body['payer_authorisations'], 114 | __response__: response.__response__, 115 | }; 116 | 117 | return formattedResponse; 118 | } 119 | 120 | public async submit(identity: string, customHeaders: Types.JsonMap = {}): Promise { 121 | const urlParameters = [{ key: 'identity', value: identity }]; 122 | const requestParams = { 123 | path: '/payer_authorisations/:identity/actions/submit', 124 | method: 'post', 125 | urlParameters, 126 | 127 | payloadKey: null, 128 | fetch: null, 129 | customHeaders, 130 | }; 131 | 132 | const response = await this.api.request(requestParams); 133 | const formattedResponse: PayerAuthorisationResponse = { 134 | ...response.body['payer_authorisations'], 135 | __response__: response.__response__, 136 | }; 137 | 138 | return formattedResponse; 139 | } 140 | 141 | public async confirm(identity: string, customHeaders: Types.JsonMap = {}): Promise { 142 | const urlParameters = [{ key: 'identity', value: identity }]; 143 | const requestParams = { 144 | path: '/payer_authorisations/:identity/actions/confirm', 145 | method: 'post', 146 | urlParameters, 147 | 148 | payloadKey: null, 149 | fetch: null, 150 | customHeaders, 151 | }; 152 | 153 | const response = await this.api.request(requestParams); 154 | const formattedResponse: PayerAuthorisationResponse = { 155 | ...response.body['payer_authorisations'], 156 | __response__: response.__response__, 157 | }; 158 | 159 | return formattedResponse; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/services/payerThemeService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface PayerThemeResponse extends Types.PayerTheme, Types.APIResponse {} 7 | 8 | interface PayerThemeListResponse extends Types.APIResponse { 9 | payer_themes: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface PayerThemeCreateForCreditorRequest { 14 | // Colour for buttons background (hexcode) 15 | 16 | button_background_colour?: string; 17 | 18 | // Colour for content box border (hexcode) 19 | 20 | content_box_border_colour?: string; 21 | 22 | // Colour for header background (hexcode) 23 | 24 | header_background_colour?: string; 25 | 26 | // Colour for text links (hexcode) 27 | 28 | link_text_colour?: string; 29 | 30 | // Resources linked to this PayerTheme. 31 | links?: Types.PayerThemeCreateForCreditorRequestLinks; 32 | } 33 | 34 | export class PayerThemeService { 35 | private api: Api; 36 | 37 | constructor(api) { 38 | this.api = api; 39 | } 40 | 41 | public async createForCreditor( 42 | requestParameters: PayerThemeCreateForCreditorRequest, 43 | idempotencyKey = '', 44 | customHeaders: Types.JsonMap = {}, 45 | ): Promise { 46 | const urlParameters = []; 47 | const requestParams = { 48 | path: '/branding/payer_themes', 49 | method: 'post', 50 | urlParameters, 51 | requestParameters, 52 | payloadKey: 'payer_themes', 53 | idempotencyKey, 54 | customHeaders, 55 | fetch: undefined, 56 | }; 57 | 58 | const response = await this.api.request(requestParams); 59 | const formattedResponse: PayerThemeResponse = { 60 | ...(response.body?.['payer_themes'] ?? response), 61 | __response__: response.__response__, 62 | }; 63 | 64 | return formattedResponse; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/services/paymentService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface PaymentResponse extends Types.Payment, Types.APIResponse {} 7 | 8 | interface PaymentListResponse extends Types.APIResponse { 9 | payments: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface PaymentCreateRequest { 14 | // Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents 15 | // in EUR). 16 | 17 | amount: string; 18 | 19 | // The amount to be deducted from the payment as the OAuth app's fee, in the 20 | // lowest denomination for the currency (e.g. pence in GBP, cents in EUR). 21 | 22 | app_fee?: string; 23 | 24 | // A future date on which the payment should be collected. If not specified, the 25 | // payment will be collected as soon as possible. If the value is before the 26 | // [mandate](#core-endpoints-mandates)'s `next_possible_charge_date` creation 27 | // will fail. If the value is not a working day it will be rolled forwards to 28 | // the next available one. 29 | 30 | charge_date?: string; 31 | 32 | // [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. 33 | // Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are 34 | // supported. 35 | 36 | currency: Types.PaymentCurrency; 37 | 38 | // A human-readable description of the payment. This will be included in the 39 | // notification email GoCardless sends to your customer if your organisation 40 | // does not send its own notifications (see [compliance 41 | // requirements](#appendix-compliance-requirements)). 42 | 43 | description?: string; 44 | 45 | // Set this to true or false in the request to create an ACH payment to 46 | // explicitly choose whether the payment should be processed through Faster 47 | // ACH or standard ACH, rather than relying on the presence or absence of the 48 | // charge date to indicate that. 49 | 50 | faster_ach?: boolean; 51 | 52 | // Resources linked to this Payment. 53 | links: Types.PaymentCreateRequestLinks; 54 | 55 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 56 | // to 50 characters and values up to 500 characters. 57 | 58 | metadata?: Types.JsonMap; 59 | 60 | // An optional reference that will appear on your customer's bank statement. The 61 | // character limit for this reference is dependent on the scheme.
62 | // ACH - 10 characters
Autogiro - 11 63 | // characters
Bacs - 10 characters
64 | // BECS - 30 characters
BECS NZ - 12 65 | // characters
Betalingsservice - 30 characters
66 | // Faster Payments - 18 characters
PAD - 67 | // scheme doesn't offer references
PayTo - 18 68 | // characters
SEPA - 140 characters
Note that this 69 | // reference must be unique (for each merchant) for the BECS scheme as it is a 70 | // scheme requirement.

Restricted: 71 | // You can only specify a payment reference for Bacs payments (that is, when 72 | // collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise 74 | // packages.

Restricted: 75 | // You can not specify a payment reference for Faster Payments.

76 | 77 | reference?: string; 78 | 79 | // On failure, automatically retry the payment using [intelligent 80 | // retries](#success-intelligent-retries). Default is `false`.

Important: To be able to use intelligent 82 | // retries, Success+ needs to be enabled in [GoCardless 83 | // dashboard](https://manage.gocardless.com/success-plus).

84 | 85 | retry_if_possible?: boolean; 86 | } 87 | 88 | interface PaymentListRequest { 89 | // Cursor pointing to the start of the desired set. 90 | 91 | after?: string; 92 | 93 | // Cursor pointing to the end of the desired set. 94 | 95 | before?: string; 96 | 97 | // 98 | charge_date?: Types.PaymentChargeDate; 99 | 100 | // The creation date of this Payment. 101 | created_at?: Types.CreatedAtFilter; 102 | 103 | // ID of a creditor to filter payments by. If you pass this parameter, you 104 | // cannot also pass `customer`. 105 | 106 | creditor?: string; 107 | 108 | // [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. 109 | // Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are 110 | // supported. 111 | 112 | currency?: Types.PaymentCurrency; 113 | 114 | // ID of a customer to filter payments by. If you pass this parameter, you 115 | // cannot also pass `creditor`. 116 | 117 | customer?: string; 118 | 119 | // Number of records to return. 120 | 121 | limit?: string; 122 | 123 | // Unique identifier, beginning with "MD". Note that this prefix may not apply 124 | // to mandates created before 2016. 125 | 126 | mandate?: string; 127 | 128 | // The direction to sort in. 129 | // One of: 130 | //
    131 | //
  • `asc`
  • 132 | //
  • `desc`
  • 133 | //
134 | 135 | sort_direction?: Types.PaymentSortDirection; 136 | 137 | // Field by which to sort records. 138 | // One of: 139 | //
    140 | //
  • `charge_date`
  • 141 | //
  • `amount`
  • 142 | //
143 | 144 | sort_field?: Types.PaymentSortField; 145 | 146 | // One of: 147 | //
    148 | //
  • `pending_customer_approval`: we're waiting for the customer to approve 149 | // this payment
  • 150 | //
  • `pending_submission`: the payment has been created, but not yet submitted 151 | // to the banks
  • 152 | //
  • `submitted`: the payment has been submitted to the banks
  • 153 | //
  • `confirmed`: the payment has been confirmed as collected
  • 154 | //
  • `paid_out`: the payment has been included in a 155 | // [payout](#core-endpoints-payouts)
  • 156 | //
  • `cancelled`: the payment has been cancelled
  • 157 | //
  • `customer_approval_denied`: the customer has denied approval for the 158 | // payment. You should contact the customer directly
  • 159 | //
  • `failed`: the payment failed to be processed. Note that payments can fail 160 | // after being confirmed if the failure message is sent late by the banks.
  • 161 | //
  • `charged_back`: the payment has been charged back
  • 162 | //
163 | 164 | status?: Types.PaymentStatus; 165 | 166 | // Unique identifier, beginning with "SB". 167 | 168 | subscription?: string; 169 | } 170 | 171 | interface PaymentUpdateRequest { 172 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 173 | // to 50 characters and values up to 500 characters. 174 | 175 | metadata?: Types.JsonMap; 176 | 177 | // On failure, automatically retry the payment using [intelligent 178 | // retries](#success-intelligent-retries). Default is `false`.

Important: To be able to use intelligent 180 | // retries, Success+ needs to be enabled in [GoCardless 181 | // dashboard](https://manage.gocardless.com/success-plus).

182 | 183 | retry_if_possible?: boolean; 184 | } 185 | 186 | interface PaymentCancelRequest { 187 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 188 | // to 50 characters and values up to 500 characters. 189 | 190 | metadata?: Types.JsonMap; 191 | } 192 | 193 | interface PaymentRetryRequest { 194 | // A future date on which the payment should be collected. If not specified, the 195 | // payment will be collected as soon as possible. If the value is before the 196 | // [mandate](#core-endpoints-mandates)'s `next_possible_charge_date` creation 197 | // will fail. If the value is not a working day it will be rolled forwards to 198 | // the next available one. 199 | 200 | charge_date?: string; 201 | 202 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 203 | // to 50 characters and values up to 500 characters. 204 | 205 | metadata?: Types.JsonMap; 206 | } 207 | 208 | export class PaymentService { 209 | private api: Api; 210 | 211 | constructor(api) { 212 | this.api = api; 213 | } 214 | 215 | public async create( 216 | requestParameters: PaymentCreateRequest, 217 | idempotencyKey = '', 218 | customHeaders: Types.JsonMap = {}, 219 | ): Promise { 220 | const urlParameters = []; 221 | const requestParams = { 222 | path: '/payments', 223 | method: 'post', 224 | urlParameters, 225 | requestParameters, 226 | payloadKey: 'payments', 227 | idempotencyKey, 228 | customHeaders, 229 | fetch: async (identity) => await this.find(identity), 230 | }; 231 | 232 | const response = await this.api.request(requestParams); 233 | const formattedResponse: PaymentResponse = { 234 | ...(response.body?.['payments'] ?? response), 235 | __response__: response.__response__, 236 | }; 237 | 238 | return formattedResponse; 239 | } 240 | 241 | public async list( 242 | requestParameters: PaymentListRequest, 243 | customHeaders: Types.JsonMap = {}, 244 | ): Promise { 245 | const urlParameters = []; 246 | const requestParams = { 247 | path: '/payments', 248 | method: 'get', 249 | urlParameters, 250 | requestParameters, 251 | payloadKey: null, 252 | fetch: null, 253 | customHeaders, 254 | }; 255 | 256 | const response = await this.api.request(requestParams); 257 | const formattedResponse: PaymentListResponse = { 258 | ...response.body, 259 | __response__: response.__response__, 260 | }; 261 | 262 | return formattedResponse; 263 | } 264 | 265 | public async *all( 266 | requestParameters: PaymentListRequest, 267 | customHeaders: Types.JsonMap = {}, 268 | ): AsyncGenerator { 269 | let cursor = undefined; 270 | do { 271 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 272 | 273 | for (const payment of list.payments) { 274 | yield payment; 275 | } 276 | 277 | cursor = list.meta.cursors.after; 278 | } while (cursor); 279 | } 280 | 281 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 282 | const urlParameters = [{ key: 'identity', value: identity }]; 283 | const requestParams = { 284 | path: '/payments/:identity', 285 | method: 'get', 286 | urlParameters, 287 | 288 | payloadKey: null, 289 | fetch: null, 290 | customHeaders, 291 | }; 292 | 293 | const response = await this.api.request(requestParams); 294 | const formattedResponse: PaymentResponse = { 295 | ...response.body['payments'], 296 | __response__: response.__response__, 297 | }; 298 | 299 | return formattedResponse; 300 | } 301 | 302 | public async update( 303 | identity: string, 304 | requestParameters: PaymentUpdateRequest, 305 | customHeaders: Types.JsonMap = {}, 306 | ): Promise { 307 | const urlParameters = [{ key: 'identity', value: identity }]; 308 | const requestParams = { 309 | path: '/payments/:identity', 310 | method: 'put', 311 | urlParameters, 312 | requestParameters, 313 | payloadKey: 'payments', 314 | fetch: null, 315 | customHeaders, 316 | }; 317 | 318 | const response = await this.api.request(requestParams); 319 | const formattedResponse: PaymentResponse = { 320 | ...response.body['payments'], 321 | __response__: response.__response__, 322 | }; 323 | 324 | return formattedResponse; 325 | } 326 | 327 | public async cancel( 328 | identity: string, 329 | requestParameters: PaymentCancelRequest, 330 | customHeaders: Types.JsonMap = {}, 331 | ): Promise { 332 | const urlParameters = [{ key: 'identity', value: identity }]; 333 | const requestParams = { 334 | path: '/payments/:identity/actions/cancel', 335 | method: 'post', 336 | urlParameters, 337 | requestParameters, 338 | payloadKey: null, 339 | fetch: null, 340 | customHeaders, 341 | }; 342 | 343 | const response = await this.api.request(requestParams); 344 | const formattedResponse: PaymentResponse = { 345 | ...response.body['payments'], 346 | __response__: response.__response__, 347 | }; 348 | 349 | return formattedResponse; 350 | } 351 | 352 | public async retry( 353 | identity: string, 354 | requestParameters: PaymentRetryRequest, 355 | customHeaders: Types.JsonMap = {}, 356 | ): Promise { 357 | const urlParameters = [{ key: 'identity', value: identity }]; 358 | const requestParams = { 359 | path: '/payments/:identity/actions/retry', 360 | method: 'post', 361 | urlParameters, 362 | requestParameters, 363 | payloadKey: null, 364 | fetch: null, 365 | customHeaders, 366 | }; 367 | 368 | const response = await this.api.request(requestParams); 369 | const formattedResponse: PaymentResponse = { 370 | ...response.body['payments'], 371 | __response__: response.__response__, 372 | }; 373 | 374 | return formattedResponse; 375 | } 376 | } 377 | -------------------------------------------------------------------------------- /src/services/payoutItemService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface PayoutItemResponse extends Types.PayoutItem, Types.APIResponse {} 7 | 8 | interface PayoutItemListResponse extends Types.APIResponse { 9 | payout_items: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface PayoutItemListRequest { 14 | // Cursor pointing to the start of the desired set. 15 | 16 | after?: string; 17 | 18 | // Cursor pointing to the end of the desired set. 19 | 20 | before?: string; 21 | 22 | // Boolean value indicating whether the API should return tax data for the 23 | // cutover period of April to August 2020. Defaults to false. 24 | 25 | include_2020_tax_cutover?: Types.PayoutItemInclude2020TaxCutover; 26 | 27 | // Number of records to return. 28 | 29 | limit?: string; 30 | 31 | // Unique identifier, beginning with "PO". 32 | 33 | payout: string; 34 | } 35 | 36 | export class PayoutItemService { 37 | private api: Api; 38 | 39 | constructor(api) { 40 | this.api = api; 41 | } 42 | 43 | public async list( 44 | requestParameters: PayoutItemListRequest, 45 | customHeaders: Types.JsonMap = {}, 46 | ): Promise { 47 | const urlParameters = []; 48 | const requestParams = { 49 | path: '/payout_items', 50 | method: 'get', 51 | urlParameters, 52 | requestParameters, 53 | payloadKey: null, 54 | fetch: null, 55 | customHeaders, 56 | }; 57 | 58 | const response = await this.api.request(requestParams); 59 | const formattedResponse: PayoutItemListResponse = { 60 | ...response.body, 61 | __response__: response.__response__, 62 | }; 63 | 64 | return formattedResponse; 65 | } 66 | 67 | public async *all( 68 | requestParameters: PayoutItemListRequest, 69 | customHeaders: Types.JsonMap = {}, 70 | ): AsyncGenerator { 71 | let cursor = undefined; 72 | do { 73 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 74 | 75 | for (const payoutitem of list.payout_items) { 76 | yield payoutitem; 77 | } 78 | 79 | cursor = list.meta.cursors.after; 80 | } while (cursor); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/services/payoutService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface PayoutResponse extends Types.Payout, Types.APIResponse {} 7 | 8 | interface PayoutListResponse extends Types.APIResponse { 9 | payouts: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface PayoutListRequest { 14 | // Cursor pointing to the start of the desired set. 15 | 16 | after?: string; 17 | 18 | // Cursor pointing to the end of the desired set. 19 | 20 | before?: string; 21 | 22 | // The creation date of this Payout. 23 | created_at?: Types.CreatedAtFilter; 24 | 25 | // Unique identifier, beginning with "CR". 26 | 27 | creditor?: string; 28 | 29 | // Unique identifier, beginning with "BA". 30 | 31 | creditor_bank_account?: string; 32 | 33 | // [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. 34 | // Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are 35 | // supported. 36 | 37 | currency?: Types.PayoutCurrency; 38 | 39 | // Number of records to return. 40 | 41 | limit?: string; 42 | 43 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 44 | // to 50 characters and values up to 500 characters. _Note:_ This should not be 45 | // used for storing PII data. 46 | 47 | metadata?: Types.JsonMap; 48 | 49 | // Whether a payout contains merchant revenue or partner fees. 50 | 51 | payout_type?: Types.PayoutPayoutType; 52 | 53 | // Reference which appears on the creditor's bank statement. 54 | 55 | reference?: string; 56 | 57 | // One of: 58 | //
    59 | //
  • `pending`: the payout has been created, but not yet sent to your bank or 60 | // it is in the process of being exchanged through our FX provider.
  • 61 | //
  • `paid`: the payout has been sent to the your bank. FX payouts will become 62 | // `paid` after we emit the `fx_rate_confirmed` webhook.
  • 63 | //
  • `bounced`: the payout bounced when sent, the payout can be retried.
  • 64 | //
65 | 66 | status?: Types.PayoutStatus; 67 | } 68 | 69 | interface PayoutUpdateRequest { 70 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 71 | // to 50 characters and values up to 500 characters. 72 | 73 | metadata?: Types.JsonMap; 74 | } 75 | 76 | export class PayoutService { 77 | private api: Api; 78 | 79 | constructor(api) { 80 | this.api = api; 81 | } 82 | 83 | public async list( 84 | requestParameters: PayoutListRequest, 85 | customHeaders: Types.JsonMap = {}, 86 | ): Promise { 87 | const urlParameters = []; 88 | const requestParams = { 89 | path: '/payouts', 90 | method: 'get', 91 | urlParameters, 92 | requestParameters, 93 | payloadKey: null, 94 | fetch: null, 95 | customHeaders, 96 | }; 97 | 98 | const response = await this.api.request(requestParams); 99 | const formattedResponse: PayoutListResponse = { 100 | ...response.body, 101 | __response__: response.__response__, 102 | }; 103 | 104 | return formattedResponse; 105 | } 106 | 107 | public async *all( 108 | requestParameters: PayoutListRequest, 109 | customHeaders: Types.JsonMap = {}, 110 | ): AsyncGenerator { 111 | let cursor = undefined; 112 | do { 113 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 114 | 115 | for (const payout of list.payouts) { 116 | yield payout; 117 | } 118 | 119 | cursor = list.meta.cursors.after; 120 | } while (cursor); 121 | } 122 | 123 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 124 | const urlParameters = [{ key: 'identity', value: identity }]; 125 | const requestParams = { 126 | path: '/payouts/:identity', 127 | method: 'get', 128 | urlParameters, 129 | 130 | payloadKey: null, 131 | fetch: null, 132 | customHeaders, 133 | }; 134 | 135 | const response = await this.api.request(requestParams); 136 | const formattedResponse: PayoutResponse = { 137 | ...response.body['payouts'], 138 | __response__: response.__response__, 139 | }; 140 | 141 | return formattedResponse; 142 | } 143 | 144 | public async update( 145 | identity: string, 146 | requestParameters: PayoutUpdateRequest, 147 | customHeaders: Types.JsonMap = {}, 148 | ): Promise { 149 | const urlParameters = [{ key: 'identity', value: identity }]; 150 | const requestParams = { 151 | path: '/payouts/:identity', 152 | method: 'put', 153 | urlParameters, 154 | requestParameters, 155 | payloadKey: 'payouts', 156 | fetch: null, 157 | customHeaders, 158 | }; 159 | 160 | const response = await this.api.request(requestParams); 161 | const formattedResponse: PayoutResponse = { 162 | ...response.body['payouts'], 163 | __response__: response.__response__, 164 | }; 165 | 166 | return formattedResponse; 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/services/redirectFlowService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface RedirectFlowResponse extends Types.RedirectFlow, Types.APIResponse {} 7 | 8 | interface RedirectFlowListResponse extends Types.APIResponse { 9 | redirect_flows: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface RedirectFlowCreateRequest { 14 | // A description of the item the customer is paying for. This will be shown on 15 | // the hosted payment pages. 16 | 17 | description?: string; 18 | 19 | // Resources linked to this RedirectFlow. 20 | links?: Types.RedirectFlowCreateRequestLinks; 21 | 22 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 23 | // to 50 characters and values up to 500 characters. _Note:_ This should not be 24 | // used for storing PII data. 25 | 26 | metadata?: Types.JsonMap; 27 | 28 | // Bank account information used to prefill the payment page so your customer 29 | // doesn't have to re-type details you already hold about them. It will be 30 | // stored unvalidated and the customer will be able to review and amend it 31 | // before completing the form. 32 | prefilled_bank_account?: Types.RedirectFlowPrefilledBankAccount; 33 | 34 | // Customer information used to prefill the payment page so your customer 35 | // doesn't have to re-type details you already hold about them. It will be 36 | // stored unvalidated and the customer will be able to review and amend it 37 | // before completing the form. 38 | prefilled_customer?: Types.RedirectFlowPrefilledCustomer; 39 | 40 | // The Direct Debit scheme of the mandate. If specified, the payment pages will 41 | // only allow the set-up of a mandate for the specified scheme. It is 42 | // recommended that you leave this blank so the most appropriate scheme is 43 | // picked based on the customer's bank account. 44 | 45 | scheme?: Types.RedirectFlowScheme; 46 | 47 | // The customer's session ID must be provided when the redirect flow is set up 48 | // and again when it is completed. This allows integrators to ensure that the 49 | // user who was originally sent to the GoCardless payment pages is the one who 50 | // has completed them. 51 | 52 | session_token: string; 53 | 54 | // The URL to redirect to upon successful mandate setup. You must use a URL 55 | // beginning `https` in the live environment. 56 | 57 | success_redirect_url: string; 58 | } 59 | 60 | interface RedirectFlowCompleteRequest { 61 | // The customer's session ID must be provided when the redirect flow is set up 62 | // and again when it is completed. This allows integrators to ensure that the 63 | // user who was originally sent to the GoCardless payment pages is the one who 64 | // has completed them. 65 | 66 | session_token: string; 67 | } 68 | 69 | export class RedirectFlowService { 70 | private api: Api; 71 | 72 | constructor(api) { 73 | this.api = api; 74 | } 75 | 76 | public async create( 77 | requestParameters: RedirectFlowCreateRequest, 78 | idempotencyKey = '', 79 | customHeaders: Types.JsonMap = {}, 80 | ): Promise { 81 | const urlParameters = []; 82 | const requestParams = { 83 | path: '/redirect_flows', 84 | method: 'post', 85 | urlParameters, 86 | requestParameters, 87 | payloadKey: 'redirect_flows', 88 | idempotencyKey, 89 | customHeaders, 90 | fetch: async (identity) => await this.find(identity), 91 | }; 92 | 93 | const response = await this.api.request(requestParams); 94 | const formattedResponse: RedirectFlowResponse = { 95 | ...(response.body?.['redirect_flows'] ?? response), 96 | __response__: response.__response__, 97 | }; 98 | 99 | return formattedResponse; 100 | } 101 | 102 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 103 | const urlParameters = [{ key: 'identity', value: identity }]; 104 | const requestParams = { 105 | path: '/redirect_flows/:identity', 106 | method: 'get', 107 | urlParameters, 108 | 109 | payloadKey: null, 110 | fetch: null, 111 | customHeaders, 112 | }; 113 | 114 | const response = await this.api.request(requestParams); 115 | const formattedResponse: RedirectFlowResponse = { 116 | ...response.body['redirect_flows'], 117 | __response__: response.__response__, 118 | }; 119 | 120 | return formattedResponse; 121 | } 122 | 123 | public async complete( 124 | identity: string, 125 | requestParameters: RedirectFlowCompleteRequest, 126 | customHeaders: Types.JsonMap = {}, 127 | ): Promise { 128 | const urlParameters = [{ key: 'identity', value: identity }]; 129 | const requestParams = { 130 | path: '/redirect_flows/:identity/actions/complete', 131 | method: 'post', 132 | urlParameters, 133 | requestParameters, 134 | payloadKey: null, 135 | fetch: null, 136 | customHeaders, 137 | }; 138 | 139 | const response = await this.api.request(requestParams); 140 | const formattedResponse: RedirectFlowResponse = { 141 | ...response.body['redirect_flows'], 142 | __response__: response.__response__, 143 | }; 144 | 145 | return formattedResponse; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/services/refundService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface RefundResponse extends Types.Refund, Types.APIResponse {} 7 | 8 | interface RefundListResponse extends Types.APIResponse { 9 | refunds: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface RefundCreateRequest { 14 | // Amount in minor unit (e.g. pence in GBP, cents in EUR). 15 | 16 | amount: string; 17 | 18 | // Resources linked to this Refund. 19 | links: Types.RefundCreateRequestLinks; 20 | 21 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 22 | // to 50 characters and values up to 500 characters. 23 | 24 | metadata?: Types.JsonMap; 25 | 26 | // An optional reference that will appear on your customer's bank statement. The 27 | // character limit for this reference is dependent on the scheme.
28 | // ACH - 10 characters
Autogiro - 11 29 | // characters
Bacs - 10 characters
30 | // BECS - 30 characters
BECS NZ - 12 31 | // characters
Betalingsservice - 30 characters
32 | // Faster Payments - 18 characters
PAD - 33 | // scheme doesn't offer references
PayTo - 18 34 | // characters
SEPA - 140 characters
Note that this 35 | // reference must be unique (for each merchant) for the BECS scheme as it is a 36 | // scheme requirement.

Restricted: 37 | // You can only specify a payment reference for Bacs payments (that is, when 38 | // collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise 40 | // packages.

Restricted: 41 | // You can not specify a payment reference for Faster Payments.

42 | 43 | reference?: string; 44 | 45 | // Total expected refunded amount in minor unit (e.g. pence/cents/öre). If there 46 | // are 47 | // other partial refunds against this payment, this value should be the sum of 48 | // the 49 | // existing refunds plus the amount of the refund being created. 50 | //
51 | // Must be supplied if `links[payment]` is present. 52 | //

It is possible to opt out of requiring 53 | // `total_amount_confirmation`, please contact our support team for more 55 | // information.

56 | 57 | total_amount_confirmation?: string; 58 | } 59 | 60 | interface RefundListRequest { 61 | // Cursor pointing to the start of the desired set. 62 | 63 | after?: string; 64 | 65 | // Cursor pointing to the end of the desired set. 66 | 67 | before?: string; 68 | 69 | // The creation date of this Refund. 70 | created_at?: Types.CreatedAtFilter; 71 | 72 | // Number of records to return. 73 | 74 | limit?: string; 75 | 76 | // Unique identifier, beginning with "MD". Note that this prefix may not apply 77 | // to mandates created before 2016. 78 | 79 | mandate?: string; 80 | 81 | // Unique identifier, beginning with "PM". 82 | 83 | payment?: string; 84 | 85 | // Whether a refund was issued against a mandate or a payment. One of: 86 | //
    87 | //
  • `payment`: default returns refunds created against payments 88 | // only
  • 89 | //
  • `mandate`: returns refunds created against mandates only
  • 90 | //
91 | 92 | refund_type?: Types.RefundRefundType; 93 | } 94 | 95 | interface RefundUpdateRequest { 96 | // Key-value store of custom data. Up to 3 keys are permitted, with key names up 97 | // to 50 characters and values up to 500 characters. 98 | 99 | metadata?: Types.JsonMap; 100 | } 101 | 102 | export class RefundService { 103 | private api: Api; 104 | 105 | constructor(api) { 106 | this.api = api; 107 | } 108 | 109 | public async create( 110 | requestParameters: RefundCreateRequest, 111 | idempotencyKey = '', 112 | customHeaders: Types.JsonMap = {}, 113 | ): Promise { 114 | const urlParameters = []; 115 | const requestParams = { 116 | path: '/refunds', 117 | method: 'post', 118 | urlParameters, 119 | requestParameters, 120 | payloadKey: 'refunds', 121 | idempotencyKey, 122 | customHeaders, 123 | fetch: async (identity) => await this.find(identity), 124 | }; 125 | 126 | const response = await this.api.request(requestParams); 127 | const formattedResponse: RefundResponse = { 128 | ...(response.body?.['refunds'] ?? response), 129 | __response__: response.__response__, 130 | }; 131 | 132 | return formattedResponse; 133 | } 134 | 135 | public async list( 136 | requestParameters: RefundListRequest, 137 | customHeaders: Types.JsonMap = {}, 138 | ): Promise { 139 | const urlParameters = []; 140 | const requestParams = { 141 | path: '/refunds', 142 | method: 'get', 143 | urlParameters, 144 | requestParameters, 145 | payloadKey: null, 146 | fetch: null, 147 | customHeaders, 148 | }; 149 | 150 | const response = await this.api.request(requestParams); 151 | const formattedResponse: RefundListResponse = { 152 | ...response.body, 153 | __response__: response.__response__, 154 | }; 155 | 156 | return formattedResponse; 157 | } 158 | 159 | public async *all( 160 | requestParameters: RefundListRequest, 161 | customHeaders: Types.JsonMap = {}, 162 | ): AsyncGenerator { 163 | let cursor = undefined; 164 | do { 165 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 166 | 167 | for (const refund of list.refunds) { 168 | yield refund; 169 | } 170 | 171 | cursor = list.meta.cursors.after; 172 | } while (cursor); 173 | } 174 | 175 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 176 | const urlParameters = [{ key: 'identity', value: identity }]; 177 | const requestParams = { 178 | path: '/refunds/:identity', 179 | method: 'get', 180 | urlParameters, 181 | 182 | payloadKey: null, 183 | fetch: null, 184 | customHeaders, 185 | }; 186 | 187 | const response = await this.api.request(requestParams); 188 | const formattedResponse: RefundResponse = { 189 | ...response.body['refunds'], 190 | __response__: response.__response__, 191 | }; 192 | 193 | return formattedResponse; 194 | } 195 | 196 | public async update( 197 | identity: string, 198 | requestParameters: RefundUpdateRequest, 199 | customHeaders: Types.JsonMap = {}, 200 | ): Promise { 201 | const urlParameters = [{ key: 'identity', value: identity }]; 202 | const requestParams = { 203 | path: '/refunds/:identity', 204 | method: 'put', 205 | urlParameters, 206 | requestParameters, 207 | payloadKey: 'refunds', 208 | fetch: null, 209 | customHeaders, 210 | }; 211 | 212 | const response = await this.api.request(requestParams); 213 | const formattedResponse: RefundResponse = { 214 | ...response.body['refunds'], 215 | __response__: response.__response__, 216 | }; 217 | 218 | return formattedResponse; 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /src/services/scenarioSimulatorService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface ScenarioSimulatorResponse extends Types.ScenarioSimulator, Types.APIResponse {} 7 | 8 | interface ScenarioSimulatorListResponse extends Types.APIResponse { 9 | scenario_simulators: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface ScenarioSimulatorRunRequest { 14 | // Resources linked to this ScenarioSimulator. 15 | links?: Types.ScenarioSimulatorRunRequestLinks; 16 | } 17 | 18 | export class ScenarioSimulatorService { 19 | private api: Api; 20 | 21 | constructor(api) { 22 | this.api = api; 23 | } 24 | 25 | public async run( 26 | identity: string, 27 | requestParameters: ScenarioSimulatorRunRequest, 28 | customHeaders: Types.JsonMap = {}, 29 | ): Promise { 30 | const urlParameters = [{ key: 'identity', value: identity }]; 31 | const requestParams = { 32 | path: '/scenario_simulators/:identity/actions/run', 33 | method: 'post', 34 | urlParameters, 35 | requestParameters, 36 | payloadKey: null, 37 | fetch: null, 38 | customHeaders, 39 | }; 40 | 41 | const response = await this.api.request(requestParams); 42 | const formattedResponse: ScenarioSimulatorResponse = { 43 | ...response.body['scenario_simulators'], 44 | __response__: response.__response__, 45 | }; 46 | 47 | return formattedResponse; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/services/schemeIdentifierService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface SchemeIdentifierResponse extends Types.SchemeIdentifier, Types.APIResponse {} 7 | 8 | interface SchemeIdentifierListResponse extends Types.APIResponse { 9 | scheme_identifiers: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface SchemeIdentifierCreateRequest { 14 | // Resources linked to this SchemeIdentifier. 15 | links?: Types.SchemeIdentifierCreateRequestLinks; 16 | 17 | // The name which appears on customers' bank statements. This should usually be 18 | // the merchant's trading name. 19 | 20 | name: string; 21 | 22 | // The scheme which this scheme identifier applies to. 23 | 24 | scheme: Types.SchemeIdentifierScheme; 25 | } 26 | 27 | interface SchemeIdentifierListRequest { 28 | // Cursor pointing to the start of the desired set. 29 | 30 | after?: string; 31 | 32 | // Cursor pointing to the end of the desired set. 33 | 34 | before?: string; 35 | 36 | // Unique identifier, beginning with "CR". 37 | 38 | creditor?: string; 39 | 40 | // Number of records to return. 41 | 42 | limit?: string; 43 | } 44 | 45 | export class SchemeIdentifierService { 46 | private api: Api; 47 | 48 | constructor(api) { 49 | this.api = api; 50 | } 51 | 52 | public async create( 53 | requestParameters: SchemeIdentifierCreateRequest, 54 | idempotencyKey = '', 55 | customHeaders: Types.JsonMap = {}, 56 | ): Promise { 57 | const urlParameters = []; 58 | const requestParams = { 59 | path: '/scheme_identifiers', 60 | method: 'post', 61 | urlParameters, 62 | requestParameters, 63 | payloadKey: 'scheme_identifiers', 64 | idempotencyKey, 65 | customHeaders, 66 | fetch: async (identity) => await this.find(identity), 67 | }; 68 | 69 | const response = await this.api.request(requestParams); 70 | const formattedResponse: SchemeIdentifierResponse = { 71 | ...(response.body?.['scheme_identifiers'] ?? response), 72 | __response__: response.__response__, 73 | }; 74 | 75 | return formattedResponse; 76 | } 77 | 78 | public async list( 79 | requestParameters: SchemeIdentifierListRequest, 80 | customHeaders: Types.JsonMap = {}, 81 | ): Promise { 82 | const urlParameters = []; 83 | const requestParams = { 84 | path: '/scheme_identifiers', 85 | method: 'get', 86 | urlParameters, 87 | requestParameters, 88 | payloadKey: null, 89 | fetch: null, 90 | customHeaders, 91 | }; 92 | 93 | const response = await this.api.request(requestParams); 94 | const formattedResponse: SchemeIdentifierListResponse = { 95 | ...response.body, 96 | __response__: response.__response__, 97 | }; 98 | 99 | return formattedResponse; 100 | } 101 | 102 | public async *all( 103 | requestParameters: SchemeIdentifierListRequest, 104 | customHeaders: Types.JsonMap = {}, 105 | ): AsyncGenerator { 106 | let cursor = undefined; 107 | do { 108 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 109 | 110 | for (const schemeidentifier of list.scheme_identifiers) { 111 | yield schemeidentifier; 112 | } 113 | 114 | cursor = list.meta.cursors.after; 115 | } while (cursor); 116 | } 117 | 118 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 119 | const urlParameters = [{ key: 'identity', value: identity }]; 120 | const requestParams = { 121 | path: '/scheme_identifiers/:identity', 122 | method: 'get', 123 | urlParameters, 124 | 125 | payloadKey: null, 126 | fetch: null, 127 | customHeaders, 128 | }; 129 | 130 | const response = await this.api.request(requestParams); 131 | const formattedResponse: SchemeIdentifierResponse = { 132 | ...response.body['scheme_identifiers'], 133 | __response__: response.__response__, 134 | }; 135 | 136 | return formattedResponse; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/services/taxRateService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface TaxRateResponse extends Types.TaxRate, Types.APIResponse {} 7 | 8 | interface TaxRateListResponse extends Types.APIResponse { 9 | tax_rates: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface TaxRateListRequest { 14 | // Cursor pointing to the start of the desired set. 15 | 16 | after?: string; 17 | 18 | // Cursor pointing to the end of the desired set. 19 | 20 | before?: string; 21 | 22 | // The jurisdiction this tax rate applies to 23 | 24 | jurisdiction?: string; 25 | 26 | // Number of records to return. 27 | 28 | limit?: string; 29 | } 30 | 31 | export class TaxRateService { 32 | private api: Api; 33 | 34 | constructor(api) { 35 | this.api = api; 36 | } 37 | 38 | public async list( 39 | requestParameters: TaxRateListRequest, 40 | customHeaders: Types.JsonMap = {}, 41 | ): Promise { 42 | const urlParameters = []; 43 | const requestParams = { 44 | path: '/tax_rates', 45 | method: 'get', 46 | urlParameters, 47 | requestParameters, 48 | payloadKey: null, 49 | fetch: null, 50 | customHeaders, 51 | }; 52 | 53 | const response = await this.api.request(requestParams); 54 | const formattedResponse: TaxRateListResponse = { 55 | ...response.body, 56 | __response__: response.__response__, 57 | }; 58 | 59 | return formattedResponse; 60 | } 61 | 62 | public async *all( 63 | requestParameters: TaxRateListRequest, 64 | customHeaders: Types.JsonMap = {}, 65 | ): AsyncGenerator { 66 | let cursor = undefined; 67 | do { 68 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 69 | 70 | for (const taxrate of list.tax_rates) { 71 | yield taxrate; 72 | } 73 | 74 | cursor = list.meta.cursors.after; 75 | } while (cursor); 76 | } 77 | 78 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 79 | const urlParameters = [{ key: 'identity', value: identity }]; 80 | const requestParams = { 81 | path: '/tax_rates/:identity', 82 | method: 'get', 83 | urlParameters, 84 | 85 | payloadKey: null, 86 | fetch: null, 87 | customHeaders, 88 | }; 89 | 90 | const response = await this.api.request(requestParams); 91 | const formattedResponse: TaxRateResponse = { 92 | ...response.body['tax_rates'], 93 | __response__: response.__response__, 94 | }; 95 | 96 | return formattedResponse; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/services/transferredMandateService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface TransferredMandateResponse extends Types.TransferredMandate, Types.APIResponse {} 7 | 8 | interface TransferredMandateListResponse extends Types.APIResponse { 9 | transferred_mandates: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | export class TransferredMandateService { 14 | private api: Api; 15 | 16 | constructor(api) { 17 | this.api = api; 18 | } 19 | 20 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 21 | const urlParameters = [{ key: 'identity', value: identity }]; 22 | const requestParams = { 23 | path: '/transferred_mandates/:identity', 24 | method: 'get', 25 | urlParameters, 26 | 27 | payloadKey: null, 28 | fetch: null, 29 | customHeaders, 30 | }; 31 | 32 | const response = await this.api.request(requestParams); 33 | const formattedResponse: TransferredMandateResponse = { 34 | ...response.body['transferred_mandates'], 35 | __response__: response.__response__, 36 | }; 37 | 38 | return formattedResponse; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/services/verificationDetailService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface VerificationDetailResponse extends Types.VerificationDetail, Types.APIResponse {} 7 | 8 | interface VerificationDetailListResponse extends Types.APIResponse { 9 | verification_details: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface VerificationDetailCreateRequest { 14 | // The first line of the company's address. 15 | 16 | address_line1: string; 17 | 18 | // The second line of the company's address. 19 | 20 | address_line2?: string; 21 | 22 | // The third line of the company's address. 23 | 24 | address_line3?: string; 25 | 26 | // The city of the company's address. 27 | 28 | city: string; 29 | 30 | // The company's registration number. 31 | 32 | company_number: string; 33 | 34 | // A summary describing what the company does. 35 | 36 | description: string; 37 | 38 | // The company's directors. 39 | 40 | directors: Types.VerificationDetailDirector[]; 41 | 42 | // Resources linked to this VerificationDetail. 43 | links: Types.VerificationDetailCreateRequestLinks; 44 | 45 | // The company's legal name. 46 | 47 | name: string; 48 | 49 | // The company's postal code. 50 | 51 | postal_code: string; 52 | } 53 | 54 | interface VerificationDetailListRequest { 55 | // Cursor pointing to the start of the desired set. 56 | 57 | after?: string; 58 | 59 | // Cursor pointing to the end of the desired set. 60 | 61 | before?: string; 62 | 63 | // Unique identifier, beginning with "CR". 64 | 65 | creditor: string; 66 | 67 | // Number of records to return. 68 | 69 | limit?: string; 70 | } 71 | 72 | export class VerificationDetailService { 73 | private api: Api; 74 | 75 | constructor(api) { 76 | this.api = api; 77 | } 78 | 79 | public async create( 80 | requestParameters: VerificationDetailCreateRequest, 81 | idempotencyKey = '', 82 | customHeaders: Types.JsonMap = {}, 83 | ): Promise { 84 | const urlParameters = []; 85 | const requestParams = { 86 | path: '/verification_details', 87 | method: 'post', 88 | urlParameters, 89 | requestParameters, 90 | payloadKey: 'verification_details', 91 | idempotencyKey, 92 | customHeaders, 93 | fetch: undefined, 94 | }; 95 | 96 | const response = await this.api.request(requestParams); 97 | const formattedResponse: VerificationDetailResponse = { 98 | ...(response.body?.['verification_details'] ?? response), 99 | __response__: response.__response__, 100 | }; 101 | 102 | return formattedResponse; 103 | } 104 | 105 | public async list( 106 | requestParameters: VerificationDetailListRequest, 107 | customHeaders: Types.JsonMap = {}, 108 | ): Promise { 109 | const urlParameters = []; 110 | const requestParams = { 111 | path: '/verification_details', 112 | method: 'get', 113 | urlParameters, 114 | requestParameters, 115 | payloadKey: null, 116 | fetch: null, 117 | customHeaders, 118 | }; 119 | 120 | const response = await this.api.request(requestParams); 121 | const formattedResponse: VerificationDetailListResponse = { 122 | ...response.body, 123 | __response__: response.__response__, 124 | }; 125 | 126 | return formattedResponse; 127 | } 128 | 129 | public async *all( 130 | requestParameters: VerificationDetailListRequest, 131 | customHeaders: Types.JsonMap = {}, 132 | ): AsyncGenerator { 133 | let cursor = undefined; 134 | do { 135 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 136 | 137 | for (const verificationdetail of list.verification_details) { 138 | yield verificationdetail; 139 | } 140 | 141 | cursor = list.meta.cursors.after; 142 | } while (cursor); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/services/webhookService.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { Api } from '../api/api'; 4 | import * as Types from '../types/Types'; 5 | 6 | interface WebhookResponse extends Types.Webhook, Types.APIResponse {} 7 | 8 | interface WebhookListResponse extends Types.APIResponse { 9 | webhooks: Array; 10 | meta: Types.ListMeta; 11 | } 12 | 13 | interface WebhookListRequest { 14 | // Cursor pointing to the start of the desired set. 15 | 16 | after?: string; 17 | 18 | // Cursor pointing to the end of the desired set. 19 | 20 | before?: string; 21 | 22 | // The creation date of this Webhook. 23 | created_at?: Types.CreatedAtFilter; 24 | 25 | // Show only test/non test webhooks 26 | 27 | is_test?: boolean; 28 | 29 | // Number of records to return. 30 | 31 | limit?: string; 32 | 33 | // Show only successful/failed webhooks 34 | 35 | successful?: boolean; 36 | } 37 | 38 | export class WebhookService { 39 | private api: Api; 40 | 41 | constructor(api) { 42 | this.api = api; 43 | } 44 | 45 | public async list( 46 | requestParameters: WebhookListRequest, 47 | customHeaders: Types.JsonMap = {}, 48 | ): Promise { 49 | const urlParameters = []; 50 | const requestParams = { 51 | path: '/webhooks', 52 | method: 'get', 53 | urlParameters, 54 | requestParameters, 55 | payloadKey: null, 56 | fetch: null, 57 | customHeaders, 58 | }; 59 | 60 | const response = await this.api.request(requestParams); 61 | const formattedResponse: WebhookListResponse = { 62 | ...response.body, 63 | __response__: response.__response__, 64 | }; 65 | 66 | return formattedResponse; 67 | } 68 | 69 | public async *all( 70 | requestParameters: WebhookListRequest, 71 | customHeaders: Types.JsonMap = {}, 72 | ): AsyncGenerator { 73 | let cursor = undefined; 74 | do { 75 | const list = await this.list({ ...requestParameters, after: cursor }, customHeaders); 76 | 77 | for (const webhook of list.webhooks) { 78 | yield webhook; 79 | } 80 | 81 | cursor = list.meta.cursors.after; 82 | } while (cursor); 83 | } 84 | 85 | public async find(identity: string, customHeaders: Types.JsonMap = {}): Promise { 86 | const urlParameters = [{ key: 'identity', value: identity }]; 87 | const requestParams = { 88 | path: '/webhooks/:identity', 89 | method: 'get', 90 | urlParameters, 91 | 92 | payloadKey: null, 93 | fetch: null, 94 | customHeaders, 95 | }; 96 | 97 | const response = await this.api.request(requestParams); 98 | const formattedResponse: WebhookResponse = { 99 | ...response.body['webhooks'], 100 | __response__: response.__response__, 101 | }; 102 | 103 | return formattedResponse; 104 | } 105 | 106 | public async retry(identity: string, customHeaders: Types.JsonMap = {}): Promise { 107 | const urlParameters = [{ key: 'identity', value: identity }]; 108 | const requestParams = { 109 | path: '/webhooks/:identity/actions/retry', 110 | method: 'post', 111 | urlParameters, 112 | 113 | payloadKey: null, 114 | fetch: null, 115 | customHeaders, 116 | }; 117 | 118 | const response = await this.api.request(requestParams); 119 | const formattedResponse: WebhookResponse = { 120 | ...response.body['webhooks'], 121 | __response__: response.__response__, 122 | }; 123 | 124 | return formattedResponse; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/webhooks.test.ts: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const webhook = require('./webhooks'); 3 | 4 | const requestBody = JSON.stringify(JSON.parse(fs.readFileSync('src/fixtures/webhook_body.json', 'utf8'))); 5 | const requestBodyBuffer = Buffer.from(requestBody); 6 | 7 | const webhookSecret = 'ED7D658C-D8EB-4941-948B-3973214F2D49'; 8 | const signatureHeader = '2693754819d3e32d7e8fcb13c729631f316c6de8dc1cf634d6527f1c07276e7e'; 9 | 10 | describe('.parse', () => { 11 | test('parses a string body with valid signature', () => { 12 | const result = webhook.parse(requestBody, webhookSecret, signatureHeader); 13 | 14 | expect(result.length).toBe(2); 15 | 16 | const firstEvent = result[0]; 17 | expect(firstEvent.id).toBe('EV00BD05S5VM2T'); 18 | }); 19 | 20 | test('parses a buffer body with valid signature', () => { 21 | const result = webhook.parse(requestBodyBuffer, webhookSecret, signatureHeader); 22 | 23 | expect(result.length).toBe(2); 24 | 25 | const firstEvent = result[0]; 26 | expect(firstEvent.id).toBe('EV00BD05S5VM2T'); 27 | }); 28 | 29 | test('parses a webhook response body with an invalid signature', () => { 30 | const badSignatureHeader = 'NOTVERYCONVINCING'; 31 | 32 | expect(() => webhook.parse(requestBody, webhookSecret, badSignatureHeader)).toThrowError( 33 | webhook.InvalidSignatureError, 34 | ); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /src/webhooks.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * GoCardless supports webhooks, allowing you to receive real-time notifications 3 | * when things happen in your account, so you can take automatic actions in 4 | * response, for example: 5 | * 6 | * When a customer cancels their mandate with the bank, suspend their club membership 7 | * 8 | * The `parse` function does two things; firstly, it validates that a webhook you receive 9 | * is genuinely from GoCardless, and secondly it parses each `event` object in the 10 | * JSON object into an `GoCardless.Event` class. 11 | */ 12 | 13 | import crypto from 'crypto'; 14 | import { Event } from './types/Types'; 15 | 16 | function InvalidSignatureError() { 17 | this.message = 'The signature header secret does not match your webhook secret!'; 18 | this.name = 'InvalidSignatureError'; 19 | } 20 | 21 | /** 22 | * Validates that a webhook was genuinely sent by GoCardless, then parses each `event` 23 | * object into an array of `GoCardless.Event` classes. 24 | * 25 | * @body The raw webhook body. 26 | * @webhookSecret The webhook endpoint secret for your webhook endpoint, as 27 | * configured in your GoCardless Dashboard. 28 | * @signatureHeader The signature included in the webhook request, as specified 29 | * by the `Webhook-Signature` header. 30 | */ 31 | function parse(body: crypto.BinaryLike, webhookSecret: string, signatureHeader: string): Event[] { 32 | verifySignature(body, webhookSecret, signatureHeader); 33 | 34 | const bodyString = typeof body === 'string' ? body : body.toString(); 35 | const eventsData = JSON.parse(bodyString) as { events: Event[] }; 36 | return eventsData.events; 37 | } 38 | 39 | /** 40 | * Validate the signature header. Note, we're using the `crypto.timingSafeEqual` 41 | * library for the hash comparison, to protect against timing attacks. 42 | * 43 | * @body The raw webhook body. 44 | * @webhookSecret The webhook endpoint secret for your webhook endpoint, as 45 | * configured in your GoCardless Dashboard. 46 | * @signatureHeader The signature included in the webhook request, as specified 47 | * by the `Webhook-Signature` header. 48 | */ 49 | function verifySignature(body: crypto.BinaryLike, webhookSecret: string, signatureHeader: string) { 50 | const bufferDigest = crypto.createHmac('sha256', webhookSecret).update(body).digest(); 51 | const bufferSignatureHeader = Buffer.from(signatureHeader, 'hex'); 52 | 53 | if ( 54 | bufferDigest.length !== bufferSignatureHeader.length || 55 | !crypto.timingSafeEqual(bufferDigest, bufferSignatureHeader) 56 | ) { 57 | throw new InvalidSignatureError(); 58 | } 59 | } 60 | 61 | export { parse, verifySignature, InvalidSignatureError }; 62 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "newLine": "lf", 5 | "esModuleInterop": true, 6 | "allowSyntheticDefaultImports": true, 7 | "allowJs": true, 8 | "target": "es2018", 9 | "pretty": true, 10 | "moduleResolution": "node", 11 | "declaration": true, 12 | "sourceMap": true, 13 | "outDir": "dist", 14 | "baseUrl": ".", 15 | "noImplicitAny": false, 16 | "noImplicitReturns": false, 17 | "skipLibCheck": true, 18 | "paths": { 19 | "*": ["node_modules/*", "src/types/*"] 20 | } 21 | }, 22 | "files": ["src/api/api.ts"], 23 | "include": ["src/**/*.ts"], 24 | "exclude": ["node_modules"] 25 | } 26 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "gts/tslint.json", 3 | "rules": { 4 | "no-any": true, 5 | "only-arrow-functions": false 6 | }, 7 | "linterOptions": { 8 | "exclude": [ 9 | "**/*.json", 10 | "**/*.js" 11 | ] 12 | } 13 | } 14 | --------------------------------------------------------------------------------