#Andora

1 messages · Page 1 of 1 (latest)

onyx wolfBOT
elder grove
#

Can you share the subscription ID?

magic cypress
#

sub_1LuWn2BvZmAnxmFyN4YmSJfk

#

As you can see I had another plan before updating but it overwrite the existing subscription even though I canceled the auth

#

Right now I'm calling the update subscription method with payment_behavior = allow_incomplete on server side

elder grove
#

What are you trying to achieve?

magic cypress
#

I'm trying to update an existing subscription and deal with the case where the user cancel the 3d secure auth. Because right now even if he cancel the 3d secure auth, the subscription stay incomplete and is overwritted with the new plan instead even though it should stay on the original plan before updating since it got cancelled

#

here are the step I follow

  1. Create subscription (server side) or Update subscription
  2. Check subscription.latest_invoice.payment_intent.status === "requires_action"
  3. Send subscription.latest_invoice.payment_intent.client_secret to the client
  4. Call confirmCardPayment using the payment_intent_secret
#

this work well when you don't already have a subscription, but if I already have one it will overwrite the existing subscription if I cancel and will stay in incomplete status and never go back to the original plan

elder grove
magic cypress
#

I tried payment_behavior=pending_if_incomplete but I don't have access to both metadata field and default_payment_method when using it

#

Which mean I cannot update the payment method if needed

steady dove
#

I don't have access to both metadata field and default_payment_method when using it
Not sure what you mean by this. Access where?

magic cypress
#

this is how the call to update looks on server side

stripe.subscriptions.update(
          existingSubscription.stripe_id,
          {
            items: [
              { id: subscription.items.data[0].id, price: plan.stripe_id },
            ],
            default_payment_method: paymentSource.token,
            metadata: {
              plan_id: plan._id.toString(),
              payment_source_id: paymentSource._id.toString(),
            },
            proration_behavior: "always_invoice",
            expand: ["latest_invoice.payment_intent"],
          }
        
#

I'm passing the payment method when updating

#

but if I use pending_if_incomplete these fields cannot be used

steady dove
#

Sure, that's expected. The general approach here is to bring your customer back on-session to re-confirm the associated PI and complete 3DS, optionally providing an alternative payment method

magic cypress
#

In my case payments method are already setup but when calling subscription.update I can pass one of the already set up payment_method. Should I use pending_if_incomplete and if yes where can I pass the payment method ?

steady dove
#

Well, you can't as pass them in the same call as you've discovered. You'd likely need to make 2 separate calls

#

Either way, your integration still needs to account for that fact that update the subscription may still trigger 3DS/auth request from the bank irregardless of if you've previously setup the card

magic cypress
#

but is using pending_if_incomplete the correct way to update the subscription in case 3d secure got cancelled ?

steady dove
#

Well, it just prevents the requested updates from applying until the associated payment succeeds if that's the desired behaviour

#

You can handle 3DS without pending_if_complete still, just means you'll need to manually rollback the updates if payment(s) fail

magic cypress
#

Ok so if I don't use pending_if_complete I need to roll back to the previous subscription plan ?

#

And I guess this is when receiving payment failed event from the webhooks right ?

magic cypress
#

thank you. Last question, when receiving a failed payment intent in webhooks how can you retrieve the previous user plan before updating to another plan so it can be rollbacked

steady dove
#

There's no automatic way to do that, it's a pretty laborious task:

You need to create a new invoice, prorate items on the invoice, and then initiate payment again. However, with the pending updates feature, you can make changes to subscriptions only if payment succeeds on the new invoice.

magic cypress
#

I see, thank you for your help

steady dove
#

np!

magic cypress
#

Just wondering, any reason why invoice.payment_failed is called even before completing the 3d secure auth

#

because it's called twice for me, one before authorizing and second time when cancelling (this one make sense).

steady dove
#

Sure, because the initial payment attempt (which triggers 3DS) is technically a failure

magic cypress
#

the issue I have is that I insert a new payment instance in my database when receiving the payment failed event. But since it fails even before completing the auth I have two payments inserted instead of one. Is there anyway to difference it to avoid inserting twice ?

steady dove
#

Well it's technically the same payment, just separate attempts. The in_xxx is the same, as is the associated Payment Intent (pi_xxx)

#

Your modelling of it in that regard is wrong. You should map your payment instances against either the in_xxx or the pi_xxx, not on a payment_failed event

magic cypress
#

But aren't my instance supposed to be created in webhook when listening to specific event ?

steady dove
#

Because you're creating 2 payment 'instances' for what is the same payment/invoice

#

In reality, you'd probably update the 'instance' in your DB to reflect the failed status

magic cypress
steady dove
#

Yes, that's how I would handle it

magic cypress
#

Make sense thank you