from where does this $token comes ?
->create($token, [
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
I'm setting up Cashier for Braintree.
I have the following code:
$user = Auth::user();
//Check if user has subscribed with their credit card to Braintree
if ($user->subscribedToPlan('main', 'annual')) {
//Go to User home page
// $user = Auth::user();
return view('home', ['user' => $user]);
} else {
//For a user that has not put in their credit card info through Braintree yet
$user->newSubscription('main', 'annual')
->trialDays(365)
->create($token, [
'email' => $user->email,
'phone' => $user->phone,
]);
}
This is in my HomeController. When I go to /home, I get "Undefined variable: token".
I see that I don't declare the variable anywhere else, but I thought that was handled by Cashier.
What am I missing?
from where does this $token comes ?
->create($token, [
This is from the basic syntax to create a subscription in Braintree through Laravel Cashier.
See the docs at https://laravel.com/docs/5.8/braintree
When you installed laravel did you install the latest version? Version 6.0.x does not support Braintree as far as I'm aware:
https://laravel.com/docs/6.x/braintree
but 5.8 does:
https://laravel.com/docs/5.8/braintree
Check version of your Cashier as well. I think this is the highest that supports Brainthree but I could be wrong: https://github.com/laravel/cashier/releases/tag/v9.3.5
Hope it helps!
I was aware of the issue of non-support of Braintree in 6.0, so I stuck with 5..8 for this project.
How do I check the version of cashier?
I just followed the docs and used:
composer require laravel/cashier-braintree
to install it. So I am assuming since it is the "-braintree" package, that it should work.
I think the token is supposed to come from the Drop-In UI from Braintree, as a form input. I'm going to work on that and see what I find out. Anyone with Cashier experience, feel free to chime in.
There are so many mixed messages out there about how to use Cashier, it is quite frustrating. A token needs to be created server-side, but the examples given by Braintree's website aren't built for Cashier. Anyone have any additional wisdom or resources?
Yes. I searched... and searched some more. With varying instructions. I focused originally on the Laravel Cashier documentation designed specifically for Braintree on Laravel's site, as I mentioned previously. I will try the links you sent and let you know. Thanks.
I've looked through the links you've sent, as well as others I have found, and interestingly, I can't find a tutorial out there that uses the syntax of:
$user = User::find(1);
$user->newSubscription('main', 'monthly')
->trialDays(10)
->create($token);
Which is found in the Laravel Cashier Docs for Braintree - https://laravel.com/docs/5.8/braintree#subscriptions
And the docs say nothing about getting the Braintree Drop-in UI, or how to get the info from the UI to the controller.
The only tutorials I found use Javascript in the view to run the CC in the Drop-In UI, then simply show a modal style "Successful" box. I would think the standard practice would be to send a user to a route to show them a "Thank You" view or something like that, like I experience everywhere when I buy something online.
I have never seen the docs be so far off what I find people talking about in tutorials.
I do have the Drop-In UI showing now, but am unsure of how to connect it back to a route (Plus it isn't processing when I hit the submit button anyway)
Currently this is my view code:
@extends('layouts.app')
@section('content')
<div class="container border">
<div class="row justify-content-center">
<div class="col-md-12">
@include('flash-message')
</div>
</div>
<div class="row sectioncontent">
<div class="col-md-12">
<div id="dropin-container"></div>
<button id="submit-button">Process for Next Year</button>
</div>
</div>
</div>
<script>
var button = document.querySelector('#submit-button');
braintree.dropin.create({
authorization: "{{ Braintree_ClientToken::generate() }}",
container: '#dropin-container'
}, function (createErr, instance) {
button.addEventListener('click', function () {
instance.requestPaymentMethod(function (err, payload) {
$.get('{{ route('payment.subscribe') }}', {payload}, function (response) {
if (response.success) {
alert('Payment successfull!');
} else {
alert('Payment failed');
}
}, 'json');
});
});
});
</script>
@endsection
Not sure why my button isn't doing anything. And not sure how to send my user to a route after processing, though it seems that I could change the script code to something like this:
instance.requestPaymentMethod(function (err, payload) {
$.get('{{ route('payment.subscribe') }}', {payload}, function (response) {
if (response.success) {
$.get('{{ route('payment.success') }}');
} else {
$.get('{{ route('payment.failed') }}');
}
And code the functions accordingly.
Not sure why my button isn't doing anything.
Do you get any error in the console?
And not sure how to send my user to a route after processing
if(response.success) {
window.location.replace("{{ route('payment.success') }}");
return;
}
window.location.replace("{{ route('payment.failed') }}");
No. No errors in the Console. Nothing in the Console. Should have mentioned that.
@wallyj do you see a request to payment.subscribe route in the network tab?
Nothing happens in the network tab either. Seems like the javascript isn't firing on the button push.
@wallyj if you add console.log('test') in your click event listener do you see test in the console?
No. So weird.
Btw, these are my script lines from app.blade.php:
<!-- Scripts -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://js.braintreegateway.com/web/dropin/1.20.1/js/dropin.min.js"></script>
<script src="{{ asset('js/app.js') }}" defer></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-3-typeahead/4.0.1/bootstrap3-typeahead.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" />
I don't know if that affects my issue.
@wallyj seems fine.
I added the console log test:
var button = document.querySelector('#submit-button');
braintree.dropin.create({
authorization: "{{ Braintree_ClientToken::generate() }}",
container: '#dropin-container'
}, function (createErr, instance) {
button.addEventListener('click', function () {
console.log('test');
instance.requestPaymentMethod(function (err, payload) {
$.get('{{ route('payment.subscribe') }}', {payload}, function (response) {
if (response.success) {
alert('Payment successfull!');
} else {
alert('Payment failed');
}
}, 'json');
});
});
});
</script>
But it didn't do show anything in the console.
Technically the Drop-In UI is part of that script, and it's showing up. So the script is firing, just not the button push.
I am loading Vue for functionality on other pages, but it loads in my app.blade.php, so it's loading for this page as well. I think that might be killing the javascript EventListener.
Do you think that could be it?
@wallyj you can try to remove all scripts except dropin.min.js and check if it solves the issue.
Makes sense. Should have tried that. Thanks.
I did that, and it worked partially. I received this error in the console:
Error in callback function dropin.min.js:1 ReferenceError: $ is not defined at cc:107 at dropin.min.js:1
Not sure if the issue is in my code or the dropin.min.js file.
@wallyj that's because you're using $.get in your code which is jQuery function. Try to load jQuery and check if it works.
Also, it only works when I comment out the app.js file, which I have to run... This really sucks.
Ok. So, I turned on JQuery, but had to comment out this line to get it to work:
<script src="{{ asset('js/app.js') }}" defer></script>
This is fairly mission critical to my project. Not sure why it is killing the Braintree UI processing.
@wallyj and why you're loading multiple jQuery versions? Why you're loading vue from CDN (you're probably already importing it in your app.js)?
@wallyj what are you importing in app.js?
When I setup typeahead, it required JQuery,(I think), so I added the lines of code for it. Then for Braintree's Drop-In, the docs/tutorials showed the other line of code, so I added it. Not sure which one I should use, so I left them both.
Also, whatever Vue tutorial I used showed the CDN link, so I used it.
I guess that's a problem with a lot of tutorials, they don't necessarily explain that something they suggest is an option, but you can do it another way for another reason.
Plus, even when I comment out the lines to make it work, I receive a 500 error in the console:
VM5025:1 GET http://app.test/payment/subscribe?payload%5Bnonce%5D=tokencc_bd_34c6p5_ptdfxx_hwj4g8_gsw4t2_3m6&payload%5Bdetails%5D%5BexpirationMonth%5D=02&payload%5Bdetails%5D%5BexpirationYear%5D=2021&payload%5Bdetails%5D%5Bbin%5D=411111&payload%5Bdetails%5D%5BcardType%5D=Visa&payload%5Bdetails%5D%5BlastFour%5D=1111&payload%5Bdetails%5D%5BlastTwo%5D=11&payload%5Btype%5D=CreditCard&payload%5Bdescription%5D=ending+in+11&payload%5BbinData%5D%5Bprepaid%5D=Unknown&payload%5BbinData%5D%5Bhealthcare%5D=Unknown&payload%5BbinData%5D%5Bdebit%5D=Unknown&payload%5BbinData%5D%5BdurbinRegulated%5D=Unknown&payload%5BbinData%5D%5Bcommercial%5D=Unknown&payload%5BbinData%5D%5Bpayroll%5D=Unknown&payload%5BbinData%5D%5BissuingBank%5D=Unknown&payload%5BbinData%5D%5BcountryOfIssuance%5D=Unknown&payload%5BbinData%5D%5BproductId%5D=Unknown 500 (Internal Server Error)
(anonymous) @ VM5025:1
send @ jquery.js:8526
ajax @ jquery.js:7978
jQuery.<computed> @ jquery.js:7614
(anonymous) @ cc:111
(anonymous) @ dropin.min.js:1
setTimeout (async)
(anonymous) @ dropin.min.js:1
(anonymous) @ dropin.min.js:1
(anonymous) @ dropin.min.js:1
Promise.then (async)
t.exports @ dropin.min.js:1
(anonymous) @ dropin.min.js:1
(anonymous) @ cc:110
I may just need to abandon the use of Cashier and use Braintree's straight PHP SDK...
The problem for me is that:
Laravel - Designed to make PHP easier
Braintree - Designed to make accepting payments easier
Cashier - Designed to make putting Laravel and Braintree together easier
Using Laravel, Cashier, and Braintree - Complete mess with terribly incomplete docs and 15 tutorials that all say something different, creating a mess of code that doesn't work.
@TaylorOtwell, any thoughts?
Pardon my ignorance, but what do you mean "importing into app.js"? I try not to touch that file, and its 52,000 lines of code.
Please or to participate in this conversation.