laravel / cashier-stripe

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.
https://laravel.com/docs/billing
MIT License
2.37k stars 672 forks source link

Subscription details do not get updated when changing subscription plan via customer portal #1111

Closed louis-l closed 3 years ago

louis-l commented 3 years ago

Description:

Im not sure if this is a bug or something that is not supported. I try to test the subscription locally using Stripe CLI. New subscription works just fine (webhooks are sent and handled, new records are created in subscriptions and subscription_items correctly). But when I try to update subscription plan to a different plan (let say from plan A to plan B) via customer portal, everything works fine in Stripe GUI, but when I get redirected back to my app, my subscription plan is still A. I checked and nothing is changed in subscriptions and subscription_items table.

Here is the screenshot of the Stripe CLI webhooks that I received when changing the plan: Screen Shot 2021-04-03 at 5 34 35 pm

Steps To Reproduce:

(described above)


I also checked the https://github.com/laravel/cashier-stripe/blob/12.x/src/Http/Controllers/WebhookController.php and it does not seem to handle any of the 3 events from the screenshot above.

Am I missing something or can you please point me to the right direction?

Thanks.

driesvints commented 3 years ago

Did you add all events to your webhook as detailed in the docs? https://laravel.com/docs/8.x/billing#handling-stripe-webhooks

image

louis-l commented 3 years ago

Thanks @driesvints

According to https://stripe.com/docs/webhooks/test

The Stripe CLI is the easiest and fastest method for testing your webhook endpoint. With the Stripe CLI you can begin listening for–and even triggering–events without any additional configuration.

So I thought we dont need to add any events in Stripe dashboard. That explains why when I first subscribed, it worked (e.g. new records got inserted in subscriptions and subscription_items tables)

louis-l commented 3 years ago

I also added 2 event listeners to listen to WebhookReceived and WebhookHandled, then log the entire payload to test if the webhooks are hitting my local app or not. And yes, its working, all the webhooks are received via Stripe CLI without any configuration.

driesvints commented 3 years ago

I'll need code to reproduce this. If you can give me that I'll try on Monday. Also tell me how you set up your products and prices.

louis-l commented 3 years ago

Here is the controller to generate checkout session (for new subscription):

public function __invoke(Request $request)
{
    $checkout = $team
        ->newSubscription('default', 'price_xxx')
        ->allowPromotionCodes()
        ->checkout([
            'success_url' => 'my_url',
            'cancel_url' => 'my_url',
        ]);

    return response()->json([
        'sessionId' => $checkout->asStripeCheckoutSession()->id,
    ]);
}

Im using Vue for the frontend, and here is where the session ID is used:

redirectToStripeCheckoutUsingSessionId(sessionId) {
  const stripeKey = process.env.STRIPE_KEY

  window.Stripe(stripeKey)
    .redirectToCheckout({ sessionId })
    .then((result) => {
      if (result.error) {
        this.$alert(result.error.message, null, {
          confirmButtonText: this.$t('action.close'),
        })
      }
    })
},

This is the controlled to generate the Stripe Customer Portal url (for updating current subscription):

public function __invoke(Request $request)
{
    return $this->response()->json([
        'url' => $team->billingPortalUrl('my_url'),
    ]);
}

And then in frontend app, just redirect to that url using window.location.replace(url)


For the setting up products and prices, basically I just follow Stripe docs:

Screen Shot 2021-04-04 at 8 03 10 am

Let me know if you need anything else.

louis-l commented 3 years ago

I do some more tests again (hope that helps) and here is the Stripe webhooks that I received:

  1. First subscribe to plan A 1 - subscribe to plan A

  2. Update to plan B (higher price) 2 - update to plan B

  3. Update back to plan A 3 - update back to plan A

  4. Cancel subscription 4 - cancel plan A


All the steps worked just fine except for step 2. Question is: should step 2 fire customer.subscription.update event?

driesvints commented 3 years ago

I just tested this myself and I can use the Stripe CLI's listen command just fine:

Screenshot 2021-04-05 at 17 03 10

Since this isn't a support channel I can't help you out further. Please try a support channel:

Thanks.

louis-l commented 3 years ago

Thanks @driesvints

Im not sure how did you test this, but the issue here is not about testing Stripe CLI (e.g. receiving webhooks), its about updating subscription plan via Stripe Customer Portal and the change does not reflect in Cashier database.

If you have tested exactly the steps I described in https://github.com/laravel/cashier-stripe/issues/1111#issue-849595170 and it worked on your end, then please let me know and I will contact Stripe to see if they can help.

Cheers,

driesvints commented 3 years ago

Thanks for clarifying. I'll take another look later this week.

driesvints commented 3 years ago

I'm sorry but I can't reproduce this. Subscription record and item in the database are updated after switching plans. I'm using: stripe listen --forward-to localhost:8000/stripe/webhook

I'm afraid I can't help you out further here. Please try a support channel:

louis-l commented 3 years ago

Thanks @driesvints and appreciate you taking time testing this. I will contact Stripe to see if they can spot out anything.

Cheers