I'm developing a simple cart with Laravel 4 and Paypal.
For the IPN Listener I've installed the following package:
- https://github.com/mike182uk/paypal-ipn-listener
I created a route with Route::any() allowing paypal to use any method on the request calling to a function with this simple code:
$listener = new \PayPal\Ipn\Listener;
$verifier = new \PayPal\Ipn\Verifier\CurlVerifier;
$ipnMessage = \PayPal\Ipn\Message::createFromGlobals();
$verifier->setIpnMessage($ipnMessage);
$verifier->setEnvironment('sandbox'); // can either be sandbox or production
$listener->setVerifier($verifier);
$listener->listen(function() use ($listener) {
// on verified IPN (everything is good!)
$resp = $listener->getVerifier()->getVerificationResponse();
$report = $listener->getReport();
$myfile = fopen("ipn.log", "w");
fwrite($myfile, $report);
fclose($myfile);
}, function() use ($listener) {
// on invalid IPN (somethings not right!)
$report = $listener->getReport();
$resp = $listener->getVerifier()->getVerificationResponse();
$myfile = fopen("ipn.log", "w");
fwrite($myfile, $report);
fclose($myfile);
});
When I see the log file Paypal return INVALID, and I see that I dont receive any post data.
But when I use IPN with a single php file with this code from Paypal github I receive all the data.
https://raw.githubusercontent.com/paypal/ipn-code-samples/master/paypal_ipn.php
P.S: I don't get any error, the IPN is sent successfully
The problem was because I had a csrf filter for al routes.
I solved it introducing this route in a group and adding this code to app/filters.php
// CSRF For routes outside "rest" route group.
$firstSegment = Request::segment(1);
if($firstSegment != 'rest')
Route::filter('csrf','post');
Related
Is it possible to globally set a listener on API calls made with Axios in Vue? The Laravel back-end has middleware set up on each endpoint that will either give the requested data or return a message saying that they need to check their messages. My goal is to capture that message and redirect the user to the page to view their message. I can't think of a way to do this other than setting something on each function that checks for the message and responds accordingly. There are hundreds of functions and that it wouldn't be a clean solution.
Any and all recommendations are welcome!
Using Axios Interceptors you can do something along these lines:
this.$http.interceptors.response.use(response => () {
// Redirect to a new page when you send
// custom header from the server
if (response.headers.hasOwnProperty('my-custom-header')) {
window.location.href = '/another-page';
}
// Or when you get a specific response status code
if (response.status === 402) {
window.location.href = '/another-page';
}
// Or when the response contains some specific data
if (response.data.someKey === 'redirect') {
window.location.href = '/another-page';
}
// ...or whatever you want
});
I tried to make my callback url dynamic because I'm configuring socialite in a multi auth system. I tried to use the socialiteproviders/manager as below:
$clientId = env($provider."_client_id");
$clientSecret = env($provider."_client_secret");
$redirectUrl = "the url i want";
$config = new \SocialiteProviders\Manager\Config($clientId,$clientSecret,$redirectUrl);
return Socialite::with($provider)->setConfig($config)->redirect();
but it says:
Call to undefined method Laravel\Socialite\Two\FacebookProvider::setConfig()
when trying to login with facebook.
Can someone please help me? Thank you.
I could reproduce and found a solution. The code you provided was outdated, and I found other instances of it here: https://laravel.io/forum/07-28-2016-dynamic-callback-url-laravel-socialite
By default, Socialite will get the provider config in services.php by passing the $providerName = facebook
So your code now becomes:
// The services.php config will return null, fix it by using: strtoupper()
$clientId = env(strtoupper($provider . "_client_id"));
$clientSecret = env(strtoupper($provider . "_client_secret"));
$redirectUrl = "/the-url-i-want";
// ->redirect() acts as a closure, without it, you'll get an error like:
// "Serialization of 'Closure' is not allowed"
$user = Socialite::with($provider)->redirect();
return redirect()->to($redirectUrl)->with(['user', $user]);
More info on redirecting with session data:
https://laravel.com/docs/6.x/redirects#redirecting-with-flashed-session-data
Im working on a project using vuejs and laravel 5.1 but i have a major problem. When i add data to the database using this code through Vuejs it randomly returns with a get request to the login page and doesn't enter the data.
this.$http.post('createAccount', this.account, function (data) {
//disable the loader
$('#loader').removeClass('active');
//show the success message with the new user url
var url = 'account=' + data;
var astr ="<a href='" + url + "'>" + " Success! View The Account By Clicking Here " + "</a>";
//Display sweet alert notification
global.displaySuccess('User Created', astr);
alert(astr);
}).error(function(data, status, request) {
global.displayError(status, 'Something went wrong!',
'Please make sure that all the fields are filled out!');
});
The above code works just fine about 3 times before it sends a request to go back to the login page as shown below.
And also when this happens sweet alert returns an extra 2 characters at the beginning of where the link should be. (Below Image)
If you reference back to the code, note the alert(astr), this is just to see whats being returned by the data. Every time the login request is randomly added this alerts the HTML code for the login page.
Lastly just incase anyone is curious this is route that its being posted to along with the code that its accessing in the controller.
//routes.php
Route::group(['prefix' => 'profitloss', 'middleware' => 'perm'], function(){
post('createAccount', 'AccountController#create');
});
//AccountController#create
public function create(Request $request)
{
$account = new Account();
$account->account_username = $request->input('account_username');
$account->account_password = $request->input('account_password');
$account->email_address = $request->input('email_address');
$account->email_password = $request->input('email_password');
$account->notes = $request->input('notes');
$account->gender = $request->input('gender');
$account->display_name = $request->input('display_name');
$account->first_name = $request->input('first_name');
$account->last_name = $request->input('last_name');
$account->save();
//return the id of that account.
return $account->id;
}
NOTE: I've had to disable CSRF because for some reason it keeps failing validation half the time and working the other half, However I don't think that this has anything to do with it.
Any help or information from anyone who has had a similar error to this would be greatly appreciated, thank you!
Short version: What would be the appropriate way to send the JWT generated from Facebook login (laravel/socialite) to the angularjs front end without using session.
Long Version
I am making an app that has angularjs front end and laravel 5.2 backend. I am using tymondesigns/jwt-auth for authentication instead of session.
I am also using laravel/socialite for social Facebook authentication. For that I am using the stateless feature of socialite so that I don't need session in any ways.
The basic authentication works perfectly. But, when I try to use Facebook login, I follow these steps
User clicks on a button on the angular side that redirects to the provider login page of the back end.
public function redirectToProvider() {
return Socialite::with('facebook')->stateless()->redirect();
}
2. User gives his login information. After logging in he is redirected to my handlecallback function.
try {
$provider = Socialite::with('facebook');
if ($request->has('code')) {
$user = $provider->stateless()->user();
}
} catch (Exception $e) {
return redirect('auth/facebook');
}
return $this->findOrCreateUser($user);
Next I use the findorcreate function to determine whether the user exists or not. If not than I just create a new user and create JWT from that.
$user = User::where('social_id', '=', $facebookUser->id)->first();
if (is_object($user)) {
$token = JWTAuth::fromUser($user);
return redirect()->to('http://localhost:9000/#/profile?' . 'token=' . $token);#angular
} else {
$result = array();
$result['name'] = $facebookUser->user['first_name']
$result['email'] = $facebookUser->user['email'];
$result['social_id'] = $facebookUser->id;
$result['avatar'] = $facebookUser->avatar;
$result['gender'] = $facebookUser->user['gender'];
$result['status'] = 'active';
$result['login_type'] = 'facebook';
$result['user_type'] = 'free_user';
try {
$user = User::create($result);
} catch (Exception $e) {
return response()->json(['error' => 'User already exists.'], HttpResponse::HTTP_CONFLICT);
}
$token = JWTAuth::fromUser($user);
return redirect()->to('http://localhost:9000/#/profile?' . 'token=' . $token);#angular
}
My problem is, in the last block of code I am having to send the jwt to my frontend via url. Which isn't secure at all. What would be the right way to send the generated JWT to the frontend without using session. Thank you
The official documentation of Laravel Socialite says:
Stateless Authentication
The stateless method may be used to disable session state verification. This is useful when adding social authentication to an API:
return Socialite::driver('google')->stateless()->user();
Then, you can authenticate using the jwt-auth method:
JWTAuth::fromUser($user)
If you're using $http on the Angular side, try returning the token as a JSON response from Laravel:
return response()->json(compact('token'));
Then store the token in localStorage or sessionStorage or what have you.
If you're generating your Angular page from within Laravel (i.e. not using Laravel as an API, but showing your Angular page from /public/index.php, for instance) you could load the view with the token in the data for the view.
As long as you're using HTTPS either of these two scenarios are better than passing the token in the redirect URL.
You can store token and use client side redirect without storing to browser history to redirect user to profile page without token in URL:
document.location.replace({profile-url})
set_flashdata is not working directly after redirect with only one redirect.
I am using one controller in this process - Profilers' Controller. It handles the member confirmation process and also displays the login page on the redirect. The process is as follows:
this session set_flashdata ('topic', 'newmember')
redirect ('login')
route ['login'] = 'profilers/signIn'
topic = $this session flashdata ('topic')
I have turned off all database session configuration for cleaner debugging and even though session library is turned on in configs, I have started calling it anyways which doesn't seem to work either.
Here is my code. As you can see, I am sending path info to a log file path.log:
in controller Profilers, function confirmMember:
public function confirmMember()
{
//use_ssl();
$this->form_validation->set_rules('handle', 'Unique Member Name', 'trim|xss_clean|required|min_length[5]|max_length[30]');
$this->form_validation->set_rules('confirmation', 'Confirmation Code', 'trim|xss_clean|required|min_length[20]|max_length[20]|alpha_numeric');
if ($this->form_validation->run() === FALSE) {echo "here";exit;
$data['handle']=$this->input->post('handle');
$data['confirmation']=$this->input->post('confirmation');
$this->load->view('signing/defaults/header',$data);
$this->load->view('defaults/heading',$data);
$this->load->view('defaults/banner');
$this->load->view('defaults/banner_right');
$this->load->view('member/temp/index',$data);
$this->load->view('defaults/footer',$data);
} else {
$post = $this->input->post(NULL,TRUE);
$data['member'] = $this->Signing_model->model_confirmMember($post);
if ($data['member']['confirmed']!==FALSE) {
/* PATH CHECK */
error_log("member confirmation not false\n",3, LOG_DIR.'path.log');
unset($post);
$this->session->sess_destroy();
$this->session->set_flashdata('topic', 'newmember');
// $this->session->keep_flashdata('topic');
redirect('login','refresh');
} else {
/* PATH CHECK */
error_log("member confirmation IS FALSE\n",3, LOG_DIR.'path.log');
$this->load->view('member/temp/index',$data);
}
My log file shows that the path is using the correct path and showing "member confirmation not false".
I have tried with keep_flash data on (which I assumed wouldn't work since there are no other redirects) and off.
I have also tried redirect without 'refresh'.
In config/routes.php:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
$route['join'] = 'profilers/joinUp';
$route['login'] = 'profilers/signIn';
...
Login page uses Profilers Controller, signIn function as show above:
public function signIn()
{
$topic = $this->session->flashdata('topic');
if (isset($topic)) {
$message = "topic is set. topic = ".$topic."\n";
if ($topic!==FALSE) {
error_log("flash var topic is not false\n", 3, LOG_DIR.'path.log');
} else {
error_log("flash var topic is FALSE\n", 3, LOG_DIR.'path.log');
}
} else {
$message = "topic is NOT set\n";
}
error_log($message,3,LOG_DIR.'path.log');
exit;
...
...
}
log file is showing that topic is set but is false.
"flash var topic is FALSE"
"topic is set. topic = "
Of course topic var not set since it is FALSE.
As you can see, I have moved the get flash data function to the beginning of my controller function to bypass anything that may be corrupting data.
You may need to start the session again after you have destroyed it.
Try adding this after your call to sess_destory():
$this->session->sess_create()
Alternatively you could avoid destroying the session, and unset() the values you wish to get rid of.