FCM (Firebase Cloud Messaging) は Android / iOS でプッシュ通知を実装する際に利用するサービスであるが、これが 2024 年 6 月 20 日から従来のレガシーな実装は廃止されるとメールで通知が来た。 なので FCM HTTP v1 API への移行を余儀なくされたわけだ。 移行に関しては公式ドキュメントに記載があるのでこの通りやればいいのだが、残念ながら PHP で書いた時の例がない。 Firebase Admin SDK を利用すれば比較的簡単に実装できるようだが、これも PHP 非対応である。 これだけメジャーで使われているのに何故こんなに PHP に対して塩対応なのか。 まあ言語仕様がアレだから Google 的には使わせたくないというのはわからないでもないが……。 ともかくこれをやる上で必要だったこと、ハマったことをここにメモっておく。

OAuth 2.0 token には Google APIs Client

前述の公式移行ドキュメントに記載のある通り HTTP ヘッダに OAuth 2.0 のアクセストークンを含める必要がある。 これを自前で発行・管理するのは面倒なので Google APIs Client Library for PHP を使ったらうまくいった。 尚、PHP が古い場合 composer require するライブラリバージョンを下げる必要がある。

// PHP 7.2 でも動くように古いバージョンを指定する
composer require google/apiclient:2.12.1

実装は以下のような感じ:

// Firebase Console から持ってきた秘密鍵 JSON を指定する. 本来は環境変数に書くべきところ
putenv('GOOGLE_APPLICATION_CREDENTIALS=hoge/fuga.json');

// まず Google API Client で OAuth 2.0 トークンを取得する
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope('https://www.googleapis.com/auth/firebase.messaging');
$httpClient = $client->authorize();

// push する JSON を組み立てる
$json = [
    'message' => [
        'token' => $token,
        'notification' => [
            'title' => 'FCM message',
        ],
        'data' => $data,
    ],
];
$url = 'https://fcm.googleapis.com/v1/projects/${project-id}/messages:send';
$result = $httpClient->post($url, ['json' => $json]);

data には key-value pair として双方とも string を指定する

上記のような実装で何度か試してみると 400: Bad Request が返却されて正しく通らない。 何故なのかずっと試行錯誤していたところ $data に含める PHP 連想配列は key, value 共に string でなければならないことがわかった。 つまり、

$data = ['key' => '1'];  // これは送信できる
$data = ['key' => 1];  // これは送信できない (値が int)
$data = ['key' => ['key2' => '1']];  // このようにネストした連想配列も送信不可

ちなみに legacy FCM API では前述のすべての例が送信できたので、全然気づかずハマってしまった。 ということで旧 API との互換性がなく、もしクライアント側でこのようなネストした値を parse している場合移行する時に工夫する必要があるかもしれない。