简介
关于APNs的工作原理,网上有大量的文章,建议学习apple的官方文档。通过APNs我们就可以通过服务器想APP推送想要的内容和事件。从而实现通知或者激活应用的目的。本文我们讲介绍如何搭建php的APNs推送以及如何实现静默推送。
APNs PHP 客户端
经过多方的验证,目前推荐这个:
https://github.com/immobiliare/ApnsPHP
证书验证
想要通过苹果服务器推送信息,必须要有合法的证书。很多人在推送这部分花了很多时间,很多情况是没搞清楚失败到底是代码的问题还是证书的问题。所以,我们需要先验证证书的合法和正确性。
推送时,我们要制作推送证书,我们要选择正确的类型,具体的制作过程可自行搜索,最终的证书类型如下:
Easy APNS Provider
先前我的文章推荐过Knuff,经过深入的实践,这里我推荐Easy APNS Provider,可以从MAC store下载。相比较Knuff,EAP更加的稳定强大。通过工具我们就可以先行验证证书的正确性,避免后面定位问题浪费更多的时间。
[2020.03.31更新]:另一款值得推荐的是: https://github.com/noodlewerk/NWPusher
在MAC上用客户端向苹果发送推送服务器请求时,我们选择上面安装的证书就可以了。
PHP服务器证书生成
上面我们讲了怎么选择正确的客户端证书,当我们使用php 服务器推送时,我们还要做些额外的工作:
- 打开“钥匙串”程序,(证书助理->从证书颁发机构请求证书),只填邮箱和常用名称,ca不用填,然后保存.certSigningRequest文件到磁盘。
- 在iOS Dev Center 点击App IDs进入App ID列表。
- 为 App 开启 Push Notification 功能。(推送证书分为两个版本,一个是Development版,一个是Production版,分别对应开发证书和发布证书。)
- 上传刚才生成的.certSigningRequest文件,生成aps_development.cer推送证书,双击安装。
- 打开“钥匙串”程序,(选择登录与我的证书选项后)找到IOS Push Services那条.
- 右键导出,存储为cert.p12,(输入密码P*d)。然后将该证书的折叠向下展开打开,导出“专用密钥”,存储为key.p12。
- 接下来打开终端执行下面的命令,生成的ck.pem就是我们在php脚本中要使用的证书。
#生成cert.pem openssl pkcs12 -clcerts -nokeys -out cert.pem -in cert.p12 #生成key.pem(先输出导出key.p12时设置的密码P*d, 然后设置一个新的密码,如pushpwd,这个密码后面php推送时要设置) openssl pkcs12 -nocerts -out key.pem -in key.p12 #合并成ck.pem cat cert.pem key.pem > ck.pem
APNs PHP客户端配置
这个软件包的最新版本支持HTTP2,如果你的PHP的版本支持HTTP2,建议优先使用。开发包里面自带了几个sample,简单配置后基本就可以使用。这里我们以sample_push.php为测试对象。
如图所示,配置要点如下:
- 目标环境:sandbox还是production,对于appstore下载的目标,请选择ENVIRONMENT_PRODUCTION,对于开发中的版本,清选择ENVIRONMENT_SANDBOX
- 证书:填写证书的相对路径,这里最好时按照上面的步骤验证通过的证书
- 在上面的步骤中我们生成pem证书时,要求一个最少4位的密码,所以这个地方一定要设置密码,否则connect会失败
- device token:这里是我们要推送的目标的token。
测试通过的返回如下:
Fri, 13 Jan 2017 13:31:35 +0100 ApnsPHP[15355]: INFO: Trying tls://gateway.sandbox.push.apple.com:2195... Fri, 13 Jan 2017 13:31:35 +0100 ApnsPHP[15355]: INFO: Connected to tls://gateway.sandbox.push.apple.com:2195. Fri, 13 Jan 2017 13:31:35 +0100 ApnsPHP[15355]: INFO: Sending messages queue, run #1: 1 message(s) left in queue. Fri, 13 Jan 2017 13:31:35 +0100 ApnsPHP[15355]: STATUS: Sending message ID 1 [custom identifier: Message-Badge-3] (1/3): 167 bytes. Fri, 13 Jan 2017 13:31:36 +0100 ApnsPHP[15355]: INFO: Disconnected.
device token
在上面我们提到了设备的device token,那么调试阶段如何获取这个token呢?在我们发起了注册请求后,系统会触发相应的消息回调。相关的参考代码如下:
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
//读取APNS token
NSString* _deviceToken = [[[[deviceToken description]
stringByReplacingOccurrencesOfString: @"<" withString: @""]
stringByReplacingOccurrencesOfString: @">" withString: @""]
stringByReplacingOccurrencesOfString: @" " withString: @""];
QMLogDebug(@"apns token:%@",_deviceToken);
NSUserDefaults * userDefault = [NSUserDefaults standardUserDefaults];
[userDefault setObject:_deviceToken forKey:APNSTOKEN];
[userDefault synchronize];
}
上面的deviceToken就获取了我们需要的token。这里的deviceToken是NSData对象,可以手动导出二进制,然后这个导出文件就可以在测试客户端中使用。
全部的证书
除了ck.pem证书,我们的项目还需要 entrust_root_certification_authority.pem 这个证书,一共两个证书。
静默推送
ios最新的版本中已经支持了静默推送,静默推送时,客户端会收到消息,执行相应的动作,但不会做任何给用户的提示。在普通的推送中我们可以通过如下的代码实现静默推送的效果:
{
"aps" : {
"badge" : 0
}
}
但是苹果还是专门定义了一个开关来表示静默推送 "content-available" : 1,由于此开关优先级较低,在静默推送的报文中不能出现alert,sound 等,否则就会变成普通推送。
静默推送的payload如下:
{
"aps" : {
"content-available" : 1
}
}
静默推送的前提:
- 只有app还在后台运行时,才能收到静默推送,否则推送了也没有用
- 跟普通推送类似,苹果对频率和到达性都不做保证。
参考:
How to generate a Push Notification certificate and download the Entrust Root Authority certificate