php - 使用 Laravel 5.8/Cashier/Stripe 设置订阅时遇到问题

标签 php laravel laravel-cashier

我一步一步地遵循了本教程:
https://appdividend.com/2018/12/05/laravel-stripe-payment-gateway-integration-tutorial-with-example/

但是,当我去测试它时,出现以下错误:

条纹\错误\无效请求
没有这样的支付方法:

一些注意事项:

  • 我确保 Stripe 处于测试模式,我的 Stripe API key 设置正确,并使用推荐的测试卡:4242 4242 4242 4242 | 04/22 |第222话12345
  • 我仔细阅读了这篇文章的评论,发现其他人有一个“类似”的问题——但不是关于付款方式的具体错误。
  • 由于 Laravel 5.8 已发布,并且 Cashier 10 已发布 - 我看到了有关“paymentIntents”的零碎内容 - 所以我不确定这是否是导致问题的原因。

  • 有没有人对我可以做些什么来解决这个错误有任何想法?

    谢谢!

    enter image description here

    编辑:(根据请求添加代码)

    这是我使用的各种代码:

    路线 (web.php)
    Route::group(['middleware' => 'auth'], function() {
      Route::get('/home', 'HomeController@index')->name('home');
      Route::get('/plans', 'PlanController@index')->name('plans.index');
      Route::get('/plan/{plan}', 'PlanController@show')->name('plans.show');
      Route::post('/subscription', 'SubscriptionController@create')- 
    >name('subscription.create');
    });
    

    计划模型 (plan.php)
    <?php
        namespace App;
        use Illuminate\Database\Eloquent\Model;
    
        class Plan extends Model {
           protected $fillable = [
             'name',
             'slug',
             'stripe_plan',
             'cost',
             'description'
           ];
    
           public function getRouteKeyName() {
              return 'slug';
           }
        }
    

    计划 Controller (PlanController.php)
    <?php
        namespace App\Http\Controllers;
        use Illuminate\Http\Request;
        use App\Plan;
    
        class PlanController extends Controller {
            public function index() {
                $plans = Plan::all();
                return view('plans.index', compact('plans'));
            }
    
            public function show(Plan $plan, Request $request) {
                return view('plans.show', compact('plan'));
            }
        }
    

    订阅 Controller (SubscriptionController.php)
    <?php
        namespace App\Http\Controllers;
        use Illuminate\Http\Request;
        use App\Plan;
    
        class SubscriptionController extends Controller {
            public function create(Request $request, Plan $plan) {
                $plan = Plan::findOrFail($request->get('plan'));
    
                $request->user()
                    ->newSubscription('main', $plan->stripe_plan)
                    ->create($request->stripeToken);
    
                return redirect()->route('home')->with('success', 'Your plan subscribed successfully');
        }
    }
    

    显示 View (show.blade.php)
    @extends('layouts.app')
    
    @section('content')
        <div class="container">
            <div class="row justify-content-center">
                <div class="col-md-12">
                    <div class="">
                        <p>You will be charged ${{ number_format($plan->cost, 2) }} for {{ $plan->name }} Plan</p>
                    </div>
                    <div class="card">
                        <form action="{{ route('subscription.create') }}" method="post" id="payment-form">
                          @csrf
                          <div class="form-group">
                            <div class="card-header">
                                <label for="card-element">
                                    Enter your credit card information
                                </label>
                            </div>
    
                            <div class="card-body">
                                <label for="card-element">Credit or debit card</label>
    
                            <div id="card-element">
                              <!-- A Stripe Element will be inserted here. -->
                            </div>
    
                            <!-- Used to display form errors. -->
                            <div id="card-errors" role="alert"></div>
                                <input type="hidden" name="plan" value="{{ $plan->id }}" />
                            </div>
                      </div>
    
                      <div class="card-footer">
                        <button class="btn btn-dark" type="submit">Submit Payment</button>
                      </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
    @endsection
    
    @section('scripts')
        <script src="https://js.stripe.com/v3/"></script>
        <script>
            // Create a Stripe client.
            var stripe = Stripe('{{ env("STRIPE_KEY") }}');
    
            // Create an instance of Elements.
            var elements = stripe.elements();
    
            // Custom styling can be passed to options when creating an Element.
            // (Note that this demo uses a wider set of styles than the guide below.)
            var style = {
              base: {
                color: '#32325d',
                lineHeight: '18px',
                fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
                fontSmoothing: 'antialiased',
                fontSize: '16px',
                '::placeholder': {
                  color: '#aab7c4'
                }
              },
              invalid: {
                color: '#fa755a',
                iconColor: '#fa755a'
              }
            };
    
            // Create an instance of the card Element.
            var card = elements.create('card', {style: style});
    
            // Add an instance of the card Element into the `card-element` <div>.
            card.mount('#card-element');
    
            // Handle real-time validation errors from the card Element.
            card.addEventListener('change', function(event) {
              var displayError = document.getElementById('card-errors');
              if (event.error) {
                displayError.textContent = event.error.message;
              } else {
                displayError.textContent = '';
              }
            });
    
            // Handle form submission.
            var form = document.getElementById('payment-form');
            form.addEventListener('submit', function(event) {
              event.preventDefault();
    
              stripe.createToken(card).then(function(result) {
                if (result.error) {
                  // Inform the user if there was an error.
                  var errorElement = document.getElementById('card-errors');
                  errorElement.textContent = result.error.message;
                } else {
                  // Send the token to your server.
                  stripeTokenHandler(result.token);
                }
              });
            });
    
            // Submit the form with the token ID.
            function stripeTokenHandler(token) {
              // Insert token ID into the form so it gets submitted to the server
              var form = document.getElementById('payment-form');
              var hiddenInput = document.createElement('input');
              hiddenInput.setAttribute('type', 'hidden');
              hiddenInput.setAttribute('name', 'stripeToken');
              hiddenInput.setAttribute('value', token.id);
              form.appendChild(hiddenInput);
    
              // Submit the form
                  form.submit();
            }
        </script>
    @endsection
    

    最佳答案

    解决了 Laravel 5.8 和 Cashier 10.2

    计划 Controller :

    public function show(\App\Plan $plan, Request $request)
    {
        $paymentMethods = $request->user()->paymentMethods();
    
        $intent = $request->user()->createSetupIntent();
        return view('plans.show', compact('plan', 'intent'));
    }
    

    看法:
    <button
       id="card-button"
       class="btn btn-dark"
       type="submit"
       data-secret="{{ $intent->client_secret }}"
     > Pay </button>
    

    ...
    <script src="https://js.stripe.com/v3/"></script>
    <script>
        // Custom styling can be passed to options when creating an Element.
        // (Note that this demo uses a wider set of styles than the guide below.)
        var style = {
            base: {
                color: '#32325d',
                lineHeight: '18px',
                fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
                fontSmoothing: 'antialiased',
                fontSize: '16px',
                '::placeholder': {
                    color: '#aab7c4'
                }
            },
            invalid: {
                color: '#fa755a',
                iconColor: '#fa755a'
            }
        };
    
        const stripe = Stripe('{{ env("STRIPE_KEY") }}', { locale: 'es' }); // Create a Stripe client.
        const elements = stripe.elements(); // Create an instance of Elements.
        const cardElement = elements.create('card', { style: style }); // Create an instance of the card Element.
        const cardButton = document.getElementById('card-button');
        const clientSecret = cardButton.dataset.secret;
    
        cardElement.mount('#card-element'); // Add an instance of the card Element into the `card-element` <div>.
    
        // Handle real-time validation errors from the card Element.
        cardElement.addEventListener('change', function(event) {
            var displayError = document.getElementById('card-errors');
            if (event.error) {
                displayError.textContent = event.error.message;
            } else {
                displayError.textContent = '';
            }
        });
    
        // Handle form submission.
        var form = document.getElementById('payment-form');
    
        form.addEventListener('submit', function(event) {
            event.preventDefault();
    
            stripe
                .handleCardSetup(clientSecret, cardElement, {
                    payment_method_data: {
                        //billing_details: { name: cardHolderName.value }
                    }
                })
                .then(function(result) {
                    console.log(result);
                    if (result.error) {
                        // Inform the user if there was an error.
                        var errorElement = document.getElementById('card-errors');
                        errorElement.textContent = result.error.message;
                    } else {
                        console.log(result);
                        // Send the token to your server.
                        stripeTokenHandler(result.setupIntent.payment_method);
                    }
                });
        });
    
        // Submit the form with the token ID.
        function stripeTokenHandler(paymentMethod) {
            // Insert the token ID into the form so it gets submitted to the server
            var form = document.getElementById('payment-form');
            var hiddenInput = document.createElement('input');
            hiddenInput.setAttribute('type', 'hidden');
            hiddenInput.setAttribute('name', 'paymentMethod');
            hiddenInput.setAttribute('value', paymentMethod);
            form.appendChild(hiddenInput);
    
            // Submit the form
            form.submit();
        }
    </script>
    

    订阅 Controller
    public function create(Request $request, \App\Plan $plan)
    {
        $plan = \App\Plan::findOrFail($request->get('plan'));
        $user = $request->user();
        $paymentMethod = $request->paymentMethod;
    
        $user->createOrGetStripeCustomer();
        $user->updateDefaultPaymentMethod($paymentMethod);
        $user
            ->newSubscription('main', $plan->stripe_plan)
            ->trialDays(7)
            ->create($paymentMethod, [
                'email' => $user->email,
            ]);
    
        return redirect()->route('home')->with('status', 'Your plan subscribed successfully');
    }
    

    关于php - 使用 Laravel 5.8/Cashier/Stripe 设置订阅时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57501889/

    相关文章:

    php - 使用 Flash、PHP、Red5 从浏览器录制视频

    php - 当数据库关闭时捕获 'PDOException'

    php - 什么是可靠但基本的 php 搜索算法?

    php - Laravel 5缓存路由未更新

    javascript - 配置文件脚本未正确显示

    php - 使用 Blade 转义字符串,渲染 HTML

    php - Laravel 5.4 Cashier - 弥合文档方面的差距

    laravel - 无法安装 Laravel 的 5 个 cashier/stripe 包

    php - Laravel & Stripe - 无法识别的请求 URL (GET :/v1/customers/)

    PHP/jQuery/AJAX + 带身份验证的 POST SOAP 请求