To implement a system where users receive virtual credits based on their subscription plan using Laravel Cashier for Stripe, you can follow these steps:
-
Define Your Plans and Credits: First, define the number of credits each plan should provide monthly. This can be stored in a configuration file or a database table.
-
Handle Subscription Changes: Use Stripe webhooks to handle subscription changes. Specifically, you can listen to
invoice.payment_succeededfor monthly credit allocation andcustomer.subscription.updatedfor plan changes. -
Implement Webhook Logic: Create a webhook controller to handle these events. You can use Laravel's built-in webhook handling capabilities.
-
Daily Cron Job: While a daily cron job might seem inefficient, it can be optimized. You can run a job that checks only users whose subscription cycle is due for credit allocation.
-
Code Implementation:
-
Webhook Controller:
use Illuminate\Http\Request; use App\Models\User; class StripeWebhookController extends Controller { public function handleInvoicePaymentSucceeded(Request $request) { $payload = $request->all(); $subscriptionId = $payload['data']['object']['subscription']; $user = User::where('stripe_subscription_id', $subscriptionId)->first(); if ($user) { $this->addMonthlyCredits($user); } return response('Webhook Handled', 200); } public function handleSubscriptionUpdated(Request $request) { $payload = $request->all(); $subscriptionId = $payload['data']['object']['id']; $user = User::where('stripe_subscription_id', $subscriptionId)->first(); if ($user) { $this->handlePlanChange($user, $payload['data']['object']); } return response('Webhook Handled', 200); } protected function addMonthlyCredits(User $user) { $plan = $user->subscription('default')->stripe_plan; $credits = $this->getCreditsForPlan($plan); $user->increment('credits', $credits); } protected function handlePlanChange(User $user, $subscription) { $currentPlan = $user->subscription('default')->stripe_plan; $newPlan = $subscription['plan']['id']; if ($newPlan !== $currentPlan) { $this->addMonthlyCredits($user); } } protected function getCreditsForPlan($plan) { // Define your plan credits here $planCredits = [ 'basic' => 10, 'standard' => 20, 'premium' => 30, ]; return $planCredits[$plan] ?? 0; } } -
Cron Job:
You can set up a daily cron job to check for users whose subscription cycle is due for credit allocation. This can be done by checking the
created_atorupdated_atfields of the subscription.use App\Models\User; use Illuminate\Console\Command; class AllocateMonthlyCredits extends Command { protected $signature = 'credits:allocate'; protected $description = 'Allocate monthly credits to users based on their subscription plan'; public function handle() { $users = User::whereHas('subscription', function ($query) { $query->where('ends_at', '>', now()) ->where('created_at', '<=', now()->subMonth()); })->get(); foreach ($users as $user) { $this->addMonthlyCredits($user); } } protected function addMonthlyCredits(User $user) { $plan = $user->subscription('default')->stripe_plan; $credits = $this->getCreditsForPlan($plan); $user->increment('credits', $credits); } protected function getCreditsForPlan($plan) { // Define your plan credits here $planCredits = [ 'basic' => 10, 'standard' => 20, 'premium' => 30, ]; return $planCredits[$plan] ?? 0; } }
-
-
Register Webhooks: Ensure that your Stripe account is set up to send webhooks to your application. You can do this in the Stripe Dashboard under Developers > Webhooks.
-
Testing: Test your implementation thoroughly to ensure that credits are allocated correctly and that plan changes are handled as expected.
By using a combination of webhooks and a cron job, you can efficiently manage credit allocation while handling plan changes appropriately.