web-dev-qa-db-fra.com

Problème de configuration d'un abonnement avec Laravel 5.8 / Cashier / Stripe

J'ai suivi ce tutoriel étape par étape: https://appdividend.com/2018/12/05/laravel-stripe-payment-gateway-integration-tutorial-with-example/

Cependant, lorsque je vais le tester, j'obtiens l'erreur suivante:

Stripe\Error\InvalidRequest Aucune méthode de paiement de ce type:

Quelques notes:

  • Je me suis assuré que Stripe est en mode test, que mes clés API Stripe sont correctement définies et j'ai utilisé la carte de test recommandée: 4242 4242 4242 4242 | 04/22 | 222 | 12345

  • J'ai parcouru les commentaires de l'article et je vois que d'autres personnes ont un problème "similaire" - mais pas spécifiquement une erreur concernant le mode de paiement.

  • Depuis Laravel 5.8 a été publié et Cashier 10 est sorti - je vois des morceaux sur "paymentIntents" - donc je ne suis pas sûr que ce soit la cause du problème.

Quelqu'un at-il des idées sur ce que je peux faire pour corriger cette erreur?

Merci!

enter image description here

Modifier: (Ajout de code, par demande)

Voici les différents morceaux de code que j'ai utilisés:

Itinéraires (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');
});

Modèle de plan (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';
       }
    }

Contrôleur de plan (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'));
        }
    }

Contrôleur d'abonnement (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');
    }
}

Afficher la vue (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
5
John Hubler

Juste au cas où, quelqu'un voudrait savoir comment j'ai corrigé cette erreur pour ce tutoriel particulier:

1) J'ai déclassé la version caissier

composer remove laravel/cashier

puis

composer require "laravel/cashier":"~9.0"

2) Ensuite, j'ai commencé à obtenir une autre erreur:

no plan exists with the name (Basic/Professional)

Pour résoudre ce problème, j'ai créé un nouveau produit récurrent au lieu d'un produit unique en bande et mis à jour le tableau des plans avec cette nouvelle entrée de plan

3) Puis j'ai de nouveau eu une autre erreur:

no plan id exits

Pour résoudre ce problème, j'ai mis à jour l'entrée de la colonne strip_plan de mes tables de plans avec l'ID de plan que j'ai obtenu à l'étape 2

Cela fonctionne pour ce tutoriel particulier, je ne suis pas sûr des autres versions

1
Faiz Akhtar

Je pense que votre problème peut être la méthode create. Essaye ça:

    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'));

        \Auth::user() //make sure your user is signed in and use the authenticated user
            ->newSubscription('main', $request->plan) //You just send the name of the subscription in Stripe, not the object
            ->create($request->stripeToken);

        return redirect()->route('home')->with('success', 'Your plan subscribed successfully');
}

Je pense que votre problème est dû au fait que vous utilisiez un utilisateur non valide et/ou parce que vous envoyez un objet de plan au lieu du nom du plan de paiement. Par exemple, si vous avez un produit nommé Main dans Stripe avec des plans de tarification appelés "Plan 1" et "Plan 2", pour abonner votre utilisateur authentifié, vous feriez ceci:

\Auth::user
    ->newSubscription('Main', 'Plan 1')
    ->create($request->stripeToken);

Et votre produit Stripe devrait ressembler à ceci:

enter image description here

0
Kevin Daniel