基于变量MYSQL IPN的子字符串问题


Issue with substr based on variable MYSQL IPN

你好,我很难弄清楚为什么我的表中没有添加用户名列。我正在尝试使用我的IPN中的付款人电子邮件来引入登录用户名。除了用户名外,所有内容都在发布中。在用户名变量编辑的位置中是否有我做错的地方?是不是我遗漏了什么东西,阻止了这篇文章的发布?

<?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";
$url = "https://www.paypal.com/cgi-bin/webscr";
$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
if (strpos($curl_result, "VERIFIED") !== false) {
    $req .= "'n'nPaypal Verified OK";
} else {
    $req .= "'n'nData NOT verified from Paypal!";
    mail("chris@test.com", "IPN interaction not verified", "$req", "From: chris@test.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 != "chris@test.com") {
    $message = "Investigate why and how receiver email is wrong. Email = " . $_POST['receiver_email'] . "'n'n'n$req";
    mail("chris@test.com", "Receiver Email is incorrect", $message, "From: chris@test.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
}
// Connect to database ------------------------------------------------------------------------------------------------------
require_once 'connect_to_mysql.php';
// Check number 3 ------------------------------------------------------------------------------------------------------------
$this_txn = $_POST['txn_id'];
$sql = mysql_query("SELECT id FROM transactions WHERE txn_id='$this_txn' LIMIT 1");
$numRows = mysql_num_rows($sql);
if ($numRows > 0) {
    $message = "Duplicate transaction ID occured so we killed the IPN script. 'n'n'n$req";
    mail("chris@test.com", "Duplicate txn_id in the IPN system", $message, "From: chris@test.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 = mysql_query("SELECT price FROM products WHERE id='$product_id' LIMIT 1");
    while($row = mysql_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['payment_gross'] . " != $fullAmount 'n'n'n$req";
        mail("chris@test.com", "Price Jack or Bad Programming", $message, "From: chris@test.com" );
        exit(); // exit script
} 
require_once '../includes/db_conx.php';
//
$payer_email = $_POST['payer_email'];
// Select the member from the users table
$username = substr($payer_email, 0, strpos($payer_email, '@'));
$sql = "SELECT username FROM transactions WHERE username='{$username}%'";
$user_query = mysqli_query($db_conx, $sql);
$numrows = mysqli_num_rows($user_query);
if($numrows < 1){
   $i = 0;
   while ($name_arr = mysqli_fetch_assoc($result)) {
      $name = $name_arr['username'];       
      $after = substr($name, strlen($username));
      if (ctype_digit($after)) {
         if (($after = (int) $after) > $i) {
            $i = $after;
         }
      }
   }
   if ($i > 0) {
      $username .= $i;
   }
}

// END ALL SECURITY CHECKS NOW IN THE DATABASE IT GOES ------------------------------------
////////////////////////////////////////////////////
// Homework - Examples of assigning local variables from the POST variables
$txn_id = $_POST['txn_id'];
$payer_email = $_POST['payer_email'];
$custom = $_POST['custom'];
$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'];
$password = mt_rand(1000, 9999); 
$p_hash = md5($password);
$username = $_POST['username'];
// Place the transaction into the database
$sql = mysql_query("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, password, ip, username) 
   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','$p_hash','$ip','$username')") or die ("unable to execute the query");
$to      = $payer_email;  
$subject = ' Login Credentials';  
$message = ' 
Your officially all ready to go. To login use the information below.
Your account login information 
------------------------- 
Email: '.$payer_email.' 
Password: '.$password.' 
------------------------- 
You can now login at https://www.test.com/signin.php';  
$headers = 'From:noreply@test.com' . "'r'n";  
mail($to, $subject, $message, $headers);  
mysql_close();
// Mail yourself the details
mail("chris@test.com", "NORMAL IPN RESULT YAY MONEY!", $req, "From: chris@test.com");
?>

〔28-Jul2013 16:05:40美国/丹佛〕PHP解析错误:语法错误,中出现意外的T_ELSE/home/lear/public_html/storescripts/my_ipn.php,第74行

〔2013年7月28日21:06:37美国/丹佛〕PHP警告:mysqli_query()参数1应为mysqli,中给定null/第100行上的home/lear/public_html/storescripts/my_ipn.php

【2013年7月28日21:06:37美国/丹佛】PHP警告:mysqli_num_rows()参数1应为mysqli_result,中给定为null/home/lear/public_html/storescripts/my_ipn.php,第102行

编辑:

我刚刚更新了剧本。我收到的错误如下:

【2013年7月28日22:18:33美国/丹佛】PHP警告:mysqli_fetch_assoc()要求参数1为mysqli_result,null在/home/learnsit/public_html/storescripts/my_ipn.php在线提供108

108号线为

while($name_arr=mysqli_fetch_assoc($result)){

我没有玩过太多,但对我来说,最值得怀疑的代码是:

$sql = "SELECT `username` FROM `transactions` WHERE `username` = ''' . $username . '%'';";

它可能看起来更像

$sql = "SELECT `username` FROM `transactions` WHERE `username` = '{$username}%'";

FYI:-PHP可以处理双引号中的单引号,而不需要反斜杠()转义。-MySQL引用不需要分号(;)转义-检查问题是否真的是MySQL查询的一个好方法是在查询函数的末尾添加或死亡(MySQL_error($db)),如下所示:

$result = mysqli_query($db_conx, $sql) or die(mysql_error($db_conx));

希望这能有所帮助!

更新:

我已经将其添加到结果区域以尝试和调试,但我没有收到任何消息。这会出现在您的标准错误页面中吗?

尝试

    echo $sql;

在进一步查看您的代码后,您似乎不应该看到username="{$username}"的任何内容,因为$username是基于$payer_email的,它尚未声明。您需要将这些用户名检查放入一个函数中,并在为变量分配$_POST索引后调用它,或者在首次声明$username变量之前将$_POST["payer_email"]移动到,以及去掉$_POST"username"]。。。虽然我还没有看到你的表单,但听起来你是通过付款人的电子邮件创建用户名的。这有帮助吗?

更新2:

mysql_fetch_assoc的错误是因为您没有声明$result。我相信您可能试图引用$user_query,在这种情况下,您的第108行应该是:

while ($name_arr = mysqli_fetch_assoc($user_query)) {  

更新3:

I got that and I've been able to post to my database finally, but I can't get it to count and add to the username to prevent duplicates.

首先,我注意到您使用的用户名="{$username}%"。我有几点要说,我希望你能听进去。我在这里给你鱼,但我也想教你。

  • 如果你想进行比较,它必须是用户名LIKE"{$username}%"
  • 我不清楚你想做什么……如果你想要一个唯一的标识符,我实际上会做一些更像username='{$username}'的事情,然后,如果它返回一个结果,则在末尾添加一个唯一标识符

你看,当你用LIKE{$username}%做某事时,如果有人试图注册为awesome_bob,而其他人已经有了awesome_bobby,你最终会得到两行。我想,你会想要一些更随机的东西,或者创建一个更复杂的函数。或者,只需将用户名保留为电子邮件,这将使其保持唯一性,并且是一个非常简单的解决方案。

我将就此离开这篇文章,因为我认为它已经回答了你最初的问题,然后又回答了一些问题。如果你还有其他问题,我想人们会很乐意单独讨论。

我对你的问题回答够了吗?如果是这样的话,我会感谢我的努力:)