Apple 推送证书:Expo 该用 .p8 还是 .p12
作者:Mehdi Azizi
发布于 ,8分钟
Apple 推送有两种凭证:永不过期、通用于所有 app 的 .p8 密钥,或每年到期的 .p12 证书。用 Expo 的话,EAS 帮你管理密钥。
Apple 的推送证书授权服务器通过 APNs(Apple 的推送通知服务)向你的 app 发送通知。它有两种形式:.p12 证书,有效期一年,只绑定一个 app;或者 .p8 密钥,不会过期,可用于你账号下的所有 app。用 Expo 的话,你不需要证书:EAS 会在第一次构建时让你创建一个 .p8 密钥,Expo 的推送服务替你使用它。
开发者证书和 provisioning profile 那篇指南只用几行带过了推送密钥。这里我们讲透:两种格式怎么选、sandbox 和 production 两个环境、续期,以及让 TestFlight 里收不到通知的各种故障。
我用 Expo 和 EAS 发布自己的 app。Solys 和 TradaZen 在配置里都声明了 expo-notifications 插件:就是它让 app 做好接收通知的准备。
为什么 Apple 要证书或密钥
一条推送通知从服务器(你自己的或 Expo 的)发出,交给 APNs,再由 APNs 送到 iPhone。所以 APNs 必须确认这个服务器有权给你的 app 发消息。Apple 提供两种证明方式。
- 基于令牌的连接,用 .p8 密钥。 按 Apple 的说法,它更快,可以在多台服务器上使用,一个密钥就能覆盖你团队的全部或部分 app。你的服务器用它签名一个令牌,至少每小时重新生成一次。
- 基于证书的连接,用 .p12 文件。 Apple 说明这种证书只绑定一个 app,有效期一年。几个 app 就要几张证书。
Apple 关于过期的页面也提到:APNs 令牌签名密钥永远不会过期。
.p8 / .p12 对比表
| 对比项 | .p8 密钥 | .p12 证书 |
|---|---|---|
| 有效期 | 不过期 | 一年 |
| 适用范围 | 你的所有 app | 单个 app |
| 环境 | 创建时选择 | Sandbox 和 production |
| 续期 | 无需续期,除非吊销 | 每年一次 |
| 下载 | 只能下载一次 | 从 Mac 导出 |
| 数量 | 每个环境两个 | 每个 app 一个 |
| 在 Expo 中 | 由 EAS 创建和管理 | Expo 文档中没有提及 |
补充三点。.p8 文件只能下载一次:Apple 不会在你的账号里保留它。而 .p12 则从创建该证书的 Mac 的钥匙串中导出。另外,每个环境两个密钥的上限针对的是团队密钥。对于只限定部分 app 的密钥,Apple 允许每个环境最多 200 个。
Expo 关于凭证的页面只讲推送密钥,并说每个账号最多两个,没有区分环境,也没有区分按 app 的密钥。对 Expo app 来说,.p8 密钥是正确选择。
Sandbox 和 production:两个环境
APNs 有两套服务器:开发(也叫 sandbox)和生产(production)。Apple 规定前者用于测试,后者用于已发布的 app。app 通过 aps-environment 这个 entitlement 知道该用哪一个。按 Apple 的说法,它的值取决于签名用的描述文件:开发描述文件对应 development,分发描述文件和 TestFlight 对应 production。
所以 TestFlight 构建连接的是 production,和 App Store 完全一样。
Expo 这边有两个细节。expo-notifications 的文档说明,项目里的 entitlement 始终写成 development,在 release 构建的归档中才改为 production。另外,Expo 令牌在创建时会绑定到 app 的环境,这是自动检测的:发送时你什么都不用选。
如果你自己创建密钥,Apple 会让你选择环境和范围:整个团队还是部分 app。Apple 的开发者文档现在描述了限定于 sandbox 或 production 的团队密钥,旧的通用密钥仍然有效。而账号帮助文档还说密钥两个环境都能用。Apple 自相矛盾:以你创建时选的环境为准。只限 sandbox 的密钥,TestFlight 和 App Store 都用不了。
Expo 如何管理推送密钥
根据 2026 年 7 月 28 日更新的 Expo 配置指南,第一次做开发构建时,它会问你是否配置推送通知、是否生成 APNs 密钥。两个都回答 yes。不用 EAS Build 的话,运行 eas credentials。你需要一个付费的 Apple Developer 账号。
之后:
- EAS 保存密钥并关联到你的 app。 按 Expo 的说法,一个密钥想用于多少个 app 都行,而且上传新密钥不会改变你用户的 Expo Push 令牌。
- 你的服务器不直接调用 APNs。 它发给 Expo 的推送服务,再由后者转给 APNs。Expo 要求你读取回执,大约在发送后 15 分钟:错误会显示在那里。
- 插件负责添加 entitlement。 在
plugins里声明expo-notifications:
{
"expo": {
"plugins": ["expo-notifications"]
}
}
两个坑。Expo 的 FAQ 说从 SDK 53 起 Expo Go 不再支持推送通知,而 expo-notifications 的页面只提到 Android。无论哪种情况,Expo 都建议用开发构建:就用它来测试。另外,用 eas credentials 删除密钥只是把它从 Expo 的服务器上移除,并不会从你的 Apple 账号里删除。要腾出名额,得去 Apple 开发者后台吊销它。和所有密钥一样,.p8 文件绝不能提交到你的代码仓库:规则和 Expo app 的 API 密钥一样。
续期:真正会过期的是什么
.p8 密钥不需要续期。 只有你吊销它,它才会失效。如果你怀疑它泄露了,Apple 建议先创建新密钥,切换过去,然后再吊销旧的。在 Expo 中替换密钥,FAQ 给出了步骤:eas credentials,选 iOS,选你的构建 profile,然后移除推送密钥并生成新的。
.p12 证书每年过期。 Apple 要求你在到期前更新,并在钥匙串里关注到期日期。一旦过期或被吊销,你就无法再向 app 发送通知。Apple 没有单独的续期流程:你从 app 的标识符创建一张新证书,在到期前装到服务器上,再移除旧证书。最好的续期方式,就是改用密钥。
你用 Intune 或其他设备管理工具管理 iPhone?那不是同一种证书。设备管理用的推送证书在 Apple Push Certificates Portal 上创建,每年续期。Apple 建议记下所用的 Apple 账号:续期时要用到。
常见故障及解决办法
开发环境能收到,TestFlight 收不到
- 你发到了错误的令牌。 TestFlight 构建在 production 注册,会拿到一个新令牌。开发构建产生的令牌用不了:当令牌与环境不匹配时,Apple 会返回
BadDeviceToken。从 TestFlight 版本的 app 本身获取令牌。 - 生产 app 没有推送凭证。 这是 Expo FAQ 给出的诊断。检查 expo.dev 上项目的凭证页面,或运行
eas credentials。 - 你的密钥只限 sandbox。 换成一个在 production 有效的密钥。
- iPhone 拿不到令牌。 如果你把 TestFlight 构建装在了 Xcode 构建之上,Expo 建议重启设备。
“No valid aps-environment entitlement string found”
按 Expo FAQ 的说法,这个错误表示你的 iOS 项目没有配置推送密钥。检查凭证页面,然后重新构建:EAS 会提示你生成密钥。同时确认 expo-notifications 确实在 plugins 里。
ITMS-90078: Missing Push Notification Entitlement
这封邮件是 Apple 在你提交后发的:你的 app 看起来会注册 APNs,但签名里没有 aps-environment entitlement。Expo 关于 SDK 51 的说明解释了原因。从这个 SDK 起,只有安装了 expo-notifications 才会添加这个 entitlement。这个警告来自 Apple 的两项检查。第一项比较你 App ID 的功能(capabilities)和 app 的 entitlement。第二项在二进制文件里查找注册通知的方法,而所有 app 中的 Expo 代码都包含这个方法。
这是警告,不是拒绝,Expo 明确说明。如果你要用通知,添加插件并重新构建:EAS 会在每次构建时同步 App ID 的功能。如果不用,就在 Apple 开发者后台把 Push Notifications 功能从你的 App ID 中移除。警告可能还会出现,但没有影响。
InvalidCredentials,或所有 app 同时收不到通知
回执里出现 InvalidCredentials 意味着你的推送凭证已失效,通常是因为密钥被吊销了。所有使用它的 app 会同时收不到通知。Expo 的解决办法:eas credentials,然后生成新密钥。如果回执提到 InvalidProviderToken,Expo 建议重新构建,同时重新生成推送密钥和描述文件。
启用通知之前
想在发布前在 iPhone 上测试通知,看 用 TestFlight 测试你的 app。如果你发送静默通知来唤醒 app,重读 关于后台模式的 guideline 2.5.4。不用 Mac 的完整流程见 没有 Mac 也能发布 iOS app,发布步骤见 在 App Store 上发布应用。
第一次发送之前,做一下免费诊断:它会告诉你项目里卡在哪里,并发给你我的 Apple 防拒审清单。要开发 app、接入订阅并发布,iOS & Android Kit 带你走完四个阶段,附带我自己 app 的起步代码,按你自己的节奏来。
常见问题
Apple 推送证书会过期吗?
.p12 证书一年后过期,如果不更换,你的通知就会停止。.p8 密钥永远不会过期:只有你吊销它才会失效。这正是首选密钥的主要原因。
每个 app 都需要一张推送证书吗?
用 .p12 证书的话,是的:每张证书只绑定一个 app。.p8 密钥可用于你账号下的所有 app。所以在 Expo 中,一个密钥就能覆盖你的全部 app。
怎么续期 Apple 推送证书?
从 app 的标识符创建一张新证书(附上新的签名请求),装到你的服务器上,再移除旧证书。要在到期前完成。最简单的还是改用 .p8 密钥,它不需要续期。
我的 .p8 文件丢了,怎么办?
Apple 只允许下载一次。如果密钥是 EAS 创建的,Expo 会保存它,你的通知照常工作。否则,创建一个新密钥,用 eas credentials 添加,然后在 Apple 开发者后台吊销旧密钥。你用户的 Expo Push 令牌不会改变。
换了推送密钥后需要重新构建吗?
一般不需要。密钥是给发送通知的服务器用的,不是给已安装的 app 用的,而且 Expo 说明新密钥不会改变令牌。例外:如果回执显示 InvalidProviderToken,Expo 建议用新密钥和新描述文件重新构建。

