#evan_api

1 messages ¡ Page 1 of 1 (latest)

loud lichenBOT
#

👋 Welcome to your new thread!

⏲️ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.

⏱️ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.

🔗 This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1310874733205520398

📝 Have more to share? Add more details, code, screenshots, videos, etc. below.

pine valley
#

this is how am creating the subscripition scheduler

const createSubscriptionScheduler = async (
  user,
  newSubscriptionPlan,
  providerSubscription,
  newProviderPlan,
  providerCouponId = null,
  dbDiscountId = null
) => {
  let scheduleId = providerSubscription.schedule
  let schedule = null
  if (!scheduleId) {
    schedule = await stripeGatewayClient.subscriptionSchedules.create({
      from_subscription: providerSubscription.id,
    })
    scheduleId = schedule.id
  }

  schedule =
    await stripeGatewayClient.subscriptionSchedules.retrieve(scheduleId)

  const defaultPhase = schedule.phases[0]

  const secondPhase = {
    items: [
      {
        price: newProviderPlan.id,
      },
    ],
    start_date: defaultPhase.end_date,
    metadata: {
      subscriptionPlanId: newSubscriptionPlan.id,
      userId: user.id,
      discountId: SYSTEM_UUID,
    },
  }

  if (providerCouponId) {
    secondPhase.coupon = providerCouponId
    secondPhase.metadata.discountId = dbDiscountId
  }

  await stripeGatewayClient.subscriptionSchedules.update(scheduleId, {
    end_behavior: 'release',
    phases: [
      {
        items: defaultPhase.items,
        start_date: defaultPhase.start_date,
        end_date: defaultPhase.end_date,
        metadata: defaultPhase.metadata,
        currency: defaultPhase.currency,
      },
      secondPhase,
    ],
  })

  return providerSubscription
}
#

after the subscription_scheduler has kicked in and downgraded the subscription as expected, if user tries to cancel the subscription, they get attached error above,

here is my cancelSubscription function:

const cancelProviderSubscription = async (providerSubscriptionId) => {
  try {
    const updatedProviderSubscription =
      await stripeGatewayClient.subscriptions.update(providerSubscriptionId, {
        cancel_at_period_end: true,
      })
    if (!updatedProviderSubscription) return null

    return {
      status: updatedProviderSubscription.status.toUpperCase(),
      intervalEndCancel: true,
    }
  } catch (ex) {
    throw new SubscriptionsProviderError(transformStripeError(ex))
  }
}

#
The subscription is managed by the subscription schedule `sub_sched_1QFwX0D9sYh65PYtF8xw3tCh`, and updating any cancelation behavior directly is not allowed. Please update the schedule instead.
#

I am assuming the end_behavior param should release the scheduler from the subscription (subscription should not be managed by sched anymore), what am I missing here?

  await stripeGatewayClient.subscriptionSchedules.update(scheduleId, {
    end_behavior: 'release',
    phases: [
      {
        items: defaultPhase.items,
        start_date: defaultPhase.start_date,
        end_date: defaultPhase.end_date,
        metadata: defaultPhase.metadata,
        currency: defaultPhase.currency,
      },
      secondPhase,
    ],
  })

subtle walrus
pine valley
#

I see, then what is end_behavior :''release" here ?

As i assumed this will detach the subscription scheduler from the subscription after the second phase is excuted..

subtle walrus
#

Yes you are right. If you set it to cancel, then the schedule will cancel the subscription upon release

pine valley
#

Okay so as far as I understood, the end_behavior should be set to release as I do not want the subscription to be cancelled right after they are downgraded when the second phase executes (Downgrade actually occurs).

Yet, although I have set the end_behavior to release the subscription somehow keeps being managed by the subscription scheduler that was released ..

if this is the case, If I have to cancel a subscription after the downgrade..

I need to check if a subscription has a scheduleId, if yes, cancel the schedule, if no, do normal update subscriptions.update(providerSubscriptionId, { cancel_at_period_end: true, })

Am I correct here? The only confusion I have is why we have the subscription being managed by scheduler even tho it was set to released...

#

below text from stripe doc

release will end the subscription schedule and keep the underlying subscription running.

if this is the case, am still not sure why I get The subscription is managed by the subscription schedule sub_sched_1QFwX0D9sYh65PYtF8xw3tCh, and updating any cancelation behavior directly is not allowed. Please update the schedule instead. when canceling the subscription.

subtle walrus
#

Did you release the subscription schedule before calling the subscription update API?

#

I just checked the schedule and it's still attached to a subscription.

pine valley
#

events?related_object=sub_1QDpYWD9sYh65PYtIWeIkZXK

#

the following event creates the scheduler evt_1QFwX0D9sYh65PYtfpEFXRkU with end_behavior : realease

subtle walrus
#

Yes, but it's still attached to the subscription when you made the request to update the subscription.

pine valley
#

Yeah that's the thing, so, if you check the next event

evt_1QP4KqD9sYh65PYt3yzgl7vv

Which does the downgrade according to the scheduler ..

#

after that event I am expecting the scheduler to be detached from the subscription

#

After this downgrade operation happened,

I can see evt_1QP5KQD9sYh65PYtOWFE9JHd

#

which updates scheduler

subtle walrus
#

Not really, I don't see you specified an end_date to end the schedule.

pine valley
#
    "released_at": null,
    "released_subscription": null,
    "renewal_behavior": "release",
    "renewal_interval": null,
    "status": "active",
    "subscription": "sub_1QDpYWD9sYh65PYtIWeIkZXK",

subtle walrus
#

You specified end_behaivour, but you didn't specify when to end

pine valley
#

Okay

But the second phase has start_date and end_date?

const createSubscriptionScheduler = async (
  user,
  newSubscriptionPlan,
  providerSubscription,
  newProviderPlan,
  providerCouponId = null,
  dbDiscountId = null
) => {
  let scheduleId = providerSubscription.schedule
  let schedule = null
  if (!scheduleId) {
    schedule = await stripeGatewayClient.subscriptionSchedules.create({
      from_subscription: providerSubscription.id,
    })
    scheduleId = schedule.id
  }

  schedule =
    await stripeGatewayClient.subscriptionSchedules.retrieve(scheduleId)

  const defaultPhase = schedule.phases[0]

  const secondPhase = {
    items: [
      {
        price: newProviderPlan.id,
      },
    ],
    start_date: defaultPhase.end_date,
    metadata: {
      subscriptionPlanId: newSubscriptionPlan.id,
      userId: user.id,
      discountId: SYSTEM_UUID,
    },
  }

  if (providerCouponId) {
    secondPhase.coupon = providerCouponId
    secondPhase.metadata.discountId = dbDiscountId
  }

  await stripeGatewayClient.subscriptionSchedules.update(scheduleId, {
    end_behavior: 'release',
    phases: [
      {
        items: defaultPhase.items,
        start_date: defaultPhase.start_date,
        end_date: defaultPhase.end_date,
        metadata: defaultPhase.metadata,
        currency: defaultPhase.currency,
      },
      secondPhase,
    ],
  })

  return providerSubscription
}
subtle walrus
#

No, I don't see an end_date on the 2nd phase.

#

My mistake, there's a end_date, which is 1735140964 2024-12-25 15:36:04 UTC

#

So this schedue will end on 25 Dec

pine valley
#

I see

#

Got it

#

So for these subscriptions, that are in this state..

And If I want to cancel their subscription, instead of calling

 await stripeGatewayClient.subscriptions.update(providerSubscriptionId, {
    cancel_at_period_end: true,
  })

I should be canceling the scheduler only

subtle walrus
#

Yes you are right

pine valley
#

Alright thanks for the help, appreciate it