awesome-node-checkout 1.0.1 → 1.1.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +44 -10
  3. package/dist/abstract/base-payment-provider.abstract.d.ts +30 -0
  4. package/dist/abstract/base-payment-provider.abstract.d.ts.map +1 -0
  5. package/dist/abstract/base-payment-provider.abstract.js +28 -0
  6. package/dist/abstract/base-payment-provider.abstract.js.map +1 -0
  7. package/dist/adapters/express/index.d.ts +65 -0
  8. package/dist/adapters/express/index.d.ts.map +1 -0
  9. package/dist/adapters/express/index.js +176 -0
  10. package/dist/adapters/express/index.js.map +1 -0
  11. package/dist/checkout-configurator.d.ts +66 -0
  12. package/dist/checkout-configurator.d.ts.map +1 -0
  13. package/dist/checkout-configurator.js +148 -0
  14. package/dist/checkout-configurator.js.map +1 -0
  15. package/dist/events/checkout-event-bus.d.ts +29 -0
  16. package/dist/events/checkout-event-bus.d.ts.map +1 -0
  17. package/dist/events/checkout-event-bus.js +37 -0
  18. package/dist/events/checkout-event-bus.js.map +1 -0
  19. package/dist/index.d.ts +19 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +25 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/interfaces/payment-provider.interface.d.ts +33 -0
  24. package/dist/interfaces/payment-provider.interface.d.ts.map +1 -0
  25. package/dist/interfaces/payment-provider.interface.js +3 -0
  26. package/dist/interfaces/payment-provider.interface.js.map +1 -0
  27. package/dist/interfaces/transaction-store.interface.d.ts +24 -0
  28. package/dist/interfaces/transaction-store.interface.d.ts.map +1 -0
  29. package/dist/interfaces/transaction-store.interface.js +3 -0
  30. package/dist/interfaces/transaction-store.interface.js.map +1 -0
  31. package/dist/models/checkout-config.model.d.ts +12 -0
  32. package/dist/models/checkout-config.model.d.ts.map +1 -0
  33. package/dist/models/checkout-config.model.js +3 -0
  34. package/dist/models/checkout-config.model.js.map +1 -0
  35. package/dist/models/errors.d.ts +7 -0
  36. package/dist/models/errors.d.ts.map +1 -0
  37. package/dist/models/errors.js +17 -0
  38. package/dist/models/errors.js.map +1 -0
  39. package/dist/models/payment-request.model.d.ts +21 -0
  40. package/dist/models/payment-request.model.d.ts.map +1 -0
  41. package/dist/models/payment-request.model.js +3 -0
  42. package/dist/models/payment-request.model.js.map +1 -0
  43. package/dist/models/payment-result.model.d.ts +23 -0
  44. package/dist/models/payment-result.model.d.ts.map +1 -0
  45. package/dist/models/payment-result.model.js +3 -0
  46. package/dist/models/payment-result.model.js.map +1 -0
  47. package/dist/providers/nexi/nexi.provider.d.ts +64 -0
  48. package/dist/providers/nexi/nexi.provider.d.ts.map +1 -0
  49. package/dist/providers/nexi/nexi.provider.js +227 -0
  50. package/dist/providers/nexi/nexi.provider.js.map +1 -0
  51. package/dist/providers/paypal/paypal.provider.d.ts +33 -0
  52. package/dist/providers/paypal/paypal.provider.d.ts.map +1 -0
  53. package/dist/providers/paypal/paypal.provider.js +167 -0
  54. package/dist/providers/paypal/paypal.provider.js.map +1 -0
  55. package/dist/providers/satispay/satispay.provider.d.ts +79 -0
  56. package/dist/providers/satispay/satispay.provider.d.ts.map +1 -0
  57. package/dist/providers/satispay/satispay.provider.js +301 -0
  58. package/dist/providers/satispay/satispay.provider.js.map +1 -0
  59. package/dist/stores/in-memory-transaction.store.d.ts +17 -0
  60. package/dist/stores/in-memory-transaction.store.d.ts.map +1 -0
  61. package/dist/stores/in-memory-transaction.store.js +30 -0
  62. package/dist/stores/in-memory-transaction.store.js.map +1 -0
  63. package/package.json +12 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,37 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.1.0] - 2026-09-27
9
+
10
+ ### Added
11
+ - **Security**: Added `buildPaymentRequest` hook in `createCheckoutRouter` options to build payment requests securely server-side (preventing clients from tampering with amounts and order parameters). Resolves #3.
12
+ - **Security**: Added mount-time warning when `createCheckoutRouter` is used without `buildPaymentRequest`.
13
+ - **Validation**: Added input validation on `POST /:provider` when `buildPaymentRequest` is not configured (requires finite positive number `amount` and non-empty `currency`).
14
+ - **Gating**: Gated `POST /:provider/refund` behind `options.refund` (returns 404 unless explicitly configured with optional middleware).
15
+ - **Hooks**: Added `onBeforeExecute` and dedicated `middleware` support in `options.execute` for `POST /:provider/execute`.
16
+ - **Examples**: Added reference Express implementation under `examples/express` demonstrating SQLite store, Handlebars UI, and full checkout flow.
17
+
18
+ ## [1.0.2] - 2026-04-23
19
+
20
+ ### Changed
21
+ - Removed compiled `dist/` artifacts from git tracking.
22
+ - Added GitHub Actions publish workflow.
23
+ - Updated dependencies.
24
+
25
+ ## [1.0.1] - 2026-04-13
26
+
27
+ ### Fixed
28
+ - Satispay provider warning at construction time when `webhookPublicKey` is not configured.
29
+ - PayPal refund implementation and security improvements.
30
+
31
+ ## [1.0.0] - 2026-03-30
32
+
33
+ ### Added
34
+ - Initial release of `awesome-node-checkout`.
35
+ - Framework-agnostic `CheckoutConfigurator`.
36
+ - PayPal, Nexi, and Satispay providers.
37
+ - Express adapter with `createCheckoutRouter`.
package/README.md CHANGED
@@ -68,12 +68,40 @@ import { createCheckoutRouter } from 'awesome-node-checkout/express';
68
68
  const app = express();
69
69
  app.use(express.json());
70
70
 
71
- // Mounts all checkout routes under /checkout
72
- app.use('/checkout', createCheckoutRouter(checkout));
71
+ // Mount checkout routes with secure server-side request builder
72
+ app.use(
73
+ '/checkout',
74
+ createCheckoutRouter(checkout, {
75
+ // Recommended: verify order and compute amount on the server
76
+ buildPaymentRequest: async (req) => {
77
+ const order = await myOrderService.getOrder(req.body.orderId);
78
+ return {
79
+ amount: order.totalAmount,
80
+ currency: order.currency, // e.g. 'EUR'
81
+ orderId: order.id,
82
+ returnUrl: 'https://myapp.com/payment/success',
83
+ cancelUrl: 'https://myapp.com/payment/cancel',
84
+ description: `Order #${order.id}`,
85
+ };
86
+ },
87
+ // Opt-in: mount POST /:provider/refund protected by admin middleware
88
+ refund: {
89
+ middleware: [requireAdminAuth],
90
+ },
91
+ // Optional: guard execution before capturing payment
92
+ execute: {
93
+ onBeforeExecute: async (req, paymentId) => {
94
+ // Verify payment belongs to current session or user
95
+ },
96
+ },
97
+ }),
98
+ );
73
99
 
74
100
  app.listen(3000);
75
101
  ```
76
102
 
103
+ > **Security Note**: Never trust client-sent amounts directly. Always define `buildPaymentRequest` so the payment amount and order parameters are derived server-side. If `buildPaymentRequest` is omitted, the router will issue a warning at mount time and validate that client bodies contain positive finite amounts and valid currencies.
104
+
77
105
  ### With Fastify (or any other framework)
78
106
 
79
107
  Use the `CheckoutConfigurator` methods directly in your own routes:
@@ -92,16 +120,22 @@ fastify.post('/checkout/:provider/webhook', async (req, reply) => {
92
120
 
93
121
  ---
94
122
 
123
+ ## Example Application
124
+
125
+ A full-featured reference implementation using Express 5, SQLite (`ITransactionStore`), and Handlebars is available in [examples/express](./examples/express).
126
+
127
+ ---
128
+
95
129
  ## Routes (Express adapter)
96
130
 
97
- | Method | Path | Description |
98
- |--------|-----------------------------|----------------------------------|
99
- | POST | `/:provider` | Create a payment |
100
- | POST | `/:provider/execute` | Execute/capture a payment |
101
- | GET | `/:provider/redirect` | Handle provider redirect callback|
102
- | GET | `/:provider/:id` | Get payment details |
103
- | POST | `/:provider/refund` | Refund a payment |
104
- | POST | `/:provider/webhook` | Handle provider webhook |
131
+ | Method | Path | Description |
132
+ |--------|-----------------------------|----------------------------------------------------------------|
133
+ | POST | `/:provider` | Create a payment (server-built or validated) |
134
+ | POST | `/:provider/execute` | Execute/capture a payment (supports `onBeforeExecute`) |
135
+ | GET | `/:provider/redirect` | Handle provider redirect callback |
136
+ | GET | `/:provider/:id` | Get payment details |
137
+ | POST | `/:provider/refund` | Refund a payment (*opt-in*: mounted only when `refund` option is set)|
138
+ | POST | `/:provider/webhook` | Handle provider webhook |
105
139
 
106
140
  ---
107
141
 
@@ -0,0 +1,30 @@
1
+ import { IPaymentProvider, PaymentFlow } from '../interfaces/payment-provider.interface';
2
+ import { PaymentRequest } from '../models/payment-request.model';
3
+ import { PaymentResult } from '../models/payment-result.model';
4
+ /**
5
+ * Convenience base class for building custom payment providers.
6
+ * Provides the `errorResult` helper to normalize error handling.
7
+ *
8
+ * Usage:
9
+ * ```typescript
10
+ * export class MyProvider extends BasePaymentProvider {
11
+ * readonly name = 'myprovider';
12
+ * readonly flow = 'redirect' as const;
13
+ * // ... implement abstract methods
14
+ * }
15
+ * ```
16
+ */
17
+ export declare abstract class BasePaymentProvider implements IPaymentProvider {
18
+ abstract readonly name: string;
19
+ abstract readonly flow: PaymentFlow;
20
+ abstract createPayment(request: PaymentRequest): Promise<PaymentResult>;
21
+ abstract executePayment(paymentId: string, data?: Record<string, string>): Promise<PaymentResult>;
22
+ abstract getPaymentDetails(paymentId: string): Promise<PaymentResult>;
23
+ abstract refundPayment(paymentId: string, amount?: number): Promise<PaymentResult>;
24
+ /**
25
+ * Helper to produce a normalized error PaymentResult.
26
+ * Extracts message from Error instances automatically.
27
+ */
28
+ protected errorResult(error: unknown, fallback?: string): PaymentResult;
29
+ }
30
+ //# sourceMappingURL=base-payment-provider.abstract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-payment-provider.abstract.d.ts","sourceRoot":"","sources":["../../src/abstract/base-payment-provider.abstract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAC;AACzF,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAE/D;;;;;;;;;;;;GAYG;AACH,8BAAsB,mBAAoB,YAAW,gBAAgB;IACnE,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAEpC,QAAQ,CAAC,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IACvE,QAAQ,CAAC,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC;IACjG,QAAQ,CAAC,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IACrE,QAAQ,CAAC,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAElF;;;OAGG;IACH,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,SAAkB,GAAG,aAAa;CAIjF"}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BasePaymentProvider = void 0;
4
+ /**
5
+ * Convenience base class for building custom payment providers.
6
+ * Provides the `errorResult` helper to normalize error handling.
7
+ *
8
+ * Usage:
9
+ * ```typescript
10
+ * export class MyProvider extends BasePaymentProvider {
11
+ * readonly name = 'myprovider';
12
+ * readonly flow = 'redirect' as const;
13
+ * // ... implement abstract methods
14
+ * }
15
+ * ```
16
+ */
17
+ class BasePaymentProvider {
18
+ /**
19
+ * Helper to produce a normalized error PaymentResult.
20
+ * Extracts message from Error instances automatically.
21
+ */
22
+ errorResult(error, fallback = 'Unknown error') {
23
+ const message = error instanceof Error ? error.message : fallback;
24
+ return { success: false, error: message };
25
+ }
26
+ }
27
+ exports.BasePaymentProvider = BasePaymentProvider;
28
+ //# sourceMappingURL=base-payment-provider.abstract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-payment-provider.abstract.js","sourceRoot":"","sources":["../../src/abstract/base-payment-provider.abstract.ts"],"names":[],"mappings":";;;AAIA;;;;;;;;;;;;GAYG;AACH,MAAsB,mBAAmB;IASvC;;;OAGG;IACO,WAAW,CAAC,KAAc,EAAE,QAAQ,GAAG,eAAe;QAC9D,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;QAClE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAC5C,CAAC;CACF;AAjBD,kDAiBC"}
@@ -0,0 +1,65 @@
1
+ import { Router, Request, RequestHandler } from 'express';
2
+ import { CheckoutConfigurator } from '../../checkout-configurator';
3
+ import { PaymentRequest } from '../../models/payment-request.model';
4
+ export interface ExpressCheckoutOptions {
5
+ /**
6
+ * Middleware applied to ALL checkout routes (e.g. API key auth).
7
+ * Webhooks are typically public — use `publicPaths` to exclude them.
8
+ */
9
+ middleware?: RequestHandler[];
10
+ /**
11
+ * Route suffixes that bypass `middleware` (e.g. [':provider/webhook']).
12
+ * Matched against the path suffix after the mount point.
13
+ */
14
+ publicPaths?: string[];
15
+ /**
16
+ * Builds the PaymentRequest on the server (amount from your own order), ignoring the client body.
17
+ */
18
+ buildPaymentRequest?: (req: Request) => PaymentRequest | Promise<PaymentRequest>;
19
+ /**
20
+ * Configuration for POST /:provider/refund.
21
+ * If omitted, the refund route is NOT mounted (returns 404).
22
+ */
23
+ refund?: {
24
+ middleware?: RequestHandler[];
25
+ };
26
+ /**
27
+ * Configuration for POST /:provider/execute.
28
+ */
29
+ execute?: {
30
+ middleware?: RequestHandler[];
31
+ onBeforeExecute?: (req: Request, paymentId: string) => void | Promise<void>;
32
+ };
33
+ }
34
+ /**
35
+ * Creates an Express Router with all checkout endpoints pre-wired.
36
+ *
37
+ * Routes mounted:
38
+ * ```
39
+ * POST /:provider → createPayment
40
+ * POST /:provider/execute → executePayment
41
+ * GET /:provider/redirect → handleRedirect (must come before /:provider/:id)
42
+ * GET /:provider/:id → getPaymentDetails
43
+ * POST /:provider/refund → refundPayment (only if options.refund is configured)
44
+ * POST /:provider/webhook → handleWebhook
45
+ * ```
46
+ *
47
+ * Usage:
48
+ * ```typescript
49
+ * import { createCheckoutRouter } from 'awesome-node-checkout/express';
50
+ * app.use('/checkout', createCheckoutRouter(checkout, {
51
+ * buildPaymentRequest: async (req) => {
52
+ * const order = await getOrder(req.body.orderId);
53
+ * return {
54
+ * amount: order.total,
55
+ * currency: 'EUR',
56
+ * orderId: order.id,
57
+ * returnUrl: 'https://example.com/success',
58
+ * cancelUrl: 'https://example.com/cancel',
59
+ * };
60
+ * },
61
+ * }));
62
+ * ```
63
+ */
64
+ export declare function createCheckoutRouter(checkout: CheckoutConfigurator, options?: ExpressCheckoutOptions): Router;
65
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/express/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAY,cAAc,EAAE,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAE9B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAEvB;;OAEG;IACH,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAEjF;;;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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,oBAAoB,EAC9B,OAAO,GAAE,sBAA2B,GACnC,MAAM,CAsIR"}
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCheckoutRouter = createCheckoutRouter;
4
+ const express_1 = require("express");
5
+ const errors_1 = require("../../models/errors");
6
+ /**
7
+ * Creates an Express Router with all checkout endpoints pre-wired.
8
+ *
9
+ * Routes mounted:
10
+ * ```
11
+ * POST /:provider → createPayment
12
+ * POST /:provider/execute → executePayment
13
+ * GET /:provider/redirect → handleRedirect (must come before /:provider/:id)
14
+ * GET /:provider/:id → getPaymentDetails
15
+ * POST /:provider/refund → refundPayment (only if options.refund is configured)
16
+ * POST /:provider/webhook → handleWebhook
17
+ * ```
18
+ *
19
+ * Usage:
20
+ * ```typescript
21
+ * import { createCheckoutRouter } from 'awesome-node-checkout/express';
22
+ * app.use('/checkout', createCheckoutRouter(checkout, {
23
+ * buildPaymentRequest: async (req) => {
24
+ * const order = await getOrder(req.body.orderId);
25
+ * return {
26
+ * amount: order.total,
27
+ * currency: 'EUR',
28
+ * orderId: order.id,
29
+ * returnUrl: 'https://example.com/success',
30
+ * cancelUrl: 'https://example.com/cancel',
31
+ * };
32
+ * },
33
+ * }));
34
+ * ```
35
+ */
36
+ function createCheckoutRouter(checkout, options = {}) {
37
+ const router = (0, express_1.Router)();
38
+ if (!options.buildPaymentRequest) {
39
+ console.warn('[awesome-node-checkout] createCheckoutRouter: the client body decides the amount; set buildPaymentRequest');
40
+ }
41
+ // Apply shared middleware (skipping public paths)
42
+ if (options.middleware?.length) {
43
+ const publicPaths = options.publicPaths ?? [];
44
+ router.use((req, res, next) => {
45
+ const providerParam = String(req.params?.provider ?? '');
46
+ const isPublic = publicPaths.some((p) => req.path.endsWith(p) || req.path.includes(p.replace(':provider', providerParam)));
47
+ if (isPublic)
48
+ return next();
49
+ // Chain all middleware in sequence
50
+ const handlers = options.middleware;
51
+ const run = (i) => {
52
+ if (i >= handlers.length)
53
+ return next();
54
+ handlers[i](req, res, () => run(i + 1));
55
+ };
56
+ run(0);
57
+ });
58
+ }
59
+ // ---- POST /:provider — create payment ------------------------------------
60
+ router.post('/:provider', async (req, res) => {
61
+ try {
62
+ let paymentRequest;
63
+ if (options.buildPaymentRequest) {
64
+ paymentRequest = await options.buildPaymentRequest(req);
65
+ }
66
+ else {
67
+ const body = req.body;
68
+ const amount = body?.amount;
69
+ const currency = body?.currency;
70
+ if (typeof amount !== 'number' ||
71
+ !Number.isFinite(amount) ||
72
+ amount <= 0 ||
73
+ typeof currency !== 'string' ||
74
+ currency.trim() === '') {
75
+ return res.status(400).json({
76
+ success: false,
77
+ error: 'Invalid payment request: amount must be a positive number and currency is required',
78
+ });
79
+ }
80
+ paymentRequest = body;
81
+ }
82
+ const result = await checkout.createPayment(String(req.params.provider), paymentRequest);
83
+ res.status(result.success ? 201 : 400).json(result);
84
+ }
85
+ catch (err) {
86
+ sendError(res, err);
87
+ }
88
+ });
89
+ // ---- POST /:provider/execute — execute payment ---------------------------
90
+ const executeHandlers = [];
91
+ if (options.execute?.middleware?.length) {
92
+ executeHandlers.push(...options.execute.middleware);
93
+ }
94
+ router.post('/:provider/execute', ...executeHandlers, async (req, res) => {
95
+ try {
96
+ const { paymentId, data } = req.body;
97
+ if (options.execute?.onBeforeExecute) {
98
+ await options.execute.onBeforeExecute(req, paymentId);
99
+ }
100
+ const result = await checkout.executePayment(String(req.params.provider), paymentId, data);
101
+ res.status(result.success ? 200 : 400).json(result);
102
+ }
103
+ catch (err) {
104
+ sendError(res, err);
105
+ }
106
+ });
107
+ // ---- POST /:provider/refund — refund payment (opt-in) --------------------
108
+ if (options.refund) {
109
+ const refundHandlers = [];
110
+ if (options.refund.middleware?.length) {
111
+ refundHandlers.push(...options.refund.middleware);
112
+ }
113
+ router.post('/:provider/refund', ...refundHandlers, async (req, res) => {
114
+ try {
115
+ const { paymentId, amount } = req.body;
116
+ const result = await checkout.refundPayment(String(req.params.provider), paymentId, amount);
117
+ res.status(result.success ? 200 : 400).json(result);
118
+ }
119
+ catch (err) {
120
+ sendError(res, err);
121
+ }
122
+ });
123
+ }
124
+ // ---- POST /:provider/webhook — handle webhook ----------------------------
125
+ router.post('/:provider/webhook', async (req, res) => {
126
+ try {
127
+ const result = await checkout.handleWebhook(String(req.params.provider), req.body, req.headers);
128
+ res.status(result.success ? 200 : 400).json(result);
129
+ }
130
+ catch (err) {
131
+ sendError(res, err);
132
+ }
133
+ });
134
+ // ---- GET /:provider/redirect — handle redirect callback ------------------
135
+ // NOTE: must be defined BEFORE /:provider/:id to avoid "redirect" being
136
+ // treated as a paymentId.
137
+ router.get('/:provider/redirect', async (req, res) => {
138
+ try {
139
+ const result = await checkout.handleRedirect(String(req.params.provider), req.query);
140
+ res.status(result.success ? 200 : 400).json(result);
141
+ }
142
+ catch (err) {
143
+ sendError(res, err);
144
+ }
145
+ });
146
+ // ---- GET /:provider/:id — get payment details ----------------------------
147
+ router.get('/:provider/:id', async (req, res) => {
148
+ try {
149
+ const result = await checkout.getPaymentDetails(String(req.params.provider), String(req.params.id));
150
+ res.status(result.success ? 200 : 404).json(result);
151
+ }
152
+ catch (err) {
153
+ sendError(res, err);
154
+ }
155
+ });
156
+ return router;
157
+ }
158
+ // ---------------------------------------------------------------------------
159
+ // Helpers
160
+ // ---------------------------------------------------------------------------
161
+ function sendError(res, err) {
162
+ if (err instanceof errors_1.CheckoutError) {
163
+ const statusMap = {
164
+ PROVIDER_NOT_FOUND: 404,
165
+ WEBHOOK_NOT_SUPPORTED: 422,
166
+ REDIRECT_NOT_SUPPORTED: 422,
167
+ };
168
+ const status = statusMap[err.code] ?? 400;
169
+ res.status(status).json({ success: false, error: err.message, code: err.code });
170
+ }
171
+ else {
172
+ const message = err instanceof Error ? err.message : 'Internal server error';
173
+ res.status(500).json({ success: false, error: message });
174
+ }
175
+ }
176
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/express/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import { IPaymentProvider } from './interfaces/payment-provider.interface';
2
+ import { PaymentRequest } from './models/payment-request.model';
3
+ import { PaymentResult, WebhookResult } from './models/payment-result.model';
4
+ import { CheckoutConfig } from './models/checkout-config.model';
5
+ import { CheckoutEventBus } from './events/checkout-event-bus';
6
+ /**
7
+ * Main entry point for awesome-node-checkout.
8
+ *
9
+ * Usage (framework-agnostic):
10
+ * ```typescript
11
+ * const checkout = new CheckoutConfigurator();
12
+ * checkout
13
+ * .registerProvider(new PayPalProvider({ clientId, clientSecret }))
14
+ * .registerProvider(new NexiProvider({ merchantId, macKey }))
15
+ * .registerProvider(new SatispayProvider({ keyId, privateKey }));
16
+ *
17
+ * // Use directly in any framework
18
+ * const result = await checkout.createPayment('paypal', request);
19
+ * ```
20
+ *
21
+ * Usage with Express adapter:
22
+ * ```typescript
23
+ * import { createCheckoutRouter } from 'awesome-node-checkout/express';
24
+ * app.use('/checkout', createCheckoutRouter(checkout));
25
+ * ```
26
+ */
27
+ export declare class CheckoutConfigurator {
28
+ private readonly config;
29
+ private readonly providers;
30
+ /** Event bus — subscribe to payment lifecycle events */
31
+ readonly events: CheckoutEventBus;
32
+ constructor(config?: CheckoutConfig);
33
+ /** Emits an event only when `config.emitEvents` is not explicitly `false`. */
34
+ private emit;
35
+ /**
36
+ * Register a payment provider. Chainable.
37
+ * @throws CheckoutError if a provider with the same name is already registered.
38
+ */
39
+ registerProvider(provider: IPaymentProvider): this;
40
+ /**
41
+ * Retrieve a registered provider by name.
42
+ * @throws CheckoutError if the provider is not found.
43
+ */
44
+ getProvider(name: string): IPaymentProvider;
45
+ /** Returns the names of all registered providers */
46
+ getRegisteredProviders(): string[];
47
+ /** Create a new payment via the specified provider */
48
+ createPayment(providerName: string, request: PaymentRequest): Promise<PaymentResult>;
49
+ /** Execute/capture a previously created payment */
50
+ executePayment(providerName: string, paymentId: string, data?: Record<string, string>): Promise<PaymentResult>;
51
+ /** Retrieve the current status and details of a payment */
52
+ getPaymentDetails(providerName: string, paymentId: string): Promise<PaymentResult>;
53
+ /** Issue a full or partial refund */
54
+ refundPayment(providerName: string, paymentId: string, amount?: number): Promise<PaymentResult>;
55
+ /**
56
+ * Handle an incoming webhook from the provider.
57
+ * @throws CheckoutError if the provider does not support webhooks.
58
+ */
59
+ handleWebhook(providerName: string, body: Record<string, unknown>, headers: Record<string, string>): Promise<WebhookResult>;
60
+ /**
61
+ * Handle the redirect callback from the provider (query params).
62
+ * @throws CheckoutError if the provider does not support redirect handling.
63
+ */
64
+ handleRedirect(providerName: string, query: Record<string, string>): Promise<PaymentResult>;
65
+ }
66
+ //# sourceMappingURL=checkout-configurator.d.ts.map
@@ -0,0 +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;IAMnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IALnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IAEtE,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAA0B;gBAE9B,MAAM,GAAE,cAAmB;IAExD,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;IAa1F,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;IAYzB,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;IAYzB;;;OAGG;IACG,aAAa,CACjB,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,OAAO,CAAC,aAAa,CAAC;IAoBzB;;;OAGG;IACG,cAAc,CAClB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,OAAO,CAAC,aAAa,CAAC;CAkB1B"}
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CheckoutConfigurator = void 0;
4
+ const errors_1 = require("./models/errors");
5
+ const checkout_event_bus_1 = require("./events/checkout-event-bus");
6
+ /**
7
+ * Main entry point for awesome-node-checkout.
8
+ *
9
+ * Usage (framework-agnostic):
10
+ * ```typescript
11
+ * const checkout = new CheckoutConfigurator();
12
+ * checkout
13
+ * .registerProvider(new PayPalProvider({ clientId, clientSecret }))
14
+ * .registerProvider(new NexiProvider({ merchantId, macKey }))
15
+ * .registerProvider(new SatispayProvider({ keyId, privateKey }));
16
+ *
17
+ * // Use directly in any framework
18
+ * const result = await checkout.createPayment('paypal', request);
19
+ * ```
20
+ *
21
+ * Usage with Express adapter:
22
+ * ```typescript
23
+ * import { createCheckoutRouter } from 'awesome-node-checkout/express';
24
+ * app.use('/checkout', createCheckoutRouter(checkout));
25
+ * ```
26
+ */
27
+ class CheckoutConfigurator {
28
+ constructor(config = {}) {
29
+ this.config = config;
30
+ this.providers = new Map();
31
+ /** Event bus — subscribe to payment lifecycle events */
32
+ this.events = new checkout_event_bus_1.CheckoutEventBus();
33
+ }
34
+ /** Emits an event only when `config.emitEvents` is not explicitly `false`. */
35
+ async emit(event, data) {
36
+ if (this.config.emitEvents !== false) {
37
+ await this.events.emit(event, data);
38
+ }
39
+ }
40
+ /**
41
+ * Register a payment provider. Chainable.
42
+ * @throws CheckoutError if a provider with the same name is already registered.
43
+ */
44
+ registerProvider(provider) {
45
+ const key = provider.name.toLowerCase();
46
+ if (this.providers.has(key)) {
47
+ throw new errors_1.CheckoutError(`Provider '${provider.name}' is already registered`, 'PROVIDER_ALREADY_REGISTERED', provider.name);
48
+ }
49
+ this.providers.set(key, provider);
50
+ return this;
51
+ }
52
+ /**
53
+ * Retrieve a registered provider by name.
54
+ * @throws CheckoutError if the provider is not found.
55
+ */
56
+ getProvider(name) {
57
+ const provider = this.providers.get(name.toLowerCase());
58
+ if (!provider) {
59
+ throw new errors_1.CheckoutError(`Payment provider '${name}' not found. Did you call registerProvider()?`, 'PROVIDER_NOT_FOUND', name);
60
+ }
61
+ return provider;
62
+ }
63
+ /** Returns the names of all registered providers */
64
+ getRegisteredProviders() {
65
+ return Array.from(this.providers.keys());
66
+ }
67
+ /** Create a new payment via the specified provider */
68
+ async createPayment(providerName, request) {
69
+ const provider = this.getProvider(providerName);
70
+ const result = await provider.createPayment(request);
71
+ await this.emit(result.success ? 'payment.created' : 'payment.failed', {
72
+ provider: providerName,
73
+ paymentId: result.paymentId,
74
+ orderId: request.orderId,
75
+ status: result.status,
76
+ error: result.error,
77
+ });
78
+ return result;
79
+ }
80
+ /** Execute/capture a previously created payment */
81
+ async executePayment(providerName, paymentId, data) {
82
+ const provider = this.getProvider(providerName);
83
+ const result = await provider.executePayment(paymentId, data);
84
+ await this.emit(result.success ? 'payment.completed' : 'payment.failed', {
85
+ provider: providerName,
86
+ paymentId,
87
+ status: result.status,
88
+ error: result.error,
89
+ });
90
+ return result;
91
+ }
92
+ /** Retrieve the current status and details of a payment */
93
+ async getPaymentDetails(providerName, paymentId) {
94
+ const provider = this.getProvider(providerName);
95
+ return provider.getPaymentDetails(paymentId);
96
+ }
97
+ /** Issue a full or partial refund */
98
+ async refundPayment(providerName, paymentId, amount) {
99
+ const provider = this.getProvider(providerName);
100
+ const result = await provider.refundPayment(paymentId, amount);
101
+ await this.emit('payment.refunded', {
102
+ provider: providerName,
103
+ paymentId,
104
+ status: result.status,
105
+ error: result.error,
106
+ });
107
+ return result;
108
+ }
109
+ /**
110
+ * Handle an incoming webhook from the provider.
111
+ * @throws CheckoutError if the provider does not support webhooks.
112
+ */
113
+ async handleWebhook(providerName, body, headers) {
114
+ const provider = this.getProvider(providerName);
115
+ if (!provider.handleWebhook) {
116
+ throw new errors_1.CheckoutError(`Provider '${providerName}' does not support webhook handling`, 'WEBHOOK_NOT_SUPPORTED', providerName);
117
+ }
118
+ const result = await provider.handleWebhook(body, headers);
119
+ await this.emit('webhook.received', {
120
+ provider: providerName,
121
+ paymentId: result.paymentId,
122
+ status: result.status,
123
+ error: result.error,
124
+ data: body,
125
+ });
126
+ return result;
127
+ }
128
+ /**
129
+ * Handle the redirect callback from the provider (query params).
130
+ * @throws CheckoutError if the provider does not support redirect handling.
131
+ */
132
+ async handleRedirect(providerName, query) {
133
+ const provider = this.getProvider(providerName);
134
+ if (!provider.handleRedirect) {
135
+ throw new errors_1.CheckoutError(`Provider '${providerName}' does not support redirect handling`, 'REDIRECT_NOT_SUPPORTED', providerName);
136
+ }
137
+ const result = await provider.handleRedirect(query);
138
+ await this.emit(result.success ? 'payment.completed' : 'payment.failed', {
139
+ provider: providerName,
140
+ paymentId: result.paymentId,
141
+ status: result.status,
142
+ error: result.error,
143
+ });
144
+ return result;
145
+ }
146
+ }
147
+ exports.CheckoutConfigurator = CheckoutConfigurator;
148
+ //# sourceMappingURL=checkout-configurator.js.map