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 671 forks source link

Check if subscribed to any plan #961

Closed liran-co closed 4 years ago

liran-co commented 4 years ago

If there are multiple price plans available on a product, it seems the only way to check if a user is subscribed to a product is by using subscribedToPlan and passing in every price id. Is there any reason we can't check based on product? In most cases, we just need to check if a user is subscribed to a certain product, it doesn't matter what pricing plan they are on. If we added a new pricing tier (ex: "quarterly"), we'd need to redeploy our app to check for that.

In theory the solution is to just check based on the name field, by using subscribed(), but that doesn't work in the case that we have multiple products or addons in a single subscription (i.e. I wouldn't be able to check if they have the "live-chat" add-on).

driesvints commented 4 years ago

Hey @liran-co. Define "add-on" please. I think you're just looking for a simple query with scopes?

// Check if the user has at least one active subscription
$user->subscriptions()->active()->count();

// Check if the user has at least one subscription (any state).
$user->subscriptions()->count();
liran-co commented 4 years ago

"Add-on" doesn't really mean much in this context, it's just a way to think about the use case. In our case a user can subscribe to "live-chat" separately or as part of another subscription.

For example, if we had a Pro and Enterprise plan plus a "live-chat" add-on where the user could either purchase "live-chat" separately or with a Pro / Enterprise plan. In that case, if we wanted to check in our app whether or not they are subscribed to the "live-chat" add-on, we need to check three cases:

  1. Check if the user is subscribed('live-chat')
  2. Check if the user is subscribedToPlan('live-chat', 'pro')
  3. Check if the user is subscribedToPlan('live-chat', 'enterprise')

Plus on top of this, if "live-chat" had a monthly or yearly option, we'd need to check for both pricing plans.

There's actually three issues here that are related:

  1. If we offer Pro/Enterprise, should those be the name of the subscription? Or should that still be something like default?
  2. In the latter case for 1, we need to pass every pricing id to check if they are subscribed to a product
  3. Depending on the answer to 1 & 2, if a product can be subscribed to independently and part of another subscription, checking for it becomes quite difficult.
driesvints commented 4 years ago

I think you've just modelled your subscription flow not really optimal. I'd tackle the add on with a subscription item instead. This might be a better question to ask on a support channel so I'm kindly directing you to one of these channels as this tracker is only for feature requests or bugs:

liran-co commented 4 years ago

Sure...but either which way you model it doesn't solve the problem. Seems like this is the key to make this work: https://github.com/laravel/cashier/issues/956.

driesvints commented 4 years ago

It's not since that only will rename a bunch of internal variables and methods. No structural changes will be applied for that issue.

liran-co commented 4 years ago

Ideally we'd store the product id though, not just the plan id that way we can check if they are subscribed to a specific product, regardless of plan.

driesvints commented 4 years ago

But that's stored for you? That's the stripe_id that you need on a subscription I think.

liran-co commented 4 years ago

That's the Stripe subscription id, not the product id though. Ideally we'd store a product_id in addition to the stripe_plan. Plans live under Products so doing so would provide us a way to check the existence of a subscription to a product without caring what pricing plan they are on.

driesvints commented 4 years ago

Gotcha. I haven't had time to really dive deeply into Stripe products yet. It's only recently been released. I also don't think I'll get around to this soon tbh.