PayPal生产与沙盒的工作方式不同


PayPal production working differently than sandbox

我已经构建了一个应用程序,它向PayPal发送一个带有登录用户GUID的通知url,在购买完成后,会调用该url,验证后,用户数据库条目会将列purchased从0更新为1。

然后,用户单击返回应用程序按钮,高级功能将基于purchased列显示。

在过去的几个月里,我一直在沙箱中测试这个。100%的测试时间(包括本期之后),在购买完成后会显示溢价选项卡。

客户非常激动,并同意投入生产。我用完全相同的URL设置了IPN,除了从www.sandbox.paypal.com切换到www.paypal.com,并将列出的账户从沙盒业务更改为个人业务外,我什么都没做。

问题是,按钮现在不会显示,直到,您才刷新屏幕。点击"返回应用程序"按钮,以前按预期工作,现在不显示高级选项卡。一旦我点击刷新,它就会出现。如果我把所有东西都切换回沙箱设置,砰的一声,它又可以正常工作了。

这是带有生产帐户的BuyNow按钮代码:

<form action="https://www.paypal.com/cgi-bin/webscr" method="post" id="buynowForm" target="_top">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="ACCOUNT EMAIL">
<input type="hidden" name="lc" value="US">
<input type="hidden" name="item_name" value="Product">
<input type="hidden" name="amount" value="10.00">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="button_subtype" value="services">
<input type="hidden" name="no_note" value="1">
<input type="hidden" name="no_shipping" value="1">
<input type='hidden' name='notify_url' value='http://app.com/purchase/<?php echo $data[0]['uid'] ?>'>
<input type='hidden' name='return' value='http://app.com/'>
<input type="hidden" name="rm" value="1">
<input type="hidden" name="cbt" value="Return to Product Plus">
<input type="hidden" name="bn" value="PP-BuyNowBF:btn_buynowCC_LG.gif:NonHosted">
<input type="submit" class="hidden-print visible-print" border="0" name="buysubmit" value="Click For Product Plus" alt="Click for Product Plus">
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">

这是上面所说的处理路线:

$app->post('/purchase/:uid', function ($uid) use ($app) {
 $request = Slim::getInstance()->request();
 $inputs = json_decode($request->getBody());
 $db_conn = conn();
 $req = 'cmd=_notify-validate'; 
    foreach ($_POST as $key => $value) 
    { 
        if (get_magic_quotes_gpc()) 
        { 
            $_POST[$key] = stripslashes($value); 
            $value = stripslashes($value); 
        } 
        $value = urlencode($value); 
        $req .= "&$key=$value"; 
    } 
    $url = "https://www.paypal.com/cgi-bin/webscr";
    $ch = curl_init();    
    curl_setopt($ch, CURLOPT_URL,$url); 
    curl_setopt($ch, CURLOPT_FAILONERROR, 1); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); 
    curl_setopt($ch, CURLOPT_TIMEOUT, 3); 
    curl_setopt($ch, CURLOPT_POST, 1); 
    curl_setopt($ch, CURLOPT_POSTFIELDS, $req); 
    $result = curl_exec($ch); 
    curl_close($ch); 
    if (strcmp ($result, "VERIFIED") == 0)
    { 
        $sql_st = 'UPDATE  `user_data` SET `purchased` = 1 WHERE uid=:uid';
          $sql = $db_conn->prepare($sql_st);
          if ($sql->execute(array('uid'=>$uid))) {
            $data = array('status' => "Ok");
          } else {
            $data = array('status' => print_r(mysql_error()));
          }
    } 
    else  
    { 
        // Did Not Process IPN Properly
    } 
});

真的希望这只是我非常愚蠢的事情。感谢任何帮助/指导。

本质上,这里的解决方案是两个选项之一-

  1. 构建第二种完成方法——换句话说,IPN不是购买软件升级的第一道防线。我这边的一切都在工作,但IPN(notify_url)调用的时间太慢,无法进行即时升级,而不是即时升级。将它们返回到执行升级的页面,然后重定向。

  2. 将升级后的功能存储在不同的路线后面-这是PayPal的建议。本质上,让app.com/basic和app.com/upgraded。这并不理想,我也不建议将其作为永久解决方案。

总结-这是贝宝的一个已知问题。沙箱和生产工作流基本上是不同的-不是功能或API,而是在使用方面-生产级别的帐户受到的打击越来越大,处理通知所需的时间也慢得多。

希望这能帮助到别人。