@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 ADDED
@@ -0,0 +1,115 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work.
38
+
39
+ "Derivative Works" shall mean any work, whether in Source or Object
40
+ form, that is based on (or derived from) the Work and for which the
41
+ editorial revisions, annotations, elaborations, or other modifications
42
+ represent, as a whole, an original work of authorship.
43
+
44
+ "Contribution" shall mean any work of authorship, including the
45
+ original version of the Work and any modifications or additions
46
+ to that Work, that is intentionally submitted to the Licensor for
47
+ inclusion in the Work by the copyright owner or by an individual or
48
+ Legal Entity authorized to submit on behalf of the copyright owner.
49
+
50
+ "Contributor" shall mean Licensor and any individual or Legal Entity
51
+ on behalf of whom a Contribution has been received by the Licensor and
52
+ subsequently incorporated within the Work.
53
+
54
+ 2. Grant of Copyright License. Subject to the terms and conditions of
55
+ this License, each Contributor hereby grants to You a perpetual,
56
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
57
+ copyright license to reproduce, prepare Derivative Works of,
58
+ publicly display, publicly perform, sublicense, and distribute the
59
+ Work and such Derivative Works in Source or Object form.
60
+
61
+ 3. Grant of Patent License. Subject to the terms and conditions of
62
+ this License, each Contributor hereby grants to You a perpetual,
63
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
64
+ patent license to make, have made, use, offer to sell, sell, import,
65
+ and otherwise transfer the Work.
66
+
67
+ 4. Redistribution. You may reproduce and distribute copies of the
68
+ Work or Derivative Works thereof in any medium, with or without
69
+ modifications, and in Source or Object form, provided that You
70
+ meet the following conditions:
71
+
72
+ (a) You must give any other recipients of the Work or
73
+ Derivative Works a copy of this License; and
74
+
75
+ (b) You must cause any modified files to carry prominent notices
76
+ stating that You changed the files; and
77
+
78
+ (c) You must retain, in the Source form of any Derivative Works
79
+ that You distribute, all copyright, patent, trademark, and
80
+ attribution notices from the Source form of the Work,
81
+ excluding those notices that do not pertain to any part of
82
+ the Derivative Works; and
83
+
84
+ (d) If the Work includes a "NOTICE" text file as part of its
85
+ distribution, then any Derivative Works that You distribute must
86
+ include a readable copy of the attribution notices contained
87
+ within such NOTICE file.
88
+
89
+ 5. Submission of Contributions.
90
+
91
+ 6. Trademarks. This License does not grant permission to use the trade
92
+ names, trademarks, service marks, or product names of the Licensor.
93
+
94
+ 7. Disclaimer of Warranty. Unless required by applicable law or
95
+ agreed to in writing, Licensor provides the Work on an "AS IS" BASIS,
96
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND.
97
+
98
+ 8. Limitation of Liability. In no event and under no legal theory shall
99
+ any Contributor be liable to You for damages.
100
+
101
+ 9. Accepting Warranty or Additional Liability.
102
+
103
+ Copyright 2026 Molecule Dev, Inc.
104
+
105
+ Licensed under the Apache License, Version 2.0 (the "License");
106
+ you may not use this file except in compliance with the License.
107
+ You may obtain a copy of the License at
108
+
109
+ http://www.apache.org/licenses/LICENSE-2.0
110
+
111
+ Unless required by applicable law or agreed to in writing, software
112
+ distributed under the License is distributed on an "AS IS" BASIS,
113
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
114
+ See the License for the specific language governing permissions and
115
+ limitations under the License.
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Bond adapter for the Stripe payment provider.
3
+ *
4
+ * Wraps the Stripe SDK functions into a PaymentProvider-compatible interface
5
+ * for use with the molecule.dev bond system.
6
+ *
7
+ * @module
8
+ */
9
+ import { type PaymentProvider } from '@molecule/api-payments';
10
+ /**
11
+ * PaymentProvider-compatible adapter for Stripe.
12
+ *
13
+ * Wraps the Stripe SDK functions into a `PaymentProvider`-compatible object
14
+ * for use with the molecule bond system. Supports subscription verification,
15
+ * webhook handling, plan upgrades/downgrades, and cancellation.
16
+ */
17
+ export declare const paymentProvider: PaymentProvider;
18
+ //# sourceMappingURL=bondAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bondAdapter.d.ts","sourceRoot":"","sources":["../src/bondAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,EAGL,KAAK,eAAe,EAOrB,MAAM,wBAAwB,CAAA;AA6C/B;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,eA8Z7B,CAAA"}
@@ -0,0 +1,406 @@
1
+ /**
2
+ * Bond adapter for the Stripe payment provider.
3
+ *
4
+ * Wraps the Stripe SDK functions into a PaymentProvider-compatible interface
5
+ * for use with the molecule.dev bond system.
6
+ *
7
+ * @module
8
+ */
9
+ import crypto from 'crypto';
10
+ import { getLogger } from '@molecule/api-bond';
11
+ const logger = getLogger();
12
+ import { get } from '@molecule/api-bond';
13
+ import { isConfigNotConfiguredError, } from '@molecule/api-payments';
14
+ import { createCheckoutSession, createPortalSession as stripeCreatePortalSession, createSetupIntent as stripeCreateSetupIntent, detachPaymentMethod as stripeDetachPaymentMethod, getCheckoutSession, getSubscription, normalizeSubscription, normalizeSubscriptionStatus, retrievePaymentMethod as stripeRetrievePaymentMethod, updateSubscription as stripeUpdateSubscription, verifyWebhookSignature, } from './provider.js';
15
+ /**
16
+ * Maps Stripe webhook event types (e.g. `customer.subscription.created`) to
17
+ * simplified event type strings (e.g. `created`, `renewed`, `canceled`).
18
+ * @param eventType - The raw Stripe webhook event type string.
19
+ * @returns A simplified event type like `'created'`, `'renewed'`, `'canceled'`, `'paused'`, `'expired'`, or `'trial_ending'`. Falls through to the raw type for unrecognized events.
20
+ */
21
+ const mapStripeEventType = (eventType) => {
22
+ switch (eventType) {
23
+ case 'customer.subscription.created':
24
+ return 'created';
25
+ case 'customer.subscription.updated':
26
+ return 'renewed';
27
+ case 'customer.subscription.deleted':
28
+ return 'canceled';
29
+ case 'customer.subscription.paused':
30
+ return 'paused';
31
+ case 'customer.subscription.resumed':
32
+ return 'renewed';
33
+ case 'customer.subscription.pending_update_applied':
34
+ return 'renewed';
35
+ case 'customer.subscription.pending_update_expired':
36
+ return 'expired';
37
+ case 'customer.subscription.trial_will_end':
38
+ return 'trial_ending';
39
+ default:
40
+ return eventType;
41
+ }
42
+ };
43
+ /**
44
+ * PaymentProvider-compatible adapter for Stripe.
45
+ *
46
+ * Wraps the Stripe SDK functions into a `PaymentProvider`-compatible object
47
+ * for use with the molecule bond system. Supports subscription verification,
48
+ * webhook handling, plan upgrades/downgrades, and cancellation.
49
+ */
50
+ export const paymentProvider = {
51
+ providerName: 'stripe',
52
+ verifyFlow: 'subscription',
53
+ notificationFlow: 'webhook',
54
+ /**
55
+ * Verifies a Stripe subscription by ID and returns a VerifiedSubscription.
56
+ *
57
+ * Accepts either a Subscription ID (`sub_xxx`) or a Checkout Session ID (`cs_xxx`).
58
+ * If a Checkout Session ID is provided, it retrieves the session first to extract
59
+ * the associated subscription ID.
60
+ * @param subscriptionId - The Stripe subscription ID (`sub_xxx`) or checkout session ID (`cs_xxx`).
61
+ * @returns The verified subscription with product, expiry, and renewal info, or `null` on failure.
62
+ */
63
+ async verifySubscription(subscriptionId) {
64
+ try {
65
+ // A Checkout Session ID (`cs_...`) only arrives via the per-user
66
+ // post-checkout redirect (success_url), which is unguessable and bound to
67
+ // the user who started checkout. A bare `sub_...` id, by contrast, can be
68
+ // a value the caller merely learned, so the handler requires an ownership
69
+ // match for it. Surface which path this was so `verifyPayment` can enforce
70
+ // that distinction.
71
+ const viaCheckoutSession = subscriptionId.startsWith('cs_');
72
+ // If this is a Checkout Session ID (from post-checkout redirect), resolve to subscription
73
+ let resolvedSubscriptionId = subscriptionId;
74
+ if (viaCheckoutSession) {
75
+ const session = await getCheckoutSession(subscriptionId);
76
+ if (!session.subscription) {
77
+ logger.error('Stripe checkout session has no subscription', { sessionId: subscriptionId });
78
+ return null;
79
+ }
80
+ resolvedSubscriptionId = session.subscription;
81
+ }
82
+ const subscription = await getSubscription(resolvedSubscriptionId);
83
+ if (!subscription) {
84
+ return null;
85
+ }
86
+ const normalized = normalizeSubscription(subscription);
87
+ // Gate the grant on subscription status: only an active/trialing
88
+ // subscription confers entitlement. A past_due/unpaid/canceled/incomplete
89
+ // subscription must NOT re-grant the plan on demand.
90
+ if (!normalized.isActive) {
91
+ logger.info(`Stripe verifySubscription: subscription ${normalized.subscriptionId} is not active (status=${normalized.status}) — rejecting`);
92
+ return null;
93
+ }
94
+ // Defense in depth: also reject if the current period has already elapsed
95
+ // (when known). `isActive` already covers Stripe's authoritative status,
96
+ // but an out-of-date period end is never a valid grant.
97
+ if (normalized.currentPeriodEnd && normalized.currentPeriodEnd <= Date.now()) {
98
+ logger.info(`Stripe verifySubscription: subscription ${normalized.subscriptionId} period has ended — rejecting`);
99
+ return null;
100
+ }
101
+ // Apps register their plan catalogue with PRICE ids (the env-configured
102
+ // `STRIPE_<APP>_…` values checkout is started with), while the
103
+ // subscription reports the parent PRODUCT id — surface both so plan
104
+ // resolution can match either.
105
+ const rawItems = normalized.rawData?.items;
106
+ const verifiedPriceId = rawItems?.data?.[0]?.price?.id;
107
+ return {
108
+ productId: normalized.productId,
109
+ priceId: verifiedPriceId ? String(verifiedPriceId) : undefined,
110
+ transactionId: normalized.subscriptionId,
111
+ expiresAt: normalized.currentPeriodEnd
112
+ ? new Date(normalized.currentPeriodEnd).toISOString()
113
+ : undefined,
114
+ autoRenews: normalized.willRenew,
115
+ data: {
116
+ customerId: typeof normalized.rawData?.customer === 'string'
117
+ ? normalized.rawData.customer
118
+ : undefined,
119
+ viaCheckoutSession,
120
+ },
121
+ };
122
+ }
123
+ catch (error) {
124
+ // A missing STRIPE_SECRET_KEY (getClient()) is a DIFFERENT failure than
125
+ // "no active subscription" — rethrow so the resource handler's catch can
126
+ // surface the actionable 503 instead of a generic 400. Swallowing it into
127
+ // the same `null` a genuine verification failure returns makes an
128
+ // operator's forgotten env var indistinguishable from "this subscription
129
+ // isn't valid."
130
+ if (isConfigNotConfiguredError(error)) {
131
+ throw error;
132
+ }
133
+ logger.error('Stripe bondAdapter verifySubscription error:', error);
134
+ return null;
135
+ }
136
+ },
137
+ /**
138
+ * Handles a Stripe webhook event by verifying the signature and parsing the payload.
139
+ *
140
+ * Expects an express-like request object with `body` (raw body as Buffer or string)
141
+ * and `headers` containing `stripe-signature`.
142
+ * @param req - An Express-like request object with `body` (or `rawBody`) and `headers['stripe-signature']`.
143
+ * @returns A parsed webhook event with simplified type and subscription details, or `null` on failure.
144
+ */
145
+ async handleWebhookEvent(req) {
146
+ try {
147
+ const request = req;
148
+ const rawBody = request.rawBody || request.body;
149
+ const signature = request.headers['stripe-signature'];
150
+ if (!rawBody || !signature) {
151
+ logger.error('Stripe bondAdapter handleWebhookEvent: missing body or stripe-signature.');
152
+ return null;
153
+ }
154
+ const event = verifyWebhookSignature(rawBody, Array.isArray(signature) ? signature[0] : signature);
155
+ // Only process subscription-related events.
156
+ if (!event.type.startsWith('customer.subscription.')) {
157
+ return {
158
+ type: event.type,
159
+ };
160
+ }
161
+ const subscriptionData = event.data.object;
162
+ // Extract the product AND price IDs from the subscription items — apps
163
+ // register plans by PRICE id (env-configured), so plan resolution needs
164
+ // both candidates.
165
+ const items = subscriptionData.items;
166
+ const productId = items?.data?.[0]?.price?.product
167
+ ? String(items.data[0].price.product)
168
+ : undefined;
169
+ const priceId = items?.data?.[0]?.price?.id ? String(items.data[0].price.id) : undefined;
170
+ // Get period end from the subscription item (Stripe API 2025+ moved it
171
+ // there). Webhook payload shape follows the API version PINNED ON THE
172
+ // WEBHOOK ENDPOINT — older endpoints still send it top-level on the
173
+ // subscription, so fall back to that rather than silently dropping the
174
+ // expiry (a missing expiresAt reads downstream as "never expires").
175
+ const subscriptionItem = (items?.data?.[0] ?? {});
176
+ const periodEnd = (subscriptionItem.current_period_end ??
177
+ subscriptionData.current_period_end);
178
+ const expiresAt = periodEnd ? new Date(periodEnd * 1000).toISOString() : undefined;
179
+ const autoRenews = event.type !== 'customer.subscription.deleted' &&
180
+ !subscriptionData.canceled_at &&
181
+ !subscriptionData.cancel_at_period_end;
182
+ // Surface the subscription status so the notification handler can enforce
183
+ // the SAME entitlement gate as `verifySubscription`. `isActive` is derived
184
+ // with the identical rule used by `normalizeSubscription` (active/trialing
185
+ // only). Without this, a renewal-payment failure (Stripe fires a signed
186
+ // `customer.subscription.updated` with status=past_due and an advanced
187
+ // current_period_end) would extend premium for an unpaid cycle.
188
+ const rawStatus = typeof subscriptionData.status === 'string' ? subscriptionData.status : undefined;
189
+ const status = normalizeSubscriptionStatus(rawStatus);
190
+ const isActive = rawStatus === 'active' || rawStatus === 'trialing';
191
+ return {
192
+ type: mapStripeEventType(event.type),
193
+ subscription: {
194
+ customerId: subscriptionData.customer ? String(subscriptionData.customer) : undefined,
195
+ productId,
196
+ priceId,
197
+ expiresAt,
198
+ autoRenews,
199
+ status,
200
+ isActive,
201
+ },
202
+ };
203
+ }
204
+ catch (error) {
205
+ logger.error('Stripe bondAdapter handleWebhookEvent error:', error);
206
+ return null;
207
+ }
208
+ },
209
+ /**
210
+ * Updates or creates a Stripe subscription for a user.
211
+ *
212
+ * 1. Looks up the user's existing Stripe subscription via PaymentRecordService.
213
+ * 2. If found, updates the subscription to the new product/price.
214
+ * 3. If not found, creates a Stripe Checkout session and returns the checkout URL.
215
+ *
216
+ * Handles subscription updates and new checkout session creation.
217
+ * @param params - The update parameters.
218
+ * @param params.userId - The molecule user ID to update the subscription for.
219
+ * @param params.newProductId - The Stripe Price ID of the new plan to switch to.
220
+ * @param params.previousProductId - The Stripe Price ID of the current plan (unused, for logging context).
221
+ * @returns An object with `updated: true` if the existing subscription was changed, or `checkoutUrl` if a new Checkout session was created.
222
+ */
223
+ async updateSubscription(params) {
224
+ try {
225
+ const records = get('paymentRecords');
226
+ // Try to find an existing Stripe subscription for this user.
227
+ if (records) {
228
+ const payment = await records.findByUserId(params.userId, 'stripe');
229
+ const subscriptionId = payment?.data?.subscriptionId;
230
+ if (subscriptionId) {
231
+ // Existing subscription found — update it with the new price.
232
+ const subscription = await getSubscription(subscriptionId);
233
+ if (subscription?.items?.data?.[0]?.id) {
234
+ const updatedSubscription = await stripeUpdateSubscription(subscriptionId, {
235
+ items: [
236
+ {
237
+ id: subscription.items.data[0].id,
238
+ price: params.newProductId,
239
+ },
240
+ ],
241
+ });
242
+ if (updatedSubscription) {
243
+ const subscriptionItem = updatedSubscription.items?.data?.[0];
244
+ const periodEnd = subscriptionItem
245
+ ?.current_period_end;
246
+ const expiresAt = periodEnd ? new Date(periodEnd * 1000).toISOString() : undefined;
247
+ return {
248
+ updated: true,
249
+ subscription: {
250
+ expiresAt,
251
+ autoRenews: !updatedSubscription.cancel_at_period_end,
252
+ },
253
+ };
254
+ }
255
+ }
256
+ }
257
+ }
258
+ // No existing subscription — create a Stripe Checkout session.
259
+ // Stripe rejects empty/relative success_url and cancel_url with
260
+ // `code: 'url_invalid'`. When neither API_ORIGIN/APP_ORIGIN nor
261
+ // ORIGIN is set (typical in dev / smoke-app spin-ups), fall back to
262
+ // `http://localhost:${PORT}` so checkout still works locally.
263
+ const apiPort = Number(process.env.PORT) || 4000;
264
+ const fallbackApiOrigin = `http://localhost:${apiPort}`;
265
+ // Conventional dev frontend lives on apiPort - 1000 (e.g. 4030 → 3030).
266
+ // Mirrors the polish-v2 dispatcher's port pairing.
267
+ const fallbackAppOrigin = `http://localhost:${apiPort - 1000}`;
268
+ const apiOrigin = process.env.API_ORIGIN || process.env.ORIGIN || fallbackApiOrigin;
269
+ const appOrigin = process.env.APP_ORIGIN || process.env.ORIGIN || fallbackAppOrigin;
270
+ if (apiOrigin === fallbackApiOrigin || appOrigin === fallbackAppOrigin) {
271
+ // Silent localhost redirect URLs in a deployed app strand the user on
272
+ // localhost after paying — make the fallback visible.
273
+ logger.warn(`Stripe checkout: API_ORIGIN/APP_ORIGIN/ORIGIN not set — falling back to ${fallbackApiOrigin} / ${fallbackAppOrigin} for redirect URLs (fine in dev, wrong in production).`);
274
+ }
275
+ // Generate idempotency key from userId + priceId + timestamp window (5-min buckets)
276
+ // This prevents duplicate checkout sessions if the user double-clicks or retries
277
+ const timeWindow = Math.floor(Date.now() / (5 * 60 * 1000));
278
+ const idempotencyKey = crypto
279
+ .createHash('sha256')
280
+ .update(`checkout:${params.userId}:${params.newProductId}:${timeWindow}`)
281
+ .digest('hex');
282
+ const session = await createCheckoutSession({
283
+ priceId: params.newProductId,
284
+ successUrl: `${apiOrigin}/api/users/${params.userId}/verify-payment/stripe?subscriptionId={CHECKOUT_SESSION_ID}`,
285
+ cancelUrl: appOrigin,
286
+ idempotencyKey,
287
+ });
288
+ if (session?.id && session?.url) {
289
+ return { updated: false, checkoutUrl: session.url };
290
+ }
291
+ return { updated: false };
292
+ }
293
+ catch (error) {
294
+ // See the matching comment in verifySubscription: a missing secret must
295
+ // reach the caller as its real 503, not be flattened into the same
296
+ // `{ updated: false }` a genuine update failure (e.g. Stripe declining
297
+ // the card) returns.
298
+ if (isConfigNotConfiguredError(error)) {
299
+ throw error;
300
+ }
301
+ logger.error('Stripe bondAdapter updateSubscription error:', error);
302
+ return { updated: false };
303
+ }
304
+ },
305
+ /**
306
+ * Creates a Stripe SetupIntent so the frontend can confirm a card off-session.
307
+ *
308
+ * @param params - SetupIntent parameters (optional Stripe customer ID, metadata, idempotency key).
309
+ * @returns The SetupIntent ID, client secret, and customer ID.
310
+ */
311
+ async createSetupIntent(params) {
312
+ return stripeCreateSetupIntent({
313
+ customerId: params.customerId,
314
+ metadata: params.metadata,
315
+ idempotencyKey: params.idempotencyKey,
316
+ });
317
+ },
318
+ /**
319
+ * Retrieves a saved Stripe payment method and returns normalized card metadata.
320
+ *
321
+ * @param providerPaymentMethodId - The Stripe payment method ID (`pm_...`).
322
+ * @returns Card brand/last4/exp, or `null` on failure.
323
+ */
324
+ async getPaymentMethod(providerPaymentMethodId) {
325
+ return stripeRetrievePaymentMethod(providerPaymentMethodId);
326
+ },
327
+ /**
328
+ * Detaches a Stripe saved payment method from its customer.
329
+ *
330
+ * @param providerPaymentMethodId - The Stripe payment method ID (`pm_...`).
331
+ * @returns `true` on success, `false` on provider error.
332
+ */
333
+ async detachPaymentMethod(providerPaymentMethodId) {
334
+ return stripeDetachPaymentMethod(providerPaymentMethodId);
335
+ },
336
+ /**
337
+ * Cancels an existing Stripe subscription for a user.
338
+ *
339
+ * Looks up the subscription via PaymentRecordService, then sets
340
+ * `cancel_at_period_end` to `true` so it expires at the end of the current billing cycle.
341
+ * @param params - The cancellation parameters.
342
+ * @param params.userId - The molecule user ID whose subscription should be canceled.
343
+ * @returns `true` if the subscription was successfully set to cancel at period end, `false` otherwise.
344
+ */
345
+ async cancelSubscription(params) {
346
+ try {
347
+ const records = get('paymentRecords');
348
+ if (!records)
349
+ return false;
350
+ const payment = await records.findByUserId(params.userId, 'stripe');
351
+ const subscriptionId = payment?.data?.subscriptionId;
352
+ if (!subscriptionId)
353
+ return false;
354
+ const subscription = await getSubscription(subscriptionId);
355
+ if (!subscription)
356
+ return false;
357
+ const updated = await stripeUpdateSubscription(subscriptionId, {
358
+ cancel_at_period_end: true,
359
+ });
360
+ return !!updated;
361
+ }
362
+ catch (error) {
363
+ // See the matching comment in verifySubscription.
364
+ if (isConfigNotConfiguredError(error)) {
365
+ throw error;
366
+ }
367
+ logger.error('Stripe bondAdapter cancelSubscription error:', error);
368
+ return false;
369
+ }
370
+ },
371
+ /**
372
+ * Creates a Stripe Billing Portal session for the user so they can manage
373
+ * payment methods, cancel, and view invoices in Stripe's hosted portal.
374
+ * Resolves the user's Stripe customer ID from their payment record (stored
375
+ * at checkout/verify time).
376
+ *
377
+ * @param params - The portal parameters.
378
+ * @param params.userId - The molecule user ID to open the portal for.
379
+ * @param params.returnUrl - URL Stripe returns the user to on exit.
380
+ * @returns The portal session `{ id, url }`, or `null` when the user has no
381
+ * Stripe customer record or Stripe rejects the request.
382
+ */
383
+ async createPortalSession(params) {
384
+ try {
385
+ const records = get('paymentRecords');
386
+ if (!records)
387
+ return null;
388
+ const payment = await records.findByUserId(params.userId, 'stripe');
389
+ const customerId = payment?.data?.customerId;
390
+ if (!customerId)
391
+ return null;
392
+ return await stripeCreatePortalSession({
393
+ customerId,
394
+ returnUrl: params.returnUrl,
395
+ });
396
+ }
397
+ catch (error) {
398
+ if (isConfigNotConfiguredError(error)) {
399
+ throw error;
400
+ }
401
+ logger.error('Stripe bondAdapter createPortalSession error:', error);
402
+ return null;
403
+ }
404
+ },
405
+ };
406
+ //# sourceMappingURL=bondAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bondAdapter.js","sourceRoot":"","sources":["../src/bondAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=browser-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-guard.d.ts","sourceRoot":"","sources":["../src/browser-guard.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,CAAA"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Browser guard — `@molecule/api-payments-stripe` is SERVER-ONLY.
3
+ *
4
+ * Generated by scripts/gen-browser-guards.mjs (workspace root) — edit THAT, not this.
5
+ * Evaluating a server package in a browser bundle is always an import-graph mistake
6
+ * (node APIs, secrets); without this guard it surfaces as a cryptic downstream crash
7
+ * ("Buffer is not defined") far from the culprit. Throwing here names the package and
8
+ * the fix at the exact moment the client bundle evaluates it. jsdom tests and SSR are
9
+ * unaffected: the throw requires browser globals AND the absence of a node runtime.
10
+ */
11
+ const g = globalThis;
12
+ if (g.window !== undefined && g.document !== undefined && !g.process?.versions?.node) {
13
+ throw new Error('@molecule/api-payments-stripe is SERVER-ONLY: it was bundled into browser/client code. Import it only ' +
14
+ 'from server code (a server route/function or your API), or dynamic-import it inside ' +
15
+ 'the server handler — never from components or shared client modules, and never ' +
16
+ 'polyfill Buffer/process to silence this.');
17
+ }
18
+ export {};
19
+ //# sourceMappingURL=browser-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-guard.js","sourceRoot":"","sources":["../src/browser-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,GAAG,UAIT,CAAA;AACD,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACrF,MAAM,IAAI,KAAK,CACb,wGAAwG;QACtG,sFAAsF;QACtF,iFAAiF;QACjF,0CAA0C,CAC7C,CAAA;AACH,CAAC"}