Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

johnchomp's avatar

Managing subscriptions (without Cashier)

Unfortunately, I'm unable to use Cashier. I have two odd use cases that prohibit it. 1. I need to handle 1.5 year subscriptions and 2. I have a tier that is basically a 3 month subscription that you agree to up front and can't cancel. After 3 months, your subscription ends.

I'm curious as to how you would handle this. Here's my solution. I feel like it's overly complicated and that I'm not making use of some XYZ feature I don't even know about. More importantly, I feel like it's not reliable in any way.

I'm using Stripe and when a user signs up, I create a Stripe customer object and store their card info in a DB. I set the time they signed up and then set the subscription end date to 3 months. I also set a column "isactive." I plan on running a daily cron task that checks each users end subscription date. If todays date = the users start date + 30 days, Ill charge them. If its 60 days, I charge them. if it 90 days, I dont charge them, but I set the isactive column to no.

My other alternative would be to actually create a subscription plan inside Stripe and then use web hooks to cancel it at the very end.

I just feel like there's an easier way here. If I weren't handling people's money here, I would just roll with it and see what happens.

Also, what happens if the server for some reason doesn't execute the job? Do I set it to charge exactly after 30 days on the second?

Any insight would be greatly appreciated

0 likes
13 replies
MikeHopley's avatar

I'm using Stripe and when a user signs up, I create a Stripe customer object and store their card info in a DB.

Are you sure you want to store their card info in your database? This opens you up to a lot of risk, and burdens you with PCI compliance. It would be better to store Stripe's card "reference", and not store the actual card info.

I just feel like there's an easier way here. If I weren't handling people's money here, I would just roll with it and see what happens.

Your can either handle the charge schedule yourself, or you can create a subscription in Stripe (i.e. sign them up to a plan). Either way you're going to have to do some work.

Also, what happens if the server for some reason doesn't execute the job? Do I set it to charge exactly after 30 days on the second?

You are going to need to rely on cron regardless. Even if you let Stripe handle the subscription, you will have to tell Stripe when to cancel the agreement.

If you do choose to let Stripe handle the subscription, then you can use the cancel_at_period_end flag to tell Stripe to stop the subscription but not immediately. Depending on how your implementation works, this may be useful. See the Stripe documentation about cancelling.

MikeHopley's avatar

Oh one more thought...

If you're worried about cron reliability, you can always use cron to set up some kind of monitoring -- so you send yourself an email every week, saying something like this:

Subscriptions: 35
    ...with 1 payment: 5
    ...with 2 payments: 10
    ...with 3 payments: 5
    ...with 4+ payments: 0
Active subscriptions: 20
Cancelled subscriptions: 15
johnchomp's avatar

Monitoring sounds like a good idea. I'm definitely not storing any sensitive data on my server. Just the Stripe customer token which I can use to make charges.

jekinney's avatar

I understand this may not be your answer or want to read, but cashier is just a wrapper around stripes PHP plugin to provide laravel like syntax with some added features that ties into (mainly) your user model. If your using stripes PHP Api in Laravel your kinda reinventing the wheel.

jekinney's avatar
  1. 3 month one time subscription.

Set up an end date three months from time of purchase and update the default cashier migration. Cashier handles one time payments. Set up a subscription name in stripe that conveys that. Done in a few lines of code.

  1. year and a half subscription same as above. But obviously cfg for your use case.

Not to be mean, of course it's an uneducated statement because of the limited knowledge of your apps scope, but the two reasons mentioned that don't fit in cashier are wrong. They do fit.

johnchomp's avatar

How would I setup a 1.5 year subscription in Stripe? The max you can set a subscription to is 1 year. If you're not dealing with subscriptions in the usual sense, Cashier has limited value. For example, you can't retrieve invoices for one off charges.

Not sure how I'd be as to use Cashier/Stripe for 1.5 year subscriptions when their API doesn't allow it?

handy_man's avatar

I just looked at my stripe dashboard and I'm able to create a custom plan on Stripe which seems to allow any amount of time that you specify (in either Months, weeks or days).

Then you simply apply the user to that plan and you're good to go with using stripe and cashier.

MikeHopley's avatar

If your using stripes PHP Api in Laravel your kinda reinventing the wheel.

Yes and no.

For example: I want to offer Paypal as a payment option as well. Cashier cannot do this.

Cashier is convenient, but it puts Stripe right at the centre of your business. I would rather have Stripe payments be an implementation of my subscription interface. Then I can add a Paypal implementation too.

With that said, Cashier is a great option in many cases.

1 like
johnchomp's avatar

@handy_man try to set it to over 12 months or 365 days. It won't let you.

This actually seems to be a common limitation in most payment gateways. I'm guessing it's because most cards will probably expire or people will end up forgetting and try to charge back.

Cashier and stripe also don't handle coupons for one off purchases, which I'm starting to have a separate issue with trying to implement.

handy_man's avatar

@johnchomp You are correct, I didn't bother to try and make a plan because I just sort of assumed that custom was without limitation rather strange that they don't offer something a bit larger than a year.

Have you considered giving them a 6 month plan (charged at 18 month amount) and then automatically crediting their account for the other 2 payments set to occur (will make your $$ reporting completely broken though).

EDIT: It would also break invoices generated by stripe/ cashier so you would have to deal with that issue too.

johnchomp's avatar

@handy_man I didn't know either until I actually tried to create a plan.

I was so excited when I first discovered Cashier, but was quickly disappointed.

I'm just going to do CRON jobs. I already have to build everything from scratch for coupons (which is a huge pain) and invoices.

I'm actually surprised there's so few options other than roll my own. I don't think my needs are too uncommon (general one off charges).

But then again, what's the point of being a developer if I'm not actually developing anything :P

Handling money just freaks me out a bit.

jekinney's avatar

@handy_man very valid point.

@johnchomp not sure on payments as far as monthly, but just to set the expiration date I have used carbon to add from today and set that date in your database. Actually you can just do one off payments when you get the token back set the expiration date code in your app as per your requirements. I implement that quite a bit so clients can dynamically set many of these parameters in the app and not back and fourth with stripe. You can also set recurring payments and one off invoices too.

Like I said cashier is nothing more then a wrapper for stripes PHP API to a laravel type syntax.

As @handy_man eluded to you can create your own to use other options too.

Please or to participate in this conversation.