PayPal IPN 有时不更新数据库
Posted
技术标签:
【中文标题】PayPal IPN 有时不更新数据库【英文标题】:PayPal IPN sometimes not updating database 【发布时间】:2021-06-17 06:48:34 【问题描述】:几个星期以来,PayPal 都没有为我的某些交易更新数据库。也许 10 个事务中有 3 个被添加到数据库中。不知道发生了什么。在此之前,一切都很好。没有错误,PayPal 历史中的每一笔交易都已完成。我不知道问题出在哪里。
这是我的 ipn.php
<?php
if (gethostbyaddr($_SERVER['REMOTE_ADDR']) !== 'notify.paypal.com')
exit();
// Require the functions to connect to database and fetch config values
require 'config.php';
require 'db.php';
// Fetch and sanitize POST and GET values
function getValue($value)
return (!empty($value)) ? sanitize($value) : false;
function sanitize($data)
return htmlentities(strip_tags(mysql_znote_escape_string($data)));
function VerifyPaypalIPN(array $IPN = null)
if(empty($IPN))
$IPN = $_POST;
if(empty($IPN['verify_sign']))
return null;
$IPN['cmd'] = '_notify-validate';
$PaypalHost = (empty($IPN['test_ipn']) ? 'www' : 'www.sandbox').'.paypal.com';
$cURL = curl_init();
curl_setopt($cURL, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($cURL, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($cURL, CURLOPT_SSLVERSION, 6);
curl_setopt($cURL, CURLOPT_CAINFO, __DIR__ . '/cert/cacert.pem');
curl_setopt($cURL, CURLOPT_URL, "https://$PaypalHost/cgi-bin/webscr");
curl_setopt($cURL, CURLOPT_ENCODING, 'gzip');
curl_setopt($cURL, CURLOPT_BINARYTRANSFER, true);
curl_setopt($cURL, CURLOPT_POST, true); // POST back
curl_setopt($cURL, CURLOPT_POSTFIELDS, $IPN); // the $IPN
curl_setopt($cURL, CURLOPT_HEADER, false);
curl_setopt($cURL, CURLOPT_RETURNTRANSFER, true);
curl_setopt($cURL, CURLOPT_FORBID_REUSE, true);
curl_setopt($cURL, CURLOPT_FRESH_CONNECT, true);
curl_setopt($cURL, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($cURL, CURLOPT_TIMEOUT, 60);
curl_setopt($cURL, CURLINFO_HEADER_OUT, true);
curl_setopt($cURL, CURLOPT_HTTPHEADER, array(
'Connection: close',
'Expect: ',
));
$Response = curl_exec($cURL);
$Status = (int)curl_getinfo($cURL, CURLINFO_HTTP_CODE);
curl_close($cURL);
if(empty($Response) or !preg_match('~^(VERIFIED|INVALID)$~i', $Response = trim($Response)) or !$Status)
return null;
if(intval($Status / 100) != 2)
return false;
return !strcasecmp($Response, 'VERIFIED');
// Fetch paypal configurations
$paypal = $config['paypal'];
$prices = $config['paypal_prices'];
// Send an empty HTTP 200 OK response to acknowledge receipt of the notification
header('HTTP/1.1 200 OK');
// Build the required acknowledgement message out of the notification just received
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value)
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
$postdata = $req;
// Assign payment notification values 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 = getValue($_POST['txn_id']);
$receiver_email = getValue($_POST['receiver_email']);
$payer_email = getValue($_POST['payer_email']);
$custom = (int)$_POST['custom'];
$connectedIp = $_SERVER['REMOTE_ADDR'];
mysql_insert("INSERT INTO `paypal` VALUES ('0', '$txn_id', 'Connection from IP: $connectedIp', '0', '0', '0')");
$status = VerifyPaypalIPN();
if ($status)
// Check that the payment_status is Completed
if ($payment_status == 'Completed')
// Check that txn_id has not been previously processed
$txn_id_check = mysql_select_single("SELECT `txn_id` FROM `paypal` WHERE `txn_id`='$txn_id'");
if ($txn_id_check !== false)
// Check that receiver_email is your Primary PayPal email
if ($receiver_email == $paypal['email'])
$status = true;
$paidMoney = 0;
$paidPoints = 0;
foreach ($prices as $priceValue => $pointsValue)
if ($priceValue == $payment_amount)
$paidMoney = $priceValue;
$paidPoints = $pointsValue;
if ($paidMoney == 0) $status = false; // Wrong amount of money
if ($payment_currency != $paypal['currency']) $status = false; // Wrong currency
// Verify that the user haven't messed around with POST data
if ($status)
// transaction log
mysql_insert("INSERT INTO `paypal` VALUES ('0', '$txn_id', '$payer_email', '$custom', '".$paidMoney."', '".$paidPoints."')");
// Process payment
$data = mysql_select_single("SELECT `premium_points` AS `old_points` FROM `accounts` WHERE `id`='$custom';");
// Give points to user
$new_points = $data['old_points'] + $paidPoints;
mysql_update("UPDATE `accounts` SET `premium_points`='$new_points' WHERE `id`='$custom'");
else
$pmail = $paypal['email'];
mysql_insert("INSERT INTO `paypal` VALUES ('0', '$txn_id', 'ERROR: Wrong mail. Received: $receiver_email, configured: $pmail', '0', '0', '0')");
else
// Something is wrong
mysql_insert("INSERT INTO `paypal` VALUES ('0', '$txn_id', 'ERROR: Invalid data. $postdata', '0', '0', '0')");
?>
【问题讨论】:
【参考方案1】:您可以在https://www.paypal.com/cgi-bin/webscr?cmd=_display-ipns-history查看您帐户的 IPN 历史记录
如果您收到所有您期望的 IPN,那么您需要调试您的侦听器。添加日志以确定出错的地方,例如无法回帖以验证 IPN。记录所有内容以确定错误是什么。同时检查您的网络服务器日志。
有关 IPN 的文档位于:https://developer.paypal.com/docs/api-basics/notifications/ipn/
【讨论】:
以上是关于PayPal IPN 有时不更新数据库的主要内容,如果未能解决你的问题,请参考以下文章
IPN 验证返回 INVALID,因为 PayPal 在 POST 中向 IPN 侦听器发送了不正确的字符集
PayPal IPN 更新以适应 HTTP1.1 - 对等方重置连接