@mostajs/payment 0.1.0 → 0.3.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 (47) hide show
  1. package/dist/core/payment-engine.d.ts +26 -0
  2. package/dist/core/payment-engine.d.ts.map +1 -0
  3. package/dist/core/payment-engine.js +57 -0
  4. package/dist/core/payment-engine.js.map +1 -0
  5. package/dist/core/provider.interface.d.ts +101 -0
  6. package/dist/core/provider.interface.d.ts.map +1 -0
  7. package/dist/core/provider.interface.js +4 -0
  8. package/dist/core/provider.interface.js.map +1 -0
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/lib/module-info.js +1 -1
  13. package/dist/lib/stripe.d.ts +37 -0
  14. package/dist/lib/stripe.d.ts.map +1 -1
  15. package/dist/lib/stripe.js +53 -1
  16. package/dist/lib/stripe.js.map +1 -1
  17. package/dist/providers/chargily.provider.d.ts +30 -0
  18. package/dist/providers/chargily.provider.d.ts.map +1 -0
  19. package/dist/providers/chargily.provider.js +112 -0
  20. package/dist/providers/chargily.provider.js.map +1 -0
  21. package/dist/providers/manual.provider.d.ts +20 -0
  22. package/dist/providers/manual.provider.d.ts.map +1 -0
  23. package/dist/providers/manual.provider.js +26 -0
  24. package/dist/providers/manual.provider.js.map +1 -0
  25. package/dist/providers/paypal.provider.d.ts +44 -0
  26. package/dist/providers/paypal.provider.d.ts.map +1 -0
  27. package/dist/providers/paypal.provider.js +160 -0
  28. package/dist/providers/paypal.provider.js.map +1 -0
  29. package/dist/providers/satim.provider.d.ts +38 -0
  30. package/dist/providers/satim.provider.d.ts.map +1 -0
  31. package/dist/providers/satim.provider.js +107 -0
  32. package/dist/providers/satim.provider.js.map +1 -0
  33. package/dist/providers/stripe.provider.d.ts +36 -0
  34. package/dist/providers/stripe.provider.d.ts.map +1 -0
  35. package/dist/providers/stripe.provider.js +203 -0
  36. package/dist/providers/stripe.provider.js.map +1 -0
  37. package/dist/schemas/payment.schema.d.ts +4 -0
  38. package/dist/schemas/payment.schema.d.ts.map +1 -1
  39. package/dist/schemas/payment.schema.js +20 -0
  40. package/dist/schemas/payment.schema.js.map +1 -1
  41. package/dist/server.d.ts +14 -1
  42. package/dist/server.d.ts.map +1 -1
  43. package/dist/server.js +13 -7
  44. package/dist/server.js.map +1 -1
  45. package/dist/types/index.d.ts +2 -0
  46. package/dist/types/index.d.ts.map +1 -1
  47. package/package.json +13 -6
@@ -0,0 +1,160 @@
1
+ // @mostajs/payment — PayPal REST API v2 provider
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ // Ref: https://developer.paypal.com/docs/api/orders/v2/
4
+ export class PayPalProvider {
5
+ config;
6
+ name = 'paypal';
7
+ supportedCurrencies = ['USD', 'EUR', 'GBP', 'CAD', 'AUD', 'JPY', 'CHF'];
8
+ supportedMethods = ['paypal'];
9
+ baseUrl;
10
+ tokenCache = null;
11
+ constructor(config) {
12
+ this.config = config;
13
+ this.baseUrl = config.testMode
14
+ ? 'https://api-m.sandbox.paypal.com'
15
+ : 'https://api-m.paypal.com';
16
+ }
17
+ async getAccessToken() {
18
+ if (this.tokenCache && Date.now() < this.tokenCache.expiresAt) {
19
+ return this.tokenCache.token;
20
+ }
21
+ const auth = Buffer.from(`${this.config.clientId}:${this.config.secret}`).toString('base64');
22
+ const res = await fetch(`${this.baseUrl}/v1/oauth2/token`, {
23
+ method: 'POST',
24
+ headers: {
25
+ 'Authorization': `Basic ${auth}`,
26
+ 'Content-Type': 'application/x-www-form-urlencoded',
27
+ },
28
+ body: 'grant_type=client_credentials',
29
+ });
30
+ if (!res.ok)
31
+ throw new Error(`[paypal] Token failed: ${res.statusText}`);
32
+ const data = await res.json();
33
+ this.tokenCache = {
34
+ token: data.access_token,
35
+ expiresAt: Date.now() + (data.expires_in - 60) * 1000, // refresh 1 min before expiry
36
+ };
37
+ return data.access_token;
38
+ }
39
+ async api(method, path, body) {
40
+ const token = await this.getAccessToken();
41
+ const res = await fetch(`${this.baseUrl}${path}`, {
42
+ method,
43
+ headers: {
44
+ 'Authorization': `Bearer ${token}`,
45
+ 'Content-Type': 'application/json',
46
+ },
47
+ body: body ? JSON.stringify(body) : undefined,
48
+ });
49
+ if (!res.ok) {
50
+ const err = await res.json().catch(() => ({}));
51
+ throw new Error(`[paypal] ${method} ${path} failed: ${err.message ?? err.error ?? res.statusText}`);
52
+ }
53
+ return res.status === 204 ? null : res.json();
54
+ }
55
+ async createCheckout(params) {
56
+ const currency = (params.currency ?? 'USD').toUpperCase();
57
+ const data = await this.api('POST', '/v2/checkout/orders', {
58
+ intent: 'CAPTURE',
59
+ purchase_units: [{
60
+ reference_id: params.orderId,
61
+ description: params.description,
62
+ amount: {
63
+ currency_code: currency,
64
+ value: params.amount.toFixed(2),
65
+ },
66
+ }],
67
+ application_context: {
68
+ return_url: params.successUrl ?? this.config.returnUrl,
69
+ cancel_url: params.cancelUrl ?? this.config.cancelUrl,
70
+ brand_name: 'OctoNet Cloud',
71
+ landing_page: 'LOGIN',
72
+ user_action: 'PAY_NOW',
73
+ },
74
+ ...(params.metadata ? { metadata: params.metadata } : {}),
75
+ });
76
+ const approveLink = data.links?.find((l) => l.rel === 'approve');
77
+ return { url: approveLink?.href ?? null, sessionId: data.id };
78
+ }
79
+ /**
80
+ * Capture a PayPal order after user approval.
81
+ * Call this when PayPal redirects back to returnUrl with ?token=ORDER_ID
82
+ */
83
+ async captureOrder(orderId) {
84
+ const data = await this.api('POST', `/v2/checkout/orders/${orderId}/capture`, {});
85
+ return { status: data.status, data };
86
+ }
87
+ /**
88
+ * Get order details.
89
+ */
90
+ async getOrder(orderId) {
91
+ return this.api('GET', `/v2/checkout/orders/${orderId}`);
92
+ }
93
+ async createRefund(params) {
94
+ // PayPal refunds work on captures, not orders
95
+ const body = {};
96
+ if (params.amount) {
97
+ body.amount = { value: params.amount.toFixed(2), currency_code: 'USD' };
98
+ }
99
+ if (params.reason)
100
+ body.note_to_payer = params.reason;
101
+ const data = await this.api('POST', `/v2/payments/captures/${params.paymentId}/refund`, body);
102
+ return {
103
+ id: data.id,
104
+ amount: parseFloat(data.amount?.value ?? '0'),
105
+ status: data.status,
106
+ };
107
+ }
108
+ async verifyWebhook(body, signature) {
109
+ // PayPal webhook verification requires calling their API
110
+ // For simplicity, parse the event and validate via API
111
+ const event = JSON.parse(body);
112
+ // In production, verify via POST /v1/notifications/verify-webhook-signature
113
+ // For now, trust the parsed event
114
+ const type = event.event_type === 'CHECKOUT.ORDER.APPROVED' ? 'payment.approved'
115
+ : event.event_type === 'PAYMENT.CAPTURE.COMPLETED' ? 'payment.success'
116
+ : event.event_type === 'PAYMENT.CAPTURE.DENIED' ? 'payment.failed'
117
+ : event.event_type ?? 'unknown';
118
+ return {
119
+ type,
120
+ data: {
121
+ orderId: event.resource?.id,
122
+ status: event.resource?.status,
123
+ amount: event.resource?.amount?.value,
124
+ currency: event.resource?.amount?.currency_code,
125
+ },
126
+ raw: event,
127
+ };
128
+ }
129
+ /**
130
+ * Verify webhook signature via PayPal API (production).
131
+ */
132
+ async verifyWebhookSignature(headers, body) {
133
+ if (!this.config.webhookId)
134
+ return false;
135
+ const data = await this.api('POST', '/v1/notifications/verify-webhook-signature', {
136
+ auth_algo: headers['paypal-auth-algo'],
137
+ cert_url: headers['paypal-cert-url'],
138
+ transmission_id: headers['paypal-transmission-id'],
139
+ transmission_sig: headers['paypal-transmission-sig'],
140
+ transmission_time: headers['paypal-transmission-time'],
141
+ webhook_id: this.config.webhookId,
142
+ webhook_event: JSON.parse(body),
143
+ });
144
+ return data.verification_status === 'SUCCESS';
145
+ }
146
+ }
147
+ /**
148
+ * Create a PayPal provider from environment variables.
149
+ */
150
+ export function createPayPalProvider(config) {
151
+ return new PayPalProvider({
152
+ clientId: config?.clientId ?? process.env.PAYPAL_CLIENT_ID ?? '',
153
+ secret: config?.secret ?? process.env.PAYPAL_SECRET ?? '',
154
+ testMode: config?.testMode ?? process.env.PAYPAL_TEST_MODE !== 'false',
155
+ returnUrl: config?.returnUrl ?? process.env.PAYPAL_RETURN_URL ?? '/payment/success',
156
+ cancelUrl: config?.cancelUrl ?? process.env.PAYPAL_CANCEL_URL ?? '/payment/canceled',
157
+ webhookId: config?.webhookId ?? process.env.PAYPAL_WEBHOOK_ID,
158
+ });
159
+ }
160
+ //# sourceMappingURL=paypal.provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paypal.provider.js","sourceRoot":"","sources":["../../src/providers/paypal.provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { PaymentProvider, CheckoutParams, CheckoutResult, WebhookEvent } from '../core/provider.interface.js';
2
+ export interface SatimConfig {
3
+ merchantId: string;
4
+ password: string;
5
+ testMode?: boolean;
6
+ returnUrl: string;
7
+ failUrl: string;
8
+ /** ISO 4217 currency code, default '012' (DZD) */
9
+ currencyCode?: string;
10
+ }
11
+ export declare class SatimProvider implements PaymentProvider {
12
+ private config;
13
+ readonly name = "satim";
14
+ readonly supportedCurrencies: string[];
15
+ readonly supportedMethods: string[];
16
+ private baseUrl;
17
+ constructor(config: SatimConfig);
18
+ createCheckout(params: CheckoutParams): Promise<CheckoutResult>;
19
+ /**
20
+ * Confirm an order after redirect callback.
21
+ * Call this when Satim redirects back to returnUrl.
22
+ */
23
+ confirmOrder(orderId: string): Promise<{
24
+ paid: boolean;
25
+ actionCode: string;
26
+ errorMessage?: string;
27
+ }>;
28
+ /**
29
+ * Get order status.
30
+ */
31
+ getOrderStatus(orderId: string): Promise<Record<string, unknown>>;
32
+ verifyWebhook(body: string, _signature: string): Promise<WebhookEvent>;
33
+ }
34
+ /**
35
+ * Create a Satim provider from environment variables.
36
+ */
37
+ export declare function createSatimProvider(config?: Partial<SatimConfig>): SatimProvider;
38
+ //# sourceMappingURL=satim.provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"satim.provider.d.ts","sourceRoot":"","sources":["../../src/providers/satim.provider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAA;AAElH,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,qBAAa,aAAc,YAAW,eAAe;IAOvC,OAAO,CAAC,MAAM;IAN1B,QAAQ,CAAC,IAAI,WAAU;IACvB,QAAQ,CAAC,mBAAmB,WAAU;IACtC,QAAQ,CAAC,gBAAgB,WAAU;IAEnC,OAAO,CAAC,OAAO,CAAQ;gBAEH,MAAM,EAAE,WAAW;IAMjC,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IA6BrE;;;OAGG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAsB1G;;OAEG;IACG,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAiBjE,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAgB7E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,aAAa,CAQhF"}
@@ -0,0 +1,107 @@
1
+ // @mostajs/payment — Satim/GIE Monetique provider (CIB — Algerie)
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ // Ref: https://test.satim.dz/payment/rest/ (sandbox)
4
+ export class SatimProvider {
5
+ config;
6
+ name = 'satim';
7
+ supportedCurrencies = ['DZD'];
8
+ supportedMethods = ['cib'];
9
+ baseUrl;
10
+ constructor(config) {
11
+ this.config = config;
12
+ this.baseUrl = config.testMode
13
+ ? 'https://test.satim.dz/payment/rest'
14
+ : 'https://cib.satim.dz/payment/rest';
15
+ }
16
+ async createCheckout(params) {
17
+ const body = new URLSearchParams({
18
+ orderNumber: params.orderId,
19
+ amount: String(Math.round(params.amount * 100)), // centimes DZD
20
+ currency: this.config.currencyCode ?? '012', // ISO 4217 DZD
21
+ returnUrl: params.successUrl ?? this.config.returnUrl,
22
+ failUrl: params.cancelUrl ?? this.config.failUrl,
23
+ userName: this.config.merchantId,
24
+ password: this.config.password,
25
+ language: 'FR',
26
+ });
27
+ if (params.description)
28
+ body.set('description', params.description);
29
+ const res = await fetch(`${this.baseUrl}/register.do`, {
30
+ method: 'POST',
31
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
32
+ body,
33
+ });
34
+ const data = await res.json();
35
+ if (data.errorCode && data.errorCode !== '0') {
36
+ throw new Error(`[satim] ${data.errorMessage ?? 'Registration failed'} (code: ${data.errorCode})`);
37
+ }
38
+ return { url: data.formUrl, sessionId: data.orderId };
39
+ }
40
+ /**
41
+ * Confirm an order after redirect callback.
42
+ * Call this when Satim redirects back to returnUrl.
43
+ */
44
+ async confirmOrder(orderId) {
45
+ const body = new URLSearchParams({
46
+ orderId,
47
+ userName: this.config.merchantId,
48
+ password: this.config.password,
49
+ language: 'FR',
50
+ });
51
+ const res = await fetch(`${this.baseUrl}/confirmOrder.do`, {
52
+ method: 'POST',
53
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
54
+ body,
55
+ });
56
+ const data = await res.json();
57
+ return {
58
+ paid: data.actionCode === 0 || data.actionCode === '0',
59
+ actionCode: String(data.actionCode),
60
+ errorMessage: data.ErrorMessage ?? data.errorMessage,
61
+ };
62
+ }
63
+ /**
64
+ * Get order status.
65
+ */
66
+ async getOrderStatus(orderId) {
67
+ const body = new URLSearchParams({
68
+ orderId,
69
+ userName: this.config.merchantId,
70
+ password: this.config.password,
71
+ language: 'FR',
72
+ });
73
+ const res = await fetch(`${this.baseUrl}/getOrderStatus.do`, {
74
+ method: 'POST',
75
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
76
+ body,
77
+ });
78
+ return res.json();
79
+ }
80
+ async verifyWebhook(body, _signature) {
81
+ // Satim uses redirect-based callbacks, not webhooks
82
+ // Parse the callback params
83
+ const params = new URLSearchParams(body);
84
+ const orderId = params.get('orderId') ?? '';
85
+ if (orderId) {
86
+ const status = await this.confirmOrder(orderId);
87
+ return {
88
+ type: status.paid ? 'payment.success' : 'payment.failed',
89
+ data: { orderId, ...status },
90
+ };
91
+ }
92
+ return { type: 'unknown', data: {} };
93
+ }
94
+ }
95
+ /**
96
+ * Create a Satim provider from environment variables.
97
+ */
98
+ export function createSatimProvider(config) {
99
+ return new SatimProvider({
100
+ merchantId: config?.merchantId ?? process.env.SATIM_MERCHANT_ID ?? '',
101
+ password: config?.password ?? process.env.SATIM_PASSWORD ?? '',
102
+ testMode: config?.testMode ?? process.env.SATIM_TEST_MODE === 'true',
103
+ returnUrl: config?.returnUrl ?? process.env.SATIM_RETURN_URL ?? '/payment/callback',
104
+ failUrl: config?.failUrl ?? process.env.SATIM_FAIL_URL ?? '/payment/failed',
105
+ });
106
+ }
107
+ //# sourceMappingURL=satim.provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"satim.provider.js","sourceRoot":"","sources":["../../src/providers/satim.provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import Stripe from 'stripe';
2
+ import type { PaymentProvider, CheckoutParams, CheckoutResult, CustomerParams, SubscriptionParams, SubscriptionResult, RefundParams, RefundResult, InvoiceResult, WebhookEvent } from '../core/provider.interface.js';
3
+ export interface StripeConfig {
4
+ secretKey: string;
5
+ webhookSecret?: string;
6
+ }
7
+ export declare class StripeProvider implements PaymentProvider {
8
+ private config;
9
+ readonly name = "stripe";
10
+ readonly supportedCurrencies: string[];
11
+ readonly supportedMethods: string[];
12
+ stripe: Stripe;
13
+ constructor(config: StripeConfig);
14
+ createCheckout(params: CheckoutParams): Promise<CheckoutResult>;
15
+ createCustomer(params: CustomerParams): Promise<string>;
16
+ getCustomer(customerId: string): Promise<Record<string, unknown>>;
17
+ updateCustomer(customerId: string, params: Partial<CustomerParams>): Promise<Record<string, unknown>>;
18
+ createSubscription(params: SubscriptionParams): Promise<SubscriptionResult>;
19
+ getSubscription(subscriptionId: string): Promise<SubscriptionResult>;
20
+ cancelSubscription(subscriptionId: string, immediate?: boolean): Promise<void>;
21
+ changeSubscription(subscriptionId: string, newPriceId: string): Promise<SubscriptionResult>;
22
+ pauseSubscription(subscriptionId: string): Promise<void>;
23
+ resumeSubscription(subscriptionId: string): Promise<void>;
24
+ createRefund(params: RefundParams): Promise<RefundResult>;
25
+ listInvoices(customerId: string, limit?: number): Promise<InvoiceResult[]>;
26
+ getUpcomingInvoice(customerId: string): Promise<InvoiceResult | null>;
27
+ createPortal(customerId: string, returnUrl: string): Promise<{
28
+ url: string;
29
+ }>;
30
+ verifyWebhook(body: string, signature: string): Promise<WebhookEvent>;
31
+ }
32
+ /**
33
+ * Create a Stripe provider from environment variables.
34
+ */
35
+ export declare function createStripeProvider(config?: Partial<StripeConfig>): StripeProvider;
36
+ //# sourceMappingURL=stripe.provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripe.provider.d.ts","sourceRoot":"","sources":["../../src/providers/stripe.provider.ts"],"names":[],"mappings":"AAGA,OAAO,MAAM,MAAM,QAAQ,CAAA;AAC3B,OAAO,KAAK,EACV,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAC/D,kBAAkB,EAAE,kBAAkB,EAAE,YAAY,EAAE,YAAY,EAClE,aAAa,EAAE,YAAY,EAC5B,MAAM,+BAA+B,CAAA;AAEtC,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,qBAAa,cAAe,YAAW,eAAe;IAOxC,OAAO,CAAC,MAAM;IAN1B,QAAQ,CAAC,IAAI,YAAW;IACxB,QAAQ,CAAC,mBAAmB,WAAQ;IACpC,QAAQ,CAAC,gBAAgB,WAAW;IAE7B,MAAM,EAAE,MAAM,CAAA;gBAED,MAAM,EAAE,YAAY;IAOlC,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAsC/D,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IASvD,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAKjE,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAWrG,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAe3E,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAUpE,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9E,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAa3F,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxD,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQzD,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAezD,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAY1E,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAgBrE,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAU7E,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAmB5E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,cAAc,CAKnF"}
@@ -0,0 +1,203 @@
1
+ // @mostajs/payment — Stripe provider (refactored from lib/stripe.ts)
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ import Stripe from 'stripe';
4
+ export class StripeProvider {
5
+ config;
6
+ name = 'stripe';
7
+ supportedCurrencies = ['*']; // all currencies
8
+ supportedMethods = ['card'];
9
+ stripe;
10
+ constructor(config) {
11
+ this.config = config;
12
+ if (!config.secretKey)
13
+ throw new Error('[stripe] secretKey is required');
14
+ this.stripe = new Stripe(config.secretKey);
15
+ }
16
+ // ─── Checkout ─────────────────────────────────
17
+ async createCheckout(params) {
18
+ if (params.priceId && params.customerId) {
19
+ // Subscription billing
20
+ const sessionParams = {
21
+ customer: params.customerId,
22
+ mode: 'subscription',
23
+ line_items: [{ price: params.priceId, quantity: 1 }],
24
+ success_url: params.successUrl,
25
+ cancel_url: params.cancelUrl,
26
+ metadata: params.metadata,
27
+ };
28
+ if (params.trialDays)
29
+ sessionParams.subscription_data = { trial_period_days: params.trialDays };
30
+ const session = await this.stripe.checkout.sessions.create(sessionParams);
31
+ return { url: session.url, sessionId: session.id };
32
+ }
33
+ // One-time payment
34
+ const currency = (params.currency ?? 'usd').toLowerCase();
35
+ const session = await this.stripe.checkout.sessions.create({
36
+ payment_method_types: ['card'],
37
+ line_items: [{
38
+ price_data: {
39
+ currency,
40
+ product_data: { name: params.description ?? `Order ${params.orderId}` },
41
+ unit_amount: Math.round(params.amount * 100),
42
+ },
43
+ quantity: 1,
44
+ }],
45
+ mode: 'payment',
46
+ success_url: params.successUrl,
47
+ cancel_url: params.cancelUrl,
48
+ metadata: { orderId: params.orderId, ...params.metadata },
49
+ });
50
+ return { url: session.url, sessionId: session.id };
51
+ }
52
+ // ─── Customers ────────────────────────────────
53
+ async createCustomer(params) {
54
+ const customer = await this.stripe.customers.create({
55
+ email: params.email,
56
+ name: params.name,
57
+ metadata: params.metadata,
58
+ });
59
+ return customer.id;
60
+ }
61
+ async getCustomer(customerId) {
62
+ const c = await this.stripe.customers.retrieve(customerId);
63
+ return c;
64
+ }
65
+ async updateCustomer(customerId, params) {
66
+ const c = await this.stripe.customers.update(customerId, {
67
+ ...(params.name ? { name: params.name } : {}),
68
+ ...(params.email ? { email: params.email } : {}),
69
+ ...(params.metadata ? { metadata: params.metadata } : {}),
70
+ });
71
+ return c;
72
+ }
73
+ // ─── Subscriptions ────────────────────────────
74
+ async createSubscription(params) {
75
+ const sub = await this.stripe.subscriptions.create({
76
+ customer: params.customerId,
77
+ items: [{ price: params.priceId }],
78
+ trial_period_days: params.trialDays,
79
+ metadata: params.metadata,
80
+ });
81
+ return {
82
+ id: sub.id,
83
+ status: sub.status,
84
+ customerId: sub.customer,
85
+ currentPeriodEnd: new Date(sub.current_period_end * 1000).toISOString(),
86
+ };
87
+ }
88
+ async getSubscription(subscriptionId) {
89
+ const sub = await this.stripe.subscriptions.retrieve(subscriptionId);
90
+ return {
91
+ id: sub.id,
92
+ status: sub.status,
93
+ customerId: sub.customer,
94
+ currentPeriodEnd: new Date(sub.current_period_end * 1000).toISOString(),
95
+ };
96
+ }
97
+ async cancelSubscription(subscriptionId, immediate) {
98
+ if (immediate) {
99
+ await this.stripe.subscriptions.cancel(subscriptionId);
100
+ }
101
+ else {
102
+ await this.stripe.subscriptions.update(subscriptionId, { cancel_at_period_end: true });
103
+ }
104
+ }
105
+ async changeSubscription(subscriptionId, newPriceId) {
106
+ const sub = await this.stripe.subscriptions.retrieve(subscriptionId);
107
+ const updated = await this.stripe.subscriptions.update(subscriptionId, {
108
+ items: [{ id: sub.items.data[0].id, price: newPriceId }],
109
+ proration_behavior: 'always_invoice',
110
+ });
111
+ return {
112
+ id: updated.id,
113
+ status: updated.status,
114
+ customerId: updated.customer,
115
+ };
116
+ }
117
+ async pauseSubscription(subscriptionId) {
118
+ await this.stripe.subscriptions.update(subscriptionId, {
119
+ pause_collection: { behavior: 'void' },
120
+ });
121
+ }
122
+ async resumeSubscription(subscriptionId) {
123
+ await this.stripe.subscriptions.update(subscriptionId, {
124
+ pause_collection: '',
125
+ });
126
+ }
127
+ // ─── Refunds ──────────────────────────────────
128
+ async createRefund(params) {
129
+ const refund = await this.stripe.refunds.create({
130
+ payment_intent: params.paymentId,
131
+ ...(params.amount ? { amount: Math.round(params.amount * 100) } : {}),
132
+ ...(params.metadata ? { metadata: params.metadata } : {}),
133
+ });
134
+ return {
135
+ id: refund.id,
136
+ amount: (refund.amount ?? 0) / 100,
137
+ status: refund.status ?? 'pending',
138
+ };
139
+ }
140
+ // ─── Invoices ─────────────────────────────────
141
+ async listInvoices(customerId, limit) {
142
+ const invoices = await this.stripe.invoices.list({ customer: customerId, limit: limit ?? 10 });
143
+ return invoices.data.map(inv => ({
144
+ id: inv.id,
145
+ amount: (inv.amount_paid ?? 0) / 100,
146
+ currency: inv.currency ?? 'usd',
147
+ status: inv.status ?? 'draft',
148
+ paidAt: inv.status_transitions?.paid_at ? new Date(inv.status_transitions.paid_at * 1000).toISOString() : undefined,
149
+ pdfUrl: inv.invoice_pdf ?? undefined,
150
+ }));
151
+ }
152
+ async getUpcomingInvoice(customerId) {
153
+ try {
154
+ const inv = await this.stripe.invoices.retrieveUpcoming({ customer: customerId });
155
+ return {
156
+ id: 'upcoming',
157
+ amount: (inv.amount_due ?? 0) / 100,
158
+ currency: inv.currency ?? 'usd',
159
+ status: 'upcoming',
160
+ };
161
+ }
162
+ catch {
163
+ return null;
164
+ }
165
+ }
166
+ // ─── Portal ───────────────────────────────────
167
+ async createPortal(customerId, returnUrl) {
168
+ const session = await this.stripe.billingPortal.sessions.create({
169
+ customer: customerId,
170
+ return_url: returnUrl,
171
+ });
172
+ return { url: session.url };
173
+ }
174
+ // ─── Webhooks ─────────────────────────────────
175
+ async verifyWebhook(body, signature) {
176
+ if (!this.config.webhookSecret)
177
+ throw new Error('[stripe] webhookSecret required for webhook verification');
178
+ const event = this.stripe.webhooks.constructEvent(body, signature, this.config.webhookSecret);
179
+ const typeMap = {
180
+ 'checkout.session.completed': 'payment.success',
181
+ 'customer.subscription.created': 'subscription.created',
182
+ 'customer.subscription.updated': 'subscription.updated',
183
+ 'customer.subscription.deleted': 'subscription.deleted',
184
+ 'invoice.paid': 'invoice.paid',
185
+ 'invoice.payment_failed': 'invoice.failed',
186
+ };
187
+ return {
188
+ type: typeMap[event.type] ?? event.type,
189
+ data: event.data.object,
190
+ raw: event,
191
+ };
192
+ }
193
+ }
194
+ /**
195
+ * Create a Stripe provider from environment variables.
196
+ */
197
+ export function createStripeProvider(config) {
198
+ return new StripeProvider({
199
+ secretKey: config?.secretKey ?? process.env.STRIPE_SECRET_KEY ?? '',
200
+ webhookSecret: config?.webhookSecret ?? process.env.STRIPE_WEBHOOK_SECRET,
201
+ });
202
+ }
203
+ //# sourceMappingURL=stripe.provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripe.provider.js","sourceRoot":"","sources":["../../src/providers/stripe.provider.ts"],"names":[],"mappings":"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"}
@@ -5,11 +5,15 @@ import type { EntitySchema } from '@mostajs/orm';
5
5
  * @param options.currency - Default currency (default: 'USD')
6
6
  * @param options.relationTarget - Related entity name (e.g. 'Reservation', 'Order')
7
7
  * @param options.relationRequired - Whether the relation is required
8
+ * @param options.subscriptionTarget - Optional relation to Subscription entity
9
+ * @param options.invoiceTarget - Optional relation to Invoice entity
8
10
  */
9
11
  export declare function createPaymentSchema(options?: {
10
12
  currency?: string;
11
13
  relationTarget?: string;
12
14
  relationRequired?: boolean;
15
+ subscriptionTarget?: string;
16
+ invoiceTarget?: string;
13
17
  }): EntitySchema;
14
18
  /** Default Payment schema (no relation, USD currency) */
15
19
  export declare const PaymentSchema: EntitySchema;
@@ -1 +1 @@
1
- {"version":3,"file":"payment.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/payment.schema.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAEhD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,GAAG,YAAY,CAiCf;AAED,yDAAyD;AACzD,eAAO,MAAM,aAAa,cAAwB,CAAA"}
1
+ {"version":3,"file":"payment.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/payment.schema.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAEhD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,GAAG,YAAY,CAqDf;AAED,yDAAyD;AACzD,eAAO,MAAM,aAAa,cAAwB,CAAA"}
@@ -4,6 +4,8 @@
4
4
  * @param options.currency - Default currency (default: 'USD')
5
5
  * @param options.relationTarget - Related entity name (e.g. 'Reservation', 'Order')
6
6
  * @param options.relationRequired - Whether the relation is required
7
+ * @param options.subscriptionTarget - Optional relation to Subscription entity
8
+ * @param options.invoiceTarget - Optional relation to Invoice entity
7
9
  */
8
10
  export function createPaymentSchema(options) {
9
11
  const schema = {
@@ -32,6 +34,24 @@ export function createPaymentSchema(options) {
32
34
  };
33
35
  schema.indexes.push({ fields: { [relKey]: 'asc' } });
34
36
  }
37
+ if (options?.subscriptionTarget) {
38
+ const relKey = options.subscriptionTarget.toLowerCase();
39
+ schema.relations[relKey] = {
40
+ target: options.subscriptionTarget,
41
+ type: 'many-to-one',
42
+ required: false,
43
+ };
44
+ schema.indexes.push({ fields: { [relKey]: 'asc' } });
45
+ }
46
+ if (options?.invoiceTarget) {
47
+ const relKey = options.invoiceTarget.toLowerCase();
48
+ schema.relations[relKey] = {
49
+ target: options.invoiceTarget,
50
+ type: 'many-to-one',
51
+ required: false,
52
+ };
53
+ schema.indexes.push({ fields: { [relKey]: 'asc' } });
54
+ }
35
55
  return schema;
36
56
  }
37
57
  /** Default Payment schema (no relation, USD currency) */