iPhoneのPush通知「APNS」をphpから完璧に通知させる方法

  • このエントリーをはてなブックマークに追加
  • このエントリーをはてなブックマークに追加

iphoneアプリをつくると必ずといっていいほど欲しいプッシュ通知。

iphoneの場合、APNSというものがPush通知のシステムとなります。

 

Apple Push Notificationを理屈抜きにとりあえず実装

ものすごーく簡単に説明するとAppleの通知センターに通知内容とともに、端末のデバイストークンを付加し送信することで、

該当の端末に通知が送られるというもの。(デバイストークンの取得方法は今回は記述しません)

こちらの記事が参考になりそう⇒Apple Push Notification サービス(APNs) の実装方法

今回はデバイストークンを取得してから実際に通知を送るプログラムをPHPにて紹介いたします。

実際のソースコードはコチラ↓


//============================================
// class_apns.php
//============================================
// 接続先
define('C_APNS_SOCKET','ssl://gateway.sandbox.push.apple.com:2195');
define('C_APNS_MESSAGE_SIZE',256);

//+++++++++++++++++++++++++++++
// class_apns
//+++++++++++++++++++++++++++++
class class_apns{
        // 接続用PEMのパス
        var     $APNS_PATH = "";
        // Put your private key's passphrase here:
        var     $APNS_PASSWORD = '';
        // APS設定情報(必要なものを記述)
        var     $APNS_BODY = array(
                //'alert' => $message,
                //"badge" => 1,
                //'sound' => 'default',
                //'content-available' => 1        // バックグラウンド起動
        );
        // 送信先デバイス
        var     $APNS_DEVICE_TOKEN = array();
        // 初期化
        function init($path,$password){
                $this->APNS_PATH = $path;
                $this->APNS_PASSWORD = $password;
                return true;
        }
        function setBody($body){
                $this->APNS_BODY = $body;
                return $this->APNS_BODY;
        }
        function setDeviceToken($token){
                $this->APNS_DEVICE_TOKEN = $token;
                return $this->APNS_DEVICE_TOKEN;
        }
        // APNS 接続
        function connectAPNS($sslclient,$pem_path,$passphrase,$retry=false){
                $ctx = stream_context_create();
                stream_context_set_option($ctx, 'ssl', 'local_cert', $pem_path);
                stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
                // Open a connection to the APNS server
                $fp = stream_socket_client($sslclient, $err,$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
                if (!$fp){
                        // 接続エラーになったので1秒後再接続を試みます
                        if($retry){
                                sleep(1);
                                return $this->connectAPNS($sslclient,$pem_path,$passphrase);
                        }
                }
                return $fp;
        }
        // メッセージサイズの取得
        function getMessageSize($deviceToken){
                // Create the payload body
                $body = array();
                $body['aps'] = $this->APNS_BODY;
                // Encode the payload as JSON
                $payload = json_encode($body);
                
                $msg = $this->getMessage($deviceToken,$payload);
                return strlen($msg);
        }
        // メッセージ取得
        function getMessage($deviceToken,$payload){
                return chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
        }
        // Push通知
        function pushMessage(){
                $fp = $this->connectAPNS(C_APNS_SOCKET,$this->APNS_PATH,$this->APNS_PASSWORD,true);
                if(!$fp){
                    //exit("Failed to connect".PHP_EOL);
                    return false;
                }
                $result_list = null;
                // Create the payload body
                $body = array();
                $body['aps'] = $this->APNS_BODY;
                // Encode the payload as JSON
                $payload = json_encode($body);
                $size = 0;
                foreach ($this->APNS_DEVICE_TOKEN as $deviceToken){
                    $msg = $this->getMessage($deviceToken,$payload);
                    $msg_size = strlen($msg);
                    $result = fwrite($fp, $msg, $msg_size);
                    // 接続成功
                    if($result){
                        $result_list[] = $result;
                    }
                    $size += $msg_size;
                    // 1回の通信で全パケットが5000?7000バイトを超えるとAPNSから切断されるので再接続
                    if($size >= 5120){
                        fclose($fp);
                        sleep(1);
                        $fp = $this->connectAPNS(C_APNS_SOCKET,$this->APNS_PATH,$this->APNS_PASSWORD,true);
                        $size = 0;
                    }
                }
                fclose($fp);
                
                return $result_list;
        }
}

 

実際の使い方とAPNSの注意点

APNS用のクラスを作成してあるので、

$apns = new class_apns();

$apns->init($path,$password);
// デバッグ設定
$apns->setDebug(false);

$options = array(

  ”alert” => “メッセージが入ります。”,

      “badge” => 4,      // バッチ数

      “sound” => “default”,      // 音を出すか

      “forgrand” => 0,

      “content-available” => 1,

);

// 送信先の設定

$apns->setDeviceToken($tokenlist);

//送信

$result = $apns->pushMessage();

 

と致します。

$path ・・・ 「.pem」ファイルへのパス。Macで作成することができるが今回は割愛。

$password・・・認証パスワード

この辺は少しAPNSがどういったものかを調べればつくれるかと思います。

自分でつくっておいて、中身はすっかり忘れているのですが、とりあえず動作的には問題ありません。

メッセージだけを送る、音を鳴らす(バイブを鳴らす)、バッチ数のみといった使い分けもできるので便利かと。

 

APNSは公式にはっていませんが、なぜか256バイト以上を一度に送信しようとすると切断されるそうです。

その辺も対応済みなので、バリバリ動作いたします。

※ただし、通知を1通1通送っているので100~の通知はものすごくサーバーに負荷がかかります。

ほんとは一度に通知を送るほうも実装したいけど・・・・次の機会にw

 

もしよかったら使って下さいm(_ _)m

You may also like...

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です