fix: 统一修复支付回调路由兼容与前端支付跳转逻辑
8 个文件变更
+38
-19
13172193298@163.com
| •app_plugins/alipay_official/admin/settings.php | +3 -2 |
| •app_plugins/alipay_official/bootstrap.php | +3 -2 |
| •app_plugins/balance/bootstrap.php | +2 -1 |
| •app_plugins/docker_shop/bootstrap.php | +1 -1 |
| •app_plugins/epay/admin/settings.php | +3 -2 |
| •app_plugins/epay/bootstrap.php | +19 -3 |
| •app_plugins/hosting_shop/bootstrap.php | +1 -1 |
| •templates/tdesign/spa/src/account/api/plugins.js | +6 -7 |
变更内容
diff --git a/app_plugins/alipay_official/admin/settings.php b/app_plugins/alipay_official/admin/settings.php
index edf2b4c..5823fdc 100644
--- a/app_plugins/alipay_official/admin/settings.php
+++ b/app_plugins/alipay_official/admin/settings.php
@@ -26,8 +26,9 @@ $siteRoot = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https://
if (substr($siteRoot, -6) === '/admin') {
$siteRoot = substr($siteRoot, 0, -6);
}
-$notifyUrl = $siteRoot . '/pay/alipay_official/notify';
-$returnUrl = $siteRoot . '/pay/alipay_official/return';
+// 回调地址统一用 index.php?_r= 兼容路由:不依赖服务器伪静态重写
+$notifyUrl = $siteRoot . '/index.php?_r=/pay/alipay_official/notify';
+$returnUrl = $siteRoot . '/index.php?_r=/pay/alipay_official/return';
?>
<div class="mn-set-card">
diff --git a/app_plugins/alipay_official/bootstrap.php b/app_plugins/alipay_official/bootstrap.php
index ce5634f..a624a79 100644
--- a/app_plugins/alipay_official/bootstrap.php
+++ b/app_plugins/alipay_official/bootstrap.php
@@ -73,8 +73,9 @@ mnbt_register_payment('alipay_official', [
}
$siteurl = isset($order['siteurl']) ? $order['siteurl'] : '';
$siteurl = rtrim((string)$siteurl, '/') . '/';
- $notifyUrl = $siteurl . 'pay/alipay_official/notify';
- $returnUrl = $siteurl . 'pay/alipay_official/return';
+ // 回调地址统一用 index.php?_r= 兼容路由:不依赖服务器伪静态重写(同 epay)
+ $notifyUrl = $siteurl . 'index.php?_r=/pay/alipay_official/notify';
+ $returnUrl = $siteurl . 'index.php?_r=/pay/alipay_official/return';
$params = [
'out_trade_no' => $order['out_trade_no'],
diff --git a/app_plugins/balance/bootstrap.php b/app_plugins/balance/bootstrap.php
index 8fb02b1..2ea5fdd 100644
--- a/app_plugins/balance/bootstrap.php
+++ b/app_plugins/balance/bootstrap.php
@@ -198,7 +198,8 @@ mnbt_register_route('POST', '/balance/api/create_recharge', function ($params, $
}
// 返回支付 HTML,前端用 document.write 输出跳转
- balance_json('正在跳转到支付页面', ['html' => $html]);
+ // code 必须为 'ok':支付发起成功(HTML 已生成),否则 SPA 等客户端会按失败处理而不跳转
+ balance_json('ok', ['html' => $html]);
});
/* ============================================================
diff --git a/app_plugins/docker_shop/bootstrap.php b/app_plugins/docker_shop/bootstrap.php
index c2909aa..dcf4692 100644
--- a/app_plugins/docker_shop/bootstrap.php
+++ b/app_plugins/docker_shop/bootstrap.php
@@ -287,7 +287,7 @@ mnbt_register_route('POST', '/docker-shop/api/create_order', function ($params,
docker_shop_json('支付方式不可用,请检查支付插件是否已启用');
}
- docker_shop_json('正在跳转到支付页面', ['html' => $html, 'order_no' => $order_no]);
+ docker_shop_json('ok', ['html' => $html, 'order_no' => $order_no]);
});
// 重置 Docker 账号密码
diff --git a/app_plugins/epay/admin/settings.php b/app_plugins/epay/admin/settings.php
index c1fcbd0..684a00b 100644
--- a/app_plugins/epay/admin/settings.php
+++ b/app_plugins/epay/admin/settings.php
@@ -26,8 +26,9 @@ $siteRoot = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https://
if (substr($siteRoot, -6) === '/admin') {
$siteRoot = substr($siteRoot, 0, -6);
}
-$notifyUrl = $siteRoot . '/pay/epay/notify';
-$returnUrl = $siteRoot . '/pay/epay/return';
+// 回调地址统一用 index.php?_r= 兼容路由:不依赖服务器伪静态重写
+$notifyUrl = $siteRoot . '/index.php?_r=/pay/epay/notify';
+$returnUrl = $siteRoot . '/index.php?_r=/pay/epay/return';
?>
<div class="mn-set-card">
diff --git a/app_plugins/epay/bootstrap.php b/app_plugins/epay/bootstrap.php
index dfa2120..fde37c7 100644
--- a/app_plugins/epay/bootstrap.php
+++ b/app_plugins/epay/bootstrap.php
@@ -92,12 +92,17 @@ mnbt_register_payment('epay', [
$siteurl = isset($order['siteurl']) ? $order['siteurl'] : '';
// 站点根 URL 末尾保证带斜杠
$siteurl = rtrim((string)$siteurl, '/') . '/';
+ // 回调地址统一用 index.php?_r= 兼容路由:不依赖服务器伪静态重写。
+ // 部分环境(未配置 rewrite 规则)下 /pay/epay/notify 会直接返回 nginx 404,
+ // 导致易支付网关异步通知收不到、订单无法结算(支付成功但余额不入账)。
+ $notifyUrl = $siteurl . 'index.php?_r=/pay/epay/notify';
+ $returnUrl = $siteurl . 'index.php?_r=/pay/epay/return';
$params = [
'type' => $method, // alipay / wxpay / qqpay
'out_trade_no' => $order['out_trade_no'],
- 'notify_url' => $siteurl . 'pay/epay/notify',
- 'return_url' => $siteurl . 'pay/epay/return',
+ 'notify_url' => $notifyUrl,
+ 'return_url' => $returnUrl,
'name' => $order['name'],
'money' => $order['money'],
];
@@ -107,15 +112,24 @@ mnbt_register_payment('epay', [
// ============================================================
// 注册回调路由:/pay/epay/notify(异步通知)
+// 注意:路由方式必须为 *(GET+POST 都接收)——
+// 部分易支付变体(如 pay1987)的自动通知/后台补发使用 GET 携带参数,
+// 只注册 POST 会导致通知命中不了路由、订单无法结算。
// ============================================================
-mnbt_register_route('POST', '/pay/epay/notify', function ($params, $ctx) {
+mnbt_register_route('*', '/pay/epay/notify', function ($params, $ctx) {
@header('Content-Type: text/plain; charset=UTF-8');
if (!epay_is_configured()) {
echo 'fail';
return;
}
$c = epay_get_config();
+ // 兼容 POST / GET 两种通知方式
$data = $_POST;
+ if (empty($data)) {
+ $data = $_GET;
+ // 路由参数 _r 是我们拼接的,不参与网关签名,验签前必须剔除
+ unset($data['_r']);
+ }
if (empty($data) || empty($data['sign'])) {
mnbt_pay_log('易支付异步通知无数据或缺少 sign', '回调异常', $data['out_trade_no'] ?? '');
echo 'fail';
@@ -152,6 +166,8 @@ mnbt_register_route('GET', '/pay/epay/return', function ($params, $ctx) {
}
$c = epay_get_config();
$data = $_GET;
+ // 剔除路由参数 _r(不参与签名)
+ unset($data['_r']);
$ok = false;
if (!empty($data) && !empty($data['sign'])) {
$ok = Epay_Core::verifySign($data, $c['key'], (string)$data['sign']);
diff --git a/app_plugins/hosting_shop/bootstrap.php b/app_plugins/hosting_shop/bootstrap.php
index 570c8b1..6e5eea0 100644
--- a/app_plugins/hosting_shop/bootstrap.php
+++ b/app_plugins/hosting_shop/bootstrap.php
@@ -323,7 +323,7 @@ mnbt_register_route('POST', '/shop/api/create_order', function ($params, $ctx) {
hosting_json('支付方式不可用,请检查支付插件是否已启用');
}
- hosting_json('正在跳转到支付页面', ['html' => $html, 'order_no' => $order_no]);
+ hosting_json('ok', ['html' => $html, 'order_no' => $order_no]);
});
/* ============================================================
diff --git a/templates/tdesign/spa/src/account/api/plugins.js b/templates/tdesign/spa/src/account/api/plugins.js
index 7b9a215..7f271a4 100644
--- a/templates/tdesign/spa/src/account/api/plugins.js
+++ b/templates/tdesign/spa/src/account/api/plugins.js
@@ -26,17 +26,16 @@ export function centsToYuan(cents) {
/**
* 处理支付跳转响应(create_recharge / create_order 通用)
- * @returns {boolean} 是否已触发跳转(html 弹窗 / redirect 跳转)
+ * @returns {boolean} 是否已触发跳转(html 写入当前文档 / redirect 跳转)
*/
export function goPay(res) {
const data = res?.data || {}
if (data.html) {
- const win = window.open('', '_blank')
- if (win) {
- win.document.open()
- win.document.write(data.html)
- win.document.close()
- }
+ // 直接写入当前文档触发表单自动提交跳转支付页。
+ // 不能用 window.open('', '_blank'):经过 await 后已无用户手势,会被浏览器弹窗拦截导致不跳转。
+ document.open()
+ document.write(data.html)
+ document.close()
return true
}
if (data.redirect) {