#ziminny-subscription-3ds
1 messages Ā· Page 1 of 1 (latest)
no problem , i may even lose my service if i do not fix it . Thanks
š
Sorry, i was waiting for you to delete the messages and move them in here
Can you do that?
But, what exactly is the issue you run into here?
You mention payments with 3ds for subscriptions but then I'm not sure how the code you shared relates to that.
I posted the wrong codes , sorry I missed one , I will post it again
------ --- FRONTEND --- -----
`await api.post("/stripe-webhook/create-subscription-first", {
customerId:user.stripe_customer_id,
priceId:price.id
}).then( async res => {
const { status , client_secret ,id } = res.data.subscription.latest_invoice.payment_intent
const { ephemeralKey , customerId } = res.data
if(status === 'requires_action') {
const response = await initPaymentSheet({
customerId,
paymentIntentClientSecret:client_secret,
customerEphemeralKeySecret:ephemeralKey,
})
await new Promise( (resolv , reject) => setTimeout(() => resolv(''), 2000) );
if(response.error) {
console.log(response.error);
return
}
console.log(response);
const response2 = await presentPaymentSheet({
clientSecret: id,
})
if(response2.error) {
console.log("Deu erro na segunda etapa");
console.log(response2.error);
return
}
console.log("SUCCESS");
}
}).catch( error => {
console.log("Error ");
console.log(error);
})`
---- --- BACKEND --- ----
`router.post('/create-subscription-first', async (request , response) => {
const {customerId,priceId} = request.body
try {
// await setPaymentMethodDefault(customerId)
const ephemeralKey = await stripe.ephemeralKeys.create(
{
customer:customerId
},
{
apiVersion:'2020-08-27'
}
)
const subscription = await stripe.subscriptions.create({
customer:customerId,
items:[
{
price:priceId
}
],
default_payment_method:'pm_1JmiOuCm39JVmPJupnamGtCq',
payment_behavior: 'allow_incomplete',
expand: ['latest_invoice.payment_intent','pending_setup_intent'],
})
console.log(subscription);
return response.json({ subscription, ephemeralKey:ephemeralKey.secret , customerId })
} catch (error) {
console.log("Error Create Subs");
console.log(error);
return response.status(404).json({error:'Error'})
}
})`
OK and can you explain the sequence of calls that ultimately leads to an unexpected error for you?
I need to step away, but my colleague @lethal lance is joining in
ok
Hello! Thanks for sharing your code! What problem do you have with this code exactly? You said it was something to do with Subscriptions that require 3D Secure?
When I create a payment , or a payment method everything goes well , when I pay a payment it goes well , when I pay a payment with paymentintents without a subscription it goes well , the only thing I can not do is pay a subscription , it generates an error in presentPaymentSweet and opens and closes the modal very quickly
What's the error?
ERROR LOG ----->>> Object { "code": "Failed", "declineCode": null, "localizedMessage": "The operation couldnāt be completed. (Stripe.PaymentSheetError error 0.)", "message": "The operation couldnāt be completed. (Stripe.PaymentSheetError error 0.)", "stripeErrorCode": null, "type": null, }
Which line of code from above triggers that error?
if(response2.error) { console.log("Deu erro na segunda etapa"); console.log(response2.error); return }
Ah, so above that you have this:
const response2 = await presentPaymentSheet({
clientSecret: id,
})
It looks like you're setting clientSecret to id (the ID of the Payment Intent) instead of its client secret.
If you fix that issue do you get past that error?
const response2 = await presentPaymentSheet({ clientSecret: client_secret, })
I've tried that too , gives the same error
I switched to id out of desperation because nothing is going right
Can you change console.log(response2.error); to console.log(response2);, try again, and see if there's more information logged that might help?
just a moment
same thing. The error message on android is different, I'll send you
Object { "code": "Failed", "declineCode": null, "localizedMessage": "A PaymentIntent with status='requires_payment_method' is required. The current PaymentIntent has status requires_action. See https://stripe.com/docs/api/payment_intents/object#payment_intent_object-status.", "message": "A PaymentIntent with status='requires_payment_method' is required. The current PaymentIntent has status requires_action. See https://stripe.com/docs/api/payment_intents/object#payment_intent_object-status.", "stripeErrorCode": null, "type": null, }
Ah, okay, that's the detail we need! It looks like the Payment Intent is in requires_action status, so let me see what you need to use in React Native to handle it...
in my initial file it is defined like this:
I understand, that's it, isn't it?
`useEffect(() => {
initStripe({
publishableKey:'pk_test_......nH',
})
},[])`
I already have the card added in this part , if I try to create a subscription without the payment method I get an error , my idea is to create the method before and after paying , if I could do this with the subscription in the frontend it could be too , but I don't know if it's possible to link a customer without a payment method to a subscription
Sorry for the delay, I wanted to make sure I had the right answer for you. Instead of using the Payment Sheet all you need to do for a Payment Intent in requires_action status is call confirmPayment(client_secret): https://stripe.dev/stripe-react-native/api-reference/modules.html#confirmPayment
That would go in your if(status === 'requires_action') { block instead of the Payment Sheet code you have there now.
` const {error , paymentIntent} = await confirmPayment(client_secret)
if(error) {
console.log(error);
return
}
console.log(paymentIntent);
console.log("Success");`
ERROR -->> Object { "code": "Failed", "declineCode": null, "localizedMessage": "You must provide paymentMethodType", "message": "You must provide paymentMethodType", "stripeErrorCode": null, "type": null, }
const {confirmPayment} = useStripe()
OR
const {error , paymentIntent} = await confirmPayment(client_secret,{ type:'Card' })
ERROR _>> Invariant Violation: No callback found with cbID 74606 and callID 37303 for StripeSdk.confirmPaymentMethod - most likely the callback was already invoked. Args: '[{"error":{"stripeErrorCode":null,"declineCode":null,"localizedMessage":"Unhandled error occured","message":"Unhandled error occured","type":null,"code":"Unknown"}}]'
Can you post all of your frontend code instead of just a snippet? Also, can you use three backticks to create a code block instead of doing all inline code?
You should not need to specify type when the Payment Intent has a status of requires_action. Hang on...
ok
I'm using the EAS Build from the expo, but I'm testing it locally, I think that doesn't interfere, right
Ah, okay, unfortunately it looks like this is a known issue: https://github.com/stripe/stripe-react-native/issues/614
There are some workarounds in that thread, but basically what you should do is attempt to confirm the Payment Intent server-side and specify it's an off-session confirmation. If that succeeds you're good to go. If it fails the Payment Intent will revert to requires_payment_method and then you can use it with the Payment Sheet in your app.
One thing that might be worth trying is specifying both type and paymentMethodId when calling stripe.confirmPayment:
{
type: 'Card'
paymentMethodId: 'pm_123'
}
Which approach worked?
{ type: 'Card' paymentMethodId: 'pm_123' }
Awesome!
It's kind of bad for me, but I think I can move on. thank you very much , it was 3 days trying to solve this
Sorry about that! We'll work on improving the documentation/SDK here.