APNS拡張ペイロードでエラーレスポンスを取得

拡張ペイロードで取得可能。
単純形式のペイロードに比べて、

  • 通知期限
  • エラー応答

をサポート。

単純形式に以下を変更、追加して通知パケットを送信

  • 1(固定コマンド 1btyte)
  • 応答識別子(integer 4byte)
  • 有効期限(UNIXタイムスタンプ integer 4byte)

拡張ペイロードサンプル
実際の通知payload生成は以下のような感じ。

function get_payload($token_id, $data, $respose )
{
    //token_idを16進→バイナリへ
    $deviceToken = pack('H64',$token_id);
    //エラー時はこの$resposeに対してエラーがあったと応答
    $responce_id = pack('N', $respose );
    //メッセージ保存は1週間
    $timeout = pack('N', time()+(7 * 24 * 60 * 60) );

    //JSON文字列作成
    $payload = '{ "aps" :{ "badge" : '. $data.' } }';

    //バイナリデータ作成
    $msg = pack('C','1').
           $responce_id.$timeout.
           pack('n',32).                             //Token length
           $deviceToken.                             //device Token(binary)
           pack('n',strlen($payload)) .              //Payload length
           $payload;
    return($msg);
}

エラーパケットの読み込みは、エラー時のみ応答パケットを返却するので、
正常時にreadしようとすると、ストリームがデータを読み出せる状態になるまで待ちつづけてしまう。
なので、ストリームを非ブロックモードに指定。

//APNSサーバ接続
$ctx = stream_context_create();  
stream_context_set_option( $ctx, 'ssl', 'local_cert',  $cert_file );
stream_context_set_option( $ctx, 'ssl', 'verify_peer', TRUE );
$fp = stream_socket_client( $url, $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx );  
//非ブロックモードに
stream_set_blocking( $fp, 0 );
//ペイロード生成
$this->get_payload( $token_id, $data, $member_id );
//パケット送信
for ($written = 0; $written < strlen($payload); $written += $fwrite) {
    $fwrite = fwrite($fp, substr($payload, $written));
    if (!$fwrite) {
        $this->_log_err( 'fwrite error ['.$written.']' );
        break;
    }
}
//エラーキャッチ
$error_byte = @fread( $fp, 6 );
if( strlen( $error_byte ) == 6 )
{
    error_log( var_export( unpack( "C", substr( $error_byte, 1, 1 ) ), 1) );
    error_log( var_export( unpack( "N", substr( $error_byte, 2    ) ), 1) );
}

これで、APNSのエラーがフックできる。


応答パケットについてはDocumentを読むのが早いがメモついでに。
command (1byte 固定値:8)
status (1byte
 0:遭遇エラーなし,
 1:処理エラー,
 2:トークン欠如,
 3:トピック欠如,
 4:ペイロード欠如,
 5:無効トークンサイズ,
 6:無効トピックサイズ,
 7:無効ペイロードサイズ,
 8:無効トークン,
 255:不明
)
identifer (4byte ペイロード指定の識別子($responseの値))