#ziminny-subscription-3ds

1 messages Ā· Page 1 of 1 (latest)

vagrant cypress
#

hey there, do you mind moving your messages into this thread?

uncut kelp
#

no problem , i may even lose my service if i do not fix it . Thanks
😭

vagrant cypress
#

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.

uncut kelp
#

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'})
}

})`

vagrant cypress
#

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

uncut kelp
#

ok

lethal lance
#

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?

uncut kelp
#

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

lethal lance
#

What's the error?

uncut kelp
#

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, }

lethal lance
#

Which line of code from above triggers that error?

uncut kelp
#

if(response2.error) { console.log("Deu erro na segunda etapa"); console.log(response2.error); return }

lethal lance
#

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?

uncut kelp
#

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

lethal lance
#

Can you change console.log(response2.error); to console.log(response2);, try again, and see if there's more information logged that might help?

uncut kelp
#

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, }

lethal lance
#

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...

uncut kelp
#

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

lethal lance
#

That would go in your if(status === 'requires_action') { block instead of the Payment Sheet code you have there now.

uncut kelp
#

` 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"}}]'

lethal lance
#

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?

uncut kelp
#

the lines that are commented all work out

lethal lance
#

You should not need to specify type when the Payment Intent has a status of requires_action. Hang on...

uncut kelp
#

ok

#

I'm using the EAS Build from the expo, but I'm testing it locally, I think that doesn't interfere, right

lethal lance
#

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'
}
uncut kelp
#

šŸ˜

lethal lance
#

Which approach worked?

uncut kelp
#

{ type: 'Card' paymentMethodId: 'pm_123' }

lethal lance
#

Awesome!

uncut kelp
#

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

lethal lance
#

Sorry about that! We'll work on improving the documentation/SDK here.