提醒
如果你只是需要一个第三方包来实现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 | 同时向同一台设备发送了过多请求 |