codeception laravel seeResponseContainsJson don't match - laravel-4

I've got frim the server this response :
)]}', {"success":0,"errors":{"error":["Invalid username or
password."]}}
and I'm not able to do work seeResponseContainsJson
I've tried with:
public function invalidUserShouldBe200AndJsonTest(AcceptanceTester $I)
{
$I->wantTo('To see a 200 status code and a json response');
$I->sendAjaxPostRequest('/api/v1/signin',array('email'=>'user#users.com','password'=>'user'));
$I->seeResponseCodeIs('200');
$I->seeResponseIsJson();
$I->seeResponseContainsJson(array('errors' => array('error' => array('Invalid username or password.'))));
}
but I've got
I see response contains json {"errors":{"error":["Invalid username or
password."]}}
and it's the same also if the response is
{"success":0,"errors":{"error":["Invalid username orpassword."]}}
mmm should be something wrong if I try
$I->seeResponseIsJson();
dd($I->grabResponse());
seeResponseIsJson give me a green bar but grabResponse get me "" :(
my test
use \AcceptanceTester;
class SessionControllerCest
{
public function _before(\AcceptanceTester $I)
{
$I->wantTo('Grab the XSRF-TOKEN cookie value');
$I->amOnPage('/');
$text = $I->grabTextFrom('body > div > script');
$chunks1 = explode("\n", trim($text));
$chunks2 = explode("=", trim($chunks1[1]));
$cookieValue = rtrim($chunks2[2], ';"');
$I->setCookie('XSRF-TOKEN',$cookieValue);
$I->setHeader('X-XSRF-TOKEN',$cookieValue);
}
public function _after()
{
}
// tests
public function invalidUserShouldBe200AndJsonTest(AcceptanceTester $I)
{
$I->wantTo('To see a 200 status code and a json response');
$I->sendAjaxPostRequest('/api/v1/signin',array('email'=>'user#user.com','password'=>'sentryuser'));
$I->seeCookie('XSRF-TOKEN');
$I->seeResponseCodeIs('200');
$I->seeResponseIsJson();// until here green bar
// dd($I->grabResponse()); // empty string
//$I->seeResponseContainsJson(array('success' => 0,'errors' => array('error' => array('Invalid username or password.'))));
$I->seeResponseContains(""); // red bar
}
}
I set like that in _before because of Cross Site Request Forgery (XSRF) Protection
it's like
Route::filter('xhr', function()
{
if(!Request::ajax()){
return Response::make('Not Found', 404);
}
});
Route::filter('xsrf', function()
{
if((!isset($_COOKIE['XSRF-TOKEN']) || is_null(Request::header('X-XSRF-TOKEN'))) || ($_COOKIE['XSRF-TOKEN'] !== Request::header('X-XSRF-TOKEN'))){
return Response::make('Not Found', 404);
}
});
the route
Route::group(array('prefix' => 'api/v1', 'before' => 'xhr|xsrf'), function() {
/* Session */
Route::post('signin', array('as' => 'session.store', 'uses' => 'App\Controllers\SessionController#store'));
});
DEBUG
There is something wrong if I comment the _before block
trying to send a cUrl request like:
curl -H 'X-Requested-With: XMLHttpRequest' -d "email=user#user.com" \
-d "password=mysentryuser" \
http://lama.io/api/v1/signin
I get
{"success":0,"errors":{"error":["Invalid username or password."]}}
but when I run this
// tests
public function invalidUserShouldBe200AndJsonTest(AcceptanceTester $I)
{
$I->wantTo('To see a 200 status code and a json response');
$I->sendAjaxPostRequest('/api/v1/signin',array('email'=>'user#user.com','password'=>'mysentryuser'));
// $I->seeCookie('XSRF-TOKEN');
$I->seeResponseCodeIs('200');
//$I->seeResponseIsJson();// until here green bar
//dd($I->grabResponse()); // empty string
$I->seeResponseContainsJson(array('success' => 0,'errors' => array('error' => array('Invalid username or password.'))));
//$I->seeResponseContains(""); // red bar
}
I got
I see response contains json {"success":0,"errors":{"error":["Invalid
username or password."]}}
so may be something wrong but WHAT !

You can rewrite the last line of your test as follows:
$I->seeResponseContainsJson(array('success' => 0, 'errors' => array('error' => array('Invalid username or password.'))));
since that is the JSON that your response contains.

Related

How to flash validation errors to session in Laravel

The built in behavior for flashing back validation errors in Laravel does not seem to be working for my use case.
I have a (React) form that posts it's data via fetch API using this method, which reloads or redirects the page with (hopefully) any session data after the response is returned:
fetch(props.register_route, {
method: 'POST',
headers: {
'X-CSRF-Token': props.csrf,
},
body: data,
})
.then((result) => {
return result.json();
})
.then((result) => {
console.log(result);
window.location.href = result.url;
},
(error) => {
console.log(error);
});
In my controller, I validate this data but if I structure it as follows, the errors are not available as $errors in the resulting page
if ($validator->fails()) {
return redirect()->back()->withErrors($validator);
}
However if I manually flash the errors to the session and return a url instead of a redirect, suddenly the behavior works.
if ($validator->fails()) {
Session::flash('errors', $validator->errors());
return response->json([
'url' => route('register'),
], Response::HTTP_NOT_ACCEPTABLE);
}
I feel as if I must be doing something incorrectly here to have to use this workaround. I could also manually send the errors back in the response, which may be the right way to structure things in the long run.
when you are calling api from javascript or front end applications like Reactjs,Angular,android etc.. .So it expect return result should be in json format so it should be like
if ($validator->fails()) {
return response()->json( $validator->errors(),422);
}
if you not calling Method from direct laravel blade then pass response in JOSN Format.
like
https://laravel.com/docs/8.x/responses#json-responses
Or
make one ResponseManager File
<?PHP
namespace App\Libraries\utils;
class ResponseManager {
public static $response = array('flag' => true, 'data' => '', 'message' => '', 'code' => 01,);
public static function getError($data = '', $code = 10, $message = '', $flag = false) {
self::$response['flag'] = $flag;
self::$response['code'] = $code;
self::$response['data'] = $data;
self::$response['message'] = $message;
return self::$response;
}
public static function getResult($data = '', $code = 10, $message = '', $flag = true) {
self::$response['flag'] = $flag;
self::$response['code'] = $code;
self::$response['data'] = $data;
self::$response['message'] = $message;
return self::$response;
}}
Define in config/app.php
//custom class
'ResponseManager' => App\Libraries\utils\ResponseManager::class,
and then use in whole project
Error Message Like
if ($validation->fails()) {
$message = $validation->messages()->first();
return Response()->json(ResponseManager::getError('', 1, $message));
}
Success Message Like
return Response()->json(ResponseManager::getResult(null, 10, "Success"));

How to access laravel API with VUE JS?

so i want to use mylogin api but its not working,it keep push the route to dashboard even the email and the password incorrect
here is my code
export default {
data(){
return{
form: {
email: null,
password: null
},
user: {},
error: false
}
},
methods: {
login() {
this.user.append("email", this.form.email);
this.user.append("password", this.form.password);
this.axios.post('http://127.0.0.1:8000/api/login', this.user).then(response => {
localStorage.setItem("Name", response.data.first_name);
this.$router.push('/userDashboard/Dashboard')
});
},
register() {
this.$router.push('/RegisterPage')
}
},}
my laravel route api
Route::post('/login', 'UserController#login');
Login function
public function login(Request $request, User $user)
{
$email = $request->input('email');
$password = $request->input('password');
$user = User::where('email', '=', $email)->first();
if (!$user) {
return response()->json(['success'=>false, 'message' => 'Login Fail, please check email']);
}
if (!Hash::check($password, $user->password)) {
return response()->json(['success'=>false, 'message' => 'Login Fail, pls check password']);
}
return response()->json(['success'=>true,'message'=>'success', 'data' => $user]);
}
sorry for my english
This is because your laravel app always return 200 HTTP responses and this causes the .then( ... ) in the frontend to always be executed.
Either in the .then( ... ) your check the success value on the response that your Laravel has set, like this:
this.user.append("email", this.form.email);
this.user.append("password", this.form.password);
this.axios.post('http://127.0.0.1:8000/api/login', this.user).then(response => {
if (response.data.success === false) {
// handle the error and stop the code with a return
this.handleError();
return;
}
localStorage.setItem("Name", response.data.first_name);
this.$router.push('/userDashboard/Dashboard')
});
OR, you can also in Laravel throw a 401 or 400 response to say the login failed which will throw an exeception in the frontend, that you can catch with .then( ... ).catch( ... ).
That is the most clean way, because no need to send 'success' => true true anymore, since the HTTP code will be the source of truth with what happend.
public function login(Request $request, User $user)
{
$email = $request->input('email');
$password = $request->input('password');
$user = User::where('email', '=', $email)->first();
if (!$user || !Hash::check($password, $user->password)) {
// never tell the person if it's email or password, always say it's one of both for security reasons
return response(401)->json(['message' => 'Login Fail, please check email or password']);
}
return response()->json(['data' => $user]);
}
Last thing, I don't understand how this.user.append("email", this.form.email); works, because this.user seems to just be a simple object, so there isn't any append method on it.
So unless I'm missing something here, the best thing should just be to do:
const user = {
email: this.form.email,
password: this.form.password
}
// OR, make a copy
const user = { ...this.form }
// then send the user var to axios
this.axios.post('your url', user).then( ... )

How to fix Paypal Checkout Order Creation Error

I am using Laravel 8 framework for PHP and I am trying to integrate paypal into my the local web.
However I am stuck on `create_order_error` even though I have strictly followed some sample snippets provided by paypal I still encounter this pro
References:
https://developer.paypal.com/demo/checkout/#/pattern/server
https://github.com/paypal/Checkout-PHP-SDK#code
https://developer.paypal.com/docs/checkout/reference/server-integration/
Error:
SyntaxError: Unexpected token < in JSON at positio…1kLoyti46gxJY-Rl1PH23n49yWhf&currency=PHP:2:79380"
Code:
<script>
// Render the PayPal button into #paypal-button-container
paypal.Buttons({
style: {
shape: 'pill',
layout: 'horizontal',
color: 'blue',
height: 35
},
// Call your server to set up the transaction
createOrder: function(data, actions) {
return fetch('/billing/createOrder', {
method: 'post',
headers: {
'content-type': 'application/json'
}
}).then(function(res) {
return res.json();
}).then(function(orderData) {
return orderData.id;
});
},
}).render('#paypal-button-container');
</script>
Note: I have removed the onApprove function since I'm stuck on createOrder
Controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use PayPalCheckoutSdk\Core\PayPalHttpClient;
use PayPalCheckoutSdk\Core\SandboxEnvironment;
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
use PayPalHttp\HttpException;
class PaypalCheckoutController extends Controller
{
private $environment;
private $client;
public function __construct()
{
$this->environment = new SandboxEnvironment(config('paypal.client_id'), config('paypal.secret'));
$this->client = new PayPalHttpClient($this->environment);
}
public function index(Request $request)
{
return view('payment.checkout');
}
public function createOrder(Request $request)
{
$order = new OrdersCreateRequest();
$order->prefer('return=representation');
$order->body = array(
'intent' => 'CAPTURE',
'application_context' =>
array(
'return_url' => 'http://dummyweb.test/billing/checkout',
'cancel_url' => 'http://dummyweb.test/billing/checkout'
),
'purchase_units' =>
array(
0 =>
array(
'amount' =>
array(
'currency_code' => 'PHP',
'value' => '420.00'
)
)
)
);
try {
$result = $this->client->execute($order);
return $result;
}
catch(HttpException $ex) {
print_r($ex->getMessage());
}
}
}
SyntaxError: Unexpected token < in JSON at positio…
You are returning things other than JSON when the browser calls /billing/createOrder. You must only return JSON.
Use the Network tab in your browser's Developer Tools, or load the path in a new tab, to inspect the Response Body of what you are actually returning.
It will clearly be something other than JSON. Based on that error message it will start with some HTML (the < character)
Only return JSON. You need to be able to copy the entire Response Body into a JSON validator and have it be OK.
try
return response()->json($result);
and in the fetch request add header
Accept: 'application/json'

How to request shopify graphql-admin-api from an api?

I am trying to request shopify graphql-admin-api from my api. I am doing it according to the documentation given by graphql-admin-api, but it still gives me authorization errors.
PHP users can follow this function to make request to Shopify Admin API using GraphQL
I am using GuzzleHttp ( PHP HTTP client ) to create request
public function graph($query , $variables = []){
$domain = 'xxx.myshopify.com';
$url = 'https://'.$domain.'/admin/api/2019-10/graphql.json';
$request = ['query' => $query];
if(count($variables) > 0) { $request['variables'] = $variables; }
$req = json_encode($request);
$parameters['body'] = $req;
$stack = HandlerStack::create();
$client = new \GuzzleHttp\Client([
'handler' => $stack,
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
'X-Shopify-Access-Token'=>$this->token // shopify app accessToken
],
]);
$response = $client->request('post',$url,$parameters);
return $body = json_decode($response->getBody(),true);
}
$query = "{ shop { name email } }"; // this is example graphQL query
$response = graph($query) // call this function
Below code can help you to check how much cost this graphQL query
$calls = $response->extensions->cost;
$apiCallLimitGraph = [
'left' => (int) $calls->throttleStatus->currentlyAvailable,
'made' => (int) ($calls->throttleStatus->maximumAvailable - $calls->throttleStatus->currentlyAvailable),
'limit' => (int) $calls->throttleStatus->maximumAvailable,
'restoreRate' => (int) $calls->throttleStatus->restoreRate,
'requestedCost' => (int) $calls->requestedQueryCost,
'actualCost' => (int) $calls->actualQueryCost,
];
Go to Apps -> Manage Apps at the bottom and then :
Create a private app in Shopify, which will connect to your application. Make sure you manage permission for what you want to query
After creating the private app you will get the password which you can use as the token for your HTTP requests with header 'X-Shopify-Access-Token' value: password
curl -X POST \
https://{shop}.myshopify.com/admin/api/2021-04/graphql.json \
-H 'Content-Type: application/graphql' \
-H 'X-Shopify-Access-Token: {password}' \
-d '
{
products(first: 5) {
edges {
node {
id
handle
}
}
pageInfo {
hasNextPage
}
}
}
'
For more visit: https://shopify.dev/docs/admin-api/getting-started#authentication
The way I use in NodeJS is by using package "graphql-request" to make requests and
const mutation = gql`
mutation createProduct(
$input: ProductInput!
$media: [CreateMediaInput!]
) {
productCreate(input: $input, media: $media) {
userErrors {
field
message
}
product {
id
metafields(first: 1) {
edges {
node {
id
}
}
}
}
}
}
`;
//const input = form your own input
const res = await graphQLClient.rawRequest(mutation, input);

How to return json reponse from laravel to angular?

I have this in controller :
public function index(Request $request){
$email = $request->email;
$password = $request->password;
if (!$email || !$password) {return redirect()->back();}
if (Auth::attempt(['email' => $email, 'password' => $password])) {
// Authentication passed...
$this->loggedUser = Auth::user();
if($this->loggedUser){
return response()->json(['isLoggedIn' => true],200);
}
}
return response()->json(['isLoggedIn' => false],200);
}
In angular i have this:
Login (body: Object): Observable<Login[]> {
let bodyString = JSON.stringify(body); // Stringify payload
let options = new RequestOptions({ headers: this.headers }); // Create a request option
return this.http.post('/index', body, options) // ...using post request
.map(response => {return response} ,console.log('aaa')) // ...and calling .json() on the response to return data
.catch((error:any) => Observable.throw(error.json().error || 'Server error' )); //...errors if any
}
Problem is that when i open in browser response i get this:
Deprecated: Automatically populating
$HTTP_RAW_POST_DATA is deprecated and will be removed in a future
version. To avoid this warning set 'always_populate_raw_post_data' to
'-1' in php.ini and use the php://input stream instead. in
Unknown on line 0 Warning: Cannot
modify header information - headers already sent in Unknown on
line 0 {"isLoggedIn":false
}
Any suggestion how can fix that so that in response i get json?
This is a warning you get from PHP5.6 and it will be obscuring your data that you are getting back from your request.
Go into your php.ini file and update this line
;always_populate_raw_post_data = -1
to
always_populate_raw_post_data = -1
Don't forget to restart apache when you have made this update

Resources