396 lines
14 KiB
Markdown
396 lines
14 KiB
Markdown
|
|
# KeyBoard 提审最终检查清单
|
|||
|
|
|
|||
|
|
更新时间:2026-03-08
|
|||
|
|
|
|||
|
|
适用目标:2026-03-09 准备提交 Apple App Store 审核
|
|||
|
|
|
|||
|
|
## 一、当前结论
|
|||
|
|
|
|||
|
|
基于当前代码、工程配置以及 Apple 截至 2026-03-08 的公开规则,这个项目现在不是“不能上”,而是仍然存在几项会明显拉低一次过审率的阻塞点。
|
|||
|
|
|
|||
|
|
如果今天不补,最可能的拒审方向仍然是:
|
|||
|
|
|
|||
|
|
1. `2.1 App Completeness`
|
|||
|
|
2. `5.1.1 Data Collection and Storage`
|
|||
|
|
3. `2.3.1 Accurate Metadata`
|
|||
|
|
4. `1.2 User-Generated Content`
|
|||
|
|
5. `3.1.2` / 订阅展示不完整
|
|||
|
|
|
|||
|
|
## 二、当前发现的问题
|
|||
|
|
|
|||
|
|
下面按严重程度排序。
|
|||
|
|
|
|||
|
|
### P0:法律文档仍是“未发布正式版”的回退状态
|
|||
|
|
|
|||
|
|
证据:
|
|||
|
|
|
|||
|
|
1. [KBConfig.h](/Users/mac/Desktop/项目/公司/KeyBoard/Shared/KBConfig.h#L76) 中 3 个正式 URL 仍然是空字符串:
|
|||
|
|
- `KB_TERMS_OF_SERVICE_URL`
|
|||
|
|
- `KB_PRIVACY_POLICY_URL`
|
|||
|
|
- `KB_MEMBERSHIP_AGREEMENT_URL`
|
|||
|
|
2. [KBWebViewViewController.m](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/WebView/KBWebViewViewController.m#L273) 到 [KBWebViewViewController.m](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/WebView/KBWebViewViewController.m#L284) 的内置 HTML 明确写着:
|
|||
|
|
- `Replace this fallback page ... before App Store submission`
|
|||
|
|
- `Built-in fallback document. Configure the final public URL ...`
|
|||
|
|
|
|||
|
|
风险:
|
|||
|
|
|
|||
|
|
1. 审核员点进协议/隐私/会员协议页面后,看到的是明显占位性质的回退文案。
|
|||
|
|
2. 这会直接伤到:
|
|||
|
|
- `2.1 App Completeness`
|
|||
|
|
- `2.3.1 Accurate Metadata`
|
|||
|
|
- `5.1.1`
|
|||
|
|
|
|||
|
|
解决方案:
|
|||
|
|
|
|||
|
|
1. 今天必须把 3 个 URL 换成正式线上地址。
|
|||
|
|
2. 正式页面必须可公开访问,不需要登录,不是占位页。
|
|||
|
|
3. 页面正文必须和真实数据流、App Privacy、Review Notes 完全一致。
|
|||
|
|
|
|||
|
|
结论:
|
|||
|
|
|
|||
|
|
这是当前最明确、最直接的提审阻塞项。
|
|||
|
|
|
|||
|
|
### P0:隐私披露与当前代码能力相比,明显不完整
|
|||
|
|
|
|||
|
|
证据:
|
|||
|
|
|
|||
|
|
1. 主 App 的 [PrivacyInfo.xcprivacy](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/PrivacyInfo.xcprivacy#L9) 目前只声明:
|
|||
|
|
- `EmailAddress`
|
|||
|
|
- `UserID`
|
|||
|
|
- `OtherUserContent`
|
|||
|
|
2. 键盘扩展的 [PrivacyInfo.xcprivacy](/Users/mac/Desktop/项目/公司/KeyBoard/CustomKeyboard/PrivacyInfo.xcprivacy#L9) 目前只声明:
|
|||
|
|
- `OtherUserContent`
|
|||
|
|
3. 但代码中已经能确认至少还涉及:
|
|||
|
|
- 语音录音上传转写
|
|||
|
|
[KBAIHomeVC.m](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/AiTalk/VC/KBAIHomeVC.m#L1238)
|
|||
|
|
[AiVM.m](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/AiTalk/VM/AiVM.m#L271)
|
|||
|
|
- 头像上传
|
|||
|
|
[KBMyVM.m](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/Me/VM/KBMyVM.m#L362)
|
|||
|
|
- 购买记录 / 钱包流水
|
|||
|
|
[KBMyVM.m](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/Me/VM/KBMyVM.m#L220)
|
|||
|
|
- Release 下 Bugly 崩溃收集
|
|||
|
|
[AppDelegate.m](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/AppDelegate.m#L93)
|
|||
|
|
- 可配置的埋点上报器
|
|||
|
|
[KBMaiPointReporter.h](/Users/mac/Desktop/项目/公司/KeyBoard/Shared/KBMaiPointReporter.h)
|
|||
|
|
|
|||
|
|
风险:
|
|||
|
|
|
|||
|
|
1. 代码实际行为、隐私政策、App Store Connect `App Privacy` 如果不一致,会非常容易被 `5.1.1` 打回。
|
|||
|
|
2. 对你这种“自定义键盘 + Full Access + AI + 语音”的组合,这一项是审核重点。
|
|||
|
|
|
|||
|
|
解决方案:
|
|||
|
|
|
|||
|
|
1. 今天必须做一张内部数据流表,确认以下数据到底是否收集、是否上传、是否保存、是否关联账号:
|
|||
|
|
- `Audio Data`
|
|||
|
|
- `Other User Content`
|
|||
|
|
- `Photos or Videos`
|
|||
|
|
- `Purchase History`
|
|||
|
|
- `Crash Data`
|
|||
|
|
- `Product Interaction`(如果 Release 真开埋点)
|
|||
|
|
2. 用这张表同时更新:
|
|||
|
|
- 隐私政策
|
|||
|
|
- App Store Connect `App Privacy`
|
|||
|
|
- 必要时更新 `PrivacyInfo.xcprivacy`
|
|||
|
|
3. 如果你拿不准 Bugly 和埋点,就先按“更保守的披露口径”处理。
|
|||
|
|
|
|||
|
|
结论:
|
|||
|
|
|
|||
|
|
这是当前第二个明确阻塞项,而且是被 Apple 追问概率非常高的一项。
|
|||
|
|
|
|||
|
|
### P0:键盘 `Full Access` 的用户可见披露仍然太泛
|
|||
|
|
|
|||
|
|
证据:
|
|||
|
|
|
|||
|
|
1. 键盘扩展开启了 `RequestsOpenAccess = true`
|
|||
|
|
[CustomKeyboard/Info.plist](/Users/mac/Desktop/项目/公司/KeyBoard/CustomKeyboard/Info.plist#L21)
|
|||
|
|
2. 当前引导文案还是:
|
|||
|
|
`Turn on Allow Full Access to experience all features`
|
|||
|
|
[KBFullAccessGuideView.m](/Users/mac/Desktop/项目/公司/KeyBoard/CustomKeyboard/View/KBFullAccessGuideView.m#L50)
|
|||
|
|
3. 但代码里已经存在:
|
|||
|
|
- 联网 AI 功能
|
|||
|
|
- 登录态依赖
|
|||
|
|
- 语音相关功能
|
|||
|
|
- 订阅能力
|
|||
|
|
|
|||
|
|
风险:
|
|||
|
|
|
|||
|
|
1. Apple 对第三方键盘的 `Full Access` 审核比普通 App 更敏感。
|
|||
|
|
2. 如果你只是告诉用户“开权限体验全部功能”,但没说清楚会发生什么,审核员会继续追问:
|
|||
|
|
- 开了 Full Access 后会不会上传输入内容
|
|||
|
|
- 哪些功能必须依赖 Full Access
|
|||
|
|
- 语音会不会上传服务器
|
|||
|
|
|
|||
|
|
解决方案:
|
|||
|
|
|
|||
|
|
1. App 内用户可见文案要补充说明:
|
|||
|
|
- 只有主动使用 AI / 语音 / 账号 / 订阅等联网能力时,相关数据才可能发送到服务器处理
|
|||
|
|
2. 隐私政策也要写同样的口径。
|
|||
|
|
3. Review Notes 必须单独解释:
|
|||
|
|
- 为什么键盘需要 Full Access
|
|||
|
|
- 哪些功能离不开 Full Access
|
|||
|
|
- 不开启时会看到什么
|
|||
|
|
|
|||
|
|
结论:
|
|||
|
|
|
|||
|
|
这项如果不补清楚,即使代码能跑,也很容易被当成隐私说明不足。
|
|||
|
|
|
|||
|
|
### P1:语音链路已经是“上传转写”,不能再按“仅本地语音输入”口径描述
|
|||
|
|
|
|||
|
|
证据:
|
|||
|
|
|
|||
|
|
1. 录音结束后会调用转写接口:
|
|||
|
|
[KBAIHomeVC.m](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/AiTalk/VC/KBAIHomeVC.m#L1238)
|
|||
|
|
2. `AiVM` 里明确存在上传音频文件并转写:
|
|||
|
|
[AiVM.m](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/AiTalk/VM/AiVM.m#L226)
|
|||
|
|
[AiVM.m](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/AiTalk/VM/AiVM.m#L271)
|
|||
|
|
3. 主 App 和扩展都声明了麦克风权限:
|
|||
|
|
[Info.plist](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Info.plist#L23)
|
|||
|
|
[Info.plist](/Users/mac/Desktop/项目/公司/KeyBoard/CustomKeyboard/Info.plist#L9)
|
|||
|
|
|
|||
|
|
风险:
|
|||
|
|
|
|||
|
|
1. 如果你后台和隐私政策没有按 `Audio Data` 相关能力申报,这会构成明显不一致。
|
|||
|
|
2. 现在权限默认文案已经改成更准确的英文,但这还不够;审核员更看重“你有没有明确说明上传转写”。
|
|||
|
|
|
|||
|
|
解决方案:
|
|||
|
|
|
|||
|
|
1. 隐私政策里明确写:
|
|||
|
|
- 语音是否上传
|
|||
|
|
- 是否只用于转写
|
|||
|
|
- 是否保存原始音频
|
|||
|
|
- 是否用于训练
|
|||
|
|
2. App Store Connect `App Privacy` 重新核对 `Audio Data`
|
|||
|
|
3. Review Notes 中说明“语音输入会调用服务端转写”
|
|||
|
|
|
|||
|
|
### P1:AI 内容安全有举报,但缺少可见的前置审核/拦截证据
|
|||
|
|
|
|||
|
|
证据:
|
|||
|
|
|
|||
|
|
1. 举报入口是存在的:
|
|||
|
|
[AIReportVC.m](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/AiTalk/VC/AIReportVC.m#L467)
|
|||
|
|
2. 举报接口也存在:
|
|||
|
|
[AiVM.m](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/AiTalk/VM/AiVM.m#L870)
|
|||
|
|
3. 但从当前代码里,没有看到足够明确的 AI 输出前置审核或策略拦截证据。
|
|||
|
|
|
|||
|
|
风险:
|
|||
|
|
|
|||
|
|
1. Apple 对 AI / 聊天 / persona 这类内容,会从 `1.1`、`1.2` 的角度看你是否有治理能力。
|
|||
|
|
2. 只有举报,没有审核/拦截说明,通常不够稳。
|
|||
|
|
|
|||
|
|
解决方案:
|
|||
|
|
|
|||
|
|
1. 你需要和后端确认:是否存在服务端内容审核。
|
|||
|
|
2. 如果有,Review Notes 里写清楚:
|
|||
|
|
- 有内容过滤
|
|||
|
|
- 有举报
|
|||
|
|
- 有处理机制
|
|||
|
|
3. 如果没有,建议先补服务端审核兜底再提。
|
|||
|
|
|
|||
|
|
结论:
|
|||
|
|
|
|||
|
|
这是“中高风险但代码里不一定能完全解决”的问题,取决于你后端现在是否已经有审核。
|
|||
|
|
|
|||
|
|
### P1:Review Notes、测试账号、审核路径说明无法从工程内验证
|
|||
|
|
|
|||
|
|
风险:
|
|||
|
|
|
|||
|
|
1. 这是键盘类 App 的典型拒审来源,不在代码里,但对过审非常关键。
|
|||
|
|
2. 审核员如果没走对路径,会直接判:
|
|||
|
|
- 功能不可用
|
|||
|
|
- 无法完成登录
|
|||
|
|
- 无法完成购买
|
|||
|
|
|
|||
|
|
解决方案:
|
|||
|
|
|
|||
|
|
1. 你必须在 App Store Connect 手工准备:
|
|||
|
|
- 测试账号
|
|||
|
|
- 启用键盘步骤
|
|||
|
|
- 开启 Full Access 步骤
|
|||
|
|
- 登录步骤
|
|||
|
|
- AI 使用路径
|
|||
|
|
- 购买和恢复购买路径
|
|||
|
|
- 哪些操作会拉起主 App
|
|||
|
|
|
|||
|
|
结论:
|
|||
|
|
|
|||
|
|
这项虽然不是代码 bug,但如果你明天就提,这是必须完成的外部阻塞项。
|
|||
|
|
|
|||
|
|
## 三、当前已具备的正向项
|
|||
|
|
|
|||
|
|
这些不是问题,属于可加分或至少不拖后腿的项:
|
|||
|
|
|
|||
|
|
1. 账号注销能力存在
|
|||
|
|
[KBCancelAccountVC.m](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/Me/VC/KBCancelAccountVC.m#L82)
|
|||
|
|
[KBMyVM.m](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/Me/VM/KBMyVM.m#L519)
|
|||
|
|
2. 订阅管理能力存在
|
|||
|
|
[StoreKitService.swift](/Users/mac/Desktop/项目/公司/KeyBoard/keyBoard/Class/Pay/StoreKit2Manager/Internal/StoreKitService.swift#L823)
|
|||
|
|
3. 协议入口已经打通,不再是空实现
|
|||
|
|
4. 麦克风权限 fallback 文案已经统一成准确英文
|
|||
|
|
5. AI 举报链路存在
|
|||
|
|
|
|||
|
|
## 四、明天前必须完成的清单
|
|||
|
|
|
|||
|
|
下面这部分按“必须完成 / 最好完成”分。
|
|||
|
|
|
|||
|
|
### A. 必须完成
|
|||
|
|
|
|||
|
|
#### A1. 正式法律文档上线
|
|||
|
|
|
|||
|
|
- [ ] 填写 `KB_TERMS_OF_SERVICE_URL`
|
|||
|
|
- [ ] 填写 `KB_PRIVACY_POLICY_URL`
|
|||
|
|
- [ ] 填写 `KB_MEMBERSHIP_AGREEMENT_URL`
|
|||
|
|
- [ ] 真机点开 3 个页面,确认不是 fallback HTML
|
|||
|
|
- [ ] 浏览器外部访问 3 个 URL,确认审核员在外部也能打开
|
|||
|
|
|
|||
|
|
#### A2. 隐私披露一致化
|
|||
|
|
|
|||
|
|
- [ ] 确认 `Audio Data` 是否收集、是否保存
|
|||
|
|
- [ ] 确认键盘 AI 输入文本是否会上传、是否保存
|
|||
|
|
- [ ] 确认头像上传是否需要申报 `Photos or Videos`
|
|||
|
|
- [ ] 确认购买记录 / 订阅状态是否申报 `Purchase History`
|
|||
|
|
- [ ] 确认 Release 下 Bugly 是否视为 `Crash Data`
|
|||
|
|
- [ ] 如果 Release 开启埋点,确认是否申报 `Product Interaction`
|
|||
|
|
- [ ] 完成 App Store Connect `App Privacy` 填写
|
|||
|
|
- [ ] 确保隐私政策正文和后台填写一致
|
|||
|
|
|
|||
|
|
#### A3. Full Access 和语音说明补清楚
|
|||
|
|
|
|||
|
|
- [ ] 在 App 内明确说明 Full Access 与联网功能关系
|
|||
|
|
- [ ] 明确说明语音会进行服务器转写
|
|||
|
|
- [ ] Review Notes 解释 Full Access 的必要性和作用边界
|
|||
|
|
|
|||
|
|
#### A4. Review Notes 和测试账号准备完成
|
|||
|
|
|
|||
|
|
- [ ] 提供审核账号
|
|||
|
|
- [ ] 写清启用键盘路径
|
|||
|
|
- [ ] 写清打开 Full Access 路径
|
|||
|
|
- [ ] 写清登录路径
|
|||
|
|
- [ ] 写清购买路径
|
|||
|
|
- [ ] 写清恢复购买路径
|
|||
|
|
- [ ] 写清哪些操作会拉起主 App
|
|||
|
|
|
|||
|
|
### B. 最好今天也完成
|
|||
|
|
|
|||
|
|
- [ ] 后端确认 AI 内容审核是否已开启
|
|||
|
|
- [ ] Review Notes 里写明有举报和内容治理机制
|
|||
|
|
- [ ] 检查商店描述里是否有夸大键盘能力的文案
|
|||
|
|
- [ ] 核对订阅名称、周期、价格、试用和 App Store Connect 一致
|
|||
|
|
|
|||
|
|
## 五、今晚的检查方案
|
|||
|
|
|
|||
|
|
建议按下面顺序做,不要乱跳。
|
|||
|
|
|
|||
|
|
### 第 1 轮:配置检查
|
|||
|
|
|
|||
|
|
目标:先排除“点进去就是错的”问题。
|
|||
|
|
|
|||
|
|
步骤:
|
|||
|
|
|
|||
|
|
1. 检查 3 个法律文档 URL 是否已经填正式地址
|
|||
|
|
2. 检查主 App 和扩展的 `Info.plist` 权限文案
|
|||
|
|
3. 检查 `PrivacyInfo.xcprivacy`
|
|||
|
|
4. 检查 Release 配置下是否保留 Bugly / 埋点
|
|||
|
|
|
|||
|
|
通过标准:
|
|||
|
|
|
|||
|
|
1. 没有 fallback URL
|
|||
|
|
2. 没有 placeholder 文案
|
|||
|
|
3. 没有明显和真实行为冲突的隐私声明
|
|||
|
|
|
|||
|
|
### 第 2 轮:真机功能链路检查
|
|||
|
|
|
|||
|
|
目标:按审核员路径完整走一遍。
|
|||
|
|
|
|||
|
|
步骤:
|
|||
|
|
|
|||
|
|
1. 卸载旧包,重新安装
|
|||
|
|
2. 首次启动
|
|||
|
|
3. 注册 / 登录
|
|||
|
|
4. 启用键盘
|
|||
|
|
5. 打开 Full Access
|
|||
|
|
6. 进入任意聊天/输入场景,切换到你的键盘
|
|||
|
|
7. 触发 AI 功能
|
|||
|
|
8. 触发语音功能
|
|||
|
|
9. 从键盘拉起主 App 登录
|
|||
|
|
10. 从键盘拉起主 App 购买
|
|||
|
|
11. 恢复购买
|
|||
|
|
12. 打开隐私政策 / 服务条款 / 会员协议
|
|||
|
|
13. 注销账号
|
|||
|
|
|
|||
|
|
通过标准:
|
|||
|
|
|
|||
|
|
1. 整条路径没有卡死、空白页、无响应
|
|||
|
|
2. 所有异常都有用户能理解的提示
|
|||
|
|
|
|||
|
|
### 第 3 轮:异常场景检查
|
|||
|
|
|
|||
|
|
目标:避免审核员踩到异常直接拒审。
|
|||
|
|
|
|||
|
|
步骤:
|
|||
|
|
|
|||
|
|
1. 未登录时进 AI
|
|||
|
|
2. 未开 Full Access 时进联网能力
|
|||
|
|
3. 断网时使用 AI / 购买 / 登录
|
|||
|
|
4. 服务端返回错误时看提示是否明确
|
|||
|
|
5. IAP 商品加载失败时看是否有兜底
|
|||
|
|
|
|||
|
|
通过标准:
|
|||
|
|
|
|||
|
|
1. 不出现无提示失败
|
|||
|
|
2. 不出现 reviewer 无法理解的状态
|
|||
|
|
|
|||
|
|
### 第 4 轮:提审物料检查
|
|||
|
|
|
|||
|
|
目标:把代码外的审核材料准备齐。
|
|||
|
|
|
|||
|
|
步骤:
|
|||
|
|
|
|||
|
|
1. 完成 App Store Connect `App Privacy`
|
|||
|
|
2. 准备 Review Notes
|
|||
|
|
3. 准备测试账号
|
|||
|
|
4. 检查商店截图和描述
|
|||
|
|
5. 检查订阅商品配置
|
|||
|
|
|
|||
|
|
通过标准:
|
|||
|
|
|
|||
|
|
1. 审核员不需要猜你产品流程
|
|||
|
|
2. 元数据和真实能力一致
|
|||
|
|
|
|||
|
|
## 六、明天提审当天的执行顺序
|
|||
|
|
|
|||
|
|
建议顺序:
|
|||
|
|
|
|||
|
|
1. 先确认线上法律文档已经发布
|
|||
|
|
2. 再核对 App Store Connect 的 `App Privacy`
|
|||
|
|
3. 再写 Review Notes
|
|||
|
|
4. 再做一次真机完整走查
|
|||
|
|
5. 最后 Archive / 上传 / 提交审核
|
|||
|
|
|
|||
|
|
不要反过来先提交再补文案。
|
|||
|
|
|
|||
|
|
## 七、我给你的最终判断
|
|||
|
|
|
|||
|
|
如果你明天提审之前把下面 4 件事补完:
|
|||
|
|
|
|||
|
|
1. 正式法律文档 URL 与正文
|
|||
|
|
2. App Privacy 与隐私政策完全对齐
|
|||
|
|
3. Review Notes + 测试账号
|
|||
|
|
4. Full Access / 语音上传 / AI 内容安全说明
|
|||
|
|
|
|||
|
|
这次的送审质量会比你现在直接提交高很多。
|
|||
|
|
|
|||
|
|
如果这 4 件事中有 2 件以上没完成,我不建议明天直接提。
|
|||
|
|
|
|||
|
|
## 八、官方参考
|
|||
|
|
|
|||
|
|
1. App Review Guidelines
|
|||
|
|
https://developer.apple.com/app-store/review/guidelines/
|
|||
|
|
2. App Privacy Details
|
|||
|
|
https://developer.apple.com/app-store/app-privacy-details/
|
|||
|
|
3. App Privacy(App Store Connect Help)
|
|||
|
|
https://developer.apple.com/help/app-store-connect/reference/app-privacy
|
|||
|
|
4. Offering account deletion in your app
|
|||
|
|
https://developer.apple.com/support/offering-account-deletion-in-your-app/
|
|||
|
|
5. Custom Keyboard Guide
|
|||
|
|
https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/CustomKeyboard.html
|