diff --git a/README.md b/README.md index 26853b3..aa135b3 100644 --- a/README.md +++ b/README.md @@ -16,12 +16,12 @@ npm install paynl-sdk --save ## Examples Some of the basic examples are listed here, for the full list of examples, please take a look at the examples directory [here](https://github.com/paynl/nodejs-sdk/tree/master/src/examples). -All examples start with importing the `paynl-sdk` and creating a client using the API token. +All examples start with importing the `paynl-sdk` and creating a client using the AT token as username and the API token as password. ```typescript import { createPayNLClient } from 'paynl-sdk'; -const payNL = createPayNLClient({ apiToken: '****************************************' }); +const payNL = createPayNLClient({ username: 'AT-####-####', password: '****************************************' }); ``` ## Service Config diff --git a/UPGRADING.md b/UPGRADING.md index e96909a..394eecb 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -4,8 +4,10 @@ All notable (breaking) changes to this project will be documented in this file. ## From 1.2.0 to 2.0.0 -As of version 2.0.0, the `serviceId` option has been removed from `createPayNLClient()` and is required to be passed -with `payNL.Orders.create({ serviceId: 'SL-####-####' })` and `payNL.DirectDebit.createMandate({ serviceId: 'SL-####-####' })`. +As of version 2.0.0, the options passed to `createPayNLClient()` have been changed. +* The `apiToken` has been renamed to `password` +* The `serviceId` option has been removed and is required to be passed to + `payNL.Orders.create({ serviceId: 'SL-####-####' })` and `payNL.DirectDebit.createMandate({ serviceId: 'SL-####-####' })`. The SDK can no longer create or update transactions using the old REST API. All orders need to be created using the new [order API](https://developer.pay.nl/reference/api_create_order-1). @@ -21,7 +23,7 @@ To upgrade, all calls to the following methods need to be replaced with new Orde * `payNL.Instore.getTerminals()` The following have different in- and outputs: -* `payNL.PaymentMethods.all()` (previously called `payNL.Paymentmethods.getList()`) +* `payNL.Core.PaymentMethods()` (previously called `payNL.Paymentmethods.getList()`) * `payNL.DirectDebit.add()` * `payNL.DirectDebit.get()` diff --git a/examples/abortOrder.ts b/examples/abortOrder.ts index 57cc336..e01d047 100644 --- a/examples/abortOrder.ts +++ b/examples/abortOrder.ts @@ -1,6 +1,6 @@ import { createPayNLClient } from '../src'; -const payNL = createPayNLClient({ apiToken: 'your-api-token' }); +const payNL = createPayNLClient({ password: 'your-api-token' }); const orderId = '00000000-1111-2222-3333-000000000000'; diff --git a/examples/addPayment.ts b/examples/addPayment.ts index 299e9ae..3d4b794 100644 --- a/examples/addPayment.ts +++ b/examples/addPayment.ts @@ -1,6 +1,6 @@ import { createPayNLClient } from '../src'; -const payNL = createPayNLClient({ apiToken: 'your-api-token' }); +const payNL = createPayNLClient({ password: 'your-api-token' }); const orderId = '00000000-1111-2222-3333-000000000000'; diff --git a/examples/cancelOrder.ts b/examples/cancelOrder.ts index 48d52f2..589dc2f 100644 --- a/examples/cancelOrder.ts +++ b/examples/cancelOrder.ts @@ -1,6 +1,6 @@ import { createPayNLClient } from '../src'; -const payNL = createPayNLClient({ apiToken: 'your-api-token' }); +const payNL = createPayNLClient({ password: 'your-api-token' }); const orderId = '00000000-1111-2222-3333-000000000000'; diff --git a/examples/createOrder.ts b/examples/createOrder.ts index 0865bf0..62c4e7a 100644 --- a/examples/createOrder.ts +++ b/examples/createOrder.ts @@ -1,6 +1,6 @@ import { createPayNLClient, ApiError } from '../src'; -const payNL = createPayNLClient({ apiToken: 'your-api-token' }); +const payNL = createPayNLClient({ password: 'your-api-token' }); try { const order = await payNL.Orders.create({ diff --git a/examples/directDebit.ts b/examples/directDebit.ts index 44bd61d..1cd9fe8 100644 --- a/examples/directDebit.ts +++ b/examples/directDebit.ts @@ -1,9 +1,6 @@ import { createPayNLClient } from '../src'; -const payNL = createPayNLClient({ - apiToken: 'your-api-token', - ATCode: 'AT-1234-5678', -}); +const payNL = createPayNLClient({ username: 'AT-1234-5678', password: 'your-api-token' }); const mandate = await payNL.DirectDebit.createMandate({ serviceId: 'SL-1234-5678', diff --git a/examples/fetchOrder.ts b/examples/fetchOrder.ts index 171fe63..4bbc00d 100644 --- a/examples/fetchOrder.ts +++ b/examples/fetchOrder.ts @@ -1,6 +1,6 @@ import { createPayNLClient } from '../src'; -const payNL = createPayNLClient({ apiToken: 'your-api-token' }); +const payNL = createPayNLClient({ password: 'your-api-token' }); const orderId = '00000000-1111-2222-3333-000000000000'; diff --git a/examples/getPaymentMethods.ts b/examples/getPaymentMethods.ts index e036693..6fe4b69 100644 --- a/examples/getPaymentMethods.ts +++ b/examples/getPaymentMethods.ts @@ -1,10 +1,7 @@ import { createPayNLClient } from '../src'; -const payNL = createPayNLClient({ - apiToken: 'your-api-token', - ATCode: 'AT-1234-5678', -}); +const payNL = createPayNLClient({ username: 'AT-1234-5678', password: 'your-api-token' }); -const methods = await payNL.PaymentMethods.all('nl_NL'); +const methods = await payNL.Core.PaymentMethods('nl_NL'); console.log(methods.paymentMethods); diff --git a/examples/orderStatus.ts b/examples/orderStatus.ts index 46b203d..1d93afe 100644 --- a/examples/orderStatus.ts +++ b/examples/orderStatus.ts @@ -1,6 +1,6 @@ import { createPayNLClient } from '../src'; -const payNL = createPayNLClient({ apiToken: 'your-api-token' }); +const payNL = createPayNLClient({ password: 'your-api-token' }); const orderId = '00000000-1111-2222-3333-000000000000'; diff --git a/examples/serviceConfig.ts b/examples/serviceConfig.ts index b23e917..8f65f4c 100644 --- a/examples/serviceConfig.ts +++ b/examples/serviceConfig.ts @@ -1,6 +1,6 @@ import { createPayNLClient } from '../src'; -const payNL = createPayNLClient({ apiToken: 'your-api-token' }); +const payNL = createPayNLClient({ password: 'your-api-token' }); const config = await payNL.Service.getConfig('SL-1234-5678'); diff --git a/examples/updateOrder.ts b/examples/updateOrder.ts index 12862cf..9178ac3 100644 --- a/examples/updateOrder.ts +++ b/examples/updateOrder.ts @@ -1,6 +1,6 @@ import { createPayNLClient } from '../src'; -const payNL = createPayNLClient({ apiToken: 'your-api-token' }); +const payNL = createPayNLClient({ password: 'your-api-token' }); const orderId = '00000000-1111-2222-3333-000000000000'; diff --git a/examples/verifyOrder.ts b/examples/verifyOrder.ts index 6ce9ab6..570da2b 100644 --- a/examples/verifyOrder.ts +++ b/examples/verifyOrder.ts @@ -1,6 +1,6 @@ import { createPayNLClient } from '../src'; -const payNL = createPayNLClient({ apiToken: 'your-api-token' }); +const payNL = createPayNLClient({ password: 'your-api-token' }); const orderId = '00000000-1111-2222-3333-000000000000'; diff --git a/src/ApiClient.ts b/src/ApiClient.ts index 56e463f..dd6d0a3 100644 --- a/src/ApiClient.ts +++ b/src/ApiClient.ts @@ -4,8 +4,11 @@ import { ApiError } from './ApiError'; import { RestApiRequest } from './RestApiRequest'; export type ClientOptions = { - apiToken: string; - ATCode?: string; + /** + * This should be a token code formatted like `AT-1234-5678` + */ + username?: string; + password: string; }; type ApiRequest = ConnectApiRequest | RestApiRequest; diff --git a/src/ConnectApiRequest.ts b/src/ConnectApiRequest.ts index ae5e287..2d99101 100644 --- a/src/ConnectApiRequest.ts +++ b/src/ConnectApiRequest.ts @@ -14,17 +14,26 @@ export class ConnectApiRequest { getRequestInit(options: ClientOptions): RequestInit { const { json, ...fetchOptions } = this.fetchOptions; + return { headers: { Accept: 'application/json', 'Content-Type': 'application/json', - Authorization: `Bearer ${options.apiToken}`, + Authorization: this.getAuthorization(options), }, body: json ? JSON.stringify(json) : undefined, ...fetchOptions, }; } + getAuthorization(options: ClientOptions): string { + if (!options.username) { + return `Bearer ${options.password}`; + } + + return `Basic ${btoa(`${options.username}:${options.password}`)}`; + } + getUrl(): string { return this.url; } diff --git a/src/PayNLProvider.ts b/src/PayNLProvider.ts index 5d03502..1108ddf 100644 --- a/src/PayNLProvider.ts +++ b/src/PayNLProvider.ts @@ -1,13 +1,13 @@ import { OrderApi } from './order/OrderApi'; import { ApiClientInterface } from './ApiClient'; -import { PaymentMethodsApi } from './core/PaymentMethodsApi'; +import { CoreApi } from './core/CoreApi'; import { DirectDebitApi } from './directdebit/DirectDebitApi'; import { ServiceApi } from './service/ServiceApi'; export type PayNLProvider = { Orders: OrderApi; Client: ApiClientInterface; + Core: CoreApi; Service: ServiceApi; - PaymentMethods: PaymentMethodsApi; DirectDebit: DirectDebitApi; }; diff --git a/src/RestApiRequest.ts b/src/RestApiRequest.ts index a6dfd5a..4014537 100644 --- a/src/RestApiRequest.ts +++ b/src/RestApiRequest.ts @@ -15,9 +15,9 @@ export class RestApiRequest { getRequestInit(options: ClientOptions): RequestInit { const { json, headers, ...fetchOptions } = this.fetchOptions; - if (!options.ATCode) { + if (!options.username) { throw new Error( - 'Initialising the PayNL client with an ATCode is required to access the REST API.', + 'Initialising the PayNL client with a username is required to access the REST API.', ); } @@ -25,7 +25,7 @@ export class RestApiRequest { headers: { Accept: 'application/json', 'Content-Type': 'application/json', - Authorization: `Basic ${btoa(`${options.ATCode}:${options.apiToken}`)}`, + Authorization: `Basic ${btoa(`${options.username}:${options.password}`)}`, ...headers, }, body: json ? JSON.stringify(json) : undefined, diff --git a/src/core/PaymentMethodsApi.ts b/src/core/CoreApi.ts similarity index 79% rename from src/core/PaymentMethodsApi.ts rename to src/core/CoreApi.ts index d0b3a2f..ce037eb 100644 --- a/src/core/PaymentMethodsApi.ts +++ b/src/core/CoreApi.ts @@ -3,19 +3,19 @@ import { RestApiRequest } from '../RestApiRequest'; import { PaymentMethod } from './PaymentMethod'; import { LocaleCode } from '../shared'; -type AllResponse = { +type AllPaymentMethodsResponse = { total: number; paymentMethods: PaymentMethod[]; }; -export class PaymentMethodsApi { +export class CoreApi { constructor(private readonly apiClient: ApiClientInterface) {} /** * Get all payment methods. * @see https://developer.pay.nl/reference/payment_method_payment_methods_get */ - async all(locale: LocaleCode = 'en_GB') { + async PaymentMethods(locale: LocaleCode = 'en_GB') { const response = await this.apiClient.request( new RestApiRequest('v2/paymentmethods', { headers: { @@ -24,6 +24,6 @@ export class PaymentMethodsApi { }), ); - return await response.body(); + return await response.body(); } } diff --git a/src/createPayNLClient.ts b/src/createPayNLClient.ts index 5f601f4..4bc7bfd 100644 --- a/src/createPayNLClient.ts +++ b/src/createPayNLClient.ts @@ -1,7 +1,7 @@ import { ClientOptions, ApiClient } from './ApiClient'; import { PayNLProvider } from './PayNLProvider'; import { OrderApi } from './order/OrderApi'; -import { PaymentMethodsApi } from './core/PaymentMethodsApi'; +import { CoreApi } from './core/CoreApi'; import { DirectDebitApi } from './directdebit/DirectDebitApi'; import { ServiceApi } from './service/ServiceApi'; @@ -11,8 +11,8 @@ export function createPayNLClient(options: ClientOptions): PayNLProvider { return { Client: apiClient, Orders: new OrderApi(apiClient), + Core: new CoreApi(apiClient), Service: new ServiceApi(apiClient), - PaymentMethods: new PaymentMethodsApi(apiClient), DirectDebit: new DirectDebitApi(apiClient), }; } diff --git a/tests/ConnectApiRequest.test.ts b/tests/ConnectApiRequest.test.ts index 027b739..24e618e 100644 --- a/tests/ConnectApiRequest.test.ts +++ b/tests/ConnectApiRequest.test.ts @@ -9,7 +9,7 @@ describe('ConnectApiRequest', () => { method: 'PATCH', headers: { Accept: 'application/json', - Authorization: 'Bearer :api-token:', + Authorization: 'Basic QVQtMTIzNC01Njc4OjphcGktdG9rZW46', 'Content-Type': 'application/json', }, }; @@ -28,7 +28,7 @@ describe('ConnectApiRequest', () => { method: 'POST', headers: { Accept: 'application/json', - Authorization: 'Bearer :api-token:', + Authorization: 'Basic QVQtMTIzNC01Njc4OjphcGktdG9rZW46', 'Content-Type': 'application/json', }, body: JSON.stringify({ foo: 'bar' }), @@ -38,6 +38,26 @@ describe('ConnectApiRequest', () => { expect(subject.getRequestInit(mockClientOptions)).toEqual(expectedOptions); }); + it('can send request with only password', () => { + const subject = new ConnectApiRequest('v1/create-json', { + method: 'POST', + json: { foo: 'bar' }, + }); + + const expectedOptions = { + method: 'POST', + headers: { + Accept: 'application/json', + Authorization: 'Bearer :api-token:', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ foo: 'bar' }), + }; + + expect(subject.getUrl()).toBe('https://connect.pay.nl/v1/create-json'); + expect(subject.getRequestInit({ password: ':api-token:' })).toEqual(expectedOptions); + }); + it('can send form data in body', () => { const subject = new ConnectApiRequest('v1/create-form', { method: 'POST', @@ -48,7 +68,7 @@ describe('ConnectApiRequest', () => { method: 'POST', headers: { Accept: 'application/json', - Authorization: 'Bearer :api-token:', + Authorization: 'Basic QVQtMTIzNC01Njc4OjphcGktdG9rZW46', 'Content-Type': 'application/json', }, body: new FormData(), diff --git a/tests/RestApiRequest.test.ts b/tests/RestApiRequest.test.ts index 4a2f6c2..66577c6 100644 --- a/tests/RestApiRequest.test.ts +++ b/tests/RestApiRequest.test.ts @@ -44,11 +44,11 @@ describe('RestApiRequest', () => { await expect(async () => subject.getRequestInit({ - apiToken: ':api-token:', + password: ':api-token:', }), ).rejects.toThrow( new Error( - 'Initialising the PayNL client with an ATCode is required to access the REST API.', + 'Initialising the PayNL client with a username is required to access the REST API.', ), ); }); diff --git a/tests/core/PaymentMethodsApi.test.ts b/tests/core/CoreApi.test.ts similarity index 76% rename from tests/core/PaymentMethodsApi.test.ts rename to tests/core/CoreApi.test.ts index 1ef6d9d..09f1c91 100644 --- a/tests/core/PaymentMethodsApi.test.ts +++ b/tests/core/CoreApi.test.ts @@ -1,15 +1,15 @@ import { ApiClientMock } from '../support/ApiClientMock'; -import { PaymentMethodsApi } from '../../src/core/PaymentMethodsApi'; +import { CoreApi } from '../../src/core/CoreApi'; import { fakePaymentMethod } from '../support/fakePaymentMethods'; describe('PaymentMethodsApi', () => { it('should return a list of all payment methods', async () => { const clientMock = new ApiClientMock(); - const subject = new PaymentMethodsApi(clientMock.getMock()); + const subject = new CoreApi(clientMock.getMock()); clientMock.mockResponse({ total: 1, paymentMethods: [fakePaymentMethod] }); - const response = await subject.all('nl_NL'); + const response = await subject.PaymentMethods('nl_NL'); expect(response.paymentMethods).toEqual([fakePaymentMethod]); expect(clientMock.getRequest()).toEqual({ diff --git a/tests/createPayNLClient.test.ts b/tests/createPayNLClient.test.ts index 776026b..440f040 100644 --- a/tests/createPayNLClient.test.ts +++ b/tests/createPayNLClient.test.ts @@ -3,10 +3,10 @@ import { ClientOptions, createPayNLClient } from '../src'; describe('createPayNLClient', () => { it('should return a client class with the given options', () => { const givenOptions: ClientOptions = { - apiToken: 'your-api-token', + password: 'your-api-token', }; const expectedOptions = { - apiToken: 'your-api-token', + password: 'your-api-token', }; const result = createPayNLClient(givenOptions); diff --git a/tests/service/ServiceApi.test.ts b/tests/service/ServiceApi.test.ts index c6f5cdd..ec3422a 100644 --- a/tests/service/ServiceApi.test.ts +++ b/tests/service/ServiceApi.test.ts @@ -2,8 +2,6 @@ import { ApiClientMock } from '../support/ApiClientMock'; import { fakeConfig } from '../support/fakeConfig'; import { ServiceApi } from '../../src/service/ServiceApi'; -jest.mock('request'); - describe('ServiceApi', () => { it('can fetch service location config', async () => { const clientMock = new ApiClientMock(); diff --git a/tests/support/mockClientOptions.ts b/tests/support/mockClientOptions.ts index 44dcaa5..be72885 100644 --- a/tests/support/mockClientOptions.ts +++ b/tests/support/mockClientOptions.ts @@ -1,6 +1,6 @@ import { ClientOptions } from '../../src'; export const mockClientOptions: ClientOptions = { - apiToken: ':api-token:', - ATCode: 'AT-1234-5678', + username: 'AT-1234-5678', + password: ':api-token:', };