Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

DougE's avatar
Level 3

Stripe Charge Failing

I am on lesson 4 of the Stripe tutorial (https://laracasts.com/series/how-to-accept-payments-with-stripe/episodes/4) and while almost everything has gone well I've run into a problem when trying to complete the charge. The issue appears to be this line:

$product = Product::findOrFail(request('product'));

As when I comment it out and hard code a price value in rather than try and pull it dynamically the operation completes as normal and I can see the charge in my Stripe account. Looking in the inspector in Google the error I am receiving is: No query results for model [App\Product]

I tried to print the request using the log but when I check it, it is empty as there is no value attached.

Here are the various pages:

bilable.blade.php (not an error, accidentally mispelled it)

@extends('layouts.app')

@section('content')
<h1>Buy My Book for $25.00</h1>

<checkout-form :products="{{ $products }}"></checkout-form>

@endsection

CheckForm.vue

<template>
    <form action="/purchases" method="POST">
        
        <input type="hidden" name="stripeToken" v-model="stripeToken">
        <input type="hidden" name="stripeEmail" v-model="stripeEmail">

        <select name="product" v-model="product">
            <option v-for="product in products" :value="product.id">
                {{ product.name }} &mdash; ${{ product.price /100 }}
            </option>
        </select>

        <button type="submit" @click.prevent="buy">Buy Book</button>

    </form>
</template>

<script>
    export default {
        props: ['products'],
        data() {
            return {
                stripeEmail: '',
                stripeToken: '',
                product: 1
            };
        },
        created(){
            this.stripe = StripeCheckout.configure({
                key: Laravel.stripeKey,
                image: "https://stripe.com/img/documentation/checkout/marketplace.png",
                locale: "auto",
                token: function(token){

                    axios.post('/purchases', {
                        stripeToken:  token.id,
                        stripeEmail: token.email
                      })
                      .then(function (response) {
                        alert('Complete! Thanks for your payment!');
                      })
                      .catch(function (error) {
                        console.log(error);
                      });

                }
            });
        },
        methods: {
            buy(){
                let product = this.findProductById(this.product);

                this.stripe.open({
                    name: product.name,
                    description: product.description,
                    zipCode: true,
                    amount: product.price
                });
            },

            findProductById(id){
                return this.products.find(product => product.id == id);
            }
        }
    }
</script>

Purchases Controller:

<?php

namespace App\Http\Controllers;

use Log;
use App\Product;
use Illuminate\Http\Request;
use Stripe\{Charge, Customer};

class PurchasesController extends Controller
{
    public function store()
    {

        Log::info("Product Info: " . request('product'));
        $product = Product::findOrFail(request('product'));

        $customer = Customer::create([
            'email' => request('stripeEmail'),
            'source' => request('stripeToken')
        ]);

        Charge::create([
            'customer' => $customer->id,
            'amount' => 8000,
            'currency' => 'aud'
        ]);

        return 'All done';
    }
}

Web Routes:

Route::get('/billing', function () {
    $products = App\Product::all();

    return view('organisation.bilable', compact('products')); // no error here, I accidentally misspelled "billable" but couldn't be bothered to fix it for what I am doing.
});
Route::post('/purchases', 'PurchasesController@store');

Thank you in advance.

Edit: The solution was to recast this in the FormCheckout.vue file to be a separate variable as seen in the answer below.

0 likes
22 replies
jlucia's avatar

Your post to /purchases doesn't seem to include the product in the request. Try adding this.product to the post after the stripe data.

stripeToken:  token.id,
stripeEmail: token.email,
this.product
DougE's avatar
Level 3

Hi jlucia, thank you, I added it as follows:

axios.post('/purchases', {
    stripeToken:  token.id,
    stripeEmail: token.email,
    product: this.product
  })
  .then(function (response) {
    alert('Complete! Thanks for your payment!');
  })
  .catch(function (error) {
    console.log(error);
  });

Unfortunately I am still getting "No query results for model [App\Product]", I rechecked the log as well and no data is being passed through to the controller.

Edit: I just saw you edited your post with that code block. I did try to insert the code in like that however npm watch threw an error trying to compile it down.

dmeganoski@gmail.com's avatar

Try using console.log(this.product) before the post to make sure it is indeed getting the right value for id.

Also, in your dev tools of your browser, you can view the data that was posted in the request.

Also, you can use dd(request('product')) to check if the server side received the value.

DougE's avatar
Level 3

Thanks dmeganoski. I added console.log like so:

console.log(this.product);

axios.post('/purchases', {
                        stripeToken:  token.id,
                        stripeEmail: token.email,
            product: this.product
                      })

And it returned with "undefined" so it seems it is not receiving anything. I also added dd(request('product')) to my controller to confirm and it returned "null".

jlucia's avatar

Sorry for the typo before. Can you confirm you have a product in your products table? If you do, what happens if you hardcode the product: 1 in the post?

dmeganoski@gmail.com's avatar

I've only begun to experiment with Vue myself. But it seems the data attribute is not being bound to the select element. Vue changes syntax quite often. It's quite possible you have a newer or older version than the tutorial. Just a guess, but try using v-bind="product" instead of v-model

jlucia's avatar

Does this give you a different outcome?

axios.post('/purchases', this.$data)
DougE's avatar
Level 3

No worries jlucia, and I can confirm I do have 2 products in my products table. The good news is that hardcoding product: 1 into the post function worked; the data was sent correctly with the charge processing ok and I can see it in Stripe.

dmeganoski@gmail.com's avatar

also, try v-bind:value="product" instead of just :value="product" (with v-model) I've seen it done that way as well.

DougE's avatar
Level 3

@dmeganoski I have the Vue toolbar installed and I can see that when I change the select option the id value is updating, but I tried changing to v-bind as you suggested but unfortunately that didn't work either, I got the same Model not found exception and this error in the console: [Vue warn]: v-bind without argument expects an Object or Array value (found in <CheckoutForm> at C:\xampp\htdocs\vehicle-checkr\resources\assets\js\components\CheckoutForm.vue)

I also tried v-bind:value="product as you suggested above but the exception error continues.

@jlucia Doing that way also doesn't work unfortunately (same error), also the Stripe token and email no longer have values as well.

jlucia's avatar

You could add a console.log(this.product); to your buy method. It should show the id value change as your change the dropdown. At least you know it is accepting that.

jlucia's avatar

You would need to bind the token and email values before the post to use this.$data.

this.stripeToken = token.id;
this.stripeEmail = token.email;
dmeganoski@gmail.com's avatar

Oh, okay newer version than I'm used to. ^^

Well... then try this. console.log(this) above your ajax call. Make sure this hasn't lost context. (it is inside a callback)

if it has, you can do let module = this (outside the callback) and then use module.product instead of this.product

DougE's avatar
Level 3

@jlucia added in the extra binds and tried your previous suggestion for post again but unfortunately I still received the error. I did though put another console.log into the buy function and the product ID outputted correctly so that function at the very least is working.

@dmeganoski No worries, but I did as you suggested and added console.log(this) above the axios.post and it out putted this: [object Object]

I must be honest and say I don't know what I am looking for here, is that correct for the this call?

dmeganoski@gmail.com's avatar

In fact, I almost always cast this to another variable towards the top of my functions since the context gets lost so often. If you are using jquery, often this refers to a jquery object you are manipulating.

dmeganoski@gmail.com's avatar

You should be able to expand that object and see what kind of properties it has.

It's hard to say exactly, but there should be some property names that hint that it's not referring to your Vue object.

You can just cast it to variable up top, log it, and compare the two.

dmeganoski@gmail.com's avatar
created(){
            console.log(this) // here is the original 
            this.stripe = StripeCheckout.configure({
                key: Laravel.stripeKey,
                image: "https://stripe.com/img/documentation/checkout/marketplace.png",
                locale: "auto",
                token: function(token){
            console.log(this) // here is probably referring to a stripe object
                    axios.post('/purchases', {
                        stripeToken:  token.id,
                        stripeEmail: token.email
                      })
                      .then(function (response) {
                        alert('Complete! Thanks for your payment!');
                      })
                      .catch(function (error) {
                        console.log(error);
                      });

                }
            });
        },
dmeganoski@gmail.com's avatar
Level 4
created(){
            let module = this; // cast to separate variable
            this.stripe = StripeCheckout.configure({
                key: Laravel.stripeKey,
                image: "https://stripe.com/img/documentation/checkout/marketplace.png",
                locale: "auto",
                token: function(token){

                    axios.post('/purchases', {
                        stripeToken:  token.id,
                        stripeEmail: token.email,
                        product: module.product
                      })
                      .then(function (response) {
                        alert('Complete! Thanks for your payment!');
                      })
                      .catch(function (error) {
                        console.log(error);
                      });

                }
            });
        },
jlucia's avatar

Can you post an updated CheckForm.vue?

DougE's avatar
Level 3

@dmeganoski Casting it to a separate value has worked! I've put through a number of test payments and they all went through fine and show up in stripe, so I guess that was the issue all this time. I would never have thought try that myself. I will mark your answer as the correct one.

@jlucia The issue was that the this had to be recast per dmeganoski's suggestion and it's working. For the reference of anyone looking in the future below I've pasted the entire working CheckForm.vue block.

Thank you so much both of you for helping me with this, I have been struggling to fix this for a few days and now I can finally move on and keep going with the tutorial. I hope Jeffrey can update the Stripe tutorial for the changes that have been made since he created it but until then, hopefully this post can assist anyone else who runs into the same problem I had.

<template>
    <form action="/purchases" method="POST">
        
        <input type="hidden" name="stripeToken" v-model="stripeToken">
        <input type="hidden" name="stripeEmail" v-model="stripeEmail">

        <select name="product" v-bind:value="product">
            <option v-for="product in products" :value="product.id">
                {{ product.name }} — ${{ product.price /100 }}
            </option>
        </select>

        <button type="submit" @click.prevent="buy">Buy Book</button>

    </form>
</template>

<script>
    export default {
        props: ['products'],
        data() {
            return {
                stripeEmail: '',
                stripeToken: '',
                product: 1
            };
        },
        created(){
            let module = this; // cast to separate variable
            this.stripe = StripeCheckout.configure({
                key: Laravel.stripeKey,
                image: "https://stripe.com/img/documentation/checkout/marketplace.png",
                locale: "auto",
                token: function(token){

                    axios.post('/purchases', {
                        stripeToken:  token.id,
                        stripeEmail: token.email,
                        product: module.product // use newly cast variable here
                      })
                      .then(function (response) {
                        alert('Complete! Thanks for your payment!');
                      })
                      .catch(function (error) {
                        console.log(error);
                      });

                }
            });
        },
        methods: {
            buy(){
                let product = this.findProductById(this.product);

                this.stripe.open({
                    name: product.name,
                    description: product.description,
                    zipCode: true,
                    amount: product.price
                });
            },

            findProductById(id){
                return this.products.find(product => product.id == id);
            }
        }
    }
</script>
dmeganoski@gmail.com's avatar

No problem. Something I've scratched my own head over for a few hours, even recently. heh. Glad to have helped.

Please or to participate in this conversation.