#ara
1 messages · Page 1 of 1 (latest)
Can you share the payment intent id?
I only create the payment intent id after the customer has confirmed the payment unfortunately...
"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
Hello! I'm taking over and catching up...
Are there any errors in the web dev console?
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...
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.
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?
https://stripe.com/docs/payments/accept-a-payment-deferred
Yeah I found the preventDefault in these docs
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.
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?
I am using the handleSubmit function for the regular paymentElement and also it is triggered by the expressCheckoutElement for apple pay
Not sure I understand. Can you show the code that's creating the event you're trying to prevent?
<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]);
Where's the preventDefault call though?
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
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.
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.
Yeah, if you just want the Express Checkout Element to create a Payment Method you can do this: https://stripe.com/docs/elements/express-checkout-element/accept-a-payment#create-pm