1

I created a subscription as described on https://stripe.com/docs/billing/subscriptions/elements but now I want to give the user the choice to change the plan on the subscription and use another payment method, ex 3d Secure card. However if I update the subscription to get a client secret for a new payment intent as following:

func (c *Client) UpdateSubscription(s *models.Subscription) (*models.Subscription, error) {
    sps := &stripe.SubscriptionParams{
        DefaultPaymentMethod: stripe.String(s.PaymentMethodId),
        CancelAtPeriodEnd:    stripe.Bool(false),
        ProrationBehavior:    stripe.String(string(stripe.SubscriptionProrationBehaviorAlwaysInvoice)),
    }
    if s.CreatePaymentIntent {
        s.PaymentBehavior = "allow_incomplete"
        sps.PaymentBehavior = stripe.String(s.PaymentBehavior)
        sps.AddExpand("latest_invoice.payment_intent")
    } else if s.ItemID != "" {
        sps.Items = []*stripe.SubscriptionItemsParams{
            {Price: stripe.String(s.PriceID)},
            {ID: stripe.String(s.ItemID), Deleted: stripe.Bool(true)},
        }
    }
    ss, err := sub.Update(s.ID, sps)
    if ss.LatestInvoice != nil && ss.LatestInvoice.PaymentIntent != nil {
        s.PaymentIntentClientSecret = ss.LatestInvoice.PaymentIntent.ClientSecret
    }
    return s, err
}

the PaymentIntentClientSecret is the same for the subscription which means it is already processed. Stripe 'confirm card' API is throwing error payment_intent_unexpected_state https://stripe.com/docs/error-codes/payment-intent-unexpected-state and that's probably because I used that payment intent previously to create the subscription. However I still need a new payment intent to authorise the new card.

Gadelkareem
  • 1,067
  • 13
  • 30

1 Answers1

0

What is the status of the PaymentIntent that you are getting these errors on?

It looks like you are properly updating the Subscription’s Price and PaymentMethod as well as creating a new Invoice for this proration. If that is the case, the Invoice may automatically be getting paid on that update. So this error might be happening because you are trying to confirm a PaymentIntent that has already successfully charged your customer.

I think it would be good to check the status of the LatestInvoice’s PaymentIntent when you get the updated Subscription object in your function.

  • If the status is succeeded you can simply send the customer back that updating their subscription was successful.
  • If the status is requires_action you should send the PaymentIntent’s client secret back to your client side and call handleCardAction[1] to allow your customer to resolve whatever action may need to be taken (3DS Auth, etc)
  • If the status is requires_payment_method the new card was declined and you should have your customer input new credit card info to try to update the subscription’s PaymentMethod again.

[1]https://stripe.com/docs/js/payment_intents/handle_card_action

Pompey
  • 943
  • 2
  • 6
  • 1
    The payment intent status is `succeeded` but that's the old payment intent for a different payment method which I changed on the subscription. I do not understand why Stripe is not requiring a new payment intent if the default payment method already changed! – Gadelkareem Oct 08 '21 at 00:48
  • 1
    I'm having trouble with this one too. Did you find a solution? It seems we need a way to generate a new PaymentIntent for subscription proration updates without actually modifying the subscription. – douliman Jan 08 '22 at 00:29