@danielrønfeldt I don’t really understand your code to be honest. If this a controller action to update a subscription, why are you checking and letting a user create a brand-new one?
You should have two distinct endpoints: one for subscribing, and one for swapping plans if your application allows that.
public function store(CreateSubscriptionRequest $request)
{
$paymentMethod = $request->input('payment_method_id');
$subscription = $request->user()
->subscription('sub_name', $request->input('plan_id'))
->create($paymentMethod);
return SubscriptionResource::make($subscription)
->response()
->setStatusCode(201);
}
public function update(UpdateSubscriptionRequest $request)
{
$subscription = $request->user()->subscription('sub_name');
$subscription->swap($request->input('new_plan_id'));
return new SubscriptionResource($subscription);
}
Any Stripe exceptions, you can handle in the exception handler and return an appropriate response:
use Illuminate\Validation\ValidationException;
use Stripe\Exception\CardException;
public function register()
{
$this->renderable(function (CardException $e, $request) {
throw ValidationException::withMessages([
'payment_method_id' => [
$e->getMessage(),
],
]);
});
}
You can then render any issues with the payment method (card) next to your Stripe Element input as if it were a “real” validation error message:
<div id="card-element"></div>
@foreach($errors->get('payment_method_id') as $error)
<div class="d-block invalid-feedback" role="alert">{{ $error }}</div>
@endforeach
Relevant Cashier documentation:
- Creating subscriptions: https://laravel.com/docs/8.x/billing#creating-subscriptions
- Changing prices (plans): https://laravel.com/docs/8.x/billing#changing-prices