#paymentplugins_api
1 messages ยท Page 1 of 1 (latest)
๐ 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/1339705657305333853
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
Hello ๐ , thanks for the info. Looking in to this
ok thank you
Can you send me the snippet of code where your page makes the confirm call?
I do see that the PM is of type link and it was created shortly before. I see the second call has something indicating that it thinks it is confirming with a card PM but I don't think that is something you are setting directly, trying to see how that is set
Here is the code snippet:
processPaymentIntent(data) {
this.stripe.confirmPayment({
...(!this.is_saved_method_selected() && {
elements: this.elements
}),
clientSecret: data.client_secret,
redirect: 'if_required',
confirmParams: {
return_url: data.return_url,
payment_method_data: {
billing_details: data.billing_details || this.get_billing_details()
},
...(data.confirmation_args && data.confirmation_args)
}
}).then(response => {
if (response.error) {
this.payment_token_received = false;
return this.submit_error(response.error);
}
let redirect = decodeURI(data.return_url);
redirect += '&' + $.param({
'_stripe_local_payment': this.gateway_id,
payment_intent: response.paymentIntent.id,
payment_intent_client_secret: response.paymentIntent.client_secret
});
if (['promptpay', 'swish', 'paynow', 'cashapp'].includes(this.paymentMethodType)) {
if (response.paymentIntent.status === 'requires_action') {
return this.get_form().unblock().removeClass('processing');
}
if (response.paymentIntent.status === 'requires_payment_method') {
this.get_form().unblock().removeClass('processing');
return this.submit_error({code: response.paymentIntent.last_payment_error.code});
}
}
window.location.href = redirect;
}).catch(error => {
return this.submit_error(error);
})
}```
I'll need to double check what the data.confirmation_args object contains.
Here is what I see in the nework tab and this time it worked:
return_url: https://testing.paymentplugins.com/checkout/?key=wc_order_qjf8kWPafshaQ&order_id=242&_stripe_payment_method=stripe_cc
payment_method: pm_1Qs9qyLVwyrKELh7Ei0d2SHB
expected_payment_method_type: link
radar_options[hcaptcha_token]: 20000000-aaaa-bbbb-cccc-000000000002
mandate_data[customer_acceptance][type]: online
mandate_data[customer_acceptance][online][infer_from_client]: true
use_stripe_sdk: true
key: pk_test_51GJ2WsLVwyrKELh7t9G4VtO3npf4w8Wa9k71hGgAns8BQa0TJBeIRIn8dlYiwHHEBKdZnjEwXDDwqq9CssHzyYgz00wnG7x28R
_stripe_account: acct_1GJ2WsLVwyrKELh7
_stripe_version: 2022-08-01
client_secret: pi_3Qs9qzLVwyrKELh7040OP3Dh_secret_VWKQb3k1u4ItJ5sVPBITemEXL
Gotcha, yeah if you can find what confirmation_args are that may be illuminating. And is this on the same page with your payment element and where you are making the createPaymentMethod call?
That is what the confirmation args contained, so just the return url. To your ealier question, yes that is where the createPaymentMethod call is occuring. Let me check what that request looks like
This is a head scratcher. Here is the request ID that was made for that createPaymentMethodCall. req_bRvDPyGPsQZGsA
Gotcha, still piecing things together. So your page calls createPaymentMethod, passes the new PM back to your server where it creates and confirms an intent, and if its status is requires_action you pass it's ID back to the frontend and try to confirm that again?
Yep that's 100% correct
Okay gotcha, I think you should change the frontend confirm into a call to handleNextAction, which is what we expect for intents in a requires_action state
If I remember correctly, we had to use the confirmPayment since we're using the universal payment element. The handleNextAction call was for the Stripe inline card form
handleNextAction can be used for this PE flow
https://docs.stripe.com/payments/finalize-payments-on-the-server?platform=web&type=payment#next-actions
Alternatively, you can avoid the server-side confirm call, just associate the PI and PM, then call confirmPayment but pass the client secret instead of elements, like in this doc
https://docs.stripe.com/payments/build-a-two-step-confirmation#create-intent
I'll have to go back in old notes but I know there was a very specific reason we used confirmPayment instead of handleNextAction. Sorry I don't have more details upfront
In that case, I would recommend that on your server you just create the payment intent and pass payment_method='pm_1234', then on the frontend use confirmPayment that takes clientSecret instead of elements (like in the first doc I linked to)
I think what is tripping things up now is that you are passing the elements instance into confirmPayment here which means we are referring to elements for what the expected payment method is and for some reason there is a conflict. If you just pass the intent's client secret instead we will just go forward confirming the intent with the PM that is attached to it, with no expected thing to conflict with.
I am starting to remember. With confirmPayment, you have to pass the elements instance since payment details are collected upfront. https://docs.stripe.com/js/payment_intents/confirm_payment#confirm_payment_intent-options-elements
We're using the deferred intent flow.
"If you just pass the intent's client secret instead we will just go forward confirming the intent with the PM that is attached to it, with no expected thing to conflict with.". Ok this makes sense. I will need to make sure this doesn't trigger any errors but the explanation makes sense.
Yeah, what you are doing is good if you aren't doing the PaymentMethod creation, when you do add that extra step the recommendation shifts slightly to what is in that "two step confirmation doc" which uses the client secret confirm. We do mention that in an optional step in the deferred intent docs.
https://docs.stripe.com/payments/accept-a-payment-deferred?platform=web&type=payment#create-ct
It's one of those annoying errors that doesn't happen often, and we process a lot of volume. I'll read through the docs you shared and see if something pops up.
But I am pretty sure the element instance has to be passed to confirmPayment since the createPaymentMethod call is made prior to the payment intent being created.
Passing in the clientSecret + confirmParams is the expected way to go here. Because you have the payment method ID, you don't need the elements instance anymore. The doc I linked to is updated so it now creates ConfirmationTokens instead of PaymentMethods, but the overall calls are the same. If you switch that should keep the existing that that work and fix this edge case
https://docs.stripe.com/js/payment_intents/confirm_payment#confirm_payment_intent-options-confirmParams-payment_method
Ok awesome, I will implement that and run testing. Is there a way to leave this thread open so I can report back tomorrow once testing has been completed?
The thread will be closed by then, but if you give a quick update on what you're trying and what you are trying to figure out the colleague who is online should be able to pick things up where we left off
Sounds good. You folks going to be at Stripe sessions this year?
Haven't heard about that specifically yet but I hope so!
Cool, if there is a support booth I'll be sure and come say hello. ๐