nodejs paypal ipn保持无效

时间:2016-03-18 23:16:59

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

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

我的环境是使用express和bodyparser的最新nodejs。我开发了我的应用程序并尝试实现简单的Paypal Express结账。我使用了paypal-ipn,但无法从Paypal获得有效的回复。我玩了我认为的问题(实现了一个原始的解析器,仅用于paypal回调,使用编码和标题选项,在paypal帐户中从windows转换为utf8编码)但你可能已经知道,没有任何工作。所以我决定离开我的应用程序并从头开始使用简单而简单的新设置。我在网上使用了一种不同的方法,最后又出现了同样的错误。然后我决定去"生活"有时会报告,沙箱总是返回无效。那次尝试花了我50美元的交易费......并保持无效: - )

让我感到困惑的是,我发现的大部分讨论都是几年之久。由于我使用了2个不同的代码片段(它们都已经存在并且仍然存在),因此我认为将其视为编程逻辑中的一般错误是公平的。 Paypal API或更新的nodejs软件包可能已经发生了变化。所以,如果你们中的任何一个人能指出我正确的方向......

这是我目前的代码。我在其中留下了一些bodyparser替代品,只是为了将其投入讨论。而且,我并不想用借来的羽毛来装饰自己。大部分代码都是来自网络的片段:

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环境。我应该说什么:无效。这让我发疯了......

1 个答案:

答案 0 :(得分:0)

这是我的代码。我有一些随机的无效答案,那些也让我发疯。问题是,我们有一个西班牙语界面,有时来自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') {