Skill: mobsupport/ios-flyverify-integration (version 1.0.0)

--- name: ios-flyverify-integration description: 面向 iOS 工程的 MobTech FlyVerify(秒验) 集成 skill。默认先扫描工程，优先使用 CocoaPods，以最小改动完成依赖接入、隐私合规、一键登录流程接线和项目内说明文档落地。 tags: - ios - flyverify - 秒验 - sdk-integration - mobtech - one-click-login - cocoapods - privacy - objective-c - swift --- # iOS FlyVerify 集成 Skill 当用户希望把 MobTech FlyVerify 集成到 iOS 工程，或者排查已有 FlyVerify 接入问题时，使用本 skill。 ## 适用场景 当用户提到以下任一主题时，使用本 skill： - iOS FlyVerify 集成 - iOS 秒验接入 - iOS 一键登录 - MobTech 秒验一键登录 - FlyVerify CocoaPods 配置 - FlyVerify `Info.plist` 配置 - FlyVerify 隐私合规 - `agreePrivacy` 调用时机 - `preLogin` / `openAuthPageWithModel` 用法 - 秒验授权页自定义 - 秒验 token 置换手机号 - 帮我在 iOS 项目里增加一键登录 - 帮我把 FlyVerify 接进现有 iOS 工程 如果用户问题明确与 iOS 秒验接入、工程配置、隐私合规、一键登录流程或授权页 UI 定制有关，应优先使用本 skill。 ## 输出语言 - 默认使用中文与用户沟通 - 代码、配置键名、类名、命令名保持原文 - 回答尽量短，先给结论，再给动作 ## 官方资料 优先使用以下线上资料，不依赖本机资料路径： 主文档： - [MobTech 文档中心](https://www.mob.com/wiki/list) - [秒验产品页](https://www.mob.com/mobService/secverify) - [SDK 下载中心](https://www.mob.com/download) - [集成指南](https://www.mob.com/wiki/detailed?wiki=531&id=78) - [SDK API 文档](https://www.mob.com/wiki/detailed?wiki=297&id=78) - [合规指南](https://www.mob.com/wiki/detailed?wiki=217&id=78) - [秒验隐私政策](https://policy.zztfly.com/sdk/verify/privacy) - [创建应用流程](https://www.mob.com/wiki/detailed?wiki=538&id=78) - [秒验审核流程](https://www.mob.com/wiki/detailed?wiki=159&id=78) - [服务端接入文档](https://www.mob.com/wiki/detailed?wiki=157&id=78) - [秒验 SDK 扩展业务功能设置](https://www.mob.com/wiki/detailed?wiki=669&id=78) - [其它 App 数据采集主动控制器配置](https://www.mob.com/wiki/detailed?wiki=675&id=714) - [App Store Connect 后台配置参考文档](https://www.mob.com/wiki/detailed?wiki=289&id=172) - [秒验 Demo](https://github.com/MobClub/FlyVerify_For_iOS) 如果某个深链失效，先从 [MobTech 文档中心](https://www.mob.com/wiki/list) 搜索对应标题，不要回退到本机绝对路径。 ## 已确认的官方事实 以下信息已经可作为执行依据，不需要再猜测： - 默认开发环境要求为 `Xcode 9.1.0+`、`iOS 8.0+` - 官方支持 `CocoaPods` 和手动导入两种集成方式 - 默认 Pod 为 `pod 'FlyVerify'` - 工程需要链接 `libsqlite3.tbd`、`libc++.tbd`、`libz.1.2.5.tbd` - `Other Linker Flags` 需要添加 `-ObjC` - `Info.plist` 需要配置 `flyverifykey` 与 `flyverifysecret` - 严格隐私模式需要在默认 `plist` 中添加 `FlyVerifyPLevel = 2` - 如果项目全局禁止 HTTP，需要为以下域名配置 ATS 白名单： - `zzx9.cn` - `cmpassport.com` - `id6.me` - `wostore.cn` - `mdn.open.wo.cn` - `agreePrivacy` 是 FlyVerify 业务起点，必须在用户同意隐私政策后、使用 SDK 能力前调用 - `preLogin` 回调在全局队列，`error == nil` 才视为成功 - `openAuthPageWithModel` 的 `uiConfigure.currentViewController` 为必传 - 授权页关闭可由 SDK 自动处理，也可通过 `manualDismiss = @(YES)` 后手动调用 `finishLoginVcAnimated:Completion:` - 一键登录成功后 SDK 返回 `opToken`、`operator`、`token` - 真实手机号需要开发者服务端调用秒验服务端接口完成置换，客户端不能直接得到手机号 - 一键登录能力依赖运营商网关取号，必须在手机开启移动蜂窝网络时使用 - 文档明确建议授权页 UI 定制参考官方 Demo - 严格隐私模式和隐私 API 支持情况必须结合线上合规文档与当前 `Podfile.lock` 中实际安装版本确认，不要只凭本地缓存判断 - 接入代码必须同时支持 Objective-C 与 Swift 工程；Swift 工程优先通过桥接头调用官方 Objective-C API ## 文档未明确，需向用户确认 以下内容在当前资料里没有被稳定、明确地定义，禁止猜： - 是否支持 Swift Package Manager - 是否需要 Bitcode、Privacy Manifest 或额外苹果隐私文件 - 用户项目应该使用 `Info.plist` 配置读取，还是代码显式 `initKey:[REDACTED_SECRET]` - 用户具体要不要开启授权页自定义 如果缺这些信息且会阻塞安全修改，必须明确写： `文档未明确，需向用户确认` ## 默认执行策略 - 默认集成方式：`CocoaPods` - 默认先扫描工程，再给改动方案 - 默认优先复用工程已有隐私弹窗和登录入口，不新造页面 - 默认先生成最小 Excel 模板，再等用户填写 - 默认不在 Excel 中收集 `Bundle ID`、Target 名称、入口类名、`Info.plist` 路径，因为这些应由扫描工程自动推断 - 默认把 FlyVerify 能力接入放在用户已同意隐私政策之后 - 默认不主动询问是否启用扩展业务主动控制器；仅在最终项目文档中说明这项可选能力 - 服务端 token 置换接口属于后续业务步骤，本轮客户端集成只保留注释占位，不追问接口域名、鉴权方式或返回结构 - 默认不运行 `pod install`、`xcodebuild` 或其他会改动依赖状态的命令，先展示计划，再执行 - 默认不把 `Pods/` 提交进项目；如项目未忽略 `Pods/`，补充 `.gitignore`，保留 `Podfile` 与 `Podfile.lock` - 一次只问用户一个阻塞问题 ## 执行流程 严格按以下顺序推进： 1. 先扫描工程，再判断接入方式。 2. 先生成或读取配置模板，再确定静态配置。 3. 先展示最小改动计划，再修改文件。 4. 依赖安装前先征求确认。 5. 完成后补项目内说明文档。 ## 第一步：扫描工程 优先扫描以下内容： - `.xcodeproj` / `.xcworkspace` - `Podfile` - `Podfile.lock` - `Package.swift` - `AppDelegate` / `SceneDelegate` / SwiftUI `@main` - `Info.plist` - 隐私政策弹窗或同意回调位置 - 登录页、手机号登录页、现有一键登录入口 - Objective-C / Swift / 混编类型，以及是否已有 Bridging Header - 是否已有 `FlyVerify`、`FVSDKHyVerify`、`FlyVerifyC`、`flyverifykey`、`flyverifysecret`、`FlyVerifyPLevel` - `.gitignore` 是否忽略 `Pods/` - `.xcworkspace` 是否包含 `contents.xcworkspacedata` 推荐命令： - `rg --files -g '*.xcodeproj' -g '*.xcworkspace' -g 'Podfile' -g 'Podfile.lock' -g 'Package.swift' -g '*Info.plist' -g '.gitignore'` - `rg --files -g '*.m' -g '*.h' -g '*.mm' -g '*.swift'` - `rg -n 'FlyVerify|FVSDKHyVerify|FlyVerifyC|flyverifykey|flyverifysecret|FlyVerifyPLevel|agreePrivacy|preLogin|openAuthPageWithModel|SWIFT_OBJC_BRIDGING_HEADER'` 扫描后先给一段简短结论，至少包含： - 当前工程依赖方式 - 当前入口结构 - 当前代码语言形态：Objective-C / Swift / 混编 - Swift 工程是否已有 Bridging Header - 是否已有 FlyVerify 残留 - 是否已经有隐私同意链路 - CocoaPods 状态：是否有有效 `Podfile`、`Podfile.lock`、`Pods/`、`*.xcworkspace/contents.xcworkspacedata` - 下一步是生成模板还是读取已有 `FlyVerify_iOS_Config.xlsx` ## 第二步：生成并读取配置模板 ### 2-1 模板生成 如果用户项目根目录还没有 `FlyVerify_iOS_Config.xlsx`： 1. 运行本 skill 目录下的 `assets/generate_excel_template.py` 2. 将生成的 `assets/FlyVerify_iOS_Config_Template.xlsx` 复制到用户项目根目录 3. 在用户项目根目录命名为 `FlyVerify_iOS_Config.xlsx` ### 2-2 向用户说明填写项 必须明确告诉用户只需要填写这些最小字段： - `appKey` - `appSecret` - 秒验审核是否已通过 - 是否需要自定义授权页 同时明确说明以下内容不需要填表： - `Bundle ID` - `Target` - `Info.plist` 路径 - 隐私弹窗类名 - 授权页按钮落点 - 是否启用扩展业务主动控制器 其中工程信息应由 Agent 扫描后推断；扩展业务主动控制器不作为前置配置项，只在最终文档中说明。 ### 2-3 配置校验 读取 `FlyVerify_iOS_Config.xlsx` 后，至少校验： - `appKey`：必填，按字符串处理，不做数值推断 - `appSecret`：必填，按字符串处理，不做数值推断 - `秒验审核`：必须明确是 `是` / `否` - `授权页自定义`：必须明确是 `是` / `否` 如不合法，列出具体问题并要求用户修正，不要继续改工程。 ## 第三步：扫描后推断工程接入点 读取配置后，再次结合工程做推断： - 优先识别主要 App Target - 推断 Objective-C / Swift / 混编 - 记录当前工程要使用 Objective-C 示例、Swift 示例还是两者都需要 - Swift 工程需检查是否已有 `{Target}-Bridging-Header.h` 与 `SWIFT_OBJC_BRIDGING_HEADER` - 定位疑似隐私同意回调位置，后续仍必须向用户确认 - 推断一键登录入口页或手机号登录页 - 推断当前是否已有 CocoaPods 体系 - 推断是否已有 ATS 配置、`-ObjC`、系统库链接 - 判断已有 `*.xcworkspace` 是否有效；只有目录但缺少 `contents.xcworkspacedata` 时，应运行 `pod install` 重新生成 - 判断已有 `Pods/` 是否完整；如果只有空 framework 目录或缺少 `Info.plist`、Headers、binary，不要按手动 SDK 接入硬改工程，应优先重新 `pod install` 以下信息必须分两类处理： ### 必须在修改前确认的信息 - 多 Target 时应该接入哪个 App Target - 用户同意隐私政策后的回调位置。即使扫描到疑似隐私弹窗，也要让用户确认 `agreePrivacy` 应插入到哪个“同意”回调 - 用户明确不想用 CocoaPods，必须改走手动导入 ### 可以在扫描后逐步确认的信息 - 是否需要自定义授权页样式 - `preLogin` 放在 `viewDidLoad`、按钮前预热还是其他业务时机 如果必须确认，串行一次只问一个问题。 ## 第四步：展示最小改动计划 修改前必须向用户展示本次最小改动计划，通常包括： - `Podfile`：按需加入 `pod 'FlyVerify'` - `.gitignore`：按需加入 `Pods/` - `Info.plist`：写入 `flyverifykey`、`flyverifysecret`、`FlyVerifyPLevel` - Xcode 构建设置：补 `-ObjC` - Swift 工程：新增或复用 Bridging Header，并配置 `SWIFT_OBJC_BRIDGING_HEADER` - 视情况补 ATS 白名单或提示用户已有配置可复用 - 在隐私同意后插入 `agreePrivacy` - 在登录链路中接入 `preLogin` 与 `openAuthPageWithModel` - 在 token 成功回调后保留服务端置换手机号逻辑注释占位 - 生成项目内 `FlyVerify_README.md` 没有确认前，不要直接改。 ## 第五步：执行工程修改 ### 5-1 依赖接入 默认优先 `CocoaPods`： - 在正确的 target 下加入 `pod 'FlyVerify'` - 如项目没有有效 workspace，运行 `pod install` 后确认 `*.xcworkspace/contents.xcworkspacedata` 已生成 - `pod install` 可能需要写用户级 CocoaPods cache；如遇 `~/Library/Caches/CocoaPods` 权限错误，应按当前执行环境申请授权后重试 - 若 `pod install` 修改 `.xcodeproj`，不要再手写重复的 Pods framework、xcconfig、shell script phase - 只有用户确认后才执行 `pod install` 如果用户明确要求手动导入： - 按官方资料把下载的 SDK 拖入工程 - 检查并补系统库、`-ObjC` 与 `Info.plist` ### 5-2 `Info.plist` 配置 默认写入或校正： - `flyverifykey` - `flyverifysecret` - `FlyVerifyPLevel = 2` ATS 处理规则： - 若工程已全局允许 HTTP，不重复扩大权限 - 若工程禁用 HTTP，则按官方域名白名单最小化添加 - 若工程已有等价白名单，复用现有配置，不重复写 ### 5-3 隐私合规接入 在用户同意隐私政策后、首次使用 FlyVerify 能力前接入： ```objective-c #import <FlyVerifyCSDK/FlyVerifyCSDK.h> [FlyVerifyC agreePrivacy:YES onResult:nil]; ``` Swift 工程必须先确保桥接头可访问 SDK 头文件： ```objc #import <FlyVerifyCSDK/FlyVerifyCSDK.h> #import <FlyVerify/FVSDKHyVerify.h> ``` 然后在用户同意隐私政策后的 Swift 回调中调用： ```swift FlyVerifyC.agreePrivacy(true, onResult: nil) ``` 如果用户明确采用代码初始化方案，才补： ```objective-c [FlyVerifyC initKey:@"<appKey>" secret:@"<appSecret>" privacyLevel:2]; ``` 否则优先沿用 `Info.plist` 配置，不同时强塞两套初始化方案。 ### 5-4 登录流程接入 建议流程： 1. 用户同意隐私政策后调用 `agreePrivacy` 2. 在即将进入一键登录前调用 `preLogin` 3. 在主线程拉起 `openAuthPageWithModel` 4. 成功返回 `token` / `opToken` 后保留服务端置换手机号注释占位 接入时必须注意： - `preLogin` 成功判断以 `error == nil` 为准 - `preLogin` 回调不是主线程，涉及 UI 必须切回主线程 - `currentViewController` 必须传当前页面或顶层页面 - 如果 `manualDismiss = @(YES)`，成功或失败后按业务自行关闭授权页 - Objective-C 与 Swift 工程都要提供对应语言代码；Swift 工程通过桥接头调用 `FVSDKHyVerify` 与 `FVSDKHyUIConfigure` - Swift 调用 `openAuthPageWithModel:openAuthPageListener:cancelAuthPageListener:oneKeyLoginListener:` 时，首参标签应为 `withModel:`，不是 `with:` - 服务端 token 置换接口的具体域名、鉴权方式、返回结构不在当前客户端集成步骤中追问，只在代码中以 `TODO` 注释标明 ### 5-5 授权页 UI 定制 只有用户明确需要时，才继续改 UI。 优先通过以下方式做最小定制： - `FVSDKHyUIConfigure` 基本属性 - `FVSDKVerifyDelegate` - `fvVerifyAuthPageViewDidLoad:userInfo:` 中设置布局或自定义控件 若用户要复杂弹窗、暗黑模式、横竖屏、自定义 loading、协议页接管，优先提示参考官方 Demo 与线上文档： - [秒验 Demo](https://github.com/MobClub/FlyVerify_For_iOS) - [MobTech 文档中心](https://www.mob.com/wiki/list) ## 第六步：验证与说明文档 完成改动后，按条件执行： - 若用户确认，可运行 `pod install` - 若环境允许，可运行一次构建验证；FlyVerify 依赖运营商库，优先验证 `generic/platform=iOS` 真机目标 - 不要把模拟器构建失败直接等同于集成失败；若错误类似 `building for 'iOS-simulator', but linking in object file ... built for 'iOS'`，说明某运营商 framework 只有真机切片，应改用真机目标验证 - Xcode 15+ 如遇 CocoaPods `[CP] Copy Pods Resources` 被 User Script Sandboxing 拦截，可在目标 Build Settings 中将 `ENABLE_USER_SCRIPT_SANDBOXING = NO`，或用等价命令行参数验证 - 如果普通沙箱下 `xcodebuild` 无法访问 CoreSimulator 或 Xcode 用户目录，应按当前环境申请授权后重试 - 若无法构建，明确说明未验证的原因 然后生成项目内 `FlyVerify_README.md`，至少包含： - 本次改动点 - `appKey` / `appSecret` 的配置位置 - `agreePrivacy` 的调用位置 - `preLogin` 与授权页拉起位置 - Objective-C / Swift 支持情况与桥接头配置情况 - CocoaPods 版本信息：`Podfile`、`Podfile.lock`、实际安装的 FlyVerify / FlyVerifyCSDK 版本 - 构建验证结果：真机目标、模拟器限制、剩余 warning - 服务端 token 置换属于后续业务步骤，当前只保留注释占位 - 扩展业务主动控制器是可选能力；如未来需要控制地理位置、WiFi、IP 等扩展业务数据采集，可参考官方扩展业务文档接入 `FlyVerifyCPrivacyDelegate` - 常见错误码排查入口 - 官方文档链接清单 ## 常见错误排查原则 遇到失败时优先检查： - 秒验审核是否已通过 - 手机是否开启移动蜂窝网络 - `agreePrivacy` 是否在隐私同意后已调用 - `currentViewController` 是否为当前顶层可 `present` 的 VC - `flyverifykey` / `flyverifysecret` 是否和后台一致 - ATS 是否拦截了运营商或 SDK 请求 - Swift 首参标签是否使用了 `withModel:` - 是否用真机目标验证，而不是只看模拟器构建结果 - CocoaPods workspace 是否有效生成 ## 与用户沟通的硬约束 - 一次只问一个阻塞问题 - 没有阻塞就不要追问，直接推进 - 每次修改前先展示计划 - 执行 `pod install` 或构建前先征求确认 - 如果某项无需修改，要明确说“无需修改”


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)