#robclayton_api
1 messages ¡ Page 1 of 1 (latest)
đ 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/1227053540980031560
đ Have more to share? Add more details, code, screenshots, videos, etc. below.
Hi guys, happy to provide any code or context.
The failed api call we made should be pretty self explanatory though
You can see phase[0] has a discount AND a coupon ... but all we did was add to the phases object returned from stripe ... phase[0] is the api's construct
Hello, anyone here?
ah, hi river!
Thanks for waiting! Discord is busy and will take time to respond
No worries
Did you have the example request ID (req_xxx) that the same request used to work?
mmmm, I'm not sure I'm afraid
our code basically does this:
stripe_subscription = stripe.Subscription.retrieve(
id=external_id,
expand=["schedule"],
api_key=stripe_client.api_key,
)
phases = subscription_schedule.phases
phases.append(
{
"items": [{"price": _item["price"], "quantity": _item["quantity"]} for _item in items],
"iterations": iterations,
"start_date": start_timestamp,
"default_payment_method": payment_method,
"coupon": promo_code.coupon.id if promo_code else None,
},
)
updated_schedule = stripe.SubscriptionSchedule.modify(
subscription_schedule.id,
api_key=self.api_key,
end_behavior="cancel",
phases=phases,
)
so we get the existing subscription, get the phases, append a new entry to the phases list, then call SubscriptionSchedule.modify
You shouldn't set the phases directly from the response phases = subscription_schedule.phases
The request should only set the parameters that are necessary. For example: https://docs.stripe.com/billing/subscriptions/subscription-schedules/use-cases#changing-subscriptions
so how do we add a phase?
I'd recommend checking the guide here: https://docs.stripe.com/billing/subscriptions/subscription-schedules/use-cases#changing-subscriptions
I'm confused ... I have an existing schedule and I need to add a new phase
that is creating just 1 phase
I have an existing schedule I need to add a phase to
def update_stripe_subscription_schedule(
self,
subscription_schedule: stripe.SubscriptionSchedule,
line_items: list[LineItem],
start_timestamp: int,
billing_period: BillingPeriod,
payment_method: str,
promo_code: PromotionCode | None,
) -> stripe.SubscriptionSchedule:
"""Update a stripe subscription schedule.
It is mainly used to renew a subscription which is achieved by adding an additional phase
to a subscription schedule.
"""
items = [subscription_item.dict() for subscription_item in line_items]
iterations = billing_period.get_iteration_num()
# It is required to pass in the current phase, and then define a new phase.
# The payment method can be set per phase.
phases = subscription_schedule.phases
phases.append(
{
"items": [{"price": _item["price"], "quantity": _item["quantity"]} for _item in items],
"iterations": iterations,
"start_date": start_timestamp,
"default_payment_method": payment_method,
"coupon": promo_code.coupon.id if promo_code else None,
},
)
updated_schedule = stripe.SubscriptionSchedule.modify(
subscription_schedule.id,
api_key=self.api_key,
end_behavior="cancel",
phases=phases,
)
logger.debug(f"Subscription schedule {subscription_schedule.id} modified")
return updated_schedule
that's our full code, with the passed in existing schedule
Our code looks to be basically the same ... but we have an existing phase and want to add another ?
Sorry river, are you still there?
I apologize for not understanding, but that modify example is creating a phase, but not adding a new one.
It is the only phase present, so doesn't reflect my scenario
Thanks for waiting! Catching up now
no worries, I splurged a lot.
So I get we should not use the phases directly, and I suspect that stripe internally creates a discount with the coupon, but still shows the coupon separate as in our payload, and if I send it back that doesn't work.
However ... I do need a way to add that phase without modifying the existing one(s)
So I get we should not use the phases directly, and I suspect that stripe internally creates a discount with the coupon, but still shows the coupon separate as in our payload, and if I send it back that doesn't work.
Yes - correct
For the existing phase, you should copy the required fields including coupons. I'm afraid it's not possible to set directly. Your system should extract the necessary information in the existing phase and set it in the modify request.
After that, then new phase can then be added
so re-create without the discount field?
basically what we are doing now, but copy the required info without the discount field?
Would this be appropriate?
new_phases = []
for phase in subscription_schedule.phases:
new_phase = {
"items": phase["items"],
"iterations": phase.get("iterations"),
"start_date": phase["start_date"],
"end_date": phase.get("end_date"),
"default_payment_method": phase.get("default_payment_method"),
}
new_phases.append(new_phase)
Append the new phase
new_phases.append(
{
"items": [{"price": _item["price"], "quantity": _item["quantity"]} for _item in items],
"iterations": iterations,
"start_date": start_timestamp,
"default_payment_method": payment_method,
"coupon": promo_code.coupon.id if promo_code else None,
},
)
Are you still keeping the coupon in the first phase? If so, coupon should still be set in the first phase
Right, I'll keep the coupon but exclude the discount
for phase in subscription_schedule.phases:
new_phase = {
"items": phase["items"],
"iterations": phase.get("iterations"),
"start_date": phase["start_date"],
"end_date": phase.get("end_date"),
"default_payment_method": phase.get("default_payment_method"),
}
# Include the coupon if it exists in the original phase
if 'coupon' in phase:
new_phase['coupon'] = phase['coupon']
new_phases.append(new_phase)
# Append the new phase
new_phases.append(
{
"items": [{"price": _item["price"], "quantity": _item["quantity"]} for _item in items],
"iterations": iterations,
"start_date": start_timestamp,
"default_payment_method": payment_method,
},
)
# Use the new list of phases when modifying the subscription schedule
updated_schedule = stripe.SubscriptionSchedule.modify(
subscription_schedule.id,
api_key=self.api_key,
end_behavior="cancel",
phases=new_phases,
)```
This looks correct to me. Are you facing any error?
I haven't tried yet, I just wrote that.
Previously I just added to the existing phases
I'd recommend giving it a try in test mode and let us know if you're still facing any issue
thanks