Stripe Subscriptions with trial
Hello all.
Have a question about Wave SAAS functionality with Cashier. Might sound a bit strange, but from reading many many docs, it seems as if I build an application offering Cashier subscriptions with Stripe, the Cashier module will track automatically and update my user subscriptions from regular user to:
- Trial - when the user pass the Stripe checkout payment page with correct details and enrolls into the subscription trial as set in Stripe for the specific subscription plan
- Premium - when the user has passed the trial and is charged for the premium subscription.
- Regular user - when the premium subscription has expired and the user did not renew their premium.
Looking at the code, I am able to charge the user for any subscription etc. but what I am not able to understand yet is where/how would the detection happen in the code and if it is really happening on the backend without any need of some extra custom code for such functionality.
Can anybody shed some light about these events as I know Stripe supports webhooks but I am not sure if we are all set for tracking the changes and updating user status automatically...
Hey Mike 👋
Yep exactly! You should be able to do that with the Stripe webhooks.
Cashier has a builtin support for handling those as well.
And from that Stripe Wave PR, you should have it available as well:
And from the PR readme file:
If you are using the Paddle Payment provider, the webhook is already configured; however, if you are using Stripe you will need to add the following URL to your
routes/web.php
in order to listen Cancel or Updates in the client account.
YOUR_URL/wave-stripe/webhook
Let me know if this works for you!
- Bobby
Hello Bobby.
Seems like the #38 has already adding all the required routes as I had those out of the box added to my wave/routes/web.php:
// Stripe routes
if (env('CASHIER_VENDOR') == 'stripe') {
Route::post('stripe/create-checkout-session', '\Wave\Http\Controllers\StripeController@postCreateCheckoutSession')->name('stripe.create-checkout-session');
Route::get('stripe/success-checkout-session', '\Wave\Http\Controllers\StripeController@postSuccessCheckout')->name('stripe.success-checkout');
Route::get('stripe/error-checkout-session', '\Wave\Http\Controllers\StripeController@postErrorCheckout')->name('stripe.error-checkout');
Route::get('stripe/billing-portal', '\Wave\Http\Controllers\StripeController@getBillingPortal')->name('stripe.billing-portal')->middleware('auth');
Route::post('wave-stripe/webhook', '\Wave\Http\Controllers\WebhookController@handleWebhook')->name('stripe.webhook');
}
I will test if a change in the code triggers a change as well on the application and get back to you. This time I've setup a fresh install where I only changed the plans price_id to make sure what is the working code out of the box.
My biggest issue is to have a webhook action for switching from regular user to a Trial (after providing payment details to Stripe) and when the Trial is over, to switch to a premium user after being charged automatically.
From what I've read Stripe does issue an invoice from the beginning while in DEV/test mode as to facilitate the testing side, but I need the user webhook to catch a switch from successful payment data collection to change the status to Trial and to change the status to Premium after the trial expiry...
Hey Bobby,
I've tested on a fresh install to see how does Wave/Stripe process a trial and I made sure to have selected the trial days in the plan details (admin->plans) but in the subscriptions I see the column: trial_ends_at to be totally empty even though I have set the same trial days in my Stripe admin too.
Are there any settings to allow the trial as from what I see, Stripe is sending a webhook signal for the expiration of a subscription in the formula:
plan_duration + trial days, but the invoice is issued right away and for my understanding if a user is enrolled in a trial, it has the right to cancel it before being enrolled to a trial without being charged...
Actually, inside of the StripeController.php I am finding a value request for the trial days which can be set via admin panel > settings, but this is global for all plans even though each plan BREAD has it's own trial option so I am confused where is the trial set from admin > plans used if we have a global settings variable set to -1 in the admin panel settings?
$trial_days = setting('billing.trial_days', 0);
$trial_ends_at = null;
// if trial days is not zero we will set trial_ends_at to ending date
if (intval($trial_days) > 0) {
$trial_ends_at = now()->addDays(setting('billing.trial_days', 0));
}
And since the creation of the script, Stripe has changed their policy to prevent allowing a trial per price of a product so I believe there is a missing workflow to intercept a call now from Stripe about the trial expiration and return a webhook to be catched so that we update an user status from Trial to Premium...