Cocos2d-x iOS打包上架:证书与描述文件完整指南

Cocos2d-x iOS打包上架:证书与描述文件完整指南 1. 先弄清苹果签名的完整链路证书、App ID、描述文件三个角色做 Cocos2d-x 游戏的老哥们应该都有这种经历游戏在 Android 上跑得飞起模拟器里也一切正常但一旦要往 iPhone 上装就开始和各种英文报错打交道。折腾了一两天最后发现根本不是代码问题全卡在“签名”这一层。这里我把这几年用 Cocos2d-x 打包 iOS 并上架 App Store 的证书与描述文件经验整理成一套完整流程照着走能省掉大半的试错时间。1.1 证书不是“钥匙”而是你的“身份印章”很多教程把证书叫“钥匙”这个比喻其实不够准确。iOS 证书更像一枚“身份印章”它解决的是苹果的安全问题你手里这个 App到底是不是某个真实开发者签出来的。具体到操作上你在 Mac 的钥匙串里生成一个 Certificate Signing RequestCSR这个过程中系统会生成一对公钥和私钥。私钥永远留在你的 Mac 钥匙串里公钥随着 CSR 提交给苹果。苹果拿着你的开发者账号信息基于公钥生成一份数字证书。之后你用本地的私钥对 App 进行签名苹果后台用证书里的公钥来验证签名是否匹配。只要私钥丢了就算重新下载那份证书文件也没用因为签名时用的是私钥不是证书本身。Cocos2d-x 工程里常见的情况是同事负责开发另一台 Mac 负责打包。负责打包的那台机器上没有生成 CSR 的私钥于是 Xcode 一直报“A valid signing identity matching this profile could not be found in your keychain”。解决办法是把私钥连同证书一起从原机器导出成 .p12 文件装到打包机上。这个我在第 3 节里会给出详细步骤。1.2 描述文件把身份、App、设备绑在一起证书只解决“你是谁”描述文件解决的是“你做的东西能不能跑跑在哪些设备上”。一个 Provisioning Profile 里打包了三种信息App ID、可用的证书、受信任的设备开发阶段的描述文件才会包含设备。你可以把它理解成一张通行证苹果先确认 App ID 对得上再确认签名证书有效最后确认当前设备的 UDID 在列表里三样都满足才允许安装。Cocos2d-x 项目牵扯到推送、Game Center、内购时App ID 还得开启对应的 App Services否则就算描述文件生成成功运行到对应 API 时也会返回奇怪错误。常见案例是内购开发时发现 SKPaymentQueue 一直拿不到商品查到最后是 App ID 没勾选 In-App Purchase又重新生成描述文件。1.3 Cocos2d-x 工程中签名信息写在哪儿Cocos2d-x 生成 Xcode 工程后会有一个 proj.ios 目录里面是 .xcodeproj 工程文件。你在 Xcode 里打开工程点击左侧 TARGETS 下的游戏 Target在 Signing Capabilities 区域能看到签名相关配置。Bundle Identifier对应 App ID 的完整值Automatically manage signing开启后由 Xcode 自动创建和管理描述文件Team你的开发者账号对应的 TeamProvisioning Profile手动签名时从这里指定描述文件Signing Certificate指定用 Apple Development 还是 Apple Distribution 证书Cocos2d-x 老版本3.x工程默认没有 .xcodeproj 还是 .xcworkspace 的区分一般直接打开 .xcodeproj 就行。但如果你在工程里用了 CocoaPods 集成第三方 SDK就必须打开 .xcworkspace否则签名能通过编译会报找不到头文件。2. 开发者账号与 App ID 准备这步错了后面全是连锁报错2.1 账号角色别搞混开发者后台与 App Store Connect 是两个入口要上架 App Store你需要一个苹果开发者账号年费 99 美元。登录 developer.apple.com 后实际会用到两个后台Certificates, Identifiers Profiles管理证书、App ID、描述文件App Store Connect管理在售 App、版本提审、TestFlight、用户访问权限等以前经常有第一次打包的同事把这两个后台混在一起。在最开始你要保证登录的 Apple ID 在两个后台都有管理员权限。个人开发者账号通常默认没问题公司账号则需要在 App Store Connect 的 Users and Access 里确认有 Admin 或 App Manager 角色否则后面创建版本时会提示没有权限。2.2 创建显式 App ID别贪图通配符的省事在 Certificates, Identifiers Profiles 页面选择 Identifiers点击加号创建 App ID。这一步有两个容易踩坑的选择。第一是 App ID 类型。Apple Developer Program 现在默认建议用 Explicit App ID也就是完整的 Bundle ID比如 com.yourcompany.cocosrunner。另一种是 Wildcard App ID形如 com.yourcompany.*可以匹配多个 App。问题在于推送、Game Center、内购这些服务不能用在通配符 ID 上而 Cocos2d-x 游戏很容易用到内购。Cocos2d-x 官方示例用的 Bundle ID 往往都是完整形式所以你创建时也直接填完整 ID省得后面推送服务开不了。第二是 App Services。我一般只勾选当前用得到的能力比如 Game Center、In-App Purchase、Push Notifications。不要一股脑全勾上因为某些能力开通后描述文件和信息属性列表之间会产生额外要求。比如 Push Notifications 开了之后如果 App 里没有正确注册推送审核时可能被要求补充说明Associated Domains 开了之后不配置 universal link 也没什么用反而容易让审核员怀疑功能不完整。创建完成后页面会列出 App ID 对应的字符串。这里有一个很值得记住的经验Bundle ID 必须和 Xcode 工程里的 Bundle Identifier 完全一致连大小写都不能差。Cocos2d-x 工程创建时默认的 Bundle Identifier 是 com.test.xxx 之类的你需要提早改成自己的正式 ID而不是拖到上传前再改。因为在 Archive 之后再改 Bundle ID描述文件、App Store Connect 里的应用记录、Xcode 工程三处不一致时报错会非常阴间。2.3 真机调试要注册 UDID模拟器却不用只在 Xcode 官方模拟器上跑 Cocos2d-x 工程不需要描述文件和证书。但你只要想装到 iPhone 上测性能、测推送、测 Retina 适配就必须先把设备的 UDID 加进开发者后台。获取 UDID 的方法有好几种最简单的是把 iPhone 连上 Mac打开 Xcode 的 Window - Devices and Simulators选中设备后能看到 Identifier 一长串字符串。这个就是 UDID。在开发者后台选择 Devices点加号输入设备名称和 UDID。注意这一步只能添加最多 100 台设备而且删除之后不能再加回来。Cocos2d-x 团队测试时经常换设备老设备的 UDID 加进去后不用刻意删用完放着不会影响上架。真正需要注意的是不要拿别人的 UDID 随便加因为描述文件里一旦包含该设备出包制作测试版时它就能安装存在审阅风险。3. 从 CSR 到描述文件类型判断与私钥管理是核心3.1 钥匙串生成 CSR 时私钥已经留在本机在 Mac 上打开“钥匙串访问”点击菜单栏的“证书助理” - “从证书颁发机构请求证书”。在弹出的界面里选择“存储到磁盘”电子邮件地址填你开发者账号对应的 Apple ID常用名称可以随意填一般写公司名或项目名。继续后生成一个 .certSigningRequest 文件。这一步里系统已经生成了一对密钥私钥默认放在登录钥匙串里公钥包含在 CSR 中。你在钥匙串访问程序里搜索“Apple Development”或“Apple Distribution”能看到生成的公钥。请专门记住这一点不要随意在“钥匙串访问”里把相关私钥删除否则后面即使重新下载了证书也签不了包。3.2 创建证书并导出 .p12多台机器打包全靠这一步回到开发者后台选择 Certificates - 加号在证书类型里选择“Apple Development”或“Apple Distribution”。开发调试阶段选前者打上传 App Store 的包选后者。上传 CSR 后立刻下载证书双击安装到钥匙串。当你要在另一台打包机上自动构建时光下载证书不够必须把私钥一起带过去。操作是在钥匙串访问里找到刚安装的证书注意看它前面有没有展开的小三角展开后能看到一个同名私钥。选中证书和私钥右键导出格式选择“个人信息交换.p12”设置一个密码。把 .p12 文件和描述文件贴到打包机后双击 .p12 导入钥匙串即可。这里要特别提醒如果生成 CSR 的人离职或换了电脑而原机器的钥匙串没备份那旧证书等于废了赶紧在开发者后台 Revoke 并重新生成。团队协作时最好指定一个人统一负责私钥密码或者用 CI 系统里的环境变量管理 .p12不要裸发到群里。3.3 描述文件类型开发、Ad Hoc、App Store 之间怎么选在 Profiles 页面点加号能看到多种描述文件类型描述文件类型是否包含设备用于iOS App Development包含最多 100 台真机调试Ad Hoc包含最多 100 台内测分发不上架也能装App Store Connect不包含具体设备提交到 App Store 审核Cocos2d-x 开发中最常用的就是三种。日常真机调试选 Development开发期给美术和策划内部装包用 Ad Hoc最终提审前 Archive 导出时选 App Store Connect。这里有一个常见误解以为开发描述文件也能传 App Store。实际上用开发描述文件打出来的包无法通过 App Store 校验上传后会被苹果直接拒绝错误码一般是“Invalid Provisioning Profile”。所以我建议在 Cocos2d-x 工程里同时配置两套签名Debug 用 Development 描述文件Release 用 App Store 描述文件在 Build Settings 里通过配置区分省得打包前反复改。创建描述文件时要选择 App ID、包含的证书、以及设备Ad Hoc/Development。下载后双击会自动装进 Xcode但凭我的经验最好把描述文件保留一份完整性校验在终端里执行security cms -D -i 描述文件.mobileprovision可以查看它的 XML 内容里面会列出 UUID、创建时间、证书信息。这样排查签名报错时很有用。3.4 描述文件过期与 Xcode 的自动刷新逻辑描述文件有明确的有效期通常是一年。过期后 Xcode 里会出现红色感叹号打出的包也会在安装时报“无法验证 App”。好消息是无需重新创建回到 Profiles 列表找到过期条目点 Edit 再点 Save系统会生成新的版本下载安装即可。描述文件名称后面有一个 UUIDXcode 实际识别的是这个 UUID不是文件名。如果开发时开启了 Automatically manage signingXcode 会在发现描述文件失效时自动去开发者后台续期。但这要求 Xcode 里的 Apple ID 有所属 Team 的管理权限。有时候团队遇到“A signing session is currently in progress”卡住其实就是 Xcode 正在联网更新描述文件等几分钟再试或者切换网络环境。4. 把签名配置落到 Cocos2d-x 工程里建议手动签名4.1 自动签名和手动签名的分岔口Cocos2d-x 工程打开后在 Signing Capabilities 里能看到 Automatically manage signing 的勾选框。个人项目勾上它确实省事Xcode 会自动创建 App ID、描述文件并在首次真机运行时自动注册当前设备。但 Cocos2d-x 工程有个特殊情况引擎自带的 AppIcon 设置和 Assets.xcassets 结构可能与新版 Xcode 不兼容自动签名偶尔会生成一个匹配错误的描述文件导致 Xcode 提示“No profiles for ... were found”。这种报错看似很底层其实只是自动签名选错了 Team 或 App ID。所以我实践下来iOS 游戏发布阶段用固定描述文件更稳妥。关闭自动签名在 Build Settings 里手动设置Code Signing IdentityRelease 下选 Apple DistributionProvisioning Profile选你刚下载好的对应描述文件Development Team正确选择 Team ID如果你不想切到 Build Settings 改也可以在 Signing Capabilities 下选好 Team但把自动签名的勾去掉然后在下方的 Provisioning Profile 下拉框里手动选择。Xcode 的高版本里手动签名后编译仍然会做签名检查但不会再去动态生成描述文件。4.2 Bundle Identifier 与 Info.plist 的联动签名时 Xcode 使用 Build Settings 里的 PRODUCT_BUNDLE_IDENTIFIER 作为最终 Bundle ID。Cocos2d-x 工程里除了 build settingsInfo.plist 里也可能存在一个旧的 Bundle Identifier但 Info.plist 里的值只是一个默认历史记录实际以 PRODUCT_BUNDLE_IDENTIFIER 为准。很多新人改错了地方改了 Info.plist 里的值签名时报错依旧原因就是这个。把 PRODUCT_BUNDLE_IDENTIFIER 改成和 App ID 完全一致的字符串后还要检查 Info.plist 里的 CFBundleDisplayName、CFBundleShortVersionString、CFBundleVersion。这三个字段直接影响 App Store 的版本号和构建号。CFBundleVersion 每次上传都必须递增否则 Transporter 会提示版本重复。对于 Cocos2d-x 3.x 老项目如果工程里还有其他 target比如一些示例代码生成的 test target签名时也要给它们分配描述文件否则 Archive 会因为其中一个 target 未签名而失败。4.3 部署目标与 AppIcon跟证书无关但也绕不开的坑证书和描述文件全对的情况下Cocos2d-x 老工程还会遇到几类看起来像签名问题的编译错误。最常见的是部署目标太低。新版 Xcode 不支持 iOS 8.0 以下部署目标而 Cocos2d-x 3.x 的默认部署目标可能是 6.0 或 7.0。解决办法是在 Build Settings 里把 iOS Deployment Target 调到当前 Xcode 支持的最低值一般设为 12.0 以上比较保险。另一个是 AppIcon。从 Xcode 14 开始上传到 App Store 的包必须包含 1024x1024 的无透明背景图标。Cocos2d-x 模板工程如果用的是旧版资源Assets.xcassets 里只有 57x57、120x120 等旧尺寸图标上传时会报“Missing required icon”。处理方式是把 1024 图标拖进 AppIcon 的 iOS 1024pt 位置同时删掉旧的 Circular Icon 等不必要配置。5. 上传与提审Archive、Transporter、审核资料的最终接力5.1 Archive 导出时选择正确的分发类型一切配置完选择 Product - Archive。Archive 之前要注意 Xcode 顶部的 Scheme 设备需要选“Any iOS Devicearm64”或 Generic iOS Device不能选模拟器因为模拟器产出的是 x86_64 架构不能用于提交。Archive 完成后 Xcode 的 Organizer 会列出本次存档。点击 Distribute App接下来会有两种分发方式App Store Connect直接上传到苹果后台等待真机审阅Development导出给测试设备安装不能提审选择 App Store Connect 后下一步会让你选择 Strip Swift Symbols、Upload Symbols 等选项。Cocos2d-x 项目如果是纯 C/Objective-C 写的没有 Swift 符号直接下一步即可如果集成了 Swift SDK建议保留 Upload Symbols方便看崩溃日志。导出完成后 Transporter 会自动打开或者你也可以在 Xcode 里直接点 Upload。上传耗时取决于游戏包体大小Cocos2d-x 的包一般几十 MB基本几分钟内能完成。5.2 最常见的几类上传失败代码和排查办法上传转圈半天后弹失败这是所有 Cocos2d-x 发布流程里最让人心态爆炸的一步。我把这几年遇到的高频错误整理成一张表便于快速对照错误码/提示原因解决办法No suitable application records were foundApp Store Connect 里还没有创建对应的 App 记录在 App Store Connect 里先新建 App填好 Bundle IDITMS-90034 Missing or invalid signature签名的证书不是 Distribution 类型或描述文件选错确认 Release 的 Code Signing Identity 是 Apple Distribution重新 ArchiveITMS-90022 Missing required icon缺少 1024x1024 图标补全 AppIcon 资源后重新打包ITMS-90426 Invalid Swift Support包里的 Swift 运行时版本不匹配把 Use Legacy Swift Language Version 调到 Swift 5重新 ArchiveITMS-90863 Apple silicon Macs support issue包内包含 x86_64 模拟器切片在 Build Settings 里排除 VALID_ARCHS 中的 x86_64Invalid Provisioning Profile描述文件和 App ID 不匹配核对描述文件中的 Bundle ID重新下载并安装Clean 后重建如果你在 Cocos2d-x 工程里集成了 Lua 脚本或动态库还要检查是否因为这些文件放错位置导致包体内出现嵌套的 .app 文件。包中嵌套 App 会被当成恶意结构拒绝上传。5.3 用 Transporter 上传可绕过 Xcode 的本地缓存问题有时候 Xcode 明明显示上传成功App Store Connect 却迟迟收不到十有八九是 Xcode 的本地上传缓存坏了。这时候我推荐用独立的 Transporter 应用。它支持从本地 .ipa 文件上传也支持从 Xcode Archive 导出后的文件夹上传。在 Organizer 里选择 Export导出类型选 App Store Connect就能得到一个 .ipa 文件和 ExportOptions.plist。然后用 Transporter 打开 .ipa 上传。Transporter 的校验比 Xcode 更直白出错时给出的错误描述也更明确比如 ITMS-90209 对应的是无效的 Segment Alignment这在 Cocos2d-x 老版本里偶尔出现需要用新版 Xcode 重新编译。上传成功后在 App Store Connect 里的 TestFlight 或版本页面能看到构建记录。注意构建版本可能需要几分钟到十几分钟才处理完成不要着急点“添加版本”。5.4 提审资料隐私政策、审核账号、权限说明一个都不能少构建上传成功只代表技术链路通了App 能不能上架还取决于提审资料。Cocos2d-x 游戏如果嵌入了统计、广告或推送 SDK都会被苹果要求提供隐私政策链接。最常见的拒审原因是“App requires user consent for data collection”也就是缺少隐私政策链接和 Apple 要求的数据收集说明。在 App Store Connect 的 App 隐私页面你需要填写“App 会收集哪些数据”、数据用途、是否关联用户等。这里我的经验是Cocos2d-x 的第三方 SDK比如统计 SDK 和崩溃上报 SDK如果默认采集 IDFA你必须声明并接入 App Tracking Transparency 框架。否则即便过审iOS 14.5 以上系统也会在用户首次打开时弹窗要求授权不添加对应 Info.plist 描述字符串的直接后果是崩溃。提审时还要填一个“审核信息”页。如果游戏功能需要登录应提供一个审核专用账号如果游戏是 Cocos2d-x 纯单机游戏没有登录账号就直接说明无需账号即可体验全部功能。广告 SDK 如果存在记得在“广告标识符”一栏如实选择虚假声明在后续抽查中非常危险。我个人的操作习惯是在正式提审前先通过 TestFlight 分发一个版本给同事和设备测试把崩溃日志、登录流程、内购流程全部验证一遍再提审。这个习惯帮我避开过两次因配置描述文件过期导致 TestFlight 版本闪退的尴尬。Cocos2d-x 项目本身跨平台能力强同一套代码在 Android 上没问题不代表 iOS 打包没问题毕竟证书、描述文件和 App 权限合在一起总能折腾出一些新惊喜。