首先,需要一個pem的證書,該證書需要與開發時簽名用的一致。 具體生成pem證書方法如下:
1. 登錄到 iPhone Developer Connection Portal(http://developer.apple.com/iphone/manage/overview/index.action ) 並點擊 App IDs
2. 選擇對應App ID。(開發與發布不一樣的。需注意)
3. 點擊App ID旁的“Configure”,然后按下按鈕生產 推送通知許可證。根據“向導” 的步驟生成一個簽名並上傳,最后下載生成的許可證。
4. 通過雙擊.cer文件將你的 aps_developer_identity.cer 引入Keychain中。
6. 單機“Apple Development Push Services”,導出p12文件,保存為 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
openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-key.p12
9. 如果你想要移除密碼,要么在導出/轉換時不要設定或者執行:
openssl rsa -in apns-dev-key.pem -out apns-dev-key-noenc.pem
10. 最后,你需要將鍵和許可文件合成為apns-dev.pem文件,此文件在連接到APNS時需要使用:
cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem
PHP后台寫法:
<?php // 這里是我們上面得到的deviceToken,直接復制過來(記得去掉空格) //deviceToken 在測試版本和上線版本上不一樣。 //lei ipod touch $deviceToken = '06fe0a85056f6b9f07fb11a4eed962aaab824b9522660a8bb165b369717159ab'; // Put your private key's passphrase here: $passphrase = 'abc123456'; // Put your alert message here: $message = 'My first push test!'; //////////////////////////////////////////////////////////////////////////////// $message = array('msg'=>'小小說閱讀器','title'=>'小小說','url'=>'http://www.apple.com.cn'); //$message = array('msg'=>'去商品詳細頁面','itemtype'=>'2','id'=>'192172'); //$message = array('msg'=>'去菜單頁面','itemtype'=>'1','zktype'=>'1','order'=>'1','zksubtype'=>'1','zktitle'=>'9.9包郵'); //$message = array('msg'=>'軟件升級'); $ctx = stream_context_create(); stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck_dev.pem'); stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase); // Open a connection to the APNS server //這個為正是的發布地址 //$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx); //這個是沙盒測試地址,發布到appstore后記得修改哦 $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' => '逗你玩!哈哈。', 'sound' => 'beep.wav', 'badge' => 1 ); $body['type']=2; $body['data']=$message; // 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); ?>
客戶端代碼:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; // Override point for customization after application launch. main = [[MainViewController alloc] init]; navMain = [[UINavigationController alloc] initWithRootViewController:main]; self.window.rootViewController = navMain; notifiDic = [[NSMutableDictionary alloc] init]; [self initNotification]; [UIApplication sharedApplication].applicationIconBadgeNumber = 0; NSLog(@"launchOption==%@",[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]); if ([launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey] != nil) { if (notifiDic.count != 0) { [notifiDic removeAllObjects]; } [notifiDic setDictionary:(NSDictionary *)[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"didFinishLaunching" message:[NSString stringWithFormat:@"didFinishLaunching:\n%@",launchOptions] delegate:self cancelButtonTitle:@"Cancek" otherButtonTitles:@"OK", nil]; [alert show]; alert.tag = 101; [alert release]; } self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; } - (void)initNotification{ [[UIApplication sharedApplication]registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert |UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound)]; } #pragma mark - -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{ NSLog(@"deviceToken: %@", deviceToken); NSLog(@"deviceToken===%@",[deviceToken description]); NSRange _range = NSMakeRange(1,[[deviceToken description] length]-2); NSString *deviceTokenStr = [[deviceToken description] substringWithRange:_range]; NSLog(@"deviceTokenStr==%@",deviceTokenStr); deviceTokenStr = [deviceTokenStr stringByReplacingOccurrencesOfString:@" " withString:@""]; NSLog(@"deviceTokenStr==%@",deviceTokenStr); UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"product deviceToken" message:deviceTokenStr delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alertView show]; [alertView release]; } - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{ NSLog(@"%s,,,,%@",__func__,userInfo); if (notifiDic.count != 0) { [notifiDic removeAllObjects]; } [notifiDic setDictionary:userInfo]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:[NSString stringWithFormat:@"受到的通知如下:\n%@",userInfo] delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil]; [alert show]; alert.tag = 100; [alert release]; } - (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { NSLog(@"%s",__func__); }
注意點:
1.推送證書都弄好后,項目的開發證書要重新下載一下。
1.反饋服務
Apple 還提供了一個 反 饋服務 ,你應該定期查詢。它提供了一個以前使用過但不再有效的(例如用戶卸載了你的iPhone程序)設備令牌列表。你可以從你的數據庫中刪除這些設備令牌。
本教程不涉及反饋服務的使用。
2.創建載荷
使用 PHP 很容易根據數組並 轉 換成 JSON而創建載荷:
$payload['aps'] = array('alert' => 'This is the alert text', 'badge' => 1, 'sound' => 'default');
$payload = json_encode($payload);
顯示 $payload 的內容可以看到傳送到APNS 的 JSON字符串:
{
"aps" : { "alert" : "This is the alert text", "badge" : 1, "sound" : "default" }
}
這將使消息顯示於設備上,觸發提升聲音並將“1”置於程序圖標上。默認按鈕“Close”和“View”同時會顯示於彈出窗口上。
對於 Server Density iPhone程序而言,讓用戶按下“View”直接進入產生此提示的服務器是很重要的,所以我們增加了額外的自定義值:
$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" : "This is the alert text", "badge" : 1, "sound" : "default" },
"server" : { "serverId" : 1, "name" : "Server name")
}
256字節的限制適用於整個載荷,包括自定義字典集。
原生接口
在Server Density中,一旦產生了一條提示,將建立一個載荷並插入隊列中。因此有必要時我們可以同時發送多個載荷。
Apple推薦使用這種方法,因為如果你在發送各載荷時頻繁連接和斷開,APNS有可能會封鎖你的IP。
3.Push Notification Provider 是一個應用程序,用於通過 APNs 發送推送通知給 iPhone 應用。
通過 APNs 發送推送通知有幾個步驟:
1. 使用前面創建的 SSL 證書與 APNs 通訊;
2. 構造所要發送的消息載體;
3. 發送載體到APNs;
APNs 是一個基於流的 TCP socket,你的 provider 以 SSL 協議與其通訊。推送通知(包括載體)是以二進制流的方式發送的。和APNs 建立連接后,你可以維持該連接並在連接中斷之前發送多個通知。
技巧:應避免每發送一次推送通知就建立、關閉一次連接。頻繁的建立、關閉連接可能會被 APNs 認為是 DOS 攻擊,從而拒絕發送 provider 的推送通知發送請求。