iOS 遠(yuǎn)程消息推送 APNS推送原理和一步一步開發(fā)詳解篇

前言:現(xiàn)在第三方推送也很多 ,比如極光轴捎,融云蚕脏,信鴿侦副,其原理也是相同利用APNS推送機(jī)制 ,前段公司讓做自己的推送驼鞭,1.避免device token被第三方泄露秦驯,保護(hù)手機(jī)設(shè)備信息,2.第三方部分開始收費(fèi)挣棕,一些免費(fèi)的以后誰又知道呢 译隘,不如自己創(chuàng)建,除了后臺麻煩點(diǎn)洛心,需要數(shù)據(jù)庫來存儲token相關(guān)字段(后臺配置部分在最后更新添加)固耘,前端實(shí)現(xiàn)起來并不復(fù)雜 。 對于iOS8.0以后皂甘,原生推送實(shí)時性很好玻驻,這篇文章參考許多資料將詳細(xì)的過程講解它 按照一步一步來很容易實(shí)現(xiàn) 。先從推送機(jī)制開始

1.APNS的推送機(jī)制

首先我們看一下蘋果官方給出的對ios推送機(jī)制的解釋。如下圖


Provider就是我們自己程序的后臺服務(wù)器璧瞬,APNS是Apple Push Notification Service的縮寫户辫,也就是蘋果的推送服務(wù)器。
上圖可以分為三個階段:
第一階段:應(yīng)用程序的服務(wù)器端把要發(fā)送的消息嗤锉、目的iPhone的標(biāo)識打包渔欢,發(fā)給APNS。
第二階段:APNS在自身的已注冊Push服務(wù)的iPhone列表中瘟忱,查找有相應(yīng)標(biāo)識的iPhone奥额,并把消息發(fā)送到iPhone。
第三階段:iPhone把發(fā)來的消息傳遞給相應(yīng)的應(yīng)用程序访诱,并且按照設(shè)定彈出Push通知垫挨。

APNS推送通知的詳細(xì)工作流程
下面這張圖是說明APNS推送通知的詳細(xì)工作流程:

根據(jù)圖片我們可以概括一下:
1、應(yīng)用程序注冊APNS消息推送触菜。
2九榔、iOS從APNS Server獲取devicetoken,應(yīng)用程序接收device token涡相。
3哲泊、應(yīng)用程序?qū)evice token發(fā)送給程序的PUSH服務(wù)端程序。
4催蝗、服務(wù)端程序向APNS服務(wù)發(fā)送消息械筛。
5抖所、APNS服務(wù)將消息發(fā)送給iPhone應(yīng)用程序。

準(zhǔn)備工作
首先要有一臺蘋果的設(shè)備劲绪,模擬器是不支持推送的哄孤,所以你需要一臺iphone灌灾,ipod touch或者ipad掌呜。

我們的客戶端與蘋果服務(wù)器之間和我們自己的服務(wù)器與蘋果服務(wù)器之間都需要證書來進(jìn)行鏈接毫捣。下面我們來開始進(jìn)入證書的制作過程。

2.注冊證書

首先蘋果證書主要分為上線證書和測試證書遍尺,相信都有所了解 在此不再累贅了 ,接下來就開始制作吧

一 CSR文件
首先我們要有生成一個Certificate Signing Request(也就是CSR)的請求文件涮拗。
在應(yīng)用程序里的使用工具中找到鑰匙串訪問乾戏。


Snip20160728_10.png

填上你的郵箱和常用名 或者是公司關(guān)聯(lián)賬號,常用名要記一下三热,一會
會用到鼓择。


Snip20160728_13.png

然后選擇保存到磁盤,繼續(xù)


Snip20160728_15.png

這時桌面上會有一個CertificateSigningRequest.certSigningRequest的請求文件就漾,也就是我們說的CSR文件呐能。在我們生成CSR文件的同時,會在鑰匙串訪問中生成一對秘鑰,名稱為剛才我們填寫的常用名

二 下載開發(fā)證書和發(fā)布證書

https://developer.apple.com/devcenter/ios/index.action 登錄后,在右側(cè)的ios Developer Program里點(diǎn)擊iOS Provisioning Portal摆出。
進(jìn)入下一級頁面后在左側(cè)選擇Certificates

點(diǎn)擊紅色的部分生成一個開發(fā)證書


點(diǎn)擊選擇文件朗徊,選擇剛才我們生成到桌面的CSR請求文件。
注意偎漫,如果你在后面測試的時候出現(xiàn)了問題爷恳,請檢查一下這里,這里的CSR請求文件必須是我們剛才生成的那個



選擇完成后點(diǎn)擊Submit提交


提交完成后返回頁面象踊。頁面會是這樣的温亲,然后我們刷新一下頁面


刷新后會出現(xiàn)一個下載按鈕,我們點(diǎn)擊下載”兀現(xiàn)在我們的開發(fā)證書已經(jīng)配置并下載好了栈虚,發(fā)布證書的配置過程和開發(fā)證書是一致的,不再贅述史隆。下載完后雙擊魂务,會跳到鑰匙串訪問里。這就是我們之后要進(jìn)行測的證書

三 配置AppID逆害,配置并下載SSL證書
點(diǎn)擊左側(cè)的App IDs头镊,找到我們要做推送功能的程序的id(如果沒有的話要先New一個。注意:這里的App ID必須不能是通配的魄幕,通配的不可以做推送)
點(diǎn)擊Configure

進(jìn)入后默認(rèn)推送功能是關(guān)閉的相艇,我們需要把推送功能打開


選中打開后,點(diǎn)擊右邊灰色的Configure按鈕



這里的文件同樣的纯陨,還是選擇我們生成在桌面上的CSR請求文件




然后點(diǎn)擊繼續(xù)


出現(xiàn)了我們需要的SSL證書坛芽,我們點(diǎn)擊下載后點(diǎn)擊Done完成。


Status狀態(tài)變成了綠色可用了翼抠。這里右邊的下載和上一步的下載是一樣的咙轩,如果在上一步中下載了證書,便無需再次下載阴颖。此時我們有了一個名字叫aps_development.cer的SSL證書活喊,同樣,我們把他放在桌面量愧。雙擊后會跳到鑰匙串訪問钾菊,出現(xiàn)我們的SSL推送證書
同樣的,發(fā)布的SSL證書的步驟也是一樣的偎肃。

四 下載Provisioning證書
在左側(cè)選擇Provisioning

配置好后點(diǎn)擊提交(注意App ID要與我們剛的程序?qū)?yīng))

之后變回出現(xiàn)下載按鈕煞烫,我們點(diǎn)擊下載。下載后雙擊累颂,并將我們的設(shè)備上的描述文件更新一下(最好把之前的全部刪除滞详,然后再安裝,防止出錯)。

五 從鑰匙串訪問中導(dǎo)出秘鑰
打開鑰匙串訪問料饥,找到我們的專用秘鑰(專用秘鑰的名稱就是我們在最開始生成CSR請求的時候填寫的常用名)

右鍵選擇導(dǎo)出


導(dǎo)出的文件名我們叫做Push


在這里需要輸入一個密碼來對文件進(jìn)行加密蒲犬。這里我們選擇abc123,當(dāng)然你也可以自己選擇是什么稀火,但是這個密碼必須要銘記暖哨,切記!


然后輸入你電腦的密碼凰狞,點(diǎn)擊允許篇裁。
這樣我們就在桌面上生成了一個Push.p12文件。

到此為止赡若,我們在桌面上一共生成了三個文件达布。一個是CSR請求文件,一個是aps_development .cer的SSL證書文件逾冬,還有一個剛才生成的Push.p12秘鑰文件黍聂。

現(xiàn)在我們的準(zhǔn)備工作已經(jīng)做完了。要開始對生成的文件進(jìn)行處理了身腻。原因上面已經(jīng)解釋過产还,因?yàn)槲覀兊姆?wù)鏈接蘋果服務(wù)器也是需要證書的,但是我們直接生成的證書windows系統(tǒng)(我們一般的服務(wù)器都是win系統(tǒng)的)是不識別的嘀趟,所以我們需要生成一個后綴為pem的帶證書帶秘鑰的文件脐区。
六 處理證書
下面我們打開終端(位置:應(yīng)用程序à實(shí)用工具à終端)。
cd到桌面她按,我們那三個文件所在的位置

1牛隅、把.cer的SSL證書轉(zhuǎn)換為.pem文件,執(zhí)行命令:
openssl x509 -in aps_development.cer -inform der -out PushChatCert.pem

在桌面上會生成一個PushChatCert.pem文件


2酌泰、把私鑰Push.p12文件轉(zhuǎn)化為.pem文件:

openssl pkcs12 -nocerts -out PushChatKey.pem -in Push.p12


這里需要我們輸入密碼媒佣,這個密碼也就是我們導(dǎo)出p12文件時的密碼,也就是我們上面設(shè)置的abc123陵刹。然后默伍,需要我們對生成的pem文件設(shè)置一個密語,這里我們推薦還是用上面這個abc123,防止混亂(當(dāng)然你也可以設(shè)置成別的更有意義的密語)衰琐,這里的密語是要告訴我們服務(wù)器的巡验。這樣,桌面上又會生成一個PushChatKey.pem文件

3碘耳、對生成的這兩個pem文件再生成一個pem文件,來把證書和私鑰整合到一個文件里:

cat PushChatCert.pem PushChatKey.pem > ck.pem

生成ck.pem文件


這樣框弛,我們的文件就制作完了辛辨。下面進(jìn)入測試階段
為了測試證書是否工作,執(zhí)行下面的命令

telnet gateway.sandbox.push.apple.com 2195

它將嘗試發(fā)送一個規(guī)則的,不加密的連接到APNS服務(wù)斗搞。如果你看到上面的反饋指攒,那說明你的MAC能夠到達(dá)APNS。按下Ctrl+C關(guān)閉連接僻焚。如果得到一個錯誤信息允悦,那么你需要確保你的防火墻允許2195端口。一般這里都不會出現(xiàn)什么問題虑啤。



下面我們要使用我們生成的SSL證書和私鑰來設(shè)置一個安全的鏈接去鏈接蘋果服務(wù)器:

openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem

執(zhí)行完這一句命令后需要我們輸入密語
Enter pass phrase for PushChatKey.pem:
我們輸入abcabc按回車
你會看到一個完整的輸出隙弛,讓你明白OpenSSL在后臺做什么。如果鏈接是成功的狞山,你可以隨便輸入一個字符全闷,按下回車,服務(wù)器就會斷開鏈接萍启,如果建立連接時有問題总珠,OpenSSL會給你返回一個錯誤信息。

當(dāng)你在最后的時候你看到這樣說明你已經(jīng)成功了:

CONNECTED(00000003)
depth=1 /C=US/O=Entrust, Inc./OU=www.entrust.net/rpa isincorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust CertificationAuthority - L1C
verify error:num=20:unable to get local issuercertificate
verify return:0
Certificate chain
0s:/C=US/ST=California/L=Cupertino/O=Apple >Inc./OU=iTMSEngineering/CN=gateway.sandbox.push.apple.com
i:/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated byreference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C
1s:/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated byreference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C
i:/O=Entrust.net/OU=www.entrust.net/CPS_2048incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.netCertification Authority (2048)
Server certificate
-----BEGIN CERTIFICATE-----
MIIFGzCCBAOgAwIBAgIETBz90jANBgkqhkiG9w0BAQUFADCBsTELMAkGA1UEBhMC
……省略……
fMGbLqkGn8YogdPqe5T1
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Cupertino/O=AppleInc./OU=iTMS Engineering/CN=gateway.sandbox.push.apple.com
issuer=/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa isincorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust CertificationAuthority - L1C
No client certificate CA names sent
SSL handshake has read 2731 bytes and written 2165 bytes
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : AES256-SHA
Session-ID:
Session-ID-ctx:
Master-Key:C7A47EED5E1F5……省略……369D4
Key-Arg : None
Start Time:1361862882
Timeout : 300 (sec)
Verify return code: 0 (ok)

在這里提醒一下勘纯,也許你會看到像我這樣的提示:verify error:num=20:unable to get local issuercertificate
verify return:0
其實(shí)是沒問題的局服。


七 項(xiàng)目測試

建立我們的推送的項(xiàng)目(注意BundleIdentifier必須和我們推送應(yīng)用的App id一致)

在AppDelegate里didFinishLaunchingWithOptions函數(shù)里寫
- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //推送的形式:標(biāo)記,聲音驳遵,提示
   [[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert];
   return YES;
}
 
- (void)application:(UIApplication *)applicationdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken {
   NSLog(@"regisger success:%@",pToken);
   //注冊成功淫奔,將deviceToken保存到應(yīng)用服務(wù)器[數(shù)據(jù)庫](http://lib.csdn.net/base/14)中
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
    // 處理推送消息
    NSLog(@"userinfo:%@",userInfo);
   
    NSLog(@"收到推送消息:%@",[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]);
}
- (void)application:(UIApplication *)applicationdidFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
   NSLog(@"Registfail%@",error); 
}

我們運(yùn)行程序的時候會有提示,說我們的程序要發(fā)送推送通知

下面我們把下載的php服務(wù)器代碼(地址在下面)和生成的ck.pem文件放在統(tǒng)一文件夾下面(這里我們還是把兩個文件統(tǒng)一放在桌面上)超埋。
用Xcode打開(其他工具也可以)php服務(wù)器端的代碼搏讶,把deviceToken改成我們現(xiàn)在要進(jìn)行測試的iphone的deviceToken(獲得方法:首先運(yùn)行我們的程序,程序啟動后打印的日志文件里可以看到霍殴。)媒惕,密語改成我們之前設(shè)置的abc123。然后保存来庭。

程序中先運(yùn)行注冊拿到deviceToken ,手動給添加妒蔚,后期可以上傳給后臺來存儲
.PHP中代碼修改

然后在終端(記住將終端切換桌面位置 因?yàn)槟愕膒hp后臺和推送證書在桌面路徑位置)運(yùn)行命令(如果剛才你關(guān)閉了終端的話,最好ls一下月弛,看看當(dāng)前是不是在桌面)肴盏,執(zhí)行命令:
php pushMe.php
然后回車(pushMe為服務(wù)器文件名稱)


如果出現(xiàn)這樣的提示說明成功了,然后在iphone上帽衙,我們期待已久的推送消息終于來了菜皂。

IMG_2759.PNG
常見問題:

1、在用證書和秘鑰鏈接服務(wù)器時出現(xiàn)提示:

Error opening client certificate private key filePushChatKey.pem20839:error:02001002:system library:fopen:No such file ordirectory:/SourceCache/OpenSSL098/OpenSSL098-44/src/crypto/bio/bss_file.c:356:fopen('PushChatKey.pem','r')
20839:error:20074002:BIO
routines:FILE_CTRL:systemlib:/SourceCache/OpenSSL098/OpenSSL098-44/src/crypto/bio/bss_file.c:358:
unable to load client certificate private key file

解決:
文件路徑不對厉萝。cd到生成的pem文件路徑下再進(jìn)行鏈接

2恍飘、前期測試沒有問題榨崩,將ck.pem給服務(wù)器,通過服務(wù)器進(jìn)行推送時推送不成功章母,提示鏈接APNS失敗母蛛。
解決:一,看一下證書的名稱乳怎,密語是否正確彩郊;二,路徑是否正確蚪缀;然后檢查一下庫秫逝,OpenSSL和libssl;此外apache還要開啟OpenSSL權(quán)限椿胯,確笨甑牵可以訪問pem

3、APNS地址 (*一定記住切換地址,好多推送不成功就是地址不對,pushMe.php中的代碼地址我已經(jīng)換成測試的了*)
測試地址gateway.sandbox.push.apple.com:2195
發(fā)布地址 gateway.push.apple.com:2195
測試的地址用的是沙盒哩盲,發(fā)布地址是不同的前方。發(fā)布軟件的時候記得改過來

4、要注意順序問題廉油,一定要按照這個順序來:
生成鑰匙串請求 -->配置下載開發(fā)證書--> 配置App ID 惠险,配置、下載SSL證書-->Provisioning證書

實(shí)例代碼 和 pushMe.php

下載地址:github: https://github.com/one-tea/APNS_test.git
有什么問題可以與我私信抒线,如果喜歡請關(guān)注班巩!
后臺的配置問題
在這里說下后臺配置,主要分兩類:
一. Java嘶炭、PHP可以通用,上面pushMe.php也就是適用代碼抱慌;

二. 另一種有.net后臺的(比如我們公司),給后臺證書為.p12格式 制作方法:
在鑰匙中找到你安裝過的推送證書眨猎,記不住就返回上面證書配置那塊看

Snip20160803_12.png
Snip20160803_13.png

導(dǎo)出為.p12抑进,密鑰也為abc123好了, 這個秘鑰需要和.p12一起給后臺
至于后臺有寫好的代碼 .net 項(xiàng)目中引PushSharp.Apple.dll,PushSharp.Core.dll(這兩個文件在網(wǎng)上搜一下,有源碼的)

總結(jié) :本篇一些內(nèi)容參考有夢想的蝸牛的博客及其他博客并整理睡陪,在此十分感謝寺渗!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市兰迫,隨后出現(xiàn)的幾起案子信殊,更是在濱河造成了極大的恐慌,老刑警劉巖汁果,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涡拘,死亡現(xiàn)場離奇詭異,居然都是意外死亡据德,警方通過查閱死者的電腦和手機(jī)鳄乏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門府蔗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人汞窗,你說我怎么就攤上這事∩囊耄” “怎么了仲吏?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蝌焚。 經(jīng)常有香客問我裹唆,道長,這世上最難降的妖魔是什么只洒? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任许帐,我火速辦了婚禮,結(jié)果婚禮上毕谴,老公的妹妹穿的比我還像新娘成畦。我一直安慰自己,他們只是感情好涝开,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布循帐。 她就那樣靜靜地躺著,像睡著了一般舀武。 火紅的嫁衣襯著肌膚如雪拄养。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天银舱,我揣著相機(jī)與錄音瘪匿,去河邊找鬼。 笑死寻馏,一個胖子當(dāng)著我的面吹牛棋弥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播操软,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼嘁锯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了聂薪?” 一聲冷哼從身側(cè)響起家乘,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎藏澳,沒想到半個月后仁锯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡翔悠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年业崖,在試婚紗的時候發(fā)現(xiàn)自己被綠了野芒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡双炕,死狀恐怖狞悲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情妇斤,我是刑警寧澤摇锋,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站站超,受9級特大地震影響荸恕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜死相,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一融求、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧算撮,春花似錦生宛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至素挽,卻和暖如春蔑赘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背预明。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工缩赛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人撰糠。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓酥馍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親阅酪。 傳聞我的和親對象是個殘疾皇子旨袒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容