http://blog.csdn.net/shenjie12345678/article/details/41120637#comments
这位兄弟写的很详细,我只是简化了一下方便自己使用,如果想详细了解的,直接去这个地址吧。
环境:证书齐全,并加入了了推送的能力。
现在push文件夹中应该放2个文件“aps_development .cer”(certificates获得的证书文件) ,"push.p12"(钥匙串里导出的文件).
先处理出两个pem文件:
openssl x509 -in aps_development.cer -inform der -out PushChatCert.pem
openssl pkcs12 -nocerts -out PushChatkey.pem -in push.p12
要先输入p12的密码,然后输入两次设置pem的密码。
cat PushChatCert.pem PushChatkey.pem > ck.pem
合并刚才生出来的pem文件。
测试网络情况
telnet gateway.sandbox.push.apple.com 2195
这这样就代表是正常的。
用我们的签名文件,连接苹果的服务器。
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem
会返回一些数据,类似于:
depth=1 /C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
0 s:/C=US/ST=California/L=Cupertino/O=Apple Inc./CN=gateway.sandbox.push.apple.com
i:/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C
1 s:/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C
i:/O=Entru
。。。。。。。。。。。。
。。。。。。。。。。。。
。。。。。。。。。。。。
。。。。。。。。。。。。
SSL-Session:
Protocol : TLSv1
Cipher : AES256-SHA
Session-ID:
Session-ID-ctx:
Master-Key: 76B1E876F979DF013598198B8EC834066C08AAAE2A53C0E4066040B590958BD3530E9164766CC30089779D403A7B95A1
Key-Arg : None
Start Time: 1456202361
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
//
// AppDelegate.m
// push
//
// Created by wangxiongtao on 16/2/20.
// Copyright © 2016年 wangxiongtao. All rights reserved.
//
#import "AppDelegate.h"
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(@"++++%@+++++",launchOptions);
#ifdef __IPHONE_8_0
if ([[UIApplicationsharedApplication]respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationSettings *settings = [UIUserNotificationSettingssettingsForTypes:UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlertcategories:nil];
[application registerUserNotificationSettings:settings];
} else {
UIRemoteNotificationType myTypes =UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeAlert |UIRemoteNotificationTypeSound;
[ application registerForRemoteNotificationTypes:myTypes];
}
#else
[application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert)];
#endif
self.window = [[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColorwhiteColor];
[self.windowmakeKeyAndVisible];
_manviewController = [[ViewControlleralloc]init];
self.window.rootViewController =self.manviewController;
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
application.applicationIconBadgeNumber =0;
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{
NSLog(@"---Token--%@", pToken);
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
NSLog(@"userInfo == %@",userInfo);
NSString *message = [[userInfo objectForKey:@"aps"]objectForKey:@"alert"];
_url = [[userInfo objectForKey:@"aps"] objectForKey:@"sound"];
UIAlertView *alert = [[UIAlertViewalloc]initWithTitle:@"提示"message:messagedelegate:selfcancelButtonTitle:@"取消"otherButtonTitles:@"确定",nil];
[alert show];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
NSLog(@"Regist fail%@",error);
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
[[UIApplicationsharedApplication]openURL: [NSURLURLWithString:_url ]];
}
}
#ifdef __IPHONE_8_0
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[application registerForRemoteNotifications];
}
#endif
@end
PHP服务端
将simplepush.php这个推送脚本也放在push文件夹中
代码部分#######################
<?php
// ??????????deviceToken???????????????
//$deviceToken = 'c95f661371b085e2517b4c12cc76293522775e5fd9bb1dea17dd80fe85583b41';
$deviceToken = 'ee66b79484e46ded099f54f8e2dbf9591da9db999ce951184dd49a165f036524';
// Put your private key's passphrase here:
$passphrase = '123123';
// Put your alert message here:
$message = 'My first 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.push.apple.com:2195?, $err, $errstr, 60, //STREAM_CLIENT_CONNECT, $ctx);
//?????????????appstore??????
$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' ,
'badge' => 2
);
// 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);
?>
###########################
在最上面的
$deviceToken = 后面要换成自己的token。
$passphrase = 后面换证自己设置的密码。
完整的工程,和php文件在:git@github.com:mgya/push.git
其他的一些说明。
iOS 设备收到一条推送(APNs),用户点击推送通知打开应用时,应用程序根据状态不同进行处理需在 AppDelegate 中的以下两个方法中添加代码以获取apn内容
- 如果 App 状态为未运行,此函数将被调用,如果launchOptions包含UIApplicationLaunchOptionsLocalNotificationKey表示用户点击apn 通知导致app被启动运行;如果不含有对应键值则表示 App 不是因点击apn而被启动,可能为直接点击icon被启动或其他。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
// apn 内容获取:NSDictionary *remoteNotification = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey]
|
- 如果 App状态为正在前台或者后台运行,那么此函数将被调用,并且可通过AppDelegate的applicationState是否为UIApplicationStateActive判断程序是否在前台运行。此种情况在此函数中处理:
- (
void
)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo;
// apn内容为userInfo
|
- 如果是使用 iOS 7 的 Remote Notification 特性那么处理函数需要使用
- (
void
)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(
void
(^)(UIBackgroundFetchResult))completionHandler;
// apn内容为userInfo
|
aps = {
alert = "推送信息";//推送显示的问题信息在这里
badge = 1;//app的icon右上角的推送数字 在这里设置
sound = "XXX.caf";//可以为空,为空就是默认的声音
};