【Shopify】Admin APIをPHPクライアントライブラリで使う

ShopifyのAdmin APIをPHPで利用したいプロジェクトがありました。
Shopifyのドキュメントの通りPHP用のライブラリを入れたのですが、OAuth認証がどうしてもできず、カスタマイズしたのでメモとして残しておきます。
つい最近GraphQL Admin API referenceからPHPがなくなったので、他の使ってよという事かもしれないのですが。
ひとつ目の上手くいかなかったところから。
OAuth::begin()で正いURLが生成されない
$authUrl = OAuth::begin($shop, $redirectUri, $isOnline);
このOAuth:begin()でOAuthのURLが生成される想定なのですが、パスが重なってどうも上手く生成されません。
しょうがないのでこれは使わずに、URLを書いて作ります。
$authUrl = "https://".env('SHOPIFY_APP_HOST_NAME')."/admin/oauth/authorize?client_id=".env('SHOPIFY_API_KEY')."&scope=".env('SHOPIFY_SCOPES')."&redirect_uri=".$redirectUrl."&state=".$state;
Shopify キー等はenvで指定しています。
次に上手くいかないこと。
リダイレクトで戻ってきた時にCOOKIEのエラーが出る
You may have taken more than 60 seconds to complete the OAuth process and need to start over in..
とCOOKIEのエラーが出ます。
そもそもこのエラーの場合はエラー内容の通りにリダイレクトまでに時間がかかっているよ、という事で、本当に時間がかかっているか、もしくはサーバーの時間がおかしいかのどちらかになります。
そういったエラーかと思っていたのですが、調査していくとどうやらOAuth::begin()を使っていないせいで、必要なCOOKIEが生成されてないのがひとつ。
仕方がないのでCOOKIEは自作します。
OAuthに必要なCOOKIEを自作する
このコードはLaravel11で作っていますのでLaravel用の関数が含んでいるかもしれません。ご容赦ください。
//Cookieは自作する
// 1. Shopify App State(CSRF保護用stateトークン)の生成と保存
$state = bin2hex(random_bytes(16));
// stateトークンをクッキーに保存
$cookies[] = cookie('shopify_app_state', $state, 60, '/', null, true, true);
// stateトークンの署名(sig)を生成
$stateSig = hash_hmac('sha256', $state, env('SHOPIFY_API_SECRET'));
// state署名をクッキーに保存
$cookies[] = cookie('shopify_app_state_sig', $stateSig, 60, '/', null, true, true);
// -------------------------------
// 2. Shopify Session IDの生成と保存
$sessionId = session_id(); // PHPのセッションIDを取得
// セッションIDをクッキーに保存
$cookies[] = cookie('shopify_session_id', $sessionId, 60, '/', null, true, true);
// セッションIDの署名(sig)を生成
$sessionSig = hash_hmac('sha256', $sessionId, env('SHOPIFY_API_SECRET'));
// セッションID署名をクッキーに保存
$cookies[] = cookie('shopify_session_id_sig', $sessionSig, 60, '/', null, true, true);
//State
$cookies[] = cookie('shopify_state', $state, 60, '/', null, true, true);
$stateは先ほどのURL生成の一番後ろにある$stateです。
もしくはライブラリでOAuth::begin()を修正してしまう
shopify/shopify-api/src/Auth/OAuth.php
53行目のこれを
'redirect_uri' => Context::$HOST_SCHEME . '://' . Context::$HOST_NAME
こっちに↓
'redirect_uri' => $redirectPath,
リダイレクトで戻ってきた時にも正く必要な値でCOOKIEに入っていることが確認できます。
しかし、どうしても先ほどのエラーで進みません。
しょうがないのでライブラリの中身を見ていると、COOKIEのexpires(期日)の取得がうまくいってないようなので、ライブラリをちょっと編集します。
Auth/OAuth.phpを修正する
shopify/shopify-api/src/Auth/OAuth.php
155行目のこれを
$sessionExpiration = ($session->getExpires() ? (int)$session->getExpires()->format('U') : 0);
次のように、0をnullにする
$sessionExpiration = ($session->getExpires() ? (int)$session->getExpires()->format('U') : null);
修正したとことでアプリを削除し再度認証を行います。
この修正で無事OAthが完了しました。