Stripe支付完成后页面不刷新/跳转问题求助
Stripe支付完成后无跳转且无支付记录问题排查
问题现象
点击Stripe支付按钮弹出窗口,输入银行卡信息并点击支付后,窗口显示绿色对勾,但页面无反应。Stripe后台无支付记录,银行卡未扣款,本该跳转到带$calback_url参数的URL,却仅显示灰色按钮,需手动刷新页面。
现有代码
Smarty模板嵌入的Stripe按钮代码
<div> <!-- Stripe --> <form action="/payment.php?custom=1&sum={$sum*100}" method="POST"> <script src="https://checkout.stripe.com/checkout.js" class="stripe-button" data-key="pk_live_xxxxxxxxx" data-amount="{$sum*100}" data-description="payment" data-locale="auto" data-zip-code="true"> </script> </form> <div style="font-size: 10px; padding: 0 0 0 22px">powered by <a href="https://stripe.com/" target="_blank" rel="nofollow">stripe</a></div> </div>
支付处理文件payment.php代码
if($_REQUEST['stripeToken']) { require_once('stripe_4/init.php'); try { // Use Stripe's library to make requests... \Stripe\Stripe::setApiKey("sk_live_xxxxxxxxxx"); $token = $_REQUEST['stripeToken']; if ($_GET['custom'] == 1) { $price = $_GET['sum']; $calback_url = 'ppdpam'; $description = "Custom payment"; } else { $_SESSION['stripe_error_message'] = "Wrong parameters!"; header("Location: https://".SITE."/data.php?er=100$parameter"); exit; } // Charge the user's card: $charge = \Stripe\Charge::create(array( "amount" => $price, "currency" => "usd", "description" => $description, "source" => $token, )); } catch(\Stripe\Error\Card $e) { // Since it's a decline, \Stripe\Error\Card will be caught $body = $e->getJsonBody(); $err = $body['error']; print('Status is:' . $e->getHttpStatus() . "\n"); print('Type is:' . $err['type'] . "\n"); print('Code is:' . $err['code'] . "\n"); // param is '' in this case print('Param is:' . $err['param'] . "\n"); print('Message is:' . $err['message'] . "\n"); $_SESSION['stripe_error_message'] = $e->getMessage(); header("Location: /data.php?er=1$parameter"); exit; header("Location: https://".SITE."/data.php?".$calback_url); exit; }
问题根源与修复方案
1. 跳转逻辑异常
- 问题: 成功支付后的跳转语句被放在
catch块之后,但仅捕获了\Stripe\Error\Card类错误,其他异常(如API密钥错误、参数非法、网络故障)会直接终止代码执行,无法触发跳转;同时catch块内的print语句会输出内容,导致后续header跳转失效(HTTP响应头必须在输出内容前发送)。 - 修复:
- 增加全局异常捕获,覆盖所有Stripe错误和PHP异常;
- 删除
catch块内的print语句,改用$_SESSION存储错误信息后直接跳转; - 将成功跳转语句移到
try块内部,确保支付成功后立即执行。
2. 参数问题
- 问题: 依赖URL中的
$_GET参数易被篡改,且$parameter变量未定义,导致跳转URL拼接错误;未对$price做合法性校验,存在安全风险。 - 修复:
- 将自定义参数放入表单隐藏域,统一通过
POST获取; - 移除未定义的
$parameter变量; - 增加参数校验逻辑,确保
$price为合法正整数。
- 将自定义参数放入表单隐藏域,统一通过
3. 代码优化后的完整版本
优化后的Smarty模板代码
<div> <!-- Stripe --> <form action="/payment.php" method="POST"> <!-- 隐藏域传递自定义参数,避免URL篡改 --> <input type="hidden" name="custom" value="1"> <input type="hidden" name="sum" value="{$sum*100}"> <script src="https://checkout.stripe.com/checkout.js" class="stripe-button" data-key="pk_live_xxxxxxxxx" data-amount="{$sum*100}" data-description="payment" data-locale="auto" data-zip-code="true"> </script> </form> <div style="font-size: 10px; padding: 0 0 0 22px">powered by <a href="https://stripe.com/" target="_blank" rel="nofollow">stripe</a></div> </div>
优化后的payment.php代码
session_start(); // 确保开启Session,用于存储错误信息 if(isset($_REQUEST['stripeToken'])) { require_once('stripe_4/init.php'); try { \Stripe\Stripe::setApiKey("sk_live_xxxxxxxxxx"); $token = $_REQUEST['stripeToken']; // 获取并校验参数 $custom = isset($_POST['custom']) ? intval($_POST['custom']) : 0; $price = isset($_POST['sum']) ? intval($_POST['sum']) : 0; if ($custom !== 1 || $price <= 0) { $_SESSION['stripe_error_message'] = "非法参数!"; header("Location: https://".SITE."/data.php?er=100"); exit; } $calback_url = 'ppdpam'; $description = "Custom payment"; // 创建Charge $charge = \Stripe\Charge::create([ "amount" => $price, "currency" => "usd", "description" => $description, "source" => $token, ]); // 支付成功跳转 header("Location: https://".SITE."/data.php?".$calback_url); exit; } catch(\Stripe\Error\Card $e) { // 银行卡相关错误处理 $body = $e->getJsonBody(); $_SESSION['stripe_error_message'] = $body['error']['message']; header("Location: /data.php?er=1"); exit; } catch(\Stripe\Error\Base $e) { // 其他Stripe API错误处理 $_SESSION['stripe_error_message'] = "支付接口错误:".$e->getMessage(); header("Location: /data.php?er=2"); exit; } catch(Exception $e) { // 全局异常处理 $_SESSION['stripe_error_message'] = "系统错误:".$e->getMessage(); header("Location: /data.php?er=99"); exit; } } else { // 无合法支付令牌,直接跳转错误页 $_SESSION['stripe_error_message'] = "无效请求!"; header("Location: /data.php?er=0"); exit; }
内容的提问来源于stack exchange,提问作者S.I.
相关产品推荐
相关产品推荐

