@molecule/api-payments-stripe 1.0.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/LICENSE +115 -0
- package/dist/bondAdapter.d.ts +18 -0
- package/dist/bondAdapter.d.ts.map +1 -0
- package/dist/bondAdapter.js +406 -0
- package/dist/bondAdapter.js.map +1 -0
- package/dist/browser-guard.d.ts +2 -0
- package/dist/browser-guard.d.ts.map +1 -0
- package/dist/browser-guard.js +19 -0
- package/dist/browser-guard.js.map +1 -0
- package/dist/connect.d.ts +252 -0
- package/dist/connect.d.ts.map +1 -0
- package/dist/connect.js +229 -0
- package/dist/connect.js.map +1 -0
- package/dist/index.d.ts +68 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/dist/provider.d.ts +204 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +413 -0
- package/dist/provider.js.map +1 -0
- package/dist/secrets.d.ts +16 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +32 -0
- package/dist/secrets.js.map +1 -0
- package/dist/types.d.ts +78 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stripe Connect support for the Stripe payment provider.
|
|
3
|
+
*
|
|
4
|
+
* Adds split-payment / payouts helpers on top of the existing
|
|
5
|
+
* `@molecule/api-payments-stripe` bond surface so multi-vendor / two-sided
|
|
6
|
+
* marketplace apps (course-marketplace, food-delivery, multi-vendor-marketplace,
|
|
7
|
+
* rental-marketplace, tutoring-marketplace, venue-booking, crowdfunding,
|
|
8
|
+
* pet-care, telemedicine, etc.) can:
|
|
9
|
+
* - Onboard sellers / drivers / providers (`createConnectedAccount` + `createAccountLink`).
|
|
10
|
+
* - Move funds into connected accounts (`createTransfer`).
|
|
11
|
+
* - Trigger payouts (`createPayout`).
|
|
12
|
+
* - Inspect onboarding/eligibility status (`getAccountStatus`).
|
|
13
|
+
* - Handle Connect-specific webhooks (`processConnectWebhook`).
|
|
14
|
+
*
|
|
15
|
+
* @see https://stripe.com/docs/connect
|
|
16
|
+
*
|
|
17
|
+
* @module
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Connected account type.
|
|
21
|
+
*
|
|
22
|
+
* Stripe distinguishes three account types with different
|
|
23
|
+
* onboarding / dashboard responsibilities. See
|
|
24
|
+
* https://stripe.com/docs/connect/accounts.
|
|
25
|
+
*/
|
|
26
|
+
export type ConnectedAccountType = 'standard' | 'express' | 'custom';
|
|
27
|
+
/**
|
|
28
|
+
* Subset of Stripe `business_profile` fields commonly set during marketplace
|
|
29
|
+
* onboarding.
|
|
30
|
+
*/
|
|
31
|
+
export interface ConnectedAccountBusinessProfile {
|
|
32
|
+
name?: string;
|
|
33
|
+
url?: string;
|
|
34
|
+
productDescription?: string;
|
|
35
|
+
supportEmail?: string;
|
|
36
|
+
supportPhone?: string;
|
|
37
|
+
mcc?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Parameters for creating a connected account.
|
|
41
|
+
*/
|
|
42
|
+
export interface CreateConnectedAccountParams {
|
|
43
|
+
/** Stripe account type — `standard`, `express`, or `custom`. */
|
|
44
|
+
type: ConnectedAccountType;
|
|
45
|
+
/** Two-letter ISO country code for the account holder (e.g. `US`, `GB`). */
|
|
46
|
+
country: string;
|
|
47
|
+
/** Email address of the account holder. */
|
|
48
|
+
email: string;
|
|
49
|
+
/** Optional business profile fields (display name, website, MCC, etc.). */
|
|
50
|
+
businessProfile?: ConnectedAccountBusinessProfile;
|
|
51
|
+
/** Optional metadata to attach to the connected account. */
|
|
52
|
+
metadata?: Record<string, string>;
|
|
53
|
+
/** Optional idempotency key for safe retries. */
|
|
54
|
+
idempotencyKey?: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Result of creating a connected account.
|
|
58
|
+
*/
|
|
59
|
+
export interface CreateConnectedAccountResult {
|
|
60
|
+
/** Stripe connected account ID (`acct_...`). */
|
|
61
|
+
id: string;
|
|
62
|
+
/** Optional onboarding URL (only present when an account link is created in the same flow). */
|
|
63
|
+
accountLinkUrl?: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Account-link types — onboarding (first-time) vs update (returning).
|
|
67
|
+
*/
|
|
68
|
+
export type AccountLinkType = 'account_onboarding' | 'account_update';
|
|
69
|
+
/**
|
|
70
|
+
* Parameters for creating an account link.
|
|
71
|
+
*/
|
|
72
|
+
export interface CreateAccountLinkParams {
|
|
73
|
+
/** Stripe connected account ID (`acct_...`). */
|
|
74
|
+
accountId: string;
|
|
75
|
+
/** URL Stripe redirects the user back to after onboarding completes. */
|
|
76
|
+
returnUrl: string;
|
|
77
|
+
/** URL Stripe redirects the user to if the link expires before completion. */
|
|
78
|
+
refreshUrl: string;
|
|
79
|
+
/** Whether this is a first-time onboarding link or an update link. */
|
|
80
|
+
type: AccountLinkType;
|
|
81
|
+
/** Optional idempotency key for safe retries. */
|
|
82
|
+
idempotencyKey?: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Result of creating an account link.
|
|
86
|
+
*/
|
|
87
|
+
export interface CreateAccountLinkResult {
|
|
88
|
+
/** Hosted onboarding URL the connected account holder should open. */
|
|
89
|
+
url: string;
|
|
90
|
+
/** Unix timestamp (seconds) when the link expires. */
|
|
91
|
+
expiresAt: number;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Parameters for creating a transfer to a connected account.
|
|
95
|
+
*/
|
|
96
|
+
export interface CreateTransferParams {
|
|
97
|
+
/** Amount in the smallest currency unit (e.g. cents for USD). */
|
|
98
|
+
amount: number;
|
|
99
|
+
/** Three-letter ISO currency code, lowercase (e.g. `usd`). */
|
|
100
|
+
currency: string;
|
|
101
|
+
/** Destination connected account ID (`acct_...`). */
|
|
102
|
+
destination: string;
|
|
103
|
+
/** Optional source charge to attach the transfer to (for separate-charges-and-transfers flow). */
|
|
104
|
+
sourceTransaction?: string;
|
|
105
|
+
/** Optional transfer group string (groups related transfers/charges together). */
|
|
106
|
+
transferGroup?: string;
|
|
107
|
+
/** Optional metadata. */
|
|
108
|
+
metadata?: Record<string, string>;
|
|
109
|
+
/** Optional idempotency key for safe retries. */
|
|
110
|
+
idempotencyKey?: string;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Result of creating a transfer.
|
|
114
|
+
*/
|
|
115
|
+
export interface CreateTransferResult {
|
|
116
|
+
/** Stripe transfer ID (`tr_...`). */
|
|
117
|
+
id: string;
|
|
118
|
+
/** Amount transferred (smallest currency unit). */
|
|
119
|
+
amount: number;
|
|
120
|
+
/** Three-letter ISO currency code. */
|
|
121
|
+
currency: string;
|
|
122
|
+
/** Destination connected account ID. */
|
|
123
|
+
destination: string;
|
|
124
|
+
/** Transfer group, if set. */
|
|
125
|
+
transferGroup?: string;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Parameters for creating a payout from a connected account's Stripe balance to its bank account.
|
|
129
|
+
*/
|
|
130
|
+
export interface CreatePayoutParams {
|
|
131
|
+
/** Connected account ID to issue the payout from (`acct_...`). */
|
|
132
|
+
accountId: string;
|
|
133
|
+
/** Amount in the smallest currency unit (e.g. cents for USD). */
|
|
134
|
+
amount: number;
|
|
135
|
+
/** Three-letter ISO currency code, lowercase (e.g. `usd`). */
|
|
136
|
+
currency: string;
|
|
137
|
+
/** Optional payout method — `standard` or `instant`. */
|
|
138
|
+
method?: 'standard' | 'instant';
|
|
139
|
+
/** Optional metadata. */
|
|
140
|
+
metadata?: Record<string, string>;
|
|
141
|
+
/** Optional idempotency key for safe retries. */
|
|
142
|
+
idempotencyKey?: string;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Result of creating a payout.
|
|
146
|
+
*/
|
|
147
|
+
export interface CreatePayoutResult {
|
|
148
|
+
/** Stripe payout ID (`po_...`). */
|
|
149
|
+
id: string;
|
|
150
|
+
/** Amount paid out (smallest currency unit). */
|
|
151
|
+
amount: number;
|
|
152
|
+
/** Three-letter ISO currency code. */
|
|
153
|
+
currency: string;
|
|
154
|
+
/** Payout status (e.g. `pending`, `paid`, `failed`). */
|
|
155
|
+
status: string;
|
|
156
|
+
/** Estimated arrival date (Unix timestamp in seconds). */
|
|
157
|
+
arrivalDate: number;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Connected-account onboarding / payout eligibility status.
|
|
161
|
+
*/
|
|
162
|
+
export interface AccountStatus {
|
|
163
|
+
/** Stripe connected account ID. */
|
|
164
|
+
id: string;
|
|
165
|
+
/** Whether the account can accept charges. */
|
|
166
|
+
chargesEnabled: boolean;
|
|
167
|
+
/** Whether the account can receive payouts. */
|
|
168
|
+
payoutsEnabled: boolean;
|
|
169
|
+
/** Whether there are any currently-due requirements (Stripe is blocked on something). */
|
|
170
|
+
requirementsCurrent: boolean;
|
|
171
|
+
/** Stripe connected-account type (`standard`, `express`, `custom`), if known. */
|
|
172
|
+
type?: ConnectedAccountType;
|
|
173
|
+
/** Currently-due requirement IDs from Stripe (empty when nothing is due). */
|
|
174
|
+
currentlyDue: readonly string[];
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Connect webhook event types this provider knows how to interpret.
|
|
178
|
+
*
|
|
179
|
+
* `unknown` is returned for any other Stripe event so callers can fall
|
|
180
|
+
* through to the standard subscription webhook handler if needed.
|
|
181
|
+
*/
|
|
182
|
+
export type ConnectWebhookEventType = 'account.updated' | 'payout.created' | 'transfer.created' | 'application_fee.refunded' | 'unknown';
|
|
183
|
+
/**
|
|
184
|
+
* Normalized Connect webhook event.
|
|
185
|
+
*
|
|
186
|
+
* Provider-agnostic shape so consumers don't have to import Stripe types
|
|
187
|
+
* to dispatch on event kind.
|
|
188
|
+
*/
|
|
189
|
+
export interface ConnectWebhookEvent {
|
|
190
|
+
/** Recognized Connect event type, or `unknown` for unrelated events. */
|
|
191
|
+
type: ConnectWebhookEventType;
|
|
192
|
+
/** Original Stripe event type string (e.g. `account.updated`). */
|
|
193
|
+
rawType: string;
|
|
194
|
+
/** The ID of the primary resource this event is about (account, payout, transfer, fee). */
|
|
195
|
+
resourceId?: string;
|
|
196
|
+
/** The connected account this event applies to, if Stripe sent one. */
|
|
197
|
+
accountId?: string;
|
|
198
|
+
/** Raw event-data object (plain JSON shape — never the live Stripe object). */
|
|
199
|
+
data: Record<string, unknown>;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Creates a Stripe connected account for a marketplace seller / driver / provider.
|
|
203
|
+
*
|
|
204
|
+
* @param params - Connected-account creation parameters.
|
|
205
|
+
* @returns The new account ID.
|
|
206
|
+
*/
|
|
207
|
+
export declare const createConnectedAccount: (params: CreateConnectedAccountParams) => Promise<CreateConnectedAccountResult>;
|
|
208
|
+
/**
|
|
209
|
+
* Creates a Stripe account link the connected account holder uses to finish
|
|
210
|
+
* onboarding (or to update payout details).
|
|
211
|
+
*
|
|
212
|
+
* @param params - Account-link creation parameters.
|
|
213
|
+
* @returns The hosted onboarding/update URL and its expiry (Unix timestamp, seconds).
|
|
214
|
+
*/
|
|
215
|
+
export declare const createAccountLink: (params: CreateAccountLinkParams) => Promise<CreateAccountLinkResult>;
|
|
216
|
+
/**
|
|
217
|
+
* Transfers funds from the platform balance to a connected account.
|
|
218
|
+
*
|
|
219
|
+
* @param params - Transfer parameters.
|
|
220
|
+
* @returns The created transfer.
|
|
221
|
+
*/
|
|
222
|
+
export declare const createTransfer: (params: CreateTransferParams) => Promise<CreateTransferResult>;
|
|
223
|
+
/**
|
|
224
|
+
* Issues a payout from a connected account's Stripe balance to its bank account.
|
|
225
|
+
*
|
|
226
|
+
* Uses Stripe's `Stripe-Account` header to scope the call to the connected account.
|
|
227
|
+
*
|
|
228
|
+
* @param params - Payout parameters.
|
|
229
|
+
* @returns The created payout.
|
|
230
|
+
*/
|
|
231
|
+
export declare const createPayout: (params: CreatePayoutParams) => Promise<CreatePayoutResult>;
|
|
232
|
+
/**
|
|
233
|
+
* Looks up a connected account's onboarding / payout status.
|
|
234
|
+
*
|
|
235
|
+
* @param accountId - Stripe connected account ID (`acct_...`).
|
|
236
|
+
* @returns Normalized account status.
|
|
237
|
+
*/
|
|
238
|
+
export declare const getAccountStatus: (accountId: string) => Promise<AccountStatus>;
|
|
239
|
+
/**
|
|
240
|
+
* Verifies and normalizes a Stripe Connect webhook event.
|
|
241
|
+
*
|
|
242
|
+
* Reuses the same `STRIPE_WEBHOOK_SECRET` env var as the standard webhook
|
|
243
|
+
* pipeline (and the same signature verification logic) — Connect events
|
|
244
|
+
* arrive on the same webhook endpoint when the platform's webhook is
|
|
245
|
+
* configured to receive Connect events.
|
|
246
|
+
*
|
|
247
|
+
* @param headers - Request headers (looks up `stripe-signature`).
|
|
248
|
+
* @param body - The raw request body (string or Buffer).
|
|
249
|
+
* @returns The verified, normalized Connect webhook event.
|
|
250
|
+
*/
|
|
251
|
+
export declare const processConnectWebhook: (headers: Record<string, string | string[] | undefined>, body: string | Buffer) => ConnectWebhookEvent;
|
|
252
|
+
//# sourceMappingURL=connect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"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"}
|
package/dist/connect.js
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stripe Connect support for the Stripe payment provider.
|
|
3
|
+
*
|
|
4
|
+
* Adds split-payment / payouts helpers on top of the existing
|
|
5
|
+
* `@molecule/api-payments-stripe` bond surface so multi-vendor / two-sided
|
|
6
|
+
* marketplace apps (course-marketplace, food-delivery, multi-vendor-marketplace,
|
|
7
|
+
* rental-marketplace, tutoring-marketplace, venue-booking, crowdfunding,
|
|
8
|
+
* pet-care, telemedicine, etc.) can:
|
|
9
|
+
* - Onboard sellers / drivers / providers (`createConnectedAccount` + `createAccountLink`).
|
|
10
|
+
* - Move funds into connected accounts (`createTransfer`).
|
|
11
|
+
* - Trigger payouts (`createPayout`).
|
|
12
|
+
* - Inspect onboarding/eligibility status (`getAccountStatus`).
|
|
13
|
+
* - Handle Connect-specific webhooks (`processConnectWebhook`).
|
|
14
|
+
*
|
|
15
|
+
* @see https://stripe.com/docs/connect
|
|
16
|
+
*
|
|
17
|
+
* @module
|
|
18
|
+
*/
|
|
19
|
+
import { getLogger } from '@molecule/api-bond';
|
|
20
|
+
import { getClient, verifyWebhookSignature } from './provider.js';
|
|
21
|
+
const logger = getLogger();
|
|
22
|
+
/**
|
|
23
|
+
* Maps the in-bond business-profile shape to Stripe SDK params.
|
|
24
|
+
*
|
|
25
|
+
* @param profile - The optional business profile.
|
|
26
|
+
* @returns A Stripe-compatible business_profile object, or `undefined` if no profile was provided.
|
|
27
|
+
*/
|
|
28
|
+
const toStripeBusinessProfile = (profile) => {
|
|
29
|
+
if (!profile)
|
|
30
|
+
return undefined;
|
|
31
|
+
const out = {};
|
|
32
|
+
if (profile.name !== undefined)
|
|
33
|
+
out.name = profile.name;
|
|
34
|
+
if (profile.url !== undefined)
|
|
35
|
+
out.url = profile.url;
|
|
36
|
+
if (profile.productDescription !== undefined)
|
|
37
|
+
out.product_description = profile.productDescription;
|
|
38
|
+
if (profile.supportEmail !== undefined)
|
|
39
|
+
out.support_email = profile.supportEmail;
|
|
40
|
+
if (profile.supportPhone !== undefined)
|
|
41
|
+
out.support_phone = profile.supportPhone;
|
|
42
|
+
if (profile.mcc !== undefined)
|
|
43
|
+
out.mcc = profile.mcc;
|
|
44
|
+
return out;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Creates a Stripe connected account for a marketplace seller / driver / provider.
|
|
48
|
+
*
|
|
49
|
+
* @param params - Connected-account creation parameters.
|
|
50
|
+
* @returns The new account ID.
|
|
51
|
+
*/
|
|
52
|
+
export const createConnectedAccount = async (params) => {
|
|
53
|
+
try {
|
|
54
|
+
const account = await getClient().accounts.create({
|
|
55
|
+
type: params.type,
|
|
56
|
+
country: params.country,
|
|
57
|
+
email: params.email,
|
|
58
|
+
business_profile: toStripeBusinessProfile(params.businessProfile),
|
|
59
|
+
metadata: params.metadata,
|
|
60
|
+
}, params.idempotencyKey ? { idempotencyKey: params.idempotencyKey } : undefined);
|
|
61
|
+
return { id: account.id };
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
logger.error('Error creating Stripe connected account:', error);
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Creates a Stripe account link the connected account holder uses to finish
|
|
70
|
+
* onboarding (or to update payout details).
|
|
71
|
+
*
|
|
72
|
+
* @param params - Account-link creation parameters.
|
|
73
|
+
* @returns The hosted onboarding/update URL and its expiry (Unix timestamp, seconds).
|
|
74
|
+
*/
|
|
75
|
+
export const createAccountLink = async (params) => {
|
|
76
|
+
try {
|
|
77
|
+
const link = await getClient().accountLinks.create({
|
|
78
|
+
account: params.accountId,
|
|
79
|
+
return_url: params.returnUrl,
|
|
80
|
+
refresh_url: params.refreshUrl,
|
|
81
|
+
type: params.type,
|
|
82
|
+
}, params.idempotencyKey ? { idempotencyKey: params.idempotencyKey } : undefined);
|
|
83
|
+
return { url: link.url, expiresAt: link.expires_at };
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
logger.error('Error creating Stripe account link:', error);
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Transfers funds from the platform balance to a connected account.
|
|
92
|
+
*
|
|
93
|
+
* @param params - Transfer parameters.
|
|
94
|
+
* @returns The created transfer.
|
|
95
|
+
*/
|
|
96
|
+
export const createTransfer = async (params) => {
|
|
97
|
+
try {
|
|
98
|
+
const transfer = await getClient().transfers.create({
|
|
99
|
+
amount: params.amount,
|
|
100
|
+
currency: params.currency,
|
|
101
|
+
destination: params.destination,
|
|
102
|
+
source_transaction: params.sourceTransaction,
|
|
103
|
+
transfer_group: params.transferGroup,
|
|
104
|
+
metadata: params.metadata,
|
|
105
|
+
}, params.idempotencyKey ? { idempotencyKey: params.idempotencyKey } : undefined);
|
|
106
|
+
return {
|
|
107
|
+
id: transfer.id,
|
|
108
|
+
amount: transfer.amount,
|
|
109
|
+
currency: transfer.currency,
|
|
110
|
+
destination: typeof transfer.destination === 'string'
|
|
111
|
+
? transfer.destination
|
|
112
|
+
: transfer.destination?.id || '',
|
|
113
|
+
transferGroup: transfer.transfer_group ?? undefined,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
logger.error('Error creating Stripe transfer:', error);
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Issues a payout from a connected account's Stripe balance to its bank account.
|
|
123
|
+
*
|
|
124
|
+
* Uses Stripe's `Stripe-Account` header to scope the call to the connected account.
|
|
125
|
+
*
|
|
126
|
+
* @param params - Payout parameters.
|
|
127
|
+
* @returns The created payout.
|
|
128
|
+
*/
|
|
129
|
+
export const createPayout = async (params) => {
|
|
130
|
+
try {
|
|
131
|
+
const requestOptions = { stripeAccount: params.accountId };
|
|
132
|
+
if (params.idempotencyKey)
|
|
133
|
+
requestOptions.idempotencyKey = params.idempotencyKey;
|
|
134
|
+
const payout = await getClient().payouts.create({
|
|
135
|
+
amount: params.amount,
|
|
136
|
+
currency: params.currency,
|
|
137
|
+
method: params.method,
|
|
138
|
+
metadata: params.metadata,
|
|
139
|
+
}, requestOptions);
|
|
140
|
+
return {
|
|
141
|
+
id: payout.id,
|
|
142
|
+
amount: payout.amount,
|
|
143
|
+
currency: payout.currency,
|
|
144
|
+
status: payout.status,
|
|
145
|
+
arrivalDate: payout.arrival_date,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
logger.error('Error creating Stripe payout:', error);
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Looks up a connected account's onboarding / payout status.
|
|
155
|
+
*
|
|
156
|
+
* @param accountId - Stripe connected account ID (`acct_...`).
|
|
157
|
+
* @returns Normalized account status.
|
|
158
|
+
*/
|
|
159
|
+
export const getAccountStatus = async (accountId) => {
|
|
160
|
+
try {
|
|
161
|
+
const account = await getClient().accounts.retrieve(accountId);
|
|
162
|
+
const currentlyDue = account.requirements?.currently_due ?? [];
|
|
163
|
+
return {
|
|
164
|
+
id: account.id,
|
|
165
|
+
chargesEnabled: account.charges_enabled === true,
|
|
166
|
+
payoutsEnabled: account.payouts_enabled === true,
|
|
167
|
+
requirementsCurrent: currentlyDue.length === 0,
|
|
168
|
+
type: account.type,
|
|
169
|
+
currentlyDue: [...currentlyDue],
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
logger.error('Error retrieving Stripe connected account:', error);
|
|
174
|
+
throw error;
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Maps a Stripe event type to the recognized Connect event type.
|
|
179
|
+
*
|
|
180
|
+
* @param raw - The raw Stripe event type.
|
|
181
|
+
* @returns The recognized event type, or `unknown`.
|
|
182
|
+
*/
|
|
183
|
+
const toConnectEventType = (raw) => {
|
|
184
|
+
switch (raw) {
|
|
185
|
+
case 'account.updated':
|
|
186
|
+
case 'payout.created':
|
|
187
|
+
case 'transfer.created':
|
|
188
|
+
case 'application_fee.refunded':
|
|
189
|
+
return raw;
|
|
190
|
+
default:
|
|
191
|
+
return 'unknown';
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
/**
|
|
195
|
+
* Verifies and normalizes a Stripe Connect webhook event.
|
|
196
|
+
*
|
|
197
|
+
* Reuses the same `STRIPE_WEBHOOK_SECRET` env var as the standard webhook
|
|
198
|
+
* pipeline (and the same signature verification logic) — Connect events
|
|
199
|
+
* arrive on the same webhook endpoint when the platform's webhook is
|
|
200
|
+
* configured to receive Connect events.
|
|
201
|
+
*
|
|
202
|
+
* @param headers - Request headers (looks up `stripe-signature`).
|
|
203
|
+
* @param body - The raw request body (string or Buffer).
|
|
204
|
+
* @returns The verified, normalized Connect webhook event.
|
|
205
|
+
*/
|
|
206
|
+
export const processConnectWebhook = (headers, body) => {
|
|
207
|
+
const sigHeader = headers['stripe-signature'];
|
|
208
|
+
const signature = Array.isArray(sigHeader) ? sigHeader[0] : sigHeader;
|
|
209
|
+
if (!signature) {
|
|
210
|
+
throw new Error('Missing stripe-signature header');
|
|
211
|
+
}
|
|
212
|
+
const verified = verifyWebhookSignature(body, signature);
|
|
213
|
+
const rawType = verified.type;
|
|
214
|
+
const data = verified.data.object;
|
|
215
|
+
const accountIdFromHeader = headers['stripe-account'];
|
|
216
|
+
const accountId = Array.isArray(accountIdFromHeader)
|
|
217
|
+
? accountIdFromHeader[0]
|
|
218
|
+
: accountIdFromHeader;
|
|
219
|
+
const resourceId = typeof data.id === 'string' ? data.id : undefined;
|
|
220
|
+
const dataAccount = typeof data.account === 'string' ? data.account : undefined;
|
|
221
|
+
return {
|
|
222
|
+
type: toConnectEventType(rawType),
|
|
223
|
+
rawType,
|
|
224
|
+
resourceId,
|
|
225
|
+
accountId: accountId || dataAccount,
|
|
226
|
+
data,
|
|
227
|
+
};
|
|
228
|
+
};
|
|
229
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAE9C,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAEjE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;AAuM1B;;;;;GAKG;AACH,MAAM,uBAAuB,GAAG,CAC9B,OAAoD,EACI,EAAE;IAC1D,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAA;IAC9B,MAAM,GAAG,GAA+C,EAAE,CAAA;IAC1D,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS;QAAE,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;IACvD,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS;QAAE,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAA;IACpD,IAAI,OAAO,CAAC,kBAAkB,KAAK,SAAS;QAAE,GAAG,CAAC,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAA;IAClG,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS;QAAE,GAAG,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,CAAA;IAChF,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS;QAAE,GAAG,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,CAAA;IAChF,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS;QAAE,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAA;IACpD,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EACzC,MAAoC,EACG,EAAE;IACzC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,SAAS,EAAE,CAAC,QAAQ,CAAC,MAAM,CAC/C;YACE,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,gBAAgB,EAAE,uBAAuB,CAAC,MAAM,CAAC,eAAe,CAAC;YACjE,QAAQ,EAAE,MAAM,CAAC,QAAQ;SAC1B,EACD,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,SAAS,CAC9E,CAAA;QACD,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAA;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,0CAA0C,EAAE,KAAK,CAAC,CAAA;QAC/D,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EACpC,MAA+B,EACG,EAAE;IACpC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,SAAS,EAAE,CAAC,YAAY,CAAC,MAAM,CAChD;YACE,OAAO,EAAE,MAAM,CAAC,SAAS;YACzB,UAAU,EAAE,MAAM,CAAC,SAAS;YAC5B,WAAW,EAAE,MAAM,CAAC,UAAU;YAC9B,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,EACD,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,SAAS,CAC9E,CAAA;QACD,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE,CAAA;IACtD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAA;QAC1D,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EACjC,MAA4B,EACG,EAAE;IACjC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,SAAS,EAAE,CAAC,SAAS,CAAC,MAAM,CACjD;YACE,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,kBAAkB,EAAE,MAAM,CAAC,iBAAiB;YAC5C,cAAc,EAAE,MAAM,CAAC,aAAa;YACpC,QAAQ,EAAE,MAAM,CAAC,QAAQ;SAC1B,EACD,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,SAAS,CAC9E,CAAA;QACD,OAAO;YACL,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,WAAW,EACT,OAAO,QAAQ,CAAC,WAAW,KAAK,QAAQ;gBACtC,CAAC,CAAC,QAAQ,CAAC,WAAW;gBACtB,CAAC,CAAE,QAAQ,CAAC,WAAsC,EAAE,EAAE,IAAI,EAAE;YAChE,aAAa,EAAE,QAAQ,CAAC,cAAc,IAAI,SAAS;SACpD,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAA;QACtD,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAAE,MAA0B,EAA+B,EAAE;IAC5F,IAAI,CAAC;QACH,MAAM,cAAc,GAA0B,EAAE,aAAa,EAAE,MAAM,CAAC,SAAS,EAAE,CAAA;QACjF,IAAI,MAAM,CAAC,cAAc;YAAE,cAAc,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAA;QAEhF,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC,OAAO,CAAC,MAAM,CAC7C;YACE,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;SAC1B,EACD,cAAc,CACf,CAAA;QACD,OAAO;YACL,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,WAAW,EAAE,MAAM,CAAC,YAAY;SACjC,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAA;QACpD,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EAAE,SAAiB,EAA0B,EAAE;IAClF,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,SAAS,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;QAC9D,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,EAAE,aAAa,IAAI,EAAE,CAAA;QAC9D,OAAO;YACL,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,cAAc,EAAE,OAAO,CAAC,eAAe,KAAK,IAAI;YAChD,cAAc,EAAE,OAAO,CAAC,eAAe,KAAK,IAAI;YAChD,mBAAmB,EAAE,YAAY,CAAC,MAAM,KAAK,CAAC;YAC9C,IAAI,EAAE,OAAO,CAAC,IAAwC;YACtD,YAAY,EAAE,CAAC,GAAG,YAAY,CAAC;SAChC,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,4CAA4C,EAAE,KAAK,CAAC,CAAA;QACjE,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,kBAAkB,GAAG,CAAC,GAAW,EAA2B,EAAE;IAClE,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,iBAAiB,CAAC;QACvB,KAAK,gBAAgB,CAAC;QACtB,KAAK,kBAAkB,CAAC;QACxB,KAAK,0BAA0B;YAC7B,OAAO,GAAG,CAAA;QACZ;YACE,OAAO,SAAS,CAAA;IACpB,CAAC;AACH,CAAC,CAAA;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,OAAsD,EACtD,IAAqB,EACA,EAAE;IACvB,MAAM,SAAS,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;IAC7C,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACrE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;IACpD,CAAC;IAED,MAAM,QAAQ,GAAG,sBAAsB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IACxD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAA;IAC7B,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAA;IACjC,MAAM,mBAAmB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACrD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAC;QAClD,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACxB,CAAC,CAAC,mBAAmB,CAAA;IAEvB,MAAM,UAAU,GAAG,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;IACpE,MAAM,WAAW,GAAG,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;IAE/E,OAAO;QACL,IAAI,EAAE,kBAAkB,CAAC,OAAO,CAAC;QACjC,OAAO;QACP,UAAU;QACV,SAAS,EAAE,SAAS,IAAI,WAAW;QACnC,IAAI;KACL,CAAA;AACH,CAAC,CAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stripe payment provider for molecule.dev.
|
|
3
|
+
*
|
|
4
|
+
* @see https://www.npmjs.com/package/stripe
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Bond this as the payments provider so `@molecule/api-payments`'s `verifySubscription` (and
|
|
8
|
+
* the payment resource) work server-side — don't call the Stripe SDK directly for
|
|
9
|
+
* verification. Env: `STRIPE_SECRET_KEY` + `STRIPE_WEBHOOK_SECRET` are SERVER-ONLY; only the
|
|
10
|
+
* publishable key (`pk_…`) is client-side.
|
|
11
|
+
*
|
|
12
|
+
* **You do NOT need molecule's Express app, the `bond()` wiring, or the UI packages to use
|
|
13
|
+
* this — the functions below are framework-agnostic.** On a non-Express / non-molecule host
|
|
14
|
+
* (Next.js App Router, serverless functions, Hono, Fastify), import them and call them from
|
|
15
|
+
* your OWN route handlers:
|
|
16
|
+
* `import { createCheckoutSession, verifyWebhookSignature, getSubscription } from '@molecule/api-payments-stripe'`.
|
|
17
|
+
* They cover the whole flow — {@link createCheckoutSession} (server-owned `priceId`, so you
|
|
18
|
+
* never take a price/amount from the client), {@link createPortalSession} (hosted Billing
|
|
19
|
+
* Portal for payment-method updates/cancellation/invoices), {@link verifyWebhookSignature},
|
|
20
|
+
* and the subscription getters/updaters — and carry the security contract (config-not-configured
|
|
21
|
+
* errors, normalized status) for free, so reach for these instead of hand-rolling raw
|
|
22
|
+
* `stripe` calls. In a Next.js App Router route, read the RAW webhook body with
|
|
23
|
+
* `await req.text()` and the header with `req.headers.get('stripe-signature')`, then
|
|
24
|
+
* `verifyWebhookSignature(rawBody, signature)` (the `express.raw(...)` note below is the
|
|
25
|
+
* Express-host equivalent). Only `@molecule/api-middleware-billing-routes` (Express glue) and
|
|
26
|
+
* `@molecule/app-billing-react` (molecule UI) are framework-coupled — skip THOSE on such a
|
|
27
|
+
* host, but still use these bond functions underneath.
|
|
28
|
+
*
|
|
29
|
+
* Two things a weak Stripe integration gets wrong:
|
|
30
|
+
*
|
|
31
|
+
* - **The webhook body MUST be RAW for signature verification.** {@link verifyWebhookSignature}
|
|
32
|
+
* (Stripe's `constructEvent`) hashes the exact bytes, so a parsed-then-re-serialized body
|
|
33
|
+
* ALWAYS fails. In a molecule app you need NO special middleware: the always-included
|
|
34
|
+
* `@molecule/api-middleware-body-parser-express` already captures the unparsed body as
|
|
35
|
+
* `req.rawBody` (a string) on EVERY request — just pass `req.rawBody` + the `stripe-signature`
|
|
36
|
+
* header to {@link verifyWebhookSignature}. Do NOT add a route-specific `express.raw(...)` here —
|
|
37
|
+
* it is redundant and fights the global JSON parser (which has already consumed the stream and
|
|
38
|
+
* set `req.rawBody`). (ONLY on a NON-molecule Express host that lacks `req.rawBody` do you mount
|
|
39
|
+
* `express.raw({ type: 'application/json' })` before the JSON parser; on Next.js App Router read
|
|
40
|
+
* the raw body with `await req.text()`.) NEVER act on an unverified webhook body — it is
|
|
41
|
+
* attacker-controlled.
|
|
42
|
+
* - **Webhooks are redelivered — be idempotent.** Stripe retries until it gets a 2xx, so the
|
|
43
|
+
* same `event.id` can arrive twice. Dedupe on it (the payment record's
|
|
44
|
+
* `UNIQUE(platformKey, transactionId)` already blocks a double-grant), and return 2xx once
|
|
45
|
+
* handled so Stripe stops retrying.
|
|
46
|
+
*
|
|
47
|
+
* Create checkout with SERVER-configured price ids ({@link createCheckoutSession}) — never an
|
|
48
|
+
* amount sent by the client.
|
|
49
|
+
*
|
|
50
|
+
* **A missing `STRIPE_SECRET_KEY` is NOT the same as "no active subscription."**
|
|
51
|
+
* `getClient()` throws a tagged config-not-configured error; `verifySubscription`,
|
|
52
|
+
* `updateSubscription`, and `cancelSubscription` on {@link paymentProvider} detect
|
|
53
|
+
* that tag (`isConfigNotConfiguredError` from `@molecule/api-payments`) and
|
|
54
|
+
* RETHROW it instead of swallowing it into the same `null` / `{ updated: false }`
|
|
55
|
+
* / `false` a genuine verification/update failure returns — so a caller (or its
|
|
56
|
+
* own catch block) can tell "the operator forgot to set the secret" apart from
|
|
57
|
+
* "this subscription/card is invalid" and surface the actionable 503 instead of
|
|
58
|
+
* a generic 400/500.
|
|
59
|
+
*
|
|
60
|
+
* @module
|
|
61
|
+
*/
|
|
62
|
+
export * from './bondAdapter.js';
|
|
63
|
+
export * from './browser-guard.js';
|
|
64
|
+
export * from './connect.js';
|
|
65
|
+
export * from './provider.js';
|
|
66
|
+
export * from './secrets.js';
|
|
67
|
+
export * from './types.js';
|
|
68
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AAEH,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stripe payment provider for molecule.dev.
|
|
3
|
+
*
|
|
4
|
+
* @see https://www.npmjs.com/package/stripe
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Bond this as the payments provider so `@molecule/api-payments`'s `verifySubscription` (and
|
|
8
|
+
* the payment resource) work server-side — don't call the Stripe SDK directly for
|
|
9
|
+
* verification. Env: `STRIPE_SECRET_KEY` + `STRIPE_WEBHOOK_SECRET` are SERVER-ONLY; only the
|
|
10
|
+
* publishable key (`pk_…`) is client-side.
|
|
11
|
+
*
|
|
12
|
+
* **You do NOT need molecule's Express app, the `bond()` wiring, or the UI packages to use
|
|
13
|
+
* this — the functions below are framework-agnostic.** On a non-Express / non-molecule host
|
|
14
|
+
* (Next.js App Router, serverless functions, Hono, Fastify), import them and call them from
|
|
15
|
+
* your OWN route handlers:
|
|
16
|
+
* `import { createCheckoutSession, verifyWebhookSignature, getSubscription } from '@molecule/api-payments-stripe'`.
|
|
17
|
+
* They cover the whole flow — {@link createCheckoutSession} (server-owned `priceId`, so you
|
|
18
|
+
* never take a price/amount from the client), {@link createPortalSession} (hosted Billing
|
|
19
|
+
* Portal for payment-method updates/cancellation/invoices), {@link verifyWebhookSignature},
|
|
20
|
+
* and the subscription getters/updaters — and carry the security contract (config-not-configured
|
|
21
|
+
* errors, normalized status) for free, so reach for these instead of hand-rolling raw
|
|
22
|
+
* `stripe` calls. In a Next.js App Router route, read the RAW webhook body with
|
|
23
|
+
* `await req.text()` and the header with `req.headers.get('stripe-signature')`, then
|
|
24
|
+
* `verifyWebhookSignature(rawBody, signature)` (the `express.raw(...)` note below is the
|
|
25
|
+
* Express-host equivalent). Only `@molecule/api-middleware-billing-routes` (Express glue) and
|
|
26
|
+
* `@molecule/app-billing-react` (molecule UI) are framework-coupled — skip THOSE on such a
|
|
27
|
+
* host, but still use these bond functions underneath.
|
|
28
|
+
*
|
|
29
|
+
* Two things a weak Stripe integration gets wrong:
|
|
30
|
+
*
|
|
31
|
+
* - **The webhook body MUST be RAW for signature verification.** {@link verifyWebhookSignature}
|
|
32
|
+
* (Stripe's `constructEvent`) hashes the exact bytes, so a parsed-then-re-serialized body
|
|
33
|
+
* ALWAYS fails. In a molecule app you need NO special middleware: the always-included
|
|
34
|
+
* `@molecule/api-middleware-body-parser-express` already captures the unparsed body as
|
|
35
|
+
* `req.rawBody` (a string) on EVERY request — just pass `req.rawBody` + the `stripe-signature`
|
|
36
|
+
* header to {@link verifyWebhookSignature}. Do NOT add a route-specific `express.raw(...)` here —
|
|
37
|
+
* it is redundant and fights the global JSON parser (which has already consumed the stream and
|
|
38
|
+
* set `req.rawBody`). (ONLY on a NON-molecule Express host that lacks `req.rawBody` do you mount
|
|
39
|
+
* `express.raw({ type: 'application/json' })` before the JSON parser; on Next.js App Router read
|
|
40
|
+
* the raw body with `await req.text()`.) NEVER act on an unverified webhook body — it is
|
|
41
|
+
* attacker-controlled.
|
|
42
|
+
* - **Webhooks are redelivered — be idempotent.** Stripe retries until it gets a 2xx, so the
|
|
43
|
+
* same `event.id` can arrive twice. Dedupe on it (the payment record's
|
|
44
|
+
* `UNIQUE(platformKey, transactionId)` already blocks a double-grant), and return 2xx once
|
|
45
|
+
* handled so Stripe stops retrying.
|
|
46
|
+
*
|
|
47
|
+
* Create checkout with SERVER-configured price ids ({@link createCheckoutSession}) — never an
|
|
48
|
+
* amount sent by the client.
|
|
49
|
+
*
|
|
50
|
+
* **A missing `STRIPE_SECRET_KEY` is NOT the same as "no active subscription."**
|
|
51
|
+
* `getClient()` throws a tagged config-not-configured error; `verifySubscription`,
|
|
52
|
+
* `updateSubscription`, and `cancelSubscription` on {@link paymentProvider} detect
|
|
53
|
+
* that tag (`isConfigNotConfiguredError` from `@molecule/api-payments`) and
|
|
54
|
+
* RETHROW it instead of swallowing it into the same `null` / `{ updated: false }`
|
|
55
|
+
* / `false` a genuine verification/update failure returns — so a caller (or its
|
|
56
|
+
* own catch block) can tell "the operator forgot to set the secret" apart from
|
|
57
|
+
* "this subscription/card is invalid" and surface the actionable 503 instead of
|
|
58
|
+
* a generic 400/500.
|
|
59
|
+
*
|
|
60
|
+
* @module
|
|
61
|
+
*/
|
|
62
|
+
export * from './bondAdapter.js';
|
|
63
|
+
export * from './browser-guard.js';
|
|
64
|
+
export * from './connect.js';
|
|
65
|
+
export * from './provider.js';
|
|
66
|
+
export * from './secrets.js';
|
|
67
|
+
export * from './types.js';
|
|
68
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AAEH,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA"}
|