@better-auth/stripe 1.7.0-beta.1 → 1.7.0-beta.10
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/client.d.mts
CHANGED
package/dist/client.mjs
CHANGED
|
@@ -341,21 +341,24 @@ type SubscriptionOptions = {
|
|
|
341
341
|
plan: StripePlan;
|
|
342
342
|
}, ctx: GenericEndpointContext) => Promise<void>) | undefined;
|
|
343
343
|
/**
|
|
344
|
-
* A callback to run
|
|
344
|
+
* A callback to run on every subscription update webhook. Use `stripeSubscription`
|
|
345
|
+
* to read fields that are not persisted in the local subscription row.
|
|
345
346
|
* @returns
|
|
346
347
|
*/
|
|
347
348
|
onSubscriptionUpdate?: ((data: {
|
|
348
349
|
event: Stripe.Event;
|
|
350
|
+
stripeSubscription: Stripe.Subscription;
|
|
349
351
|
subscription: Subscription;
|
|
350
352
|
}) => Promise<void>) | undefined;
|
|
351
353
|
/**
|
|
352
|
-
* A callback to run
|
|
354
|
+
* A callback to run once when a subscription transitions into a pending-cancel state
|
|
355
|
+
* (e.g. `cancel_at_period_end` or a scheduled `cancel_at`).
|
|
353
356
|
* @returns
|
|
354
357
|
*/
|
|
355
358
|
onSubscriptionCancel?: ((data: {
|
|
356
|
-
event
|
|
357
|
-
subscription: Subscription;
|
|
359
|
+
event: Stripe.Event;
|
|
358
360
|
stripeSubscription: Stripe.Subscription;
|
|
361
|
+
subscription: Subscription;
|
|
359
362
|
cancellationDetails?: Stripe.Subscription.CancellationDetails | null;
|
|
360
363
|
}) => Promise<void>) | undefined;
|
|
361
364
|
/**
|
|
@@ -573,6 +576,8 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
|
|
|
573
576
|
}>)[];
|
|
574
577
|
}>) => Promise<{
|
|
575
578
|
session: StripeCtxSession;
|
|
579
|
+
}>) | ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<{
|
|
580
|
+
referenceId: string;
|
|
576
581
|
}>) | ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<void>))[];
|
|
577
582
|
}, {
|
|
578
583
|
url: string;
|
|
@@ -634,6 +639,8 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
|
|
|
634
639
|
}>)[];
|
|
635
640
|
}>) => Promise<{
|
|
636
641
|
session: StripeCtxSession;
|
|
642
|
+
}>) | ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<{
|
|
643
|
+
referenceId: string;
|
|
637
644
|
}>) | ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<void>))[];
|
|
638
645
|
}, {
|
|
639
646
|
url: string;
|
|
@@ -680,7 +687,9 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
|
|
|
680
687
|
}>)[];
|
|
681
688
|
}>) => Promise<{
|
|
682
689
|
session: StripeCtxSession;
|
|
683
|
-
}>) | ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<
|
|
690
|
+
}>) | ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<{
|
|
691
|
+
referenceId: string;
|
|
692
|
+
}>))[];
|
|
684
693
|
}, Stripe.Response<Stripe.Subscription>>;
|
|
685
694
|
listActiveSubscriptions: better_call0.StrictEndpoint<"/subscription/list", {
|
|
686
695
|
method: "GET";
|
|
@@ -722,7 +731,9 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
|
|
|
722
731
|
}>)[];
|
|
723
732
|
}>) => Promise<{
|
|
724
733
|
session: StripeCtxSession;
|
|
725
|
-
}>) | ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<
|
|
734
|
+
}>) | ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<{
|
|
735
|
+
referenceId: string;
|
|
736
|
+
}>))[];
|
|
726
737
|
}, {
|
|
727
738
|
limits: Record<string, unknown> | undefined;
|
|
728
739
|
priceId: string | undefined;
|
|
@@ -798,6 +809,8 @@ declare const stripe: <O extends StripeOptions>(options: O) => {
|
|
|
798
809
|
}>)[];
|
|
799
810
|
}>) => Promise<{
|
|
800
811
|
session: StripeCtxSession;
|
|
812
|
+
}>) | ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<{
|
|
813
|
+
referenceId: string;
|
|
801
814
|
}>) | ((inputContext: better_call0.MiddlewareInputContext<better_call0.MiddlewareOptions>) => Promise<void>))[];
|
|
802
815
|
}, {
|
|
803
816
|
url: string;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as CheckoutSessionLocale, c as StripeOptions, d as SubscriptionOptions, f as WithActiveOrganizationId, i as CheckoutSessionLineItem, l as StripePlan, n as stripe, o as CustomerType, p as WithStripeCustomerId, r as AuthorizeReferenceAction, s as StripeCtxSession, t as StripePlugin, u as Subscription } from "./index-
|
|
1
|
+
import { a as CheckoutSessionLocale, c as StripeOptions, d as SubscriptionOptions, f as WithActiveOrganizationId, i as CheckoutSessionLineItem, l as StripePlan, n as stripe, o as CustomerType, p as WithStripeCustomerId, r as AuthorizeReferenceAction, s as StripeCtxSession, t as StripePlugin, u as Subscription } from "./index-XU8GMPhh.mjs";
|
|
2
2
|
export { AuthorizeReferenceAction, CheckoutSessionLineItem, CheckoutSessionLocale, CustomerType, StripeCtxSession, StripeOptions, StripePlan, StripePlugin, Subscription, SubscriptionOptions, WithActiveOrganizationId, WithStripeCustomerId, stripe };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as STRIPE_ERROR_CODES, t as PACKAGE_VERSION } from "./version-
|
|
1
|
+
import { n as STRIPE_ERROR_CODES, t as PACKAGE_VERSION } from "./version-Cup6oezK.mjs";
|
|
2
2
|
import { APIError, HIDE_METADATA } from "better-auth";
|
|
3
3
|
import { defu } from "defu";
|
|
4
4
|
import { createAuthEndpoint, createAuthMiddleware } from "@better-auth/core/api";
|
|
@@ -91,13 +91,13 @@ function isStripePendingCancel(stripeSub) {
|
|
|
91
91
|
}
|
|
92
92
|
/**
|
|
93
93
|
* Escapes a value for use in Stripe search queries.
|
|
94
|
-
* Stripe search query uses
|
|
95
|
-
*
|
|
94
|
+
* Stripe search query uses backslash escaping inside double-quoted
|
|
95
|
+
* string values, so literal backslashes must be escaped before quotes.
|
|
96
96
|
*
|
|
97
97
|
* @see https://docs.stripe.com/search#search-query-language
|
|
98
98
|
*/
|
|
99
99
|
function escapeStripeSearchValue(value) {
|
|
100
|
-
return value.
|
|
100
|
+
return value.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"");
|
|
101
101
|
}
|
|
102
102
|
/**
|
|
103
103
|
* Resolve the quantity for a subscription by checking the seat item first,
|
|
@@ -234,13 +234,13 @@ async function onCheckoutSessionCompleted(ctx, options, event) {
|
|
|
234
234
|
async function onSubscriptionCreated(ctx, options, event) {
|
|
235
235
|
try {
|
|
236
236
|
if (!options.subscription?.enabled) return;
|
|
237
|
-
const
|
|
238
|
-
const stripeCustomerId =
|
|
237
|
+
const stripeSubscriptionCreated = event.data.object;
|
|
238
|
+
const stripeCustomerId = stripeSubscriptionCreated.customer?.toString();
|
|
239
239
|
if (!stripeCustomerId) {
|
|
240
240
|
ctx.context.logger.warn(`Stripe webhook warning: customer.subscription.created event received without customer ID`);
|
|
241
241
|
return;
|
|
242
242
|
}
|
|
243
|
-
const { subscriptionId } = subscriptionMetadata.get(
|
|
243
|
+
const { subscriptionId } = subscriptionMetadata.get(stripeSubscriptionCreated.metadata);
|
|
244
244
|
const existingSubscription = await ctx.context.adapter.findOne({
|
|
245
245
|
model: "subscription",
|
|
246
246
|
where: subscriptionId ? [{
|
|
@@ -248,7 +248,7 @@ async function onSubscriptionCreated(ctx, options, event) {
|
|
|
248
248
|
value: subscriptionId
|
|
249
249
|
}] : [{
|
|
250
250
|
field: "stripeSubscriptionId",
|
|
251
|
-
value:
|
|
251
|
+
value: stripeSubscriptionCreated.id
|
|
252
252
|
}]
|
|
253
253
|
});
|
|
254
254
|
if (existingSubscription) {
|
|
@@ -261,9 +261,9 @@ async function onSubscriptionCreated(ctx, options, event) {
|
|
|
261
261
|
return;
|
|
262
262
|
}
|
|
263
263
|
const { referenceId, customerType } = reference;
|
|
264
|
-
const resolved = await resolvePlanItem(options,
|
|
264
|
+
const resolved = await resolvePlanItem(options, stripeSubscriptionCreated.items.data);
|
|
265
265
|
if (!resolved) {
|
|
266
|
-
ctx.context.logger.warn(`Stripe webhook warning: Subscription ${
|
|
266
|
+
ctx.context.logger.warn(`Stripe webhook warning: Subscription ${stripeSubscriptionCreated.id} has no items matching a configured plan`);
|
|
267
267
|
return;
|
|
268
268
|
}
|
|
269
269
|
const { item: subscriptionItem, plan } = resolved;
|
|
@@ -271,12 +271,12 @@ async function onSubscriptionCreated(ctx, options, event) {
|
|
|
271
271
|
ctx.context.logger.warn(`Stripe webhook warning: No matching plan found for priceId: ${subscriptionItem.price.id}`);
|
|
272
272
|
return;
|
|
273
273
|
}
|
|
274
|
-
const seats = resolveQuantity(
|
|
274
|
+
const seats = resolveQuantity(stripeSubscriptionCreated.items.data, subscriptionItem, plan.seatPriceId);
|
|
275
275
|
const periodStart = /* @__PURE__ */ new Date(subscriptionItem.current_period_start * 1e3);
|
|
276
276
|
const periodEnd = /* @__PURE__ */ new Date(subscriptionItem.current_period_end * 1e3);
|
|
277
|
-
const trial =
|
|
278
|
-
trialStart: /* @__PURE__ */ new Date(
|
|
279
|
-
trialEnd: /* @__PURE__ */ new Date(
|
|
277
|
+
const trial = stripeSubscriptionCreated.trial_start && stripeSubscriptionCreated.trial_end ? {
|
|
278
|
+
trialStart: /* @__PURE__ */ new Date(stripeSubscriptionCreated.trial_start * 1e3),
|
|
279
|
+
trialEnd: /* @__PURE__ */ new Date(stripeSubscriptionCreated.trial_end * 1e3)
|
|
280
280
|
} : {};
|
|
281
281
|
const newSubscription = await ctx.context.adapter.create({
|
|
282
282
|
model: "subscription",
|
|
@@ -285,8 +285,8 @@ async function onSubscriptionCreated(ctx, options, event) {
|
|
|
285
285
|
...plan.limits ? { limits: plan.limits } : {},
|
|
286
286
|
referenceId,
|
|
287
287
|
stripeCustomerId,
|
|
288
|
-
stripeSubscriptionId:
|
|
289
|
-
status:
|
|
288
|
+
stripeSubscriptionId: stripeSubscriptionCreated.id,
|
|
289
|
+
status: stripeSubscriptionCreated.status,
|
|
290
290
|
plan: plan.name.toLowerCase(),
|
|
291
291
|
periodStart,
|
|
292
292
|
periodEnd,
|
|
@@ -294,11 +294,11 @@ async function onSubscriptionCreated(ctx, options, event) {
|
|
|
294
294
|
billingInterval: subscriptionItem.price.recurring?.interval
|
|
295
295
|
}
|
|
296
296
|
});
|
|
297
|
-
ctx.context.logger.info(`Stripe webhook: Created subscription ${
|
|
297
|
+
ctx.context.logger.info(`Stripe webhook: Created subscription ${stripeSubscriptionCreated.id} for ${customerType} ${referenceId} from dashboard`);
|
|
298
298
|
await options.subscription.onSubscriptionCreated?.({
|
|
299
299
|
event,
|
|
300
300
|
subscription: newSubscription,
|
|
301
|
-
stripeSubscription:
|
|
301
|
+
stripeSubscription: stripeSubscriptionCreated,
|
|
302
302
|
plan
|
|
303
303
|
});
|
|
304
304
|
} catch (error) {
|
|
@@ -308,15 +308,15 @@ async function onSubscriptionCreated(ctx, options, event) {
|
|
|
308
308
|
async function onSubscriptionUpdated(ctx, options, event) {
|
|
309
309
|
try {
|
|
310
310
|
if (!options.subscription?.enabled) return;
|
|
311
|
-
const
|
|
312
|
-
const resolved = await resolvePlanItem(options,
|
|
311
|
+
const stripeSubscriptionUpdated = event.data.object;
|
|
312
|
+
const resolved = await resolvePlanItem(options, stripeSubscriptionUpdated.items.data);
|
|
313
313
|
if (!resolved) {
|
|
314
|
-
ctx.context.logger.warn(`Stripe webhook warning: Subscription ${
|
|
314
|
+
ctx.context.logger.warn(`Stripe webhook warning: Subscription ${stripeSubscriptionUpdated.id} has no items matching a configured plan`);
|
|
315
315
|
return;
|
|
316
316
|
}
|
|
317
317
|
const { item: subscriptionItem, plan } = resolved;
|
|
318
|
-
const { subscriptionId } = subscriptionMetadata.get(
|
|
319
|
-
const customerId =
|
|
318
|
+
const { subscriptionId } = subscriptionMetadata.get(stripeSubscriptionUpdated.metadata);
|
|
319
|
+
const customerId = stripeSubscriptionUpdated.customer?.toString();
|
|
320
320
|
let subscription = await ctx.context.adapter.findOne({
|
|
321
321
|
model: "subscription",
|
|
322
322
|
where: subscriptionId ? [{
|
|
@@ -324,7 +324,7 @@ async function onSubscriptionUpdated(ctx, options, event) {
|
|
|
324
324
|
value: subscriptionId
|
|
325
325
|
}] : [{
|
|
326
326
|
field: "stripeSubscriptionId",
|
|
327
|
-
value:
|
|
327
|
+
value: stripeSubscriptionUpdated.id
|
|
328
328
|
}]
|
|
329
329
|
});
|
|
330
330
|
if (!subscription) {
|
|
@@ -344,12 +344,12 @@ async function onSubscriptionUpdated(ctx, options, event) {
|
|
|
344
344
|
subscription = activeSub;
|
|
345
345
|
} else subscription = subs[0];
|
|
346
346
|
}
|
|
347
|
-
const seats = plan ? resolveQuantity(
|
|
348
|
-
const trial =
|
|
349
|
-
trialStart: /* @__PURE__ */ new Date(
|
|
350
|
-
trialEnd: /* @__PURE__ */ new Date(
|
|
347
|
+
const seats = plan ? resolveQuantity(stripeSubscriptionUpdated.items.data, subscriptionItem, plan.seatPriceId) : subscriptionItem.quantity;
|
|
348
|
+
const trial = stripeSubscriptionUpdated.trial_start && stripeSubscriptionUpdated.trial_end ? {
|
|
349
|
+
trialStart: /* @__PURE__ */ new Date(stripeSubscriptionUpdated.trial_start * 1e3),
|
|
350
|
+
trialEnd: /* @__PURE__ */ new Date(stripeSubscriptionUpdated.trial_end * 1e3)
|
|
351
351
|
} : {};
|
|
352
|
-
const
|
|
352
|
+
const subscriptionUpdated = await ctx.context.adapter.update({
|
|
353
353
|
model: "subscription",
|
|
354
354
|
update: {
|
|
355
355
|
...trial,
|
|
@@ -358,36 +358,41 @@ async function onSubscriptionUpdated(ctx, options, event) {
|
|
|
358
358
|
limits: plan.limits
|
|
359
359
|
} : {},
|
|
360
360
|
updatedAt: /* @__PURE__ */ new Date(),
|
|
361
|
-
status:
|
|
361
|
+
status: stripeSubscriptionUpdated.status,
|
|
362
362
|
periodStart: /* @__PURE__ */ new Date(subscriptionItem.current_period_start * 1e3),
|
|
363
363
|
periodEnd: /* @__PURE__ */ new Date(subscriptionItem.current_period_end * 1e3),
|
|
364
|
-
cancelAtPeriodEnd:
|
|
365
|
-
cancelAt:
|
|
366
|
-
canceledAt:
|
|
367
|
-
endedAt:
|
|
364
|
+
cancelAtPeriodEnd: stripeSubscriptionUpdated.cancel_at_period_end,
|
|
365
|
+
cancelAt: stripeSubscriptionUpdated.cancel_at ? /* @__PURE__ */ new Date(stripeSubscriptionUpdated.cancel_at * 1e3) : null,
|
|
366
|
+
canceledAt: stripeSubscriptionUpdated.canceled_at ? /* @__PURE__ */ new Date(stripeSubscriptionUpdated.canceled_at * 1e3) : null,
|
|
367
|
+
endedAt: stripeSubscriptionUpdated.ended_at ? /* @__PURE__ */ new Date(stripeSubscriptionUpdated.ended_at * 1e3) : null,
|
|
368
368
|
seats,
|
|
369
|
-
stripeSubscriptionId:
|
|
369
|
+
stripeSubscriptionId: stripeSubscriptionUpdated.id,
|
|
370
370
|
billingInterval: subscriptionItem.price.recurring?.interval,
|
|
371
|
-
stripeScheduleId:
|
|
371
|
+
stripeScheduleId: stripeSubscriptionUpdated.schedule ? typeof stripeSubscriptionUpdated.schedule === "string" ? stripeSubscriptionUpdated.schedule : stripeSubscriptionUpdated.schedule.id : null
|
|
372
372
|
},
|
|
373
373
|
where: [{
|
|
374
374
|
field: "id",
|
|
375
375
|
value: subscription.id
|
|
376
376
|
}]
|
|
377
377
|
});
|
|
378
|
-
if (subscriptionUpdated
|
|
379
|
-
subscription,
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
378
|
+
if (!subscriptionUpdated) {
|
|
379
|
+
ctx.context.logger.warn(`Stripe webhook warning: Subscription ${subscription.id} update returned no row (likely deleted concurrently), skipping callbacks`);
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (stripeSubscriptionUpdated.status === "active" && isStripePendingCancel(stripeSubscriptionUpdated) && !isPendingCancel(subscription)) await options.subscription.onSubscriptionCancel?.({
|
|
383
|
+
event,
|
|
384
|
+
subscription: subscriptionUpdated,
|
|
385
|
+
stripeSubscription: stripeSubscriptionUpdated,
|
|
386
|
+
cancellationDetails: stripeSubscriptionUpdated.cancellation_details || void 0
|
|
383
387
|
});
|
|
384
388
|
await options.subscription.onSubscriptionUpdate?.({
|
|
385
389
|
event,
|
|
386
|
-
subscription:
|
|
390
|
+
subscription: subscriptionUpdated,
|
|
391
|
+
stripeSubscription: stripeSubscriptionUpdated
|
|
387
392
|
});
|
|
388
393
|
if (plan) {
|
|
389
|
-
if (
|
|
390
|
-
if (
|
|
394
|
+
if (stripeSubscriptionUpdated.status === "active" && subscription.status === "trialing" && plan.freeTrial?.onTrialEnd) await plan.freeTrial.onTrialEnd({ subscription: subscriptionUpdated }, ctx);
|
|
395
|
+
if (stripeSubscriptionUpdated.status === "incomplete_expired" && subscription.status === "trialing" && plan.freeTrial?.onTrialExpired) await plan.freeTrial.onTrialExpired(subscriptionUpdated, ctx);
|
|
391
396
|
}
|
|
392
397
|
} catch (error) {
|
|
393
398
|
ctx.context.logger.error(`Stripe webhook failed. Error: ${error}`);
|
|
@@ -396,8 +401,8 @@ async function onSubscriptionUpdated(ctx, options, event) {
|
|
|
396
401
|
async function onSubscriptionDeleted(ctx, options, event) {
|
|
397
402
|
if (!options.subscription?.enabled) return;
|
|
398
403
|
try {
|
|
399
|
-
const
|
|
400
|
-
const subscriptionId =
|
|
404
|
+
const stripeSubscriptionDeleted = event.data.object;
|
|
405
|
+
const subscriptionId = stripeSubscriptionDeleted.id;
|
|
401
406
|
const subscription = await ctx.context.adapter.findOne({
|
|
402
407
|
model: "subscription",
|
|
403
408
|
where: [{
|
|
@@ -406,11 +411,11 @@ async function onSubscriptionDeleted(ctx, options, event) {
|
|
|
406
411
|
}]
|
|
407
412
|
});
|
|
408
413
|
if (subscription) {
|
|
409
|
-
const trial =
|
|
410
|
-
trialStart: /* @__PURE__ */ new Date(
|
|
411
|
-
trialEnd: /* @__PURE__ */ new Date(
|
|
414
|
+
const trial = stripeSubscriptionDeleted.trial_start && stripeSubscriptionDeleted.trial_end ? {
|
|
415
|
+
trialStart: /* @__PURE__ */ new Date(stripeSubscriptionDeleted.trial_start * 1e3),
|
|
416
|
+
trialEnd: /* @__PURE__ */ new Date(stripeSubscriptionDeleted.trial_end * 1e3)
|
|
412
417
|
} : {};
|
|
413
|
-
await ctx.context.adapter.update({
|
|
418
|
+
const subscriptionUpdated = await ctx.context.adapter.update({
|
|
414
419
|
model: "subscription",
|
|
415
420
|
where: [{
|
|
416
421
|
field: "id",
|
|
@@ -420,17 +425,21 @@ async function onSubscriptionDeleted(ctx, options, event) {
|
|
|
420
425
|
...trial,
|
|
421
426
|
status: "canceled",
|
|
422
427
|
updatedAt: /* @__PURE__ */ new Date(),
|
|
423
|
-
cancelAtPeriodEnd:
|
|
424
|
-
cancelAt:
|
|
425
|
-
canceledAt:
|
|
426
|
-
endedAt:
|
|
428
|
+
cancelAtPeriodEnd: stripeSubscriptionDeleted.cancel_at_period_end,
|
|
429
|
+
cancelAt: stripeSubscriptionDeleted.cancel_at ? /* @__PURE__ */ new Date(stripeSubscriptionDeleted.cancel_at * 1e3) : null,
|
|
430
|
+
canceledAt: stripeSubscriptionDeleted.canceled_at ? /* @__PURE__ */ new Date(stripeSubscriptionDeleted.canceled_at * 1e3) : null,
|
|
431
|
+
endedAt: stripeSubscriptionDeleted.ended_at ? /* @__PURE__ */ new Date(stripeSubscriptionDeleted.ended_at * 1e3) : null,
|
|
427
432
|
stripeScheduleId: null
|
|
428
433
|
}
|
|
429
434
|
});
|
|
435
|
+
if (!subscriptionUpdated) {
|
|
436
|
+
ctx.context.logger.warn(`Stripe webhook warning: Subscription ${subscription.id} update returned no row (likely deleted concurrently), skipping callbacks`);
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
430
439
|
await options.subscription.onSubscriptionDeleted?.({
|
|
431
440
|
event,
|
|
432
|
-
stripeSubscription:
|
|
433
|
-
subscription
|
|
441
|
+
stripeSubscription: stripeSubscriptionDeleted,
|
|
442
|
+
subscription: subscriptionUpdated
|
|
434
443
|
});
|
|
435
444
|
} else ctx.context.logger.warn(`Stripe webhook error: Subscription not found for subscriptionId: ${subscriptionId}`);
|
|
436
445
|
} catch (error) {
|
|
@@ -442,12 +451,14 @@ async function onSubscriptionDeleted(ctx, options, event) {
|
|
|
442
451
|
const stripeSessionMiddleware = createAuthMiddleware({ use: [sessionMiddleware] }, async (ctx) => {
|
|
443
452
|
return { session: ctx.context.session };
|
|
444
453
|
});
|
|
445
|
-
const referenceMiddleware = (
|
|
454
|
+
const referenceMiddleware = (options, action) => createAuthMiddleware(async (ctx) => {
|
|
455
|
+
const subscriptionOptions = options.subscription;
|
|
446
456
|
const ctxSession = ctx.context.session;
|
|
447
457
|
if (!ctxSession) throw APIError$1.from("UNAUTHORIZED", STRIPE_ERROR_CODES.UNAUTHORIZED);
|
|
448
458
|
const customerType = ctx.body?.customerType || ctx.query?.customerType;
|
|
449
459
|
const explicitReferenceId = ctx.body?.referenceId || ctx.query?.referenceId;
|
|
450
460
|
if (customerType === "organization") {
|
|
461
|
+
if (!options.organization?.enabled) throw APIError$1.from("BAD_REQUEST", STRIPE_ERROR_CODES.ORGANIZATION_SUBSCRIPTION_NOT_ENABLED);
|
|
451
462
|
if (!subscriptionOptions.authorizeReference) {
|
|
452
463
|
ctx.context.logger.error(`Organization subscriptions require authorizeReference to be defined in your stripe plugin config.`);
|
|
453
464
|
throw APIError$1.from("BAD_REQUEST", STRIPE_ERROR_CODES.AUTHORIZE_REFERENCE_REQUIRED);
|
|
@@ -460,10 +471,10 @@ const referenceMiddleware = (subscriptionOptions, action) => createAuthMiddlewar
|
|
|
460
471
|
referenceId,
|
|
461
472
|
action
|
|
462
473
|
}, ctx)) throw APIError$1.from("UNAUTHORIZED", STRIPE_ERROR_CODES.UNAUTHORIZED);
|
|
463
|
-
return;
|
|
474
|
+
return { referenceId };
|
|
464
475
|
}
|
|
465
|
-
|
|
466
|
-
if (explicitReferenceId === ctxSession.user.id) return;
|
|
476
|
+
const referenceId = explicitReferenceId || ctxSession.user.id;
|
|
477
|
+
if (!explicitReferenceId || explicitReferenceId === ctxSession.user.id) return { referenceId };
|
|
467
478
|
if (!subscriptionOptions.authorizeReference) {
|
|
468
479
|
ctx.context.logger.error(`Passing referenceId into a subscription action isn't allowed if subscription.authorizeReference isn't defined in your stripe plugin config.`);
|
|
469
480
|
throw APIError$1.from("BAD_REQUEST", STRIPE_ERROR_CODES.REFERENCE_ID_NOT_ALLOWED);
|
|
@@ -471,9 +482,10 @@ const referenceMiddleware = (subscriptionOptions, action) => createAuthMiddlewar
|
|
|
471
482
|
if (!await subscriptionOptions.authorizeReference({
|
|
472
483
|
user: ctxSession.user,
|
|
473
484
|
session: ctxSession.session,
|
|
474
|
-
referenceId
|
|
485
|
+
referenceId,
|
|
475
486
|
action
|
|
476
487
|
}, ctx)) throw APIError$1.from("UNAUTHORIZED", STRIPE_ERROR_CODES.UNAUTHORIZED);
|
|
488
|
+
return { referenceId };
|
|
477
489
|
});
|
|
478
490
|
//#endregion
|
|
479
491
|
//#region src/routes.ts
|
|
@@ -511,19 +523,21 @@ function getUrl(ctx, url) {
|
|
|
511
523
|
return `${ctx.context.options.baseURL}${url.startsWith("/") ? url : `/${url}`}`;
|
|
512
524
|
}
|
|
513
525
|
/**
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
* - `organization`: uses activeOrganizationId from session
|
|
526
|
+
* Retrieve the subscription a row points to, or `null` if it no longer exists
|
|
527
|
+
* (`resource_missing`) so callers can treat the row as stale.
|
|
517
528
|
* @internal
|
|
518
529
|
*/
|
|
519
|
-
function
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
return
|
|
525
|
-
|
|
526
|
-
|
|
530
|
+
async function retrieveStripeSubscription(client, ctx, stripeSubscriptionId) {
|
|
531
|
+
return await client.subscriptions.retrieve(stripeSubscriptionId).catch((e) => {
|
|
532
|
+
/**
|
|
533
|
+
* @see https://docs.stripe.com/error-codes
|
|
534
|
+
*/
|
|
535
|
+
if (e?.code === "resource_missing") return null;
|
|
536
|
+
throw ctx.error("BAD_REQUEST", {
|
|
537
|
+
code: e.code,
|
|
538
|
+
message: e.message
|
|
539
|
+
});
|
|
540
|
+
});
|
|
527
541
|
}
|
|
528
542
|
const upgradeSubscriptionBodySchema = z.object({
|
|
529
543
|
plan: z.string().meta({ description: "The name of the plan to upgrade to. Eg: \"pro\"" }),
|
|
@@ -566,15 +580,19 @@ const upgradeSubscription = (options) => {
|
|
|
566
580
|
metadata: { openapi: { operationId: "upgradeSubscription" } },
|
|
567
581
|
use: [
|
|
568
582
|
stripeSessionMiddleware,
|
|
569
|
-
referenceMiddleware(
|
|
583
|
+
referenceMiddleware(options, "upgrade-subscription"),
|
|
570
584
|
originCheck((c) => {
|
|
571
|
-
return [
|
|
585
|
+
return [
|
|
586
|
+
c.body.successUrl,
|
|
587
|
+
c.body.cancelUrl,
|
|
588
|
+
c.body.returnUrl
|
|
589
|
+
];
|
|
572
590
|
})
|
|
573
591
|
]
|
|
574
592
|
}, async (ctx) => {
|
|
575
593
|
const { user, session } = ctx.context.session;
|
|
576
594
|
const customerType = ctx.body.customerType || "user";
|
|
577
|
-
const referenceId = ctx.
|
|
595
|
+
const referenceId = ctx.context.referenceId;
|
|
578
596
|
if (!user.emailVerified && subscriptionOptions.requireEmailVerification) throw APIError$1.from("BAD_REQUEST", STRIPE_ERROR_CODES.EMAIL_VERIFICATION_REQUIRED);
|
|
579
597
|
const plan = await getPlanByName(options, ctx.body.plan);
|
|
580
598
|
if (!plan) throw APIError$1.from("BAD_REQUEST", STRIPE_ERROR_CODES.SUBSCRIPTION_PLAN_NOT_FOUND);
|
|
@@ -666,6 +684,10 @@ const upgradeSubscription = (options) => {
|
|
|
666
684
|
break;
|
|
667
685
|
}
|
|
668
686
|
}
|
|
687
|
+
if (stripeCustomer) {
|
|
688
|
+
const ownerId = customerMetadata.get(stripeCustomer.metadata).userId;
|
|
689
|
+
if (!!ownerId && ownerId !== user.id || !user.emailVerified) stripeCustomer = void 0;
|
|
690
|
+
}
|
|
669
691
|
if (!stripeCustomer) stripeCustomer = await client.customers.create({
|
|
670
692
|
email: user.email,
|
|
671
693
|
name: user.name,
|
|
@@ -983,16 +1005,23 @@ const upgradeSubscription = (options) => {
|
|
|
983
1005
|
})).some((s) => {
|
|
984
1006
|
return !!(s.trialStart || s.trialEnd) || s.status === "trialing";
|
|
985
1007
|
}) && plan.freeTrial ? { trial_period_days: plan.freeTrial.days } : void 0;
|
|
1008
|
+
const { mode: _mode, customer: _customer, customer_email: _customer_email, success_url: _success_url, cancel_url: _cancel_url, line_items: _line_items, client_reference_id: _client_reference_id, ...additionalParams } = params?.params ?? {};
|
|
986
1009
|
const response = {
|
|
987
1010
|
...await client.checkout.sessions.create({
|
|
1011
|
+
...additionalParams,
|
|
1012
|
+
mode: "subscription",
|
|
988
1013
|
...customerId ? {
|
|
989
1014
|
customer: customerId,
|
|
990
|
-
|
|
1015
|
+
customer_email: void 0,
|
|
1016
|
+
customer_update: additionalParams.customer_update ?? (customerType !== "user" ? { address: "auto" } : {
|
|
991
1017
|
name: "auto",
|
|
992
1018
|
address: "auto"
|
|
993
|
-
}
|
|
994
|
-
} : {
|
|
995
|
-
|
|
1019
|
+
})
|
|
1020
|
+
} : {
|
|
1021
|
+
customer: void 0,
|
|
1022
|
+
customer_email: user.email
|
|
1023
|
+
},
|
|
1024
|
+
locale: ctx.body.locale ?? additionalParams.locale,
|
|
996
1025
|
success_url: getUrl(ctx, `${ctx.context.baseURL}/subscription/success?callbackURL=${encodeURIComponent(ctx.body.successUrl)}&checkoutSessionId={CHECKOUT_SESSION_ID}`),
|
|
997
1026
|
cancel_url: getUrl(ctx, ctx.body.cancelUrl),
|
|
998
1027
|
line_items: [
|
|
@@ -1006,22 +1035,21 @@ const upgradeSubscription = (options) => {
|
|
|
1006
1035
|
}] : [],
|
|
1007
1036
|
...plan.lineItems ?? []
|
|
1008
1037
|
],
|
|
1038
|
+
client_reference_id: referenceId,
|
|
1009
1039
|
subscription_data: {
|
|
1010
1040
|
...freeTrial,
|
|
1041
|
+
...additionalParams.subscription_data,
|
|
1011
1042
|
metadata: subscriptionMetadata.set({
|
|
1012
1043
|
userId: user.id,
|
|
1013
1044
|
subscriptionId: subscription.id,
|
|
1014
1045
|
referenceId
|
|
1015
|
-
}, ctx.body.metadata,
|
|
1046
|
+
}, ctx.body.metadata, additionalParams.subscription_data?.metadata)
|
|
1016
1047
|
},
|
|
1017
|
-
mode: "subscription",
|
|
1018
|
-
client_reference_id: referenceId,
|
|
1019
|
-
...params?.params,
|
|
1020
1048
|
metadata: subscriptionMetadata.set({
|
|
1021
1049
|
userId: user.id,
|
|
1022
1050
|
subscriptionId: subscription.id,
|
|
1023
1051
|
referenceId
|
|
1024
|
-
}, ctx.body.metadata,
|
|
1052
|
+
}, ctx.body.metadata, additionalParams.metadata)
|
|
1025
1053
|
}, params?.options).catch(async (e) => {
|
|
1026
1054
|
throw ctx.error("BAD_REQUEST", {
|
|
1027
1055
|
message: e.message,
|
|
@@ -1057,19 +1085,17 @@ const cancelSubscriptionBodySchema = z.object({
|
|
|
1057
1085
|
*/
|
|
1058
1086
|
const cancelSubscription = (options) => {
|
|
1059
1087
|
const client = options.stripeClient;
|
|
1060
|
-
const subscriptionOptions = options.subscription;
|
|
1061
1088
|
return createAuthEndpoint("/subscription/cancel", {
|
|
1062
1089
|
method: "POST",
|
|
1063
1090
|
body: cancelSubscriptionBodySchema,
|
|
1064
1091
|
metadata: { openapi: { operationId: "cancelSubscription" } },
|
|
1065
1092
|
use: [
|
|
1066
1093
|
stripeSessionMiddleware,
|
|
1067
|
-
referenceMiddleware(
|
|
1094
|
+
referenceMiddleware(options, "cancel-subscription"),
|
|
1068
1095
|
originCheck((ctx) => ctx.body.returnUrl)
|
|
1069
1096
|
]
|
|
1070
1097
|
}, async (ctx) => {
|
|
1071
|
-
const
|
|
1072
|
-
const referenceId = ctx.body.referenceId || getReferenceId(ctx.context.session, customerType, options);
|
|
1098
|
+
const referenceId = ctx.context.referenceId;
|
|
1073
1099
|
let subscription = ctx.body.subscriptionId ? await ctx.context.adapter.findOne({
|
|
1074
1100
|
model: "subscription",
|
|
1075
1101
|
where: [{
|
|
@@ -1085,23 +1111,18 @@ const cancelSubscription = (options) => {
|
|
|
1085
1111
|
}).then((subs) => subs.find((sub) => isActiveOrTrialing(sub)));
|
|
1086
1112
|
if (ctx.body.subscriptionId && subscription && subscription.referenceId !== referenceId) subscription = void 0;
|
|
1087
1113
|
if (!subscription || !subscription.stripeCustomerId) throw APIError$1.from("BAD_REQUEST", STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND);
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
* from the database. This is a rare case and should not happen.
|
|
1093
|
-
*/
|
|
1094
|
-
await ctx.context.adapter.deleteMany({
|
|
1114
|
+
if (!subscription.stripeSubscriptionId) throw APIError$1.from("BAD_REQUEST", STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND);
|
|
1115
|
+
const activeSubscription = await retrieveStripeSubscription(client, ctx, subscription.stripeSubscriptionId);
|
|
1116
|
+
if (!activeSubscription || !isActiveOrTrialing(activeSubscription)) {
|
|
1117
|
+
await ctx.context.adapter.delete({
|
|
1095
1118
|
model: "subscription",
|
|
1096
1119
|
where: [{
|
|
1097
|
-
field: "
|
|
1098
|
-
value:
|
|
1120
|
+
field: "id",
|
|
1121
|
+
value: subscription.id
|
|
1099
1122
|
}]
|
|
1100
1123
|
});
|
|
1101
1124
|
throw APIError$1.from("BAD_REQUEST", STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND);
|
|
1102
1125
|
}
|
|
1103
|
-
const activeSubscription = activeSubscriptions.find((sub) => sub.id === subscription.stripeSubscriptionId);
|
|
1104
|
-
if (!activeSubscription) throw APIError$1.from("BAD_REQUEST", STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND);
|
|
1105
1126
|
const { url } = await client.billingPortal.sessions.create({
|
|
1106
1127
|
customer: subscription.stripeCustomerId,
|
|
1107
1128
|
return_url: getUrl(ctx, ctx.body?.returnUrl || "/"),
|
|
@@ -1149,15 +1170,13 @@ const restoreSubscriptionBodySchema = z.object({
|
|
|
1149
1170
|
});
|
|
1150
1171
|
const restoreSubscription = (options) => {
|
|
1151
1172
|
const client = options.stripeClient;
|
|
1152
|
-
const subscriptionOptions = options.subscription;
|
|
1153
1173
|
return createAuthEndpoint("/subscription/restore", {
|
|
1154
1174
|
method: "POST",
|
|
1155
1175
|
body: restoreSubscriptionBodySchema,
|
|
1156
1176
|
metadata: { openapi: { operationId: "restoreSubscription" } },
|
|
1157
|
-
use: [stripeSessionMiddleware, referenceMiddleware(
|
|
1177
|
+
use: [stripeSessionMiddleware, referenceMiddleware(options, "restore-subscription")]
|
|
1158
1178
|
}, async (ctx) => {
|
|
1159
|
-
const
|
|
1160
|
-
const referenceId = ctx.body.referenceId || getReferenceId(ctx.context.session, customerType, options);
|
|
1179
|
+
const referenceId = ctx.context.referenceId;
|
|
1161
1180
|
let subscription = ctx.body.subscriptionId ? await ctx.context.adapter.findOne({
|
|
1162
1181
|
model: "subscription",
|
|
1163
1182
|
where: [{
|
|
@@ -1204,8 +1223,9 @@ const restoreSubscription = (options) => {
|
|
|
1204
1223
|
const releasedSub = await client.subscriptions.retrieve(subscription.stripeSubscriptionId);
|
|
1205
1224
|
return ctx.json(releasedSub);
|
|
1206
1225
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1226
|
+
if (!subscription.stripeSubscriptionId) throw APIError$1.from("BAD_REQUEST", STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND);
|
|
1227
|
+
const activeSubscription = await retrieveStripeSubscription(client, ctx, subscription.stripeSubscriptionId);
|
|
1228
|
+
if (!activeSubscription || !isActiveOrTrialing(activeSubscription)) throw APIError$1.from("BAD_REQUEST", STRIPE_ERROR_CODES.SUBSCRIPTION_NOT_FOUND);
|
|
1209
1229
|
const updateParams = {};
|
|
1210
1230
|
if (activeSubscription.cancel_at) updateParams.cancel_at = "";
|
|
1211
1231
|
else if (activeSubscription.cancel_at_period_end) updateParams.cancel_at_period_end = false;
|
|
@@ -1251,15 +1271,13 @@ const listActiveSubscriptionsQuerySchema = z.optional(z.object({
|
|
|
1251
1271
|
* @see [Read our docs to learn more.](https://better-auth.com/docs/plugins/stripe#api-method-subscription-list)
|
|
1252
1272
|
*/
|
|
1253
1273
|
const listActiveSubscriptions = (options) => {
|
|
1254
|
-
const subscriptionOptions = options.subscription;
|
|
1255
1274
|
return createAuthEndpoint("/subscription/list", {
|
|
1256
1275
|
method: "GET",
|
|
1257
1276
|
query: listActiveSubscriptionsQuerySchema,
|
|
1258
1277
|
metadata: { openapi: { operationId: "listActiveSubscriptions" } },
|
|
1259
|
-
use: [stripeSessionMiddleware, referenceMiddleware(
|
|
1278
|
+
use: [stripeSessionMiddleware, referenceMiddleware(options, "list-subscription")]
|
|
1260
1279
|
}, async (ctx) => {
|
|
1261
|
-
const
|
|
1262
|
-
const referenceId = ctx.query?.referenceId || getReferenceId(ctx.context.session, customerType, options);
|
|
1280
|
+
const referenceId = ctx.context.referenceId;
|
|
1263
1281
|
const subscriptions = await ctx.context.adapter.findMany({
|
|
1264
1282
|
model: "subscription",
|
|
1265
1283
|
where: [{
|
|
@@ -1292,8 +1310,7 @@ const subscriptionSuccess = (options) => {
|
|
|
1292
1310
|
use: [originCheck((ctx) => ctx.query.callbackURL)]
|
|
1293
1311
|
}, async (ctx) => {
|
|
1294
1312
|
let callbackURL = ctx.query?.callbackURL || "/";
|
|
1295
|
-
|
|
1296
|
-
if (!session) throw ctx.redirect(getUrl(ctx, callbackURL));
|
|
1313
|
+
if (!await getSessionFromCtx(ctx)) throw ctx.redirect(getUrl(ctx, callbackURL));
|
|
1297
1314
|
if (!ctx.query?.checkoutSessionId) throw ctx.redirect(getUrl(ctx, callbackURL));
|
|
1298
1315
|
/**
|
|
1299
1316
|
* Replace the Stripe {CHECKOUT_SESSION_ID} template variable in callbackURL.
|
|
@@ -1322,12 +1339,9 @@ const subscriptionSuccess = (options) => {
|
|
|
1322
1339
|
throw ctx.redirect(getUrl(ctx, callbackURL));
|
|
1323
1340
|
}
|
|
1324
1341
|
if (isActiveOrTrialing(subscription)) throw ctx.redirect(getUrl(ctx, callbackURL));
|
|
1325
|
-
const
|
|
1326
|
-
if (!
|
|
1327
|
-
const stripeSubscription = await client.subscriptions.
|
|
1328
|
-
customer: customerId,
|
|
1329
|
-
status: "active"
|
|
1330
|
-
}).then((res) => res.data[0]).catch((error) => {
|
|
1342
|
+
const stripeSubscriptionId = typeof checkoutSession.subscription === "string" ? checkoutSession.subscription : checkoutSession.subscription?.id;
|
|
1343
|
+
if (!stripeSubscriptionId || checkoutSession.payment_status === "unpaid") throw ctx.redirect(getUrl(ctx, callbackURL));
|
|
1344
|
+
const stripeSubscription = await client.subscriptions.retrieve(stripeSubscriptionId).catch((error) => {
|
|
1331
1345
|
ctx.context.logger.error("Error fetching subscription from Stripe", error);
|
|
1332
1346
|
throw ctx.redirect(getUrl(ctx, callbackURL));
|
|
1333
1347
|
});
|
|
@@ -1380,20 +1394,19 @@ const createBillingPortalBodySchema = z.object({
|
|
|
1380
1394
|
});
|
|
1381
1395
|
const createBillingPortal = (options) => {
|
|
1382
1396
|
const client = options.stripeClient;
|
|
1383
|
-
const subscriptionOptions = options.subscription;
|
|
1384
1397
|
return createAuthEndpoint("/subscription/billing-portal", {
|
|
1385
1398
|
method: "POST",
|
|
1386
1399
|
body: createBillingPortalBodySchema,
|
|
1387
1400
|
metadata: { openapi: { operationId: "createBillingPortal" } },
|
|
1388
1401
|
use: [
|
|
1389
1402
|
stripeSessionMiddleware,
|
|
1390
|
-
referenceMiddleware(
|
|
1403
|
+
referenceMiddleware(options, "billing-portal"),
|
|
1391
1404
|
originCheck((ctx) => ctx.body.returnUrl)
|
|
1392
1405
|
]
|
|
1393
1406
|
}, async (ctx) => {
|
|
1394
1407
|
const { user } = ctx.context.session;
|
|
1395
1408
|
const customerType = ctx.body.customerType || "user";
|
|
1396
|
-
const referenceId = ctx.
|
|
1409
|
+
const referenceId = ctx.context.referenceId;
|
|
1397
1410
|
let customerId;
|
|
1398
1411
|
if (customerType === "organization") {
|
|
1399
1412
|
customerId = (await ctx.context.adapter.findOne({
|
|
@@ -1650,12 +1663,11 @@ const stripe = (options) => {
|
|
|
1650
1663
|
const { organization } = data;
|
|
1651
1664
|
if (!organization.stripeCustomerId) return;
|
|
1652
1665
|
try {
|
|
1653
|
-
const
|
|
1666
|
+
for await (const sub of client.subscriptions.list({
|
|
1654
1667
|
customer: organization.stripeCustomerId,
|
|
1655
1668
|
status: "all",
|
|
1656
1669
|
limit: 100
|
|
1657
|
-
});
|
|
1658
|
-
for (const sub of subscriptions.data) if (sub.status !== "canceled" && sub.status !== "incomplete" && sub.status !== "incomplete_expired") throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES.ORGANIZATION_HAS_ACTIVE_SUBSCRIPTION);
|
|
1670
|
+
})) if (sub.status !== "canceled" && sub.status !== "incomplete" && sub.status !== "incomplete_expired") throw APIError.from("BAD_REQUEST", STRIPE_ERROR_CODES.ORGANIZATION_HAS_ACTIVE_SUBSCRIPTION);
|
|
1659
1671
|
} catch (error) {
|
|
1660
1672
|
if (error instanceof APIError) throw error;
|
|
1661
1673
|
ctx.logger.error(`Failed to check organization subscriptions: ${error.message}`);
|
|
@@ -1760,6 +1772,10 @@ const stripe = (options) => {
|
|
|
1760
1772
|
break;
|
|
1761
1773
|
}
|
|
1762
1774
|
}
|
|
1775
|
+
if (stripeCustomer) {
|
|
1776
|
+
const ownerId = customerMetadata.get(stripeCustomer.metadata).userId;
|
|
1777
|
+
if (!!ownerId && ownerId !== user.id || !user.emailVerified) stripeCustomer = void 0;
|
|
1778
|
+
}
|
|
1763
1779
|
if (stripeCustomer) {
|
|
1764
1780
|
await ctx.context.internalAdapter.updateUser(user.id, { stripeCustomerId: stripeCustomer.id });
|
|
1765
1781
|
await options.onCustomerCreate?.({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth/stripe",
|
|
3
|
-
"version": "1.7.0-beta.
|
|
3
|
+
"version": "1.7.0-beta.10",
|
|
4
4
|
"description": "Stripe plugin for Better Auth",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -55,17 +55,17 @@
|
|
|
55
55
|
"zod": "^4.3.6"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"better-call": "1.3.
|
|
58
|
+
"better-call": "1.3.7",
|
|
59
59
|
"stripe": "^22.0.1",
|
|
60
60
|
"tsdown": "0.21.1",
|
|
61
|
-
"@better-auth/core": "1.7.0-beta.
|
|
62
|
-
"better-auth": "1.7.0-beta.
|
|
61
|
+
"@better-auth/core": "1.7.0-beta.10",
|
|
62
|
+
"better-auth": "1.7.0-beta.10"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"better-call": "1.3.
|
|
65
|
+
"better-call": "1.3.7",
|
|
66
66
|
"stripe": "^18 || ^19 || ^20 || ^21 || ^22",
|
|
67
|
-
"@better-auth/core": "^1.7.0-beta.
|
|
68
|
-
"better-auth": "^1.7.0-beta.
|
|
67
|
+
"@better-auth/core": "^1.7.0-beta.10",
|
|
68
|
+
"better-auth": "^1.7.0-beta.10"
|
|
69
69
|
},
|
|
70
70
|
"scripts": {
|
|
71
71
|
"build": "tsdown",
|