【问题标题】:Laravel Cashier - prevent creating user if payment failLaravel Cashier - 如果付款失败,防止创建用户
【发布时间】:2021-02-27 13:02:57
【问题描述】:

我正在使用 Laravel 5.8 和 Cashier 通过 Stripe 创建订阅者。 我需要在创建用户之前付款。

我的代码前端:

<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>

还有JS代码:

<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>

我的 RegisterController.php 是:

 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),
        ]);
    }

我对 BOTS 有疑问。每天都会创建一百个新用户。我想阻止它。

我的代码在 Stripe 支付失败并且用户出错但在数据库中创建用户时创建了一个用户。为什么?我想阻止它。所以如果没有成功的支付用户不应该被创建。请帮忙!

【问题讨论】:

    标签: javascript php laravel stripe-payments laravel-cashier


    【解决方案1】:

    为什么不将创建用户放在 try/catch 块中?

     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()]);
    
            }
        }
    
    

    【讨论】:

    • 我也尝试添加 catch - $user->delete();但用户仍然创建...
    • 这也很有趣,因为我的 ReCaptcha 验证不起作用
    • 好的,是的,您需要一个能够为其创建订阅的用户。在 catch 中删除将是一个好方法,但 $newSubscription = $user-&gt;newSubscription('main', $request-&gt;plan)-&gt;create($request-&gt;payment_method, ['email' =&gt; $user-&gt;email]); 实际上是抛出异常还是只需要检查结果? Like ``` if($newSubscription) { // 订阅创建成功 } else { throw new \Exception('Payment failed); } ```
    • 我认为你最好的选择是关注为什么你的 ReCaptcha 不起作用@AleksPer。理想情况下,这应该可以防止任何此类事情的发生。如果付款失败,删除客户并不能解决问题——它只是一个创可贴。我也建议在这里阅读本指南:stripe.com/docs/card-testing
    猜你喜欢
    • 2021-11-27
    • 2021-02-14
    • 1970-01-01
    • 2020-06-09
    • 2022-11-28
    • 2020-12-14
    • 2021-11-13
    • 1970-01-01
    • 2011-07-24
    相关资源
    最近更新 更多