
Greenlight scan源码解析如何调用 App Store Connect API 做元数据完整性与加密合规检查【免费下载链接】greenlightPre-submission compliance scanner for the Apple App Store and Google Play. Scans code, privacy manifests, Android manifests, and IPA/APK/AAB binaries against the review guidelines. Offline, no account.项目地址: https://gitcode.com/gh_mirrors/greenlight2/greenlightGreenlight是一个面向 App Store 与 Google Play 的提审前合规扫描工具。本文深入解析它的greenlight scan命令通过 JWT 鉴权调用 App Store Connect API在提交审核前自动检查元数据完整性、截图规格、年龄分级与加密合规Encryption Compliance把常见的拒审原因消灭在本地。项目概览提审前先体检Greenlight 的核心理念是Know before you submit提审前先知道。它提供四类能力命令作用是否离线greenlight preflight本地静态扫描源码、隐私清单、IPA/APK✅ 完全离线greenlight scan调用 App Store Connect API 做线上检查❌ 需要 API 密钥greenlight verify云真机上运行删号/恢复购买/Sign in with Apple 流程❌ 需要 Revyl 账号greenlight guidelines内置苹果审核指南数据库支持全文搜索✅ 完全离线本文聚焦greenlight scan它是唯一直接对接 App Store Connect 的命令。一次 scan 调用的整体链路整个扫描由三层代码协作完成greenlight scan --app-id 6758967212 │ ▼ internal/cli/scan.go CLI 入口读取配置、构造客户端 │ ▼ internal/asc/ API 客户端JWT 生成 REST 请求 │ ▼ internal/checks/ 检查编排器按 Tier 依次执行各项检查入口与编排internal/cli/scan.goAPI 客户端internal/asc/检查逻辑internal/checks/CLI 层做的事很薄加载本地凭据 → 用KeyID、IssuerID、私钥路径构造asc.Client→ 交给checks.Runner按 Tier 执行 → 生成报告。API 客户端JWT 鉴权与自动续期scan使用 App Store Connect 官方 API基础地址https://api.appstoreconnect.apple.com/v1鉴权方式为 ES256 签名的 JWT实现见 internal/asc/auth.go从本地读取.p8格式私钥PKCS8 解包为 ECDSA 密钥填充iss签发者、exp20 分钟过期、aud: appstoreconnect-v1等声明用密钥 ID 作为kid头部字段签名客户端封装在 internal/asc/client.go 中有一个值得学习的小设计令牌自动续期。NewClient在构造时先生成一个令牌验证凭据有效性随后在内部缓存令牌并记录过期时间为签发后 15 分钟早于 Apple 的 20 分钟上限。每次get()请求前比较当前时间过期则静默刷新——调用方完全无感知internal/asc/client.go#L40-L55。API 侧封装了九个只读接口全部集中在 internal/asc/apps.go方法端点用途GetApp/apps/{id}应用基础信息与名称GetAppStoreVersions/apps/{id}/appStoreVersions版本及审核状态GetVersionLocalizations/appStoreVersions/{id}/...Localizations描述/关键词/更新说明等本地化元数据GetScreenshotSets/GetScreenshots/appScreenshotSets/...截图集与单张截图尺寸GetBuilds/builds?filter[app]...最近构建的处理状态GetAppInfos/apps/{id}/appInfos年龄分级声明GetBetaGroups/GetAppAvailability/GetAppPriceScheduleTestFlight 组 / 可售地区 / 定价辅助合规项所有响应通过泛型包装DataResponse[T]/ListResponse[T]统一解析Go 1.24 的泛型在这里让代码非常干净。Tier 1元数据完整性检查Tier 编排逻辑在 internal/checks/runner.go#L35-L54。Tier 1TierMetadata注册了 11 项检查全部实现在 internal/checks/tier1_metadata.go。检查清单一览检查项判定为 BLOCK 的条件对应指南应用可访问API 取不到应用ID 错误或密钥无权限—应用名称名称为空或超过 30 字符§2.3版本就绪不存在可提交状态的版本—元数据完整描述为空或超 4000 字符、关键词超 100、促销文案超 170、缺 Support URL§2.3 / §1.5截图未上传、缺 6.7/5.5 iPhone 尺寸、分辨率不匹配§2.3构建就绪构建未处于VALID状态—年龄分级未填写年龄分级问卷§1.3加密合规usesNonExemptEncryption未声明§5.0可售地区未配置任何地区—定价未显式设置价格含免费—几个有代表性的实现细节字符上限用utf8.RuneCountInString计数internal/checks/tier1_metadata.go#L75-L82。元数据常量直接来自 App Store Connect 的规则描述 4000、关键词 100、促销文案 170、应用名 30。用 Rune 计数意味着中文等多字节字符也按 1 个字计算与 Apple 的实际校验口径一致。截图尺寸精确到像素requiredScreenshotDimensions映射表internal/checks/tier1_metadata.go#L343-L353规定 6.7 iPhone 必须是 1290×2796并兼容横竖屏两种上传方向——这是审核中被频繁驳回的隐形雷。检查失败不中断流程Runner 中单项检查报错时不 panic而是记为一条 WARN 级 Finding 继续执行internal/checks/runner.go#L77-L89保证报告永远完整。加密合规检查是如何工作的这是本文标题中的重点。Apple 要求每个应用声明是否使用非豁免加密未声明会导致 App 无法在某些地区上架。实现只有十几行internal/checks/tier1_metadata.go#L320-L340拉取该应用最近 5 个构建按上传时间倒序取最新一个读取构建属性usesNonExemptEncryption——注意它是*bool指针类型专门区分未声明nil和声明为 false若为 nil输出 WARN 级 Finding建议设置ITSAppUsesNonExemptEncryptionInfo.plist或在 App Store Connect 中声明指针类型的选择体现了严谨性一个用了标准 HTTPS 就标 false的应用和一个根本没填的应用风险完全不同代码层面直接建模了这个区别。Tier 2内容分析顺带做了什么Tier 2 的元数据文本分析也依赖同一套 API 数据internal/checks/tier2_content.go竞品平台引用扫描描述/关键词/更新说明中是否出现 android、google play 等 8 组词命中即 BLOCK§2.3占位内容检测lorem ipsum、coming soon、example.com等 13 组占位词模式§2.1URL 可达性对 Support URL 和 Marketing URL 发起真实 HTTP 请求4xx/5xx 即告警——因为 Apple 审核员真的会点开这些链接两套鉴权方式scan支持两种登录方式入口在 internal/cli/auth.go方式命令实现适用场景API 密钥推荐greenlight auth setupinternal/asc/auth.go JWTCI/CD 自动化Apple ID 双因素greenlight auth logininternal/asc/session_auth.go 会话 Cookie本地一次性使用Apple ID 登录走的是网页版 App Store Connect 的会话流程向idmsa.apple.com发起 sign-in收到 409 表示需要 6 位验证码SubmitTwoFactorCode提交后调用trustSession让设备被信任约 30 天。这条路径主要用于没有 API 密钥的个人开发者快速体验。凭据保存在本地配置中scan执行时由config.Load()读取未认证会直接提示先运行greenlight auth setupinternal/cli/scan.go#L56-L73。快速上手# 1. 配置 API 密钥App Store Connect → 用户和访问 → 密钥 greenlight auth setup # 2. 只跑 Tier 1最快纯 API 元数据检查 greenlight scan --app-id 6758967212 --tier 1 # 3. 全量检查输出 JSON 供 CI 消费 greenlight scan --app-id 6758967212 --format json --output report.json每条 Finding 都会带上tier / severity / guideline / fix四要素internal/checks/types.go#L35-L43例如Keywords exceed 100 character limit会直接告诉你怎么改。严重度分三级BLOCK几乎必然被拒、WARN高风险、INFO最佳实践Summary.Passed在没有 BLOCK 时为 true可作为 CI 门禁。小结greenlight scan的源码结构值得借鉴的地方有三点分层清晰asc包只管鉴权与 HTTPchecks包只管业务规则cli只管参数与呈现三层可以独立演进韧性设计令牌自动续期、单项检查失败降级为 WARN、API 无权限时优雅跳过非关键项规则可追溯每条 Finding 都引用苹果审核指南编号§2.3、§5.0 等用户可以直接对照官方文档。对于想避免提交后才发现缺截图、忘填年龄分级、未声明加密这类低级拒审的团队这套 Tier 1 检查是一份很实用的自动化清单。想动手研究完整实现可以从 internal/checks/runner.go 的注册表模式读起。【免费下载链接】greenlightPre-submission compliance scanner for the Apple App Store and Google Play. Scans code, privacy manifests, Android manifests, and IPA/APK/AAB binaries against the review guidelines. Offline, no account.项目地址: https://gitcode.com/gh_mirrors/greenlight2/greenlight创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考