#daartanian_connect-embedded

1 messages ยท Page 1 of 1 (latest)

blissful jackalBOT
pallid hingeBOT
#

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.

blissful jackalBOT
#

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

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

vagrant bison
#

sup @undone whale ๐Ÿ‘‹๐Ÿป

undone whale
#

Hey @vagrant bison ! I'm happy to help but I need you to clearly ask your summarized question. I won't be able to go and read the thread to get the state (see the message from the bot above)

vagrant bison
#

Ah. Hmm... ok. I can give more context.

#

It started with that happening in my code ๐Ÿ‘†๐Ÿป

#

So we ended up moving the ConnectComponentProvider wrapper closer to the components that seemed to be having issues. That seemed to clear up that error.

So it went from this (the state from the video):

#

to this:

undone whale
#

Do you have a 2 or 3 sentences summary in text as human?

vagrant bison
#

And that seemed to clear up that issue. But in the back of my head I remembered an issue popping up that caused me to back the ConnectComponentProvider all the way back to the base level

#

in text as human

#

do you just mean not a video?

undone whale
#

I mean I will watch that video but it'd help to have a real summary in words in text that I can read in 10 seconds to get an understanding of what you're even asking. You jumped deep in screenshot of something I don't really follow with no context yet. I'm trying to get my bearings, we have dozens of products and APIs

vagrant bison
#

Cool, cool. I can do that.

undone whale
#

oh boy an 8 minutes video

#

so yeah let's pause on that and wait for a clear summary if possible

vagrant bison
#

I am using Stripe Connect integrated into our software.

I was having issues where when I was trying to load a component underneath the ConnectComponentProvider wrapper (as you guys instruct to do in your docs), I was getting an error saying it couldn't find the ConnectComponentProvider.

Working together with another suport dev last night, we moved the ConnectComponentProvider closer to where the Stripe Connect Component is being called. But now there is an issue where it is saying, when I try and switch from one Stripe Connect Component to another one inside of the ConnectComponentProvider wrapper:

`"cannot_create_account_session"
"You tried to claim an account session that has already been claimed."

and it doesn't load.

undone whale
#

Okay what exact doc are you following and which part of your code exactly is showing that new error

#

daartanian_connect-embedded

vagrant bison
#

let me find the right docs for you

undone whale
#

Sure and if you can share the relevant part of the code where you switch the component, that'd help. My guess is that you reinitializing something with a cached AccountSession client_secret

vagrant bison
#

let me get you some code

vagrant bison
#

This is where people are directed to a zero state if we can't find a Stripe Connect account Id associated with them. There is a Sign Up button inside of ManageBillingZeroState that they click and we create an account for the user with a call to that endpoint outlined in Step 1 of that document:

const ManageBilling = () => {
    const userConfig = useUserConfig();
    const partnerId = String(userConfig?.partnerRecord[0]?.id);
    const [isUserSignedUpToStripe, setIsUserSignedUpToStripe] = useState(Boolean(
        userConfig?.partnerRecord[0]?.stripe_connected_account_id,
    ));
    const [stripeAccountId, setStripeAccountId] = useState<string>(userConfig?.partnerRecord[0]?.stripe_connected_account_id || '');

    const handleStripeSignUp = ({
        accountIdForStripe,
        userSignedUpToStripeValue,
    }: HandleStripeSignUpParams) => {
        setStripeAccountId(accountIdForStripe);
        setIsUserSignedUpToStripe(userSignedUpToStripeValue);

        const domain = window.location.hostname;
        const queryKey = ['config', { domain }];
        guardianQueryClient.invalidateQueries(queryKey);
    };

    const getBillingContent = () => {
        switch (isUserSignedUpToStripe) {
            case true:
                return <StripeContent stripeAccountId={stripeAccountId} />;

            default:
                return (
                    <ManageBillingZeroState
                        handleStripeSignUp={handleStripeSignUp}
                        partnerId={partnerId}
                    />
                );
        }
    };

    return (
        <WidgetWrapper headerIcon={CreditCardIcon} title="Billing">
            {getBillingContent()}
        </WidgetWrapper>
    );
};

export default ManageBilling;
#

I didn't include imports for the sake of discords text limits

undone whale
#

Okay, which exact part of that code is raising the exact error you mentioned?

vagrant bison
#

Good question. So inside of the StripeContent, we have this code:

const StripeContent = ({ stripeAccountId }: StripeOnboardingProps) => {
    const [currentStripeComponent, setCurrentStripeComponent] = useState<StripeComponent | undefined>();

    const {
        hasBeenOnboarded,
        isPending: isRetrieveAccountPending,
        error: retrieveAccountError,
    } = useStipeRetrieveAccount(stripeAccountId);

    useEffect(() => {
        switch (hasBeenOnboarded) {
            case true:
                setCurrentStripeComponent(StripeComponent.Dashboard);
                break;

            case false:
                setCurrentStripeComponent(StripeComponent.Onboarding);
                break;

            default:
                // We don't want to log an error during the re-renders on loading
                if (!isRetrieveAccountPending) {
                    consoleLogger.errorMessage({ message: 'No onboarding status found' });
                }
        }
    }, [hasBeenOnboarded]);

    const handleOnboardingExit = async () => {
        // The waiting is due to a bug in Stripe's components,
        // it needs time to know onboarding has been completed
        await delay(2000);
        setCurrentStripeComponent(StripeComponent.Dashboard);
    };

    const getStripeContent = () => {
        switch (currentStripeComponent) {
            case StripeComponent.Dashboard:
                return (
                    <StripeDashboard />
                );

            case StripeComponent.Onboarding:
                return (
                    <ConnectAccountOnboarding onExit={handleOnboardingExit} />
                );

            default:
                return <LoadingState />;
        }
    };

    return (
        <div className="text-center">
            <StripeConnectWrapper stripeAccountId={stripeAccountId}>
                {getStripeContent()}
            </StripeConnectWrapper>
        </div>
    )
}
#

Its in this step that I get the error. When the UI tries to load the ConnectAccountOnboarding

#

It errors on this claim endpoint: https://api.stripe.com/v1/account_sessions/claim

undone whale
#

okay, sorry I struggle with React nad that's so much code without a clear "this exact line is the issue"

#

where in your code do you pass the AccountSession's client_secret?

vagrant bison
#

Yea, sorry, the Stripe stuffed is pretty weaved in to React code here. That <StripeConnectWrapper /> is where that happens:

import React, { useEffect } from 'react';
import { loadConnectAndInitialize } from '@stripe/connect-js';
import { ConnectComponentsProvider } from '@stripe/react-connect-js';

const StripeConnectWrapper = ({ stripeAccountId, children }: StripeConnectComponentWrapperProps) => {
    const appConfig = getConfig();
    const thisIsADevelopmentEnvironment = isThisADevelopmentEnvironment();
    const [stripeKey, setStripeKey] = React.useState<string>('');
    const { stripe_publishable_key, stripe_publishable_test_key } = appConfig.global_configuration;

    useEffect(() => {
        setStripeKey(thisIsADevelopmentEnvironment ? stripe_publishable_test_key : stripe_publishable_key);
    }, []);

    if (!stripeAccountId) return <div>{children}</div>;

    const {
        clientSecret,
        isPending: isFetchClientSecretPending,
        error: fetchClientSecretError,
    } = useStipeFetchClientSecret(stripeAccountId);

    if (isFetchClientSecretPending) return <LoadingState />;
    if (fetchClientSecretError) {
        return (
            <ErrorState
                error={fetchClientSecretError}
                description="Please try again and contact support if this continues."
            />
        );
    }

    const connectInstance = loadConnectAndInitialize({
        publishableKey: stripeKey,
        fetchClientSecret: () => clientSecret,
        appearance: {
            variables: {
                // This is the same color as tailwind color admin-portal-blue
                colorPrimary: '#C8B56E', // optional appearance param,
            },
        },
    });

    return (
        <div className="text-center">
            <ConnectComponentsProvider connectInstance={connectInstance}>
                {children}
            </ConnectComponentsProvider>
        </div>
    );
};

export default StripeConnectWrapper;
undone whale
#

okay that helps. Damn I hate React lol

vagrant bison
#

In this file ๐Ÿ‘†๐Ÿป you can see this chunk:

const connectInstance = loadConnectAndInitialize({
        publishableKey: stripeKey,
        fetchClientSecret: () => clientSecret,
        appearance: {
            variables: {
                // This is the same color as tailwind color admin-portal-blue
                colorPrimary: '#C8B56E', // optional appearance param,
            },
        },
    });
undone whale
#

so many lines for so much magic.

vagrant bison
#

can't argue, it can be verbose for sure

undone whale
#

Can you add a clean log in your fetchClientSecret callback thingy? I feel like you're hardcoding a value on load instead of explicitly calling your server to get a fresh one every time

#

fetchClientSecret: () => clientSecret, like this is supposed to call your server and get a fresh client_secret from a brand new AccountSession every time it's called

#

so if you can add a log line here where you log the client_secret value and see if this happens right before your error that would help

vagrant bison
#

got it, so you want to see that client_secret value as it comes out from Stripe?

undone whale
#

I am currently guessing that you didn't understand that, created an AccountSession once when the app loaded and so now when Connect.js tries to get a fresh one, instead of going to your server to create a brand new one, you return the "cached" secret you had on load.
This is really just an educated guess, so adding a clear log to your callback there would help

vagrant bison
#

I think I understand. I will see what I can find

#

Ok, so I got my endpoint to not cache data, thus seeing this behavior:

#

aka fresh account sessions / secrets each time

#

But still erroring

#

oh hold up

#

this error might be mine

#

2 seconds

undone whale
#

yeah that error is different

vagrant bison
#

yea I was looking at the wrong thing though, that error didn't block. it popped and then resolved.

#

this is the blocking error

#

same one I started with

#

this is coming back from that claim endpoint:

#

https://api.stripe.com/v1/account_sessions/claim

undone whale
#

Hum and you are certain you are returning a unique AccountSession client_secret? sorry not seeing what you're seeing so I'm flying blind

#

Can you share that req_123 in text instead of a picture?

vagrant bison
#

ooh sure sure

#

yea, the first image I have shared is the console.log() coming back from my server endpoint that is basically just hitting the https://api.stripe.com/v1/account_sessions and returning the clientSecret. The image shows several difrerent console.log()'s popping each with a unique clientSecret coming back on the different renders.

#

Then the second on is just the error:

You tried to claim an account session that has already been claimed.

undone whale
#

I need the req_123456 in your picture

vagrant bison
#

Are you talking about this text?

{
    "code": "cannot_create_account_session",
    "message": "You tried to claim an account session that has already been claimed.",
    "request_log_url": "https://dashboard.stripe.com/test/logs/req_pKhb1FpiMQDfm1?t=1723762735",
    "type": "invalid_request_error"
}
undone whale
#

yes thanks

#

So you mentioned your earlier pictures were from your server-side code?
Are you certain you are properly returning the right updated client_secret in that callback client-side? Can you share your updated code for that part with exact logs so I can look at it?

vagrant bison
#

sure! one second

#
const {
        clientSecret,
        isPending: isFetchClientSecretPending,
        error: fetchClientSecretError,
    } = useStipeFetchClientSecret(stripeAccountId);

    if (isFetchClientSecretPending) return <LoadingState />;
    if (fetchClientSecretError) {
        return (
            <ErrorState
                error={fetchClientSecretError}
                description="Please try again and contact support if this continues."
            />
        );
    }

    console.log('[StripeConnectWrapper]', {
        clientSecret,
    });

    const connectInstance = loadConnectAndInitialize({
        publishableKey: stripeKey,
        fetchClientSecret: () => clientSecret,
        appearance: {
            variables: {
                // This is the same color as tailwind color admin-portal-blue
                colorPrimary: '#C8B56E', // optional appearance param,
            },
        },
    });

    return (
        <div className="text-center">
            <ConnectComponentsProvider connectInstance={connectInstance}>
                {children}
            </ConnectComponentsProvider>
        </div>
    );

so you can see that I am logging right before the fresh secret is being provided to the loadConnectAndInitialize which is a Stripe function, not mine.

So to the best of my knowledge that function is eating a fresh secret each time.

undone whale
#

hum

#

fetchClientSecret: () => clientSecret, this doesn't seem to fetch anything? This seems to still hardcode that id?

#

Can you add logs to that exact line of code to log the value you are returning to the component?

vagrant bison
#

yup, let me give it a whirl with console.logs and see

undone whale
#

thanks and please share the exact code you end up with. It's possible I'm wrong and your magic in React with useState and such dynamically changes the value, but it doesn't seem like it

vagrant bison
#

Ok, so here is my console, both showing different Stripe errors as well as when my secrets were fresh...

oh and the only change I made was to console.log() inside of the fetchClientSecret :

fetchClientSecret: () => {
            console.log('clientSecret inside of the fetchClientSecret', clientSecret);
            return clientSecret;
        },
undone whale
#

Okay so you see a fresh id before you see the other error?

vagrant bison
#

I mean, I see fresh sets of secrets followed by that error

undone whale
#

this looks like a clear duplicate no?

#

Like what I don't get is that your code is supposed to call your server during that callback

#

It really seems like my intuition is right and you return the same secret twice and the second time it errors

vagrant bison
#

yea, that might be right. let me try and see what I can do with that

vagrant bison
#

got it. thats helpful

#

I need to step out now unfortunately, but I will run with this and return if its still acting funny

#

thanks @undone whale ๐Ÿป

undone whale
#

Good luck!