How to fix Paypal Checkout Order Creation Error - laravel

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'

Related

InertiaJs Redirect returns 302 but doesn't render

Really sorry if this has been covered before but I can't find a working solution and have even asked numerous work colleagues.
I have a form which sends a POST request to my MailController, validation and everything works just as expected, but on success, I want to redirect to a Thank you page. The Post request returns either a 200 or 302 depending on the method I try but every time it only sends the HTML to the response and doesn't render the component.
I can, however, navigate to that page if I visit the URL and it loads perfectly.
I've tried
to_route
Inertia::render
Redirect()
Redirect()->route()
Redirect::route()
even sending it in response, catching it in Axio's request in the component, and redirecting from there.
This is driving me nuts I just can't see what I'm doing wrong.
TIA for your help and suggestions
//controller
<?php
namespace App\Http\Controllers;
use ...
use Inertia\Inertia;
use...
class MailController extends Controller
{
public function sendEmail(Request $request)
{
$contact = $request->validate([
......
],[
.......
]);
Mail::to('email#email.co.uk')->send(new ContactEmail($contact));
return Redirect::route('thankyou');
// return response()->json([
// 'data' => $contact,
// 'message' => 'Message sent successfully.',
// 'redirect' => route('thankyou')
// ], 201);
}
}
// route
Route::get('/thankyou', function () {
return Inertia::render('Thankyou');
})->name('thankyou');
// submit function
submitContact: function () {
axios.post('/email', this.contact)
.then(response => {
console.log(response.data.redirect);
// if (response.data.redirect) {
// return Inertia.location(response.data.redirect);
// }
}).catch(err => {
const errors = err.response.data.errors;
if (err) {
Object.keys(errors).forEach(key => {
this.errors[key] = errors[key][0];
});
}
})
}

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"));

Sf2 : FOS UserBundle : registration AJAX

I'm trying to register a user with AJAX.
I created an event listener on FOSUserEvents::REGISTRATION_SUCCESS
So I'm trying to know is an AJAX request has been made but the response on my client side doesn't satisfy me.
Here my event listener, note that the response sent is a test so of course there should be no "else" condition.
<?php
namespace SE\AppBundle\EventListener;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Ajax listener on FOS UserBundle registration
*/
class RegistrationListener implements EventSubscriberInterface
{
private $router;
public function __construct(RequestStack $RequestStack)
{
$this->requestStack = $RequestStack;
}
/**
* {#inheritDoc}
*/
public static function getSubscribedEvents()
{
return array(
FOSUserEvents::REGISTRATION_SUCCESS => 'onRegistrationSuccess'
);
}
public function onRegistrationSuccess()
{
$request = $this->requestStack->getCurrentRequest();
if ($request->isXmlHttpRequest()) {
$array = array( 'success' => true ); // data to return via JSON
$response = new Response( json_encode( $array ) );
$response->headers->set( 'Content-Type', 'application/json' );
return $response;
}
else{
$array = array( 'success' => false ); // data to return via JSON
$response = new Response( json_encode( $array ) );
$response->headers->set( 'Content-Type', 'application/json' );
return $response;
}
}
}
services.yml:
se.app.listener.registration:
class: SE\AppBundle\EventListener\RegistrationListener
arguments: ["#request_stack"]
tags:
- { name: kernel.event_subscriber }
javascript:
// Submit the request
$.ajax({
type : 'POST',
url : url,
data : data,
success : function(data, status, object) {
console.log('success');
console.log(data);
},
error: function(data, status, object){
console.log('error');
console.log(data);
}
});
Firstly the weird thing is that it goes in the error condition.
The console.log (data) is returned the DOM of the registration success page :
...
<p>Congrats brieuc.tribouillet7777#gmail.com, your account is now activated.</p>
...
So does this logic should be here or should I override the controller? What am I doing wrong?
Because of the level of the REGISTRATION_SUCCESS event, you can't return a response directly from the EventListener.
You need to grab the FormEvent and modify its response.
Lets pass it as argument:
class RegistrationListener implements EventSubscriberInterface
{
// ...
public function onRegistrationSuccess(FormEvent $event)
{
$request = $this->requestStack->getCurrentRequest();
// Prepare your response
if ($request->isXmlHttpRequest()) {
$array = array( 'success' => true ); // data to return via JSON
$response = new Response( json_encode( $array ) );
$response->headers->set( 'Content-Type', 'application/json' );
} else {
$array = array( 'success' => false ); // data to return via JSON
$response = new Response( json_encode( $array ) );
$response->headers->set( 'Content-Type', 'application/json' );
}
// Send it
$event->setResponse($response);
}
}
And it should work.
Note There is an issue about this event where the response cannot be modified.
If the problem occurs, you need to set a low priority in your event subscribing:
public static function getSubscribedEvents()
{
return [
FOSUserEvents::REGISTRATION_SUCCESS => [
['onRegistrationSuccess', -10],
],
];
}
See #1799.
EDIT
Note You should use a JsonResponse instead of json_encode your data and set the Content-Type manually.
To grab the form itself and its eventual errors, you can do this:
public function onRegistrationSuccess(FormEvent $event)
{
$form = $event->getForm();
if (count($validationErrors = $form->getErrors()) == 0) {
return $event->setResponse(new JsonResponse(['success' => true]));
}
// There is some errors, prepare a failure response
$body = [];
// Add the errors in your response body
foreach ($validationErrors as $error) {
$body[] = [
'property' => $error->getPropertyPath() // The field
'message' => $error->getMessage() // The error message
];
}
// Set the status to Bad Request in order to grab it in front (i.e $.ajax({ ...}).error(...))
$response = new JsonResponse($body, 400);
$event->setResponse($response);
}
But because it's a success event, you may need to override the method itself.

Ajax query works when adding new post but doesn't work when update an entity

I have two Select box one for the Countries and the second for the cities and the second one depends from the selected choice of the first one.
I the code is as the example Dynamic Generation for Submitted Forms in the documentation http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#cookbook-form-events-submitted-data
All things work fine when adding a new post , but when trying do update a post, the Ajax query to display cities doesn't work .
This is the controller
// newAction
/**
* #ParamConverter("agence", options={"mapping": {"agence_slug":"slug"}})
*/
public function newAction(Agence $agence, Request $request)
{
$em = $this->getDoctrine()->getManager();
$travel = new Travel();
$form = $this->createForm(new TravelType($agence), $travel);
if ($request->getMethod() == 'POST')
{
//....
}
return $this->render('AppBundle:Dashboard/Travel:new.html.twig',
array(
'form' => $form->createView() ,
'agence' => $agence,
));
}
//editAction
/**
* #ParamConverter("agence", options={"mapping": {"agence_slug":"slug"}})
* #ParamConverter("travel", options={"mapping": {"travel_id":"id"}})
*/
public function editAction(Travel $travel, Agence $agence, Request $request)
{
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(new TravelEditType($agence), $travel);
if ($request->getMethod() == 'POST'){
//....
}
return $this->render('AppBundle:Dashboard/Travel:edit.html.twig',
array(
'form' => $form->createView() ,
'travel' => $travel,
'agence' => $agence,
));
}
travelType and ti works good
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
//........
use Symfony\Component\Form\FormInterface;
use AppBundle\Entity\Country;
class TravelType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
//....
$formModifier = function (FormInterface $form, Country $country = null) {
$cities = null === $country ? array() : $country->getCities();
$form->add('destination', 'entity', array(
'class' => 'AppBundle:CityWorld',
'choices' => $cities,
'multiple' => false,
'expanded' => false,
'property' => 'name',
'label' => 'Destination',
'attr' => array('class' => 'col-xs-10 col-sm-10', 'placeholder' => 'Destination'),
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity, i.e. SportMeetup
$data = $event->getData();
$formModifier($event->getForm(), $data->getCountry());
}
);
$builder->get('country')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$country = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $country);
}
);
$builder->addEventListener(FormEvents::POST_SUBMIT, function ($event) {
$event->stopPropagation();
}, 90000000000000); // Always set a higher priority than ValidationListener
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Travel'
));
}
public function getName()
{
return null;
}
}
This is TravelEditType
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
//........
use Symfony\Component\Form\FormInterface;
use AppBundle\Entity\Country;
class TravelEditType extends TravelType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options) ;
}
public function getName()
{
return null;
}
}
This is the form and javascript code
<form method="post" action="" class="form-horizontal" role="form" {{ form_enctype(form) }} >
//.............
</form>
<script type="text/javascript">
var $county = $('#country');
$county.change(function () {
// ... retrieve the corresponding form.
var $form = $(this).closest('form');
var data = {};
data[$county.attr('name')] = $county.val();
// Submit data via AJAX to the form's action path.
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: data,
success: function (html) {
// Replace current position field ...
$('#city').replaceWith(
// ... with the returned one from the AJAX response.
$(html).find('#city')
);
// Position field now displays the appropriate positions.
}
});
});
Try it without parameter in URI:
dashboard_city_ajax:
path: /citiies/ajax
defaults: { _controller: AppBundle:TravelDashboard:ajaxCities }
And send data with POST:
$.ajax({
url: '{{ path('dashboard_city_ajax') }}',
type: 'POST',
data: { agence_slug: '{{ agenceSlug }}' },
You can receive it in controller:
$request->request->get('bar', 'default value if bar does not exist');
The problem is in your route matching. There is many way to solve problem. Try just include in your ajax route requirements for matching route or in $.ajax function use another route, for example
The simplest way for you (if you don't want rebuild your controller) is just rebuild your route and put in the first place your ajax route like :
dashboard_city_ajax:
path: /{ajax}/{agence_slug}/citiies
defaults: { _controller: AppBundle:TravelDashboard:ajaxCities }
requirements:
ajax: ajax
$.ajax({
url: '{{ path('dashboard_city_ajax', {'agence_slug': agence.slug, 'ajax': 'ajax' }) }}',
type: 'POST',
data: data,
But the right way IMHO is get your data from request. For example
vplanning_ajax:
path: /ajax
defaults: { _controller: VplanningPageBundle:Page:Ajax }
function getData(init) {
$.post(
{{ path('vplanning_ajax') }},
{
agence_slug: agence.slug,
yourdata2: 'yourdata2
} ,
function ( data ) {
handleData(data);
}
);
}
And in your Controller your just do
$agence_slug = $this->request->request->get('agence_slug');
$yourdata2 = $this->request->request->get('yourdata2);
...

Backbone.js Collections not applying Models (using Code Igniter)

I'm attempting to develop a site using CodeIgniter and Backbone.js, but I'm running into an issue when attempting to set Models to a Collection I have called fetch() on. I am using the REST API by Phil Sturgeon, and am receiving a JSON response when using fetch() on the Collection, but no children Models are added to it.
Here's the javascript I'm using:
$(document).ready(function() {
window.Person = Backbone.Model.extend({});
window.People = Backbone.Collection.extend({
model: Person,
url: "/api/content/users/format/json"
});
});
And my CI Controller:
require APPPATH.'/libraries/REST_Controller.php';
class Content extends REST_Controller {
function users_get() {
$users = array(
array('id' => 1, 'name' => 'Some Guy', 'email' => 'example1#example.com'),
array('id' => 2, 'name' => 'Person Face', 'email' => 'example2#example.com')
);
if($users) {
$this->response($users, 200); // 200 being the HTTP response code
} else {
$this->response(array('error' => 'Couldn\'t find any users!'), 404);
}
}
}
And when attempting to fetch() the Models for the Collection via the console like:
peoples = new People();
peoples.fetch();
peoples.models;
It gets the JSON response, but still says 'There are no child objects' (see image):
http://i.stack.imgur.com/e5vZv.png
Any idea what is going wrong? Totally stumped!
Explications
It's normal that people.models is empty directly after the fetch() call, you need to wait the end of the ajax request.
Indeed, fetch() is asynchronous and the Backbone JS documention says :
collection.fetch([options])
[...] The options hash takes success and error callbacks which will be passed (collection, response) as arguments.
Source: http://documentcloud.github.com/backbone/#Collection-fetch
Solution
You need to use :
peoples = new People();
peoples.fetch({
success: function (collection, response) {
// The collection is filled
console.log('Models : ', peoples.models);
}
});

Resources