市面上有很多第三方推送,实现起来也很丰富,但是作为开发,多少还是得了解下原生的不,因为有些公司没有用原生的,重要的事现在有些第三方已经开始收费了,对于iOS,自己创建并不麻烦,只是后台可能会多点事情,废话不多说
-
APNS 的推送机制
首先看下苹果官方的解释
这个图更直观更简介,Provider就是我们自己的后台,APNS是Apple Push Notification Service的缩写,意思就是苹果的推送服务
其实更直观的解释分为三步:
第一步:我们自己的后台服务器把要发送的消息,目的iPhone的标示打包发给我APNS
第二步:APNS在自身的已注册的push服务的iphone列表中国年,查找有相应的标识iphone,并把消息发送给iphone
第三步:iphone把发来的消息传递给相应的应用程序,并且按照设定弹出push通知
-
APNS推送通知的详细工作流程
上面这张图是说明APNS推送通知的详细工作流程:
流程也可以分为如下几部:
第一步:应用程序也就是我们的app注册APNS的消息推送
第二步:iOS从APNS Server获取devicetoken,app会在代理中接受到devicetoken
第三步:服务端程序向APNS发送消息
第四步:APNS服务将消息发给我iPhone的应用程序
-
开始我们的从无到有验证
-
生成各种证书
-
1.csr证书
选择保存到磁盘,新建一个桌面文件夹“远程推送”,把刚生成的文件保存到这个文件夹
就是如下文件
-
2.创建APP ID
然后一直点 最后 Done就行了,刷新你会发现你刚刚注册的app id
-
3.申请推送的开发者证书
如果你之前没有创建过 Push 证书或者是要重新创建一个新的,请在证书列表下面新建
所以我们选择开发推送证书,因为调试和开发都能用
点下一步
然后一直点,直到
继续
先下载下来,再点完成
-
4. 重新生成下配置文件
![Uploading A351FD61-44B9-49F4-B9F2-20D0D824B056_755548.png . . .]
选择开发的吧
然后一直seleted all 直到
然后一直点,最后把它下载下来,因为可以导出给其他同事一起用
-
5.导出证书
先不管最后生成的配置证书,在第三步生成的
这个证书导出为Push.p12,这步就不多说了,导出的时候可以设置密码
因为我xcode有账号,所以我只做了1235,没有做第四步
好,继续
-
处理证书
现在我的文件夹里有
下面我们打开终端。
cd到桌面,我们那三个文件所在的位置
-
1.把.cer的SSL证书转换为.pem文件,执行命令:
openssl x509 -in aps.cer -inform der -out PushChatCert.pem
文件夹里会生成一个PushChatCert.pem文件
-
2.把私钥Push.p12文件转化为.pem文件
openssl pkcs12 -nocerts -out PushChatKey.pem -in Push.p12
这里需要我们输入密码,这个密码也就是我们导出p12文件时的密码,也就是我们上面设置的密码。然后,需要我们对生成的pem文件设置一个密语,这里我们推荐还是用上面这个密码,防止混乱(当然你也可以设置成别的更有意义的密语),这里的密语是要告诉我们服务器的。这样,桌面上又会生成一个PushChatKey.pem文件
-
3.对生成的这两个pem文件再生成一个pem文件,来把证书和私钥整合到一个文件里:
cat PushChatCert.pem PushChatKey.pem > ck.pem
生成ck.pem文件
-
4.验证证书是否工作
这样,我们的文件就制作完了。下面进入测试阶段
为了测试证书是否工作,执行下面的命令:
telnet gateway.sandbox.push.apple.com 2195
它将尝试发送一个规则的,不加密的连接到APNS服务。如果你看到上面的反馈,那说明你的MAC能够到达APNS。按下Ctrl+C关闭连接。如果得到一个错误信息,那么你需要确保你的防火墙允许2195端口。一般这里都不会出现什么问题。
下面我们要使用我们生成的SSL证书和私钥来设置一个安全的链接去链接苹果服务器
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem
执行完这一句命令后需要我们输入密语
Enter pass phrase for PushChatKey.pem:
我们输入abcabc按回车
你会看到一个完整的输出,让你明白OpenSSL在后台做什么。如果链接是成功的,你可以随便输入一个字符,按下回车,服务器就会断开链接,如果建立连接时有问题,OpenSSL会给你返回一个错误信息。
当你在最后的时候你看到这样说明你已经成功了:
-
开始测试
打开你的xocde工程,这个工程的build ID必须和创建证书的第二步的app ID要一样
而且需要打开远程通知的开关
上代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationType type = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:type
categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
}
//注册远程通知
[application registerForRemoteNotifications];
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);
}
问题来了,如果注册远程推送成功,那么到了devicetoken,就传给服务器,如果现在没有服务器怎么办
有个mac工具:https://github.com/shaojiankui/SmartPush
有一个php的文件,直接复制出代码吧,因为上传文件一直失败,文件: pushMe.php xcode可打开
<?php
// Put your device token here (without spaces):
$deviceToken = '0144f60c92325eae3cbc3abe618f34c85d1dfb466360efd1065901180444a467';
// Put your private key's passphrase here:密语
$passphrase = 'abc123';
// Put your alert message here:
$message = 'frist push ! —-test';
////////////////////////////////////////////////////////////////////////////////
$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);
?>
然后在终端(记住将终端切换桌面位置 因为你的php后台和推送证书在桌面路径位置)运行命令(如果刚才你关闭了终端的话,最好ls一下,看看当前是不是在桌面),执行命令:
php pushMe.php
然后回车(pushMe为服务器文件名称)
那么此时iphone就来推送了