mollie-api-typescript 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -0
- package/dist/commonjs/funcs/mandatesList.js +1 -0
- package/dist/commonjs/funcs/mandatesList.js.map +1 -1
- package/dist/commonjs/index.d.ts +1 -0
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +1 -0
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/lib/config.d.ts +2 -2
- package/dist/commonjs/lib/config.js +2 -2
- package/dist/commonjs/models/billingaddress.d.ts +2 -0
- package/dist/commonjs/models/billingaddress.d.ts.map +1 -1
- package/dist/commonjs/models/billingaddress.js.map +1 -1
- package/dist/commonjs/models/clientlinkrequest.d.ts +4 -0
- package/dist/commonjs/models/clientlinkrequest.d.ts.map +1 -1
- package/dist/commonjs/models/clientlinkrequest.js.map +1 -1
- package/dist/commonjs/models/customerresponse.d.ts +4 -0
- package/dist/commonjs/models/customerresponse.d.ts.map +1 -1
- package/dist/commonjs/models/customerresponse.js.map +1 -1
- package/dist/commonjs/models/entitycustomer.d.ts +4 -0
- package/dist/commonjs/models/entitycustomer.d.ts.map +1 -1
- package/dist/commonjs/models/entitycustomer.js.map +1 -1
- package/dist/commonjs/models/entityorganization.d.ts +4 -0
- package/dist/commonjs/models/entityorganization.d.ts.map +1 -1
- package/dist/commonjs/models/entityorganization.js.map +1 -1
- package/dist/commonjs/models/index.d.ts +1 -0
- package/dist/commonjs/models/index.d.ts.map +1 -1
- package/dist/commonjs/models/index.js +1 -0
- package/dist/commonjs/models/index.js.map +1 -1
- package/dist/commonjs/models/listcustomerresponse.d.ts +4 -0
- package/dist/commonjs/models/listcustomerresponse.d.ts.map +1 -1
- package/dist/commonjs/models/listcustomerresponse.js.map +1 -1
- package/dist/commonjs/models/listmandateresponse.d.ts +26 -0
- package/dist/commonjs/models/listmandateresponse.d.ts.map +1 -1
- package/dist/commonjs/models/listmandateresponse.js +15 -1
- package/dist/commonjs/models/listmandateresponse.js.map +1 -1
- package/dist/commonjs/models/listpaymentresponse.d.ts +5 -3
- package/dist/commonjs/models/listpaymentresponse.d.ts.map +1 -1
- package/dist/commonjs/models/listpaymentresponse.js.map +1 -1
- package/dist/commonjs/models/listprofileresponse.d.ts +4 -0
- package/dist/commonjs/models/listprofileresponse.d.ts.map +1 -1
- package/dist/commonjs/models/listprofileresponse.js.map +1 -1
- package/dist/commonjs/models/listsettlementpaymentresponse.d.ts +5 -3
- package/dist/commonjs/models/listsettlementpaymentresponse.d.ts.map +1 -1
- package/dist/commonjs/models/listsettlementpaymentresponse.js.map +1 -1
- package/dist/commonjs/models/mandateresponse.d.ts +26 -0
- package/dist/commonjs/models/mandateresponse.d.ts.map +1 -1
- package/dist/commonjs/models/mandateresponse.js +14 -1
- package/dist/commonjs/models/mandateresponse.js.map +1 -1
- package/dist/commonjs/models/mandatescopes.d.ts +22 -0
- package/dist/commonjs/models/mandatescopes.d.ts.map +1 -0
- package/dist/commonjs/models/mandatescopes.js +54 -0
- package/dist/commonjs/models/mandatescopes.js.map +1 -0
- package/dist/commonjs/models/operations/getcustomer.d.ts +4 -0
- package/dist/commonjs/models/operations/getcustomer.d.ts.map +1 -1
- package/dist/commonjs/models/operations/getcustomer.js.map +1 -1
- package/dist/commonjs/models/operations/listmandates.d.ts +5 -0
- package/dist/commonjs/models/operations/listmandates.d.ts.map +1 -1
- package/dist/commonjs/models/operations/listmandates.js +1 -0
- package/dist/commonjs/models/operations/listmandates.js.map +1 -1
- package/dist/commonjs/models/operations/submitonboardingdata.d.ts +4 -0
- package/dist/commonjs/models/operations/submitonboardingdata.d.ts.map +1 -1
- package/dist/commonjs/models/operations/submitonboardingdata.js.map +1 -1
- package/dist/commonjs/models/operations/updatecustomer.d.ts +4 -0
- package/dist/commonjs/models/operations/updatecustomer.d.ts.map +1 -1
- package/dist/commonjs/models/operations/updatecustomer.js.map +1 -1
- package/dist/commonjs/models/operations/updateprofile.d.ts +4 -0
- package/dist/commonjs/models/operations/updateprofile.d.ts.map +1 -1
- package/dist/commonjs/models/operations/updateprofile.js.map +1 -1
- package/dist/commonjs/models/paymentaddress.d.ts +2 -0
- package/dist/commonjs/models/paymentaddress.d.ts.map +1 -1
- package/dist/commonjs/models/paymentaddress.js.map +1 -1
- package/dist/commonjs/models/paymentrequest.d.ts +13 -3
- package/dist/commonjs/models/paymentrequest.d.ts.map +1 -1
- package/dist/commonjs/models/paymentrequest.js +1 -0
- package/dist/commonjs/models/paymentrequest.js.map +1 -1
- package/dist/commonjs/models/paymentresponse.d.ts +5 -3
- package/dist/commonjs/models/paymentresponse.d.ts.map +1 -1
- package/dist/commonjs/models/paymentresponse.js.map +1 -1
- package/dist/commonjs/models/profilerequest.d.ts +4 -0
- package/dist/commonjs/models/profilerequest.d.ts.map +1 -1
- package/dist/commonjs/models/profilerequest.js.map +1 -1
- package/dist/commonjs/models/profileresponse.d.ts +4 -0
- package/dist/commonjs/models/profileresponse.d.ts.map +1 -1
- package/dist/commonjs/models/profileresponse.js.map +1 -1
- package/dist/commonjs/models/salesinvoicerecipient.d.ts +4 -0
- package/dist/commonjs/models/salesinvoicerecipient.d.ts.map +1 -1
- package/dist/commonjs/models/salesinvoicerecipient.js.map +1 -1
- package/dist/commonjs/models/salesinvoicerecipientresponse.d.ts +4 -0
- package/dist/commonjs/models/salesinvoicerecipientresponse.d.ts.map +1 -1
- package/dist/commonjs/models/salesinvoicerecipientresponse.js.map +1 -1
- package/dist/commonjs/utils/webhooks/index.d.ts +2 -0
- package/dist/commonjs/utils/webhooks/index.d.ts.map +1 -0
- package/dist/commonjs/utils/webhooks/index.js +7 -0
- package/dist/commonjs/utils/webhooks/index.js.map +1 -0
- package/dist/commonjs/utils/webhooks/signature_validator.d.ts +17 -0
- package/dist/commonjs/utils/webhooks/signature_validator.d.ts.map +1 -0
- package/dist/commonjs/utils/webhooks/signature_validator.js +88 -0
- package/dist/commonjs/utils/webhooks/signature_validator.js.map +1 -0
- package/dist/esm/funcs/mandatesList.js +1 -0
- package/dist/esm/funcs/mandatesList.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/config.d.ts +2 -2
- package/dist/esm/lib/config.js +2 -2
- package/dist/esm/models/billingaddress.d.ts +2 -0
- package/dist/esm/models/billingaddress.d.ts.map +1 -1
- package/dist/esm/models/billingaddress.js.map +1 -1
- package/dist/esm/models/clientlinkrequest.d.ts +4 -0
- package/dist/esm/models/clientlinkrequest.d.ts.map +1 -1
- package/dist/esm/models/clientlinkrequest.js.map +1 -1
- package/dist/esm/models/customerresponse.d.ts +4 -0
- package/dist/esm/models/customerresponse.d.ts.map +1 -1
- package/dist/esm/models/customerresponse.js.map +1 -1
- package/dist/esm/models/entitycustomer.d.ts +4 -0
- package/dist/esm/models/entitycustomer.d.ts.map +1 -1
- package/dist/esm/models/entitycustomer.js.map +1 -1
- package/dist/esm/models/entityorganization.d.ts +4 -0
- package/dist/esm/models/entityorganization.d.ts.map +1 -1
- package/dist/esm/models/entityorganization.js.map +1 -1
- package/dist/esm/models/index.d.ts +1 -0
- package/dist/esm/models/index.d.ts.map +1 -1
- package/dist/esm/models/index.js +1 -0
- package/dist/esm/models/index.js.map +1 -1
- package/dist/esm/models/listcustomerresponse.d.ts +4 -0
- package/dist/esm/models/listcustomerresponse.d.ts.map +1 -1
- package/dist/esm/models/listcustomerresponse.js.map +1 -1
- package/dist/esm/models/listmandateresponse.d.ts +26 -0
- package/dist/esm/models/listmandateresponse.d.ts.map +1 -1
- package/dist/esm/models/listmandateresponse.js +14 -0
- package/dist/esm/models/listmandateresponse.js.map +1 -1
- package/dist/esm/models/listpaymentresponse.d.ts +5 -3
- package/dist/esm/models/listpaymentresponse.d.ts.map +1 -1
- package/dist/esm/models/listpaymentresponse.js.map +1 -1
- package/dist/esm/models/listprofileresponse.d.ts +4 -0
- package/dist/esm/models/listprofileresponse.d.ts.map +1 -1
- package/dist/esm/models/listprofileresponse.js.map +1 -1
- package/dist/esm/models/listsettlementpaymentresponse.d.ts +5 -3
- package/dist/esm/models/listsettlementpaymentresponse.d.ts.map +1 -1
- package/dist/esm/models/listsettlementpaymentresponse.js.map +1 -1
- package/dist/esm/models/mandateresponse.d.ts +26 -0
- package/dist/esm/models/mandateresponse.d.ts.map +1 -1
- package/dist/esm/models/mandateresponse.js +13 -0
- package/dist/esm/models/mandateresponse.js.map +1 -1
- package/dist/esm/models/mandatescopes.d.ts +22 -0
- package/dist/esm/models/mandatescopes.d.ts.map +1 -0
- package/dist/esm/models/mandatescopes.js +18 -0
- package/dist/esm/models/mandatescopes.js.map +1 -0
- package/dist/esm/models/operations/getcustomer.d.ts +4 -0
- package/dist/esm/models/operations/getcustomer.d.ts.map +1 -1
- package/dist/esm/models/operations/getcustomer.js.map +1 -1
- package/dist/esm/models/operations/listmandates.d.ts +5 -0
- package/dist/esm/models/operations/listmandates.d.ts.map +1 -1
- package/dist/esm/models/operations/listmandates.js +1 -0
- package/dist/esm/models/operations/listmandates.js.map +1 -1
- package/dist/esm/models/operations/submitonboardingdata.d.ts +4 -0
- package/dist/esm/models/operations/submitonboardingdata.d.ts.map +1 -1
- package/dist/esm/models/operations/submitonboardingdata.js.map +1 -1
- package/dist/esm/models/operations/updatecustomer.d.ts +4 -0
- package/dist/esm/models/operations/updatecustomer.d.ts.map +1 -1
- package/dist/esm/models/operations/updatecustomer.js.map +1 -1
- package/dist/esm/models/operations/updateprofile.d.ts +4 -0
- package/dist/esm/models/operations/updateprofile.d.ts.map +1 -1
- package/dist/esm/models/operations/updateprofile.js.map +1 -1
- package/dist/esm/models/paymentaddress.d.ts +2 -0
- package/dist/esm/models/paymentaddress.d.ts.map +1 -1
- package/dist/esm/models/paymentaddress.js.map +1 -1
- package/dist/esm/models/paymentrequest.d.ts +13 -3
- package/dist/esm/models/paymentrequest.d.ts.map +1 -1
- package/dist/esm/models/paymentrequest.js +1 -0
- package/dist/esm/models/paymentrequest.js.map +1 -1
- package/dist/esm/models/paymentresponse.d.ts +5 -3
- package/dist/esm/models/paymentresponse.d.ts.map +1 -1
- package/dist/esm/models/paymentresponse.js.map +1 -1
- package/dist/esm/models/profilerequest.d.ts +4 -0
- package/dist/esm/models/profilerequest.d.ts.map +1 -1
- package/dist/esm/models/profilerequest.js.map +1 -1
- package/dist/esm/models/profileresponse.d.ts +4 -0
- package/dist/esm/models/profileresponse.d.ts.map +1 -1
- package/dist/esm/models/profileresponse.js.map +1 -1
- package/dist/esm/models/salesinvoicerecipient.d.ts +4 -0
- package/dist/esm/models/salesinvoicerecipient.d.ts.map +1 -1
- package/dist/esm/models/salesinvoicerecipient.js.map +1 -1
- package/dist/esm/models/salesinvoicerecipientresponse.d.ts +4 -0
- package/dist/esm/models/salesinvoicerecipientresponse.d.ts.map +1 -1
- package/dist/esm/models/salesinvoicerecipientresponse.js.map +1 -1
- package/dist/esm/utils/webhooks/index.d.ts +2 -0
- package/dist/esm/utils/webhooks/index.d.ts.map +1 -0
- package/dist/esm/utils/webhooks/index.js +2 -0
- package/dist/esm/utils/webhooks/index.js.map +1 -0
- package/dist/esm/utils/webhooks/signature_validator.d.ts +17 -0
- package/dist/esm/utils/webhooks/signature_validator.d.ts.map +1 -0
- package/dist/esm/utils/webhooks/signature_validator.js +83 -0
- package/dist/esm/utils/webhooks/signature_validator.js.map +1 -0
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/funcs/mandatesList.ts +1 -0
- package/src/index.ts +1 -0
- package/src/lib/config.ts +2 -2
- package/src/models/billingaddress.ts +2 -0
- package/src/models/clientlinkrequest.ts +4 -0
- package/src/models/customerresponse.ts +4 -0
- package/src/models/entitycustomer.ts +4 -0
- package/src/models/entityorganization.ts +4 -0
- package/src/models/index.ts +1 -0
- package/src/models/listcustomerresponse.ts +4 -0
- package/src/models/listmandateresponse.ts +36 -0
- package/src/models/listpaymentresponse.ts +5 -3
- package/src/models/listprofileresponse.ts +4 -0
- package/src/models/listsettlementpaymentresponse.ts +5 -3
- package/src/models/mandateresponse.ts +33 -0
- package/src/models/mandatescopes.ts +30 -0
- package/src/models/operations/getcustomer.ts +4 -0
- package/src/models/operations/listmandates.ts +6 -0
- package/src/models/operations/submitonboardingdata.ts +4 -0
- package/src/models/operations/updatecustomer.ts +4 -0
- package/src/models/operations/updateprofile.ts +4 -0
- package/src/models/paymentaddress.ts +2 -0
- package/src/models/paymentrequest.ts +14 -3
- package/src/models/paymentresponse.ts +5 -3
- package/src/models/profilerequest.ts +4 -0
- package/src/models/profileresponse.ts +4 -0
- package/src/models/salesinvoicerecipient.ts +4 -0
- package/src/models/salesinvoicerecipientresponse.ts +4 -0
- package/src/utils/webhooks/index.ts +4 -0
- package/src/utils/webhooks/signature_validator.ts +136 -0
|
@@ -23,6 +23,10 @@ export type UpdateProfileRequestBody = {
|
|
|
23
23
|
website?: string | null | undefined;
|
|
24
24
|
/**
|
|
25
25
|
* The email address associated with the profile's trade name or brand.
|
|
26
|
+
*
|
|
27
|
+
* @remarks
|
|
28
|
+
*
|
|
29
|
+
* If the domain contains non-ASCII characters, encode it as Punycode per [RFC 3492](https://www.rfc-editor.org/rfc/rfc3492).
|
|
26
30
|
*/
|
|
27
31
|
email?: string | null | undefined;
|
|
28
32
|
/**
|
|
@@ -64,6 +64,8 @@ export type PaymentAddress = {
|
|
|
64
64
|
* email upon payment creation. The language of the email will follow the locale parameter of the payment.
|
|
65
65
|
*
|
|
66
66
|
* Required for payment methods `billie`, `in3`, `klarna` and `riverty`.
|
|
67
|
+
*
|
|
68
|
+
* If the domain contains non-ASCII characters, encode it as Punycode per [RFC 3492](https://www.rfc-editor.org/rfc/rfc3492).
|
|
67
69
|
*/
|
|
68
70
|
email?: string | undefined;
|
|
69
71
|
/**
|
|
@@ -176,6 +176,8 @@ export type PaymentRequestBillingAddress = {
|
|
|
176
176
|
* email upon payment creation. The language of the email will follow the locale parameter of the payment.
|
|
177
177
|
*
|
|
178
178
|
* Required for payment methods `billie`, `in3`, `klarna` and `riverty`.
|
|
179
|
+
*
|
|
180
|
+
* If the domain contains non-ASCII characters, encode it as Punycode per [RFC 3492](https://www.rfc-editor.org/rfc/rfc3492).
|
|
179
181
|
*/
|
|
180
182
|
email?: string | undefined;
|
|
181
183
|
/**
|
|
@@ -443,12 +445,12 @@ export type PaymentRequest = {
|
|
|
443
445
|
routing?: Array<EntityPaymentRoute> | null | undefined;
|
|
444
446
|
sequenceType?: SequenceType | undefined;
|
|
445
447
|
/**
|
|
446
|
-
* **Only relevant for recurring payments.**
|
|
448
|
+
* **Only relevant for recurring payments and stored cards.**
|
|
447
449
|
*
|
|
448
450
|
* @remarks
|
|
449
451
|
*
|
|
450
|
-
* When creating recurring payments, the ID of a specific [mandate](get-mandate) can be supplied to indicate which of
|
|
451
|
-
* the customer's accounts should be
|
|
452
|
+
* When creating recurring or stored cards payments, the ID of a specific [mandate](get-mandate) can be supplied to indicate which of
|
|
453
|
+
* the customer's accounts should be debited.
|
|
452
454
|
*/
|
|
453
455
|
mandateId?: string | null | undefined;
|
|
454
456
|
customerId?: string | undefined;
|
|
@@ -466,6 +468,13 @@ export type PaymentRequest = {
|
|
|
466
468
|
* The date by which the payment should be completed in `YYYY-MM-DD` format
|
|
467
469
|
*/
|
|
468
470
|
dueDate?: string | undefined;
|
|
471
|
+
/**
|
|
472
|
+
* Whether the card details should be stored for the customer after a successful payment. This will create a mandate for the customer,
|
|
473
|
+
*
|
|
474
|
+
* @remarks
|
|
475
|
+
* allowing for future customer present saved-card CIT payments. Requires customerId, cardToken, and the creditcard method to be specified.
|
|
476
|
+
*/
|
|
477
|
+
storeCredentials?: boolean | undefined;
|
|
469
478
|
/**
|
|
470
479
|
* Whether to create the entity in test mode or live mode.
|
|
471
480
|
*
|
|
@@ -738,6 +747,7 @@ export type PaymentRequest$Outbound = {
|
|
|
738
747
|
customerId?: string | undefined;
|
|
739
748
|
profileId?: string | undefined;
|
|
740
749
|
dueDate?: string | undefined;
|
|
750
|
+
storeCredentials?: boolean | undefined;
|
|
741
751
|
testmode?: boolean | null | undefined;
|
|
742
752
|
applePayPaymentToken?: string | undefined;
|
|
743
753
|
company?: Company$Outbound | undefined;
|
|
@@ -789,6 +799,7 @@ export const PaymentRequest$outboundSchema: z.ZodType<
|
|
|
789
799
|
customerId: z.string().optional(),
|
|
790
800
|
profileId: z.string().optional(),
|
|
791
801
|
dueDate: z.string().optional(),
|
|
802
|
+
storeCredentials: z.boolean().optional(),
|
|
792
803
|
testmode: z.nullable(z.boolean()).optional(),
|
|
793
804
|
applePayPaymentToken: z.string().optional(),
|
|
794
805
|
company: z.lazy(() => Company$outboundSchema).optional(),
|
|
@@ -321,6 +321,8 @@ export type PaymentResponseBillingAddress = {
|
|
|
321
321
|
* email upon payment creation. The language of the email will follow the locale parameter of the payment.
|
|
322
322
|
*
|
|
323
323
|
* Required for payment methods `billie`, `in3`, `klarna` and `riverty`.
|
|
324
|
+
*
|
|
325
|
+
* If the domain contains non-ASCII characters, encode it as Punycode per [RFC 3492](https://www.rfc-editor.org/rfc/rfc3492).
|
|
324
326
|
*/
|
|
325
327
|
email?: string | undefined;
|
|
326
328
|
/**
|
|
@@ -1042,12 +1044,12 @@ export type PaymentResponse = {
|
|
|
1042
1044
|
*/
|
|
1043
1045
|
subscriptionId?: string | null | undefined;
|
|
1044
1046
|
/**
|
|
1045
|
-
* **Only relevant for recurring payments.**
|
|
1047
|
+
* **Only relevant for recurring payments and stored cards.**
|
|
1046
1048
|
*
|
|
1047
1049
|
* @remarks
|
|
1048
1050
|
*
|
|
1049
|
-
* When creating recurring payments, the ID of a specific [mandate](get-mandate) can be supplied to indicate which of
|
|
1050
|
-
* the customer's accounts should be
|
|
1051
|
+
* When creating recurring or stored cards payments, the ID of a specific [mandate](get-mandate) can be supplied to indicate which of
|
|
1052
|
+
* the customer's accounts should be debited.
|
|
1051
1053
|
*/
|
|
1052
1054
|
mandateId?: string | null | undefined;
|
|
1053
1055
|
customerId?: string | undefined;
|
|
@@ -22,6 +22,10 @@ export type ProfileRequest = {
|
|
|
22
22
|
website: string;
|
|
23
23
|
/**
|
|
24
24
|
* The email address associated with the profile's trade name or brand.
|
|
25
|
+
*
|
|
26
|
+
* @remarks
|
|
27
|
+
*
|
|
28
|
+
* If the domain contains non-ASCII characters, encode it as Punycode per [RFC 3492](https://www.rfc-editor.org/rfc/rfc3492).
|
|
25
29
|
*/
|
|
26
30
|
email: string;
|
|
27
31
|
/**
|
|
@@ -123,6 +123,10 @@ export type ProfileResponse = {
|
|
|
123
123
|
website: string;
|
|
124
124
|
/**
|
|
125
125
|
* The email address associated with the profile's trade name or brand.
|
|
126
|
+
*
|
|
127
|
+
* @remarks
|
|
128
|
+
*
|
|
129
|
+
* If the domain contains non-ASCII characters, encode it as Punycode per [RFC 3492](https://www.rfc-editor.org/rfc/rfc3492).
|
|
126
130
|
*/
|
|
127
131
|
email: string;
|
|
128
132
|
/**
|
|
@@ -59,6 +59,10 @@ export type SalesInvoiceRecipient = {
|
|
|
59
59
|
vatNumber?: string | null | undefined;
|
|
60
60
|
/**
|
|
61
61
|
* The email address of the recipient.
|
|
62
|
+
*
|
|
63
|
+
* @remarks
|
|
64
|
+
*
|
|
65
|
+
* If the domain contains non-ASCII characters, encode it as Punycode per [RFC 3492](https://www.rfc-editor.org/rfc/rfc3492).
|
|
62
66
|
*/
|
|
63
67
|
email: string;
|
|
64
68
|
/**
|
|
@@ -62,6 +62,10 @@ export type SalesInvoiceRecipientResponse = {
|
|
|
62
62
|
vatNumber?: string | null | undefined;
|
|
63
63
|
/**
|
|
64
64
|
* The email address of the recipient.
|
|
65
|
+
*
|
|
66
|
+
* @remarks
|
|
67
|
+
*
|
|
68
|
+
* If the domain contains non-ASCII characters, encode it as Punycode per [RFC 3492](https://www.rfc-editor.org/rfc/rfc3492).
|
|
65
69
|
*/
|
|
66
70
|
email: string;
|
|
67
71
|
/**
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
export class InvalidSignatureException extends Error {
|
|
2
|
+
constructor(message: string) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = "InvalidSignatureException";
|
|
5
|
+
|
|
6
|
+
Object.setPrototypeOf(this, InvalidSignatureException.prototype);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class SignatureValidator {
|
|
11
|
+
static readonly SIGNATURE_HEADER = "X-Mollie-Signature";
|
|
12
|
+
private static readonly SIGNATURE_PREFIX = "sha256=";
|
|
13
|
+
|
|
14
|
+
private readonly signingSecrets: string[];
|
|
15
|
+
|
|
16
|
+
constructor(signingSecrets: string | string[]) {
|
|
17
|
+
this.signingSecrets = Array.isArray(signingSecrets)
|
|
18
|
+
? [...signingSecrets]
|
|
19
|
+
: [signingSecrets];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static async validate(
|
|
23
|
+
payload: string,
|
|
24
|
+
signingSecrets: string | string[],
|
|
25
|
+
signatures?: string | string[] | null,
|
|
26
|
+
): Promise<boolean> {
|
|
27
|
+
return new SignatureValidator(signingSecrets).validatePayload(
|
|
28
|
+
payload,
|
|
29
|
+
signatures,
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async validatePayload(
|
|
34
|
+
payload: string,
|
|
35
|
+
signatures?: string | string[] | null,
|
|
36
|
+
): Promise<boolean> {
|
|
37
|
+
const signatureList = this.normalizeSignatures(signatures);
|
|
38
|
+
|
|
39
|
+
if (signatureList.length === 0) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return this.validateSignatures(payload, signatureList);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private normalizeSignatures(
|
|
47
|
+
signatures?: string | string[] | null,
|
|
48
|
+
): string[] {
|
|
49
|
+
if (typeof signatures === "string") {
|
|
50
|
+
return signatures ? [signatures] : [];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!signatures) {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return signatures.filter((signature): signature is string => !!signature);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private async validateSignatures(
|
|
61
|
+
payload: string,
|
|
62
|
+
signatures: string[],
|
|
63
|
+
): Promise<boolean> {
|
|
64
|
+
for (const signature of signatures) {
|
|
65
|
+
const extractedSignature = this.extractSignature(signature);
|
|
66
|
+
|
|
67
|
+
if (await this.isValidSignature(extractedSignature, payload)) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
throw new InvalidSignatureException("Invalid webhook signature");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private extractSignature(signatureHeader: string): string {
|
|
76
|
+
if (signatureHeader.startsWith(SignatureValidator.SIGNATURE_PREFIX)) {
|
|
77
|
+
return signatureHeader.slice(SignatureValidator.SIGNATURE_PREFIX.length);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return signatureHeader;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private async isValidSignature(
|
|
84
|
+
providedSignature: string,
|
|
85
|
+
payload: string,
|
|
86
|
+
): Promise<boolean> {
|
|
87
|
+
for (const secret of this.signingSecrets) {
|
|
88
|
+
const expectedSignature = await SignatureValidator.createSignature(
|
|
89
|
+
payload,
|
|
90
|
+
secret,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
if (constantTimeEquals(expectedSignature, providedSignature)) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
static async createSignature(payload: string, secret: string): Promise<string> {
|
|
102
|
+
const subtle = globalThis.crypto?.subtle;
|
|
103
|
+
if (!subtle) {
|
|
104
|
+
throw new Error("Web Crypto API is not available in this runtime");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const encoder = new TextEncoder();
|
|
108
|
+
const key = await subtle.importKey(
|
|
109
|
+
"raw",
|
|
110
|
+
encoder.encode(secret),
|
|
111
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
112
|
+
false,
|
|
113
|
+
["sign"],
|
|
114
|
+
);
|
|
115
|
+
const signature = await subtle.sign("HMAC", key, encoder.encode(payload));
|
|
116
|
+
|
|
117
|
+
return toHex(signature);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function constantTimeEquals(left: string, right: string): boolean {
|
|
122
|
+
const maxLength = Math.max(left.length, right.length);
|
|
123
|
+
let mismatch = left.length ^ right.length;
|
|
124
|
+
|
|
125
|
+
for (let index = 0; index < maxLength; index++) {
|
|
126
|
+
mismatch |= (left.charCodeAt(index) || 0) ^ (right.charCodeAt(index) || 0);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return mismatch === 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function toHex(buffer: ArrayBuffer): string {
|
|
133
|
+
return Array.from(new Uint8Array(buffer))
|
|
134
|
+
.map((value) => value.toString(16).padStart(2, "0"))
|
|
135
|
+
.join("");
|
|
136
|
+
}
|