Method App\Http\Controllers\XeroController::data does not exist - php

Hello i am having xero API
i am trying to integrate it with my laravel project , i am getting above error I am using following laravel package for same.
github package link : https://github.com/webfox/laravel-xero-oauth2/
----------------routes-----------------
Route::get('/manage/xero', [XeroController::class, 'index'])->name('xero.auth.success');
Route::get('xero/auth/callback', [XeroController::class, 'data'])->name('xero.auth.callback');
---controller-----------------
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Webfox\Xero\OauthCredentialManager;
class XeroController extends Controller
{
public function index(Request $request, OauthCredentialManager $xeroCredentials)
{
try {
// Check if we've got any stored credentials
if ($xeroCredentials->exists()) {
/*
* We have stored credentials so we can resolve the AccountingApi,
* If we were sure we already had some stored credentials then we could just resolve this through the controller
* But since we use this route for the initial authentication we cannot be sure!
*/
$xero = resolve(\XeroAPI\XeroPHP\Api\AccountingApi::class);
$organisationName = $xero->getOrganisations($xeroCredentials->getTenantId())->getOrganisations()[0]->getName();
$user = $xeroCredentials->getUser();
$username = "{$user['given_name']} {$user['family_name']} ({$user['username']})";
}
} catch (\throwable $e) {
// This can happen if the credentials have been revoked or there is an error with the organisation (e.g. it's expired)
$error = $e->getMessage();
}
return view('xero', [
'connected' => $xeroCredentials->exists(),
'error' => $error ?? null,
'organisationName' => $organisationName ?? null,
'username' => $username ?? null
]);
}
}

Your xero/auth/callback route is routed to the XeroController::data() function, which does not exist.
Looking at that package, it looks like it already registers a route for xero/auth/callback, pointing to the AuthorizationCallbackController in the package. I'm assuming you just need to remove your manually defined route.

Related

Laravel Cashier cancel() throws a BadMethodCallException

I used Laravel Cashier to handle my user's subscription, however when I try to do the basic cancellation $user->subscription('main')->cancel(), an exception is being thrown
BadMethodCallException: Call to undefined method Illuminate\Database\Query\Builder::asStripeCustomer() in
\try\vendor\laravel\framework\src\Illuminate\Database\Query\Builder.php:2483
Stack trace:
\try\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php(1470): Illuminate\Database\Eloquent\Builder->__call('asStripeCustome...', Array)
\try\vendor\laravel\cashier\src\Subscription.php(345): Illuminate\Database\Eloquent\Model->__call('asStripeCustome...', Array)
\try\vendor\laravel\cashier\src\Subscription.php(256): Laravel\Cashier\Subscription->asStripeSubscription()
I setup the Model correctly and I uses the Billable trait so I really have no idea what's really causing this error
App\User.php
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Cashier\Billable;
class User extends Authenticatable{
use Billable;
...
}
App\Http\Controllers\UserController.php
public function cancelSubscription(Request $request)
{
$user = $request->user();
try {
if ($user->subscription('main')->onTrial()) {
$user->subscription('main')->cancelNow();
} else {
$user->subscription('main')->cancel();
}
} catch (\Exception $e) {
\Log::error($e);
return [
'success' => 0,
'message' => "Something went wrong while trying cancel your subscription. Please try again later."
];
}
Any help and hints will be greatly appreciated, thanks in advance!
My bad, I just found out that it was actually with my stripe configuration on /config/services.php as I have two models for my Users (because I'm also using another package other than laravel-cashier to handle payments via Authorize.net on which I ended up creating different Models for them to work)
'stripe' => [
// 'model' => App\AnetUser::class, => this actually caused the error as
// ->asStripeCustomer() doesn't exists on an Authorize.net's Billable trait
'model' => App\User::class,
'key' => env('STRIPE_KEY'),
'secret' => env('STRIPE_SECRET'),
],
I feel so stupid. XD
Hi I've never worked with Laravel Cashier before but, I think the root of your problem might be that you are accessing user from the request, therefore it's not a user instance thats why it triggers undefined methods errors.
So creating a user instance should probably work out for you:
Note: I don't know if $request->user is primary key or whole user instance so I added different solutions
public function cancelSubscription(Request $request)
{
// if $request->user is the user instance you can do this:
$user = App\User::findOrFail($request->user->id);
// if $request->user was any other field from user you could retrieve
// the user using something like->
// App\User::where('fieldName', 'LIKE', $request->user)->firstOrFail();
try {
if ($user->subscription('main')->onTrial()) {
$user->subscription('main')->cancelNow();
} else {
$user->subscription('main')->cancel();
}
} catch (\Exception $e) {
\Log::error($e);
return [
'success' => 0,
'message' => "Something went wrong while trying cancel your subscription. Please try again later."
];
}
}

JWT authentication in Laravel without database

I have a question regarding Authentication in Laravel 5.x. I’ve been specifically looking at tymondesigns/jwt-auth and irazasyed/jwt-auth-guard packages to do the JSON web token authentication token handling in my Laravel application.
I am not using a local database whatsoever, nor do I want to. I have environment variables set up in .env for my API’s URL, USERNAME & PASSWORD. The Guzzle PHP HTTP client is doing the trick just fine, connecting and returning data between the API and my application as needed.
However, I need to set up Authentication within my Laravel instance. I run into problems here, and the auth is wanting a DB connection.
$token = JWTAuth::attempt($credentials)
Here's the exception:
PDOException in Connector.php line 55:
SQLSTATE[HY000] [14] unable to open database file
How can I make use of JWT without using a database?
How can I COMPLETELY shut-off database connections within Laravel?
Thanks.
UPDATE:
Using tymon/jwt-auth, I've set things up within the routes, Kernel, Middleware, etc.
I created a "claim" successfully, but I need to create the token by encoding the "payload."
$this->username = $request->username;
$sub = $this->username;
$iat = time();
$jti = md5($sub . $iat);
$aud = env('APP_URL');
$this->claims = [
'sub' => $sub,
'iat' => $iat,
'exp' => time() + (2 * 7 * 24 * 60 * 60),
'nbf' => $iat,
'iss' => 'khill',
'jti' => $jti,
'aud' => $aud,
];
$payload = JWTFactory::make($this->claims);
How do I get the custom token?
You should define a custom Authentication Provider and set it in config/jwt.php.
Example of provider
Put this class anywhere you like.
namespace MyNamespace;
use Tymon\JWTAuth\Providers\Auth\AuthInterface;
class MyCustomAuthenticationProvider implements AuthInterface
{
public function byCredentials(array $credentials = [])
{
return $credentials['username'] == env('USERNAME') && $credentials['password'] == env('PASSWORD');
}
public function byId($id)
{
// maybe throw an expection?
}
public function user()
{
// you will have to implement this maybe.
}
}
Example of configuration
In the providers array in config/jwt.php, change this:
'auth' => 'Tymon\JWTAuth\Providers\Auth\IlluminateAuthAdapter',
to this:
'auth' => 'MyNamespace\MyCustomAuthenticationProvider',
Other considerations
Using the env() function anywhere is not good practice. It's better to use it in your config files, and then use the config() function anywhere else.
You may need to reimplement also the User Provider.
JWTAuth::attempt() won't help you with this, because it hits the database for you behind the scenes. You need some other way to check the environment credentials.
Add a custom method to a class somewhere which will do that for you or pass the credentials against the API you are hitting with Guzzle.
Code example:
public function authenticate($username, $password)
{
if(!$username === env('USERNAME') or !$password === env('PASSWORD')) {
// return a message that the user could not be authenticated or false.
}
// Generate the JWT token here and store it somewhere.
}
As a quick fix I decided to implement the following custom code...
1) Created custom middleware to handle the logic.
class CustomMiddleware
{
protected $loginPath = 'login';
public function handle($request, Closure $next) {
$logged_in = $request->session()->get('logged_in');
if (!$logged_in) {
return redirect()->guest('login')->with('flag','1');
}
return $next($request);
}
}
2) Added a reference to the middleware class.
class Kernel extends HttpKernel
{
protected $routeMiddleware = [
'custom' => \App\Http\Middleware\CustomMiddleware::class,
];
}
3) Added it to routes.php.
Route::group(['middleware' => ['custom']], function () {
// Add routes here
}
yes.
you can create jwt token without database using tymondesigns/jwt-auth package...
for that you have to use jwt::encode method...
let me explain ...
first you have to put your credential in .env file...
then i am recomending you to use custom claims ...
after that you can create jwt token using below code ...
$customClaims = ['foo' => 'bar', 'baz' => 'bob'];
$factory = JWTFactory::customClaims($customClaims);
$token = JWTAuth::encode($payload);
for further details you can refer below link
wiki

Using Laravel Socialite with an API?

I'm trying to use Laravel Socialite package over an api. I try to pass the code into my api to fetch the user but it keeps giving me an error:
Fatal error: Call to a member function pull() on null
Since I'm doing the request over an API, I take the following steps.
Send a request to api for the url to fetch the code:
Socialite::with('facebook')->stateless()->redirect()->getTargetUrl()
Then make a request with the above fetched url, which redirects with the code parameter.
Send the code to the api and fetch the user:
$fb_user = Socialite::with('facebook')->user();
This is where it crashes. I'm not sure why.
I've used the package before and it works fine when I just have an app that reloads the page. But when I send it to an api (on a different domain) it crashes. I'm thinking there is some issue with how the code is generated. Is there anyway to fix this?
Just found my answer. Need to use stateless in both calls:
Socialite::with('facebook')->stateless()->redirect()->getTargetUrl()
$fb_user = Socialite::with('facebook')->stateless()->user();
Hope this helps someone.
I made SocialController.php and url (POST request) /api/social-login which accepts provider and access_token.
SocialAccount here is a laravel model where you'll provider and provider_user_id and local database user id. Below is the example of social_accounts table
And in SocialController :
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
use App\User;
use App\SocialAccount;
use Socialite;
class SocialController extends Controller
{
public function social(Request $request) {
$provider = $request->input('provider');
switch($provider){
case SocialAccount::SERVICE_FACEBOOK:
$social_user = Socialite::driver(SocialAccount::SERVICE_FACEBOOK)->fields([
'name',
'first_name',
'last_name',
'email'
]);
break;
case SocialAccount::SERVICE_GOOGLE:
$social_user = Socialite::driver(SocialAccount::SERVICE_GOOGLE)
->scopes(['profile','email']);
break;
default :
$social_user = null;
}
abort_if($social_user == null , 422,'Provider missing');
$social_user_details = $social_user->userFromToken($request->input('access_token'));
abort_if($social_user_details == null , 400,'Invalid credentials'); //|| $fb_user->id != $request->input('userID')
$account = SocialAccount::where("provider_user_id",$social_user_details->id)
->where("provider",$provider)
->with('user')->first();
if($account){
return $this->issueToken($account->user);
}
else {
// create new user and social login if user with social id not found.
$user = User::where("email",$social_user_details->getEmail())->first();
if(!$user){
// create new social login if user already exist.
$user = new User;
switch($provider){
case SocialAccount::SERVICE_FACEBOOK:
$user->first_name = $social_user_details->user['first_name'];
$user->last_name = $social_user_details->user['last_name'];
break;
case SocialAccount::SERVICE_GOOGLE:
$user->first_name = $social_user_details->user['name']['givenName'];
$user->last_name = $social_user_details->user['name']['familyName'];
break;
default :
}
$user->email = $social_user_details->getEmail();
$user->username = $social_user_details->getEmail();
$user->password = Hash::make('social');
$user->save();
}
$social_account = new SocialAccount;
$social_account->provider = $provider;
$social_account->provider_user_id = $social_user_details->id;
$user->social_accounts()->save($social_account);
return $this->issueToken($user);
}
}
private function issueToken(User $user) {
$userToken = $user->token() ?? $user->createToken('socialLogin');
return [
"token_type" => "Bearer",
"access_token" => $userToken->accessToken
];
}
}
EDIT:
I have created package for the same https://packagist.org/packages/pimplesushant/laravelsocialiteapi

auth::attempt($credentials) not work in other controller in laravel 5.1

I have a custom need where I am trying to connect Laravel with Django app. Currently, I am not using laravel's default login post method to establish user session, instead of that I am trying to access Auth::attempt($credentials);. By this way, I am able to establish user session in my custom login controller whereas in other controllers the session is not established.
Login controller:
$credentials = array('email' => $userjson["email"],'password' => $password);
Auth::attempt($credentials);
if(Auth::guest())
echo "guest";
else
return redirect()->intended('/dashboard');
Result: redirect to the dashboard page (which means session is established)
Dashboard controller
if(Auth::check())
echo "true";
else
echo "false";
Result: false (which means the session is not established)
Can someone help me to resolve this?
Use this code .we'll need to make sure to import the Auth facade at the top of the class .For more help go to https://laravel.com/docs/5.2/authentication and ready topic Manually Authenticating Users. Thanks
namespace App\Http\Controllers;
use Auth;
class OtherController extends Controller
{
/**
* Handle an authentication attempt.
*
* #return Response
*/
public function authenticate()
{
if (Auth::attempt(['email' => $email, 'password' => $password])) {
// Authentication passed...
return redirect()->intended('dashboard');
}
}
}

Laravel cURL POST Throwing TokenMismatchException

I have a problem with POST cURL request to my application.
Currently, I'm building RESTFUL registration function using laravel 5.
The routes for this is example is
localhost:8000/user/create
I pass value using cURL function on terminal
curl -d 'fname=randy&lname=tan&id_location=1&email=randy#randytan.me&password=randytan&remember_token=Y&created_at=2015-03-03' localhost:8000/auth/register/
And this is my routes.php
Route::post('user/create', 'UserController#create');
And this is my function to store the registration user
public function create()
{
//function to create user.
$userAccounts = new User;
$userAccounts->fname = Request::get('fname');
$userAccounts->lname = Request::get('lname');
$userAccounts->id_location = Request::get('id_location');
$userAccounts->email = Request::get('email');
$userAccounts->password = Hash::make(Request::get('password'));
$userAccounts->created_at = Request::get('created_at');
$userAccounts->save();
return Response::json(array(
'error' => false,
'user' => $userAccounts->fname . " " . $userAccounts->lname
), 200);
}
Executing the cURL syntax above, I'm getting this error TokenMismatchException
Do you have any ideas?
Because I'm implementing middleware only in my few urls, and this cURL registration url is not tight into any authentication mechanism.
Thanks before.
In Laravel 5 (latest version) you can specify routes you want to exclude in /app/Http/Middleware/VerifyCsrfToken.php
class VerifyCsrfToken extends BaseVerifier
{
/**
* The URIs that should be excluded from CSRF verification.
*
* #var array
*/
protected $except = [
'rest-api/*', # all routes to rest-api will be excluded.
];
}
Hope this helps.
Laravel 5 enforces CSFR token authentication in middleware by default.
you can disable CSFR on selected route Here is the link
or you can try some of these solutions. Hope so it will help.
changing your csfr token method /app/Http/Middleware/VerifyCsrfToken.php
public function handle ($request, Closure $next)
{
if ( !$request->is("api/*"))
{
return parent::handle($request, $next);
}
return $next($request);
}
In my case, i needed to add the route on api.php instead of web.php

Categories