Shopify 統合の開発を開始しています。統合しようとしているアプリには、ユーザー アカウントごとに異なるサブドメインがあるため、oauth 接続要求ごとに異なるコールバック ドメインにリダイレクトする必要があります。これまでのところ、Shopify 承認 URL にリダイレクトして、ユーザーが自分のアカウントへのアクセスを許可できるようにしています。ただし、次のエラー応答が返されます。
{"error":"invalid_request",
"error_description":"The redirect_uri and application url must have matching hosts"}
URL の形式は次のとおりです。
https://SHOP_NAME.myshopify.com/admin/oauth/authorize?client_id=MY_CLIENT_ID&scope=read_order&redirect_uri=SUBDOMAIN.MYAPP.com
アプリケーション URL (Shopify の管理ページで設定) をこれらすべてに設定しようとしましたが、同じエラーが表示されます。
http://MYAPP.com
http://.MYAPP.com
http://*.MYAPP.com
ただし、次のように動作させることができます。
http://SUBDOMAIN.MYAPP.com
クエリ文字列から情報を取得し、サブドメインにリダイレクトするエンドポイントを作成できます。次に例を示します。
callback.MYAPP.com?subdomain=SUBDOMAIN
これは回避できますが、Shopify ページでアプリへのリンクも作成したいので、Shopify API がサブドメインをサポートし、これらのレベルの間接化を構築し続ける必要がないようにしたいと考えています。(ただし、アプリケーション リンクの管理ページを見ると、そこでも同じことをしなければならないようです。)
非標準の TLD を使用しています (これは現在開発中のため)。したがって、MYAPP.com を配置した場所は実際には oh.dev ですが、hosts ファイルを編集して .com を使用しようとしましたが、同じ結果が得られました。
Shopifyにサブドメインをcallback_urlとして受け入れるようにする方法を知っている人はいますか? 明らかな何かを見逃しましたか?
Clojure のコードは次のとおりです。
(require '[com.twinql.clojure.http :as http] '[clojure.contrib.logging :as log])
(defn consumer []
{:key "1234567890"
:secret "1234567890abcde"})
(defn shopify-config [shop-name]
{:request-token-url (str "https://" shop-name ".myshopify.com/admin/oauth/authorize")
:authorise-url (str "https://" shop-name ".myshopify.com/admin/oauth/authorize")
:access-token-url (str "https://" shop-name ".myshopify.com/admin/oauth/access_token")
:api-endpoint-url (str "https://" shop-name ".myshopify.com")})
(defn get-redirect-url [shop-name callback-url]
(let [{consumer-token :key consumer-token-secret :secret} (consumer)]
(str (-> shop-name shopify-config :request-token-url)
"?client_id=" consumer-token
"&scope=read_orders,read_products,read_customers"
"&redirect_uri=" callback-url)))
(defn get-access-credentials [verifier shop-name]
(let [{:keys [key secret]} (consumer)
response (http/post (-> shop-name shopify-config :access-token-url)
:as :json
:query {"client_id" key
"client_secret" secret
"code" verifier})]
(log/debug (str "response from getting access credentials from shopify : " response))
{:access-token (-> response :content :access_token)
:consumer-key key
:consumer-secret secret}))
(def methods {:get http/get
:post http/post
:delete http/delete
:put http/put})
(defn- make-request [method shop-name url token params]
(let [response (method (str (-> shop-name shopify-config :api-endpoint-url) url)
:as :json
:query params
:headers {"X-Shopify-Access-Token" token})]
(if (-> response :code (= 200))
(:content response)
(do
(log/error (str "Error in shopify request : " response))
(throw (Err. {:handle :shopify-request-error
:response response}))))))
(defn get-products [shop-name token page]
(make-request (:get methods) shop-name "/admin/products.json" token {:page page :limit 200}))
また、ユーザーからショップ名などを取得し、DBなどに格納するコードもあります。したがって、基本的に get-redirect-url を呼び出してユーザーを shopify にリダイレクトし、権限を承認してもらいます。Shopify に渡す callback-url は次のようなものです。
http://customer1.oh.dev/integrations/shopify/1/callback
次に、提供されたコードを受け取り、get-access-credentials を呼び出します。周囲のコードには、返されるアクセス トークンなどが格納されます。次に、トークンとショップ名を取得した後、get-products を呼び出す別のユーザー アクションがあります。