2014年1月23日 星期四

Apple Push Nofification service SSL Certificates

iOS App 有內建的推播可以用, 首先要設定App 允許推播. 前置準備是要弄一台 Apache + Php 來送資料到 Apple.

Step 1: 進入 iOS Developer Center, 點 Cerfificates


Step 2: 點 "Edit"


Step 3: Push Notifications 打勾


Step 4: 按下面的步驟可以產生 CSR, 產生好後按 "Continue"


Step 5: 上傳 CSR 檔案,並按下 Generate


Step 6: 下載certificate
說明: 這個 certificates 分 development 和 product, develop 的好像3個月會過期,要重新 generate 並 download 一次.


Q: Step 5: 上傳 CSR 檔案,並按下 Generate
development跟product需要從分別不同的CSR嗎?還是同一個CSR就可以了 A: 還是同一個CSR就可以了 .


接下來的步驟,只能在 Mac 上執行.接棒給Mac.
(其實: 從頭到尾通通在 Mac 上做就ok了.)
==========================

Step 7: 進入  keychain 匯出 Push Services key 為 .p12 的檔案
(有2種,Development & Production 的 certificates, 有要測 development  的話請匯出2次。 )



Step 8: Save as 輸入檔名,點  "Save"

輸入  password


Step 9: 產生 pem 檔案:
openssl pkcs12 -clcerts -nokeys -out cert.pem -in ios_push_cert.p12
openssl pkcs12 -nocerts -out key.pem -in ios_push_cert.p12
openssl rsa -in key.pem -out key.unencrypted.pem
cat cert.pem key.unencrypted.pem > ck.pem


production指令範例:
openssl pkcs12 -clcerts -nokeys -out cert_production.pem -in ios_push_cert_production.p12
openssl pkcs12 -nocerts -out key_production.pem -in ios_push_cert_production.p12
openssl rsa -in key_production.pem -out key.unencrypted_production.pem
cat cert_production.pem key.unencrypted_production.pem > ck_production.pem


測試 sandbox push server 是否可以被連到:
telnet gateway.sandbox.push.apple.com 2195

測試 sandbox push server 是否可以使用 SSL 憑證連到:
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert pushtestcert.pem -key pushtestkey.pem


收到的推播測試訊息:



browser 執行畫面:

badge 數字顯示:


notification:




xcode 裡的程式碼:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSLog(@"Registeringfor push notifications...");
    [[UIApplication sharedApplication]
     registerForRemoteNotificationTypes:
     (UIRemoteNotificationTypeAlert |
      UIRemoteNotificationTypeBadge |
      UIRemoteNotificationTypeSound)];
    
    return YES;
}

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSString *str = [NSString
                     stringWithFormat:@"%@",deviceToken];
    NSLog(@"Device Token:%@",str);
}

- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)err
{
    NSLog(@"didFailToRegisterForRemoteNotificationsWithError:%@",[err description]);
}

- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    /*
    for (id key in userInfo) {
        NSLog(@"key: %@, value: %@", key, [userInfo objectForKey:key]);
    }
     */
    NSDictionary *apsInfo = [userInfo objectForKey:@"aps"];
    
    NSString *alertMsg = @"";
    NSInteger badge = 0;
    NSString *sound = @"";
    NSString *custom = @"";
    
    if( [apsInfo objectForKey:@"alert"] != NULL)
    {
        alertMsg = [apsInfo objectForKey:@"alert"];
    }
    
    
    if( [apsInfo objectForKey:@"badge"] != NULL)
    {
        badge = [[apsInfo objectForKey:@"badge"integerValue];
    }
    if(badge>0)
    {
        // reset badge counter.
        int currentBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber;
        currentBadgeNumber += badge;
        [UIApplication sharedApplication].applicationIconBadgeNumber = currentBadgeNumber;
    }
    
    
    if( [apsInfo objectForKey:@"sound"] != NULL)
    {
        sound = [apsInfo objectForKey:@"sound"];
    }
    
    if( [userInfo objectForKey:@"Custom"] != NULL)
    {
        custom = [userInfo objectForKey:@"Custom"];
    }

}


php 的範例:
<?php
// Put your device token here (without spaces):修改點1
$deviceToken = '740f4707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bb78ad';
// Put your private key's passphrase here:修改點2
$passphrase = 'passowrd';
// Put your alert message here:修改點3
$message = 'My first push notification!';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');修改點4 *.pem
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);
?>

沒有留言:

張貼留言