#hugo_best-practices

1 messages ยท Page 1 of 1 (latest)

peak shardBOT
#

๐Ÿ‘‹ 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/1341399414794878997

๐Ÿ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

Below are links to other discussions we've had with you in the past week in case you want to review that information. If your question is related to one of these previous discussions, please provide a comprehensive summary of the current state and what you need help with now. We help many users simultaneously, so a summary allows us to resolve your issue as soon as possible.

sonic rune
#

Then, for some reasons, he pays the failed invoice from the 1st payment attempt with his valid CC.

This will activate the firstly created subscription. Leading to having two active subscriptions for this customer.

What is the recommended thing to do to prevent this ?

#

I know after 1 day, the "incomplete" marked subscription goes into "incomplete_expired", but sometimes, the customer try again in the same day, without staying in the same checkout UI, leading to this.

native pier
#

๐Ÿ‘‹
In your website, you need to add an extra check: before creating a new Checkout Session, see if the customer has already a Subscription or not that could be still used/paid ?

sonic rune
# native pier ๐Ÿ‘‹ In your website, you need to add an extra check: before creating a new Check...

And if so, I pass it in the checkout session creation step ?

    const options: StripeType.Checkout.SessionCreateParams = {
        customer: stripeCustomerId,
        mode: "subscription",
        line_items: [{ price: priceId, quantity: 1 }],
        success_url: successUrl,
        cancel_url: cancelUrl,
        metadata: {
            userId,
            priceId,
        },
        subscription_data: {
            metadata: {
                userId,
            },
        },
    };

    if (referalId) options.client_reference_id = referalId; // Rewardfull

    const session = await stripe.checkout.sessions.create(options);
native pier
#

No, you need to fetch the latest invoice generated from the intial subscription and share the hosted invoice url with the customer in order to pay it

sonic rune
#
  1. User try to subscribe to the plan A, fails
  2. The user come back later in the day, try to subscribe to the plan B, but as I saw an unpaid invoice, I'll send back said invoice URL, but it's a plan A product invoice.
#

What is the standard way to handle this in Stripe ?

native pier
#

Yeah you need to make sure that the old Subscription is still valid (with same product)

native pier
sonic rune
#

So, I need to fetch the invoice generated from the initial subscription, or the old subscription as a source of truth ?

native pier
#

Both are valid, the Subscription or its latest invoice

sonic rune
native pier
#

If the custom has a matched Susbcription session, then the payment url will be a hosted invoice url

sonic rune
#

So something like this should work ?

    const stripe = new Stripe(isDevOrPreview ? SECRET_STRIPE_TEST : SECRET_STRIPE);
    let stripeCustomerId = await getStripeCustomerId(userId);

    if (!stripeCustomerId) {
        const customer = await stripe.customers.create();
        stripeCustomerId = customer.id;
        await setStripeCustomerId(userId, stripeCustomerId);
    }

    const incompleteSubscriptions = await stripe.subscriptions.list({
        customer: stripeCustomerId,
        status: "incomplete",
    });

    if (incompleteSubscriptions.data.length) {
        const incompleteSubscription = incompleteSubscriptions.data[0];
        const incompleteSubscriptionPriceId = incompleteSubscription.items.data[0].price.id;
        if (incompleteSubscriptionPriceId === priceId) {
            const invoice = await stripe.invoices.retrieve(incompleteSubscription.latest_invoice as string);
            return invoice.hosted_invoice_url;
        }
    }

    const options: StripeType.Checkout.SessionCreateParams = {
        customer: stripeCustomerId,
        mode: "subscription",
        line_items: [{ price: priceId, quantity: 1 }],
        success_url: successUrl,
        cancel_url: cancelUrl,
        metadata: {
            userId,
            priceId,
        },
        subscription_data: {
            metadata: {
                userId,
            },
        },
    };

    if (referalId) options.client_reference_id = referalId; // Rewardfull

    const session = await stripe.checkout.sessions.create(options);

    return session.url;
}
#

Also, no need to care about "incomplete_expired" ones ? There is nothing the user can do / pay for them ?

native pier
#

Yes correct.

sonic rune
#

Gotcha, anything you'd recommend / see in my integration to make it better ?

native pier
#

So far nope.

sonic rune