awesome-node-checkout 1.2.0 → 1.2.2
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/CHANGELOG.md +40 -0
- package/README.md +41 -16
- package/dist/adapters/express/index.d.ts +7 -3
- package/dist/adapters/express/index.d.ts.map +1 -1
- package/dist/adapters/express/index.js +41 -21
- package/dist/adapters/express/index.js.map +1 -1
- package/dist/checkout-configurator.d.ts +4 -0
- package/dist/checkout-configurator.d.ts.map +1 -1
- package/dist/checkout-configurator.js +25 -1
- package/dist/checkout-configurator.js.map +1 -1
- package/dist/interfaces/payment-provider.interface.d.ts +1 -0
- package/dist/interfaces/payment-provider.interface.d.ts.map +1 -1
- package/dist/models/payment-result.model.d.ts +9 -1
- package/dist/models/payment-result.model.d.ts.map +1 -1
- package/dist/providers/nexi/nexi.provider.d.ts +5 -0
- package/dist/providers/nexi/nexi.provider.d.ts.map +1 -1
- package/dist/providers/nexi/nexi.provider.js +62 -16
- package/dist/providers/nexi/nexi.provider.js.map +1 -1
- package/dist/providers/paypal/paypal.provider.d.ts.map +1 -1
- package/dist/providers/paypal/paypal.provider.js +37 -10
- package/dist/providers/paypal/paypal.provider.js.map +1 -1
- package/dist/providers/satispay/satispay.provider.d.ts +33 -4
- package/dist/providers/satispay/satispay.provider.d.ts.map +1 -1
- package/dist/providers/satispay/satispay.provider.js +161 -49
- package/dist/providers/satispay/satispay.provider.js.map +1 -1
- package/dist/utils/parsing.util.d.ts +18 -0
- package/dist/utils/parsing.util.d.ts.map +1 -0
- package/dist/utils/parsing.util.js +79 -0
- package/dist/utils/parsing.util.js.map +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,46 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.2.2] - 2026-09-28
|
|
9
|
+
|
|
10
|
+
### Security
|
|
11
|
+
- **Satispay**: Enforced minimum signed headers requirement in HTTP Signature verification: rejects any signature whose `headers` parameter omits `(request-target)`, `date`, or (when a request body is present) `digest`. Resolves #19.
|
|
12
|
+
- **Satispay**: Strictly enforced presence and freshness of the `Date` HTTP header; requests without a `Date` header are immediately rejected. Resolves #19.
|
|
13
|
+
- **Satispay**: Redacted provider API response bodies from user-facing error messages to prevent internal details or secrets from leaking to callers. Resolves #19.
|
|
14
|
+
- **Express Adapter**: Stripped `raw` provider payloads from all HTTP JSON route responses (`POST /:provider`, `POST /:provider/execute`, `POST /:provider/refund`, `GET /:provider/redirect`, `GET /:provider/:id`, `GET/POST /:provider/webhook`) to protect sensitive payer details. Resolves #19.
|
|
15
|
+
- **Core**: Hardened `parseAmount` and `parseAmountFromCents` to use strict decimal and integer regexes, rejecting hex (`0x10`), octal (`0o77`), binary (`0b10`), and scientific notation (`1e3`). Resolves #19.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- **Satispay**: Documented and implemented dedicated handling for GET callbacks (`?payment_id=...`): accepted as unsigned notification triggers for server-to-server API re-read authenticated with merchant private key; untrusted query parameters are ignored while POST webhooks strictly enforce HTTP Signature verification. Resolves #19.
|
|
19
|
+
- **Core**: Enforced that `success` is never `true` when `amount` is undefined or missing across all providers (PayPal, Satispay, Nexi). Confirmed payments without an amount now return `success: false` with `'Payment amount is missing or invalid'`. Resolves #19.
|
|
20
|
+
- **PayPal**: Exposed `captureStatus` separately in `PaymentResult` and `WebhookResult`. When an order has no capture, `status` is set to `'NO_CAPTURE'`, `captureStatus` is `undefined`, and `success` is `false`. Resolves #19.
|
|
21
|
+
- **Nexi**: Aligned `getPaymentDetails` to require paid/settled status (`'Contabilizzato'`, `'Autorizzato'`, `'Catturato'`) and valid amount for `success: true`. Resolves #19.
|
|
22
|
+
- **Documentation**: Documented `webhookPublicKey` requirement in production, raw body capture in Express, router mount prefix requirements, and fixed minor-unit status checking example. Resolves #19.
|
|
23
|
+
|
|
24
|
+
## [1.2.1] - 2026-09-28
|
|
25
|
+
|
|
26
|
+
### Security
|
|
27
|
+
- **Satispay**: Disallowed request body acting as headers during webhook signature verification. Resolves #16.
|
|
28
|
+
- **Satispay**: Enforced timestamp freshness window (`signatureMaxAgeMs`, default 5 minutes) on webhook signatures to prevent replay attacks. Resolves #16.
|
|
29
|
+
- **Satispay**: Strictly bound `Digest` header validation to the raw request body (`context.rawBody` or stringified body) verifying `SHA-256=<base64>`. Resolves #16.
|
|
30
|
+
- **Satispay**: Enforced `(request-target)` to be derived solely from trusted `context.method` and `context.path`. Resolves #16.
|
|
31
|
+
- **Satispay**: URL-encoded `payment_id` across API endpoints and strictly validated payment ID format (`/^[A-Za-z0-9_-]{1,64}$/`) rejecting directory traversal patterns. Resolves #16.
|
|
32
|
+
- **Nexi**: Enforced strict 40-character hexadecimal format validation on outcome MAC strings to prevent `RangeError` during timing-safe comparisons. Resolves #17.
|
|
33
|
+
- **Express Adapter**: Prevented sensitive internal provider payload data from being echoed in HTTP webhook JSON responses (strips `raw`). Resolves #17.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
- **PayPal**: Payment `success` is now strictly derived from capture status (`capture.status === 'COMPLETED'`) in `executePayment` and `getPaymentDetails`. Payments with non-completed or missing captures evaluate to `success: false`. Resolves #17.
|
|
37
|
+
- **Nexi**: Removed `report[0]` fallback in `getPaymentDetails` when the requested transaction order ID is not present in the BackOffice report, returning `{ success: false, error: 'Report not found' }`. Resolves #17.
|
|
38
|
+
- **Nexi**: Mapped ISO-4217 numeric currency codes (e.g. `'978'` -> `'EUR'`, `'840'` -> `'USD'`) to uppercase alpha-3 codes, returning `undefined` for unrecognized numeric codes. Resolves #17.
|
|
39
|
+
- **Core**: Empty or whitespace-only amount strings are parsed to `undefined` rather than coercing to `0`. Resolves #17.
|
|
40
|
+
- **Core**: Bounded `paymentOrders` map capacity to 10,000 entries with FIFO eviction to prevent memory leaks in long-running processes. Resolves #17.
|
|
41
|
+
- **Express Adapter**: Handled `res.headersSent` when `buildPaymentRequest` sends a response directly via `ctx.res` and returns `null`, preventing `ERR_HTTP_HEADERS_SENT` / double response errors. Resolves #17.
|
|
42
|
+
- **Documentation**: Corrected `publicPaths` examples, clarified Satispay callback URL configuration, raw body middleware, and GET callback authentication. Resolves #17.
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
- **Core**: Added optional `orderId` to `PaymentResult` and `WebhookResult`. Resolves #17.
|
|
46
|
+
- **Core**: Added `rawBody` support to `context` parameter in `IPaymentProvider.handleWebhook`. Resolves #16.
|
|
47
|
+
|
|
8
48
|
## [1.2.0] - 2026-09-27
|
|
9
49
|
|
|
10
50
|
### Security
|
package/README.md
CHANGED
|
@@ -40,8 +40,10 @@ checkout
|
|
|
40
40
|
.registerProvider(new SatispayProvider({
|
|
41
41
|
keyId: process.env.SATISPAY_KEY_ID!,
|
|
42
42
|
privateKey: fs.readFileSync('private.pem', 'utf8'),
|
|
43
|
+
webhookPublicKey: fs.readFileSync('satispay_public.pem', 'utf8'), // Required in production to verify incoming webhook signatures
|
|
43
44
|
environment: 'sandbox',
|
|
44
|
-
serverUrl: 'https://myapp.com',
|
|
45
|
+
serverUrl: 'https://myapp.com', // Base URL for callbacks: serverUrl + callbackPath (must include router mount prefix, e.g. /checkout)
|
|
46
|
+
callbackPath: '/checkout/satispay/webhook', // Optional: defaults to /checkout/satispay/webhook
|
|
45
47
|
}));
|
|
46
48
|
|
|
47
49
|
// Use directly — no HTTP framework needed
|
|
@@ -66,7 +68,12 @@ import express from 'express';
|
|
|
66
68
|
import { createCheckoutRouter } from 'awesome-node-checkout/express';
|
|
67
69
|
|
|
68
70
|
const app = express();
|
|
69
|
-
|
|
71
|
+
// Capture rawBody for webhook signature & digest verification (e.g. Satispay)
|
|
72
|
+
app.use(express.json({
|
|
73
|
+
verify: (req, _res, buf) => {
|
|
74
|
+
(req as any).rawBody = buf;
|
|
75
|
+
},
|
|
76
|
+
}));
|
|
70
77
|
// If using Nexi server notifications (urlpost), urlencoded parser is required:
|
|
71
78
|
app.use(express.urlencoded({ extended: false }));
|
|
72
79
|
|
|
@@ -106,10 +113,10 @@ app.use(
|
|
|
106
113
|
// Verify payment belongs to current session or user
|
|
107
114
|
},
|
|
108
115
|
},
|
|
109
|
-
// Public paths matching segments safely without substring bypasses
|
|
116
|
+
// Public paths matching segments safely without substring bypasses (accepts strings or segment arrays)
|
|
110
117
|
publicPaths: [
|
|
111
|
-
|
|
112
|
-
|
|
118
|
+
':provider/webhook',
|
|
119
|
+
':provider/redirect',
|
|
113
120
|
],
|
|
114
121
|
}),
|
|
115
122
|
);
|
|
@@ -129,12 +136,20 @@ fastify.post('/checkout/:provider', async (req, reply) => {
|
|
|
129
136
|
reply.status(result.success ? 201 : 400).send(result);
|
|
130
137
|
});
|
|
131
138
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
139
|
+
// Handle both POST and GET webhooks (e.g. Satispay GET callback vs Nexi/Satispay POST notification)
|
|
140
|
+
fastify.route({
|
|
141
|
+
method: ['GET', 'POST'],
|
|
142
|
+
url: '/checkout/:provider/webhook',
|
|
143
|
+
handler: async (req, reply) => {
|
|
144
|
+
const result = await checkout.handleWebhook(req.params.provider, req.body, req.headers, req.query, {
|
|
145
|
+
method: req.method,
|
|
146
|
+
path: req.url,
|
|
147
|
+
rawBody: (req as any).rawBody,
|
|
148
|
+
});
|
|
149
|
+
// Strip internal raw data before responding
|
|
150
|
+
const { raw, ...safeResult } = result;
|
|
151
|
+
reply.status(result.success ? 200 : 400).send(safeResult);
|
|
152
|
+
},
|
|
138
153
|
});
|
|
139
154
|
```
|
|
140
155
|
|
|
@@ -164,21 +179,31 @@ A full-featured reference implementation using Express 5, SQLite (`ITransactionS
|
|
|
164
179
|
Relying solely on front-end browser redirects (`GET /:provider/redirect`) to fulfill orders introduces significant risk:
|
|
165
180
|
- **Drop-off**: Shoppers may close the tab, lose connectivity, or navigate away before reaching your redirect URL.
|
|
166
181
|
- **Tampering**: Unless protected by cryptographic signatures (such as Nexi's mandatory outcome MAC), client-controlled URL parameters can be manipulated.
|
|
167
|
-
- **Amount Mismatch**: Always verify that the captured payment amount matches your order ledger before fulfilling goods or services.
|
|
182
|
+
- **Amount Mismatch**: Always verify that the captured payment amount matches your order ledger before fulfilling goods or services. In `awesome-node-checkout`, `success: true` strictly requires that a payment is confirmed with a valid amount.
|
|
168
183
|
|
|
169
184
|
To ensure safe fulfillment:
|
|
170
|
-
1. **Verify Amount & Currency**: `PaymentResult` and `WebhookResult` return `amount` and `currency` extracted directly from the provider.
|
|
185
|
+
1. **Verify Amount & Currency**: `PaymentResult` and `WebhookResult` return `amount` and `currency` extracted directly from the provider. Compare amounts in minor units (cents) or with rounding to prevent floating-point discrepancies:
|
|
171
186
|
```typescript
|
|
172
187
|
const result = await checkout.handleRedirect(provider, req.query);
|
|
173
|
-
if (result.success && result.status === 'COMPLETED') {
|
|
174
|
-
if (result.amount
|
|
188
|
+
if (result.success && (result.status === 'COMPLETED' || result.status === 'ACCEPTED')) {
|
|
189
|
+
if (result.amount === undefined) {
|
|
190
|
+
throw new Error('Payment reported success but amount is missing');
|
|
191
|
+
}
|
|
192
|
+
const orderCents = Math.round(order.totalAmount * 100);
|
|
193
|
+
const resultCents = Math.round(result.amount * 100);
|
|
194
|
+
if (resultCents !== orderCents || result.currency !== order.currency) {
|
|
175
195
|
throw new Error('Authorized amount does not match order total');
|
|
176
196
|
}
|
|
177
197
|
}
|
|
178
198
|
```
|
|
179
199
|
2. **Use Server Notifications / Webhooks**:
|
|
180
200
|
- For **Nexi**: Pass `notifyUrl` in `PaymentRequest` (e.g. `https://myapp.com/checkout/nexi/webhook`). Nexi sends a server-to-server POST notification (`urlpost`) with the 7-field outcome MAC. Ensure your app includes `app.use(express.urlencoded({ extended: false }))`.
|
|
181
|
-
- For **Satispay**:
|
|
201
|
+
- For **Satispay**: Set `serverUrl` (and optionally `callbackPath`, default `/checkout/satispay/webhook`). Note that `serverUrl + callbackPath` must include the router mount prefix (e.g. if mounted at `/checkout`, use `/checkout/satispay/webhook`).
|
|
202
|
+
- **Production Requirement**: Configure `webhookPublicKey` with Satispay's RSA public key (obtained via `GET /g_business/v1/consumers/{keyId}`) to enforce HTTP Signature verification. The verifier strictly requires at least `(request-target)`, `date`, and `digest` (when a body is present), as well as a valid `Date` header within the freshness window.
|
|
203
|
+
- **Raw Body Requirement**: In Express, capture the raw body buffer using `express.json({ verify: (req, _res, buf) => { (req as any).rawBody = buf; } })`. Passing a re-serialized or pretty-printed JSON body will alter whitespace and fail SHA-256 digest validation.
|
|
204
|
+
- **GET Callbacks vs POST Webhooks**:
|
|
205
|
+
- **POST Webhooks**: Sent directly from Satispay servers with an HTTP `Signature` header. When `webhookPublicKey` is configured, signature validity, header completeness, and freshness are strictly verified before processing.
|
|
206
|
+
- **GET Callbacks** (`?payment_id=...`): Satispay GET callbacks (e.g. user return/redirect) do not carry HTTP signatures. An unsigned GET callback is accepted solely as a trigger for a secure server-to-server re-read (`GET /payments/{id}`) authenticated with your merchant RSA private key. The `payment_id` is strictly sanitized to prevent traversal, and all parameters from the query string are ignored.
|
|
182
207
|
3. **Idempotency**: Because both the redirect callback and the webhook notification may arrive for the same order, ensure your fulfillment handler is idempotent.
|
|
183
208
|
|
|
184
209
|
---
|
|
@@ -15,12 +15,15 @@ export interface ExpressCheckoutOptions {
|
|
|
15
15
|
/**
|
|
16
16
|
* Route patterns that bypass `middleware` (e.g. [':provider/webhook', ':provider/redirect']).
|
|
17
17
|
* Matched by path segments after the mount point (:provider matches any single segment).
|
|
18
|
+
* Supports both path strings (':provider/webhook') and segment arrays ([':provider', 'webhook']).
|
|
18
19
|
*/
|
|
19
|
-
publicPaths?: string[];
|
|
20
|
+
publicPaths?: (string | string[])[];
|
|
20
21
|
/**
|
|
21
22
|
* Builds the PaymentRequest on the server (amount from your own order), ignoring the client body.
|
|
23
|
+
* If the hook sends an HTTP response directly (e.g. via `ctx.res.status(403)...`),
|
|
24
|
+
* returning `null` or `undefined` halts further adapter processing without error.
|
|
22
25
|
*/
|
|
23
|
-
buildPaymentRequest?: (req: Request, ctx: PaymentRequestContext) => PaymentRequest | Promise<PaymentRequest>;
|
|
26
|
+
buildPaymentRequest?: (req: Request, ctx: PaymentRequestContext) => PaymentRequest | null | undefined | Promise<PaymentRequest | null | undefined>;
|
|
24
27
|
/**
|
|
25
28
|
* When configured, GET /:provider/redirect responds with a 302 redirect
|
|
26
29
|
* to the URL returned by onSuccess or onFailure instead of JSON.
|
|
@@ -55,8 +58,9 @@ export interface ExpressCheckoutOptions {
|
|
|
55
58
|
/**
|
|
56
59
|
* Matches a request path against public path patterns by segments.
|
|
57
60
|
* ':provider' matches any single non-empty segment.
|
|
61
|
+
* Accepts patterns formatted as string ('/:provider/webhook') or segment arrays ([':provider', 'webhook']).
|
|
58
62
|
*/
|
|
59
|
-
export declare function isPathPublic(reqPath: string, publicPaths: string[]): boolean;
|
|
63
|
+
export declare function isPathPublic(reqPath: string, publicPaths: (string | string[])[]): boolean;
|
|
60
64
|
/**
|
|
61
65
|
* Creates an Express Router with all checkout endpoints pre-wired.
|
|
62
66
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/express/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAElE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,QAAQ,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAE9B
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/express/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAElE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,QAAQ,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAE9B;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC;IAEpC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,CACpB,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,qBAAqB,KACvB,cAAc,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAEpF;;;OAGG;IACH,QAAQ,CAAC,EAAE;QACT,SAAS,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;QAC3D,SAAS,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;KAC5D,CAAC;IAEF;;;OAGG;IACH,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;KAC/B,CAAC;IAEF;;;OAGG;IACH,MAAM,CAAC,EAAE;QACP,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;KAC/B,CAAC;IAEF;;OAEG;IACH,OAAO,CAAC,EAAE;QACR,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;QAC9B,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KAC7E,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,CAgBzF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,oBAAoB,EAC9B,OAAO,GAAE,sBAA2B,GACnC,MAAM,CA6LR"}
|
|
@@ -7,16 +7,19 @@ const errors_1 = require("../../models/errors");
|
|
|
7
7
|
/**
|
|
8
8
|
* Matches a request path against public path patterns by segments.
|
|
9
9
|
* ':provider' matches any single non-empty segment.
|
|
10
|
+
* Accepts patterns formatted as string ('/:provider/webhook') or segment arrays ([':provider', 'webhook']).
|
|
10
11
|
*/
|
|
11
12
|
function isPathPublic(reqPath, publicPaths) {
|
|
12
13
|
const reqSegments = reqPath.split('/').filter(Boolean);
|
|
13
14
|
return publicPaths.some((pattern) => {
|
|
14
|
-
const patternSegments =
|
|
15
|
+
const patternSegments = Array.isArray(pattern)
|
|
16
|
+
? pattern
|
|
17
|
+
: pattern.split('/').filter(Boolean);
|
|
15
18
|
if (reqSegments.length !== patternSegments.length) {
|
|
16
19
|
return false;
|
|
17
20
|
}
|
|
18
21
|
return patternSegments.every((patSeg, i) => {
|
|
19
|
-
if (patSeg === ':provider') {
|
|
22
|
+
if (patSeg === ':provider' || patSeg.startsWith(':')) {
|
|
20
23
|
return reqSegments[i].length > 0;
|
|
21
24
|
}
|
|
22
25
|
return patSeg === reqSegments[i];
|
|
@@ -81,27 +84,31 @@ function createCheckoutRouter(checkout, options = {}) {
|
|
|
81
84
|
const provider = String(req.params.provider);
|
|
82
85
|
let paymentRequest;
|
|
83
86
|
if (options.buildPaymentRequest) {
|
|
84
|
-
|
|
87
|
+
const customReq = await options.buildPaymentRequest(req, {
|
|
85
88
|
provider,
|
|
86
89
|
res,
|
|
87
90
|
});
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
typeof
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
91
|
+
if (res.headersSent) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (!customReq ||
|
|
95
|
+
typeof customReq !== 'object' ||
|
|
96
|
+
typeof customReq.amount !== 'number' ||
|
|
97
|
+
!Number.isFinite(customReq.amount) ||
|
|
98
|
+
customReq.amount <= 0 ||
|
|
99
|
+
typeof customReq.currency !== 'string' ||
|
|
100
|
+
customReq.currency.trim() === '' ||
|
|
101
|
+
typeof customReq.returnUrl !== 'string' ||
|
|
102
|
+
customReq.returnUrl.trim() === '' ||
|
|
103
|
+
typeof customReq.cancelUrl !== 'string' ||
|
|
104
|
+
customReq.cancelUrl.trim() === '') {
|
|
99
105
|
return res.status(400).json({
|
|
100
106
|
success: false,
|
|
101
107
|
code: 'INVALID_PAYMENT_REQUEST',
|
|
102
108
|
error: 'Invalid payment request returned by buildPaymentRequest: amount must be a positive number, currency, returnUrl, and cancelUrl are required strings',
|
|
103
109
|
});
|
|
104
110
|
}
|
|
111
|
+
paymentRequest = customReq;
|
|
105
112
|
}
|
|
106
113
|
else {
|
|
107
114
|
const body = req.body;
|
|
@@ -120,7 +127,8 @@ function createCheckoutRouter(checkout, options = {}) {
|
|
|
120
127
|
paymentRequest = body;
|
|
121
128
|
}
|
|
122
129
|
const result = await checkout.createPayment(provider, paymentRequest);
|
|
123
|
-
|
|
130
|
+
const { raw, ...safeResult } = result;
|
|
131
|
+
res.status(result.success ? 201 : 400).json(safeResult);
|
|
124
132
|
}
|
|
125
133
|
catch (err) {
|
|
126
134
|
sendError(res, err);
|
|
@@ -138,7 +146,8 @@ function createCheckoutRouter(checkout, options = {}) {
|
|
|
138
146
|
await options.execute.onBeforeExecute(req, paymentId);
|
|
139
147
|
}
|
|
140
148
|
const result = await checkout.executePayment(String(req.params.provider), paymentId, data);
|
|
141
|
-
|
|
149
|
+
const { raw, ...safeResult } = result;
|
|
150
|
+
res.status(result.success ? 200 : 400).json(safeResult);
|
|
142
151
|
}
|
|
143
152
|
catch (err) {
|
|
144
153
|
sendError(res, err);
|
|
@@ -154,7 +163,8 @@ function createCheckoutRouter(checkout, options = {}) {
|
|
|
154
163
|
try {
|
|
155
164
|
const { paymentId, amount } = req.body;
|
|
156
165
|
const result = await checkout.refundPayment(String(req.params.provider), paymentId, amount);
|
|
157
|
-
|
|
166
|
+
const { raw, ...safeResult } = result;
|
|
167
|
+
res.status(result.success ? 200 : 400).json(safeResult);
|
|
158
168
|
}
|
|
159
169
|
catch (err) {
|
|
160
170
|
sendError(res, err);
|
|
@@ -164,8 +174,14 @@ function createCheckoutRouter(checkout, options = {}) {
|
|
|
164
174
|
// ---- GET & POST /:provider/webhook — handle webhook ----------------------
|
|
165
175
|
const webhookHandler = async (req, res) => {
|
|
166
176
|
try {
|
|
167
|
-
const result = await checkout.handleWebhook(String(req.params.provider), req.body, req.headers, req.query, {
|
|
168
|
-
|
|
177
|
+
const result = await checkout.handleWebhook(String(req.params.provider), req.body, req.headers, req.query, {
|
|
178
|
+
method: req.method,
|
|
179
|
+
path: req.originalUrl || req.url,
|
|
180
|
+
rawBody: req.rawBody ?? (Buffer.isBuffer(req.body) ? req.body : undefined),
|
|
181
|
+
});
|
|
182
|
+
// Sanitize: do not echo raw provider payload in webhook response
|
|
183
|
+
const { raw, ...safeResult } = result;
|
|
184
|
+
res.status(result.success ? 200 : 400).json(safeResult);
|
|
169
185
|
}
|
|
170
186
|
catch (err) {
|
|
171
187
|
sendError(res, err);
|
|
@@ -185,7 +201,8 @@ function createCheckoutRouter(checkout, options = {}) {
|
|
|
185
201
|
: options.redirect.onFailure(result, req);
|
|
186
202
|
return res.redirect(302, targetUrl);
|
|
187
203
|
}
|
|
188
|
-
|
|
204
|
+
const { raw, ...safeResult } = result;
|
|
205
|
+
res.status(result.success ? 200 : 400).json(safeResult);
|
|
189
206
|
}
|
|
190
207
|
catch (err) {
|
|
191
208
|
sendError(res, err);
|
|
@@ -202,7 +219,8 @@ function createCheckoutRouter(checkout, options = {}) {
|
|
|
202
219
|
}
|
|
203
220
|
try {
|
|
204
221
|
const result = await checkout.getPaymentDetails(String(req.params.provider), String(req.params.id));
|
|
205
|
-
|
|
222
|
+
const { raw, ...safeResult } = result;
|
|
223
|
+
res.status(result.success ? 200 : 404).json(safeResult);
|
|
206
224
|
}
|
|
207
225
|
catch (err) {
|
|
208
226
|
sendError(res, err);
|
|
@@ -214,6 +232,8 @@ function createCheckoutRouter(checkout, options = {}) {
|
|
|
214
232
|
// Helpers
|
|
215
233
|
// ---------------------------------------------------------------------------
|
|
216
234
|
function sendError(res, err) {
|
|
235
|
+
if (res.headersSent)
|
|
236
|
+
return;
|
|
217
237
|
if (err instanceof errors_1.CheckoutError) {
|
|
218
238
|
const statusMap = {
|
|
219
239
|
PROVIDER_NOT_FOUND: 404,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/express/index.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/express/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,10 +27,13 @@ import { CheckoutEventBus } from './events/checkout-event-bus';
|
|
|
27
27
|
export declare class CheckoutConfigurator {
|
|
28
28
|
private readonly config;
|
|
29
29
|
private readonly providers;
|
|
30
|
+
private readonly maxPaymentOrders;
|
|
30
31
|
private readonly paymentOrders;
|
|
31
32
|
/** Event bus — subscribe to payment lifecycle events */
|
|
32
33
|
readonly events: CheckoutEventBus;
|
|
33
34
|
constructor(config?: CheckoutConfig);
|
|
35
|
+
/** Stores a paymentId -> orderId mapping with bounded capacity to prevent memory leaks */
|
|
36
|
+
private setPaymentOrder;
|
|
34
37
|
/** Emits an event only when `config.emitEvents` is not explicitly `false`. */
|
|
35
38
|
private emit;
|
|
36
39
|
/**
|
|
@@ -60,6 +63,7 @@ export declare class CheckoutConfigurator {
|
|
|
60
63
|
handleWebhook(providerName: string, body?: Record<string, unknown>, headers?: Record<string, string>, query?: Record<string, string>, context?: {
|
|
61
64
|
method?: string;
|
|
62
65
|
path?: string;
|
|
66
|
+
rawBody?: Buffer | string;
|
|
63
67
|
}): Promise<WebhookResult>;
|
|
64
68
|
/**
|
|
65
69
|
* Handle the redirect callback from the provider (query params).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkout-configurator.d.ts","sourceRoot":"","sources":["../src/checkout-configurator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAA2C,MAAM,6BAA6B,CAAC;AAExG;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,oBAAoB;
|
|
1
|
+
{"version":3,"file":"checkout-configurator.d.ts","sourceRoot":"","sources":["../src/checkout-configurator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAA2C,MAAM,6BAA6B,CAAC;AAExG;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,oBAAoB;IAQnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IACtE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkC;IAEhE,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAA0B;gBAE9B,MAAM,GAAE,cAAmB;IAExD,0FAA0F;IAC1F,OAAO,CAAC,eAAe;IAUvB,8EAA8E;YAChE,IAAI;IASlB;;;OAGG;IACH,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAalD;;;OAGG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB;IAY3C,oDAAoD;IACpD,sBAAsB,IAAI,MAAM,EAAE;IAIlC,sDAAsD;IAChD,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAkB1F,mDAAmD;IAC7C,cAAc,CAClB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,OAAO,CAAC,aAAa,CAAC;IAkBzB,2DAA2D;IACrD,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAKxF,qCAAqC;IAC/B,aAAa,CACjB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,aAAa,CAAC;IAkBzB;;;OAGG;IACG,aAAa,CACjB,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EACpC,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;IAmCzB;;;OAGG;IACG,cAAc,CAClB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,OAAO,CAAC,aAAa,CAAC;CA6B1B"}
|
|
@@ -28,10 +28,21 @@ class CheckoutConfigurator {
|
|
|
28
28
|
constructor(config = {}) {
|
|
29
29
|
this.config = config;
|
|
30
30
|
this.providers = new Map();
|
|
31
|
+
this.maxPaymentOrders = 10000;
|
|
31
32
|
this.paymentOrders = new Map();
|
|
32
33
|
/** Event bus — subscribe to payment lifecycle events */
|
|
33
34
|
this.events = new checkout_event_bus_1.CheckoutEventBus();
|
|
34
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
|
+
}
|
|
35
46
|
/** Emits an event only when `config.emitEvents` is not explicitly `false`. */
|
|
36
47
|
async emit(event, data) {
|
|
37
48
|
if (this.config.emitEvents !== false) {
|
|
@@ -70,7 +81,8 @@ class CheckoutConfigurator {
|
|
|
70
81
|
const provider = this.getProvider(providerName);
|
|
71
82
|
const result = await provider.createPayment(request);
|
|
72
83
|
if (result.paymentId && request.orderId) {
|
|
73
|
-
this.
|
|
84
|
+
this.setPaymentOrder(result.paymentId, request.orderId);
|
|
85
|
+
result.orderId = request.orderId;
|
|
74
86
|
}
|
|
75
87
|
await this.emit(result.success ? 'payment.created' : 'payment.failed', {
|
|
76
88
|
provider: providerName,
|
|
@@ -87,6 +99,9 @@ class CheckoutConfigurator {
|
|
|
87
99
|
const provider = this.getProvider(providerName);
|
|
88
100
|
const result = await provider.executePayment(paymentId, data);
|
|
89
101
|
const orderId = this.paymentOrders.get(paymentId);
|
|
102
|
+
if (orderId && !result.orderId) {
|
|
103
|
+
result.orderId = orderId;
|
|
104
|
+
}
|
|
90
105
|
await this.emit(result.success ? 'payment.completed' : 'payment.failed', {
|
|
91
106
|
provider: providerName,
|
|
92
107
|
paymentId,
|
|
@@ -107,6 +122,9 @@ class CheckoutConfigurator {
|
|
|
107
122
|
const provider = this.getProvider(providerName);
|
|
108
123
|
const result = await provider.refundPayment(paymentId, amount);
|
|
109
124
|
const orderId = this.paymentOrders.get(paymentId);
|
|
125
|
+
if (orderId && !result.orderId) {
|
|
126
|
+
result.orderId = orderId;
|
|
127
|
+
}
|
|
110
128
|
await this.emit('payment.refunded', {
|
|
111
129
|
provider: providerName,
|
|
112
130
|
paymentId,
|
|
@@ -134,6 +152,9 @@ class CheckoutConfigurator {
|
|
|
134
152
|
rawAny?.codTrans ??
|
|
135
153
|
query?.order_id ??
|
|
136
154
|
(result.paymentId ? this.paymentOrders.get(result.paymentId) : undefined);
|
|
155
|
+
if (orderId && !result.orderId) {
|
|
156
|
+
result.orderId = orderId;
|
|
157
|
+
}
|
|
137
158
|
await this.emit('webhook.received', {
|
|
138
159
|
provider: providerName,
|
|
139
160
|
paymentId: result.paymentId,
|
|
@@ -158,6 +179,9 @@ class CheckoutConfigurator {
|
|
|
158
179
|
const orderId = (result.paymentId ? this.paymentOrders.get(result.paymentId) : undefined) ??
|
|
159
180
|
query?.order_id ??
|
|
160
181
|
query?.codTrans;
|
|
182
|
+
if (orderId && !result.orderId) {
|
|
183
|
+
result.orderId = orderId;
|
|
184
|
+
}
|
|
161
185
|
await this.emit(result.success ? 'payment.completed' : 'payment.failed', {
|
|
162
186
|
provider: providerName,
|
|
163
187
|
paymentId: result.paymentId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkout-configurator.js","sourceRoot":"","sources":["../src/checkout-configurator.ts"],"names":[],"mappings":";;;AAIA,4CAAgD;AAChD,oEAAwG;AAExG;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAa,oBAAoB;
|
|
1
|
+
{"version":3,"file":"checkout-configurator.js","sourceRoot":"","sources":["../src/checkout-configurator.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,7 @@ export interface IPaymentProvider {
|
|
|
27
27
|
handleWebhook?(body?: Record<string, unknown>, headers?: Record<string, string>, query?: Record<string, string>, context?: {
|
|
28
28
|
method?: string;
|
|
29
29
|
path?: string;
|
|
30
|
+
rawBody?: Buffer | string;
|
|
30
31
|
}): Promise<WebhookResult>;
|
|
31
32
|
/**
|
|
32
33
|
* Handle the redirect callback from the provider (query params from returnUrl).
|
|
@@ -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;;;;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,CAAA;KAAE,
|
|
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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** Unified result returned by all payment operations */
|
|
2
2
|
export interface PaymentResult {
|
|
3
|
+
/** True when payment is confirmed/completed with a valid captured amount */
|
|
3
4
|
success: boolean;
|
|
4
5
|
/** Provider-specific payment identifier */
|
|
5
6
|
paymentId?: string;
|
|
@@ -7,20 +8,27 @@ export interface PaymentResult {
|
|
|
7
8
|
approvalUrl?: string;
|
|
8
9
|
/** Current payment status (provider-specific string, e.g. 'COMPLETED', 'ACCEPTED') */
|
|
9
10
|
status?: string;
|
|
11
|
+
/** Provider-specific capture status if distinct from overall order status (e.g. PayPal) */
|
|
12
|
+
captureStatus?: string;
|
|
10
13
|
/** Amount reported by the provider, major units (same unit as PaymentRequest.amount) */
|
|
11
14
|
amount?: number;
|
|
12
15
|
/** ISO 4217 alpha code reported by the provider (e.g. 'EUR') */
|
|
13
16
|
currency?: string;
|
|
17
|
+
/** Order identifier associated with the payment if tracked */
|
|
18
|
+
orderId?: string;
|
|
14
19
|
/** Error message if success is false */
|
|
15
20
|
error?: string;
|
|
16
|
-
/** Raw provider response —
|
|
21
|
+
/** Raw provider response — preserved in events and returned models, stripped from HTTP router responses */
|
|
17
22
|
raw?: any;
|
|
18
23
|
}
|
|
19
24
|
/** Result returned by handleWebhook() */
|
|
20
25
|
export interface WebhookResult {
|
|
26
|
+
/** True when payment is confirmed/completed with a valid captured amount */
|
|
21
27
|
success: boolean;
|
|
22
28
|
paymentId?: string;
|
|
29
|
+
orderId?: string;
|
|
23
30
|
status?: string;
|
|
31
|
+
captureStatus?: string;
|
|
24
32
|
/** Amount reported by the provider, major units (same unit as PaymentRequest.amount) */
|
|
25
33
|
amount?: number;
|
|
26
34
|
/** ISO 4217 alpha code reported by the provider (e.g. 'EUR') */
|
|
@@ -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,wFAAwF;IACxF,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf
|
|
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,4EAA4E;IAC5E,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,2FAA2F;IAC3F,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,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,2GAA2G;IAC3G,GAAG,CAAC,EAAE,GAAG,CAAC;CACX;AAED,yCAAyC;AACzC,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,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"}
|
|
@@ -47,6 +47,11 @@ export declare class NexiProvider extends BasePaymentProvider {
|
|
|
47
47
|
* Format: `alias={alias}codTrans={codTrans}importo={importo}timestamp={timestamp}{macKey}`
|
|
48
48
|
*/
|
|
49
49
|
private generateRefundMac;
|
|
50
|
+
/**
|
|
51
|
+
/**
|
|
52
|
+
* Validates that the MAC is a string of exactly 40 hexadecimal characters.
|
|
53
|
+
*/
|
|
54
|
+
private isValidHexMac;
|
|
50
55
|
/**
|
|
51
56
|
* Verifies the SHA-1 outcome MAC included in a Nexi POST-back response or server notification.
|
|
52
57
|
* Format: `codTrans={codTrans}esito={esito}importo={importo}divisa={divisa}data={data}orario={orario}codAut={codAut}{macKey}`
|
|
@@ -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,aAAa,EAAE,MAAM,mCAAmC,CAAC;
|
|
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;IAsD9F;;;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;IAgDnB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAqG5D,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"}
|