I am tryin to include a global payment gateway (GPG checkout) to my MERN website.
After the payment process is done, the GPG server should send me a post request using cURL to a route I set in the GPG dashboard. The content of this post request is: PayAmount, PAYID, TransStatus, Signature.
This is my route:
router.route('/confirm-payment-detailes').post(async (req,res)=>{
//const {TotalAmount,PAYID,TransStatus,Signature} = req.body;
//console.log({TotalAmount,PAYID,TransStatus,Signature});
// show any post request content to this route
console.log(req.body)
});
I am showing all POST fields I get on that route.
When I test using insomnia or cURL on my laptop, it shows me the data that I did send in server log, But it shows empty object when I complete the payment process (which means that the GPG checkout server knows my notification URL and sends a POST request but it shows empty anyway).
I called support team and they send me a PHP example of notification page:
<?php
$url = (!empty($_SERVER['HTTPS'])) ? "https://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] : "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
$url = $_SERVER['REQUEST_URI'];
$my_url = explode('wp-content' , $url);
$path = $_SERVER['DOCUMENT_ROOT']."/".$my_url[0];
$PayAmount = $_POST['TotalAmount'];
$PAYID = $_POST['PAYID'];
$TransStatus = $_POST['TransStatus'];
$Signature = $_POST['Signature'];
include_once $path . '/wp-config.php';
include_once $path . '/wp-includes/wp-db.php';
include_once $path . '/wp-includes/pluggable.php';
$sign = sha1( $_POST['TransStatus']. $PAYID . "XXXXXXX" );
if($Signature == $sign){
$order = wc_get_order( $PAYID );
switch ( $TransStatus ) {
case '05' : // refus
$order->update_status( 'wc-failed', $reason );
break;
case '00' : // accord
$order->update_status( 'wc-processing', $reason );
WC()->cart->empty_cart();
break;
case '06' : //annuler
$order->update_status( 'wc-cancelled', $reason );
break;
case '07' : // rembourser
$order->update_status( 'wc-refunded', $reason );
break;
case '08' : // Charge back
default :
break;
}
}
?>
As far as I know, it's just a simple POST request! Why is my server showing empty object? While it works fine when I test with insomnia or cURL with random fields.
This is my app.js file content:
//imports Here :
const express = require('express');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const mongoStore = require('connect-mongo');
//declare app here :
const app = express();
app.disable('x-powered-by');
app.set('view engine','ejs');
app.set('views','Views');
app.use(express.static(__dirname '/Public'));
app.use(cookieParser());
app.use(express.json());
app.use(express.urlencoded({extended:false}));
app.use(cors());
//Clients API Routes :
app.use(process.env.CLIENT_API_PATH,require('./Routes/clientAPIRoutes'));
//Admin Pages Routes :
app.use(process.env.ADMIN_PATH,require('./Routes/adminPageRoutes'));
module.exports = app;
Does anyone have any idea about this problem?
Edit : I did create a php file on my server to recive the data instead of the node app , and it did work by just using $_POST["field_name"] , so am really confused about that !
CodePudding user response:
set your content type header while sending a request from your php script. here CURL ( curl may give you output but in wrong format), postman does that for you by default. here server needs to know what type of data you are sending in a request, so it can use appropriate methods to fetch that encoded data. i.e json, xml,x-www-form-urlencoded and multipart etc
that can be done by setting Content-Type header in the request
set it like this Content-Type : application/json(for json data) or xml (for xml data) or x-www-form-urlencoded
$_POST uses application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request.
run a check in your PHP script by including this echo $_SERVER["CONTENT_TYPE"];
and possible output might be multipart/form-data
on the basis of application/x-www-form-urlencoded
is already getting parsed in your node server.
for parsing multipart/form-data
install npm multer middleware package npm install multer
.
//imports Here :
const express = require('express');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const mongoStore = require('connect-mongo');
const multer= require('multer');
//declare app here :
const app = express();
app.disable('x-powered-by');
app.set('view engine','ejs');
app.set('views','Views');
app.use(express.static(__dirname '/Public'));
app.use(cookieParser());
app.use(express.json());
app.use(express.urlencoded({extended:false}));
app.use(multer().array()) // parses multipart/form-data
app.use(cors());
//Clients API Routes :
app.use(process.env.CLIENT_API_PATH,require('./Routes/clientAPIRoutes'));
//Admin Pages Routes :
app.use(process.env.ADMIN_PATH,require('./Routes/adminPageRoutes'));
module.exports = app;
CodePudding user response:
I think i found out the problem.
The payment gateway server is using php cURL wich it seems to be not going well wen posting data to Node/express Js apps.
So i have no way to fix it since it's their server error .
Made PHP curl POST to nodeJS API but can't read response data
PHP cURL request body is undefined in node.js
Node js can not read the data from curl request via php
Am going to report this issue. But for now , am going with this php script since i need the job done !
<?php
/*
Author : Rouissi Iheb ( [email protected] )
Date : 27/09/2021
stackoverflow qustion : https://stackoverflow.com/questions/69286519/expressjs-showing-empty-req-body-object-on-post-request-but-not-with-insomnia-o/
This script is used to redirect the POST payment detailes recived from GPG checkout servers to the E-commerce Node/expressJs server
reason :
https://stackoverflow.com/questions/54385528/made-php-curl-post-to-nodejs-api-but-cant-read-response-data
https://stackoverflow.com/questions/35162073/php-curl-request-body-is-undefined-in-node-js
https://stackoverflow.com/questions/63463873/node-js-can-not-read-the-data-from-curl-request-via-php
*/
function execInBackground($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd . " > /dev/null &");
}
}
if(isset($_POST['TotalAmount']) && isset($_POST['PAYID']) && isset($_POST['TransStatus']) && isset($_POST['Signature'])){
//for test only TO REMOVE ON PRODUCTION !!
//-----------------------------
$content = "New Post Request from : ".$_SERVER['REMOTE_ADDR']." \n";
$myfile = fopen("log.txt", "a") or die("Unable to open file!");
fwrite($myfile, $content);
fclose($myfile);
//------------------------------
$data = "TotalAmount=".$_POST['TotalAmount']."&PAYID=".$_POST['PAYID']."&TransStatus=".$_POST['TransStatus']."&Signature=".$_POST['Signature'];
execInBackground('curl -X POST -d "'.$data.'" http://nodeserver:nodeport/some-route');
}
?>
About the notification link that i need to provide to recive the data on it , i had to install php on my server , create a new subdomain with ssl and added this configurations to my nginx config :
server{
listen 80;
server_name gpg-gateway.mywebsite.com;
root /home/user/php-proxy;
index index.php;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
}
}