APNS消息推送(node.js实现)
一、 推送流程
步骤:
1.应用程序需要激活推送通知功能。在使用之前,用户需要确认他是否愿意接受这些推送功能。
2.IOS跟APNSServer要deviceToken,应用程序接到一个“devicetoken”。你可以认为“devicetoken”是推送通知发送信息的目的地址。
3.应用程序会将“devicetoken”发送给PUSH服务端程序(Provider)。
4.当你的应用程序发生了有趣的事情,你的服务器向“苹果推送通知的服务器(ApplePush Notification Service,缩写,APSN)”发送通知。
5.APNS服务将消息通知发送到用户的设备(例如,iPhone,iPad等)的应用程序。
备注:
产品发布APNS服务器,gateway.push.apple.com
测试APNS服务器,gateway.sandbox.push.apple.com
二、 获取证书,无论是客户端和APNS,还是Provider和APNS,都需要通过证书进行连接
提示:
(1)需要申请Apple开发者帐号,准备一台真实设备。模拟器没有DeviceToken,不能测试APNS;
(2)收到提醒时,如果程序在前台打开会看不到提醒。
1)在Apple开发者中心创建AppID
创建时勾选AppServices-PushNotifications。AppID Suffix选择通用AppID(Wildcard App ID)还是固定AppID(Explicit App ID)都可以,如果要开发多个App可以选择通用AppID。创建成功后在Identifiers-AppIDs可以查看,点击之前创建的AppID,在展开的菜单中点击[Settings]按钮进入配置界面。
在配置界面中找到PushNotifications,点击[CreateCertificate...]按钮创建SSL证书。DevelopmentSSL Certificate 和 ProductionSSL Certificate对应开发环境和生产环境,选择DevelopmentSSL Certificate。
备注:也可以点击左侧导航菜单的Certificates,来添加一个APNs证书。选择ApplePush Notification service SSL (Sandbox),之后的步骤相同。
2) 生成CSR(证书请求)文件
在Mac系统中打开实用工具-钥匙串-钥匙串访问-证书助理-从证书颁布机构请求证书,填入邮箱和名称,选择[存储到磁盘],得到一个名为CertificateSigningRequest.certSigningRequest的证书请求文件,同时会在登陆- 密钥里新增两条纪录,一个公用密钥和一个专用密钥:
回到Apple开发者中心的网页,点击[Continue]继续,上传生成的CertificateSigningRequest.certSigningRequest文件。完成这一步就可以得到.cert文件了。
3)App开发过程中要在真实设备上调试,需要DevelopmentProvisioning profile和DevelopmentCertificate。
在 左侧导航菜单-Devices,添加一个ios设备。UUID可以在iTunes里查到。然后增加一个iOSApp Development的Certificate和ProvisioningProfile:
4)最后得到一个证书文件,和一个.mobileprovision后缀的文件,就是ProvisioningProfile文件了。
安装证书文件,将.mobileprovision文件通过Xcode导入设备中。一般连接iso设备时Xcode会自动弹出,也可以在Xocde菜单的Help-Xcode Help-Devices修改ProvisioningProfile文件。下图是在Apple开发者中心创建的ProvisioningProfile:
备注:要保证AppID和程序的TargetProperies-Bundleidentifier的值相同,否则会报错。
5)安装
切换到左侧导航菜单的Certificates,找到之前生成的APNsDevelopmentiOS证书,点击[Download]按钮下载,得到aps_development.cer。安装后,在钥匙串访问中找到对应的证书。
6)导出Provider需要的证书和专用密钥
选中AppleDevelopment IOS Push Services: org.dmyz.app上点击右键,选择[导出AppleDevelopment IOS Push Services:org.dmyz.app],文件格式切换成.cer,导出为cert.cer。点击左侧▶展开它,可以看到名为dmyz,类别为[专用密钥]的这个子项,选中导出为key.p12。
7)将导出的文件进行openssl处理
方法一:
opensslx509 -in cert.cer -inform DER -outform PEM -out cert.pem
opensslpkcs12 -in key.p12 -out key.pem -nodes
备注:会要求输入importPassword,如果导出时没有设置则为空
方法二:
opensslpkcs12 -clcerts -nokeys -out cert.pem -in cert.p12
opensslpkcs12 -nocerts -out key.pem -in key.p12
cat cert.pem key.pem >key.pem
备注:主要差别是key没有加nodes参数,最后把两个文件合并了。测试过可以通过。执行第二条命令时需要输入PEMpass phrase,至少4个字符。
现在得到key.pem和cert.pem文件了,无论服务是NodeJS,Python还是Ruby,这只需要这两个文件。
三、 推送程序
1)客户端:通知计数、点击通知执行的函数等细节设置和Locationnotification相同,区别是要指定Device。Xcode中打开项目的AppDelegate.m文件中增加一个函数,来获取设备Token:
(void)application:(UIApplication*)applicationdidRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken{
NSLog(@"deviceToken: %@", deviceToken); }
2)服务器端:
安装apn,把key.pem和cert.pem拷贝到项目目录(也可不用,可在程序中指定路径即可)。
varapn=require('apn');
var token = '7eda0e6e775f50f7da3998423c8bd06a0ca505213ec241b22d2507b626dd6498'; //长度为64的设备Token,去除空格 var options = { "cert": "/..../cert.pem", //cert.pem文件的路径 "key": "/..../key.pem", //key.pem文件的路径 "gateway": "gateway.sandbox.push.apple.com", "port": 2195}, apnConnection = new apn.Connection(options), device = new apn.Device(token), note = new apn.Notification(); note.expiry = Math.floor(Date.now() / 1000) + 60; note.badge = 3; note.alert = 'test APNS '; note.sound = 'default'; note.payload = {'messageFrom': 'Caroline'}; note.device = device; apnConnection.pushNotification(note, device);
还可添加相应的事件处理:
apnConnection.on('connected',function() {
console.log("Connected");
});
apnConnection.on('transmitted',function(notification, device) {
console.log("Notificationtransmitted to:" + device.token.toString('hex'));
});
apnConnection.on('transmissionError',function(errCode, notification, device) {
console.error("Notificationcaused error: " + errCode + " for device ", device,notification);
});
apnConnection.on('timeout',function () {
console.log("ConnectionTimeout");
});
apnConnection.on('disconnected',function() {
console.log("Disconnectedfrom APNS");
});
apnConnection.on('socketError',console.error);
运行服务器程序,客户端即可收到推送消息。