invertase / stripe-firebase-extensions

Repository of Firebase Extensions built by Stripe.
https://firebase.google.com/products/extensions
Apache License 2.0
423 stars 161 forks source link

If a customer has a failed payment, then successful payment, the claim isn't being set #333

Open Chaddeus opened 2 years ago

Chaddeus commented 2 years ago

Bug report

Describe the bug

If a new subscriber encounters a payment issue during checkout and then leaves to try again later, they end up with two subscriptions stored in Firestore. One is inactive (payment failed subscription) the other is active.

That's fine, except the claim is not getting set appropriately. It's as if the inactive subscription is blocking the active one.

So the user's experience is that they finally just paid for their subscription, get redirected to my app, but my app isn't showing them as subscribed because the claim isn't set.

To resolve I have to go into their Firestore document, remove the inactive subscription, then go into Stripe and add some dummy metadata to trigger the subscription to resync to my Firestore database.

However, this will all happen again to the user because apparently, Stripe holds the unpaid subscription open while awaiting payment -- and after some amount of time flips it to inactive -- triggering another webhook update to my Firestore database, which adds the inactive subscription back to my user again.

So I have to repeat the process of deleting the inactive subscription, going into Stripe to trigger a refresh of the active subscription so the user can log in and use my app.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

The only way to reproduce this is to have a customer first have a failed payment, leave for some amount of time, come back and then successfully complete a payment.

Expected behavior

I would expect that so long as the user has at least one active subscription the claim would be set (as setup in the metadata for the product). I want to have confidence in a reliable claim and active subscription process.

Screenshots

If applicable, add screenshots to help explain your problem.

System information

This is all handled in the Firebase cloud functions set up by the Stripe firebase extension.

FezVrasta commented 2 years ago

Having the same issue, it's causing so many problems to us ☹️

I think it's also somewhat related to this https://github.com/stripe-samples/firebase-subscription-payments/issues/43, it looks like the code isn't able to handle multiple subscription items in the database and just picks a random one (or the oldest one?).

FezVrasta commented 2 years ago

Is anyone from Stripe following this issue tracker?

Chaddeus commented 2 years ago

Having the same issue, it's causing so many problems to us ☹️

I think it's also somewhat related to this stripe-samples/firebase-subscription-payments#43, it looks like the code isn't able to handle multiple subscription items in the database and just picks a random one (or the oldest one?).

Mhmm... that does seem to be what's happening. Maybe not random, but whatever the logic is, it is quite annoying to deal with. I manually go in and delete the "old" subscription from Firestore. Then go back into Stripe and add a bogus metadata change (I usually call it "refresh") so the webhook is triggered and updates the user's subscription in Firestore.

A tedious task. Really need someone from Stripe to track this.

Chaddeus commented 2 years ago

@thorsten-stripe Any chance Stripe is aware of this issue and working on a solution, please? 🙏

cjavilla-stripe commented 2 years ago

Thanks for the report. We'll take a look.

cjavilla-stripe commented 2 years ago

Instead of pushing customers back through Checkout for failed payment, I wonder if redirecting to customer portal would be better so they can update their payment method on the existing Subscription instead of creating a new one.

Trying to think through how we would remove the old subscription and old claim safely. One risk is there's already a successful subscription set up, and for some reason the customer going through checkout again.

FezVrasta commented 2 years ago

The problem happens even if a customer unsubscribes and then later decides to subscribe again.

cjavilla-stripe commented 2 years ago

I think it may have to do with the line where we're setting the claim to null. I feel like we should be deleting the claim or something instead of setting to null.

cjavilla-stripe commented 2 years ago

Seems like our attempt to remove the claim doesn't work as expected: https://stackoverflow.com/a/65081669

Still need to reproduce, but my guess is we need to blow away all claims, then set it to everything except the one we're removing.

Chaddeus commented 2 years ago

Seems like our attempt to remove the claim doesn't work as expected: https://stackoverflow.com/a/65081669

Still need to reproduce, but my guess is we need to blow away all claims, then set it to everything except the one we're removing.

Yea, if it is still true that Firebase forces you to remove all claims, that might introduce other issues -- where the developer might have created their own custom claims.

So when doing this, you may need to collect all the claims first, remove the "old" Stripe claim, then add all the previous claims back along with the new Stripe claim.

FezVrasta commented 2 years ago

Is there any chance for this bug to be addressed? It's critical to provide the service to the customers who paid for them and there's no straightforward workaround available.

colindm commented 8 months ago

Has this been solved or is there a workaround? This is a pain to deal with every time a user resubscribes I have to manually add a stripe role to their email and then keep checking it to make sure they're still subscribed 😒

emilwallner commented 7 months ago

I'm having the same issue. I had to remove the subscriptions in firebase, delete the subscription in Stripe, and then recreate the subscription manually. I'd also really appreciate a workaround for this or a bug fix.

colindm commented 7 months ago

I've given up at this point and started writing my own cloud function to handle payments. This was fine for when I had fewer customers but micromanaging hundreds of customers because of issues with this extension was becoming too time consuming.