#ara

1 messages · Page 1 of 1 (latest)

flat canyonBOT
dark harness
#

Can you share the payment intent id?

mint shore
#

I only create the payment intent id after the customer has confirmed the payment unfortunately...

dark harness
#

Ah

#

What's the error message exactly?

flat canyonBOT
mint shore
#

"Payment Failed" from apple then it highlights my card and says "Try Different Payment Card" under it

#

I mean it might just straight up work in live mode but I havent checked because I dont want to mess with prod before testing

cloud sage
#

Hello! I'm taking over and catching up...

#

Are there any errors in the web dev console?

mint shore
#

Wait looks like I accidentally did try in live mode and it failed.

#

Yes found logs

#

"Unrecognized confirm event paymentFailed callback parameter: message is not a recognized parameter. This may cause issues with your integration in the future.
The following is the relevant code where handle submit confirms the payment with stripe:

  useEffect(() => {
    if (stripe && elements) {
      expressCheckoutElement = elements.getElement(ExpressCheckoutElement);
      console.log('expressCheckoutElement', expressCheckoutElement);

      // Check if express checkout is available for conditional UI rendering
      expressCheckoutElement.on('ready', (event) => {
        if (event.availablePaymentMethods) {
          setIsExpressCheckoutAvailable(true);
        }
      });

      // Handle shipping address requirements on click
      expressCheckoutElement.on('click', (event) => {
        event.resolve({
          shippingAddressRequired: true,
          shippingRates: shippingRates,
        });
      });

      // Handle payment confirmation on 'confirm' event for Express Checkout
      expressCheckoutElement.on('confirm', async (event) => {
        try {
          await handleSubmit(event);
        } catch (error) {
          // Handle payment failures
          event.paymentFailed({
            message: 'Payment could not be processed at this time. Please try again later.'
          });
        }
      });

    }
  }, [stripe, elements]);
#

But that callback parameter error isnt really relevant to the issue it seems. The issue is that the payment fails in the first place from apple pay...

cloud sage
#

When you catch the error before calling event.paymentFailed can you log the details of that error? Right now you seem to be ignoring it, and I think it contains the details we're looking for.

mint shore
#

Logged that error. Seems like it is me preventing the default event that is causing it and the express checkout element must not have a default event.

Error confirmating payment: TypeError: qt.preventDefault is not a function. (In 'qt.preventDefault()', 'qt.preventDefault' is undefined

in handle submit:

    if (e) {
      console.log('e', e);
      e.preventDefault();
    }

I think this e.preventDefault was shown in the docs (not sure if true) to prevent the form's default event (the form that holds the payment elements). If preventing the default of the event is not necessary for the form, i can probably just remove it and it should be fine. Do you know if it is necessary?

#

Looks like the form refreshes the page if I dont prevent it.

#

I can probably just check if e.preventDefault function exists before running it.

cloud sage
#

If you're inside a <form> you need to prevent the submit event, but it sounds like you're trying to call preventDefault on a completely different event?

mint shore
#

I am using the handleSubmit function for the regular paymentElement and also it is triggered by the expressCheckoutElement for apple pay

cloud sage
#

Not sure I understand. Can you show the code that's creating the event you're trying to prevent?

mint shore
#
    <form id='payment-form' onSubmit={handleSubmit} className='w-full'>
      <ExpressCheckoutElement className='mt-4' id='express-checkout-element' options={expressCheckoutElementOptions} />
      <LinkAuthenticationElement
        id='link-authentication-element'
        onChange={handleEmailChange}
        options={linkElementOptions}
      />

      <h3 className='my-4'>Shipping</h3>
      <AddressElement options={addressElementOptions} onChange={handleAddressChange} />

      <h3 className='my-4'>Payment</h3>
      <PaymentElement id='payment-element' options={paymentElementOptions} />
      <button
        disabled={!stripe || isLoading}
        id='submit' ....

This is the form... this works fine (except for the ExpressCheckoutElement).

And for the ExpressCheckoutElement i add listeners:

 useEffect(() => {
    if (stripe && elements) {
      expressCheckoutElement = elements.getElement(ExpressCheckoutElement);
      console.log('expressCheckoutElement', expressCheckoutElement);

      // Handle shipping address requirements on click
      expressCheckoutElement.on('click', (event) => {
        event.resolve({
          shippingAddressRequired: true,
          shippingRates: shippingRates,
        });
      });

      // Handle payment confirmation on 'confirm' event for Express Checkout
      expressCheckoutElement.on('confirm', async (event) => {
        try {
          await handleSubmit(event);
        } catch (error) {
          console.error('Error confirming payment:', error);
          // Handle payment failures
          // event.paymentFailed({
          //   message: 'Payment could not be processed at this time. Please try again later.'
          // });
        }
      });

    }
  }, [stripe, elements]);
cloud sage
#

Where's the preventDefault call though?

mint shore
#

They both use this function:

const handleSubmit = async (e) => {

    if (e.preventDefault()) {
      console.log('e', e);
      e.preventDefault();
    }

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

    setIsLoading(true);

    const { error: submitError } = await elements.submit();
    if (submitError) {
      handleError(submitError);
      return;
    }

    // Create the payment intent and retrieve the client secret:

    const paymentIntentData = await createPaymentIntent();
    const clientSecret = paymentIntentData.clientSecret;

    // Confirm the PaymentIntent using the details collected by the Payment Element
    const { error } = await stripe.confirmPayment({
      elements,
      clientSecret,
      confirmParams: {
        // Make sure to change this to your payment completion page
        return_url: domain_url + '/shop/checkout/success',
        receipt_email: email,
      },
    });
    ...
#

Is this function compatible with those two? Besides the e.preventDefault()? If so, I can just check if the e.preventDefault() function exists before calling it

cloud sage
#

Oh, I see.

#

Yeah, you can't do that.

#

The events that the Express Checkout Element emits are special, they're not typical DOM events and can't be handled the same way.

#

You need to handle the events per our documentaiton, not using boilerplate event handling code.

mint shore
#

Checking if e.preventDefault is defined got it past that code but now it cant create a payment intent (with express checkout element, payment element works fine). So I have to handle express checkout element payments and payment elements differently? Do you guys have docs showing how to integrate both without creating a payment intent until the user tries to confirm the purchase? I cant create the payment intent until then because I allow users to edit their cart while in the checkout page.

cloud sage