使用PHP和cURL发回数据后,PayPal IPN响应无效

时间:2018-01-02 05:15:56

标签: php curl paypal paypal-ipn

我的PayPal IPN代码在购买完成后接收从PayPal发回的发布数据,但不会将数据插入数据库。如果代码无法将数据插入数据库,我的代码会向我发送电子邮件。如果我把这个帖子数据并在ipn.php后粘贴到地址栏中,它就能完美运行。我究竟做错了什么?我是否必须将数据发回PayPal?

我的IPN听众

    <?php
include 'includes/class.user.php';
$user = new USER();
$emailtext = "";

$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
    $keyval = explode ('=', $keyval);
    if (count($keyval) == 2)
        $myPost[$keyval[0]] = urldecode($keyval[1]);
}

$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
    $get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
    $value = urlencode($value);
    $req .= "&$key=$value";
}

$paypalURL = "https://ipnpb.paypal.com/cgi-bin/webscr";
$ch = curl_init($paypalURL);
if ($ch == FALSE) {
    return FALSE;
}
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_SSLVERSION, 6);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close', 'User-Agent: Company name removed for security, LLC.'));
$res = curl_exec($ch);

$tokens = explode("\r\n\r\n", trim($res));
$res = trim(end($tokens));

    //Payment data
    $txn_id = $_GET['txn_id'];
    $payment_gross = $_GET['mc_gross'];
    $currency_code = $_GET['mc_currency'];
    $pay_status = $_GET['payment_status'];
    $payer_email = $_GET['payer_email'];
    $date = date("m-d-y");
    $invNum = md5($date);
    $orderNum = md5($txn_id);
    $fullname = $_GET['address_name'];
    $address = $_GET['address_street'];
    $city = $_GET['address_city'];
    $state = $_GET['address_state'];
    $zip = $_GET['address_zip'];

    if($user->verify_txnid($txn_id)){
        exit();
    }else{
        $insertPayment = $user->insert_purchase($fullname,$address,$city,$state,$zip,"0000000000",$payer_email,$orderNum,$date,$txn_id,$invNum,$pay_status);
        if($insertPayment === TRUE){
            $num_cart_items = $_GET['num_cart_items'];
            for ($i = 0; $i <= $num_cart_items; $i++) {
                $order_item_name = $_GET['item_name' . $i];
                $order_item_quantity = $_GET['quantity' . $i];
                $order_item_gross_amount = $_GET['mc_gross_' . $i];
                $order_item_custom = $_GET['option_selection1_' . $i];
                $user->insert_order($txn_id, $order_item_name, $order_item_quantity, $order_item_gross_amount, $order_item_custom);

            }

        }else{
            foreach ($_GET as $key => $value)
            {
                $emailtext .= $key . " = " .$value ."\n\n";
            }
            mail('myemail@gmail.com', 'Insert Payment FAILED', $emailtext."\r\n".$req."\r\n".$res);
        }

    }
header("HTTP/1.1 200 OK");

我已确认PayPal的帖子将帖子与PayPal匹配,但我仍然收到INVALID响应,并且没有数据插入到数据库中。如果我从PayPal的初始POST获取原始发布数据字符串并将其粘贴到地址栏中,它就可以很好地插入到数据库中。我无法弄清楚为什么它不会自己将数据插入数据库。我在PayPal上的IPN历史记录显示500的html响应及其重试。

2 个答案:

答案 0 :(得分:0)

如果您回发的IPN消息与发送给您的一个PayPal不完全匹配,则将发生INVALID状态。您可以仔细检查您回发的IPN消息中是否有乱码,例如非英文字符。但如果您仍然无法找到根本原因,则必须通过https://www.paypal-techsupport.com/app/ask/联系PayPal技术支持,并提供PayPal交易ID以便进一步检查。

答案 1 :(得分:0)

沙盒上存在完全相同的问题。

通过关闭帐户配置文件设置中的“否定测试”并从ipn模拟器中删除日期来实现它。

这个简单的代码使其有效

$ipn_post_data = $_POST;
// Choose url
if (array_key_exists('test_ipn', $ipn_post_data) && 1 === (int) $ipn_post_data['test_ipn']){
    $url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
}else{
    $url = 'https://www.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,
));

    // 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') {
    $today = date("Y_m_d");
    $file = fopen("LogIPN.$today.txt", "ab");
    $hour = date("H:i:s T");
    fwrite($file, "Verified\r\n");
} else {
    $today = date("Y_m_d");
    $file = fopen("LogIPN.$today.txt", "ab");
    $hour = date("H:i:s T");
    fwrite($file, $response."\r\n");
    fwrite($file, $status."\r\n");
}

出于多种原因,我绝不会在生产中使用该代码。

希望这可以让你感到轻松。