Stripe error "The resource ID cannot be null or whitespace" - laravel

I am trying to create a subscription but get the error "The resource ID cannot be null or whitespace". I have stripe and cashier installed and migrated.
<?php
namespace App\Http\Controllers;
require_once('../vendor/autoload.php');
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Laravel\Cashier\Cashier;
use \Stripe\Stripe;
use Exception;
use Stripe_Error;
class SubscriptionController extends Controller {
public function __construct() {
$this->middleware('auth');
}
public function retrievePlans() {
$key = \config('services.stripe.secret');
$stripe = new \Stripe\StripeClient($key);
$plansraw = $stripe->plans->all();
$plans = $plansraw->data;
foreach($plans as $plan) {
$prod = $stripe->products->retrieve(
$plan->product,[]
);
$plan->product = $prod;
}
return $plans;
}
public function showSubscription() {
$plans = $this->retrievePlans();
$user = Auth::user();
return view('subscribe', [
'user'=>$user,
'intent' => $user->createSetupIntent(),
'plans' => $plans
]);
}
public function processSubscription(Request $request)
{
$user = Auth::user();
$paymentMethod = $request->input('payment_method');
$user->createOrGetStripeCustomer();
$user->addPaymentMethod($paymentMethod);
$plan = $request->input('plan');
try {
$user->newSubscription('default', $plan)->create($paymentMethod, [
'email' => $user->email
]);
} catch (\Exception $e) {
return back()->withErrors(['message' => 'Error creating subscription. ' . $e->getMessage()]);
}
return redirect('dashboard');
}
}
I keep getting the error when creating a user $user->createOrGetStripeCustomer();

In the user table, while creating a new user just kept the stripe-id field as NULL. It should be either a stripe id or must be set as NULL. If you just keep it blank will get the error
Another important point, stripe_id filed is highly case sensitive so keep it as utf8mb4_ci encoding

I had that same error. And in my case was because the following:
Subscribe user 1 (and thus was created as customer in Stripe)
Delete customer from the Stripe dashboard
Try to subscribe user 1 again (in the next 10 minutes or so after delete from the customers Stripe list)
This stop happening when I subscribe a different user that has never been in the customers list.
Perphaps and this is just me doing a long shot: Stripe needs a bit of time between delete and re-subscribe.
I also looked in docs but nothing came up about this error.
only this: https://stripe.com/docs/error-codes#resource-missing

I was trying to integrate subscription with stripe using cashier in Laravel 8 but I was getting the same error. For me, I have already stripe_id field as NULL by default and kept utf8mb4_ci encoding.
After debugging many things, I found that "payment_method" was not coming in post and found issue with below code.
<button id="card-button" data-secret="{{ $intent->client_secret }}" class="btn btn-lg btn-success btn-block">SUBMIT</button>
It was submitting the form before JavaScript code get fully executed to get the payment method and payment method was not getting posted. So adding type="button" resolved my issue. Below is the submit button code that resolved my issue.
<button type="button" id="card-button" data-secret="{{ $intent->client_secret }}" class="btn btn-lg btn-success btn-block">SUBMIT</button>

Modify processSubscription function to check if the user has a payment method already before creating one to him like this:
if(! $user->hasPaymentMethod())
$user->addPaymentMethod($paymentMethod);

Related

Assign specific roles from where the user clicks

I would like to assign roles depending on which button the user clicks:
For example:
- If you click on I want to be an Advisor, redirect to the Laravel registration form and assign the role of advisor.
- If the user clicks on I want to be a Buyer, they redirect to the Laravel registration form and assign the buyer role.
But I do not know how to do it.
I have this code in my 'RegisterController':
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
//'password' => Hash::make($data['password']), //mutador en User model
'password' => $data['password'],
'surname1' => $data['surname1'],
'surname2' => $data['surname2'],
'comunidad_id' => $data['cbx_comunidad'],
'provincia_id' => $data['cbx_provincia'],
'municipio_id' => $data['cbx_municipio'],
]);
//dd(Request::url());
// $user->assignRole('Asesor');
//quiero asignar varios roles depende de el botón que clicken
return $user;
}
For now, what I have done is to add such a parameter, in the view that calls the view 'register':
href="{{ route('register','Asesor') }}"
and in the view 'register' send it by post in a hidden:
<div class="form-group">
<?php
$pos = strpos(Request::fullUrl(), '?');
$cadena = substr (Request::fullUrl() , $pos+1, strlen(Request::fullUrl()) );
?>
<input type="hidden" name="role" id="role" value="{{ $cadena }}">
</div>
Then in the controller I do this:
if ($data['role'] == 'Asesor=')
{
$user->assignRole('Asesor');
}
return $user;
But I don't know if it's the right way to act.
I think, you could work with events like this:
In your EventServiceProvider class, create an item inside your property $listen:
'App\Events\User\Created' => ['App\Listeners\User\AssignRoles'],
After that, you going to run the command:
php artisan event:generate
Now, you need to turn on this event in your User class declaring protected property $dispatchesEvents, like this:
protected $dispatchesEvents = ['created' => 'App\Events\User\Created'];
After all call create method in your User class, the created event is going to be called and run AssignRoles logic.
In your App\Events\User\Created class you need to inject User into __construct method, like this:
public $user;
public function __construct(User $user)
{
$this->user = $user;
}
Remember to put the complete path of User class!
This is the object that is going to be filled with data coming from User::create method.
Inside your Listener AssignRoles you have the event linked with the user filled and you can get it this way:
public function handle(Created $event)
{
$event->user;
// ...
}
Inside your Listener AssignRoles you can get all Requested params in your __construct method:
private $request;
public function __construct(Illuminate\Http\Request $request)
{
$this->request = $request;
}
With requested params in your hand you can apply the logic depending on the clicked button inside handle method:
public function handle(Created $event)
{
$event->user;
// here is the best place to do all the logic about roles that is going to be attached in this user. E.g:
switch($role = $this->request->role) {
case $role == 'Asesor':
$event->user->roles()->assignRole('Asesor');
break;
case $role == 'Buyer':
$event->user->roles()->assignRole('Buyer');
break;
}
}
To send role param into Request you need to create a form with hidden element,
<input type='hidden' name='role' />
create more than one submit button to fill role hidden element
<input type='submit' value='I want to be an Advisor' onClick='setRole("Advisor")' />
<input type='submit' value='I want to be a Buyer' onClick='setRole("Buyer")' />
And, finally you need a logic to setRole js method. Good Look. ;-)
For assign Role to user.
Controller function will be like.
/* assign role */
if(is_array($request['role']))
{
foreach($request['role'] as $d)
{
$user->roles()->attach(Role::where('id',$d)->first());
}
}
return redirect()->route();

Laravel Policies Via blade template

I got an error when i want to use Policies to limit users access, when user access the system as guest, the system won't show edit button vice versa if user as admin the system will show the edit button. But i got an error when user are logged in as Admin and no error when user are not logged in. This are my error messages
oo few arguments to function App\Policies\InverterPolicy::update(), 1 passed in /Applications/XAMPP/xamppfiles/htdocs/PROJECT/ta/vendor/laravel/framework/src/Illuminate/Auth/Access/Gate.php on line 691 and exactly 2 expected
This are my blade
#can('update',App\Inverter::class)
<button type="button" class="btn btn-warning" name="button">Edit</button>
#endcan
This are my Controllers
public function update(Request $request, Inverter $inverter)
{
$this->authorize('update',$inverter);
$data = $request->validate([
'name'=>'bail|required|max:191',
'warehouse_id'=>'bail|required|numeric',
'company_id'=>'bail|required|numeric',
'length'=>'numeric',
'width'=>'numeric',
'height'=>'numeric',
'maxInputPower'=>'numeric',
'maxInputVoltage'=>'numeric',
'maxInputCurrent'=>'numeric',
'MPPTOperatingRange'=>'numeric',
'parallelInput'=>'numeric',
'MPPTTrackers'=>'numeric',
'nominalOutputPower'=>'numeric',
'maxOutputPower'=>'numeric',
'nominalOutputCurrent'=>'numeric',
'maxOutputCurrent'=>'numeric',
'ACFrequencyRange'=>'numeric',
'THDI'=>'numeric',
'efficiency'=>'numeric',
'MPPTEfficiency'=>'numeric',
'euroEfficiency'=>'numeric',
]);
Inverter::find($inverter->id)->update($data);
return redirect(action('InverterController#index'));
}
this are my policies
public function update(User $user, Inverter $inverter)
{
return in_array($user->role,[
'Admin',
]);
}
When you call the can() method on a User using, as the second parameter, the class name instead of an instance, you're actually calling the method without the second parameter at all. Just make the $inverter nullable in your policy and it should be fixed:
public function update(User $user, Inverter $inverter = null)
{
return in_array($user->role,[
'Admin',
]);
}

i want to store restaurant id when saving my review blade

I have created a review blade for restaurants i need it to save the restaurants id .i have a variable called restaurant_id which stores the restaurants review comment.This is my review blade
<html>
{!!Form::open(['action' =['ReviewsController#store'],'method'=>'POST','enctype'=>'multipart/form-data'])!!}
<div class="form-group">
{{Form::textarea('value',null,['id'=>'value','placeholder'=>'Insert
here','name'=>'value'])}}
</div>
{{Form::submit('submit',['class'=>'btn btn-
primary','type'=>'submit','id'=>'submit'])}}
{!!Form::close()!!}
</html>
i also have user_id which stores the id the currently logged in user but it gives me an error
ErrorException (E_NOTICE)
Trying to get property 'id' of non-object
This is the review controller function that stores the review
public function store(Request $request )
{
// $restaurant=Restaurant::find($id);
$review=new Review;
$review->user_id=auth()->user()->id;
$review->restaurant_id=$request->route('id');
$review->value=$request->input('value');
$review->save();
}
This is the link to the review blade template on the restaurant
Add review
$review->user_id=auth()->user()->id;
This line assumes the existence of a logged in user. If your application supports reviews from non-authenticated users, you need to account for auth()->user() being null instead of a User object:
$review->user_id = auth()->user() ? auth()->user()->id : null;
Your code, specifically:
auth()->user()->id;
is assuming there is always an authenticated user. Currently there isn't, therefore you are:
Trying to get property 'id' of non-object
since auth()->user() is a non-object and you're attempting to get the property id from it.
You will have to do some kind of authentication check assuming you only want authenticated users doing what you want done.
public function store(Request $request)
{
if (! Auth::check() {
// Do something here if the user isn't authenticated, such as
// return back()->withInput();
}
$review = new Review;
$review->user_id = auth()->user()->id;
$review->restaurant_id = $request->route('id');
$review->value=$request->input('value');
$review->save();
}

How to use actuallymab\laravel-comment comments system?

I'm new to Laravel and I'm trying to implement a comments system on some posts. I found a package which seems well supported and I thought I could save some time by using it rather than starting from scratch.
The packing is here:
https://github.com/actuallymab/laravel-comment
There are some usage details but they don't seem quite clear enough for someone at my level.
Where I'm at:
Composer done
Migrations done
in my "User" model:
use Actuallymab\LaravelComment\CanComment;
In my "Post" model:
use Actuallymab\LaravelComment\Commentable;
class Posts extends Model {
use Commentable;
protected $canBeRated = true;
//etc
}
In my PostsController I have:
public function comment()
{
$userid = Auth::id();
$postid = "1"; //static post id for testing
$user = User::where('id','=',$userid);
$post = Post::where('id','=',$postid)->first();
$user->comment($post, 'Lorem ipsum ..', 3); // static comment for testing
}
And finally, my posts.blade:
<form action="{{ route('posts.comment') }}" method="POST">
{{ csrf_field() }}
<input type="text" id="commentdata"/> //not using this yet
<div class="form-group">
<input type="submit" class="btn btn-primary" value="Publish" />
<a class="btn btn-primary" href="{{ route('posts.comment') }}">Cancel</a>
</div>
Unfortunately, when I hit by submit button I get:
"Call to undefined method Illuminate\Database\Query\Builder::comment()"
So it seems I need to define a function in my User model? I'm not sure what to do here. I'm hoping some has used this package before.
Update 1:
I'm now using the following PostsController code:
public function comment()
{
$userid = "1"; //static user id for testing
$postid = "1"; //static post id for testing
$user = User::find($userid);
$post = Post::where('id','=',$postid)->first();
$user->comment($post, 'Lorem ipsum ..', 3); // static comment for testing
}
The error remains as "Call to undefined method Illuminate\Database\Query\Builder::comment()"
Call to undefined method Illuminate\Database\Query\Builder
You can be almost certain when you receive this error it's because you've missed out a step: you're calling a method on the query builder not the model. You need to retrieve the model(s) from the query.
Here's your current code:
$user = User::where('id','=',$userid);
You need to retrieve the first model from the results, e.g:
$user = User::where('id','=',$userid)->first();
Although you can improve this by using the find method which accepts a primary key and returns the model, e.g:
$user = User::find($userid);
Then from there you're ready to create the comment:
$user = User::find($userid);
$user->comment($post, 'Lorem ipsum ..', 3);
Example of using the trait:
<?php
namespace App;
use Actuallymab\LaravelComment\CanComment;
class User
{
use CanComment;
}

Laravel error is not passed to view

I can't figure put why laravel blade doesn't catch my error validation and doesn't pass it to my view.
In detail
I do have error snippet in my blade template
below is my validation which works correctly
What I'm missing?
Thank you
This is json message I see instead of message in blade template
{
message: "The given data was invalid.",
status_code: 500
}
This snippet I use to let user know about error
#if(count($errors))
<div class="form-group">
<div class="alert alert-danger">
<ul>
#if($errors->all())
#foreach($errors->all() as $error)
<li>{{$error}}</li>
#endforeach
#endif
</ul>
</div>
</div> #endif
And finally this is my correctly working validation
$request->validate([
'email' => 'required|email|unique:subscribers|max:255',
]);
EDIT:
This is the rout in web.php
Route::post('saveemail', 'SaveSubscriberEmailController#saveEmail');
And this is the method
namespace App\Http\Controllers;
use App\subscriber;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Ramsey\Uuid\Uuid;
class SaveSubscriberEmailController extends Controller
{
public function saveEmail(Request $request)
{
$request->validate([
'email' => 'required|email|unique:subscribers|max:255',
]);
$uuid = Uuid::uuid4();
$subscriber = new subscriber();
$subscriber->email = $request->email;
$subscriber->uuid = $uuid->toString();
$subscriber->created_at = Carbon::now();
$subscriber->save();
flash('Registration conformation email has been sent. Please check your mailbox. Thank you!')->success();
return redirect()->back();
}
}
I've had this problem before and the way I was able to fix it was to wrap the routes with a middleware group that includes the middleware \Illuminate\View\Middleware\ShareErrorsFromSession::class. It adds the session's errors to the view.
In your Kernel.php class's protected $middlewareGroups array it can look something like:
'web' => [
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
// other middleware
],
Then where you declare your routes you can do:
Route::group(['middleware' => ['web']], function () {
Route::post('saveemail', 'SaveSubscriberEmailController#saveEmail');
};
Request validation only send error of 422 not 500 if you are getting this error it's because of something else and the formRequest error bag won't catch this error .
Route::post('saveemail', 'SaveSubscriberEmailController#saveEmail');
Put this route into web middleware. you can do this like
Route::middleware(['web'])->group(function () {
Route::post('saveemail', 'SaveSubscriberEmailController#saveEmail');
});
Change your controller to this.
class SaveSubscriberEmailController extends Controller
{
public function saveEmail(Request $request)
{
$validator = validate($request->all(),[
'email' => 'required|email|unique:subscribers|max:255',
]);
if($validator->fails()){
return back()->withErrors($validator);
}
$uuid = Uuid::uuid4();
$subscriber = new subscriber();
$subscriber->email = $request->email;
$subscriber->uuid = $uuid->toString();
$subscriber->created_at = Carbon::now();
$subscriber->save();
flash('Registration conformation email has been sent. Please check your mailbox. Thank you!')->success();
return redirect()->back();
}
}
Hope this helps

Resources