💥
Shopify/Ruby: プライベートアプリのAPI設定で BAD_REQUEST エラーが出る場合の対処法
環境
- Ruby 2.6.9
- gem shopify_api 10.1.0
背景
Fulfillment APIが利用できなくなるため、Shopifyプライベートアプリの gem shopify_api
をv9からv10にアップグレードにしないといけませんでした。
エラー
ビルトインのRESTリソース(Shop.all
など)を利用した場合、Product.update
やInventoryItem.find
などの一部のAPIエンドポイントで以下のエラーが発生しました。
ShopifyAPI::Errors::HttpResponseError: {"message"=>"Bad Request", "extensions"=>{"code"=>"BAD_REQUEST"}}
また同エラーでGraphQLも同様に一部利用できませんでした。
原因
gemのREADMEに基づき、設定ファイルは以下のように書いていました。
scope = %w[
read_content
read_customers
write_orders
write_products
write_inventory
write_fulfillments
write_assigned_fulfillment_orders
write_merchant_managed_fulfillment_orders
write_third_party_fulfillment_orders
write_custom_fulfillment_services
].join(',')
ShopifyAPI::Context.setup(
api_key: Rails.application.credentials.shopify[:api_key],
api_secret_key: Rails.application.credentials.shopify[:api_secret_key],
host: "https://application-host-name.com",
scope: scope,
session_storage: ShopifyAPI::Auth::FileSessionStorage.new,
is_embedded: false,
api_version: "2022-04",
is_private: true,
)
session = ShopifyAPI::Auth::Session.new(
shop: 'application-host-name.com',
access_token: Rails.application.credentials.shopify[:api_access_token]
)
p = ShopifyAPI::Product.find(session: session, id: 123456789)
p.title = "new title"
p.update!
# ShopifyAPI::Errors::HttpResponseError: {"message"=>"Bad Request", "extensions"=>{"code"=>"BAD_REQUEST"}}
ダッシュボードで生成されたAPIアクセストークンのみ使ったプライベートアプリの設定方法がドキュメントでは明確じゃないのですが、どうやら問題は Auth::Session
の shop
はカスタムドメイン(application-host-name.com)ではなく「myshopify.comドメイン」でないとダメだったみたいです。
解決策
同エラーに関連するIssueページ:https://github.com/Shopify/shopify-api-ruby/issues/91
スレッドのアドバイスに基づいて以下の変更を行い、ついにプライベートアプリが shopify_api
v10で動作するようになりました🎉
ShopifyAPI::Context.setup(
# These values are required but not actually used for private apps
api_key: "DUMMY_VALUE",
host_name: "DUMMY_VALUE",
scope: "DUMMY_VALUE",
private_shop: 'your.myshopify.com',
api_secret_key: Rails.application.credentials.shopify[:api_access_token],
session_storage: ShopifyAPI::Auth::FileSessionStorage.new,
is_embedded: false,
is_private: true,
api_version: '2022-04',
)
-
private_shop
: <your.myshopify.com> -
api_secret_key
: APIアクセストークン -
api_key
,host_name
,scope
は無視してOK
session = ShopifyAPI::Utils::SessionUtils.load_current_session
p = ShopifyAPI::Product.find(session: session, id: 123456789)
p.title = "new title"
p.update!
# T::Private::Types::Void::VOID
Discussion