#m0uka

1 messages · Page 1 of 1 (latest)

vague ridgeBOT
floral tiger
#

Hm that sounds unexpected

#

Do you have a test page we can repro on?

tawny rose
floral tiger
#

Thanks

#

Can you also share your payment element code

#

For initialization and confirmation

tawny rose
#

sure, this is the confirmation:

const { error } = await stripe!.confirmPayment({
          clientSecret,
          elements: elements!,
          confirmParams: {
            return_url: getCompleteURL(),
            payment_method_data: {
              billing_details: {
                name: details.name,
                email: details.email,
                address: {
                  country: details.address!.country!,
                  postal_code: details.address!.postal_code!,
                  state: details.address!.state!,
                  line1: details.address!.line_1!,
                  line2: details.address!.line_2!,
                  city: details.address!.city!,
                },
              },
            },
          },
        })

        // This point will only be reached if there is an immediate error when
        // confirming the payment. Otherwise, your customer will be redirected to
        // your `return_url`. For some payment methods like iDEAL, your customer will
        // be redirected to an intermediate site first to authorize the payment, then
        // redirected to the `return_url`.
        if (error.type === 'card_error' || error.type === 'validation_error') {
          setMessage(error.message)
        } else if (
          error.code === 'parameter_missing' &&
          error.param?.startsWith('billing_details')
        ) {
          // Probably some payment method crying about not having full payment details, redirect to Billing Details and force full address
          const searchParams = new URLSearchParams(window.location.search)
          searchParams.set('force_full_address', '1')
          navigate(`/?${searchParams}`)
        } else {
          setMessage('An unexpected error occurred.')
        }```
#

submitting:

const handleSubmit = async (e: React.SyntheticEvent) => {
    e.preventDefault()

    if (!stripe || !elements) {
      // Stripe.js has not yet loaded.
      // Make sure to disable form submission until Stripe.js has loaded.
      return
    }

    setLoading(true)

    await elements.submit()
    changePaymentMethodMutation.mutate()
  }

  return (
    <form ref={formRef} id="payment-form" onSubmit={(e) => handleSubmit(e)}>
      <PaymentElement
        id="payment-element"
        options={elementOptions}
        onReady={(e) => e.focus()}
      />
      <div className={'mt-4 flex flex-col gap-3'}>
        <Button
          isSubmit
          isLoading={isLoading}
          style={{
            backgroundColor: checkoutStyle.color_primary,
            color: getContrastYIQ(checkoutStyle.color_primary),
            borderRadius: '8px',
          }}
          className={'w-full font-semibold focus:ring-0 focus:ring-offset-0'}
          variant={'custom'}
        >
          <span>Pay Now</span>
        </Button>
      </div>
      {message && (
        <div
          className="mt-2 text-xs text-black dark:text-white"
          id="payment-message"
        >
          <span>{message}</span>
        </div>
      )}
    </form>
  )```
#

also elements setup options (don't know if that's relevant)

const options: StripeElementsOptions = {
    mode: checkout?.subscription ? 'subscription' : 'payment',
    currency: checkout?.currency!,
    amount: checkout?.total_amount!,
    fonts: [
      {
        family: checkoutStyle.font_family,
        cssSrc: `https://fonts.googleapis.com/css2?family=${checkoutStyle.font_family}:wght@300;400;500;600;700;800&display=swap`,
      },
    ],
    appearance: {
      theme: isDarkmode ? 'night' : 'stripe',
      variables: {
        fontFamily: checkoutStyle.font_family,
        colorPrimary: checkoutStyle.color_primary,
        colorBackground: isDarkmode ? '#0f0f0f' : '#fff',
        colorText: isDarkmode ? '#eee' : '#111827',
        borderRadius: `5px`,
        fontSizeBase: '14px',
        colorTextPlaceholder: isDarkmode ? '#6B7280' : '#44444480',
      },
      labels: 'above',
    },
  }

  return (
    <Elements options={options} stripe={stripePromise}>
      <CheckoutForm />
    </Elements>
  )```
floral tiger
#

Thanks looking

#

Just curious, can you share: getCompleteURL's code

tawny rose
#
export function getCompleteURL() {
  return `${window.location.origin}/complete${window.location.search}`
}```
floral tiger
#

got it thanks

#

yeah this seems wrong. let me see if I can reproduce in my own integration as well

#

Yeah was able to reproduce elsewhere as well

#

Asking a colleague for next steps. Will need to report this to the owning team

tawny rose
#

Just noticed the same issue with WeChat Pay - not really a concern for us since we don't use the payment method, but I figured it would be useful to you

floral tiger
#

Ok gotcha

#

So I chatted with a colleague about this. They reported the issue to the owning team. However, I was also advised to tell you to not rely on redirect_status in your code and instead retrieve the PaymentIntent from the API to get its status. redirect_status is not a documented param, so it is unreliable

#

Which isn't great

#

We're reporting all this as feedback to the team, but for now I'd strongly recommend not relying on it

#

I know it's not ideal

tawny rose
#

hmm I see, I wanted to avoid an additional API call but if there's no other way I have no choice

#

so I am guessing check if the PaymentIntent is still in a pending state or something, and if so, assume the payment is still pending?

floral tiger
#

Yeah unfortunately that's going to be the most reliable way here

tawny rose
#

is it guaranteed to not be in a pending state if the payment succeeded (the customer got redirected)?

floral tiger
#

Depends on the payment method. Some remain in pending for a while. Like bank transfers

#

cashapp i believe is immediate though

#

But always recomend just checking status on payment intent

tawny rose
#

alright thanks, do you have any info if this issue is going to be solved at some point, or if you are going to abandon this query parameter altogether? Cash App Pay is a very small market share of our user-base, so I don't really want to overengineer things

#

also any possibility I can handle the redirect myself somehow? so the customers wont get redirected to the complete screen and then back to the payment page if they just close the modal, seems counter-intuitive

#

no worries if you don't know, just trying to figure out what to do right now

floral tiger
#

alright thanks, do you have any info if this issue is going to be solved at some point
I don't know at this point. Really recommend using payment intent's status.

also any possibility I can handle the redirect myself somehow?
No unfortunately not

tawny rose
#

alright, thanks for your help

#

have a good day