fix: charge immediately on subscription and read item-level period dates
All checks were successful
Deploy to Staging / Build Images (push) Successful in 3m39s
Deploy to Staging / Deploy to Staging (push) Successful in 53s
Deploy to Staging / Verify Staging (push) Successful in 9s
Deploy to Staging / Notify Staging Ready (push) Successful in 8s
Deploy to Staging / Notify Staging Failure (push) Has been skipped
All checks were successful
Deploy to Staging / Build Images (push) Successful in 3m39s
Deploy to Staging / Deploy to Staging (push) Successful in 53s
Deploy to Staging / Verify Staging (push) Successful in 9s
Deploy to Staging / Notify Staging Ready (push) Successful in 8s
Deploy to Staging / Notify Staging Failure (push) Has been skipped
Three fixes to the Stripe subscription flow: 1. Change payment_behavior from 'default_incomplete' to 'error_if_incomplete' so Stripe charges the card immediately instead of leaving the subscription in incomplete status waiting for frontend payment confirmation that never happens. 2. Read currentPeriodStart/End from subscription items instead of the top-level subscription object. Stripe moved these fields to items.data[0] in API version 2025-03-31.basil, causing epoch-zero dates (Dec 31, 1969). 3. Map Stripe 'incomplete' status to 'active' in mapStripeStatus() so it doesn't fall through to the default 'canceled' mapping. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -570,11 +570,13 @@ export class SubscriptionsService {
|
||||
}
|
||||
|
||||
// Update subscription with Stripe subscription ID
|
||||
// Period dates moved from subscription to items in API 2025-03-31.basil
|
||||
const item = stripeSubscription.items?.data?.[0];
|
||||
await this.repository.update(subscription.id, {
|
||||
stripeSubscriptionId: stripeSubscription.id,
|
||||
status: this.mapStripeStatus(stripeSubscription.status),
|
||||
currentPeriodStart: new Date(stripeSubscription.current_period_start * 1000),
|
||||
currentPeriodEnd: new Date(stripeSubscription.current_period_end * 1000),
|
||||
currentPeriodStart: new Date((item?.current_period_start ?? 0) * 1000),
|
||||
currentPeriodEnd: new Date((item?.current_period_end ?? 0) * 1000),
|
||||
});
|
||||
|
||||
// Log event
|
||||
@@ -608,11 +610,13 @@ export class SubscriptionsService {
|
||||
const tier = this.determineTierFromStripeSubscription(stripeSubscription);
|
||||
|
||||
// Update subscription
|
||||
// Period dates moved from subscription to items in API 2025-03-31.basil
|
||||
const item = stripeSubscription.items?.data?.[0];
|
||||
const updateData: UpdateSubscriptionData = {
|
||||
status: this.mapStripeStatus(stripeSubscription.status),
|
||||
tier,
|
||||
currentPeriodStart: new Date(stripeSubscription.current_period_start * 1000),
|
||||
currentPeriodEnd: new Date(stripeSubscription.current_period_end * 1000),
|
||||
currentPeriodStart: new Date((item?.current_period_start ?? 0) * 1000),
|
||||
currentPeriodEnd: new Date((item?.current_period_end ?? 0) * 1000),
|
||||
cancelAtPeriodEnd: stripeSubscription.cancel_at_period_end || false,
|
||||
};
|
||||
|
||||
@@ -849,6 +853,7 @@ export class SubscriptionsService {
|
||||
switch (stripeStatus) {
|
||||
case 'active':
|
||||
case 'trialing':
|
||||
case 'incomplete':
|
||||
return 'active';
|
||||
case 'past_due':
|
||||
return 'past_due';
|
||||
|
||||
Reference in New Issue
Block a user