stripe / react-connect-js

React components for Connect.js and Connect embedded components
https://stripe.com/docs/connect/get-started-connect-embedded-components
MIT License
20 stars 8 forks source link

Embedded Onboarding Popup Blocked #93

Open kbernst30 opened 3 months ago

kbernst30 commented 3 months ago

I've been following the tutorial for setting up Onboarding with Stripe Connect https://docs.stripe.com/connect/onboarding/quickstart#init-stripe

I have everything set up, and the iFrame that contains the button to "Add Information" displays on the page, but once i click it, i get a Console Error saying the following:

AccountOnboarding.tsx:133 Uncaught (in promise) SubmerchantAuthError: Popup is blocked by browser.
    at SubmerchantAuthenticationContext.tsx:436:18
    at new Promise (<anonymous>)
    at SubmerchantAuthenticationContext.tsx:431:14
    at SubmerchantAuthenticationContext.tsx:452:14
    at async SubmerchantAuthenticationContext.tsx:580:17

Even so, a popup does indeed open (definitely wasn't blocked) but shows just a loading indicator.

I dug into the code a bit and the issue seems to occur because the call from window.open in the Stripe connect library returns null. And the error message saying "Popup blocked" happens if the result from that call is null. I know this can be a problem with window.open when not initiated directly by a user, but i don't see anyone else having this problem with Stripe and React.

Here is my code for this.. perhaps I'm doing something subtly wrong, even though I followed the tutorial:

const createAccountSession = async (accountId: string) => {
  const { data } = await api.post("/payments/sessions", { account: accountId })
  return data
}

const useCreateAccountSession = () => useMutation({
  mutationFn: (accountId: string) => createAccountSession(accountId)
})

const useStripeConnect = (accountId: string) => {
  const { mutate, data, isPending, isError, isSuccess } = useCreateAccountSession()
  const [stripeConnectInstance, setStripeConnectInstance] = useState<StripeConnectInstance>()

  useEffect(() => {
    if (data) {
      setStripeConnectInstance(
        loadConnectAndInitialize({
          publishableKey: import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY,
          fetchClientSecret: () => data.clientSecret,
          appearance: {
            overlays: "dialog",
            variables: {
              colorPrimary: "#635BFF",
            },
          },
        })
      );
    } else {
      mutate(accountId)
    }
  }, [data])

  return stripeConnectInstance;
};

const OnboardSeller = ({ accountId }: OnboardSellerProps) => {

  const stripeConnectInstance = useStripeConnect(accountId)
  const [onboardingExited, setOnboardingExited] = useState(false)

  return (
    <>
      {stripeConnectInstance && (
        <ConnectComponentsProvider connectInstance={stripeConnectInstance}>
          <ConnectAccountOnboarding
            onExit={() => setOnboardingExited(true)}
          />
        </ConnectComponentsProvider>
      )}
    </>
  )
}

This happens in all browsers and for all test users I've created.

VinnyLimogrid commented 1 month ago

Did you find a solution?

jorgea-stripe commented 1 month ago

Unfortunately I am unable to repro this issue at the moment.

Are you able to repro if you use our quickstart to embedded onboarding sample? https://docs.stripe.com/connect/onboarding/quickstart?connect-onboarding-surface=embedded&connect-dashboard-type=none&connect-economic-model=revshare&connect-loss-liability-owner=stripe&connect-charge-type=direct

@VinnyLimogrid @kbernst30 would you be able to attach a video, or a sample repository that is reproing the issue?

jorgea-stripe commented 1 month ago

To double check - your site does comply with the CSP and HTTP header requirements - in particular the Cross-Origin-Opener-Policy value? https://docs.stripe.com/connect/get-started-connect-embedded-components#csp-and-http-header-requirements