cartalyst/stripe-laravel Laravel 6.0: The Stripe API key is not defined

1k views Asked by At

I get the above error when trying to checkout. In my services.php,I have my keys and values:

'stripe' => [
        'model' => App\Product::class,
        'public_key' => env('STRIPE_KEY'),
        'secret_key' => env('STRIPE_SECRET'),
    ]

The values are given in the .env:

STRIPE_KEY=blabla
STRIPE_SECRET=blabla

Here's my code when I checkout:

class CheckoutController extends Controller
{
    public function store(Request $request)
    {
        request()->validate([
            'name' => 'required|min:5',
            'email' => 'required|min:10',
            'address' => 'required|min:10',
            'address2',
            'country' => 'required',
            'postcode' => 'required',
            'card-name' => 'required'
        ]);

        // storing Stripe data
        $stripe = new Stripe();
        $stripe = Stripe::make('blabla');

        try {
            $charge = Stripe::charges()->create([
                'amount' => Cart::total(),
                'currency' => 'GBP',
                'source' => $request->stripeToken,
                'description' => 'Thank you for your purchase.',
                'receipt_email' => $request->email,
                'metadata' => [
                    'quantity' => 1,
                ],
            ]);

            $customer = $stripe->customers()->create(['email' => $request->email]);

            Cart::destroy();

            Mail::send(new OrderConfirmed);

            return redirect()->route('confirmation')
            ->with('paymentSuccessMessage', 'Thank you! Your payment has been accepted.
                   Please check your inbox for a confirmation email.');

        } 
            catch (CardErrorException $e) {
            return back()->withErrors('Error! ' . $e->getMessage());
        }
    }
}

What am I missing here? I believe I have everything defined where it should be.

EDIT: Here's my checkout.blade.php:

<link rel="stylesheet" type="text/css" href="/css/app.css">

<!-- Stripe integration -->
<script src="https://js.stripe.com/v3/"></script>

    <title>Checkout</title>

    <body class="bg-light">

    <hr style="width: 90%;" class="mt-4 mb-5">

    <div class="container">

        {{-- BILLING INFO --}}
        <div class="col-md-8 order-md-1">
        <h4 class="mb-3">Billing Information</h4>

        <form action="{{ route('checkout.store') }}" method="POST" class="needs-validation" id="payment-form" novalidate>
            @csrf 
            <div class="row">
                <div class="col-md-6 mb-3">
                    <label for="name">Name</label>
                    <input name="name" type="text" class="form-control" id="name" placeholder="John Appleseed" value="{{ old('name') }}" required>
                    <div class="invalid-feedback">Valid name is required.</div>
                </div>
                <div class="col-md-6 mb-3">
                    <label for="email">Email</label>
                    <input name="email" type="text" class="form-control" id="email" placeholder="[email protected]" value="{{ old('email') }}" required>
                    <div class="invalid-feedback">Valid email is required.</div>
                </div>
            </div>

            <div class="mb-3">
                <label for="address">Address</label>
                <input name="address" type="text" class="form-control" id="address" placeholder="1234 Main St" value="{{ old('address') }}" required>
                <div class="invalid-feedback">Please enter your shipping address.</div>
            </div>

            <div class="mb-3">
                <label for="address2">Address 2 <span class="text-muted">(Optional)</span></label>
                <input name="address2" type="text" class="form-control" id="address2" placeholder="Apartment or suite" value="{{ old('address2') }}">
            </div>

            <div class="row">
            <div class="col-md-5 mb-3">


                <div class="invalid-feedback">
                    Please select a valid country.
                </div>
            </div>

            <div class="col-md-3 mb-3">
                <label for="postcode">Postcode</label>
                <input name="postcode" type="text" class="form-control" id="postcode" value="{{ old('postcode') }}" required>
                <div class="invalid-feedback">
                    Postcode required.
                </div>
            </div>
            </div>
            <hr class="mb-4">

            <h4 class="mb-3">Payment</h4>

            <div class="row">
                <div class="col-md-6 mb-3">
                    <label for="cc-name">Name on card</label>
                    <input name="card-name" type="text" class="form-control" id="cc-name" placeholder="John F Appleseed" value="{{ old('card-name') }}" required>
                    <small class="text-muted">Full name as displayed on card</small>
                    <div class="invalid-feedback">Name on card is required</div>
                </div>
            </div>

            <!-- STRIPE ELEMENTS -->
            <form action="/charge" method="post" id="payment-form">
                <div class="form-row">
                  <label class="ml-1" 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>
                </div>
                <br>
                <hr class="mb-4">
                <p id="no-products"></p>
                <button id="submit-payment" class="btn btn-lg btn-block" type="submit"><b>Submit Payment</b></button>
            </form>
            <!-- END STRIPE ELEMENTS -->
            {{-- END BILLING INFO --}}

        </form> 
        </div>
    </div>
    </div>

    {{-- ALERT: CART IS EMPTY --}}
    @if(Cart::count() == 0)
        <script>
            document.getElementById('submit-payment').disabled = true;
            document.getElementById('no-products').textContent = 'Your cart is empty!';
            document.getElementById('no-products').className = 'w-25 alert alert-danger';
        </script>
    @endif
    {{-- END ALERT: CART IS EMPTY --}}

    <script>
        (function() {
        // creates a Stripe client
        var stripe = Stripe('pk_test_9dn1vt3i0j0Q5GZdwAXn9iUs00iMziQDyD');

        // creates an instance of Elements
        var elements = stripe.elements();

        var style = {
        base: {
            color: '#32325d',
            fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
            fontSmoothing: 'antialiased',
            fontSize: '16px',
            '::placeholder': {
            color: '#aab7c4'
            }
        },
        invalid: {
            color: 'red',
            iconColor: 'red'
        }
        };

        // creates an instance of the card Element
        var card = elements.create('card', { style: style, hidePostalCode: true });

        // Add an instance of the card Element into the `card-element` <div>.
        card.mount('#card-element');

        // handles 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 = '';
        }
        });

        // handles form submission.
        var form = document.getElementById('payment-form');
        form.addEventListener('submit', function(event) {
        event.preventDefault();

        // disables the submit button to prevent repeated clicks
        document.getElementById('submit-payment').disabled = true; 

        stripe.createToken(card).then(function(result) {
            if (result.error) {
            // informs the user if there was an error
            // enables the submit button if validation fails
            document.getElementById('submit-payment').disabled = false;
            var errorElement = document.getElementById('card-errors');
            errorElement.textContent = result.error.message;
            } else {
            // sends the token to the server
            stripeTokenHandler(result.token);
            }
        });
        });

        // submits the form with the token ID
        function stripeTokenHandler(token) {
        // inserts 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', 'stripeToken');
        hiddenInput.setAttribute('value', token.id);
        form.appendChild(hiddenInput);

        // submits the form
        form.submit();
        }
        })();
    </script>

    </body>
    </html>

I can see the Stripe token being added in dev tools so it's there.

1

There are 1 answers

2
livreson ltc On

You will to submit the form with the token ID. First you have to create the token handler function

// Submit the form with the token ID.
function stripeTokenHandler(token) {
  // Insert the token ID into the form so it gets submitted to the server
  var form = document.getElementById('payment-form'); // The id of the form that handles payment submission
  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();
}

Submit the form

// Handle form submission.
var form = document.getElementById('payment-form'); // the id of the form
form.addEventListener('submit', function(event) {
  event.preventDefault();

  // Disable the submit button to prevent repeated clicks
  document.getElementById('complete-donation').disabled = true; // This is the ID of the button, it will disable the button after submitting to avoid multiple submission


  stripe.createToken(card, options).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;

      // Enable the submit button if there was an error
      document.getElementById('complete-donation').disabled = false; // If there is an error enable the button

    } else {
      // Send the token to your server.
      stripeTokenHandler(result.token);
    }
  });
});

Then in Your controller you will access the token this way

$token = $_POST['stripeToken'];
$customer = $stripe->customers()->create(['email' => $request->email], $token); // pass the token

Please let know it that helps.