PayPal Express Error: Unexpected token S in JSON at position 0 - php

I am integrating PayPal express checkout (server-side) in my PHP website. While I am integrating the PayPal express popup is not opening and it is giving me "Unexpected token S in JSON at position 0" in the console. Here is the screenshot https://prnt.sc/10f10qi
Here is HTML code:
<script src="https://www.paypal.com/sdk/js?client-id=<client-id>"></script>
<script>
paypal.Buttons({
createOrder: function() {
return fetch('paypal/create-payment.php', {
method: 'post',
headers: {
'content-type': 'application/json'
}
}).then(function(res) {
return res.json();
}).then(function(data) {
return data.id;
});
},
onAuthorize: function(data, actions) {
return actions.payment.execute().then(function() {
alert(data.orderID);
});
}
}).render('#paypal-button');
</script>
<div id="paypal-button"></div>
Here is the server side code for create-payment.php
<?php
namespace Sample\CaptureIntentExamples;
require __DIR__ . '/vendor/autoload.php';
//1. Import the PayPal SDK client that was created in `Set up Server-Side SDK`.
use Sample\PayPalClient;
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
require 'paypal-client.php';
class CreateOrder
{
// 2. Set up your server to receive a call from the client
/**
*This is the sample function to create an order. It uses the
*JSON body returned by buildRequestBody() to create an order.
*/
public static function createOrder($debug=false)
{
$request = new OrdersCreateRequest();
$request->prefer('return=representation');
$request->body = self::buildRequestBody();
// 3. Call PayPal to set up a transaction
$client = PayPalClient::client();
$response = $client->execute($request);
if ($debug)
{
print "Status Code: {$response->statusCode}\n";
print "Status: {$response->result->status}\n";
print "Order ID: {$response->result->id}\n";
print "Intent: {$response->result->intent}\n";
print "Links:\n";
foreach($response->result->links as $link)
{
print "\t{$link->rel}: {$link->href}\tCall Type: {$link->method}\n";
}
// To print the whole response body, uncomment the following line
// echo json_encode($response->result, JSON_PRETTY_PRINT);
}
// 4. Return a successful response to the client.
return $response;
}
/**
* Setting up the JSON request body for creating the order with minimum request body. The intent in the
* request body should be "AUTHORIZE" for authorize intent flow.
*
*/
private static function buildRequestBody()
{
return array(
'intent' => 'CAPTURE',
'application_context' =>
array(
'return_url' => 'https://example.com/return',
'cancel_url' => 'https://example.com/cancel'
),
'purchase_units' =>
array(
0 =>
array(
'amount' =>
array(
'currency_code' => 'USD',
'value' => '220.00'
)
)
)
);
}
}
/**
*This is the driver function that invokes the createOrder function to create
*a sample order.
*/
if (!count(debug_backtrace()))
{
CreateOrder::createOrder(true);
}
?>
Please let me know what I am doing wrong? Thanks!

Related

Laravel 9 Queue Jobs Doesn't Send Web Push Messages

I am creating a laravel web app on windows server and IIS.
I want to send web push messages to clients and to boost performance I want to use Laravel Queue. Addition queue or work with queue is okay but web push messages don't come.
I am using IIS service on a azure virtual machine. My codes are here.
Thank you.
This is my notification controller :
<?php
namespace App\Http\Controllers\dashboard\notifications;
use App\Http\Controllers\Controller;
use App\Jobs\SendNotifications;
use App\Models\Notifications;
use Illuminate\Http\Request;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
class indexController extends Controller
{
public function subscription(Request $request)
{
$request->validate([
"endpoint" => "required",
"p256dh" => "required",
"axn" => "required",
"auth" => "required"
]);
if ($request->axn == "subscribe") {
$num = Notifications::where("endpoint", "=", strip_tags($request->endpoint))->count();
if ($num == 0) {
$result = Notifications::create([
"user_id" => auth()->user()->id,
"auth" => $request->auth,
"p256dh" => $request->p256dh,
"endpoint" => strip_tags($request->endpoint)
]);
if ($result) {
$endpoints = Notifications::where("user_id", "=", auth()->user()->id)->get();
foreach ($endpoints as $key => $value){
dispatch(new SendNotifications($value->endpoint,$value->auth,$value->p256dh, __("notifications.New device has been subscribed to our notification service."), __("notifications.New device has been subscribed to our notification service."), LaravelLocalization::localizeUrl('/dashboard')));
}
return response()->json(['success' => true, "data" => "success"], 200);
} else {
return response()->json(['success' => false, "data" => "fail"], 400);
}
} else {
return response()->json(['success' => true, "data" => "success"], 200);
}
} else {
$deletion = Notifications::where("endpoint", "=", strip_tags($request->endpoint))->delete();
if ($deletion) {
return response()->json(['success' => true, "data" => "success"], 200);
} else {
return response()->json(['success' => false, "data" => "fail"], 400);
}
}
}
}
and this is my SendNotification laravel queue :
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Minishlink\WebPush\WebPush;
use Minishlink\WebPush\Subscription;
class SendNotifications implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $contentEncoding = "aesgcm";
private $title;
private $message;
private $url;
private $endpoint;
private $image;
private $auth_key;
private $p256dh;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($endpoint, $auth_key, $p256dh, $title, $message, $url, $image = "")
{
$this->endpoint = $endpoint;
$this->title = $title;
$this->message = $message;
$this->url = $url;
$this->image = $image;
$this->auth_key = $auth_key;
$this->p256dh = $p256dh;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$auth = [
'VAPID' => [
'subject' => $this->url, // can be a mailto: or your website address
'publicKey' => env("VAPID_PUBLIC_KEY"), // (recommended) uncompressed public key P-256 encoded in Base64-URL
'privateKey' => env("VAPID_PRIVATE_KEY"), // (recommended) in fact the secret multiplier of the private key encoded in Base64-URL
],
];
$defaultOptions = [
'TTL' => 5000, // defaults to 4 weeks
'urgency' => 'normal', // protocol defaults to "normal"
'topic' => 'new_event', // not defined by default,
'batchSize' => 1000, // defaults to 1000
];
$webPush = new WebPush($auth, $defaultOptions);
$webPush->setDefaultOptions($defaultOptions);
$payload = '{"title":"'.$this->title.'","msg":"'.$this->message.'","icon":"https://diginorm.com.tr/images/icons/icon-96x96.png","badge":"https://diginorm.com.tr/images/icons/icon-96x96.png","image":"'.$this->image.'","openUrl":"'.$this->url.'"}';
$subscription = new Subscription($this->endpoint, $this->p256dh, $this->auth_key, $this->contentEncoding);
$webPush->sendOneNotification($subscription, $payload);
}
}
And this is my ServiceWorker.js
self.addEventListener('notificationclick', function(event) {
var notification = event.notification;
var action = event.action;
console.log(notification);
if (action === 'confirm') {
console.log('Confirm was chosen');
notification.close();
} else {
console.log(action);
event.waitUntil(
clients.matchAll()
.then(function(clis) {
var client = clis.find(function(c) {
return c.visibilityState === 'visible';
});
if (client !== undefined) {
client.navigate(notification.data.url);
client.focus();
} else {
clients.openWindow(notification.data.url);
}
notification.close();
})
);
}
});
self.addEventListener('notificationclose', function(event) {
console.log('Notification was closed', event);
});
self.addEventListener('push', function(event) {
console.log('Push Notification received', event);
var data = {title: 'New!', msg: 'Something new happened!', image: '/images/icons/icon-512x512.png', openUrl: '/'};
if (event.data) {
data = JSON.parse(event.data.text());
}
var options = {
body: data.msg,
icon: "/images/icons/icon-96x96.png",
badge: "/images/icons/icon-96x96.png",
image: data.image,
dir: "ltr",
lang: "en-GP",
vibrate:[200, 100, 200, 100, 200, 100, 200],
data: {
url: data.openUrl
}
};
event.waitUntil(
self.registration.showNotification(data.title, options)
);
});
this is jobs table :
and this is the php artisan command result :

WordPress REST API endpoint doesn't respond

I have created a custom payment plugin now I need to set up an endpoint that will receive webhook callbacks from the payment gateway. My code for the endpoint is as seen below:
add_action('rest_api_init', function () {
register_rest_route(
'namespace/v1/', 'endpoint',
array (
'methods' => 'POST',
'callback' => 'return_payment_status'
)
);
});
function return_payment_status (WP_REST_Request $request_data) {
$pay_resp = array();
$params = $request_data->get_params();
if ( isset($params['result']) ) {
$pay_resp['result'] = $params['result'];
$pay_resp['message'] = $params['message'];
}
else {
$pay_resp['result'] = 'Payment failed';
$pay_resp['message'] = $params['message'];
}
return $pay_resp;
}
Now when I try the endpoint in POSTMAN and send data I get the following response:
{ "result":"Payment failed", "message":null }
Which seems that no data is being sent to the endpoint. What can I do to fix it?

Laravel 7: Verify email using API endpoint + single page application

I have a NuxtJS/Vue SPA and I want to verify the user email with the Laravel API that's my server side.
I create a custom notification called VerifyEmail.php:
<?php
namespace App\Notifications;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Lang;
use Illuminate\Notifications\Notification;
class VerifyEmail extends Notification {
public function via($notifiable) {
return ['mail'];
}
public function toMail($notifiable) {
$params = [
'id' => $notifiable->getKey(),
'hash' => sha1($notifiable->getEmailForVerification()),
'expiry' => Carbon::now()->addMinutes(60)->timestamp
];
$url = config('app.web_client_url') . '/verify-email?';
foreach ($params as $key => $param) {
$url .= "{$key}={$param}&";
}
$key = config('app.key');
$signature = hash_hmac('sha256', $url, $key);
$url .= "signature=$signature";
return (new MailMessage)
->subject(Lang::get('Verify Email Address'))
->line(Lang::get('Please click the button below to verify your email address.'))
->action(Lang::get('Verify Email Address'), $url)
->line(Lang::get('If you did not create an account, no further action is required.'));
}
}
In my registration controller when a user registers I use:
...
$user->save();
$user->notify(new VerifyEmail());
return response()->json([
'message' => $user
], 201);
and the email gets sent. The URL in the email is something like: https://localhost:7000/verify-email?id=37&hash=4c1691e6db623b85d90cee62f80d6f9085648c92&expiry=1595596017&signature=d6c6374b203b1da66d11818728921a4160e30ebf43c5a8be544220c8eca97bb3 (localhost:7000 is the address of my NuxtJS application).
Upon going to that page, I make the following request in the mounted lifecycle method:
this.signature = this.$route.query.signature
this.expiry = this.$route.query.expiry
this.hash = this.$route.query.hash
this.id = this.$route.query.id
this.$axios.$get(`api/email/verify/${this.id}?hash=${this.hash}&expiry=${this.expiry}&signature=${this.signature}`)
.then(response => {
this.successMessage = response
}).catch(error => {
this.errorMessage = error
})
This request hits the endpoint on my server and the following method runs:
public function verify($user_id, Request $request) {
if (!$request->hasValidSignature()) { // Check always fails and we get a 401
return response()->json(["msg" => "Invalid URL provided."], 401);
}
$user = User::findOrFail($user_id);
if (!$user->hasVerifiedEmail()) {
$user->markEmailAsVerified();
}
return response()->json(["msg" => "Email verified."], 200);
}
The route for laravel endpoint:
Route::get('email/verify/{id}', 'Api\EmailVerificationController#verify')->name('verification.verify');
I can see that the parameters are received in the verify method request object parameter (e.g. setting a breakpoint and checking):
The check for a valid signature always fails and results in a 401 being sent back to the client. What's wrong with the URL/signature that I'm generating?
Here what I did to solve the problem. Go to AuthServiceProvider
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
//
VerifyEmail::createUrlUsing(function ($notifiable) {
$params = [
"expires" => Carbon::now()
->addMinutes(60)
->getTimestamp(),
"id" => $notifiable->getKey(),
"hash" => sha1($notifiable->getEmailForVerification()),
];
ksort($params);
// then create API url for verification. my API have `/api` prefix,
// so i don't want to show that url to users
$url = \URL::route("verification.verify", $params, true);
// get APP_KEY from config and create signature
$key = config("app.key");
$signature = hash_hmac("sha256", $url, $key);
// generate url for yous SPA page to send it to user
return env("APP_FRONT") .
"/auth/verify-email/" .
$params["id"] .
"/" .
$params["hash"] .
"?expires=" .
$params["expires"] .
"&signature=" .
$signature;
});
}
}
add this to api.php
Route::get("/verify-email/{id}/{hash}", [
VerifyEmailController::class,
"__invoke",
])
->middleware(["auth:sanctum","signed", "throttle:6,1"])
->name("verification.verify");
add this to VerifyEmailController.php
/**
* Mark the authenticated user's email address as verified.
*
* #param \Illuminate\Foundation\Auth\EmailVerificationRequest $request
* #return \Illuminate\Http\RedirectResponse
*/
public function __invoke(EmailVerificationRequest $request)
{
if ($request->user()->hasVerifiedEmail()) {
return response()->json(
[
"message" => "Your'r email already verified.",
],
Response::HTTP_BAD_REQUEST
);
}
if ($request->user()->markEmailAsVerified()) {
event(new Verified($request->user()));
}
return response()->json(
[
"message" => "Verification complete thank you.",
],
Response::HTTP_OK
);
}
}
Front end
async verfyEmail() {
try {
const params = new URLSearchParams(this.$route.query)
let res = await this.$axios.get(
'verify-email/' +
this.$route.params.id +
'/' +
this.$route.params.hash,
{ params }
)
this.$router.push({ name: 'platform-dashboard' })
} catch (error) {
console.log(error.response)
this.$router.push({ name: 'platform-dashboard' })
}
}

Wordpress custom endpoints (WP_REST_Controller) 404 only on mobile

I currently have a working controller that extends WP_REST_Controller in a file under the current theme. These are being called using jQuery ajax. (all code below)
The issue I am facing is that I receive this error ONLY when accessing with a mobile device.
{"code": "rest_no_route", "message": "No route was found matching the URL and request method" "data": {"status": 404}}
settings -> permalinks -> save changes
tried using controller namespace "api/v1" and "wp/v2"
javascript
function getAllClients() {
jQuery.ajax({
url: "http://myurl.com/index.php/wp-json/wp/v2/get_all_clients",
type: "GET",
data: { /*data object*/},
success: function (clientList) {
// success stuff here
},
error: function (jqXHR, textStatus, errorThrown) {
alert(jqXHR.statusText);
}
})
}
api/base.php
<?php
class ApiBaseController extends WP_REST_Controller
{
//The namespace and version for the REST SERVER
var $my_namespace = 'wp/v';
var $my_version = '2';
public function register_routes()
{
$namespace = $this->my_namespace . $this->my_version;
register_rest_route(
$namespace,
'/get_all_clients',
array(
array(
'methods' => 'GET',
'callback' => array(new ApiDefaultController('getAllClients'), 'init'),
)
)
);
$ApiBaseController = new ApiBaseController();
$ApiBaseController->hook_rest_server();
api/func.php
<?php
class ApiDefaultController extends ApiBaseController
{
public $method;
public $response;
public function __construct($method)
{
$this->method = $method;
$this->response = array(
// 'Status' => false,
// 'StatusCode' => 0,
// 'StatusMessage' => 'Default'
// );
}
private $status_codes = array(
'success' => true,
'failure' => 0,
'missing_param' => 150,
);
public function init(WP_REST_Request $request)
{
try {
if (!method_exists($this, $this->method)) {
throw new Exception('No method exists', 500);
}
$data = $this->{$this->method}($request);
$this->response['Status'] = $this->status_codes['success'];
$this->response['StatusMessage'] = 'success';
$this->response['Data'] = $data;
} catch (Exception $e) {
$this->response['Status'] = false;
$this->response['StatusCode'] = $e->getCode();
$this->response['StatusMessage'] = $e->getMessage();
}
return $this->response['Data'];
}
public function getAllClients()
{
// db calls here
return json_encode($stringArr,true);
}
}
These are registered in the Functions.php file
require get_parent_theme_file_path('api/base.php');
require get_parent_theme_file_path('api/func.php');
Turns out the issue was a plugin my client installed called "oBox mobile framework" that was doing some weird routing behind the scenes. Disabling it resolved the issue, though there is probably a way to hack around this and get both to play together.

paypal success url error laravel

I'm using laravel Omni plugin for transactions. Once payment has been done , I'm getting error for success url.
public function checkOut(Request $request)
{
$params = array(
'cancelUrl' => 'http://localhost/vis/public/cancel_order',
'returnUrl' => 'http://localhost/vis/public/payment_success',
'name' => 'Meal',
'description' => 'Casper',
'amount' => '1.00',
'currency' => 'USD'
);
Session::put('params', $params);
Session::save();
$gateway = Omnipay::create('PayPal_Express');
$gateway->setUsername('un');
$gateway->setPassword('pwd');
$gateway->setSignature('signature');
$gateway->setTestMode(true);
$response = $gateway->purchase($params)->send();
if ($response->isSuccessful()) {
print_r($params);
redirect('payment_success/' . $this->orderNo);
// payment was successful: update database
print_r($response);
} elseif ($response->isRedirect()) {
// redirect to offsite payment gateway
$response->redirect();
} else {
// payment failed: display message to customer
echo $response->getMessage();
}
}
public function getSuccessPayment()
{
$gateway = Omnipay::create('PayPal_Express');
$gateway->setUsername('un');
$gateway->setPassword('pwd');
$gateway->setSignature('signature');
$gateway->setTestMode(true);
$params = Session::get('params');
$response = $gateway->completePurchase($params)->send();
$paypalResponse = $response->getData(); // this is the raw response object
if(isset($paypalResponse['PAYMENTINFO_0_ACK']) && $paypalResponse['PAYMENTINFO_0_ACK'] === 'Success') {
// Response
print_r($params);
// print_r($paypalResponse);
} else {
//Failed transaction
}
// return View('result');
print_r($params);
print_r($paypalResponse);
}
I'm getting following error
Not Found
HTTP Error 404. The requested resource is not found.
http://localhost/vis/public/payment_success?token=EC-1R845179Asss493N&PayerID=swdw3BS9REA4AN
It looks like you may have forgotten to add that route in the routes.php, Make sure you have something like this in routes.php
Route::get('/payment_success', 'StoreController#getSuccessPayment');
Change StoreController to the name of the controller this function is in.

Categories