
本文档旨在帮助开发者解决在使用 PHP 验证 PayPal IPN (Instant Payment Notification) 时遇到的 “Access Denied” 错误。通过详细的代码分析和配置调整,我们将指导你如何正确配置 cURL 请求头,从而成功验证 IPN 信息,确保交易的可靠性和安全性。
问题分析
在使用 PHP 脚本验证 PayPal IPN 时,出现 “Access Denied” 错误通常是由于服务器拒绝了你的请求。这可能是因为 PayPal 服务器需要特定的请求头信息才能正确处理你的请求。常见的解决方法是修改 cURL 请求头,添加 User-Agent 字段。
解决方案
以下是修改后的 PHP 代码示例,重点在于 CURLOPT_HTTPHEADER 的配置:
$raw_post_array = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_array);
$myPost = array();
foreach ($raw_post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2)
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
// read the IPN message sent from PayPal and prepend 'cmd=_notify-validate'
$req = 'cmd=_notify-validate';
if (function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($myPost 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";
}
// Step 2: POST IPN data back to PayPal to validate
//Operacion: https://ipnpb.paypal.com/cgi-bin/webscr
//Sandbox: https://ipnpb.sandbox.paypal.com/cgi-bin/webscr
$ch = curl_init('https://ipnpb.sandbox.paypal.com/cgi-bin/webscr');
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_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
// 修改 CURLOPT_HTTPHEADER 添加 User-Agent
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close', 'User-Agent: YourCompanyName'));
// In wamp-like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "https://curl.haxx.se/docs/caextract.html" and set
// the directory path of the certificate as shown below:
// curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
if ( !($res = curl_exec($ch)) ) {
// error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
exit;
}
curl_close($ch);
// inspect IPN validation result and act accordingly
if (strcmp ($res, "VERIFIED") == 0) {
// The IPN is verified, process it:
// check whether 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 the notification
// 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'];
$header = "From: <a class=/"__cf_email__/" data-cfemail=/"137a7d757c537e7c7d76616a3d707c7e/" href=/"/cdn-cgi/l/email-protection/">[email protected]</a>/nReply-To:".$payer_email."/n";
$mensaje = "Se recibio " . $item_name . ", status fue: " . $payment_status . ", el recibidor fue: " . $receiver_email . ", el pagador fue: " . $payer_email . ". Se cobro $" . $payment_amount;
mail('<a class="__cf_email__" data-cfemail="e18c8e8f849398d3d1a1868c80888dcf828e8c" href="/cdn-cgi/l/email-protection/">[email protected]</a>',$item_name, $mensaje, $header);
// IPN message values depend upon the type of notification sent.
// To loop through the &_POST array and print the NV pairs to the screen:
foreach($_POST as $key => $value) {
echo $key . " = " . $value . "<br>";
}
} else{
// IPN invalid, log for manual investigation
$payer = '<a class="__cf_email__" data-cfemail="e78a888982959ed5d7a7808a868e8bc984888a" href="/cdn-cgi/l/email-protection/">[email protected]</a>';
$item_name = 'Ha fallado';
echo "The response from IPN was: <b>" .$res ."</b>";
$header = "From: <a class=/"__cf_email__/" data-cfemail=/"e0898e868fa08d8f8e859299ce838f8d/" href=/"/cdn-cgi/l/email-protection/">[email protected]</a>/nReply-To:".$payer."/n";
$mensaje = "Fue invalido, recibiste " . $res;
mail('<a class="__cf_email__" data-cfemail="cba6a4a5aeb9b2f9fb8baca6aaa2a7e5a8a4a6" href="/cdn-cgi/l/email-protection/">[email protected]</a>',$item_name, $mensaje, $header);
}
登录后复制
关键代码解释:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close', 'User-Agent: YourCompanyName'));
登录后复制
- User-Agent: YourCompanyName:这行代码设置了 User-Agent 请求头。将 YourCompanyName 替换为你公司的名称或其他标识符。
其他注意事项
- SSL 证书验证: 在生产环境中,确保 CURLOPT_SSL_VERIFYPEER 设置为 true,并配置正确的 CA 证书。在开发环境中,如果遇到 SSL 证书问题,可以暂时设置为 false,但强烈建议在生产环境中不要这样做。
- Sandbox 环境: 在测试阶段,请使用 PayPal Sandbox 环境(https://ipnpb.sandbox.paypal.com/cgi-bin/webscr)。
- 错误日志: 在代码中添加详细的错误日志,以便在出现问题时进行调试。
- IPN 监听器 URL: 确保你的 IPN 监听器 URL 在 PayPal 账户中正确配置。
- 数据验证: 在处理 IPN 数据时,务必进行严格的验证,包括支付状态、交易 ID、接收者邮箱、支付金额和货币等。
总结
通过正确配置 cURL 请求头,特别是添加 User-Agent 字段,可以有效解决 PayPal IPN 验证中的 “Access Denied” 问题。同时,注意 SSL 证书验证、Sandbox 环境的使用以及数据验证,可以确保 IPN 验证的可靠性和安全性。
以上就是解决 PayPal IPN 验证中的 “Access Denied” 问题的详细内容,更多请关注php中文网其它相关文章!


