【问题标题】:ExpressJS showing empty req.body object on POST request, but not with Insomnia or cURLExpressJS 在 POST 请求中显示空的 req.body 对象,但不包括 Insomnia 或 cURL
【发布时间】:2021-11-16 01:20:55
【问题描述】:

我正在尝试在我的 MERN 网站中加入一个全球支付网关(GPG 结账)。

支付过程完成后,GPG 服务器应该使用 cURL 向我发送一个 post 请求到我在 GPG 仪表板中设置的路由。这个post请求的内容是:PayAmount, PAYID, TransStatus, Signature。

这是我的路线:

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

我正在显示我在该路线上获得的所有 POST 字段。

当我在笔记本电脑上使用 insomnia 或 cURL 进行测试时,它显示了我在服务器日志中发送的数据,但是当我完成付款过程时它显示为空对象(这意味着 GPG 结帐服务器知道我的通知 URL并发送一个 POST 请求,但它仍然显示为空)。

我打电话给支持团队,他们给我发了一个通知页面的 PHP 示例:

<?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;
    }
    
}
?>

据我所知,这只是一个简单的 POST 请求!为什么我的服务器显示空对象?虽然当我用随机字段测试失眠或 cURL 时它工作正常。

这是我的 app.js 文件内容:

//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;

有人知道这个问题吗?

编辑: 我确实在我的服务器上创建了一个 php 文件来接收数据而不是节点应用程序,并且它确实通过使用 $_POST["field_name"] 来工作,所以我对此感到非常困惑!

【问题讨论】:

    标签: node.js express curl post


    【解决方案1】:

    在从您的 php 脚本发送请求时设置您的内容类型标头。这里 CURL ( curl 可能会给你输出但格式错误),邮递员默认为你做。这里服务器需要知道您在请求中发送的数据类型,因此它可以使用适当的方法来获取该编码数据。即 json、xml、x-www-form-urlencoded 和 multipart 等

    这可以通过在请求中设置 Content-Type 标头来完成

    这样设置Content-Type : application/json(for json data) or xml (for xml data) or x-www-form-urlencoded

    $_POST 使用 application/x-www-form-urlencoded 或 multipart/form-data 作为请求中的 HTTP Content-Type。 通过包含此echo $_SERVER["CONTENT_TYPE"]; 在您的PHP 脚本中运行检查,并且可能的输出可能是multipart/form-data,因为application/x-www-form-urlencoded 已经在您的节点服务器中被解析。 用于解析multipart/form-data 安装npm multer 中间件包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;
    

    【讨论】:

    • 我在测试 api 时确实接收数据(json 或 urlencoded 都在工作)。但是当 GPG 结帐服务器发送请求时,我只接收到空对象。
    • 我认为问题在于Content-type。尝试将其解析为 xml,因为大多数银行和金融 API 都以 application/xml or text/xml 格式发送和接收数据。 https://www.npmjs.com/package/body-parser-xml 看看这个。
    • 我确实在我的服务器上创建了一个 php 文件来接收数据而不是节点应用程序,并且它只使用 $_POST["field_name"] 就可以工作,所以我真的很困惑!
    • 可能已经找到解决方案,$_POST 默认使用application/x-www-form-urlencoded or multipart/form-data签出编辑后的答案
    【解决方案2】:

    我想我发现了问题。

    支付网关服务器正在使用 php cURL,它在向 Node/express Js 应用程序发布数据时似乎不太顺利。

    所以我没有办法修复它,因为这是他们的服务器错误。

    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

    我将报告此问题。但是现在,我要使用这个 php 脚本,因为我需要完成这项工作!

    <?php
    /*
        
       
        Author : Rouissi Iheb ( rouissi2017@gmail.com ) 
        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');
    }
    ?>
    

    关于我需要提供接收数据的通知链接,我必须在我的服务器上安装 php,使用 ssl 创建一个新的子域并将此配置添加到我的 nginx 配置中:

    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;
            }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-03-08
      • 1970-01-01
      • 1970-01-01
      • 2016-11-20
      • 2021-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-28
      相关资源
      最近更新 更多