【@shopify/shopify-api】Received Invalid shop argumentの対処法

## はじめに

Shopifyの公式ライブラリを使って、認証認可を行うときにエラーがでたので今回はエラーとその対処法について書いていこうと思います。

ちなみにShopifyの公式ライブラリの他のエラーについても記事にしているのでよろしければご覧ください。

[**@shopify/shopify-api**: Shopify.Context.initialize()がundefinedになる](https://qiita.com/manasan-iTL/items/0201583ec9bd1b6e4bf9) 

### この記事の対象者

- Shopifyの公式ライブラリ「**@shopify/shopify-api**」を使っている人
- Shopifyの認証認可で躓いている人

### 解決法だけ知りたい人へ

beginAuth()に渡すshopの引数をURLではなく、**ドメイン名**にする。

```jsx
// 以下は動かない
// const shop = "[https://test-theme-jp.myshopify.com/](https://development-test-theme-jp.myshopify.com/)"

// ドメイン名で保存する
const shop = "[test-theme-jp.myshopify.com](https://development-test-theme-jp.myshopify.com/)"
```

### **実行環境**

- OS：Windows 11 Home 21H2
- 言語
    - Node.js
        - version: 16.11.1
    - npm
        - version: 8.0.0
- 使用しているライブラリ・フレームワーク
    - Express
        - version: 4.18.1
    - @shopify/shopify-api (shopify-api-node Shopify公式のライブラリ)
        - version: ^5.0.1

### 前提知識
<details>
<summary>shopify/shopify-apiとは？</summary>
<ul>
    <li>Shopifyが提供するNode.js製のライブラリ。</li>
    <li>Shopify Appのインストール時に発生する<strong>OAuth認証</strong>のフローを抽象化し、自分で一から実装するよりも<strong>短く、安全</strong>にOAuth認証～アクセストークン取得を実装することができる。
    </li>
</ul>
</details>
<details>
<summary><code>beginAuth()</code>について</summary>
<ul>
    <li>概要</li>
    <ul>
      <li>OAuth認証を始めるときに呼び出す関数。認証認可画面に遷移し、ユーザが認可を終えたあと、引数に渡したコールバックURLに認可コードが送られる。
      </li>
    </ul>
    <li>引数</li>
    <ul>
        <li>request: HTTPリクエスト</li>
        <li>response: HTTPレスポンス</li>
        <li>shop: ストアの<strong>ドメイン名<strong></li>
        <li>redirectPath: アプリ管理画面で指定したコールバックURL</li>
        <li>isOnline: オンラインセッションかオフラインセッションかをbooleanで判定</li>
    </ul>
    <li>戻り値</li>
    <ul>
        <li>認証・認可画面へのURL</li>
    </ul>
</ul>
</details>

## エラーの詳細

### やりたかったこと

- Shopifyが提供するAdmin APIへのアクセストークンを取得する
    - ユーザーが遷移する認証認可のURLを生成したい。
    - [このドキュメント](https://github.com/Shopify/shopify-api-node/blob/main/docs/usage/oauth.md#add-your-oauth-callback-route)で、認証認可のURLを生成する`beiginAuth()`を実行してユーザーを認証画面にリダイレクトしたい。

### 発生したエラー（上手くいかなかったこと）

- `beginAuth()`を実行すると、**Received Invalid shop argument**というエラーが発生した。
    - shopに渡している値が**正しくない**と怒られる。
    - [公式ドキュメント](https://github.com/Shopify/shopify-api-node/blob/main/docs/getting_started.md#set-up-environment)では、shopの値を**環境変数**で管理してそれを読み取って`beginAuth()`に渡しており、自分も同じように実装した。
        - **Express**で実装しています。

コード例

```jsx
import dotenv from 'dotenv'

dotenv.config()

// 環境変数の読み取り
const { API_KEY, API_SECRET_KEY, SCOPES, SHOP, HOST, HOST_SCHEME } = process.env;

/*       途中の処理は割愛        */

router.get('/login', async(req, res) => {
    console.log(SHOP)
    let authRoute = await Shopify.Auth.beginAuth(
        req,
        res,
				// ここで渡している値が正しくないと怒られる 
        SHOP,
        '/shopify/auth/callback',
        false,
      );
      return res.redirect(authRoute);
})
```

### 調査

<details>
<summary>1 環境変数が読み取れるかをConosoleで確認する</summary>
<ul>
    <li>環境変数で取得したSHOPの中身を<code>beginAuth()</code>の直前で確認する。ここで<code>undefined</code>になっていないかを確認。</li>
    <li>
         Consoleで確認したところ、<code>https://test-theme-jp.myshopify.com/</code> だった。
    </li>
</ul>
</details>
<details>
<summary>2 公式ドキュメントを読み直す</summary>
<ul>
    <li>公式ドキュメントを読み直した。環境変数を設定するページではSHOPに<strong>dev store url</strong>を保存すると書いてあった。
    </li>
       <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2983519/049d4f75-64bb-1cba-7982-a75eebaf2849.png">
    <li>
       引用元：<a href="https://github.com/Shopify/shopify-api-node/blob/main/docs/getting_started.md#set-up-environment">https://github.com/Shopify/shopify-api-node/blob/main/docs/getting_started.md#set-up-environment</a>
    </li>
    <li>
    ただ、<code>beginAuth()</code>の引数について解説するページでは、urlではなく<strong>ドメイン名</strong>を渡すように書いてあった。
    </li>
    <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2983519/a448a440-a0bf-d1b6-5876-a19f85bc58b0.png">
</ul>
</details>

### 調査結果、エラーの原因

- すごいややこしいが、<code>beginAuth()</code>に渡すshop名は<strong>ドメイン名</strong>でないといけない。
    - 環境変数の方にはurlと書いてあったので自分はそっちを保存していた。
    - 公式ドキュメント分かりづらい。。

## エラーの解決法

- 環境変数でshopにストアのURLを保存するときは、**ドメイン名**で保存すれば良い
- 動かない
    - [`https://test-theme-jp.myshopify.com/`](https://development-test-theme-jp.myshopify.com/)
    - https://　スキーマが含まれていると動かない
- 動く
    - [`test-theme-jp.myshopify.com`](http://development-test-theme-jp.myshopify.com/)
    - ドメイン名だとちゃんと動く

## おわりに

ちゃんとライブラリが用意している関数やクラスなどの**仕様**を見ておくことが大事だと改めて痛感しました。

とはいえ、あの記述の仕方だと勘違いしてしまうので修正してほしいですね。。

## 【参考にしたサイト・動画等】

- 公式ドキュメント　環境変数のセットアップ
[shopify-api-node/getting_started.md at main · Shopify/shopify-api-node](https://github.com/Shopify/shopify-api-node/blob/main/docs/getting_started.md#set-up-environment)

- 公式ドキュメント　beginAuth()の引数について
[shopify-api-node/oauth.md at main · Shopify/shopify-api-node](https://github.com/Shopify/shopify-api-node/blob/main/docs/usage/oauth.md#add-a-route-to-start-oauth)

- このライブラリに関する他のエラー及び解決法
[**@shopify/shopify-api**: Shopify.Context.initialize()がundefinedになる](https://qiita.com/manasan-iTL/items/0201583ec9bd1b6e4bf9)