Skip to content

Commit 8aafcf9

Browse files
jillingkwboereboomAleffio
authored
Management Webhooks (#1242)
* add management webhooks * remove any return type on generic webhook * removed unused import * Update README.md Co-authored-by: Wouter Boereboom <62436079+wboereboom@users.noreply.github.com> * Update README.md Co-authored-by: Alessio Zampatti <gigendh@gmail.com> * Update README.md Co-authored-by: Alessio Zampatti <gigendh@gmail.com> * fix test --------- Co-authored-by: Wouter Boereboom <62436079+wboereboom@users.noreply.github.com> Co-authored-by: Alessio Zampatti <gigendh@gmail.com>
1 parent efa0ceb commit 8aafcf9

21 files changed

+1244
-46
lines changed

Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ openapi-generator-url:=https://repo1.maven.org/maven2/org/openapitools/openapi-g
44
openapi-generator-jar:=build/openapi-generator-cli.jar
55
openapi-generator-cli:=java -jar $(openapi-generator-jar)
66

7-
services:=acsWebhooks balanceControl balancePlatform binLookup checkout configurationWebhooks dataProtection legalEntityManagement management payment payout recurring reportWebhooks storedValue terminalManagement transfer transferWebhooks
7+
services:=acsWebhooks balanceControl balancePlatform binLookup checkout configurationWebhooks dataProtection legalEntityManagement management managementWebhooks payment payout recurring reportWebhooks storedValue terminalManagement transfer transferWebhooks
88

99
# Generate models (for each service)
1010
models: $(services)
@@ -32,6 +32,8 @@ acsWebhooks: spec=BalancePlatformAcsNotification-v1
3232
configurationWebhooks: spec=BalancePlatformConfigurationNotification-v1
3333
reportWebhooks: spec=BalancePlatformReportNotification-v1
3434
transferWebhooks: spec=BalancePlatformTransferNotification-v3
35+
# ManagementWebhooks
36+
managementWebhooks: spec=ManagementNotificationService-v1
3537

3638
$(services): build/spec $(openapi-generator-jar)
3739
rm -rf src/typings/$@ build/model

README.md

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,15 @@ This library supports the following:
3939
## Supported Webhook versions
4040
The library supports all webhooks under the following model directories:
4141

42-
| Webhooks | Description | Model Name | Supported Version |
43-
|---------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|-------------------|
44-
| [Authentication Webhooks](https://docs.adyen.com/api-explorer/acs-webhook/1/overview) | Adyen sends this webhook when the process of cardholder authentication is finalized, whether it is completed successfully, fails, or expires. | [AcsWebhooks](src/typings/acsWebhooks) | **v1** |
45-
| [Configuration Webhooks](https://docs.adyen.com/api-explorer/balanceplatform-webhooks/1/overview) | You can use these webhooks to build your implementation. For example, you can use this information to update internal statuses when the status of a capability is changed. | [ConfigurationWebhooks](src/typings/configurationWebhooks) | **v1** |
46-
| [Transfer Webhooks](https://docs.adyen.com/api-explorer/transfer-webhooks/3/overview) | You can use these webhooks to build your implementation. For example, you can use this information to update balances in your own dashboards or to keep track of incoming funds. | [TransferWebhooks](src/typings/transferWebhooks) | **v3** |
47-
| [Report Webhooks](https://docs.adyen.com/api-explorer/report-webhooks/1/overview) | You can download reports programmatically by making an HTTP GET request, or manually from your Balance Platform Customer Area | [ReportWebhooks](src/typings/reportWebhooks) | **v1** |
48-
| [Notification Webhooks](https://docs.adyen.com/api-explorer/Webhooks/1/overview) | We use webhooks to send you updates about payment status updates, newly available reports, and other events that you can subscribe to. For more information, refer to our documentation | [Notification](src/typings/notification) | **v1** |
42+
| Webhooks | Description | Model Name | Supported Version |
43+
|---------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------|-------------------|
44+
| [Authentication Webhooks](https://docs.adyen.com/api-explorer/acs-webhook/1/overview) | Adyen sends this webhook when the process of cardholder authentication is finalized, whether it is completed successfully, fails, or expires. | [AcsWebhooks](src/typings/acsWebhooks) | **v1** |
45+
| [Configuration Webhooks](https://docs.adyen.com/api-explorer/balanceplatform-webhooks/1/overview) | You can use these webhooks to build your implementation. For example, you can use this information to update internal statuses when the status of a capability is changed. | [ConfigurationNotification](src/typings/configurationWebhooks) | **v1** |
46+
| [Transfer Webhooks](https://docs.adyen.com/api-explorer/transfer-webhooks/3/overview) | You can use these webhooks to build your implementation. For example, you can use this information to update balances in your own dashboards or to keep track of incoming funds. | [TransferNotification](src/typings/transferWebhooks) | **v3** |
47+
| [Report Webhooks](https://docs.adyen.com/api-explorer/report-webhooks/1/overview) | You can download reports programmatically by making an HTTP GET request, or manually from your Balance Platform Customer Area | [ReportNotification](src/typings/reportWebhooks) | **v1** |
48+
| [Management Webhooks](https://docs.adyen.com/api-explorer/ManagementNotification/1/overview) | Adyen uses webhooks to inform your system about events that happen with your Adyen company and merchant accounts, stores, payment terminals, and payment methods when using Management API. | [ManagementWebhooks](src/typings/managementWebhooks) | **v1** |
49+
| [Notification Webhooks](https://docs.adyen.com/api-explorer/Webhooks/1/overview) | We use webhooks to send you updates about payment status updates, newly available reports, and other events that you can subscribe to. For more information, refer to our documentation | [Notification](src/typings/notification) | **v1** |
50+
4951
For more information, refer to our [documentation](https://docs.adyen.com/) or the [API Explorer](https://docs.adyen.com/api-explorer/).
5052

5153
## Before you begin
@@ -269,7 +271,7 @@ let bankingWebhookHandler = new BankingWebhookHandler(YOUR_BANKING_WEBHOOK);
269271
const accountHolderNotificationRequest: AccountHolderNotificationRequest = bankingWebhookHandler.getAccountHolderNotificationRequest();
270272
const genericWebhook = bankingWebhookHandler.getGenericWebhook();
271273
```
272-
Parse a generic Banking webhook;
274+
You can also parse the webhook with a generic type, in case you do not know the webhook type in advance. In this case you can check the instance of the webhook in order to parse it to the respective type (or just use it dynamically);
273275
``` typescript
274276
let bankingWebhookHandler = new BankingWebhookHandler(YOUR_BANKING_WEBHOOK);
275277
const genericWebhook = bankingWebhookHandler.getGenericWebhook();
@@ -278,6 +280,12 @@ Verify the authenticity (where you retrieve the hmac key from the CA and the sig
278280
``` typescript
279281
const isValid = hmacValidator.validateBankingHMAC("YOUR_HMAC_KEY", "YOUR_HMAC_SIGNATURE", jsonString)
280282
```
283+
## Management Webhooks
284+
Management webhooks are verified the exact same way as the banking webhooks. To parse them however, instead you use:
285+
``` typescript
286+
let managementWebhookHandler = new ManagementWebhookHandler(YOUR_MANAGEMENT_WEBHOOK);
287+
const genericWebhook = managementWebhookHandler.getGenericWebhook();
288+
```
281289

282290
## Proxy configuration
283291

src/__tests__/notification.spec.ts

Lines changed: 77 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ import SuccessEnum = NotificationRequestItem.SuccessEnum;
1010
import BankingWebhookHandler from "../notification/bankingWebhookHandler";
1111
import {AccountHolderNotificationRequest} from "../typings/configurationWebhooks/accountHolderNotificationRequest";
1212
import HmacValidator from "../utils/hmacValidator";
13+
import ManagementWebhookHandler from "../notification/managementWebhookHandler";
14+
import {
15+
PaymentMethodCreatedNotificationRequest
16+
} from "../typings/managementWebhooks/paymentMethodCreatedNotificationRequest";
17+
import {MerchantUpdatedNotificationRequest} from "../typings/managementWebhooks/merchantUpdatedNotificationRequest";
1318
import {AuthenticationNotificationRequest} from "../typings/acsWebhooks/authenticationNotificationRequest";
1419
import {TransferNotificationRequest} from "../typings/transferWebhooks/transferNotificationRequest";
1520

@@ -20,7 +25,7 @@ describe("Notification Test", function (): void {
2025
hmacValidator = new HmacValidator();
2126
});
2227

23-
it("should return authorisation success", function (): void {
28+
it("should return authorisation success", function (): void {
2429
const notificationRequest = new NotificationRequest(authorisationTrue as unknown as Notification);
2530
expect(notificationRequest.notificationItems).toHaveLength(1);
2631

@@ -100,7 +105,21 @@ describe("Notification Test", function (): void {
100105
});
101106

102107
it("should deserialize Banking Webhooks", function (): void {
103-
const json = { "data": {"balancePlatform":"YOUR_BALANCE_PLATFORM","accountHolder":{"contactDetails":{"address":{"country":"NL","houseNumberOrName":"274","postalCode":"1020CD","street":"Brannan Street"},"email": "s.hopper@example.com","phone": {"number": "+315551231234","type": "Mobile"}},"description": "S.Hopper - Staff 123","id": "AH00000000000000000000001","status": "Active"}},"environment": "test","type": "balancePlatform.accountHolder.created"};
108+
const json = {
109+
"data": {
110+
"balancePlatform": "YOUR_BALANCE_PLATFORM",
111+
"accountHolder": {
112+
"contactDetails": {
113+
"address": {
114+
"country": "NL",
115+
"houseNumberOrName": "274",
116+
"postalCode": "1020CD",
117+
"street": "Brannan Street"
118+
}, "email": "s.hopper@example.com", "phone": {"number": "+315551231234", "type": "Mobile"}
119+
}, "description": "S.Hopper - Staff 123", "id": "AH00000000000000000000001", "status": "Active"
120+
}
121+
}, "environment": "test", "type": "balancePlatform.accountHolder.created"
122+
};
104123
const jsonString = JSON.stringify(json);
105124
let bankingWebhookHandler = new BankingWebhookHandler(jsonString);
106125
const accountHolderNotificationRequest: AccountHolderNotificationRequest = bankingWebhookHandler.getAccountHolderNotificationRequest();
@@ -115,47 +134,69 @@ describe("Notification Test", function (): void {
115134
expect(isValid).toBe(true)
116135
});
117136

137+
it("should deserialize Management Webhooks", function (): void {
138+
const json = {
139+
"createdAt": "2022-01-24T14:59:11+01:00",
140+
"data": {
141+
"id": "PM3224R223224K5FH4M2K9B86",
142+
"merchantId": "MERCHANT_ACCOUNT",
143+
"result": "SUCCESS",
144+
"storeId": "ST322LJ223223K5F4SQNR9XL5",
145+
"type": "visa"
146+
},
147+
"environment": "test",
148+
"type": "paymentMethod.created"
149+
};
150+
const jsonString = JSON.stringify(json);
151+
let managementWebhookHandler = new ManagementWebhookHandler(jsonString);
152+
const paymentMethodCreatedNotificationRequest: PaymentMethodCreatedNotificationRequest = managementWebhookHandler.getPaymentMethodCreatedNotificationRequest();
153+
const genericWebhook = managementWebhookHandler.getGenericWebhook();
154+
expect(genericWebhook instanceof PaymentMethodCreatedNotificationRequest).toBe(true)
155+
expect(genericWebhook instanceof MerchantUpdatedNotificationRequest).toBe(false)
156+
expect(paymentMethodCreatedNotificationRequest.type).toEqual(PaymentMethodCreatedNotificationRequest.TypeEnum.PaymentMethodCreated)
157+
});
158+
118159
it("should deserialize Banking Authentication Webhook", function (): void {
119160
const json = {
120-
"data" : {
121-
"balancePlatform" : "YOUR_BALANCE_PLATFORM",
122-
"creationDate" : "2023-01-19T17:07:59+01:00",
123-
"id" : "a8fc7a40-6e48-498a-bdc2-494daf0f490a",
124-
"authentication" : {
125-
"acsTransId" : "a8fc7a40-6e48-498a-bdc2-494daf0f490a",
126-
"challenge" : {
127-
"flow" : "OTP_SMS",
128-
"lastInteraction" : "2023-01-19T17:37:13+01:00",
129-
"phoneNumber" : "******6789",
130-
"resends" : 0,
131-
"retries" : 2
161+
"data": {
162+
"balancePlatform": "YOUR_BALANCE_PLATFORM",
163+
"creationDate": "2023-01-19T17:07:59+01:00",
164+
"id": "a8fc7a40-6e48-498a-bdc2-494daf0f490a",
165+
"authentication": {
166+
"acsTransId": "a8fc7a40-6e48-498a-bdc2-494daf0f490a",
167+
"challenge": {
168+
"flow": "OTP_SMS",
169+
"lastInteraction": "2023-01-19T17:37:13+01:00",
170+
"phoneNumber": "******6789",
171+
"resends": 0,
172+
"retries": 2
132173
},
133-
"challengeIndicator" : "01",
134-
"createdAt" : "2023-01-19T17:07:17+01:00",
135-
"deviceChannel" : "app",
136-
"dsTransID" : "59de4e30-7f84-4a77-aaf8-1ca493092ef9",
137-
"exemptionIndicator" : "noExemptionApplied",
138-
"inPSD2Scope" : false,
139-
"messageCategory" : "payment",
140-
"messageVersion" : "2.2.0",
141-
"threeDSServerTransID" : "8bc0fdbd-5c8a-4bed-a171-9d10347e7798",
142-
"transStatus" : "N",
143-
"transStatusReason" : "19",
144-
"type" : "challenge"
174+
"challengeIndicator": "01",
175+
"createdAt": "2023-01-19T17:07:17+01:00",
176+
"deviceChannel": "app",
177+
"dsTransID": "59de4e30-7f84-4a77-aaf8-1ca493092ef9",
178+
"exemptionIndicator": "noExemptionApplied",
179+
"inPSD2Scope": false,
180+
"messageCategory": "payment",
181+
"messageVersion": "2.2.0",
182+
"threeDSServerTransID": "8bc0fdbd-5c8a-4bed-a171-9d10347e7798",
183+
"transStatus": "N",
184+
"transStatusReason": "19",
185+
"type": "challenge"
145186
},
146-
"paymentInstrumentId" : "PI3227C223222B5BPCMFXD2XG",
147-
"purchase" : {
148-
"date" : "2022-12-22T15:49:03+01:00",
149-
"merchantName" : "TeaShop_NL",
150-
"originalAmount" : {
151-
"currency" : "EUR",
152-
"value" : 1000
187+
"paymentInstrumentId": "PI3227C223222B5BPCMFXD2XG",
188+
"purchase": {
189+
"date": "2022-12-22T15:49:03+01:00",
190+
"merchantName": "TeaShop_NL",
191+
"originalAmount": {
192+
"currency": "EUR",
193+
"value": 1000
153194
}
154195
},
155-
"status" : "rejected"
196+
"status": "rejected"
156197
},
157-
"environment" : "test",
158-
"type" : "balancePlatform.authentication.created"
198+
"environment": "test",
199+
"type": "balancePlatform.authentication.created"
159200
};
160201
const jsonString = JSON.stringify(json);
161202
let bankingWebhookHandler = new BankingWebhookHandler(jsonString);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Adyen NodeJS API Library
3+
* Copyright (c) 2023 Adyen B.V.
4+
* This file is open source and available under the MIT license.
5+
* See the LICENSE file for more info.
6+
*/
7+
import {managementWebhooks} from "../typings";
8+
9+
class ManagementWebhookHandler {
10+
private readonly payload: string;
11+
12+
public constructor(jsonPayload: string) {
13+
this.payload = JSON.parse(jsonPayload)
14+
}
15+
16+
// Return generic webhook type
17+
public getGenericWebhook(): managementWebhooks.MerchantUpdatedNotificationRequest
18+
| managementWebhooks.MerchantCreatedNotificationRequest
19+
| managementWebhooks.PaymentMethodCreatedNotificationRequest {
20+
const type = this.payload['type'];
21+
if(Object.values(managementWebhooks.MerchantCreatedNotificationRequest.TypeEnum).includes(type)){
22+
return this.getMerchantCreatedNotificationRequest();
23+
}
24+
25+
if(Object.values(managementWebhooks.MerchantUpdatedNotificationRequest.TypeEnum).includes(type)){
26+
return this.getMerchantUpdatedNotificationRequest();
27+
}
28+
29+
if(Object.values(managementWebhooks.PaymentMethodCreatedNotificationRequest.TypeEnum).includes(type)){
30+
return this.getPaymentMethodCreatedNotificationRequest();
31+
}
32+
33+
throw new Error("Could not parse the json payload: " + this.payload)
34+
}
35+
36+
public getMerchantCreatedNotificationRequest(): managementWebhooks.MerchantCreatedNotificationRequest {
37+
return managementWebhooks.ObjectSerializer.deserialize(this.payload, "MerchantCreatedNotificationRequest");
38+
}
39+
40+
public getMerchantUpdatedNotificationRequest(): managementWebhooks.MerchantUpdatedNotificationRequest {
41+
return managementWebhooks.ObjectSerializer.deserialize(this.payload, "MerchantUpdatedNotificationRequest");
42+
}
43+
44+
public getPaymentMethodCreatedNotificationRequest(): managementWebhooks.PaymentMethodCreatedNotificationRequest {
45+
return managementWebhooks.ObjectSerializer.deserialize(this.payload, "PaymentMethodCreatedNotificationRequest");
46+
}
47+
48+
}
49+
50+
export default ManagementWebhookHandler;

src/typings/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,5 @@ export * as dataProtection from './dataProtection/models';
3030
export * as configurationWebhooks from './configurationWebhooks/models';
3131
export * as reportWebhooks from './reportWebhooks/models';
3232
export * as transferWebhooks from './transferWebhooks/models';
33-
export * as acsWebhooks from './acsWebhooks/models';
33+
export * as managementWebhooks from './managementWebhooks/models';
34+
export * as acsWebhooks from './acsWebhooks/models';

0 commit comments

Comments
 (0)