#Multiple payment intent after update cart data

1 messages · Page 1 of 1 (latest)

silver zephyr
#

Hi,
Im trying to implement payment with PaymentElement and have problem with multiple payment intents.
I noticed that, when I update my cart with new email (for example user moves step back and changes email address), it creates new payment intents on stripe (screenshot).
I guess it should know its the same cart and just update intent. I checked in stripe logs and all 3 have same cartId in resource_id. How to debug this to find out what is happening?

client secret also is changed (with new pi_)

Im using stripe plugin,
"medusa-payment-stripe": "^6.0.9",
"@medusajs/admin": "^7.1.14",
"@medusajs/medusa": "^1.20.6",

This is how my update cart looks like:

    cartId,
    cartData,
}: {
    cartId: string;
    cartData: StorePostCartsCartReq;
}) => {
    try {
        const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/store/carts/${cartId}`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(cartData),
        });

        if (!res.ok) {
            throw new Error(`Failed to add shipping address to a cart: ${cartId}`);
        }

        const data = (await res.json()) as { cart: Cart };
        return data?.cart;
    } catch (error) {
        console.log('[ERROR] updateCartShippingAddress', error);
        return null;
    }
};

Any tips for understanding this would be super helpful!

south hatch
#

First would be React Strict Mode. Turn it off

#

And don't create payment session until email is filled in.

#

Actually no, sorry.

#

It will behave like that

#

It creates a new intent with new customer in Stripe.

#

Be sure to finish the correct intent. Use client secret when firing confirmPayment.

river storm
#

Same pb here, not investigated yet but this could be fixed easily I think

silver zephyr
#

I tried running with React strict mode off, but there was no difference. I also did some additional debugging.

After opening the checkout page, I create a payment session, which creates an intent with a random customer named cus_... on Stripe.

export const createPaymentSession = async ({ cartId }: { cartId: string }) => {
    try {
        const res = await fetch(
            `${process.env.NEXT_PUBLIC_API_URL}/store/carts/${cartId}/payment-sessions`,
            {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                credentials: 'include',
            },
        );

        if (!res.ok) {
            throw new Error(`Failed to create payment session: ${cartId}`);
        }

        const data = (await res.json()) as { cart: Cart };
        return data?.cart;
    } catch (error) {
        console.log('[ERROR] createPaymentSession', error);
        return null;
    }
};

After I pass the address data, it creates another payment intent with the provided email as the customer name. Later, when I add the shipping method, it correctly updates the intent instead of creating a new one with the updated amount.

I found a warning in my console from Stripe:
Unsupported prop change: options.clientSecret is not a mutable property
which was from StripeProvider (the same implementation as in medusa-storefront).

This answer https://stackoverflow.com/a/71678681/15073323, seems to fix it by recreating <Elements /> with the clientSecret passed as a key:
<Elements options={options} stripe={stripePromise} key={clientSecret}>. This ensures that we are resolving correct intent after data changes (like updating email). After adding this key prop, I can finish my "last" intent with correct data and leave the "original" intent.
However, it still feels wrong that we are leaving the original intent and creating a new one instead of updating it.

south hatch
#

As i said, don't create payment sessions until email is filled in. If you do create payment sessions before email is filled in, the above situation will show up. One intent with no email and another with email filled in.
I run createPaymentSessions only after email is filled in.

#

When you change email it will probably create a new customer in medusa with different email. This will create a new payment intent with new customer in Stripe

#

When running confirmPayment from Stripe ensure that you pass the clientSecret there from cart.payment_sessions