Closed unruha closed 8 months ago
Hi @unruha,
What version of svelte-stripe are you using? An issue like that was recently fixed, so I'm wonder if you're on the latest version 1.1.3
Hi @joshnuss,
Thanks for the quick response. Yes I'm using version 1.1.3. I'm adding some additional details below.
I generate the Stripe checkout session in a form action on the previous page, then pass the session ID to the checkout page:
export const actions: Actions = {
submit: async (event) => {
const stripe = new Stripe(STRIPE_SECRET_KEY, {
apiVersion: "2023-10-16"
});
// create a checkout session and pass the session ID to the checkout page
const stripeSession: Stripe.Checkout.Session = await stripe.checkout.sessions.create({
ui_mode: "embedded",
line_items: [
{
price: PRODUCT,
quantity: 1
}
],
mode: "subscription",
return_url: `{BASE_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
});
throw redirect(308, `/checkout?checkoutSessionId=${stripeSession.client_secret}`);
}
}
Pass the checkout session ID into the page data on the checkout page:
import type { PageServerLoad } from "./$types";
export const load: PageServerLoad = async (event) => {
return {
checkoutSessionId: event.url.searchParams.get("checkoutSessionId")
}
};
Lastly, I use the checkout session ID in the EmbeddedCheckout element:
<script lang="ts">
import { loadStripe } from "@stripe/stripe-js";
import { onMount } from "svelte";
import { EmbeddedCheckout } from "svelte-stripe";
export let data: PageData;
let stripe = null;
onMount(async () => {
stripe = await loadStripe(STRIPE_PUBLISHABLE_KEY);
});
</script>
<div>
<EmbeddedCheckout {stripe} clientSecret={data.checkoutSessionId} >
</EmbeddedCheckout>
</div>
The embedded checkout displays correctly on the initial load. But if I navigate away and back to the checkout page, I see the error. I have also tried generating the checkout session in the load function of the checkout page (as seen in the example) but with the same result.
I had the same issue, seems the key is to destroy the stripe element when your component is destroyed. E.g. my embedded checkout control looks for the destroy event and then calls the destroy event of the stripe element:
``
@conorw thanks for the tip. I think the difference is that I'm trying to use the embedded checkout component while you're using the native HTML JS solution. I tried to replicate what you did here by destroying the EmbeddedCheckout
element when the component is destroyed, but it still didn't work for me.
wrapper.svelte
<script lang="ts">
import type { Stripe } from "@stripe/stripe-js";
import { EmbeddedCheckout } from "svelte-stripe";
import { onDestroy } from "svelte";
export let clientSecret: string;
export let stripe: Stripe;
let checkoutRef: EmbeddedCheckout;
onDestroy(() => {
console.log("destroying component")
checkoutRef.$destroy();
});
</script>
<EmbeddedCheckout bind:this={checkoutRef} {stripe} clientSecret={clientSecret} >
</EmbeddedCheckout>
If I can't get this working I may just try to native solution that you're using. It definitely seems like an underlying issue with the lifecycle management of the embeddedCheckout on Stripe's side, and not within this library.
@joshnuss I ran the project locally and I see the same error. I tested the solution proposed by @conorw and it seemed to resolve the issue. If we are interested in this workaround, I have created a PR for the fix here.
I think this can be closed with #99.
Thanks for reporting and submitting the fix 👍🏻
related to this issue, @joshnuss - what would be the best practice for handling multiple <EmbeddedCheckout />
?
i fixed the above error by adding the binding and onDestroy, but let's say i want the customer to be able to choose between two different products, which have 2 different client secrets.
am i re-assigning the clientsecret to a new value, but keeping one <EmbeddedCheckout />
object? this seems to return the same error.
or do i have two <EmbeddedCheckout />
somewhere each with their own client secret, but only one is shown?
Thanks!
i'm not sure this issue is entirely resolved. (i'm using 1.1.3
, but don't see that release linked to here in GitHub)
if i show/hide
error:
Uncaught (in promise) IntegrationError: You cannot have multiple Embedded Checkout objects.
even when i do this on hide:
checkoutRef.$destroy();
and have bound:
<EmbeddedCheckout bind:this={checkoutRef} {stripe} clientSecret={ClientSecret}/>
after a bit more digging, it looks like npm hasn't been updated in a couple of months.
@joshnuss - is there an ETA on the next npm release, or should i try to find a workround from source?
Hi @rawwerks,
I've released a new version, can you try the latest and let me know if it's still an issue
@joshnuss
I still see the error in version 1.1.4. My implementation is here:
@gagansuie I will investigate
In the meantime, try wrapping your dialog with a {#key condition}
block. That will cause everything to re-mount when the condition changes.
@joshnuss
Facing the same error here, I tried wrapping the dialog with the client_secret as the condition of the key block but It didn't solve the issue. Binding the and then destroying the component doesn't work on my side :(
I'm using the latest version of the package.
Same problem. Version 1.1.7, svelte 4.2.15, kit 2.5.7
Describe the bug
First of all, thank you for the work put into this project, its providing a much cleaner checkout flow in SvelteKit for me as opposed to other methods.
When you load Embedded Checkout then navigate away client-side, and try to load the Embedded Checkout element again, you get this error on the client and the checkout doesn't load:
The checkout element then loads again when you refresh the page.
Reproduction
Create a checkout session on the server side (outlined here). Then mount the embedded checkout element and pass it your client secret provided by the checkout session creation response. It should show correctly on the first load.
If you navigate elsewhere on the client side then return to the checkout page and try to mount the embedded checkout element again, you see the error outlined above and the element doesn't show.
This behavior is seen both with the same checkout client secret and if you generate a new client secret before mounting the element.
Refreshing the page causes the element to load correctly again.
Severity
serious, but I can work around it
Additional Information
No response