我已经构建了一个应用程序,它向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
}
});
真的希望这只是我非常愚蠢的事情。感谢任何帮助/指导。
本质上,这里的解决方案是两个选项之一-
-
构建第二种完成方法——换句话说,IPN不是购买软件升级的第一道防线。我这边的一切都在工作,但IPN(notify_url)调用的时间太慢,无法进行即时升级,而不是即时升级。将它们返回到执行升级的页面,然后重定向。
-
将升级后的功能存储在不同的路线后面-这是PayPal的建议。本质上,让app.com/basic和app.com/upgraded。这并不理想,我也不建议将其作为永久解决方案。
总结-这是贝宝的一个已知问题。沙箱和生产工作流基本上是不同的-不是功能或API,而是在使用方面-生产级别的帐户受到的打击越来越大,处理通知所需的时间也慢得多。
希望这能帮助到别人。