感謝Hello杰少的文章,我在此基礎(chǔ)上進(jìn)行豐富
1/11. 獲取CSR文件
為了便于文件管理,所有文件都放在AppPush文件夾中。命令行中的命令也在改文件夾下。
本次操作基于開發(fā)模式下,生產(chǎn)模式下類同,相關(guān)文件改為在Distribution下創(chuàng)建即可。
2/11. 進(jìn)入MemberCenter,選擇創(chuàng)建 AppID。填寫App ID Description,然后選擇Explicit App ID(推送不能使用模糊匹配的id)填寫你所要開發(fā)的app的準(zhǔn)確Bundle ID
。 同時(shí)要在App Services中勾選Push Notifications,然后continue,然后register。
3/11. 接下來(lái)配置推送證書??梢栽赼ppID中配置,也可以在Certificates配置,但在appID中更便捷。 選擇剛剛創(chuàng)建的appID,然后可以看到Push Notifications處于可設(shè)置狀態(tài),選擇Edit。
4/11. 接下來(lái)在push notifications下選擇創(chuàng)建證書,此時(shí)其實(shí)也就是跳轉(zhuǎn)到了Certificates中來(lái)配置。
5/11. 接下來(lái)continue,然后在提示要csr文件時(shí)提交剛開始創(chuàng)建的csr文件,然后生成證書,下載下來(lái)后保存文件名為aps_push.cer,然后雙擊證書自動(dòng)安裝到鑰匙串中。
6/11 接著還需要mobileprovision文件。選擇創(chuàng)建profile,然后選擇iOS App Development,點(diǎn)擊continue。選擇上面創(chuàng)建的AppID,選擇開發(fā)者賬號(hào),選擇測(cè)試設(shè)備,然后一路continue,最后輸入profile文件名,這里設(shè)為pushTest。然后Generate,再下載下來(lái)雙擊即可自動(dòng)安裝到xcode中。
7/11. 在鑰匙串中找到剛剛安裝的aps_push.cer證書,右鍵選擇導(dǎo)出,然后這里最好把存儲(chǔ)文件名修改為英文,然后選擇存儲(chǔ)。接著要求設(shè)置證書密碼,這里設(shè)置為abc123,然后還要輸入管理員密碼。搞定這些,所需要的p12文件就OK了。
8/11. 在接下來(lái)還要對(duì)證書進(jìn)行整合處理,在終端中進(jìn)入AppPush文件夾,
然后執(zhí)行命令openssl x509 -in aps_push.cer -inform der -out PushCert.pem
獲得一個(gè)PushCert.pem文件。
接著再執(zhí)行命令openssl pkcs12 -nocerts -in pushTest.p12 -out PushKey.pem
,這時(shí)需要輸入p12文件的密碼,就是上邊設(shè)置的abc123,然后還要設(shè)置PushKey.pem文件的密碼,依然設(shè)為abc123. 最后獲的一個(gè)PushKey.pem文件。
然后還有最后一擊,執(zhí)行命令cat PushCert.pem PushKey.pem > ck.pem
獲取最終服務(wù)器要用的ck.pem文件。
9/11. 經(jīng)過(guò)以上的步驟,所需要的文件都準(zhǔn)備好了,但是為了確保完事具備,還要進(jìn)行簡(jiǎn)單的測(cè)試。
執(zhí)行命令telnet gateway.sandbox.push.apple.com 2195
,檢測(cè)是否可以訪問(wèn)apple的推送服務(wù)器.顯示如下則表明是OK的。(中間需要使用control+c來(lái)中斷連接)
執(zhí)行命令openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushCert.pem -key PushKey.pem
測(cè)試上面生成的證書是否OK。內(nèi)容很多,但只用關(guān)心最后是否如圖所示,是則表示證書是OK的。這里也要輸入密碼及用control+c中斷連接
10/11. 經(jīng)過(guò)上面的繁瑣步驟終于準(zhǔn)備好素材了。。。。。。開始實(shí)際代碼開發(fā)吧。 新建工程,保證工程的Bundle ID和上邊請(qǐng)求證書時(shí)使用的Bundle ID一致即可。然后代碼的戰(zhàn)場(chǎng)在AppDelegate.m中,不涉及其他地方。運(yùn)行一次程序,從log信息中獲取到deviceToken值(注意:如果上面沒(méi)有安裝profile文件,那么也會(huì)獲取到一個(gè)deviceToken值,但是這個(gè)值是沒(méi)卵用的)。
//
// AppDelegate.m
// apnsTest
//
// Created by yuweiMac on 16/4/28.
// Copyright ? 2016年 yuweiMac. All rights reserved.
//
#import "AppDelegate.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// 調(diào)用該方法有3種路徑:點(diǎn)擊appIcon或者點(diǎn)擊通知進(jìn)入或者第三方應(yīng)用跳轉(zhuǎn)。
// 如果點(diǎn)擊appIcon進(jìn)入時(shí)launchOptions為nil。其他則 !nil,但兩者的key同
if (launchOptions == nil) {
[self showAlertWithTitle:@"由AppIcon啟動(dòng)" msg:[launchOptions description]];
}else{
if ([[launchOptions allKeys] containsObject:@"UIApplicationLaunchOptionsURLKey"]) {
[self showAlertWithTitle:@"由第三方應(yīng)用啟動(dòng)" msg:[launchOptions description]];
} else {
[self showAlertWithTitle:@"點(diǎn)擊通知啟動(dòng)" msg:[launchOptions description]];
}
}
// 注冊(cè)推送權(quán)限.iOS8之前的注冊(cè)方式不一樣,但現(xiàn)在最低兼容ios8,忘了7吧
// if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
// {
//IOS8
//創(chuàng)建UIUserNotificationSettings,并設(shè)置消息的顯示類類型
// 可以通過(guò)判斷是否已經(jīng)注冊(cè)遠(yuǎn)程通知來(lái)決定是否要進(jìn)行注冊(cè)操作,這里不這么做。
// if (![application isRegisteredForRemoteNotifications]) {
// 注冊(cè)通知權(quán)限
UIUserNotificationSettings *notiSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil];
[application registerUserNotificationSettings:notiSettings];
// 注冊(cè)遠(yuǎn)程通知
[application registerForRemoteNotifications];
// }
// } else{ // ios7
// [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert)];
// }
return YES;
}
-(void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{
// 成功注冊(cè)消息通知權(quán)限
NSLog(@"成功注冊(cè)消息通知");
}
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
// 成功注冊(cè)遠(yuǎn)程推送并獲得deviceToken信息
NSLog(@"didRegisterForRemote---deviceToken-->%@", deviceToken);
}
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
// 注冊(cè)遠(yuǎn)程推送失敗
NSLog(@"FailToRegisterForRemoteN---fail-->%@",error);
}
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
// 當(dāng)應(yīng)用在前臺(tái)時(shí)接收到遠(yuǎn)程推送消息
[self showAlertWithTitle:@"收到遠(yuǎn)程推送消息" msg:[userInfo description]];
}
//當(dāng)從第三方應(yīng)用跳轉(zhuǎn)到本應(yīng)用時(shí)會(huì)調(diào)用該方法
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
NSLog(@"-->%@ -->%@",url,sourceApplication);
return YES;
}
//彈出信息警告框
-(void)showAlertWithTitle:(NSString*)title msg:(NSString*)msg{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:msg delegate:nil cancelButtonTitle:nil otherButtonTitles:@"確定",nil];
[alert show];
}
@end
11//11.接下來(lái)要寫一個(gè)AppPush.php文件,來(lái)向apns服務(wù)器發(fā)送內(nèi)容。
需要注意的幾個(gè)地方:deviceToken填寫你接收到的token;passPhrase則填寫你的ck.pem設(shè)置的密碼。當(dāng)然如果你在上邊保存文件時(shí)命名不是ck,那還需要替換程序內(nèi)的文件名稱$pemFile。 最后再在終端中執(zhí)行命令php AppPush.php
,然后一切都應(yīng)該很美好的OK了。
<?php
// ??????????deviceToken???????????????
$deviceToken = '493c0d7eaa19a529a4422cd9ee779fc474f95b9915051118887fed7e1b0af85f';
// Put your private key's passphrase here:
$passphrase = 'abc123';
$pemFile = 'ck.pem';
// Put your alert message here:
$message = 'My first push test!';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $pemFile);
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);
?>