以下資料網上收集整理得來
轉自:https://www.cnblogs.com/ymms/p/3865913.html
1、在ios dev center制作相關證書和文件用客戶端實現(不再贅述,網上很多,)
網上教程:
http://blog.csdn.net/lizhenning87/article/details/8259270
官方文檔:
https://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ProvisioningDevelopment/ProvisioningDevelopment.html#//apple_ref/doc/uid/TP40008194-CH104-SW1
2、制作好后下載下來,雙擊導入。然后在鑰匙串訪問處找到剛導入的證書,展開可看到鑰匙,選中證書,導出.p12文件,由於PHP不好處理這種格式,所以要轉換成.pem文件,方法如下,在終端執行:
openssl pkcs12 -in CertificateName.p12 -out CertificateName.pem -nodes(將文伯拖入終端可以免去自己寫路徑),分別制作一個production,development證書
4、服務端,創建測試文件apns.php,並將CertificateName.pem放到同一目錄,
正式地址:gateway.push.apple.com, port 2195(使用正式證書)
測試地址:gateway.sandbox.push.apple.com, port 2195(使用測試證書)
//接收到設備發來的token,這里我手動填上。 $deviceToken = "015c5a2377ac146830f8ed09059b82bb91ed7190ebf74b633809bc2245da95ee"; //構造消息體 $body = array("aps" => array("alert" => '測試測試測試', "badge" => 1, "sound" => 'received5.caf')); $ctx = stream_context_create(); stream_context_set_option($ctx, "ssl", "local_cert", "CertificateName.pem"); //建立socket連接 $fp = stream_socket_client("ssl://gateway.sandbox.push.apple.com:2195", $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx); if (!$fp) { print "Failed to connect $err $errstrn"; return; } print "Connection OK"; $payload = json_encode($body); $msg = chr(0) . pack("n",32) . pack("H*", $deviceToken) . pack("n",strlen($payload)) . $payload; print "sending message :" . $payload . "\n"; fwrite($fp, $msg); fclose($fp);
5、服務器返饋
當用戶將我們的應用刪除時,我們應該停止對這台機器推送,這個SSL地址是:
正式機:feedback.push.apple.com, port 2196
測試機:feedback.sandbox.push.apple.com, port 2196
具本見
https://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingWIthAPS/CommunicatingWIthAPS.html
php如下:
$certFile = 'apns-dev.pem'; while(true){ $ctx = stream_context_create(); stream_context_set_option($ctx, 'ssl', 'local_cert', $certFile); //stream_context_set_option($ctx, 'ssl', 'passphrase', $this->certPass); echo "try to open stream\n"; $fp = stream_socket_client('ssl://feedback.sandbox.push.apple.com:2196', $err, $errstr, 5, STREAM_CLIENT_CONNECT, $ctx); if (!$fp) { print "Failed to connect". $err . $errstr. "\n"; exit(); } else { echo 'Connected to feedback sandbox...'; while(($in = fread($fp, 1024)) != EOF) { echo 'read '. $in . "\n"; } socket_close($fp); fclose($fp); } sleep(2000); }
注意,要將你的APP刪除后,再發一個推送,才可能返回數據
開發狀態服務器地址 gateway.sandbox.push.apple.com 2195
產品狀態服務器地址 gateway.push.apple.com 2195
Development和Production兩個版本對應的apns device token是不同的,前者是develop的mobileprovision下獲取的。后者是production的mobileprovision獲取的。
Development和Production兩個版本可以共用一個App ID(不推薦。共用時每次調試前都要刪除設備上的app,重新打包生成。而且公用appid會經常抓狂,早上行,下午就不行了。所以不推薦),但是不能共用一個mobileprovision,所以要單獨生成Distribution的證書供production版本使用。
注:Distribution的版本是無法在設備上debug調試的!
Development和Production兩個版本的code sign是不同的,前者是iPhone Developer,后者是iPhone Distribution。注意不能搞錯。
無論是Development Push SSLCertificate還是Production Push SSL Certificate 都有過期時間的。Development Push SSL Certificate有效期大概四個月左右,而ProductionPush SSL Certificate的有效期是一年。需要注意在過期之前生成新的證書,以免影響使用。
openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12
openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-cert.p12
openssl rsa -in apns-dev-key.pem -out apns-dev-key-noenc.pem
cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem
在Mac上生成 Apple推送通知SSL許可證:
1. 登錄到 iPhone Developer Connection Portal 並點擊 App IDs
2. 創建一個不使用通配符的 App ID 。通配符 ID 不能用於推送通知服務。例如,我們的iPhone程序ID像這樣: AB123346CD.com.serverdensity.iphone
3. 點擊App ID旁的“Configure”,然后按下按鈕生產 推送通知許可證。根據“向導”指導的步驟生成一個簽名並上傳,最后下載生成的許可證。此步驟在 Apple文檔中 也有談到。
4. 通過雙擊.cer文件將你的 aps_developer_identity.cer 引入Keychain中。
5. 在Mac上啟動 Keychain助手,然后在login keychain中選擇 Certificates分類。你將看到一個可擴展選項“Apple Development Push Services”
6. 擴展此選項然后右擊“Apple Development Push Services” > Export “Apple Development Push Services ID123”。保存為 apns-dev-cert.p12 文件。
7. 擴展“Apple Development Push Services” 對“Private Key”做同樣操作,保存為 apns-dev-key.p12 文件。
8. 需要通過終端命令將這些文件轉換為PEM格式:
openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12
9. 轉換得到key的pem:
openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-cert.p12
10. 如果你想要移除密碼,要么在導出/轉換時不要設定或者執行:
openssl rsa -in apns-dev-key.pem -out apns-dev-key-noenc.pem
11. 最后,你需要將鍵和許可文件合成為apns-dev.pem文件,此文件在連接到APNS時需要使用:
cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem
將此文件保存為一個易記的名字,你有可能以后會用到它。上述步驟同樣適合於生成產品許可證。
檢驗證書是否正確的方法:
$ telnet gateway.sandbox.push.apple.com 2195
Trying 17.172.232.226…
Connected to gateway.sandbox.push-apple.com.akadns.net.
Escape character is ‘^]’.
它將嘗試發送一個規則的,不加密的連接到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:
你會看到一個完整的輸出,讓你明白OpenSSL在后台做什么。如果連接是成功的,你可以鍵入一些字符。當你按下回車后,服務就會斷開連接。如果在建立連接時有問題,OpenSSL將會給你一個錯誤消息,但是你不得不向上翻輸出LOG,來找到它。
當然上面要測試prodution版本是否正確的話,把gateway.sandbox.push.apple.com換成gateway.push.apple.com就好。
客戶端很好做,申請證書,復制代碼,就行了。
服務器端,如果是php的,那必須使用.pem的證書,如果是java的,那必須使用.p12的證書。(很可能還需要雙擊證書進行安裝!)
服務器端發出的json包是有大小限制的,最大256字節,包括自定義字典集。
aps中的alert字符串里是可以添加"\n"做換行的。
json包中除了alert,badge,sound之外,還是是可以自定值的。
額外的自定義值:
$payload['aps'] = array('alert' => 'This is the alert text', 'badge' => 1, 'sound' => 'default');
$payload['server'] = array('serverId' => $serverId, 'name' => $name);
$output = json_encode($payload);
當用戶按下“View”后,自定義server值將被傳遞到設備中的程序。JSON 值如下:
{
"aps" :
{ "alert" :
{
"action-loc-key" : "顯示" ,
"body" : "This is the alert text"
},
"badge" : 1,
"sound" : "default" },
"server" : { "serverId" : 1, "name" : "Server name")
}
256字節的限制適用於整個payload,包括自定義字典集。
原生接口
在Server Density中,一旦產生了一條提示,將建立一個payload並插入隊列中。因此有必要時我們可以同時發送多個payload。
Apple推薦使用這種方法,因為如果你在發送各payload時頻繁連接和斷開,APNS有可能會封鎖你的IP。
如Apple 描述:
原生接口使用原生socket,具有二進制內容,采用數據流技術,不產生回饋。
高人的總結:
APPLE推送通知服務教程 PART-1
APPLE推送通知服務教程 PART-2
APPLE推送通知服務教程 PART-3
apns php版本:
https://code.google.com/p/apns-php/wiki/CertificateCreation
IOS7之前,蘋果對於一個設備上的多個APP,生成相同的DeviceToken。
IOS7以及之后,蘋果對於一個設備上的多個APP,生成不同的DeviceToken。
這種新改變導致APNS上創建了一張新老token的映射表,如果你一直用老的token,那沒問題,但是,一旦服務器使用新的DeviceToken,映射表中的記錄就會被刪除,這意味着,老的DeviceToken就不能用了,必然發送失敗。
待驗證:IOS5和IOS6,APP永遠可以獲取DeviceToken,除此之外的系統,如果用戶拒絕了,或者關閉了推送,那么無法獲取DeviceToken,走失敗回調。
原文出處:https://support.urbanairship.com/customer/portal/articles/1321513-how-ios-7-handles-push-differently
http://stackoverflow.com/questions/6652242/does-the-device-token-ever-change-once-created
生成證書需要注意事項:
蘋果開發者賬號分好幾種角色
Agent:代理人,擁有最高權限,可以訪問iTunes Connect。
Admin:管理員,擁有管理成員、維護設備列表,維護APPID以及證書列表權限。
Member:普通成員,只讀權限。
備注:3013.9.11經過測試,我發現前段時間蘋果網站下線期間更新了證書生成機制。以前,利用鑰匙串生成一個CSR文件,可以一直用。但是,現在每當你要生成證書,做generate的時候都需要提前重新生成一個CSR文件,否則你生成的證書都是無效的,假證書,尤其是PUSH的,服務端使用這種證書根本無法和APNS建立連接,這種詭異的問題超難跟蹤的!希望看到這段話的人都能避免走彎路,不用謝了!
在使用PushMeBaby中也遇到各種問題。首先,雖然工程中已經使用了.cer的公鑰證書,但是本地鑰匙串中必須有帶私鑰的證書,否則連接無法成功建立。而且需要注意的是,證書最好放在“登錄”分組中,否則程序也是找不到私鑰的。其次,原始的工程中在scanString的時候會死循環,需要修改為如下代碼:
NSUInteger count = 0;
while(![scanner isAtEnd]) {
[scanner scanHexInt:&value];
value = htonl(value);
[deviceTokenData appendBytes:&value length:sizeof(value)];
if (++count >= [self.deviceToken length]-1) {
break;
}
}