From 60399e96dbf26407b6e4b1eb26fc1b23faf6c419 Mon Sep 17 00:00:00 2001 From: API Changelog Bot Date: Tue, 5 May 2026 18:01:05 +0800 Subject: [PATCH] =?UTF-8?q?frontend(mmg):=20wx=20=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E5=AE=89=E5=85=A8=E6=96=B9=E6=A1=88=E5=89=8D=E7=AB=AF=E9=9B=86?= =?UTF-8?q?=E6=88=90=E6=8C=87=E5=8D=97=20(Phase=201-2E=20=E5=85=A8?= =?UTF-8?q?=E9=93=BE=E8=B7=AF=205=20PR=20+=20Hotfix=20#1670)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...05_frontend_mmg_wx-security-integration.md | 280 ++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 changelogs/2026-05/05_frontend_mmg_wx-security-integration.md diff --git a/changelogs/2026-05/05_frontend_mmg_wx-security-integration.md b/changelogs/2026-05/05_frontend_mmg_wx-security-integration.md new file mode 100644 index 0000000..dd6844e --- /dev/null +++ b/changelogs/2026-05/05_frontend_mmg_wx-security-integration.md @@ -0,0 +1,280 @@ +# frontend(mmg): 微信内容安全方案 — 前端集成指南 + +**关联 PR**: #1659 #1661 #1667 #1666 #1668 #1669(全 5 Phase 已合 dev) +**日期**: 2026-05-05 +**对接人**: mmg + +后端方案已全链路闭环,前端需要按本指南接入新接口 + 调整 body/响应字段。本指南是 5 个 Phase 的整合视图,不需要去翻散落的 changelog。 + +--- + +## 一、新增接口(前端直接调) + +### 1. `POST /mp/security/text-check` 文本同步机审 + +提交评价/投诉/反馈/姓名修改等含用户输入文本的业务前,**先调本接口**拿审核结果决定是否拦截。 + +**请求**: +```js +http.post('/mp/security/text-check', { + content: "用户提交的文本内容", // 必填,≤2500 字 + scene: 2 // 必填:1=资料/2=评论/3=论坛/4=社交日志 +}) +``` + +**响应**: +```json +{ + "code": 200, + "data": { + "pass": true, + "suggest": "pass", // pass / review / risky / pass-degraded + "label": 100, // Integer 类型,100=正常 + "traceId": "xxx", + "degraded": false, + "detail": null // 命中时是关键词摘要字符串 + } +} +``` + +**前端拦截规则**: +- `pass=true` 或 `suggest=pass` → 放行 +- `suggest=review` → toast「内容疑似违规,请修改后重试」+ 阻断 +- `suggest=risky` → toast「内容包含违规信息,请修改」+ 阻断 +- `suggest=pass-degraded` 或网络异常 → **降级放行**(不阻断业务,后端事后人工兜底) + +### 2. `POST /mp/security/media-check` 媒体异步机审 + +图片/音频上传到 OSS 后,**调本接口拿 traceId**,把 traceId 数组随业务 API 提交。 + +**请求**: +```js +http.post('/mp/security/media-check', { + mediaUrl: "https://oss.example.com/xxx.jpg", // 必填,已上传 OSS 的 https URL + mediaType: "image" // 必填:image / audio +}) +``` + +**响应**: +```json +{ + "code": 200, + "data": { + "traceId": "967e945cd8a3e458effc23eb0e7c84e1" // 失败时为 null + } +} +``` + +**前端使用**: +- 同步只返 `traceId`,**不阻断业务提交**(异步审核) +- traceId 收集到数组里,业务 API 提交时随 `mediaTraceIds` 字段传给后端 +- traceId=null(降级)时仍然继续业务,后端按未审核处置 + +--- + +## 二、业务 API body 新增 `mediaTraceIds` 字段(5 个接口) + +| 业务接口 | body 新增字段 | +|---|---| +| `POST /mp/review/create` 评价 | `mediaTraceIds: string[]` | +| `POST /mp/complaint/create` 投诉 | `mediaTraceIds: string[]` | +| `POST /mp/order/{orderId}/refund` 退款 | `mediaTraceIds: string[]` | +| `POST /mp/order/refund/{appId}/appeal` 申诉 | `mediaTraceIds: string[]` | +| `POST /mp/order/refund/{orderId}/direct-appeal` 直接申诉 | `mediaTraceIds: string[]` | +| `POST /mp/common/feedback` 客服反馈 | `mediaTraceIds: string[]` | + +**例**: +```js +// 评价提交流程 +const traceIds = [] +for (const url of uploadedImageUrls) { + const r = await http.post('/mp/security/media-check', { mediaUrl: url, mediaType: 'image' }) + if (r.data.traceId) traceIds.push(r.data.traceId) // null 时跳过即可 +} +await http.post('/mp/review/create', { + orderId: '...', + content: '评价文本', + images: uploadedImageUrls, + mediaTraceIds: traceIds // 新加字段 +}) +``` + +未传 `mediaTraceIds` 的接口(发票/退款理由/昵称/姓名)按无图处理,不影响。 + +--- + +## 三、查询响应新增字段 + +### `/mp/review/my` 我的评价列表 + 详情 + +VO 新增 2 字段(私有列表才返,公开列表后端已自动过滤未审核内容): + +```jsonc +{ + "id": "...", + "content": "...", + "rating": 5, + "auditStatus": "MANUAL_REVIEW", // 新增 (Phase 2A): wx 内容安全机审状态 + "reportStatus": "NORMAL", // 新增 (Phase 2B): 举报状态 + "hiddenReason": null, // 新增 (Phase 2B): HIDDEN 时返回隐藏原因 + "createdAt": "..." +} +``` + +**前端展示状态条文案**: + +| auditStatus | 状态条 | +|---|---| +| `PENDING` | 「审核中,通过后展示」灰色 | +| `APPROVED` | (无提示,正常展示) | +| `MANUAL_REVIEW` | 「审核中,预计 24h 内」黄色 | +| `REJECTED` | 「内容未通过审核」红色 + 重新编辑按钮 | + +| reportStatus | 状态条 | +|---|---| +| `NORMAL` | (无提示) | +| `PENDING_REVIEW` | (无提示,仍展示) | +| `HIDDEN` | 「该评价已下架」+ `hiddenReason` | + +**公开列表**(产品评价/首页精选/旅行相册)后端已强制过滤 `audit_status='APPROVED' AND report_status!='HIDDEN'`,前端**无需特殊处理**。 + +--- + +## 四、新接口:评价举报 `POST /mp/review/report` + +```js +http.post('/mp/review/report', { + reviewId: '101010101010', // String 雪花 ID(必填,严禁 Number) + reason: 'SPAM', // 必填,字典 review_report_reason + detail: '广告链接,引导外部' // 可选(≤500 字) +}) +``` + +**reason 字典**(建议从 `dict.getList('review_report_reason')` 取,避免硬编码): + +| reason | 文案 | +|---|---| +| `SPAM` | 广告/营销 | +| `INSULT` | 辱骂/人身攻击 | +| `PORN` | 色情低俗 | +| `POLITICS` | 政治敏感 | +| `FAKE` | 虚假评价 | +| `LEAK_PRIVACY` | 泄露他人隐私 | +| `OTHER` | 其他 | + +**响应**: 成功 200 / 失败业务码: + +| code | 文案 | 处理 | +|---|---|---| +| 551001 | 举报原因无效 | toast | +| 551002 | 今日举报次数已达上限 | toast,引导明日再来 | +| 551003 | 评价不存在 | toast | +| 551004 | 不能举报自己的评价 | toast | +| 551005 | 您已举报过该评价 | toast | +| 551006 | 无法识别用户身份,请重新登录 | 引导重新登录 | + +举报后业务流程: +- 同 review 累计举报 ≥3 次 → `report_status=PENDING_REVIEW`(用户侧仍可见,运营人工审核中) +- ≥10 次且 24h 内 → 自动 `HIDDEN`(用户侧立即下架) +- 命中举报触发再机审:risky → 强制 HIDDEN + +--- + +## 五、出行人姓名(前端不做硬拦截) + +按官方契约 §8,姓名是实名信息,**前端不应做内容机审**(怕误伤真实姓「操/苟」、少数民族罕字、港澳台/外籍拼音)。 + +**前端不需要改**: +- ❌ 不要在创建出行人前调 text-check +- ❌ 不要本地正则/黑名单拦截 + +**后端三层兜底已自动处理**: +- 第 1 层:异步机审(不阻塞业务,命中标 MANUAL_REVIEW 不删数据) +- 第 2 层:下单选出行人时**仅挡 REJECTED**(人工裁决),其他状态全放行 +- 第 3 层:本地正则(长度/字符集/重复字符防垃圾) + +**新增错误码**(出行人下单时): +| code | 文案 | +|---|---| +| 100701 | 姓名长度异常(2-30 字符) | +| 100702 | 姓名含非法字符 | +| 100703 | 姓名含敏感词 | +| 100704 | 姓名格式不正确 | +| 100705 | 此出行人信息异常,请联系客服核实 | + +同款适用:紧急联系人 / 用户实名。 + +--- + +## 六、头像 / 昵称(前端流程同现状) + +- **昵称**:前端调 text-check 文本同步机审(按"一"节流程),命中拦截 +- **头像**:前端 `fileApi.upload` 上传 OSS → `securityApi.checkMedia` 拿 traceId → `userApi.updateUserInfo({avatar})` **不传 traceId**(后端会在 /mp/file/upload 内部异步审,traceId 关联到 fileId 后通过 webhook 自动反查 user 表) + +REJECTED 时后端自动重置默认头像,前端展示用户资料时拿到的就是已重置后的 URL。 + +--- + +## 七、调用顺序总结 + +### 评价/投诉/退款申诉 (含图) +``` +1. 用户填表(选图) +2. 图上传 OSS → 拿 url[] +3. 文本调 /mp/security/text-check → 拿 suggest 决定是否阻断 +4. 每张图调 /mp/security/media-check → 收集 traceId[] +5. 业务接口提交 (body 含 mediaTraceIds) +``` + +### 客服反馈 / 心愿单 / 备注 (仅文本) +``` +1. 用户填表 +2. 调 /mp/security/text-check → 决定阻断 +3. 业务接口提交 (body 不含 mediaTraceIds) +``` + +### 用户昵称 +``` +1. 用户填昵称 +2. 调 /mp/security/text-check → 决定阻断 +3. /mp/user/profile 提交 +``` + +### 用户头像 +``` +1. 上传 OSS +2. 调 /mp/security/media-check → 拿 traceId (失败也继续) +3. /mp/user/profile 提交 avatar (不传 traceId) +``` + +### 出行人 +``` +1. 用户填姓名 +2. /mp/user/traveler 直接提交 (前端不调 security) +3. 后端三层兜底自动处理 +``` + +--- + +## 八、降级容错 + +任何 `/mp/security/*` 接口 5xx 或网络异常: +- 前端按 **降级放行** 处理(不阻断业务) +- 用户体验优先于绝对合规 +- 后端会通过 `pass-degraded` 标记记录,事后人工兜底审核 + +--- + +## 九、前端工作量预估 + +按本指南改前端约: +- 通用工具:`utils/contentSecurity.js` + `utils/ugc.js` 包装 text-check / media-check(已有则更新) +- 6 个业务页面调用点:评价提交 / 投诉提交 / 退款申请 / 申诉提交 / 客服反馈 / 心愿提交 +- 评价列表:私有列表加状态条文案(auditStatus / reportStatus) +- 评价举报新页面:调 /mp/review/report +- 字典:拉 review_report_reason 字典做举报原因下拉 +- 头像/昵称:检查现有流程是否已按上述顺序 + +--- + +@mmg 有任何疑问随时找我。后端已部署到 dev 分支,等运维 nacos 配 wechat.miniapp.webhook.token 后即可联调。