0

Stack on stripe integration gateway laravel project. After creating controller function for post checkout and checkout.js file i'm facing the above error. It seems to be ok, and i don't know what do. I find some answers about this topic on stackoverflow but the code seems to be ok and i'm very stack on this. Request POST body:

{
  "amount": "11100000",
  "currency": "usd",
  "description": "My First Test Charge"
}

Response body:

{
  "error": {
    "code": "parameter_missing",
    "doc_url": "https://stripe.com/docs/error-codes/parameter-missing",
    "message": "Must provide source or customer.",
    "type": "invalid_request_error"
  }
}

productController:

use Stripe\Charge;
use Stripe\Stripe;
public function postCheckout(Request $request)
    {

        $curl = new \Stripe\HttpClient\CurlClient([CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1]);
        $curl->setEnableHttp2(false);
        \Stripe\ApiRequestor::setHttpClient($curl);


        if (!Session::has('cart')) {
            return redirect()->route('shoppingCart');
        }
        $oldCart = Session::get('cart');
        $cart = new Cart($oldCart);


Stripe::setApiKey('sk_test_..........');

        try {

            Charge::create(array(
            "amount" => $cart->totalPrice,
            "currency" => "usd",
            "source" => $request->input('stripeToken'), // obtained with Stripe.js
            "description" => "My First Test Charge"
        ));

       } catch (\Exeption $e) {
           return redirect()->route('checkout')->with('error', $e->getMessage());
       }

       Session::forget('cart');
       return redirect()->route('home')->with('succes', 'Successfully purchaised!');
    }

}

checkout.js:

Stripe.setPublishableKey('pk_test_..........');

var $form = $('#checkout-form');

$form.submit(function(event) {
    $('#charge-error').addClass('hidden');
    $form.find('button').prop('disabled', true);

    Stripe.card.createToken({
      number: $('#card-number').val(),
      cvc: $('#card-cvc').val(),
      exp_month: $('#card-expiry-month').val(),
      exp_year: $('#card-expiry-year').val(),
      name: $('#card-name').val()
    }, stripeResponseHandler);
    return false;
});

function stripeResponseHandler(status, response) {
    if (response.error) {
        $('#charge-error').removeClass('hidden');
        $('#charge-error').text(response.error.message);
        $form.find('button').prop('disalbed', false);
    } else {// Token was created!

    // Get the token ID:
        var token = response.id;
        // Insert the token into the form so it gets submitted to the server:
        $form.append($('<input type="hidden" name="stripeToken" />').val(token));
        console.log(token);

        // Submit the form:
        $form.get(0).submit();
    }
}

checkout.blade.php:

@extends('layouts.app')

@section('title')
 Checkout
@endsection

@section('content')

@section('style')

<html lang="en"><head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">

    <link rel="canonical" href="https://getbootstrap.com/docs/4.0/examples/checkout/">

    <!-- Bootstrap core CSS -->
    <link href="../../dist/css/bootstrap.min.css" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="form-validation.css" rel="stylesheet">


  </head>
  @endsection

  <body class="bg-light">

    <div class="container">
      <div class="py-5 text-center">
        <img class="d-block mx-auto mb-4" src="#" alt="" width="72" height="72">
        <h2> <a href=" {{ url('/') }} "> Basket</a></h2>
      </div>

      <div class="row">
        <div class="col-md-4 order-md-2 mb-4">
          <h4 class="d-flex justify-content-between align-items-center mb-3">
            <span class="text-muted">Your cart</span>
            <!--<span class="badge badge-secondary badge-pill">3</span>-->
          </h4>
          <ul class="list-group mb-3">
          <hr class="featurette-divider" style="margin-top: 13px;">
            
            <li class="list-group-item d-flex justify-content-between">
              <span>
                <h4>Total (USD)</h4>
              </span>
              <strong>${{ $total }}</strong>
            </li>
          </ul>
          <div id="charge-error" class="alert alert-danger {{ !Session::has('error') ? 'hidden' : '' }} "> {{ Session::get('error') }} 
          </div>
        </div>

        <div class="col-md-8 order-md-1">
          <h4 class="mb-3">Billing address</h4>

          <form class="needs-validation" novalidate="" action=" {{ route('checkout') }} " method="post" id="checkout-form">
            <div class="row">
              <div class="col-md-6 mb-3">
                <label for="card-name">First name</label>
                <input type="text" class="form-control" id="card-name" placeholder="" value="" >
                
              </div>
              <div class="col-md-6 mb-3">
                <label for="lastName">Last name</label>
                <input type="text" class="form-control" id="lastName" placeholder="" value="" >
                
              </div>
            </div>

            <div class="mb-3">
              <label for="username">Username</label>
              <div class="input-group">
                <div class="input-group-prepend">
                  <span class="input-group-text">@</span>
                </div>
                <input type="text" class="form-control" id="username" placeholder="Username" >
               
              </div>
            </div>

            <div class="mb-3">
              <label for="email">Email <span class="text-muted">(Optional)</span></label>
              <input type="email" class="form-control" id="email" placeholder="you@example.com">
              
            </div>

            <div class="mb-3">
              <label for="address">Address</label>
              <input type="text" class="form-control" id="address" placeholder="1234 Main St" >
              
            </div>

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

            <div class="row">
              <div class="col-md-5 mb-3">
                <label for="country">Country</label>
                <select class="custom-select d-block w-100" id="country" >
                  <option value="">Choose...</option>
                  <option>Albania</option>
                </select>
                
              </div>
              <div class="col-md-4 mb-3">
                <label for="state">State</label>
                <select class="custom-select d-block w-100 selectpicker countrypicker" id="state" >
                  <option value="">Choose...</option>
                  <option>Albania</option>
                  
                </select>
                
              </div>
              <div class="col-md-3 mb-3">
                <label for="zip">Zip</label>
                <input type="text" class="form-control" id="zip" placeholder="" >
              </div>
            </div>
            <div class="row">
              <div class="col-md-6 mb-3">
                <label for="card-name">Name on card</label>
                <input type="text" class="form-control" id="card-name" placeholder="John Doe" >
                <small class="text-muted">Full name as displayed on card</small>
               
              </div>
              <div class="col-md-6 mb-3">
                <label for="card-number">Credit card number</label>
                <input type="text" class="form-control" id="card-number" placeholder="" >
               
              </div>
            </div>
            <div class="row">
              <div class="col-md-3 mb-3">
                <label for="card-expiry-month">Expiration month</label>
                <input type="text" class="form-control" id="card-expiry-month" placeholder="00" >
                
              </div>
              <div class="col-md-3 mb-3">
                <label for="card-expiry-year">Expiration year</label>
                <input type="text" class="form-control" id="card-expiry-year" placeholder="00" required>
                
              </div>
              <div class="col-md-3 mb-3">
                <label for="card-cvc">CVV</label>
                <input type="text" class="form-control" id="card-cvc" placeholder="CVV" >
                
              </div>
            </div>
            
            {{ csrf_field() }}

            <hr class="mb-4">
            <button class="btn btn-primary btn-lg btn-block" type="submit">Continue to checkout</button>

          </form>
        </div>
      </div>
      <div>
          <hr class="featurette-divider" style="margin-top: 65px;">
      </div>

      <footer class="my-5 pt-5 text-muted text-center text-small">
        <p class="mb-1">© 2020-2021 Basket</p>
        <ul class="list-inline">
          <li class="list-inline-item"><a href="#">Privacy</a></li>
          <li class="list-inline-item"><a href="#">Terms</a></li>
          <li class="list-inline-item"><a href="#">Support</a></li>
        </ul>
      </footer>
    </div>
  </body>
</html>

@endsection

@section('scripts')

 <!-- Stripe.js -------------------------------------------------->
    <script type= "text/javascript" src="https://js.stripe.com/v2/"></script>
    <script src="https://js.stripe.com/v3/"></script>
    <script type= "text/javascript" src=" {{ URL::to('Stripe_js/checkout.js') }} "></script>
 
@endsection
Gazmir Sulcaj
  • 91
  • 3
  • 10
  • I've worked with Stripe checkouts recently (unfortunately in nodeJS not php) but always used the hosted checkout session by stripe. Maybe this answer can help you, since the guy seems to have your same issue: https://stackoverflow.com/a/42504702/5784743 – Caius Jul 15 '20 at 15:34

1 Answers1

0

Most likely you just need to add event.preventDefault() immediately inside $form.submit. What's probably happening now without that is the form is submitting before the async Stripe token function returns and adds the hidden input, so then on your backend $request->input('stripeToken') is null.

$form.submit(function(event) {
    event.preventDefault();
    $('#charge-error').addClass('hidden');
    ...
karllekko
  • 5,648
  • 1
  • 15
  • 19
  • i tried also with `event.preventDefault()` but doesn't change, still the same... – Gazmir Sulcaj Jul 15 '20 at 19:06
  • The error definitely comes from `$request->input('stripeToken')` being null. You will have to add more logs to see if it's set, check your Chrome devtools to see what is being sent to the backend server in the POST request, check if `stripeResponseHandler` is called by using breakpoints, and so on. I can't see anything obviously wrong with your code. – karllekko Jul 16 '20 at 09:18
  • I checked chrome devtools with POST request 500 (internal server error). The respnse of the server is on the `Network` tool is `checkout` and `favicon.ico`, no functions no html... – Gazmir Sulcaj Jul 16 '20 at 12:38
  • I mean the POST request that your frontend sends to the backend, the request body(https://datawookie.netlify.app/blog/2016/09/view-post-data-using-chrome-developer-tools/). Does that contain the stripeToken form element? If not, then you need to work backwards through the Javascript code to see why not(is stripeResponseHandler called, is the form.submit() function called, etc. – karllekko Jul 16 '20 at 16:29