javascript - Laravel Cashier - prevent creating user if payment fail
Get the solution ↓↓↓I'm using Laravel 5.8 and Cashier to create subscribers using Stripe. I need to take payment before the user is created.
My code frontend:
<div class="form-group">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" placeholder="Email Address">
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="form-group row">
<div class="col-sm-6 mb-3 mb-sm-0">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password" placeholder="Password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
<div class="col-sm-6">
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password" placeholder="Confirm Password">
</div>
</div>
<hr>
<div class="text-center">
<h1 class="h4 text-gray-900 mb-4">Payment Details</h1>
</div>
<div class="flex flex-wrap mb-6">
<label for="card-element" class="block text-gray-700 text-sm font-bold mb-2">
Choose a subscription plan
</label>
<select id="plan" name="plan" class="form-control">
<option value="price_1HU5qCJ0Bip59UAeKGtNPHra">Boost B2C & B2B - 29,99 eur a month (most popular)</option>
<option value="price_1HU5qOJ0Bip59UAeSBeGhV7Q">Boost B2C - 14,99 eur a month</option>
</select>
</div>
<div class="flex flex-wrap mb-6 mt-4">
<label for="card-element" class="block text-gray-700 text-sm font-bold mb-2">
Please enter your Credit Card detail below
</label>
<div id="card-element" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"></div>
<div id="card-errors" class="text-red-400 text-bold mt-2 text-sm font-medium text-danger"></div>
</div>
<div class="col-md-12">
<div class="form-group{{ $errors->has('g-recaptcha-response') ? ' has-error' : '' }}">
<label class="col-md-4 control-label">Captcha</label>
<div class="col-md-6 pull-center">
{!! app('captcha')->display() !!}
@if ($errors->has('g-recaptcha-response'))
<span class="help-block">
<strong>{{ $errors->first('g-recaptcha-response') }}</strong>
</span>
@endif
</div>
</div>
</div>
<button type="submit" id="card-button" class="mt-3 btn btn-primary shadow-sm inline-block align-right text-right select-none border font-bold whitespace-no-wrap py-2 px-4 rounded text-base leading-normal no-underline text-gray-100 bg-blue-500 hover:bg-blue-700 pull-right">
{{ __('Register') }}
</button>
also there is JS code:
<script src="https://js.stripe.com/v3/"></script>
<script>
const stripe = Stripe('pk_live_123456789');
console.log(stripe);
const elements = stripe.elements();
const cardElement = elements.create('card');
cardElement.mount('#card-element');
const cardHolderName = document.getElementById('name');
const cardButton = document.getElementById('card-button');
const clientSecret = cardButton.dataset.secret;
let validCard = false;
const cardError = document.getElementById('card-errors');
cardElement.addEventListener('change', function(event) {
if (event.error) {
validCard = false;
cardError.textContent = event.error.message;
} else {
validCard = true;
cardError.textContent = '';
}
});
var form = document.getElementById('signup-form');
form.addEventListener('submit', async (e) => {
event.preventDefault();
const { paymentMethod, error } = await stripe.createPaymentMethod(
'card', cardElement, {
billing_details: { name: cardHolderName.value }
}
);
if (error) {
// Display "error.message" to the user...
console.log(error);
cardError.textContent = error.message;
} else {
// The card has been verified successfully...
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'payment_method');
hiddenInput.setAttribute('value', paymentMethod.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
});
</script>
my RegisterController.php is:
public function register(Request $request)
{
$this->validator($request->all())->validate();
DB::beginTransaction();
event(new Registered($user = $this->create($request->all())));
try {
$newSubscription = $user->newSubscription('main', $request->plan)->create($request->payment_method, ['email' => $user->email]);
} catch ( Exception $exception ){
DB::rollback();
return redirect()->back()->with(['error_message' => $exception->getMessage()]);
}
DB::commit();
$this->guard()->login($user);
return $this->registered($request, $user)
?: redirect($this->redirectPath());
}
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
'g-recaptcha-response' => ['required', 'captcha'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'hotel_name' => $data['hotel_name'],
'address' => $data['address'],
'country' => $data['country'],
'city' => $data['city'],
'zipcode' => $data['zipcode'],
'position' => $data['position'],
'website' => $data['website'],
'phone' => $data['phone'],
'password' => Hash::make($data['password']),
'token' => str_random(5),
]);
}
I have a problem with BOTS. There create a hundred new users each day. I want to prevent it.
My code creates a user when Stripe payment fails and the user got an error but in the database, the user is created. WHy? I want to prevent it. So if there is no successful payment user should NOT be created. Please help!
Answer
Solution:
Why not put the create user in the try/catch block?
public function register(Request $request)
{
$this->validator($request->all())->validate();
try {
event(new Registered($user = $this->create($request->all())));
$newSubscription = $user->newSubscription('main', $request->plan)->create($request->payment_method, ['email' => $user->email]);
$this->guard()->login($user);
return $this->registered($request, $user) ?: redirect($this->redirectPath());
} catch ( Exception $exception ){
return redirect()->back()->with(['error_message' => $exception->getMessage()]);
}
}
Share solution ↓
Additional Information:
Link To Answer People are also looking for solutions of the problem: illuminate\http\exceptions\posttoolargeexception
Didn't find the answer?
Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.
Similar questions
Find the answer in similar questions on our website.
Write quick answer
Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.