- 首先我們先介紹一下APNs工作原理
1)首先應(yīng)用程序會(huì)將'要發(fā)送的消息'和'設(shè)備令牌(deviceToken)'打包發(fā)給APNs。
2)APNs會(huì)在自己已經(jīng)注冊(cè)的iphone列表中根據(jù)'設(shè)備令牌(deviceToken)'查找目標(biāo)iphone。然后將消息發(fā)給目標(biāo)iphone。
3)iphone會(huì)把'消息'發(fā)送給相應(yīng)的程序,并且已設(shè)定的方式彈出。
利用PHP,實(shí)現(xiàn)一個(gè)簡(jiǎn)單的??吧?。。?/p>
需要(下面對(duì)應(yīng)的文件名稱噢):
php文件 : pushMe.php
certificates : aps_development-7.cer
appID : touteng
provisioning profiles : pp
p12(pem) : push.p12
配置證書(shū):
1、在進(jìn)行此步驟時(shí),假設(shè)已經(jīng)有了一個(gè)appID (此iD不可以是統(tǒng)配的,統(tǒng)配的不可以做推送) , 下載證書(shū)名字為 'aps_development-7.cer'

12A04E53-B8AF-4C1F-96AD-7F77F27FA888.jpg
下載證書(shū)'雙擊'導(dǎo)入鑰匙串中,假設(shè)證書(shū)名字是'aps_development-7.cer'.
終端輸入: 'openssl x509 -in aps_development-7.cer -inform der -out PushChatCert.pem'//生成的PushChatCert.pem將會(huì)和p12生成的pem合成ck.pem
2、配置app IDs
-
創(chuàng)建完成后Configurable 會(huì)變成綠色
7BA242CA-7AE5-4C38-947F-462D16DAE7AD.png

4410ABFE-3CBB-4B7D-BB65-DCC9E69A7B82.jpg
3、導(dǎo)出p12文件
'創(chuàng)建'并且'下載'然后'雙擊'證書(shū),進(jìn)入鑰匙串導(dǎo)出名為'push.p12'的文件,導(dǎo)出過(guò)程需要輸入密碼,例如1234

3A2E249F-51BB-45D2-A5E1-1762CFAACE5A.png
4、生成ck.pem文件
- 配置p12文件:push.p12
終端:'openssl pkcs12 -in pushCert.p12 -out PushChatKey.pem -nodes'
- 合成 'ck.pem'
然后將上一步生成的'PushChatCert.pem'和剛生成的'PushChatKey.pem'合并成'ck.em',我需要通過(guò)'ck.pem'進(jìn)行推送,一般推送不成功與'ck.pem'有關(guān)
終端: 'cat PushChatCert.pem PushChatKey.pem > ck.pem'
5、配置pp

AF2AE5B6-412C-4229-A974-0C1B6F0D803A.jpg
6.php文件
該文件參考http://blog.csdn.net/zhugq_1988/article/details/37656107 中的php文件
7.配置php文件
$deviceToken ='你的deviceToken';
$passphrase = '1234';//你設(shè)置的密碼
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');//生成的pem名字要相同,將你的pem文件和php文件放在同一目錄下
8.新建Xcode項(xiàng)目,配置好證書(shū)。
在AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge|UIUserNotificationTypeAlert|UIUserNotificationTypeSound categories:nil];
[application registerForRemoteNotifications];
[application registerUserNotificationSettings:settings];
} else {
[application registerForRemoteNotificationTypes:UIUserNotificationTypeSound | UIUserNotificationTypeBadge| UIUserNotificationTypeAlert];
}
return YES;
}
添加:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo {
NSLog(@"userInfo : %@", userInfo);
NSLog(@"收到:%@", [[userInfo objectForKey:@"aps"] objectForKey:@"alert"]);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:[[userInfo objectForKey:@"aps"] objectForKey:@"alert"] delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil, nil];
[alert show];
}
// 獲取Token
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
//注冊(cè)成功,將deviceToken保存到應(yīng)用服務(wù)器數(shù)據(jù)庫(kù)中
NSMutableString *deviceTokenString1 = [NSMutableString string];
const char *bytes = deviceToken.bytes;
int iCount = deviceToken.length;
for (int i = 0; i < iCount; i++) {
[deviceTokenString1 appendFormat:@"%02x", bytes[i]&0x000000FF];
}
}
// 獲取Token失敗返回信息
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"error : %@", error);
}
9.打開(kāi)終端,進(jìn)行推送
'cd'到php文件目錄下(確保你的pushMe.php和ck.pem在同一目錄下)
終端:php pushMeBaby.php
終端結(jié)果如下,你就可以看到手機(jī)的推送了:
bogon:~ wang$ cd /Users/wang/Desktop/LLLLLLLLL
bogon:LLLLLLLLL wang$ php pushMeBaby.php
Connected to APNS
Message successfully delivered
bogon:LLLLLLLLL wang$
如果沒(méi)有看到推送,1檢查deviceToken,2看看證書(shū)是否正確,3鑰匙串里面的證書(shū)是否失效了,4php文件配置是否正確。
(我剛開(kāi)始配置沒(méi)有成功是因?yàn)槲业蔫€匙串里面的證書(shū)全部失效了,參考網(wǎng)址:http://blog.csdn.net/manmanking/article/details/50668526)
?
-APNS 接口
消息推送:
開(kāi)發(fā)接口:gateway.sandbox.push.apple.com:2195
發(fā)布接口:gateway.push.apple.com:2195
反饋服務(wù):
開(kāi)發(fā)接口:feedback.sandbox.push.apple.com:2196
發(fā)布接口:產(chǎn)品接口:feedback.push.apple.com:2196
- 手機(jī)的deviceToken不是一成不變
- 檢驗(yàn)證書(shū)是否正確的方法:
$ telnet gateway.sandbox.push.apple.com 2195
Trying 17.172.232.226…
Connected to gateway.sandbox.push-apple.com.akadns.net.
Escape character is ‘^]’.
它將嘗試發(fā)送一個(gè)規(guī)則的,不加密的連接到APNS服務(wù)。如果你看到上面的反饋,那說(shuō)明你的MAC能夠到達(dá)APNS。按下Ctrl C 關(guān)閉連接。如果得到一個(gè)錯(cuò)誤信息,那么你需要確保你的防火墻允許2195端口。
- 然后再次連接,這次用我們的SSL證書(shū)和私鑰來(lái)設(shè)置一個(gè)安全的連接:
$ openssl s_client -connect gateway.sandbox.push.apple.com:2195
-cert PushChatCert.pem -key PushChatKey.pem
Enter pass phrase for PushChatKey.pem:
你會(huì)看到一個(gè)完整的輸出,讓你明白OpenSSL在后臺(tái)做什么。如果連接是成功的,你可以鍵入一些字符。當(dāng)你按下回車后,服務(wù)就會(huì)斷開(kāi)連接。如果在建立連接時(shí)有問(wèn)題,OpenSSL將會(huì)給你一個(gè)錯(cuò)誤消息,但是你不得不向上翻輸出LOG,來(lái)找到它。
當(dāng)然上面要測(cè)試prodution版本是否正確的話,把
gateway.sandbox.push.apple.com換成
gateway.push.apple.com就好。
補(bǔ)充:
獲取Token 的幾種方法:
第一種:
-(NSString *)stringWithDeviceToken:(NSData *)deviceToken
{
const char *data = [deviceToken bytes];
NSMutableString *token = [NSMutableString string];
for (int i = 0; i < [deviceToken length]; i++)
{
[token appendFormat:@"%02.2hhX", data[i]];
}
return [token copy];
}
第二種:
NSString *deviceTokenString2 = [[[[deviceToken description] stringByReplacingOccurrencesOfString:@"<"withString:@""]
stringByReplacingOccurrencesOfString:@">" withString:@""]
stringByReplacingOccurrencesOfString:@" " withString:@""];
第三種:
上述代碼中的一種。
忘了參考的那個(gè)的網(wǎng)址了,嘿嘿??!
參考:
http://blog.csdn.net/jiajiayouba/article/details/39926017
http://stephen830.iteye.com/blog/1702748
http://blog.csdn.net/studyrecord/article/details/39620377
