【问题标题】:Paypal IPN Cancel Membership PHPPaypal IPN 取消会员资格 PHP
【发布时间】:2016-01-23 07:12:07
【问题描述】:

因此,当用户购买会员资格时,我获得的代码可以完美运行。但是,如果用户取消,我不确定如何编码。当用户通过它们取消时,教皇会向您抛出哪些字段?

我知道我应该使用subscr_cancelled,但我不确定取消背后的正确伪代码和逻辑。

例如:

  • 用户取消时的支付状态是什么?
  • 我会忽略付款状态吗?

到目前为止,这是我的代码,因为我已经进行了很多测试,所以它有点笨拙:

if (strcmp ($res, "VERIFIED") == 0) {
    // check whether the payment_status is Completed
    // check that txn_id has not been previously processed
    // check that receiver_email is your PayPal email
    // check that payment_amount/payment_currency are correct
    // process payment and mark item as paid.
    // assign posted variables to local variables

    $item_name = $_POST['item_name'];
    $item_number = $_POST['item_number'];
    $txn_type = $_POST['txn_type'];
    $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'];
    $id = $_POST['custom'];
    $make_premium =1;
    $make_loser=0;


        if($payment_status=="Completed"){
        $user_id_check = $mysqli->query("SELECT `username` FROM `users` WHERE `ID` ='$id'");
        if($user_id_check->num_rows > 0){
            $txn_id_check = $mysqli->query("SELECT `transaction_id` FROM `payment` WHERE `transaction_id`='$txn_id'");
            if($txn_id_check->num_rows != 1) {  
                        $query = "INSERT INTO `payment` (`transaction_id`, `payment_status`, `users_id`, `txn_type`) VALUES(?, ?, ?, ?)";
                        $statement = $mysqli->prepare($query);
                        $statement->bind_param('ssis',$txn_id, $payment_status, $id, $txn_type);
                        if($statement->execute()){
                            if($txn_type =="subscr_signup"){
                                $update_user_to_premium =("UPDATE `users` SET `is_member` =? WHERE `ID` =?");
                                $stmt =$mysqli->prepare($update_user_to_premium);
                                $stmt->bind_param('ii',$make_premium,$id);
                                $stmt->execute();
                            }
                        }else{
                        die('Error : ('. $mysqli->errno .') '. $mysqli->error);
                        }
                        $statement->close();
               }
            }
        }
    }
    if($txn_id_check->num_rows == 1){
        if($txn_type=="subscr_cancel"){
            $update_user_to_loser =("UPDATE `users` SET `is_member` =? WHERE `ID` =?");
            $stmt =$mysqli->prepare($update_user_to_loser);
            $stmt->bind_param('ii',$make_loser,$id);
            $stmt->execute();
        }
    {
    if(DEBUG == true) {
        error_log(date('[Y-m-d H:i e] '). "Verified IPN: $req ". PHP_EOL, 3, LOG_FILE);
    }
} else if (strcmp ($res, "INVALID") == 0) {
    // log for manual investigation
    // Add business logic here which deals with invalid IPN messages
    if(DEBUG == true) {
        error_log(date('[Y-m-d H:i e] '). "Invalid IPN: $req" . PHP_EOL, 3, LOG_FILE);
    }
}

我应该使用这样的东西

switch ($_POST['txn_type']) {   
 case 'subscr_signup':
        break;

    case 'subscr_eot':
       //subscription end of term
        break;

    case 'subscr_cancel':
        //subscription canceled
        break;

编辑:

if (strcmp ($res, "VERIFIED") == 0) {
    // check whether the payment_status is Completed
    // check that txn_id has not been previously processed
    // check that receiver_email is your PayPal email
    // check that payment_amount/payment_currency are correct
    // process payment and mark item as paid.
    // assign posted variables to local variables

    $item_name = $_POST['item_name'];
    $item_number = $_POST['item_number'];
    $txn_type = $_POST['txn_type'];
    $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'];
    $id = $_POST['custom'];
    $subscr_id = $_POST['subscr_id'];
    $make_premium =1;
    $make_loser=0;


        if($payment_status=="Completed"){
        $user_id_check = $mysqli->query("SELECT `username` FROM `users` WHERE `ID` ='$id'");
        if($user_id_check->num_rows > 0){
            $txn_id_check = $mysqli->query("SELECT `transaction_id` FROM `payment` WHERE `transaction_id`='$txn_id'");
            if($txn_id_check->num_rows != 1) {  
                        $query = "INSERT INTO `payment` (`transaction_id`, `payment_status`, `users_id`, `txn_type`, `subscr_id`) VALUES(?, ?, ?, ?, ?)";
                        $statement = $mysqli->prepare($query);
                        $statement->bind_param('ssiss',$txn_id, $payment_status, $id, $txn_type, $subscr_id);
                        if($statement->execute()){
                            if($txn_type =="subscr_signup"){
                                $update_user_to_premium =("UPDATE `users` SET `is_member` =? WHERE `ID` =?");
                                $stmt =$mysqli->prepare($update_user_to_premium);
                                $stmt->bind_param('ii',$make_premium,$id);
                                $stmt->execute();
                            }
                        }else{
                        die('Error : ('. $mysqli->errno .') '. $mysqli->error);
                        }
                        $statement->close();
               }
            }
        }
    }

        if($txn_type=="subscr_cancel"){
            // get user id from row with subscription id 
            $get_user_id = $mysqli->("SELECT `users_id` FROM `payment` WHERE `subscr_id`='$subscr_id'");
            $row = $get_user_id->fetch_assoc();
            $users_id = $row[`users_id`];
            $update_user_to_loser =("UPDATE `users` SET `is_member` =? WHERE `ID` =?");
            $stmt =$mysqli->prepare($update_user_to_loser);
            $stmt->bind_param('ii',$make_loser,$users_id);
            $stmt->execute();
        }
    {
    if(DEBUG == true) {
        error_log(date('[Y-m-d H:i e] '). "Verified IPN: $req ". PHP_EOL, 3, LOG_FILE);
    }
} else if (strcmp ($res, "INVALID") == 0) {
    // log for manual investigation
    // Add business logic here which deals with invalid IPN messages
    if(DEBUG == true) {
        error_log(date('[Y-m-d H:i e] '). "Invalid IPN: $req" . PHP_EOL, 3, LOG_FILE);
    }
}
?>

【问题讨论】:

  • 你为什么不用IPN simulator
  • 因为 IPN 模拟器不考虑定期会员资格。我已经用 IPN 模拟器测试了好几天了! @Alon 它也不考虑取消等。
  • 我必须考虑 subscr_id 吗?我真的希望有更多关于定期付款的文档@AndrewAngell
  • 我将原始评论移至包含更多详细信息的答案。至于 subscr_id,这取决于你。您可以对发送的 IPN 数据做任何您想做/需要做的事情,但根据处理的交易类型(付款、退款、订阅注册/付款/取消等),您可能有也可能没有特定的参数。

标签: php mysql paypal paypal-ipn


【解决方案1】:

如果个人资料被取消,则不会进行任何付款。那是一种不同类型的交易。没有付款,因此没有付款状态,因此您不会在那种 IPN 中获得该参数。

您可以在沙盒中轻松地对此进行测试。您只需要创建一个卖家账户和一个买家账户,并在您的卖家账户中配置 IPN 即可点击您的监听器。然后从卖家账户创建订阅按钮,从买家账户注册,然后取消。这将触发每个步骤的 IPN,因此您可以看到预期的内容并相应地调整您的 IPN 侦听器。

这里是 subscr_cancel 交易的 IPN 示例。

Array
(
    [amount3] => 4.99
    [address_status] => confirmed
    [recur_times] => 2
    [subscr_date] => 15:51:33 Jan 19, 2015 PST
    [payer_id] => YW66KXBKJRRES
    [address_street] => 123 Test Ave
    [mc_amount3] => 4.99
    [charset] => windows-1252
    [address_zip] => 64030
    [first_name] => Tester
    [reattempt] => 1
    [address_country_code] => US
    [address_name] => Testers, LLC
    [notify_version] => 3.8
    [subscr_id] => S-6YS75493RP123324L
    [payer_status] => verified
    [business] => sandbo_1215254764_biz@angelleye.com
    [address_country] => United States
    [address_city] => Grandview
    [verify_sign] => AI7Wj0s667jdpY.UclGpjUpSpsZNAJzn.UcYbCVhXVG5fO05tyBo36EL
    [payer_email] => drew@angelleye.com
    [payer_business_name] => Testers, LLC
    [last_name] => Testerson
    [address_state] => MO
    [receiver_email] => sandbo_1215254764_biz@angelleye.com
    [recurring] => 1
    [txn_type] => subscr_cancel
    [item_name] => Test Subscription
    [mc_currency] => USD
    [item_number] => TEST-123
    [residence_country] => US
    [test_ipn] => 1
    [period3] => 1 M
    [ipn_track_id] => f0f2f2be88fd
)

【讨论】:

  • 所以我的布局是正确的?通过不将 subscr_cancelled 放在 payment_status if 语句中?另外,当用户取消会员资格时我应该存储信息还是应该将其更新为非会员?另外,我当然需要考虑 subscr_id 才能将用户更新为非高级用户?
  • txn_type 的值不会是 subscr_cancelled,而是 subscr_cancel
  • 第一个正确使用 subscr_cancel 但第二个仍然显示 subscr_cancelled
  • 哦,是的,对不起,这不是我要问的。我为此使用了正确的逻辑吗?这是我应该解决问题的方式吗?
  • 这取决于您的目标是什么,但是是的,您可以保留在 if/then 逻辑内取消订阅时运行的代码。您只需要确保使用正确的值。
猜你喜欢
  • 2016-06-29
  • 2013-02-04
  • 2017-10-24
  • 2011-02-03
  • 2022-11-20
  • 2011-09-01
  • 2016-06-16
  • 2015-07-07
  • 2019-12-01
相关资源
最近更新 更多