提醒
如果你只是需要一个第三方包来实现APN服务的话,推荐直接使用现有的项目 node-apn
提前工作
确保你是 Apple Developer 会员
点这里生成一个 *.p8 格式的私钥,仅能下载一次,注意妥善保存。(由于我使用的是Token-Based的认证方式,所以需要此格式。*.p12格式的证书不适用于本文的内容)
获取APNsAuthKeyId(Key ID):下好的 *.p8文件中就包含有Key ID。如’AuthKey_AXN12P9G17.p8’,那么’AXN12P9G17’就是Key ID。
获取AppleDeveloperId(Team Id): 进此页查看
获取BundleId: 注册App Id时填写的名称,一般其格式为 ‘com.app-name.app’
获取deviceToken
deviceToken相当于用户手机的id, 用户在下载App启动后就可以获取deviceToken。开发者可以在Xcode中拿到自己手机的deviceToken。
参见:
基于node v12.19.0版本
使用私钥生成签名
1  | // typescript  | 
使用Http/2请求
在生成签名后,作者尝试向苹果服务器发出请求,结果遇到了报错
1  | Parse Error: Expected HTTP/  | 
作者一度怀疑是node版本的问题(甚至还升级了版本 XD)。然而待作者仔细阅读Apple的文档后发现,原来是APNs只支持http/2的协议,难怪一直跑不通呢!这里也非常佩服苹果,总是投入资源来推动新技术的普及。
不过问题找到了,其实也会很容易解决
1  | // typescript  | 
开始推送
1  | //typescript  | 
请求成功后,Apple会返回对应的状态码和reason。一般出现403状态都说明生成的签名错误,请检查你是否使用错了证书(本文中的签名方法仅针对 *.p8格式的私钥)
参考:Apple官方文档
APN服务对应的状态码:
| status code | reason | 描述 | 
|---|---|---|
| 200 | / | 成功 | 
| 400 | BadDeviceToken | DeviceToken无效,或者环境错了。 | 
| 400 | BadTopic | apns-topic值无效 | 
| 400 | DeviceTokenNotForTopic | DeviceToken和Topic不匹配 | 
| 400 | MissingDeviceToken | 没有DeviceToken | 
| 400 | MissingTopic | 请求头缺少apns-topic | 
| 403 | BadCertificate | 证书无效 | 
| 403 | BadCertificateEnvironment | 证书的环境不对 | 
| 403 | ExpiredProviderToken | Token过期了 | 
| 403 | MissingProviderToken | 没有提供客户端认证证书,也没有设置authorization | 
| 413 | PayloadTooLarge | payload太大。(不得大于4 KB) | 
| 429 | TooManyProviderTokenUpdates | Token更新太过频繁(小于20分钟) | 
| 429 | TooManyRequests | 同时向同一台设备发送了过多请求 |