@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.
- package/dist/core/payment-engine.d.ts +26 -0
- package/dist/core/payment-engine.d.ts.map +1 -0
- package/dist/core/payment-engine.js +57 -0
- package/dist/core/payment-engine.js.map +1 -0
- package/dist/core/provider.interface.d.ts +101 -0
- package/dist/core/provider.interface.d.ts.map +1 -0
- package/dist/core/provider.interface.js +4 -0
- package/dist/core/provider.interface.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/module-info.js +1 -1
- package/dist/lib/stripe.d.ts +37 -0
- package/dist/lib/stripe.d.ts.map +1 -1
- package/dist/lib/stripe.js +53 -1
- package/dist/lib/stripe.js.map +1 -1
- package/dist/providers/chargily.provider.d.ts +30 -0
- package/dist/providers/chargily.provider.d.ts.map +1 -0
- package/dist/providers/chargily.provider.js +112 -0
- package/dist/providers/chargily.provider.js.map +1 -0
- package/dist/providers/manual.provider.d.ts +20 -0
- package/dist/providers/manual.provider.d.ts.map +1 -0
- package/dist/providers/manual.provider.js +26 -0
- package/dist/providers/manual.provider.js.map +1 -0
- package/dist/providers/paypal.provider.d.ts +44 -0
- package/dist/providers/paypal.provider.d.ts.map +1 -0
- package/dist/providers/paypal.provider.js +160 -0
- package/dist/providers/paypal.provider.js.map +1 -0
- package/dist/providers/satim.provider.d.ts +38 -0
- package/dist/providers/satim.provider.d.ts.map +1 -0
- package/dist/providers/satim.provider.js +107 -0
- package/dist/providers/satim.provider.js.map +1 -0
- package/dist/providers/stripe.provider.d.ts +36 -0
- package/dist/providers/stripe.provider.d.ts.map +1 -0
- package/dist/providers/stripe.provider.js +203 -0
- package/dist/providers/stripe.provider.js.map +1 -0
- package/dist/schemas/payment.schema.d.ts +4 -0
- package/dist/schemas/payment.schema.d.ts.map +1 -1
- package/dist/schemas/payment.schema.js +20 -0
- package/dist/schemas/payment.schema.js.map +1 -1
- package/dist/server.d.ts +14 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +13 -7
- package/dist/server.js.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- 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
|
|
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) */
|