向PayPal沙箱环境传递变量时显示错误页,IPN捐赠集成求助
排查PayPal沙箱跳转错误的解决方案
嘿,从你遇到的情况来看——昨天还能正常跳转沙箱完成捐赠支付,今天传变量就弹出错误页,大概率是表单传递的PayPal核心参数缺失/格式错误,或者后台中转逻辑漏了关键配置。结合你用CodeIgniter的场景,我给你整理了一步步的排查和修复方案:
1. 先检查表单的PayPal核心参数是否完整
PayPal的一次性捐赠请求必须包含几个必填参数,你贴的表单代码只显示了amount字段,很可能是缺了关键项导致沙箱报错。完整的捐赠表单应该包含这些内容:
<form method="post" action="<?php echo base_url(); ?>controller/donation_redirect" name="DonationForm" id="DonationForm" class="mt-20"> <!-- PayPal 必填隐藏参数 --> <input type="hidden" name="cmd" value="_donations"> <input type="hidden" name="business" value="你的沙箱收款账户邮箱"> <input type="hidden" name="currency_code" value="USD"> <!-- 换成你需要的货币,比如CNY --> <!-- 用户输入的金额 --> <input type="number" min="1" placeholder="Amount" id="amount" name="amount" class="form-control" required> <button type="submit" class="btn btn-primary">提交捐赠</button> </form>
注:你之前把表单提交到自己的controller方法是没问题的,但要确保后台是把参数正确转发给PayPal沙箱,而不是直接处理完就结束了。
2. 修复后台中转逻辑(关键!)
如果你的表单提交到CodeIgniter控制器中转,一定要确保所有PayPal参数都完整传递,没有遗漏或转义错误。比如你的控制器方法可以这么写:
public function donation_redirect() { // 先验证金额合法性 $amount = $this->input->post('amount'); if (!is_numeric($amount) || $amount < 1) { $this->session->set_flashdata('error', '请输入有效的捐赠金额'); redirect('donation'); return; } // 先把捐赠记录存入数据库,标记为「未支付」 $donation_data = [ 'amount' => $amount, 'status' => 'unpaid', 'created_at' => date('Y-m-d H:i:s') ]; $this->db->insert('donations', $donation_data); $donation_id = $this->db->insert_id(); // 组装PayPal跳转参数,关键是带上自定义ID关联数据库记录 $paypal_params = [ 'cmd' => '_donations', 'business' => '你的沙箱收款邮箱', 'currency_code' => 'USD', 'amount' => $amount, 'return' => base_url('donation/success/' . $donation_id), // 支付成功返回页 'cancel_return' => base_url('donation/cancel/' . $donation_id), // 取消返回页 'notify_url' => base_url('donation/ipn_handler'), // IPN回调地址 'custom' => $donation_id // 自定义参数,用来关联你的数据库记录 ]; // 跳转到PayPal沙箱 header('Location: https://www.sandbox.paypal.com/cgi-bin/webscr?' . http_build_query($paypal_params)); exit; }
这里的核心是:绝对不能遗漏cmd=_donations和business这两个参数,它们是PayPal识别捐赠请求的关键,缺失直接会导致沙箱报错。
3. 快速排查小技巧
- 直接在浏览器里拼接参数访问沙箱地址,比如:
https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_donations&business=你的沙箱邮箱&amount=10¤cy_code=USD,如果能正常跳转,说明是你的表单/后台中转的参数有问题;如果还是报错,去PayPal开发者平台检查沙箱收款账户是否已验证。 - 查看服务器日志,确认参数传递时有没有被转义、丢失的情况。
4. IPN回调更新支付状态的核心代码
等PayPal支付完成后,会向你设置的notify_url发送IPN通知,你需要在控制器里处理这个请求,更新数据库的支付状态:
public function ipn_handler() { // 接收PayPal的IPN数据 $raw_post_data = file_get_contents('php://input'); $raw_post_array = explode('&', $raw_post_data); $myPost = []; foreach ($raw_post_array as $keyval) { $keyval = explode('=', $keyval); if (count($keyval) == 2) { $myPost[$keyval[0]] = urldecode($keyval[1]); } } // 向PayPal沙箱发送验证请求,确认IPN有效性 $req = 'cmd=_notify-validate'; foreach ($myPost as $key => $value) { $value = urlencode($value); $req .= "&$key=$value"; } $ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr'); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $req); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); $res = curl_exec($ch); curl_close($ch); // 验证通过后更新数据库状态 if (strcmp($res, "VERIFIED") == 0) { $donation_id = $this->input->post('custom'); $payment_status = $this->input->post('payment_status'); if ($payment_status == 'Completed') { $this->db->where('id', $donation_id)->update('donations', ['status' => 'paid']); } elseif (in_array($payment_status, ['Failed', 'Denied'])) { $this->db->where('id', $donation_id)->update('donations', ['status' => 'failed']); } } else { // IPN无效,记录日志方便排查 log_message('error', 'PayPal IPN Invalid: ' . $raw_post_data); } }
内容的提问来源于stack exchange,提问作者Vijay Gupta
相关产品推荐
相关产品推荐

