fix(billing): create Stripe customer before redirecting to billing portal (#206)
## Summary - Users without a Stripe customer ID (`stripe_id = null`) would hit an `InvalidCustomer` exception when visiting the billing portal - Added a `hasStripeId()` check before calling `redirectToBillingPortal()`, creating the Stripe customer on-the-fly if needed - Added two tests covering both branches (with and without an existing Stripe customer ID)
This commit is contained in:
parent
ac1476eeff
commit
e8bc5fd786
|
|
@ -136,6 +136,12 @@ class SubscriptionController extends Controller
|
|||
->withErrors(['demo' => 'Billing management is not available on the demo account.']);
|
||||
}
|
||||
|
||||
return $request->user()->redirectToBillingPortal(route('settings.billing'));
|
||||
$user = $request->user();
|
||||
|
||||
if (! $user->hasStripeId()) {
|
||||
$user->createAsStripeCustomer();
|
||||
}
|
||||
|
||||
return $user->redirectToBillingPortal(route('settings.billing'));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
<?php
|
||||
|
||||
use App\Http\Middleware\HandleInertiaRequests;
|
||||
use App\Models\Account;
|
||||
use App\Models\AccountBalance;
|
||||
use App\Models\BankingConnection;
|
||||
use App\Models\Category;
|
||||
use App\Models\Transaction;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Laravel\Pennant\Feature;
|
||||
|
||||
beforeEach(function () {
|
||||
|
|
@ -277,3 +279,35 @@ test('paywall shows canUseFreePlan false when open banking is not active', funct
|
|||
->where('canUseFreePlan', false)
|
||||
);
|
||||
});
|
||||
|
||||
test('billing portal creates stripe customer when user has no stripe id', function () {
|
||||
$user = Mockery::mock(User::class)->shouldIgnoreMissing();
|
||||
$user->shouldReceive('isDemoAccount')->andReturn(false);
|
||||
$user->shouldReceive('hasStripeId')->once()->andReturn(false);
|
||||
$user->shouldReceive('createAsStripeCustomer')->once();
|
||||
$user->shouldReceive('redirectToBillingPortal')
|
||||
->with(route('settings.billing'))
|
||||
->once()
|
||||
->andReturn(new RedirectResponse(route('settings.billing')));
|
||||
|
||||
$this->withoutMiddleware(HandleInertiaRequests::class);
|
||||
$this->actingAs($user);
|
||||
|
||||
$this->get(route('settings.billing.portal'))->assertRedirect();
|
||||
});
|
||||
|
||||
test('billing portal skips stripe customer creation when user already has a stripe id', function () {
|
||||
$user = Mockery::mock(User::class)->shouldIgnoreMissing();
|
||||
$user->shouldReceive('isDemoAccount')->andReturn(false);
|
||||
$user->shouldReceive('hasStripeId')->once()->andReturn(true);
|
||||
$user->shouldNotReceive('createAsStripeCustomer');
|
||||
$user->shouldReceive('redirectToBillingPortal')
|
||||
->with(route('settings.billing'))
|
||||
->once()
|
||||
->andReturn(new RedirectResponse(route('settings.billing')));
|
||||
|
||||
$this->withoutMiddleware(HandleInertiaRequests::class);
|
||||
$this->actingAs($user);
|
||||
|
||||
$this->get(route('settings.billing.portal'))->assertRedirect();
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue