Paypal SandBox IPN总是返回INVALID



正如下面答案中的一条评论中所提到的,我尝试遵循本教程。所以现在我有了以下内容:


ipn.php文件:

<?php
    $ipn_post_data = $_POST;
    $url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
    // Set up request to PayPal
    $request = curl_init();
    curl_setopt_array($request, array
    (
        CURLOPT_URL => $url,
        CURLOPT_POST => TRUE,
        CURLOPT_POSTFIELDS => http_build_query(array('cmd' => '_notify-validate') + $ipn_post_data),
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_HEADER => FALSE,
        CURLOPT_SSL_VERIFYPEER => TRUE,
        CURLOPT_CAINFO => 'cacert.pem',
    ));
    // Execute request and get response and status code
    $response = curl_exec($request);
    $status   = curl_getinfo($request, CURLINFO_HTTP_CODE);
    // Close connection
    curl_close($request);
    if($status == 200 && $response == 'VERIFIED')
    {
        $subject = "valid";
        $message = "good";
    }
    else
    {
        $subject = "invalid";
        $message = "bad";
    }
    $to = "oshirowanen@mail.com";
    $from = "me@desktop.com";
    $header  = 'MIME-Version: 1.0' . "rn";
    $header .= 'Content-type: text/html; charset=iso-8859-1' . "rn";
    $header .= 'To: Oshirowanen <oshirowanen@mail.com>' . "rn";
    $header .= 'From: Me <me@desktop.com>' . "rn";
    mail($to,$subject,$message,$header);
?>

收到的电子邮件:

Subject "invalid"
Message "bad"

编辑:

现在我可以看到您输出的数组了,请尝试替换它以消除PHP数组错误:

foreach ($_POST as $key => $value) {
    if (!is_array($value)) {
        $value = urlencode(stripslashes($value));
        $req .= "&$key=$value";
    }
    else if (is_array($value)) {
        $paymentArray = explode(' ', $value[0]);
        $paymentCurrency = urlencode(stripslashes($paymentArray[0]));
        $paymentGross = urlencode(stripslashes($paymentArray[1]));
        $req .= '&mc_currency=' . $paymentCurrency . '&mc_gross=' . $paymentGross;
    }
}

以下是经过编辑的完整代码:

// read the post from PayPal system and add 'cmd'
$req = 'cmd=' . urlencode('_notify-validate');
foreach ($_POST as $key => $value) {
    if (!is_array($value)) {
        $value = urlencode(stripslashes($value));
        $req .= "&$key=$value";
    }
    else if (is_array($value)) {
        $paymentArray = explode(' ', $value[0]);
        $paymentCurrency = urlencode(stripslashes($paymentArray[0]);
        $paymentGross = urlencode(stripslashes($paymentArray[1]);
        $req .= '&mc_currency=' . $paymentCurrency . '&mc_gross=' . $paymentGross;
    }
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Host: www.paypal.com'));
$res = curl_exec($ch);
curl_close($ch);

// assign posted variables to local variables
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];

if (strcmp ($res, "VERIFIED") == 0) {
    // check the payment_status is Completed
    // check that txn_id has not been previously processed
    // check that receiver_email is your Primary PayPal email
    // check that payment_amount/payment_currency are correct
    // process payment
}
else if (strcmp ($res, "INVALID") == 0) {
    // log for manual investigation
}

看看这个!

编辑:查看PayPal故障排除提示:

https://cms.paypal.com/us/cgi-bin/?cmd=_render-内容&content_ID=developer/e_howto_admin_IPNTesting

问题是您没有检查HTTP响应代码,所以您将"无效主机头"集成为PayPal响应,而它是web服务器响应(状态代码400)
如果你看一下PayPal文档,有一个PHP示例与你的代码非常相似,因为它使用"fsockopen"、"fputs"one_answers"fgets"函数与PayPal服务器通信
但如果你仔细看"fsockopen"呼叫后的备注,你可以读到:

// Process validation from PayPal 
// TODO: This sample does not test the HTTP response code. All 
// HTTP response codes must be handled or you should use an HTTP 
// library, such as cUrl

这正是你的问题:在解析响应主体之前,你没有检查HTTP响应代码是否为200(OK)
此外,使用"strtolower"函数是不正确的,因为PayPal服务器的实际响应总是大写的,如上面引用的示例所示
即使PayPal示例使用"fsockopen"方法,我认为使用PHP cURL库来实现IPN侦听器应该要好得多
还可以看看以下答案:

  • PHP cURL PayPal沙盒
  • cURL或fsockopen for paypal ipn

但是,如果您真的想使用"fsockopen"函数,您应该始终在POST请求中指定"Host"头字段,如以下代码片段所示(取自PHP手册):

<?php
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp) {
    echo "$errstr ($errno)<br />n";
} else {
    $out = "GET / HTTP/1.1rn";
    $out .= "Host: www.example.comrn";
    $out .= "Connection: Closernrn";
    fwrite($fp, $out);
    while (!feof($fp)) {
        echo fgets($fp, 128);
    }
    fclose($fp);
}
?>

更新

这里有一个用于递归条带斜杠/urlencoding的简单函数:

<html>
<body>
<pre>
<?
$post = Array (
  "transaction" => Array("USD 20.00"),
  "payment_request_date" => "Sun Aug '05 08:49:20 PDT 2012",
  "return_url" => "http://000.000.000.000/success.php"
);
echo "before myUrlencode...n";
print_r($post);
function myUrlencode($post) {
  foreach ($post as $key => $val) {
    if (is_array($val)) {
      $post[$key] = myUrlencode($val);
    } else {
      $post[$key] = urlencode(stripslashes($val));
    }
  }
  return($post);
}
echo "nafter myUrlencode...n";
print_r(myUrlencode($post));
?>
</pre>
</body>
</html>
  1. 使用基本样本代码4b,使其工作

  2. 从基本样本代码中清除了$ipnNotificationUrl = "";,因为我在其中添加了一个值,

  3. 创建了一个卖家帐户,而不是沙盒中的商业专业帐户,

  4. 设置卖家帐户以启用ipn url、

  5. 为ipn侦听器使用了以下PHP 5.2示例代码

  6. 将2行添加到侦听器中,如上所述,这2行可以在下面看到:

  7. 从这里下载了cacert.pem证书到我的服务器,并将其放在与ipn侦听器相同的目录中:

第6点中提到的2行:

CURLOPT_SSL_VERIFYPEER => TRUE,
CURLOPT_CAINFO => 'cacert.pem',

我不知道为什么沙盒商业专业账户不允许我设置ipn url,但卖家账户允许。

这些链接可以解决您的问题,

Paypal:无效的IPN问题

http://www.webmasterworld.com/ecommerce/4292847.htm

Paypal沙盒IPN返回无效

我不确定你的代码现在到底出了什么问题,但我不久前也在努力,我的修复方法是在标头中添加HOST,主机必须是www.Paypal.com。我使用了fsockopen方法,现在工作正常。

在Curl中,我以前遇到过ssl问题。解决方案是把这些线:

curl_setopt($curl, CURLOPT_COOKIEJAR, dirname(__FILE__) . "/cookies.txt");
curl_setopt($curl, CURLOPT_COOKIEFILE, dirname(__FILE__) . "/cookies.txt");

当然文件cookies.txt必须存在。更重要的是,我必须运行一个到页面的连接来获取会话数据,然后发送帖子数据。

以下是fsockopen方法对我来说很好的标题

$header = "POST /cgi-bin/webscr HTTP/1.0rn";
$header .= "Host: www.paypal.comrn";
$header .= "Content-Type: application/x-www-form-urlencodedrn";
$header .= "Content-Length: " . strlen($req) . "rnrn";

这是一个+字符的问题,它经常被错误地提取,所以我做了这个变通方法,它对我有效。

payment_data=2016年6月4日星期六15:11:16 GMT+0200(CEST)

foreach ($_POST as $key => $value) {
if($key !== "payment_date"){
    $req .= '&' . $key . '=' . rawurlencode(html_entity_decode($value, ENT_QUOTES, 'UTF-8'));
}else{
    $req .= '&' . $key . '=' . rawurlencode(str_replace(array('GMT '),array('GMT+'),$value));
}}

以下是如何避免这些错误。。。

foreach ($_POST as $key => $value) {
     if ($key=='transaction')
          foreach ($value as $key2=>$value2) {
               $value['transaction'][$key2] = urlencode(stripslashes($value2));
     }
     else {
          $value = urlencode(stripslashes($value));
     }
     $req .= "&$key=$value";
 }

几个小时的头发拉扯,直到我看到Izudin的答案。他是对的。。日期中的+未被转移。为了测试,我从模拟器中预先填充的字段中删除了它,最后得到了一个Verified

我终于找到了这个查询的最新(2016年8月5日)工作答案。您可以使用此代码作为Sandbox或Live的最终IPN。考虑以下因素:

  1. 请务必将您的IPN侦听器放置到->我的销售工具->即时支付通知部分
  2. 不要在沙箱中使用IPN模拟器,它将始终返回INVALID
  3. 创建并使用一个实际的沙盒按钮,但不要把你的IPN监听器放在RETURN PAGE上,上面写着"当客户完成结账时,把他们带到这个URL"

仅此而已。我希望这会有所帮助。

这是工作代码:

<?php
$post_data = file_get_contents('php://input');
$post_array = explode('&', $post_data);
$dataFromPayPal = array();
foreach ($post_array as $keyval) {
    $keyval = explode ('=', $keyval);
    if (count($keyval) == 2)
        $dataFromPayPal[$keyval[0]] = urldecode($keyval[1]);
}
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
    $get_magic_quotes_exists = true;
}
foreach ($dataFromPayPal as $key => $value) {
    if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
        $value = urlencode(stripslashes($value));
    } else {
        $value = urlencode($value);
    }
    $req .= "&$key=$value";
}
$ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');
//use https://www.sandbox.paypal.com/cgi-bin/webscr in case you are testing this on a PayPal Sanbox environment
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
if( !($res = curl_exec($ch)) ) {
    curl_close($ch);
    exit;
}
curl_close($ch);

if (strcmp ($res, "INVALID") == 0) {
        echo "INVALID";
}
else if (strcmp ($res, "VERIFIED") == 0) {
        echo "VALID";
}
?>

相关内容

  • 没有找到相关文章

最新更新