#robclayton_api

1 messages ¡ Page 1 of 1 (latest)

lunar totemBOT
#

👋 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.

tribal vortex
#

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?

atomic forgeBOT
tribal vortex
#

ah, hi river!

storm aurora
#

Thanks for waiting! Discord is busy and will take time to respond

tribal vortex
#

No worries

storm aurora
#

Did you have the example request ID (req_xxx) that the same request used to work?

tribal vortex
#

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

storm aurora
#

You shouldn't set the phases directly from the response phases = subscription_schedule.phases

tribal vortex
#

so how do we add a phase?

storm aurora
tribal vortex
#

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

storm aurora
#

Thanks for waiting! Catching up now

tribal vortex
#

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)

storm aurora
#

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

tribal vortex
#

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,
},
)

storm aurora
#

Are you still keeping the coupon in the first phase? If so, coupon should still be set in the first phase

tribal vortex
#

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,
)```
storm aurora
#

This looks correct to me. Are you facing any error?

tribal vortex
#

I haven't tried yet, I just wrote that.
Previously I just added to the existing phases

storm aurora
#

I'd recommend giving it a try in test mode and let us know if you're still facing any issue

tribal vortex
#

thanks