PHP

iOSプッシュ通知の通信をHTTP2に改修しました【やり方を解説】

2021年1月22日

iOSプッシュ通知の 通信をhttp2に改修しました【やり方を解説】と書かれた画像

 

あなた
iOSプッシュ通知のHTTP/2移行方法が知りたいです。

 

2021年3月以降にレガシーバイナリプロトコルがサポートされない旨がAppleから発表されました。

 

概要は以下のとおりです。

APNは、2021年3月31日以降、レガシーバイナリプロトコルをサポートしません。このページからHTTP / 2ベースのAPIにできるだけ早く更新することをお勧めします。

引用:Sending Notification requests to APNs

 

自分もその対応に迫られましたので対応方法を記しておきます。

 

【この記事でわかること/対象者】

✔  iOSプッシュ通知をHTTP2で行う方法

✔  サーバーサイドの方

 

iOSプッシュ通知の通信をHTTP2に変更しました

 

今回はサーバーサイドのエンジニアの方のためにiOSのプッシュ通知をHTTP2に変更する方法を紹介していきます。

 

ちなみに言語はPHPです。

環境ができていないとプッシュ通知を送ることができないので以下の条件を満たすように環境を整えてください。

  • openssl 1.0.2e以上
  • curl 7.46以上(+nghttp2)
  • PHP 5.5.24以上

 

プッシュ通知の仕組み

 

まずはじめに簡単にiOSのプッシュ通知の仕組みを話しておきます。

iOSのプッシュ通知はAPNs(Apple Push Notification service)というものを使います。

 

あなたが直接ユーザーの端末に送るわけではなくて、アプリの情報をコントロールしているAPNsサーバーにプッシュ通知のデータを送り、APNsサーバーがユーザーの端末にプッシュ通知を送るという仕組みです。

 

あなたのサーバー(アプリサーバー)→APNsサーバー→ユーザー端末

 

上記の流れを把握しておきましょう。

そしてAPNsサーバーに送るときのデータ形式も決められているので守りましょう。

 

実際のコード

 

では実際のコードを紹介します。

 

まずはヘッダーとデータのコンテンツ部分です。

今回は画像つきプッシュ通知をする際のデータとなっています。

 

//$apnsTopicはアップバンドルID、$imageUrlは画像のURL(カスタムキー)、$textは文言
$headers = ["apns-topic: $apnsTopic", "apns-expiration: 30"];
$alert = '{"aps":{"alert":"' . $text . '","sound":"default","mutable-content":"1"},"image-url":"' . $imageUrl . '"}';

 

"image-url"のキーの部分はアプリによって変わりますので、画像プッシュを採用しているアプリの場合はアプリ側のエンジニアに問い合わせてみてください。

 

もし画像プッシュがないのであればここはまるまる消してOKです。

 

headerの「"apns-expiration: 30"」はユーザーオフライン時のプッシュの再送処理です。

30は30秒を意味します。

The date at which the notification is no longer valid. This value is a UNIX epoch expressed in seconds (UTC). If the value is nonzero, APNs stores the notification and tries to deliver it at least once, repeating the attempt as needed until the specified date. If the value is 0, APNs attempts to deliver the notification only once and doesn’t store it.

 

実際にプッシュ通知を送るコードは以下のとおりです。

開発用のAPNsサーバーと本番用のAPNsサーバーではURLが変わりますので注意が必要です。

 

「$pemFile」にはプッシュ通知の証明書を指定します。

 

/**
     * curlでプッシュ通知を送る。
     * 開発サーバーURL "https://api.sandbox.push.apple.com/3/device/$deviceToken"
     *
     * @param $deviceTokens
     * @param $alert
     * @param $headers
     * @param $pemFile
     *
     * @return array  失敗時は不正なトークンの配列。成功時は空の配列を返す
     */
    private function __sendPushByCurl($deviceTokens, $alert, $headers, $pemFile){
        $detectedTokens = [];
        foreach($deviceTokens as $deviceToken){
            //本番サーバー
            $url = "https://api.push.apple.com/3/device/$deviceToken";
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $alert);
            curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($ch, CURLOPT_SSLCERT, $pemFile);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            $response = json_decode(curl_exec($ch), true);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            if($httpCode == 400){
                if($response["reason"] == "BadDeviceToken" || $response["reason"] == "MissingDeviceToken"){
                    array_push($detectedTokens, $deviceToken);
                }
            }
            if($httpCode == 403){
                if($response["reason"] == "ExpiredProviderToken" || $response["reason"] == "InvalidProviderToken"){
                    array_push($detectedTokens, $deviceToken);
                }
            }
            if($httpCode == 410){
                if($response["reason"] == "Unregistered"){
                    array_push($detectedTokens, $deviceToken);
                }
            }
        }
        return $detectedTokens;
    }

 

上記コードではデバイストークンごとにプッシュ通知を行い、失敗した場合は失敗したトークンを配列に入れて返しています。

 

ちなみにステータスコードやレスポンスの内容に関しては以下の公式ページで公開されています。

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/handling_notification_responses_from_apns

 

検出したいステータスコードは好みにカスタムしてください。

 

ハマりそうな点

 

以下の点は注意しておくといいかなと思います。

 

・ペイロードのカスタムのキー(画像など)

・画像プッシュの場合は「"mutable-content":"1"」が必要なこと

・HTTP2通信を行うには環境は

  • openssl 1.0.2e以上
  • curl 7.46以上(+nghttp2)
  • PHP 5.5.24以上
上記が必要。
 
・MAMPとか使っている場合はローカルの環境構築は面倒なのでサーバーを立てて、そこに環境作っちゃったほうが良い

 

仕組みを把握すればそんなに難しくはないのでぱぱっとやってしまおう

 

今回はiOSのプッシュ通知をhttp2で行う方法を紹介しました。

以前はAPNsPHPみたいなライブラリを使っていたのですがそれよりも記述量がすくなくなったのでありがたいです。

 

レスポンスも詳しく公式がまとめてくれているのでステータスコードによる処理の分岐も明確にできるかなと思います。

 

プッシュ通知の仕組みを理解すればそんなに難しくはないのでぱぱっとやってしまいましょう。

 

今回は以上です。

 

プログラミングスクールに関する情報

【無料あり】プログラミングスクールおすすめランキング【WEBエンジニアになりたい方向け】と書かれた画像
【無料あり】プログラミングスクールおすすめランキング【WEBエンジニアになりたい方向け】

  あなたプログラミングスクールに通いたいけどたくさんありすぎてどこがいいのかわかりません。   最近はエンジニアブームということもありプログラミングスクールが増えました。 一方でたくさんありすぎてど ...

続きを見る

フリーランス
無料あり:フリーランスを目指せるプログラミングスクールランキング【体験をもとに徹底分析しました】

  あなたフリーランスエンジニアを目指すことができるプログラミングスクールってありますか?   最近では、高年収や働きやすさの魅力からフリーランスエンジニアを目指す方も増えてきまし ...

続きを見る

返金保証ありのプログラミングスクールランキング【エンジニアが選びました】と表示されたパソコンの画面
返金保証ありのプログラミングスクールランキング【エンジニアが選びました】

  あなた返金保証がついているオススメのプログラミングスクールってありますか?   結論から話すと、返金保証つきのプログラミングスクールランキングは次の通りです。   1位:DMMWEBキャンプ  【 ...

続きを見る

WEB系自社開発企業にいけるプログラミングスクールランキング【現役エンジニアおすすめ】と書かれた画像
WEB系自社開発企業にいけるプログラミングスクールランキング【現役エンジニアおすすめ】

  あなたWEB系の自社開発企業に就職したいです。 オススメのスクールを教えて下さい。   結論から話すと、WEB系自社開発に行きやすいスクールのランキングは以下の通り。   第1位:テックアカデミー ...

続きを見る

プログラミンングスクールに無料で通うならココ【現役エンジニアおすすめ】と書かれた画像
プログラミンングスクールに無料で通うならココ【現役エンジニアおすすめ】

  あなたプログラミングスクールに通いたいけどどのスクールも何十万もして通えません。コスパよくエンジニアになれるスクールはありますか?   今回はコスパが良いどころか完全に無料でプ ...

続きを見る

-PHP

© 2021 エンジニアてんし君ブログ