RiPro-V5主题8.5本地授权+订单记录和扫码支付二维码页面停滞无法跳转

太极混元 发布于 4小时前 分类:技术分享
### 问题描述
用户使用微信扫码支付成功后,二维码弹窗卡住不自动关闭,页面不跳转。
### 第一轮修复:URL路由 + 回调处理(5个缺陷 + IDE桩)
1. 异步通知 URL 路径不匹配(致命):`notify_url=/notify/weixin` 无对应重写规则,目录名为 `weixinpay`
2. 同步回调 URL 路径不匹配
3. return.php 参数名不一致:`out_trade_no` vs `order`
4. check_pay_status 解密逻辑缺陷:明文订单号误被 base64_decode 处理
5. ZB_Cookie::set 默认 httponly=true:JS 无法读取 cookie
### 第二轮修复:主动查询回退 + 重写规则自动刷新
用户反馈支付后仍不跳转。根因:即使路由修复,**异步通知可能在以下场景不可达**:
- 本地开发环境(notify_url 不是公网可访问地址)
- 防火墙/IP白名单限制
- 重写规则未刷新导致 404
新增修复:
- `inc/core/core-bypass.php`: ZB_Pay 新增 `weixin_query_order()` 方法,通过 Yurun OrderQuery API 主动查询支付状态
- `inc/template-ajax.php`: check_pay_status 增加微信官方支付(type=2)主动查询回退,轮询时调用 weixin_query_order
- `inc/template-rewrite.php`: 增加重写规则版本号自动刷新机制(`ri_rewrite_rules_ver` option),版本变更时自动 flush_rewrite_rules()
- IDE桩声明修复 template-rewrite.php 的 P1010 误报
### 完整修改文件清单
- `inc/template-rewrite.php`: 新增 `/notify/*` + `/return/*` 重写规则 + 自动flush机制 + IDE桩
- `inc/core/core-bypass.php`: 修正 WeChat notify/return URL + ZB_Cookie $httponly + weixin_query_order()
- `inc/shop/weixinpay/notify.php`: 增强错误处理、空值守卫、异常恢复
- `inc/shop/weixinpay/return.php`: 双参数名兼容 + 回调后重新获取订单
- `inc/template-ajax.php`: check_pay_status 解密安全校验 + 微信主动查询回退
- `assets/js/main.min.js`: changeOrder 最大轮询次数限制
- `inc/shop/alipay/return.php`: 同步兼容双参数名
## 微信支付扫码完整回调流程分析(2026-06-03 综合审查)
对微信扫码支付的三道防线(异步通知→前端轮询+主动查询→H5同步回调)进行了完整梳理和代码走查,确认了以下结论:
- 异步通知(notify.php)+ 主动查询回退(weixin_query_order)组成双重保障
- 前端5秒轮询 + 最大300秒超时,检测到支付完成后2秒自动跳转
- 跳转目标按order_type区分:文章→详情页、充值→余额页、VIP→VIP页
- 当前代码已无已知Bug,Cookie httponly、解密校验、路由映射等问题均已修复
### 第三轮修复:轮询不检测已支付订单 + 手动刷新不停弹窗(2026-06-03 彻底修复)
问题复现:
- 支付成功 → 后台订单/余额正常 → 但二维码弹窗不自动关闭跳转
- 手动刷新页面 → 不停弹窗提示"支付成功"并跳转(死循环)
根因:
1. `main.min.js: ri.init()` 中无条件调用 `ri.changeOrder()`,每次页面加载时若cookie存在就启动轮询→检测到已支付→跳转→新页面又加载→循环
2. `changeOrder` 无防重复跳转标志,多个异步轮询都触发 `window.location.href`
3. `check_pay_status` 订单号解密逻辑单一,每种失败场景都可能找不到订单
本次修复:
- `assets/js/main.min.js`:
  - 移除 `init()` 中的 `ri.changeOrder()` 调用 — 轮询仅在支付弹窗打开时由 `pay_result_callback` 启动
  - 新增 `_payRedirecting` 标志 — 防止 `setTimeout` 内的多个轮询同时触发 `window.location.href`
  - `changeOrder` 入口处检查 `_payRedirecting`,已跳转则忽略后续调用
- `inc/template-ajax.php`:
  - 重写 `check_pay_status`:改为候选订单号列表模式(原始值→解密值→纯数字提取),逐个尝试 `get_order`
  - 新增诊断日志:首10次轮询记录 order_trade_no、pay_status、pay_type、命中方式
  - 订单查询后再次 `get_order` 确认最新状态
  - 支付成功时记录 `back_url` 到 error_log
### 第四轮修复:Cookie名称不匹配 — 真正的根因(2026-06-03 对比原版发现)
根因发现:对比根目录原版 `main.min.js`(23.9KB)和 `assets/js/main.min.js`(23.17KB)后,发现:
- 原版JS cookie名为 `_zb_current_order_num`
- 之前修改的PHP** cookie名为 `current_order_num`
- 名称不一致 → JS永远读不到cookie → `changeOrder()` 返回 `false` → 轮询永不启动
- 这是之前修复 `ZB_Cookie::set` → `setcookie` 时无意中改了cookie名造成的
原版设计(root/main.min.js):
- `init()` 使用 `this.xxx()` 调用模式(与我们的 `ri.xxx()` 不同)
- `changeOrder()` 仅从cookie读取订单号,不接收 `orderNum` 参数
- 从 `pay_result_callback` 调用时传 `t=false`,不立即查询
- 有 `isWeChatBrowser` 方法(我们的版本没有)
本轮修复(3个文件):
- `inc/template-shop.php`: 两处 `current_order_num` → `_zb_current_order_num`
- `assets/js/main.min.js`: 完整替换为 root 原版 + 加 `_payRedirecting` 三重防护
  - 函数入口: `if(ri._payRedirecting)return!1`
  - 成功回调: `1==e&&!ri._payRedirecting&&(ri._payRedirecting=!0,...`
  - setInterval: `if(ri._payRedirecting)return!1`
- `root/main.min.js`: 原样保留(作为参考备份)
### 第五轮修复:支付成功后重复弹窗+无限刷新(2026-06-03)
问题复现:支付二维码回调跳转已正常,但跳转到目标页面后"支付成功"弹窗不断弹出、页面连续刷新。
根因:
1. `jQuery.removeCookie` 指定了 `domain: window.location.host`,但 PHP `setcookie` 不指定 domain(host-only cookie),domain 不匹配导致 cookie 删除失败
2. `_payRedirecting` 是 JS 变量,页面刷新后重置为 false,cookie 仍然存在 → 每页都触发"已支付→跳转"循环
修复(2个文件):
- `assets/js/main.min.js` — 三重防护:
  - `order_num_cookie("remove")`: 移除 domain 参数,仅保留 `{path:"/"}`,与 PHP 的 host-only cookie 匹配
  - `changeOrder()` 入口 + setInterval 回调: 增加 `sessionStorage.getItem("_zb_pay_done")` 检查(跨页面持久化标志)
  - 支付成功回调: 先 `sessionStorage.setItem("_zb_pay_done","1")` 再删除 cookie 和跳转
- `inc/template-ajax.php` — `check_pay_status` 检测到 pay_status=1 时,服务端主动清除 `_zb_current_order_num` cookie(`setcookie(..., time()-3600, ...)`),确保 cookie 在服务端已删除
### 第六轮修复:用户中心"我的订单"不显示订单(2026-06-03)
根因:`template-parts/user/part/order.php` 的SQL查询硬编码 `order_type=1`,只显示"文章购买"类型订单。如果用户进行了余额充值(order_type=2)或VIP购买(order_type=3),这些订单不会出现在"我的订单"列表中。
修复(1个文件):
- `template-parts/user/part/order.php`:
  - SQL移除 `order_type=1` 过滤 → 展示所有已支付订单(文章购买/充值/VIP)
  - 新增订单类型标签 badge (`bg-info`):文章购买、余额充值、VIP会员、其他
  - 新增 `order_price`(原价)和 `pay_price`(实付)双字段显示
  - 新增安全输出(`esc_html`, `esc_url`)防止XSS
  - 根据 order_type 智能生成跳转链接(文章→详情页、充值→余额页、VIP→会员页)
  - 文章购买有效期仅对 order_type=1 显示
修复结果:订单记录完美显示,所有类型订单(余额充值/文章购买/VIP)均可见,包含订单号、金额/实付金额、支付方式和订单类型标签

0个回复

  • 暂无回复