PayPal IPN未连接到我的数据库以插入事务

时间:2015-07-03 21:50:29

标签: php mysql database paypal paypal-ipn

我是paypal和php的菜鸟所以我在网上关注了这个教程:https://www.developphp.com/video/PHP/PayPal-IPN-PHP-Instant-Payment-Notification-Script

我的问题是我的IPN结果都很好但是我的ipn.php脚本不会连接到我的数据库,所以我可以存储结果。

IPN.PHP代码

<?php
//connect to the database
    include_once ('includes/connect_to_mysql.php');
// Check to see there are posted variables coming into the script
if ($_SERVER['REQUEST_METHOD'] != "POST") die ("No Post Variables");
// Initialize the $req variable and add CMD key value pair
$req = 'cmd=_notify-validate';
// Read the post from PayPal
foreach ($_POST as $key => $value) {
    $value = urlencode(stripslashes($value));
    $req .= "&$key=$value";
}
// Now Post all of that back to PayPal's server using curl, and validate everything with PayPal
// We will use CURL instead of PHP for this for a more universally operable script (fsockopen has issues on some environments)
$url = "https://www.sandbox.paypal.com/cgi-bin/webscr"; //USE SANDBOX ACCOUNT TO TEST WITH
//$url = "https://www.paypal.com/cgi-bin/webscr"; //LIVE ACCOUNT
$curl_result=$curl_err='';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/x-www-form-urlencoded", "Content-Length: " . strlen($req)));
curl_setopt($ch, CURLOPT_HEADER , 0);   
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$curl_result = @curl_exec($ch);
$curl_err = curl_error($ch);
curl_close($ch);

$req = str_replace("&", "\n", $req);  // Make it a nice list in case we want to email it to ourselves for reporting

// Check that the result verifies with PayPal
if (strpos($curl_result, "VERIFIED") !== false) {
    $req .= "\n\nPaypal Verified OK";
    mail("email@gmail.com", "Verified OK", "$req", "From: email@gmail.com" );
} else {
    $req .= "\n\nData NOT verified from Paypal!";
    mail("email@gmail.com", "IPN interaction not verified", "$req", "From: email@gmail.com" );
    exit();
}

/* CHECK THESE 4 THINGS BEFORE PROCESSING THE TRANSACTION, HANDLE THEM AS YOU WISH
1. Make sure that business email returned is your business email
2. Make sure that the transaction’s payment status is “completed”
3. Make sure there are no duplicate txn_id
4. Make sure the payment amount matches what you charge for items. (Defeat Price-Jacking) */

// Check Number 1 ------------------------------------------------------------------------------------------------------------
$receiver_email = $_POST['receiver_email'];
if ($receiver_email != "email-facilitator@hotmail.com") {
    $message = "Investigate why and how receiver_email variable sent back by PayPal does not match the buisness email set in            cart.php. Email = " . $_POST['receiver_email'] . "\n\n\n$req";
    mail("email@gmail.com", "Receiver Email is incorrect", $message, "From: email@gmail.com" );
    exit(); // exit script
}
// Check number 2 ------------------------------------------------------------------------------------------------------------
if ($_POST['payment_status'] != "Completed") {
    // Handle how you think you should if a payment is not complete yet, a few scenarios can cause a transaction to be incomplete
    $message = "Investigate why payment was not completed. Email = " . $_POST['receiver_email'] . "\n\n\n$req";
    mail("email@gmail.com", "Payment not complete", $message, "From: email@gmail.com" );
    exit(); // exit script
}
// Check number 3 ------------------------------------------------------------------------------------------------------------
$this_txn = $_POST['txn_id'];
$sql = mysqli_query($conn, "SELECT id FROM transactions WHERE txn_id='$this_txn' LIMIT 1"); //check to see transaction id exists in the DB
$numRows = mysqli_num_rows($sql);
if ($numRows == 0) {
    $message = "Duplicate transaction ID occured so we killed the IPN script. \n\n\n$req";
    mail("email@gmail.com", "Duplicate transaction ID(txn_id) in the IPN system", $message, "From: email@gmail.com" );
    exit(); // exit script
} 
// Check number 4 ------------------------------------------------------------------------------------------------------------
$product_id_string = $_POST['custom'];
$product_id_string = rtrim($product_id_string, ","); // remove last comma
// Explode the string, make it an array, then query all the prices out, add them up, and make sure they match the payment_gross amount
$id_str_array = explode(",", $product_id_string); // Uses Comma(,) as delimiter(break point)
$fullAmount = 0;
foreach ($id_str_array as $key => $value) {

    $id_quantity_pair = explode("-", $value); // Uses Hyphen(-) as delimiter to separate product ID from its quantity
    $product_id = $id_quantity_pair[0]; // Get the product ID
    $product_quantity = $id_quantity_pair[1]; // Get the quantity
    $sql = mysqli_query($conn, "SELECT price FROM products WHERE id='$product_id' LIMIT 1");
    while($row = mysqli_fetch_array($sql)){
        $product_price = $row["price"];
    }
    $product_price = $product_price * $product_quantity;
    $fullAmount = $fullAmount + $product_price;
}
$fullAmount = number_format($fullAmount, 2);
$grossAmount = $_POST['mc_gross']; 
if ($fullAmount != $grossAmount) {
        $message = "Possible Price Jack: " . $_POST['mc_gross'] . " != $fullAmount \n\n\n$req";
        mail("email@gmail.com", "Price Jack or Bad Programming", $message, "From: email@gmail.com" );
        exit(); // exit script
} 
// END ALL SECURITY CHECKS NOW IN THE DATABASE IT GOES ------------------------------------
////////////////////////////////////////////////////
// Assign local variables from the POST PayPal variables
$custom = $_POST['custom'];
$payer_email = $_POST['payer_email'];
$first_name = $_POST['first_name'];
$last_name = $_POST['last_name'];
$payment_date = $_POST['payment_date'];
$mc_gross = $_POST['mc_gross'];
$payment_currency = $_POST['payment_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payment_type = $_POST['payment_type'];
$payment_status = $_POST['payment_status'];
$txn_type = $_POST['txn_type'];
$payer_status = $_POST['payer_status'];
$address_street = $_POST['address_street'];
$address_city = $_POST['address_city'];
$address_state = $_POST['address_state'];
$address_zip = $_POST['address_zip'];
$address_country = $_POST['address_country'];
$address_status = $_POST['address_status'];
$notify_version = $_POST['notify_version'];
$verify_sign = $_POST['verify_sign'];
$payer_id = $_POST['payer_id'];
$mc_currency = $_POST['mc_currency'];
$mc_fee = $_POST['mc_fee'];

// Place the transaction into the database
$sql = mysqli_query($conn, "INSERT INTO transactions (product_id_array, payer_email, first_name, last_name, payment_date, mc_gross, payment_currency, txn_id, receiver_email, payment_type, payment_status, txn_type, payer_status, address_street, address_city, address_state, address_zip, address_country, address_status, notify_version, verify_sign, payer_id, mc_currency, mc_fee) 
   VALUES('$custom','$payer_email','$first_name','$last_name','$payment_date','$mc_gross','$payment_currency','$txn_id','$receiver_email','$payment_type','$payment_status','$txn_type','$payer_status','$address_street','$address_city','$address_state','$address_zip','$address_country','$address_status','$notify_version','$verify_sign','$payer_id','$mc_currency','$mc_fee')") or die ("unable to execute the query");

mysqli_close();
// Mail yourself the details
mail("email@gmail.com", "NORMAL IPN RESULT - Transaction Entered", $req, "From: email@gmail.com");
?>

在测试时,我给自己发了一封电子邮件,其中包含IPN结果,这些结果已经过验证并且payment_status =已完成。

这是IPN输出:

cmd=_notify-validate
mc_gross=9.99
protection_eligibility=Eligible
address_status=confirmed
item_number1=
payer_id=BDK3Z8X34KY3Y
tax=0.00
address_street=1+Maire-Victorin
payment_date=13%3A51%3A16+Jul+06%2C+2015+PDT
payment_status=Completed
charset=windows-1252
address_zip=M5A+1E1
mc_shipping=0.00
mc_handling=0.00
first_name=test
mc_fee=0.59
address_country_code=CA
address_name=test+buyer
notify_version=3.8
custom=9-1%2C
payer_status=verified
business=email-facilitator%40hotmail.com
address_country=Canada
num_cart_items=1
mc_handling1=0.00
address_city=Toronto
verify_sign=A2YnYs6LuOd-R8BHIdbWTA6xHgalAu.DiwxDdytu5YxLaIvebtzbprOA
payer_email=email-buyer%40hotmail.com
mc_shipping1=0.00
tax1=0.00
txn_id=6HE31475W2614530U
payment_type=instant
last_name=buyer
address_state=Ontario
item_name1=Leather+Pouch
receiver_email=email-facilitator%40hotmail.com
payment_fee=
quantity1=1
receiver_id=SF4CCTMHQJMF8
txn_type=cart
mc_gross_1=9.99
mc_currency=CAD
residence_country=CA
test_ipn=1
transaction_subject=9-1%2C
payment_gross=
ipn_track_id=a7531c2eb1cec

Paypal Verified OK

我进一步调试了代​​码,直到我的select语句没有返回任何值,这些值对我来说表明与数据库的连接失败了。

任何人都可以帮我解释为什么我无法使用ipn.php代码连接到我的数据库?我的网站的所有其他页面将使用除此页面之外的相同代码进行连接,因此我只能认为它与PayPal调用此页面有关,而不是我的服务器。

这是我在connect_to_mysql.php中的连接代码:

<?php
/* PHP Database Connection */ 
$servername = "localhost";
$username = "user";
$password = "passs";
$database = "database";

// Create connection
$conn = mysqli_connect($servername, $username, $password, $database);

// Check connection
if (!$conn) {
    die("Connection failed: " . mysqli_connect_error());
}
echo "Connected successfully";
?>

2 个答案:

答案 0 :(得分:0)

您需要对脚本进行故障排除才能找到问题。使用IPN可能会很困难,但如果您按照how to test PayPal IPN的这些步骤进行操作,则应该可以很快跟踪它。

答案 1 :(得分:0)

我解决了这个问题。我需要将所有查询切换到Mysqli版本而不是旧的Mysql。固定代码如下:

<?php
// Report all PHP errors
ini_set('error_reporting', E_ALL);

// Destinations
define("ADMIN_EMAIL", "email@gmail.com");

// Destination types
define("DEST_EMAIL", "1");

/* PHP Database Connection */ 
$servername = "localhost";
$username = "aesirleatherworks";
$password = "";
$database = "my_aesirleatherworks";

// Create connection
$conn = mysqli_connect($servername, $username, $password, $database);


// Send an e-mail to the administrator if connection fails
if (!$conn) {
        error_log("Failed to connect to MYSQL ".mysqli_connect_error(), DEST_EMAIL, ADMIN_EMAIL);
    }

// Check to see there are posted variables coming into the script
if ($_SERVER['REQUEST_METHOD'] != "POST") die ("No Post Variables");
// Initialize the $req variable and add CMD key value pair
$req = 'cmd=_notify-validate';
// Read the post from PayPal
foreach ($_POST as $key => $value) {
    $value = urlencode(stripslashes($value));
    $req .= "&$key=$value";
}
// Now Post all of that back to PayPal's server using curl, and validate everything with PayPal
// We will use CURL instead of PHP for this for a more universally operable script (fsockopen has issues on some environments)
$url = "https://www.sandbox.paypal.com/cgi-bin/webscr"; //USE SANDBOX ACCOUNT TO TEST WITH
//$url = "https://www.paypal.com/cgi-bin/webscr"; //LIVE ACCOUNT
$curl_result=$curl_err='';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/x-www-form-urlencoded", "Content-Length: " . strlen($req)));
curl_setopt($ch, CURLOPT_HEADER , 0);   
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$curl_result = @curl_exec($ch);
$curl_err = curl_error($ch);
curl_close($ch);

$req = str_replace("&", "\n", $req);  // Make it a nice list in case we want to email it to ourselves for reporting

// Check that the result verifies with PayPal
if (strpos($curl_result, "VERIFIED") !== false) {
    $req .= "\n\nPaypal Verified OK";
} else {
    $req .= "\n\nData NOT verified from Paypal!";
    mail("email@gmail.com", "IPN interaction not verified", "$req", "From: email@gmail.com" );
    exit();
}

/* CHECK THESE 4 THINGS BEFORE PROCESSING THE TRANSACTION, HANDLE THEM AS YOU WISH
1. Make sure that business email returned is your business email
2. Make sure that the transaction’s payment status is “completed”
3. Make sure there are no duplicate txn_id
4. Make sure the payment amount matches what you charge for items. (Defeat Price-Jacking) */

// Check Number 1 ------------------------------------------------------------------------------------------------------------
$receiver_email = $_POST['receiver_email'];
if ($receiver_email != "email-facilitator@hotmail.com") {
    $message = "Investigate why and how receiver_email variable sent back by PayPal does not match the buisness email set in            cart.php. Email = " . $_POST['receiver_email'] . "\n\n\n$req";
    mail("email@gmail.com", "Receiver Email is incorrect", $message, "From: email@gmail.com" );
    exit(); // exit script
}
// Check number 2 ------------------------------------------------------------------------------------------------------------
if ($_POST['payment_status'] != "Completed") {
    // Handle how you think you should if a payment is not complete yet, a few scenarios can cause a transaction to be incomplete
    $message = "Investigate why payment was not completed. Email = " . $_POST['receiver_email'] . "\n\n\n$req";
    mail("email@gmail.com", "Payment not complete", $message, "From: email@gmail.com" );
    exit(); // exit script
}
// Check number 3 ------------------------------------------------------------------------------------------------------------
$this_txn = $_POST['txn_id'];
$query = "SELECT id FROM transactions WHERE txn_id='$this_txn' LIMIT 1";
$result = mysqli_query($conn, $query);
$numRows = mysqli_num_rows($result);
if ($numRows != 0) {
    $message = "Duplicate transaction ID occured so we killed the IPN script. Transaction ID:$this_txn \n\n\n$req";
    mail("email@gmail.com", "Duplicate transaction ID(txn_id) in the IPN system", $message, "From: email@gmail.com" );
    exit(); // exit script
} 
// Check number 4 ------------------------------------------------------------------------------------------------------------
$product_id_string = $_POST['custom'];
$product_id_string = rtrim($product_id_string, ","); // remove last comma
// Explode the string, make it an array, then query all the prices out, add them up, and make sure they match the payment_gross amount
$id_str_array = explode(",", $product_id_string); // Uses Comma(,) as delimiter(break point)
$fullAmount = 0;
foreach ($id_str_array as $key => $value) {

    $id_quantity_pair = explode("-", $value); // Uses Hyphen(-) as delimiter to separate product ID from its quantity
    $product_id = $id_quantity_pair[0]; // Get the product ID
    $product_quantity = $id_quantity_pair[1]; // Get the quantity
    $query = "SELECT price FROM products WHERE id='$product_id' LIMIT 1";
    $result = mysqli_query($conn, $query);
    while($row = mysqli_fetch_array($result)){
        $product_price = $row["price"];
    }
    $product_price = $product_price * $product_quantity;
    $fullAmount = $fullAmount + $product_price;
}
$fullAmount = number_format($fullAmount, 2);
$grossAmount = $_POST['mc_gross']; 
if ($fullAmount != $grossAmount) {
        $message = "Possible Price Jack: " . $_POST['mc_gross'] . " != $fullAmount \n\n\n$req";
        mail("email@gmail.com", "Price Jack or Bad Programming", $message, "From: email@gmail.com" );
        exit(); // exit script
} 
// END ALL SECURITY CHECKS NOW IN THE DATABASE IT GOES ------------------------------------
////////////////////////////////////////////////////
// Assign local variables from the POST PayPal variables
$custom = $_POST['custom'];
$payer_email = $_POST['payer_email'];
$first_name = $_POST['first_name'];
$last_name = $_POST['last_name'];
$payment_date = $_POST['payment_date'];
$mc_gross = $_POST['mc_gross'];
$payment_currency = $_POST['payment_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payment_type = $_POST['payment_type'];
$payment_status = $_POST['payment_status'];
$txn_type = $_POST['txn_type'];
$payer_status = $_POST['payer_status'];
$address_street = $_POST['address_street'];
$address_city = $_POST['address_city'];
$address_state = $_POST['address_state'];
$address_zip = $_POST['address_zip'];
$address_country = $_POST['address_country'];
$address_status = $_POST['address_status'];
$notify_version = $_POST['notify_version'];
$verify_sign = $_POST['verify_sign'];
$payer_id = $_POST['payer_id'];
$mc_currency = $_POST['mc_currency'];
$mc_fee = $_POST['mc_fee'];

// Place the transaction into the database
$sql = mysqli_query($conn, "INSERT INTO transactions (id, product_id_array, payer_email, first_name, last_name, payment_date, mc_gross, payment_currency, receiver_email, payment_type, payment_status, txn_type, payer_status, address_street, address_city, address_state, address_zip, address_country, address_status, notify_version, verify_sign, payer_id, mc_currency, mc_fee) 
   VALUES('$txn_id','$custom','$payer_email','$first_name','$last_name','$payment_date','$mc_gross','$payment_currency','$receiver_email','$payment_type','$payment_status','$txn_type','$payer_status','$address_street','$address_city','$address_state','$address_zip','$address_country','$address_status','$notify_version','$verify_sign','$payer_id','$mc_currency','$mc_fee')") or die ("unable to execute the query");

mysqli_close();
// Mail yourself the details
mail("email@gmail.com", "New Order Entered: ".$txn_id, $req, "From: email@gmail.com");
?>