最近的项目中使用到了推送,第一次搞推送,遇到了不少坑,所以记录下来。
参考:手把手教你做IOS推送
APNS的推送机制
首先我们看一下苹果官方给出的对iOS推送机制的解释。如下图
Provider就是我们自己程序的后台服务器,APNS是Apple Push Notification Service的缩写,也就是苹果的推送服务器。
上图可以分为三个阶段:
第一阶段:应用程序的服务器端把要发送的消息、目的iPhone的标识打包,发给APNS。
第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发送到iPhone。
第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。
APNS推送通知的详细工作流程
下面这张图是说明APNS推送通知的详细工作流程:
根据图片我们可以概括一下:
1、应用程序注册APNS消息推送。
2、iOS从APNS Server获取devicetoken,应用程序接收device token。
3、应用程序将device token发送给程序的PUSH服务端程序。
4、服务端程序向APNS服务发送消息。
5、APNS服务将消息发送给iPhone应用程序。
好啦,流程讲完,再来讲讲要准备的东西
1.一台iphone。ipod 或者ipad
2.开发者账户
3.IOS开发环境
下面,正式开始。
一.新建工程
记住我们的Bundle Identifier是 com.slpcb.PushDemo
二.制作证书
我们的客户端与苹果服务器之间和我们自己的服务器与苹果服务器之间都需要证书来进行链接。下面我们来开始进入证书的制作过程。
1.生成CSR文件
首先我们要有生成一个Certificate Signing Request(也就是CSR)的请求文件。
打开钥匙串访问,点击 钥匙串访问-》证书助理-》从证书颁发机构请求证书
2.制作证书
进入苹果开发者网站,
添加新的APPID
填写必要信息
注意必须填写确定的appid,通配的时不可以的
勾选push notification,然后点击继续
接下来就是提交
然后下载证书(记得下载后双击安装)
3.生成Profile
证书生产好了之后 ,我们还需要对应的Profile文件
照例先进入管理界面,点击添加
继续
现则App ID,继续
选择证书,继续
选择设备,继续
起个名字,继续
好啦,完成啦 ,下载下来
制作证书完毕,接下来就是处理它们了。
首先先把证书导出来。
打开钥匙串访问 ,右击导出我们刚刚生成的证书
起个名字
设置密码,这个密码很重要。要记住。这里我设置为123456
现在来整理一下,做了上面的步骤之后。我们得到了下面几个文件
1.PushDemoDev.certSigningRequest CSR文件
2.aps_development.cer SSL证书文件
3.PushDemo.p12 秘钥文件
但是这些还不够,我们需要的是生成一个后缀为pem的文件,接下来我们搞定它
打开终端,定位到我们那几个文件所在的位置
1、把.cer的SSL证书转换为.pem文件,执行命令:
openssl x509 -in aps_development.cer -inform der -out PushChatCert.pem
在推送整理文件夹内会生成一个PushChatCert.pem文件
2、把私钥PushDemo.p12文件转化为.pem文件:
openssl pkcs12 -nocerts -out PushChatKey.pem -in PushDemo.p12
,这里会让你输入3次密码,第一次是你到处p12文件的时候设置的密码,也就是我们上面设置的123456
第二第三次是对我们生成的pem文件设置密码,这个密码是需要告诉服务器的。为了方便,我们还是设置为123456
3、对生成的这两个pem文件再生成一个pem文件,来把证书和私钥整合到一个文件里:
cat PushChatCert.pem PushChatKey.pem > ck.pem
生成ck.pem文件
下面我们要使用我们生成的SSL证书和私钥来设置一个安全的链接去链接苹果服务器:
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem
执行完这一句命令后需要我们输入密语
Enter pass phrase for PushChatKey.pem:
我们输入123456按回车
你会看到一个完整的输出,让你明白OpenSSL在后台做什么。如果链接是成功的,你可以随便输入一个字符,按下回车,服务器就会断开链接,如果建立连接时有问题,OpenSSL会给你返回一个错误信息。
如果看到下面的反馈,说明你成功了
好啦,此间事了,改去看看我们一开始新建的工程了
打开工程PushDemo
打开AppDelegate
换上
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//推送的形式:标记,声音,提示
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert];
return YES;
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken {
NSLog(@"regisger success:%@",pToken);
//注册成功,将deviceToken保存到应用服务器数据库中
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
// 处理推送消息
NSLog(@"userinfo:%@",userInfo);
NSLog(@"收到推送消息:%@",[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]);
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"Registfail%@",error);
}
然后设置
好的 run 一个。成功进入后,应用会弹出窗口让用户确认接收通知
这时,我们看看xcode的output,里面输出了我们苹果机器的deviceToken,把它记下来
点击 好。
接下来就是我们的服务端登场了
里面的代码如下
这里要注意的是
$deviceToken 的值换成我们上面得到的deviceToken,空格去掉
$passphrase 是我们之前设置的密码,123456
<?php
// Put your device token here (without spaces):
$deviceToken = ‘978042ec5cda4a0e790b14431d00e33218c9707526d3ac3cf0d8549b72cef2cd‘;
// Put your private key‘s passphrase here:密语
$passphrase = ‘123456‘;
// Put your alert message here:
$message = ‘发布测试!"‘;
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, ‘ssl‘, ‘local_cert‘, ‘ck.pem‘);
stream_context_set_option($ctx, ‘ssl‘, ‘passphrase‘, $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
‘ssl://gateway.sandbox.push.apple.com:2195‘, $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo ‘Connected to APNS‘ . PHP_EOL;
// Create the payload body
$body[‘aps‘] = array(
‘alert‘ => $message,
‘sound‘ => ‘default‘
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack(‘n‘, 32) . pack(‘H*‘, $deviceToken) . pack(‘n‘, strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo ‘Message not delivered‘ . PHP_EOL;
else
echo ‘Message successfully delivered‘ . PHP_EOL;
// Close the connection to the server
fclose($fp);
?>
把我们的pushMe.php放在证书的那个目录,然后终端定位到该目录
执行:php pushMe.php
yeah, 大功告成!
不过,这只是开发版的而已,如果是要发布版,则要创建对应的发布版证书,当然,地址也得变变。
APNS地址
测试地址gateway.sandbox.push.apple.com:2195
发布地址 gateway.push.apple.com:2195
测试的地址用的是沙盒,发布地址是不同的。发布软件的时候记得改过来.
原文地址:http://blog.csdn.net/simafeiyu/article/details/41241535