From 6fcc120e91c0236281298b037a4d8e872a1b38b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Wed, 15 Jul 2026 22:51:47 +0800 Subject: [PATCH] =?UTF-8?q?fix(subscription):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E7=BB=AD=E8=B4=B9=E9=85=8D=E7=BD=AE=E6=9F=A5=E8=AF=A2=E8=A2=AB?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E9=9A=94=E7=A6=BB=E5=AF=BC=E8=87=B4=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修正 `MybatisPlusConfig.java` 中租户拦截器忽略表列表,新增 `"app_setting"` 以防止租户隔离导致配置查询失败 - 解决续费时 `platform_miniprogram` 配置查询因租户过滤返回空的问题,从而避免报“配置不存在或解析失败” - 复核 `app_setting` 表查询应无租户隔离,与代码注释设计意图保持一致 - 记录排查方法,使用 pymysql 连接远程数据库验证数据状态 - 纠正广告编辑保存逻辑,取消广告图片 URL 拼接 OSS 压缩处理后缀 - 修改 cmsAd 组件 `chooseFile` 函数,图片 URL 直接使用原始链接,不再添加图片压缩参数 - 保持其他 cms 组件未改动,根据用户需求仅调整广告相关逻辑 --- .workbuddy/memory/2026-07-15.md | 29 ++++++++++++++++++++ src/views/cms/cmsAd/components/cmsAdEdit.vue | 8 ++---- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/.workbuddy/memory/2026-07-15.md b/.workbuddy/memory/2026-07-15.md index d888ae7..57941c7 100644 --- a/.workbuddy/memory/2026-07-15.md +++ b/.workbuddy/memory/2026-07-15.md @@ -248,3 +248,32 @@ - max 逻辑对新订阅和续费都正确:新订阅 expireTime 为 null → expireBase=now → now+period;续费未过期 → 原+period(不丢时长);续费已过期 → now+period。 - 放弃支付现状:订阅保持 active+payStatus=0,服务不中断;用户可再次点"立即续费"重新 renew-pay(会覆盖 payPrice/period 并重新生成码)。无清理 pending 续费订单的需求(不再产生 pending 记录)。 - 前端无需改动(renew-pay 调用不变)。 + +## 续费"配置不存在"真正根因:app_setting 未加入租户忽略列表(已修复) + +- 纠正之前猜测:app_setting 表 platform_miniprogram 配置**完全正常**(pymysql 直查 db_websopy 确认:setting_id=12, tenant_id=5, 169字节, JSON 合法, appId=wx541db955e7a62709, appSecret 齐全)。 +- 真正根因:`MybatisPlusConfig.java` 的 `TenantLineHandler.ignoreTable` 列表里有 `app_subscription` 但**没有 `app_setting`**。 + - app_setting 查询受租户拦截器隔离 → `getByKey('platform_miniprogram')` 被自动加 `AND tenant_id=当前租户`。 + - 配置记录 tenant_id=5;续费用户租户 ≠ 5(或请求头/域名取不到租户)→ 查询过滤掉这条记录 → 返回 null → 报"配置不存在或解析失败"。 + - 订阅 pay 能用 = access_token 缓存命中(Redis key 固定 `WX_ACCESS_TOKEN:5` 不分租户,TTL 7000秒)没走 app_setting 查询;续费报错 = 缓存过期走了查询被拦截。与"之前还可以、现在不行"的时间差完全吻合。 + - `AppSettingServiceImpl` 代码注释明说"平台配置不按租户隔离"、getByKey 不带租户条件,但拦截器在 SQL 层强制隔离,两者矛盾——这是历史遗留 bug。 +- 修复(后端 `MybatisPlusConfig.java`):ignoreTable 列表在 `"app_subscription"` 后加 `"app_setting"`(一行改动)。改完 app_setting 所有查询忽略租户,与代码设计意图一致。 +- 排查方法值得记录:pymysql 直连远程库(47.119.165.234:13308 db_websopy / redis 16379 db0)验证数据;mysql 客户端未装时用 managed python venv 装 pymysql 查。dev profile 连此库。 +- 前端订阅 API 域名硬编码 `https://websopy-api.websoft.top/api/app/subscription`(api/index.ts WEBSOPY_API_BASE),主站 API 走 shop-api.websoft.top。用户对比的 `websoft.top/api/_app/...` 是另一个入口(疑 nginx 转发 _app→app)。 + +## 续费"弹二维码自动完成支付"修复:清除旧 Redis 支付标记 + +- 现象:续费 renew-pay 弹出小程序码后几秒,前端轮询 checkStatus 返回 paid=true,自动判定支付成功(用户没扫码)。 +- 根因(pymysql+redis 直查确认):续费复用原订阅记录的 subscriptionNo,原订阅支付时 mpConfirm/handleBalancePay 写入的 Redis 标记 `wxpay:paid:{subscriptionNo}=1`(TTL 30分钟)未清除。checkStatus 逻辑 `paidViaRedis || paidViaDb`,pay_status 维度(renewPay 设 0)已返回 false,但 Redis 维度残留 → 误判。 + - 数据证据:id=94 status=active pay_status=0 expire_time=2027-06-15(订阅支付成功→renewPay 改 pay_status=0);Redis wxpay:paid:SUB202607152237396107=1 残留。 +- 修复(方案A,用户确认):`AppSubscriptionController.renewPay` 在 updateById 后加 `redisUtil.delete("wxpay:paid:" + sub.getSubscriptionNo())`(RedisUtil.delete 在 line 214)。配合 pay_status=0,checkStatus 两个维度都 false → paid=false。 +- 次要问题(未解决):续费把原订阅 pay_status 1→0,若放弃支付,原订阅变 active+pay_status=0(语义"已激活但未支付"),不影响功能。彻底解决需方案C(renewPay 新建独立订阅记录,原订阅不动),暂不做。 +- 排查手段:managed python venv 装 pymysql+redis 直连远程库(47.119.165.234:13308/16379)查 app_subscription 表 + Redis scan wxpay:paid:*,比看日志更直接。 + +## cmsAd 编辑保存不再拼 OSS 压缩后缀 + +- 需求:广告编辑保存时图片 URL 不再拼接 `?x-oss-process=image/resize,m_fixed,w_2000/quality,Q_90` 后缀,因为图片压缩已统一在小程序端处理。 +- 改动 `src/views/cms/cmsAd/components/cmsAdEdit.vue` 的 `chooseFile` 函数: + - `images.value.push` 的 `url` 由 `data.downloadUrl + '?x-oss-process=...'` 改为 `data.downloadUrl`。 + - `form.images` 同步去掉后缀,直接用 `data.downloadUrl`。 +- 注意:本次只改广告(cmsAd);`cmsArticle/articleEdit.vue`、`cmsModel/cmsModelEdit.vue` 同样有此后缀,用户未提及,暂不动。 diff --git a/src/views/cms/cmsAd/components/cmsAdEdit.vue b/src/views/cms/cmsAd/components/cmsAdEdit.vue index c61fbcb..d3a0aa7 100644 --- a/src/views/cms/cmsAd/components/cmsAdEdit.vue +++ b/src/views/cms/cmsAd/components/cmsAdEdit.vue @@ -333,16 +333,12 @@ const chooseFile = (data: FileRecord) => { images.value.push({ uid: data.id, - url: - data.downloadUrl + - '?x-oss-process=image/resize,m_fixed,w_2000/quality,Q_90', + url: data.downloadUrl, status: 'done', title: '', // 初始化标题为空 path: '' // 初始化链接为空 }); - form.images = - data.downloadUrl + - '?x-oss-process=image/resize,m_fixed,w_2000/quality,Q_90'; + form.images = data.downloadUrl; }; const onDeleteItem = (index: number) => {