PHP蘋果推送實現(APNS)


以下資料網上收集整理得來

轉自: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;
        }
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM