PayPal捐赠返回URL返回空数组问题求助
解决PayPal捐赠return页面无法获取交易数据的问题
我来帮你梳理下问题原因和解决方案:
为什么return页面拿不到数据?
你遇到的情况是PayPal捐赠按钮(_donations命令)的特性导致的:
- 即使表单用POST方法,且设置了
rm=2,PayPal对于捐赠类的请求,默认不会将交易详情通过POST/GET直接传递到return URL。 - return URL的跳转只是给用户展示一个感谢页面,交易的核心数据需要通过**IPN(Instant Payment Notification)或者PDT(Payment Data Transfer)**来获取。你已经能正常接收IPN,说明IPN配置没问题,但return页面本身不会自动拿到这些数据。
解决方案一:启用PDT获取return页面的交易数据
PDT是PayPal提供的用来在return页面获取交易数据的功能,需要先在账户里启用:
1. 启用PDT并获取令牌
- 登录你的PayPal账户(沙盒和正式环境要分别设置)
- 进入【卖家设置】→【网站支付设置】→【付款数据传输】
- 启用PDT,复制生成的PDT令牌
2. 修改捐赠表单
在现有表单里添加几个隐藏字段:
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post" target="_top"> <input type="hidden" name="cmd" value="_donations" /> <input type="hidden" name="business" value="myEmail@gmail.com" /> <input type="hidden" name="currency_code" value="USD" /> <!-- 添加PDT相关字段 --> <input type="hidden" name="charset" value="utf-8"> <input type="hidden" name="custom" value="<?php echo session_id(); ?>"> <!-- 可选:传递自定义标识,比如用户会话ID --> <input type="hidden" name="cbt" value="返回我的网站"> <!-- 可选:设置跳转按钮的文本 --> <input type="hidden" name="return" value="http://localhost/thankyou.php" id="paypal_return"> <input type="hidden" name="notify_url" value="https://test.org/ipn_route_for_payment" id="ipn_url"> <input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" title="PayPal - The safer, easier way to pay online!" alt="Donate with PayPal button" /> <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1" /> </form>
3. 修改thankyou.php代码获取PDT数据
替换你当前的PHP代码,通过PayPal的同步接口验证并获取交易数据:
<?php // 替换成你的PDT令牌(沙盒和正式环境的令牌不同) $pdt_token = '你的PDT令牌'; $tx_id = $_GET['tx']; // PDT会通过GET传递交易ID参数tx if (!empty($tx_id)) { $ch = curl_init(); // 沙盒环境用这个URL,正式环境替换为https://www.paypal.com/cgi-bin/webscr curl_setopt($ch, CURLOPT_URL, 'https://www.sandbox.paypal.com/cgi-bin/webscr'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'cmd' => '_notify-synch', 'tx' => $tx_id, 'at' => $pdt_token ])); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); if (strpos($response, 'SUCCESS') === 0) { // 解析响应数据 $transaction_data = []; $lines = explode("\n", trim($response)); foreach ($lines as $line) { if (strpos($line, '=') !== false) { list($key, $value) = explode('=', $line, 2); $transaction_data[urldecode($key)] = urldecode($value); } } print_r($transaction_data); } else { echo '获取交易数据失败,请稍后重试'; } } else { echo '无效的交易请求'; } ?>
解决方案二:结合IPN存储数据,在return页面查询
因为你已经能正常接收IPN,也可以用这种方式:
1. 修改表单添加自定义标识
在表单里加一个custom字段,用来传递唯一标识(比如用户会话ID):
<input type="hidden" name="custom" value="<?php echo session_id(); ?>">
2. 在IPN处理页面存储交易数据
修改你的ipn_route_for_payment页面,把IPN接收到的交易数据(比如txn_id、mc_gross、custom等)存储到数据库中。
3. 在thankyou.php查询数据
当PayPal跳转回return页面时,会通过GET传递tx参数(交易ID),用这个ID去数据库查询已存储的交易数据:
<?php session_start(); $tx_id = $_GET['tx']; if (!empty($tx_id)) { // 连接你的数据库(示例用PDO,可根据你的数据库类型调整) $pdo = new PDO('mysql:host=localhost;dbname=你的数据库名', '用户名', '密码'); $stmt = $pdo->prepare('SELECT * FROM paypal_donations WHERE txn_id = ?'); $stmt->execute([$tx_id]); $donation = $stmt->fetch(PDO::FETCH_ASSOC); if ($donation) { print_r($donation); } else { echo '捐赠记录暂未同步,请稍后刷新页面'; } } else { echo '无效的交易请求'; } ?>
补充说明
- 为什么
rm=2没生效?PayPal的_donations命令不支持rm参数的POST返回,这个参数仅适用于普通支付按钮(如_xclick),捐赠按钮的return跳转默认是GET,且不会携带交易详情。 - 沙盒和正式环境的PDT令牌、接口URL都要分开设置,不能混用。
- 无论用PDT还是IPN,都要验证数据的真实性,避免伪造请求。
内容的提问来源于stack exchange,提问作者Fahad
相关产品推荐
相关产品推荐

