#Matt11-PI
1 messages ยท Page 1 of 1 (latest)
Hello!
of course pi_3LDbcHApMCw5clA31mqPheW2
can I try to explain my current logic?
yes sure
- we have an automatic script that look for out expired subscriptions and creates a payment_intent for renew them.
I create id with ruby apis like this:
payment_intent = ::Stripe::PaymentIntent.create({
amount: amount,
customer: user.stripe_customer_id,
currency: 'eur',
payment_method_types: ['card'],
setup_future_usage: 'off_session',
payment_method: payment_method_id
})
- after that I try to confirm it like this
::Stripe::PaymentIntent.confirm(
payment_intent.id,
{ payment_method: payment_method_id }
)
ok
- when I land on my platform I check if the subscription is in 3DS status and do this:
if intent['status'] == 'requires_action'
return_url = subscribe_sca_success_url
intent = Stripe::PaymentIntent.confirm(
intent_id,
{
return_url: return_url
}
)
if intent && intent['next_action'] && intent['next_action']['redirect_to_url'] && intent['next_action']['redirect_to_url']['url']
to_url = intent['next_action']['redirect_to_url']['url']
redirect_to to_url
end
end
I try to confirm it with a return_url
but it seems that the customer entered an infinite loop looking the payment_intent log on Stripe dashboard
do you understand what I'm doing wrong?
Hey, taking over here
we have an automatic script that look for out expired subscriptions and creates a payment_intent for renew them.
This sounds non conventional. What's an 'expired' subscription?
I have a database table named 'subscriptions' where we write internal subscriptions with from/to dates. An expired subscription is a row with today greater than "to" field
So my 'subscriptions' are nothing to do with Stripe subscriptions. It is only a custom way to manage internal subscriptions. And for every renewal we create one-shot payment intents.
So you need to think that our automatic script, check if there is a database row with "to"<"today" and create a payment_intent with an amount.
Why are you doing server-side confirmation?
You should just instead bring your customer back on-session and use confirmPayment from Stripe.js
They will likely need to do that anyway, so the server-side method is pointless in this case
I'm doing it because the automatic script is doing all the work.
Don't know how to bring the customer back on-session and confirm it from Stripe.js
Is it possible to fix this and do it in the server side way?
Do I need to confirm it with the redirect_url already in the first attempt?
You will need to bring your user on-session to complete the 3DS flow (if requested), regardless of whether you confirm server-side or nor
This is way it's best to just use confirmPayment with Stripe.js โ you pass it the PI client_secret and it handles the rest
how I achieve this procedure?
I don't know how
So I create the payment_intent server-side and it's in 'requires_confirmation' status, is correct?
Yep, or you can pass confirm: true if you're passing a payment_method too
this is my api call
payment_intent = ::Stripe::PaymentIntent.create({
amount: amount,
customer: user.stripe_customer_id,
currency: 'eur',
payment_method_types: ['card'],
setup_future_usage: 'off_session',
payment_method: payment_method_id
})
At that point, it'll either succeed or 3DS/auth will be requested (status: 'requires_action'). At that point you'd bring your user back on-session and use confirmPayment. This is all outlined here: https://stripe.com/docs/payments/payment-intents/verifying-status
Yep, so if you pass confirm: true there will automatically attempt to confirm it (which removed the need for that call server-side)
so the confirm:true flag is equal to do this?
::Stripe::PaymentIntent.confirm(
payment_intent.id,
{ payment_method: payment_method_id }
)
Yep
and if there's not difference why I cannot keep "my version"?
At that point, depending on the card used, the PI status will either be requires_action, succeeded or requires_payment_method
Well, you can. The fundamental issue here is that you can't do this flow entirely in the server without Stripe.js involvement
Because a good portion of these payments are going to require 3DS/auth from the user
I pass you a customer on Stripe, is mine I just tried
cus_LveVg1CAg4lQF9
I did the current logic, so created a payment_intent and confirmed server-side
so the pi_3LDnKvApMCw5clA31WHU0bCF went to requires_action
and this is what happend on the platform
redirect to home page,
redirect to 3ds page
confirmed payment
and later insufficient funds
so I don't understand why this worked (pi_3LDnKvApMCw5clA31WHU0bCF is mine) and this one don't (pi_3LDbcHApMCw5clA31mqPheW2 another customer)
the only difference I see is that mine is like this:
"next_action": {
"type": "use_stripe_sdk",
"use_stripe_sdk": {
"type": "three_d_secure_redirect",
}
}
and the customer's one is like this:
"next_action": {
"type": "use_stripe_sdk",
"use_stripe_sdk": {
"type": "stripe_3ds2_fingerprint",
}
}
Yep, this is why you should use Stripe.js instead of handling the next action yourself!
In this case its a 3DS2 biometric auth (i.e. FaceID, TouchID or similar)
Which I guess your integration can't handle because you're not using Stripe.js
so when I land on my platform I need to redirect the customer to a custom page with Stripe.js?
Yep, using confirmPayment from Stripe.js: https://stripe.com/docs/js/payment_intents/confirm_payment
confirmPayment or confirmCardPayment? beacuse earlier you linked me this: https://stripe.com/docs/payments/payment-intents/verifying-status
Yeah, sorry. you need this: https://stripe.com/docs/js/payment_intents/confirm_card_payment#stripe_confirm_card_payment-existing
As you're not using Payment Element and have an existing pm_xxx object
ok thanks! but into the page what I need to put? the html I mean
to let Stripe build the page with JS
Well this is the thing, if requires_action you're gonna need to bring your user back to a page in order for them to complete the 3DS auth
So you'll need to build that page/UI
btw, if you were using Billing we take care of a lot of this
so for example a page with a button, anche the action of that button is:
stripe
.confirmCardPayment('{PAYMENT_INTENT_CLIENT_SECRET}', {
payment_method: '{PAYMENT_METHOD_ID}',
})
.then(function(result) {
// Handle result.error or result.paymentIntent
});
?
Yup ๐
Billing is the subscriptions logic from Stripe?
Yep, exactly
we just moved away from this ๐
Oh, how come?
because we have multiple gateways in our application so we don't want to have customer data all over them,
we have everything on our database and the make a single payment when needed
So with confirmCardPayment I don't need to do something like:
var stripe = Stripe('#{Rails.configuration.stripe[:publishable_key]}');
var elements = stripe.elements();
var card = elements.create('card', {style: style});
card.mount('#card-element');
?
to get a stripe form
Yes, you'll need to initialise Stripe.js but you don't need an Elements instance no (as you already have the pm_xxx object)
If you wanted the user to provide new payment details then you'd need a Card Element yes
Sure, my colleague @limpid zenith is taking over now โ they can answer any follow-ups!
How do you mean?
If the 3ds is successfull I need to redirect the user to another URL
You'd do that in your promise chain:
stripe
.confirmCardPayment('{PAYMENT_INTENT_CLIENT_SECRET}', {
payment_method: '{PAYMENT_METHOD_ID}',
})
.then(function(result) {
if (result.paymentIntent) window.location.assign(redirect)
});
oh ok thanks a lot!! ๐
Hi @warm mountain ๐ re-opened
Hi thanks!
I'd like to ask about the PAYMENT_INTENT_CLIENT_SECRET
I'm passing the pi_ but it tells me that is wrong. What I'm I missing?
What is the exact error that you are getting here?
Does it have the format pi_1234 or pi_1234_secret_5678?
It will be in the client_secret field on the payment intent object after you have created it https://stripe.com/docs/api/payment_intents/object#payment_intent_object-client_secret
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.