awesome-node-checkout 1.1.0 → 1.2.1

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.
Files changed (35) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +88 -28
  3. package/dist/adapters/express/index.d.ts +40 -9
  4. package/dist/adapters/express/index.d.ts.map +1 -1
  5. package/dist/adapters/express/index.js +85 -15
  6. package/dist/adapters/express/index.js.map +1 -1
  7. package/dist/checkout-configurator.d.ts +9 -1
  8. package/dist/checkout-configurator.d.ts.map +1 -1
  9. package/dist/checkout-configurator.js +52 -3
  10. package/dist/checkout-configurator.js.map +1 -1
  11. package/dist/events/checkout-event-bus.d.ts +1 -0
  12. package/dist/events/checkout-event-bus.d.ts.map +1 -1
  13. package/dist/events/checkout-event-bus.js.map +1 -1
  14. package/dist/interfaces/payment-provider.interface.d.ts +8 -3
  15. package/dist/interfaces/payment-provider.interface.d.ts.map +1 -1
  16. package/dist/models/payment-request.model.d.ts +2 -0
  17. package/dist/models/payment-request.model.d.ts.map +1 -1
  18. package/dist/models/payment-result.model.d.ts +11 -0
  19. package/dist/models/payment-result.model.d.ts.map +1 -1
  20. package/dist/providers/nexi/nexi.provider.d.ts +26 -8
  21. package/dist/providers/nexi/nexi.provider.d.ts.map +1 -1
  22. package/dist/providers/nexi/nexi.provider.js +180 -45
  23. package/dist/providers/nexi/nexi.provider.js.map +1 -1
  24. package/dist/providers/paypal/paypal.provider.d.ts.map +1 -1
  25. package/dist/providers/paypal/paypal.provider.js +28 -4
  26. package/dist/providers/paypal/paypal.provider.js.map +1 -1
  27. package/dist/providers/satispay/satispay.provider.d.ts +39 -5
  28. package/dist/providers/satispay/satispay.provider.d.ts.map +1 -1
  29. package/dist/providers/satispay/satispay.provider.js +130 -23
  30. package/dist/providers/satispay/satispay.provider.js.map +1 -1
  31. package/dist/utils/parsing.util.d.ts +17 -0
  32. package/dist/utils/parsing.util.d.ts.map +1 -0
  33. package/dist/utils/parsing.util.js +60 -0
  34. package/dist/utils/parsing.util.js.map +1 -0
  35. package/package.json +9 -3
@@ -28,9 +28,21 @@ class CheckoutConfigurator {
28
28
  constructor(config = {}) {
29
29
  this.config = config;
30
30
  this.providers = new Map();
31
+ this.maxPaymentOrders = 10000;
32
+ this.paymentOrders = new Map();
31
33
  /** Event bus — subscribe to payment lifecycle events */
32
34
  this.events = new checkout_event_bus_1.CheckoutEventBus();
33
35
  }
36
+ /** Stores a paymentId -> orderId mapping with bounded capacity to prevent memory leaks */
37
+ setPaymentOrder(paymentId, orderId) {
38
+ if (this.paymentOrders.size >= this.maxPaymentOrders) {
39
+ const firstKey = this.paymentOrders.keys().next().value;
40
+ if (firstKey) {
41
+ this.paymentOrders.delete(firstKey);
42
+ }
43
+ }
44
+ this.paymentOrders.set(paymentId, orderId);
45
+ }
34
46
  /** Emits an event only when `config.emitEvents` is not explicitly `false`. */
35
47
  async emit(event, data) {
36
48
  if (this.config.emitEvents !== false) {
@@ -68,12 +80,17 @@ class CheckoutConfigurator {
68
80
  async createPayment(providerName, request) {
69
81
  const provider = this.getProvider(providerName);
70
82
  const result = await provider.createPayment(request);
83
+ if (result.paymentId && request.orderId) {
84
+ this.setPaymentOrder(result.paymentId, request.orderId);
85
+ result.orderId = request.orderId;
86
+ }
71
87
  await this.emit(result.success ? 'payment.created' : 'payment.failed', {
72
88
  provider: providerName,
73
89
  paymentId: result.paymentId,
74
90
  orderId: request.orderId,
75
91
  status: result.status,
76
92
  error: result.error,
93
+ raw: result.raw,
77
94
  });
78
95
  return result;
79
96
  }
@@ -81,11 +98,17 @@ class CheckoutConfigurator {
81
98
  async executePayment(providerName, paymentId, data) {
82
99
  const provider = this.getProvider(providerName);
83
100
  const result = await provider.executePayment(paymentId, data);
101
+ const orderId = this.paymentOrders.get(paymentId);
102
+ if (orderId && !result.orderId) {
103
+ result.orderId = orderId;
104
+ }
84
105
  await this.emit(result.success ? 'payment.completed' : 'payment.failed', {
85
106
  provider: providerName,
86
107
  paymentId,
108
+ orderId,
87
109
  status: result.status,
88
110
  error: result.error,
111
+ raw: result.raw,
89
112
  });
90
113
  return result;
91
114
  }
@@ -98,11 +121,17 @@ class CheckoutConfigurator {
98
121
  async refundPayment(providerName, paymentId, amount) {
99
122
  const provider = this.getProvider(providerName);
100
123
  const result = await provider.refundPayment(paymentId, amount);
124
+ const orderId = this.paymentOrders.get(paymentId);
125
+ if (orderId && !result.orderId) {
126
+ result.orderId = orderId;
127
+ }
101
128
  await this.emit('payment.refunded', {
102
129
  provider: providerName,
103
130
  paymentId,
131
+ orderId,
104
132
  status: result.status,
105
133
  error: result.error,
134
+ raw: result.raw,
106
135
  });
107
136
  return result;
108
137
  }
@@ -110,18 +139,30 @@ class CheckoutConfigurator {
110
139
  * Handle an incoming webhook from the provider.
111
140
  * @throws CheckoutError if the provider does not support webhooks.
112
141
  */
113
- async handleWebhook(providerName, body, headers) {
142
+ async handleWebhook(providerName, body, headers = {}, query, context) {
114
143
  const provider = this.getProvider(providerName);
115
144
  if (!provider.handleWebhook) {
116
145
  throw new errors_1.CheckoutError(`Provider '${providerName}' does not support webhook handling`, 'WEBHOOK_NOT_SUPPORTED', providerName);
117
146
  }
118
- const result = await provider.handleWebhook(body, headers);
147
+ const result = await provider.handleWebhook(body, headers, query, context);
148
+ const rawAny = result.raw;
149
+ const orderId = rawAny?.orderId ??
150
+ rawAny?.order_id ??
151
+ rawAny?.external_code ??
152
+ rawAny?.codTrans ??
153
+ query?.order_id ??
154
+ (result.paymentId ? this.paymentOrders.get(result.paymentId) : undefined);
155
+ if (orderId && !result.orderId) {
156
+ result.orderId = orderId;
157
+ }
119
158
  await this.emit('webhook.received', {
120
159
  provider: providerName,
121
160
  paymentId: result.paymentId,
161
+ orderId,
122
162
  status: result.status,
123
163
  error: result.error,
124
- data: body,
164
+ data: body ?? query,
165
+ raw: result.raw,
125
166
  });
126
167
  return result;
127
168
  }
@@ -135,11 +176,19 @@ class CheckoutConfigurator {
135
176
  throw new errors_1.CheckoutError(`Provider '${providerName}' does not support redirect handling`, 'REDIRECT_NOT_SUPPORTED', providerName);
136
177
  }
137
178
  const result = await provider.handleRedirect(query);
179
+ const orderId = (result.paymentId ? this.paymentOrders.get(result.paymentId) : undefined) ??
180
+ query?.order_id ??
181
+ query?.codTrans;
182
+ if (orderId && !result.orderId) {
183
+ result.orderId = orderId;
184
+ }
138
185
  await this.emit(result.success ? 'payment.completed' : 'payment.failed', {
139
186
  provider: providerName,
140
187
  paymentId: result.paymentId,
188
+ orderId,
141
189
  status: result.status,
142
190
  error: result.error,
191
+ raw: result.raw,
143
192
  });
144
193
  return result;
145
194
  }
@@ -1 +1 @@
1
- {"version":3,"file":"checkout-configurator.js","sourceRoot":"","sources":["../src/checkout-configurator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"checkout-configurator.js","sourceRoot":"","sources":["../src/checkout-configurator.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ export interface CheckoutEventPayload {
6
6
  status?: string;
7
7
  error?: string;
8
8
  data?: any;
9
+ raw?: unknown;
9
10
  timestamp: Date;
10
11
  }
11
12
  type EventListener = (payload: CheckoutEventPayload) => void | Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"checkout-event-bus.d.ts","sourceRoot":"","sources":["../../src/events/checkout-event-bus.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GACzB,iBAAiB,GACjB,mBAAmB,GACnB,gBAAgB,GAChB,kBAAkB,GAClB,kBAAkB,CAAC;AAEvB,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,KAAK,aAAa,GAAG,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE7E;;;;;;;;;GASG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsD;IAEhF,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAM3D,GAAG,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAQtD,IAAI,CACR,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,WAAW,CAAC,GAC/C,OAAO,CAAC,IAAI,CAAC;CAKjB"}
1
+ {"version":3,"file":"checkout-event-bus.d.ts","sourceRoot":"","sources":["../../src/events/checkout-event-bus.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GACzB,iBAAiB,GACjB,mBAAmB,GACnB,gBAAgB,GAChB,kBAAkB,GAClB,kBAAkB,CAAC;AAEvB,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,KAAK,aAAa,GAAG,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE7E;;;;;;;;;GASG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsD;IAEhF,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAM3D,GAAG,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAQtD,IAAI,CACR,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,WAAW,CAAC,GAC/C,OAAO,CAAC,IAAI,CAAC;CAKjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"checkout-event-bus.js","sourceRoot":"","sources":["../../src/events/checkout-event-bus.ts"],"names":[],"mappings":";;;AAmBA;;;;;;;;;GASG;AACH,MAAa,gBAAgB;IAA7B;QACmB,cAAS,GAA4C,IAAI,GAAG,EAAE,CAAC;IAwBlF,CAAC;IAtBC,EAAE,CAAC,KAAwB,EAAE,QAAuB;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACjD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,KAAwB,EAAE,QAAuB;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,IAAI,CACR,KAAwB,EACxB,OAAgD;QAEhD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACjD,MAAM,WAAW,GAAyB,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;QAChF,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;CACF;AAzBD,4CAyBC"}
1
+ {"version":3,"file":"checkout-event-bus.js","sourceRoot":"","sources":["../../src/events/checkout-event-bus.ts"],"names":[],"mappings":";;;AAoBA;;;;;;;;;GASG;AACH,MAAa,gBAAgB;IAA7B;QACmB,cAAS,GAA4C,IAAI,GAAG,EAAE,CAAC;IAwBlF,CAAC;IAtBC,EAAE,CAAC,KAAwB,EAAE,QAAuB;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACjD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,KAAwB,EAAE,QAAuB;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,IAAI,CACR,KAAwB,EACxB,OAAgD;QAEhD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACjD,MAAM,WAAW,GAAyB,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;QAChF,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;CACF;AAzBD,4CAyBC"}
@@ -20,10 +20,15 @@ export interface IPaymentProvider {
20
20
  /** Issue a full or partial refund on a completed payment */
21
21
  refundPayment(paymentId: string, amount?: number): Promise<PaymentResult>;
22
22
  /**
23
- * Handle an incoming webhook notification from the provider.
24
- * Optional — implement only for providers that use the `webhook` flow.
23
+ * Handle an incoming webhook or server-to-server outcome notification from the provider.
24
+ * Optional — implement for providers that use the `webhook` flow or support
25
+ * server-to-server notifications.
25
26
  */
26
- handleWebhook?(body: Record<string, unknown>, headers: Record<string, string>): Promise<WebhookResult>;
27
+ handleWebhook?(body?: Record<string, unknown>, headers?: Record<string, string>, query?: Record<string, string>, context?: {
28
+ method?: string;
29
+ path?: string;
30
+ rawBody?: Buffer | string;
31
+ }): Promise<WebhookResult>;
27
32
  /**
28
33
  * Handle the redirect callback from the provider (query params from returnUrl).
29
34
  * Optional — implement only for providers that use the `redirect` flow.
@@ -1 +1 @@
1
- {"version":3,"file":"payment-provider.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/payment-provider.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAE9E,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAE3B,8FAA8F;IAC9F,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE/D,mDAAmD;IACnD,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAEzF,2DAA2D;IAC3D,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE7D,4DAA4D;IAC5D,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE1E;;;OAGG;IACH,aAAa,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAEvG;;;OAGG;IACH,cAAc,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CACxE"}
1
+ {"version":3,"file":"payment-provider.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/payment-provider.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAE9E,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAE3B,8FAA8F;IAC9F,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE/D,mDAAmD;IACnD,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAEzF,2DAA2D;IAC3D,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE7D,4DAA4D;IAC5D,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE1E;;;;OAIG;IACH,aAAa,CAAC,CACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,GACtE,OAAO,CAAC,aAAa,CAAC,CAAC;IAE1B;;;OAGG;IACH,cAAc,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CACxE"}
@@ -13,6 +13,8 @@ export interface PaymentRequest {
13
13
  returnUrl: string;
14
14
  /** URL to redirect the user to if the payment is cancelled */
15
15
  cancelUrl: string;
16
+ /** Optional webhook / server-to-server notification URL forwarded to providers that support it */
17
+ notifyUrl?: string;
16
18
  /** External order identifier from the merchant's system */
17
19
  orderId?: string;
18
20
  /** Arbitrary key-value pairs forwarded to the provider when supported */
@@ -1 +1 @@
1
- {"version":3,"file":"payment-request.model.d.ts","sourceRoot":"","sources":["../../src/models/payment-request.model.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IAEf,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IAEjB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAElB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAElB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC"}
1
+ {"version":3,"file":"payment-request.model.d.ts","sourceRoot":"","sources":["../../src/models/payment-request.model.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IAEf,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IAEjB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAElB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAElB,kGAAkG;IAClG,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC"}
@@ -7,6 +7,12 @@ export interface PaymentResult {
7
7
  approvalUrl?: string;
8
8
  /** Current payment status (provider-specific string, e.g. 'COMPLETED', 'ACCEPTED') */
9
9
  status?: string;
10
+ /** Amount reported by the provider, major units (same unit as PaymentRequest.amount) */
11
+ amount?: number;
12
+ /** ISO 4217 alpha code reported by the provider (e.g. 'EUR') */
13
+ currency?: string;
14
+ /** Order identifier associated with the payment if tracked */
15
+ orderId?: string;
10
16
  /** Error message if success is false */
11
17
  error?: string;
12
18
  /** Raw provider response — useful for debugging or provider-specific fields */
@@ -16,7 +22,12 @@ export interface PaymentResult {
16
22
  export interface WebhookResult {
17
23
  success: boolean;
18
24
  paymentId?: string;
25
+ orderId?: string;
19
26
  status?: string;
27
+ /** Amount reported by the provider, major units (same unit as PaymentRequest.amount) */
28
+ amount?: number;
29
+ /** ISO 4217 alpha code reported by the provider (e.g. 'EUR') */
30
+ currency?: string;
20
31
  error?: string;
21
32
  raw?: any;
22
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"payment-result.model.d.ts","sourceRoot":"","sources":["../../src/models/payment-result.model.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IAEjB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,+EAA+E;IAC/E,GAAG,CAAC,EAAE,GAAG,CAAC;CACX;AAED,yCAAyC;AACzC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,GAAG,CAAC;CACX"}
1
+ {"version":3,"file":"payment-result.model.d.ts","sourceRoot":"","sources":["../../src/models/payment-result.model.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IAEjB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,wFAAwF;IACxF,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,+EAA+E;IAC/E,GAAG,CAAC,EAAE,GAAG,CAAC;CACX;AAED,yCAAyC;AACzC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,wFAAwF;IACxF,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,GAAG,CAAC;CACX"}
@@ -1,6 +1,6 @@
1
1
  import { BasePaymentProvider } from '../../abstract/base-payment-provider.abstract';
2
2
  import { PaymentRequest } from '../../models/payment-request.model';
3
- import { PaymentResult } from '../../models/payment-result.model';
3
+ import { PaymentResult, WebhookResult } from '../../models/payment-result.model';
4
4
  export interface NexiProviderConfig {
5
5
  merchantId: string;
6
6
  macKey: string;
@@ -23,6 +23,13 @@ export declare class NexiProvider extends BasePaymentProvider {
23
23
  readonly flow: "redirect";
24
24
  private readonly apiUrl;
25
25
  constructor(config: NexiProviderConfig);
26
+ /**
27
+ * Computes the SHA-1 MAC required by Nexi to authenticate the payment request.
28
+ * Format: `codTrans={val}divisa={val}importo={val}{macKey}`
29
+ *
30
+ * SHA-1 is used here because Nexi XPay mandates it for MAC computation.
31
+ */
32
+ private sha1;
26
33
  /**
27
34
  * Computes the SHA-1 MAC required by Nexi to authenticate the payment request.
28
35
  * Format: `codTrans={val}divisa={val}importo={val}{macKey}`
@@ -31,8 +38,8 @@ export declare class NexiProvider extends BasePaymentProvider {
31
38
  */
32
39
  private generateMac;
33
40
  /**
34
- * Computes the SHA-1 MAC for the status (getPaymentDetails) API call.
35
- * Format: `alias={alias}codTrans={codTrans}timestamp={timestamp}{macKey}`
41
+ * Computes the SHA-1 MAC for the status (bo/situazioneOrdine) API call.
42
+ * Format: `apiKey={alias}codiceTransazione={codiceTransazione}timeStamp={timeStamp}{macKey}`
36
43
  */
37
44
  private generateStatusMac;
38
45
  /**
@@ -41,23 +48,34 @@ export declare class NexiProvider extends BasePaymentProvider {
41
48
  */
42
49
  private generateRefundMac;
43
50
  /**
44
- * Verifies the SHA-1 MAC included in a Nexi POST-back response.
45
- * Format: `codTrans={val}esito={val}importo={val}divisa={val}{macKey}`
51
+ /**
52
+ * Validates that the MAC is a string of exactly 40 hexadecimal characters.
53
+ */
54
+ private isValidHexMac;
55
+ /**
56
+ * Verifies the SHA-1 outcome MAC included in a Nexi POST-back response or server notification.
57
+ * Format: `codTrans={codTrans}esito={esito}importo={importo}divisa={divisa}data={data}orario={orario}codAut={codAut}{macKey}`
46
58
  */
47
59
  private verifyResponseMac;
60
+ private safeVerifyResponseMac;
48
61
  createPayment(request: PaymentRequest): Promise<PaymentResult>;
49
62
  /**
50
63
  * Validates the POST-back data from Nexi.
51
64
  * `data` is the query/body object sent by Nexi to the returnUrl.
52
- * The MAC is verified before the result is considered authoritative.
65
+ * The outcome MAC is mandatory and verified over all 7 fields before the result is considered authoritative.
53
66
  */
54
67
  executePayment(paymentId: string, data?: Record<string, string>): Promise<PaymentResult>;
68
+ /**
69
+ * Handles the incoming server-to-server outcome notification (urlpost) from Nexi.
70
+ * The outcome MAC is mandatory and verified over all 7 fields.
71
+ */
72
+ handleWebhook(body?: Record<string, unknown>, _headers?: Record<string, string>): Promise<WebhookResult>;
55
73
  getPaymentDetails(paymentId: string): Promise<PaymentResult>;
56
74
  refundPayment(paymentId: string, amount?: number): Promise<PaymentResult>;
57
75
  /**
58
76
  * Handles the POST-back from Nexi to the returnUrl.
59
- * Nexi sends `esito`, `codTrans`, `importo`, `divisa`, `mac`, etc. as query/body params.
60
- * The MAC is verified to ensure the response was not spoofed.
77
+ * Nexi sends `esito`, `codTrans`, `importo`, `divisa`, `mac`, `data`, `orario`, `codAut` etc.
78
+ * The outcome MAC is mandatory and verified over all 7 fields to ensure authenticity.
61
79
  */
62
80
  handleRedirect(query: Record<string, string>): Promise<PaymentResult>;
63
81
  }
@@ -1 +1 @@
1
- {"version":3,"file":"nexi.provider.d.ts","sourceRoot":"","sources":["../../../src/providers/nexi/nexi.provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAElE,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;CACxC;AAED;;;;;;;GAOG;AACH,qBAAa,YAAa,SAAQ,mBAAmB;IAMvC,OAAO,CAAC,QAAQ,CAAC,MAAM;IALnC,QAAQ,CAAC,IAAI,UAAU;IACvB,QAAQ,CAAC,IAAI,EAAG,UAAU,CAAU;IAEpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEH,MAAM,EAAE,kBAAkB;IAQvD;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAKnB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAKzB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAUzB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAYnB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAiCpE;;;;OAIG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;IAoCxF,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA2B5D,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAkC/E;;;;OAIG;IACG,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;CAG5E"}
1
+ {"version":3,"file":"nexi.provider.d.ts","sourceRoot":"","sources":["../../../src/providers/nexi/nexi.provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAGjF,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;CACxC;AAED;;;;;;;GAOG;AACH,qBAAa,YAAa,SAAQ,mBAAmB;IAMvC,OAAO,CAAC,QAAQ,CAAC,MAAM;IALnC,QAAQ,CAAC,IAAI,UAAU;IACvB,QAAQ,CAAC,IAAI,EAAG,UAAU,CAAU;IAEpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEH,MAAM,EAAE,kBAAkB;IAQvD;;;;;OAKG;IACH,OAAO,CAAC,IAAI;IAIZ;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAInB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAIzB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IASzB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAIrB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAwBzB,OAAO,CAAC,qBAAqB;IAiBvB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAqCpE;;;;OAIG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;IA6C9F;;;OAGG;IACG,aAAa,CACjB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACpC,OAAO,CAAC,aAAa,CAAC;IAuCnB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAwF5D,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAkC/E;;;;OAIG;IACG,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;CAG5E"}
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.NexiProvider = void 0;
37
37
  const crypto = __importStar(require("crypto"));
38
38
  const base_payment_provider_abstract_1 = require("../../abstract/base-payment-provider.abstract");
39
+ const parsing_util_1 = require("../../utils/parsing.util");
39
40
  /**
40
41
  * Nexi eCommerce provider.
41
42
  * Flow: `redirect` — builds a signed checkout URL, redirects the user to Nexi,
@@ -61,34 +62,64 @@ class NexiProvider extends base_payment_provider_abstract_1.BasePaymentProvider
61
62
  *
62
63
  * SHA-1 is used here because Nexi XPay mandates it for MAC computation.
63
64
  */
64
- generateMac(codTrans, divisa, importoCents) {
65
- const raw = `codTrans=${codTrans}divisa=${divisa}importo=${importoCents}${this.config.macKey}`;
65
+ sha1(raw) {
66
66
  return crypto.createHash('sha1').update(raw).digest('hex');
67
67
  }
68
68
  /**
69
- * Computes the SHA-1 MAC for the status (getPaymentDetails) API call.
70
- * Format: `alias={alias}codTrans={codTrans}timestamp={timestamp}{macKey}`
69
+ * Computes the SHA-1 MAC required by Nexi to authenticate the payment request.
70
+ * Format: `codTrans={val}divisa={val}importo={val}{macKey}`
71
+ *
72
+ * SHA-1 is used here because Nexi XPay mandates it for MAC computation.
71
73
  */
72
- generateStatusMac(alias, codTrans, timestamp) {
73
- const raw = `alias=${alias}codTrans=${codTrans}timestamp=${timestamp}${this.config.macKey}`;
74
- return crypto.createHash('sha1').update(raw).digest('hex');
74
+ generateMac(codTrans, divisa, importoCents) {
75
+ return this.sha1(`codTrans=${codTrans}divisa=${divisa}importo=${importoCents}${this.config.macKey}`);
76
+ }
77
+ /**
78
+ * Computes the SHA-1 MAC for the status (bo/situazioneOrdine) API call.
79
+ * Format: `apiKey={alias}codiceTransazione={codiceTransazione}timeStamp={timeStamp}{macKey}`
80
+ */
81
+ generateStatusMac(alias, codiceTransazione, timeStamp) {
82
+ return this.sha1(`apiKey=${alias}codiceTransazione=${codiceTransazione}timeStamp=${timeStamp}${this.config.macKey}`);
75
83
  }
76
84
  /**
77
85
  * Computes the SHA-1 MAC for the refund (storno) API call.
78
86
  * Format: `alias={alias}codTrans={codTrans}importo={importo}timestamp={timestamp}{macKey}`
79
87
  */
80
88
  generateRefundMac(alias, codTrans, importo, timestamp) {
81
- const raw = `alias=${alias}codTrans=${codTrans}importo=${importo}timestamp=${timestamp}${this.config.macKey}`;
82
- return crypto.createHash('sha1').update(raw).digest('hex');
89
+ return this.sha1(`alias=${alias}codTrans=${codTrans}importo=${importo}timestamp=${timestamp}${this.config.macKey}`);
90
+ }
91
+ /**
92
+ /**
93
+ * Validates that the MAC is a string of exactly 40 hexadecimal characters.
94
+ */
95
+ isValidHexMac(mac) {
96
+ return typeof mac === 'string' && /^[0-9a-fA-F]{40}$/.test(mac);
83
97
  }
84
98
  /**
85
- * Verifies the SHA-1 MAC included in a Nexi POST-back response.
86
- * Format: `codTrans={val}esito={val}importo={val}divisa={val}{macKey}`
99
+ * Verifies the SHA-1 outcome MAC included in a Nexi POST-back response or server notification.
100
+ * Format: `codTrans={codTrans}esito={esito}importo={importo}divisa={divisa}data={data}orario={orario}codAut={codAut}{macKey}`
87
101
  */
88
- verifyResponseMac(codTrans, esito, importo, divisa, mac) {
89
- const raw = `codTrans=${codTrans}esito=${esito}importo=${importo}divisa=${divisa}${this.config.macKey}`;
90
- const expected = crypto.createHash('sha1').update(raw).digest('hex');
91
- return crypto.timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(mac, 'hex'));
102
+ verifyResponseMac(codTrans, esito, importo, divisa, dataStr, orario, codAut, mac) {
103
+ if (!this.isValidHexMac(mac)) {
104
+ return false;
105
+ }
106
+ const raw = `codTrans=${codTrans}esito=${esito}importo=${importo}divisa=${divisa}` +
107
+ `data=${dataStr}orario=${orario}codAut=${codAut}${this.config.macKey}`;
108
+ const expected = this.sha1(raw);
109
+ const expBuf = Buffer.from(expected, 'hex');
110
+ const macBuf = Buffer.from(mac, 'hex');
111
+ if (expBuf.length !== macBuf.length || expBuf.length === 0) {
112
+ return false;
113
+ }
114
+ return crypto.timingSafeEqual(expBuf, macBuf);
115
+ }
116
+ safeVerifyResponseMac(codTrans, esito, importo, divisa, dataStr, orario, codAut, mac) {
117
+ try {
118
+ return this.verifyResponseMac(codTrans, esito, importo, divisa, dataStr, orario, codAut, mac);
119
+ }
120
+ catch {
121
+ return false;
122
+ }
92
123
  }
93
124
  async createPayment(request) {
94
125
  try {
@@ -104,6 +135,9 @@ class NexiProvider extends base_payment_provider_abstract_1.BasePaymentProvider
104
135
  url_back: request.cancelUrl,
105
136
  mac,
106
137
  };
138
+ if (request.notifyUrl) {
139
+ params.urlpost = request.notifyUrl;
140
+ }
107
141
  if (this.config.group) {
108
142
  params.gruppo = this.config.group;
109
143
  }
@@ -122,7 +156,7 @@ class NexiProvider extends base_payment_provider_abstract_1.BasePaymentProvider
122
156
  /**
123
157
  * Validates the POST-back data from Nexi.
124
158
  * `data` is the query/body object sent by Nexi to the returnUrl.
125
- * The MAC is verified before the result is considered authoritative.
159
+ * The outcome MAC is mandatory and verified over all 7 fields before the result is considered authoritative.
126
160
  */
127
161
  async executePayment(paymentId, data) {
128
162
  try {
@@ -130,28 +164,34 @@ class NexiProvider extends base_payment_provider_abstract_1.BasePaymentProvider
130
164
  const codTrans = data?.codTrans ?? paymentId;
131
165
  const importo = data?.importo ?? '';
132
166
  const divisa = data?.divisa ?? '';
133
- const mac = data?.mac ?? '';
134
- if (mac) {
135
- let macValid;
136
- try {
137
- macValid = this.verifyResponseMac(codTrans, esito, importo, divisa, mac);
138
- }
139
- catch {
140
- macValid = false;
141
- }
142
- if (!macValid) {
143
- return {
144
- success: false,
145
- paymentId: codTrans,
146
- status: 'FAILED',
147
- error: 'MAC verification failed: response may have been tampered with',
148
- };
149
- }
167
+ const dataStr = data?.data ?? '';
168
+ const orario = data?.orario ?? '';
169
+ const codAut = data?.codAut ?? '';
170
+ const mac = data?.mac;
171
+ if (!mac) {
172
+ return {
173
+ success: false,
174
+ paymentId: codTrans,
175
+ status: 'FAILED',
176
+ error: 'MAC missing',
177
+ };
178
+ }
179
+ if (!this.isValidHexMac(mac) || !this.safeVerifyResponseMac(codTrans, esito, importo, divisa, dataStr, orario, codAut, mac)) {
180
+ return {
181
+ success: false,
182
+ paymentId: codTrans,
183
+ status: 'FAILED',
184
+ error: 'MAC verification failed: response may have been tampered with',
185
+ };
150
186
  }
187
+ const amount = (0, parsing_util_1.parseAmountFromCents)(importo);
188
+ const currency = (0, parsing_util_1.parseNexiCurrency)(divisa);
151
189
  return {
152
190
  success: esito === 'OK',
153
191
  paymentId: codTrans,
154
192
  status: esito === 'OK' ? 'COMPLETED' : 'FAILED',
193
+ amount,
194
+ currency,
155
195
  raw: data,
156
196
  };
157
197
  }
@@ -159,25 +199,120 @@ class NexiProvider extends base_payment_provider_abstract_1.BasePaymentProvider
159
199
  return this.errorResult(error, 'Failed to execute Nexi payment');
160
200
  }
161
201
  }
202
+ /**
203
+ * Handles the incoming server-to-server outcome notification (urlpost) from Nexi.
204
+ * The outcome MAC is mandatory and verified over all 7 fields.
205
+ */
206
+ async handleWebhook(body, _headers = {}) {
207
+ try {
208
+ if (!body) {
209
+ return { success: false, error: 'MAC verification failed' };
210
+ }
211
+ const f = (k) => String(body?.[k] ?? '');
212
+ const codTrans = f('codTrans');
213
+ const esito = f('esito');
214
+ const importo = f('importo');
215
+ const divisa = f('divisa');
216
+ const dataStr = f('data');
217
+ const orario = f('orario');
218
+ const codAut = f('codAut');
219
+ const mac = body?.['mac'];
220
+ if (!this.isValidHexMac(mac) || !this.safeVerifyResponseMac(codTrans, esito, importo, divisa, dataStr, orario, codAut, mac)) {
221
+ return {
222
+ success: false,
223
+ paymentId: codTrans || undefined,
224
+ error: 'MAC verification failed',
225
+ };
226
+ }
227
+ const amount = (0, parsing_util_1.parseAmountFromCents)(importo);
228
+ const currency = (0, parsing_util_1.parseNexiCurrency)(divisa);
229
+ return {
230
+ success: esito === 'OK',
231
+ paymentId: codTrans,
232
+ status: esito === 'OK' ? 'COMPLETED' : 'FAILED',
233
+ amount,
234
+ currency,
235
+ raw: body,
236
+ };
237
+ }
238
+ catch (error) {
239
+ return { success: false, error: 'MAC verification failed' };
240
+ }
241
+ }
162
242
  async getPaymentDetails(paymentId) {
163
243
  try {
164
- const timestamp = new Date().toISOString();
165
- const mac = this.generateStatusMac(this.config.merchantId, paymentId, timestamp);
166
- const params = {
167
- alias: this.config.merchantId,
168
- codTrans: paymentId,
169
- timestamp,
244
+ const timeStamp = String(Date.now());
245
+ const mac = this.generateStatusMac(this.config.merchantId, paymentId, timeStamp);
246
+ const requestBody = {
247
+ apiKey: this.config.merchantId,
248
+ codiceTransazione: paymentId,
249
+ timeStamp,
170
250
  mac,
171
251
  };
172
- const response = await fetch(`${this.apiUrl}/ecomm/api/vas/igfs/status/plain`, {
252
+ const response = await fetch(`${this.apiUrl}/ecomm/api/bo/situazioneOrdine`, {
173
253
  method: 'POST',
174
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
175
- body: new URLSearchParams(params),
254
+ headers: { 'Content-Type': 'application/json' },
255
+ body: JSON.stringify(requestBody),
176
256
  });
177
257
  if (!response.ok)
178
258
  throw new Error(`Nexi API error: ${response.statusText}`);
179
259
  const result = await response.json();
180
- return { success: true, paymentId, status: result['status'], raw: result };
260
+ const esito = String(result['esito'] ?? '');
261
+ if (esito !== 'OK') {
262
+ const errMsg = result['errore']?.messaggio ?? 'Payment details request failed';
263
+ return { success: false, paymentId, error: errMsg, raw: result };
264
+ }
265
+ // Verify response MAC
266
+ const idOperazione = String(result['idOperazione'] ?? '');
267
+ const respTimeStamp = String(result['timeStamp'] ?? '');
268
+ const expectedMac = this.sha1(`esito=${esito}idOperazione=${idOperazione}timeStamp=${respTimeStamp}${this.config.macKey}`);
269
+ const respMac = result['mac'];
270
+ if (!this.isValidHexMac(respMac)) {
271
+ return {
272
+ success: false,
273
+ paymentId,
274
+ error: 'MAC verification failed: response may have been tampered with',
275
+ raw: result,
276
+ };
277
+ }
278
+ const expBuf = Buffer.from(expectedMac, 'hex');
279
+ const macBuf = Buffer.from(respMac, 'hex');
280
+ let macValid = false;
281
+ try {
282
+ macValid = expBuf.length === macBuf.length && expBuf.length > 0 && crypto.timingSafeEqual(expBuf, macBuf);
283
+ }
284
+ catch {
285
+ macValid = false;
286
+ }
287
+ if (!macValid) {
288
+ return {
289
+ success: false,
290
+ paymentId,
291
+ error: 'MAC verification failed: response may have been tampered with',
292
+ raw: result,
293
+ };
294
+ }
295
+ const report = Array.isArray(result['report']) ? result['report'] : [];
296
+ const item = report.find((r) => r?.codiceTransazione === paymentId);
297
+ if (!item) {
298
+ return {
299
+ success: false,
300
+ paymentId,
301
+ error: 'Report not found',
302
+ raw: result,
303
+ };
304
+ }
305
+ const stato = item.stato;
306
+ const amount = (0, parsing_util_1.parseAmountFromCents)(item.importo);
307
+ const currency = (0, parsing_util_1.parseNexiCurrency)(item.divisa);
308
+ return {
309
+ success: true,
310
+ paymentId,
311
+ status: stato,
312
+ amount,
313
+ currency,
314
+ raw: result,
315
+ };
181
316
  }
182
317
  catch (error) {
183
318
  return this.errorResult(error, 'Failed to get Nexi payment details');
@@ -216,8 +351,8 @@ class NexiProvider extends base_payment_provider_abstract_1.BasePaymentProvider
216
351
  }
217
352
  /**
218
353
  * Handles the POST-back from Nexi to the returnUrl.
219
- * Nexi sends `esito`, `codTrans`, `importo`, `divisa`, `mac`, etc. as query/body params.
220
- * The MAC is verified to ensure the response was not spoofed.
354
+ * Nexi sends `esito`, `codTrans`, `importo`, `divisa`, `mac`, `data`, `orario`, `codAut` etc.
355
+ * The outcome MAC is mandatory and verified over all 7 fields to ensure authenticity.
221
356
  */
222
357
  async handleRedirect(query) {
223
358
  return this.executePayment(query['codTrans'] ?? '', query);