【问题标题】:nodejs paypal ipn keeps invalidnodejs paypal ipn保持无效
【发布时间】:2016-03-18 23:16:58
【问题描述】:

我知道这已经讨论过好几次了——尽管研究了每一个线程,但我无法让它运行。在放弃之前,我想最后一次尝试:

我的环境是带有 express 和 bodyparser 的最新 nodejs。我开发了我的应用程序并尝试实现一个简单的 Paypal Express 结帐。我使用了 paypal-ipn,但无法从 Paypal 获得 VALID 响应。我玩弄了我认为是问题的东西(为贝宝回调实现了一个原始正文解析器,使用编码和标题选项,将贝宝帐户中的设置从 windows 切换为 utf8 编码)但你可能已经知道,没有任何效果.所以我决定离开我的应用程序并从头开始进行简单的新设置。我使用了在网上找到的另一种方法,但最终还是出现了同样的错误。然后我决定“上线”,因为有时据报道,沙盒总是返回无效。那次尝试花了我 50 美分的交易费......并且无效:-)

让我感到困惑的是,我发现的大多数讨论都是几年前的。由于我使用了 2 段不同的代码(它们都是并且仍然是)报告为有效,我认为假设这不是编程逻辑中的一般错误是公平的。 Paypal API 可能发生了变化,或者更新的 nodejs 包破坏了某些东西。所以,如果你们中的任何人能指出我正确的方向......

这是我当前的代码。我在其中留下了一些 bodyparser 替代方案,只是为了将其投入讨论。再说一次,我不想用借来的羽毛装饰自己。大部分代码都是来自网络的sn-ps:

var express = require('express');
var querystring = require('querystring');
var request = require('request');
var colors = require('colors');
var bodyParser = require('body-parser');
var StringDecoder = require('string_decoder').StringDecoder;


colors.setTheme({
    silly: 'rainbow',
    input: 'grey',
    verbose: 'cyan',
    prompt: 'grey',
    info: 'green',
    data: 'grey',
    help: 'cyan',
    warn: 'yellow',
    debug: 'blue',
    error: 'red'
});

var app = express();
var bpJSON = bodyParser.json();
var bpUrl = bodyParser.urlencoded({
    extended: false
});

var parseRaw = function (req, res, next) {
    req.body = '';
    var helper = '';
    req.setEncoding('utf8');
    var decoder = new StringDecoder('utf8');

    req.on('data', function (chunk) {
        req.body += decoder.write(chunk);
        console.log(req.body);
    });

    req.on('end', function () {
        next();
    });
};

app.use(function (req, res, next) {
    if (!~req.url.indexOf('/notipal')) bpJSON(req, res, next)
    else return next();
});

app.use(function (req, res, next) {
    if (!~req.url.indexOf('/notipal')) bpUrl(req, res, next)
    else return next();
});

app.use(function (req, res, next) {
    if (~req.url.indexOf('/notipal')) parseRaw(req, res, next)
    else return next();
});

app.get('/', function (req, res) {
    res.end('Response will be available on console, nothing to look here!');
});

app.post('/notipal', function (req, res) {
    console.log('Received POST /'.bold);
    console.log(req.body);
    logger.log(req.body);
    console.log('\n\n');

    // STEP 1: read POST data
    req.body = req.body || {};
    res.send('200');
    res.end();

    // read the IPN message sent from PayPal and prepend 'cmd=_notify-validate'
    var postreq = 'cmd=_notify-validate';
    for (var key in req.body) {
        if (req.body.hasOwnProperty(key)) {
            var value = querystring.escape(req.body[key]);
            postreq = postreq + "&" + key + "=" + value;
            console.log('key: ' + key + ' value: ' + value);
        }
    }

    // Step 2: POST IPN data back to PayPal to validate
    console.log('Posting back to paypal'.bold);
    console.log(postreq);
    console.log('\n\n');
    var options = {
        url: 'https://www.sandbox.paypal.com/cgi-bin/webscr',
        method: 'POST',
        headers: {
            'Connection': 'close'
        },
        body: postreq,
        strictSSL: true,
        rejectUnauthorized: false,
        requestCert: true,
        agent: false
    };

    request(options, function callback(error, response, body) {
        if (!error && response.statusCode === 200) {

            // inspect IPN validation result and act accordingly

            if (body.substring(0, 8) === 'VERIFIED') {
                // The IPN is verified, process it
                console.log('Verified IPN!'.green);
                console.log('\n\n');

                // assign posted variables to local variables
                var item_name = req.body['item_name'];
                var item_number = req.body['item_number'];
                var payment_status = req.body['payment_status'];
                var payment_amount = req.body['mc_gross'];
                var payment_currency = req.body['mc_currency'];
                var txn_id = req.body['txn_id'];
                var receiver_email = req.body['receiver_email'];
                var payer_email = req.body['payer_email'];

                //Lets check a variable
                console.log("Checking variable".bold);
                console.log("payment_status:", payment_status)
                console.log('\n\n');

                // IPN message values depend upon the type of notification sent.
                // To loop through the &_POST array and print the NV pairs to the screen:
                console.log('Printing all key-value pairs...'.bold)
                for (var key in req.body) {
                    if (req.body.hasOwnProperty(key)) {
                        var value = req.body[key];
                        console.log(key + "=" + value);
                    }
                }

            } else if (body.substring(0, 7) === 'INVALID') {
                // IPN invalid, log for manual investigation
                console.log('Invalid IPN!'.error);
                console.log('\n\n');
                console.log(body);
            }
        }
    });

});

var port = 80;
app.listen(port);
var msg = 'Listening at http://localhost:' + port;
console.log(msg.green.bold);

控制台日志显示接收和发送的两个相同的正文。

有什么想法吗?

非常感谢。

一天后编辑: 事情变得越来越好奇。为了进一步调查,我使用在 Github 上发布的 Paypals 自己的 php 示例设置了一个 wamp 环境。我该怎么说:无效。这让我抓狂...

【问题讨论】:

  • 我目前遇到了完全相同的问题。也无法得到下面的答案。你最后碰巧解决了这个问题吗?

标签: node.js express paypal-ipn paypal-sandbox


【解决方案1】:

这是我的代码。我有一些随机的无效答案,这些也让我发疯。问题是,我们有一个西班牙语界面,有时来自 PAYPAL 的调用包含特殊字符,但那些已经被转义了……我们再次转义了它们。因此,我们在向 paypal 发送帖子请求时删除了“querystring.escape”;这解决了我们的问题。

这是代码:

function processNotify(req, res) {

    console.log('Receiving call in /paypal/notify as POST. Dumping req.body...');
    console.log(JSON.stringify(req.body));

    // STEP 1: Read the IPN message sent from PayPal and prepend 'cmd=_notify-validate'
    var postreq = 'cmd=_notify-validate';
    for (var key in req.body) {
        if (req.body.hasOwnProperty(key)) {
            // postreq = postreq + "&" + key + "=" + querystring.escape(req.body[key]);
            postreq = postreq + "&" + key + "=" + req.body[key];
        }
    }

    // Step 2: POST IPN data back to PayPal to validate
    console.log('Posting back to paypal');

    config.paypal.verifyOptions.body = postreq;
    request(config.paypal.verifyOptions, function callback(error, response, body) {

        if (!error && response.statusCode !== 200) {
            console.log('Error: Response status code !== 200, it is:' + response.statusCode());
            return;
        }

        if (body.substring(0, 8) === 'VERIFIED') {

【讨论】:

  • 所以唯一的问题是带有特殊字符的参数来自贝宝回调。谢谢大佬!
猜你喜欢
  • 2017-02-09
  • 2023-04-09
  • 2011-10-26
  • 2014-02-23
  • 2013-09-20
  • 2018-10-29
  • 2016-06-26
  • 2017-02-17
相关资源
最近更新 更多