Shopify APIを利用して在庫管理を行うShopify APIで在庫を自動更新する仕組みを調査・実装してみた

最近、Shopifyで販売している商品の在庫を、一定間隔で指定数に自動更新してほしいという依頼を受けました。
そこで、Shopify APIの仕様や利用方法について詳しく調査してみました。
Shopifyの在庫を更新するには?
Shopifyの商品在庫を更新するには、**Shopify API(GraphQL)**を使用します。
公式ドキュメントは https://shopify.dev/api にあります。
Shopify APIを利用するには?
APIを利用するには、アクセストークンの取得が必要です。
アクセストークンはShopifyの管理画面からアプリを作成し、スコープを設定することで取得可能です。
在庫に関するAPIは?
2022年9月時点で、在庫を「直接更新」するAPIは提供されていないようです。
そのため、現在の在庫を取得 → 必要数を計算 → 追加分を加算する、という形で更新を行います。
Shopify APIを利用する
まずは、商品ごとの inventoryItemId
(在庫アイテムID)と SKU
を取得します。
inventoryItems
まずは[inventoryItems]を利用して商品の「inventory item Id」「SKU」を取得します。
1 2 3 4 5 6 7 8 9 10 | $query = '{ inventoryItems(first:50) { edges { node { id sku } } } }'; |
PHPでのリクエスト例(GraphQL):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $options = [ 'http' => [ 'ignore_errors' => true, 'method' => 'POST', 'header' => [ 'scope: read_customers', 'Content-Type: application/graphql', 'X-Shopify-Access-Token: ' . 'shpat_*****************' ], 'content' => $query ] ]; $context = stream_context_create($options); $contents = file_get_contents('https://********.myshopify.com/admin/api/2022-07/graphql.json', false, $context); print_r(json_decode($contents)); |
レスポンス例:
[id]がinventory item Id、[sku]がSKUとなります。
※SKUは必須ではないため、事前にユニークな値を登録しておくと扱いやすくなります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | stdClass Object ( [data] => stdClass Object ( [inventoryItems] => stdClass Object ( [edges] => Array ( [0] => stdClass Object ( [node] => stdClass Object ( [id] => gid://shopify/InventoryItem/41887914033229 [sku] => test-0001 ) ) [1] => stdClass Object ( [node] => stdClass Object ( [id] => gid://shopify/InventoryItem/41887914065997 [sku] => test-0002 ) ) [2] => stdClass Object ( [node] => stdClass Object ( [id] => gid://shopify/InventoryItem/41887914098765 [sku] => test-0003 ) ) ) ) ) [extensions] => stdClass Object ( [cost] => stdClass Object ( [requestedQueryCost] => 52 [actualQueryCost] => 31 [throttleStatus] => stdClass Object ( [maximumAvailable] => 1000 [currentlyAvailable] => 969 [restoreRate] => 50 ) ) ) ) |
productVariants
続いて、商品バリアントから**現在の在庫数(inventoryQuantity
)**を取得します。
1 2 3 4 5 6 7 8 9 10 11 12 13 | $query = '{ productVariants(first: 50) { edges { node { id sku barcode inventoryQuantity price } } } }'; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | stdClass Object ( [data] => stdClass Object ( [productVariants] => stdClass Object ( [edges] => Array ( [0] => stdClass Object ( [node] => stdClass Object ( [id] => gid://shopify/ProductVariant/39788322979917 [sku] => test-0001 [barcode] => [inventoryQuantity] => 10 [price] => 1000 ) ) [1] => stdClass Object ( [node] => stdClass Object ( [id] => gid://shopify/ProductVariant/39788323012685 [sku] => test-0002 [barcode] => [inventoryQuantity] => 10 [price] => 1000 ) ) [2] => stdClass Object ( [node] => stdClass Object ( [id] => gid://shopify/ProductVariant/39788323045453 [sku] => test-0003 [barcode] => [inventoryQuantity] => 10 [price] => 1000 ) ) ) ) [extensions] => stdClass Object ( [cost] => stdClass Object ( [requestedQueryCost] => 52 [actualQueryCost] => 31 [throttleStatus] => stdClass Object ( [maximumAvailable] => 1000 [currentlyAvailable] => 969 [restoreRate] => 50 ) ) ) ) |
在庫調整には「ロケーションID」が必要です。以下のクエリで取得できます。
locations
複数ロケーションを管理している場合は、対象商品がどのロケーションに属しているかの割り当ても必要ですが、今回は1件のみのため割愛します。
1 2 3 4 5 6 7 8 9 | $query = '{ locations(first: 50) { edges { node { id } } } }'; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | stdClass Object ( [data] => stdClass Object ( [locations] => stdClass Object ( [edges] => Array ( [0] => stdClass Object ( [node] => stdClass Object ( [id] => gid://shopify/Location/61785047117 ) ) ) ) ) [extensions] => stdClass Object ( [cost] => stdClass Object ( [requestedQueryCost] => 52 [actualQueryCost] => 3 [throttleStatus] => stdClass Object ( [maximumAvailable] => 1000 [currentlyAvailable] => 997 [restoreRate] => 50 ) ) ) ) |
全ての情報が取得できたら、現在の在庫数から加算したい在庫数を商品ごとに計算し「inventory item Id」を利用して在庫を加算していきます。
inventoryBulkAdjustQuantityAtLocation
加算処理は以下のMutationで実施します。
クエリーは下記のように記載します。「availableDelta」に加算したい在庫数を設定、「inventoryItemId」「locationId」には取得したIDを記載します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $mutation = ' mutation{ inventoryBulkAdjustQuantityAtLocation( inventoryItemAdjustments:{ availableDelta: 10, inventoryItemId: "gid://shopify/InventoryItem/41946259030093" }, locationId: "gid://shopify/Location/61785047117" ) { inventoryLevels { id available } } } '; |
正常に更新されると、available
が加算された数値として返ってきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | stdClass Object ( [data] => stdClass Object ( [inventoryBulkAdjustQuantityAtLocation] => stdClass Object ( [inventoryLevels] => Array ( [0] => stdClass Object ( [id] => gid://shopify/InventoryLevel/96102449229?inventory_item_id=41946259030093 [available] => 20 ) ) ) ) [extensions] => stdClass Object ( [cost] => stdClass Object ( [requestedQueryCost] => 10 [actualQueryCost] => 10 [throttleStatus] => stdClass Object ( [maximumAvailable] => 1000 [currentlyAvailable] => 990 [restoreRate] => 50 ) ) ) ) |
Shopify APIを利用してみて
今回、初めてShopify API、そしてGraphQLを使って実装しました。
結論としては、構文のクセこそあるものの、構造を理解すれば非常に便利で柔軟性の高いAPIだと感じました。
ただし、Shopifyでは在庫を直接「この数に設定する」APIは用意されていない点に注意が必要です。
そのため「差分加算」で在庫を調整する必要があり、やや回りくどく感じました。
また、在庫編集に関する情報はあまり多くなかったため、情報共有・備忘録としてこの記事をまとめました。
同様の課題に取り組む方の参考になれば幸いです。
S.E->お勧め記事;
- Python 配列(タプル)
- PHPフレームワーク「Laravel」Bladeテンプレートを利用する
- CrowdWorks いつの間にか「プロクラウドワーカー」になっていた
- Panic Nova 購入から1年が過ぎライセンスの更新時期の注意点
- macOS Monterey にアップデート後、composerやhomebrewでenv: php: No such file or directoryが出る
- CrowdWorks 提案後、受注に繋がりました。提案〜契約までの流れを解説
- PHPフレームワーク「Laravel」ファイル構造
- PHP フレームワーク Laravel ディレクティブ – ループ変数 $loop –
- プログラマー になる為に必要な プログラミング以外 の知識・スキル
S.E->PR;
チームのタスク管理ツール【backlog】
FREENANCE(フリーナンス)
S.E->Weekly Ranking;
S.E->プロフィール;

