I've installed Laravel Cashier (v3.0.4) in my project and am at the point of allowing users to update their credit cards, but am running into issues when I attempt to do so. Here's the relevant pieces from my controller that handles it:
public function __construct() {
$this->user = Auth::user();
}
/**
* Update credit card
* @return \Illuminate\Http\RedirectResponse
*/
public function updateCardPost() {
$this->user->updateCard(Input::get('stripe-token'));
session()->flash('flash_message', 'You have updated your credit card');
return redirect()->route('dashboard.index');
}
I've verified the sanity-check items:
But every time I try submit it, I'm getting an error in Cashier itself:
FatalErrorException in StripeGateway.php line 454:
Call to a member function create() on null
I've looked into this and it looks like it's passing the $token
to the following: $card = $customer->cards->create(['card' => $token]);
So, I then did another sanity check by dd($token)
in that method and that returns exactly what my form is supplying. It doesn't look like this block has changed much recently -- but there were some PSR-2 and one-off purchase updates; neither of which appear to have anything to do with what's going on here. So I'm at my whits-end on what's up here, but any clues would be a huge help. Thanks!
Have verified running dd($customer->cards)
inside of the updateCard()
method returns null -- probably because it's not ever saving the last four to the database when creating the subscription. Struggling to see how I can create a subscription (verified on Stripe), cancel and resume, yet my card details are not being updated locally, nor can I swap cards.
I used https://www.youtube.com/watch?v=iPaKX7aPczQ as inspiration for how simple it "should be" to do this, with success on that end, but not mine.
Here's my entire User controller and Coffee implementation if it helps:
<?php namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Laravel\Cashier\Billable;
use Laravel\Cashier\Contracts\Billable as BillableContract;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract, BillableContract {
use Authenticatable, CanResetPassword, Billable;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'users';
/**
* Laravel Cashier
*
* @var array
*/
protected $dates = ['trial_ends_at', 'subscription_ends_at'];
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'email',
'password',
'first_name',
'last_name',
'phone',
'biography',
'twitter',
'facebook',
'linkedin'
];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = ['password', 'remember_token'];
/**
* A user can have many listings
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function listings() {
return $this->hasMany('App\Models\Dashboard\Listing');
}
}
Stripe.coffee
(($) ->
'use strict'
StripeBilling =
init: ->
@form = $('.js-subscription__create')
@submitButton = @form.find '.js-subscription__create__submit'
@submitButtonText = @submitButton.text()
stripeKey = $('meta[name="publishable_key"]').attr 'content'
Stripe.setPublishableKey stripeKey
@bindEvents()
return
bindEvents: ->
@form.on('submit', $.proxy(@sendToken, @))
return
sendToken: (event) ->
event.preventDefault()
@submitButton.attr("disabled", true).text 'One Moment'
Stripe.createToken(@form, $.proxy(@stripeResponseHandler, @))
return
stripeResponseHandler: (status, response) ->
if response.error
@form.find('.js-form__errors').removeClass("uk-hidden").text response.error.message
return @submitButton.text(@submitButtonText).attr('disabled', false)
$('<input>'
type: 'hidden'
name: 'stripe-token'
value: response.id
).appendTo @form
@form[0].submit()
return
StripeBilling.init()
return
) jQuery
I think it's due to an API change on Stripe's end. If you look at their changelog you'll notice that the "cards" attribute was changed to "sources" fairly recently.
UPDATE
You can choose the API Version that Stripe's own PHP framework is using with the following static method:
Stripe::setApiVersion("2015-02-10");
(That version number worked for me, but it could be that we need an older version.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With