Shopify の注文・支払い API を利用する

注文・支払い関連の API の Create / Read / Update / Delete（以降CRUD）を検証し、概要を解説します。本記事は公式ドキュメントの翻訳・抜粋です。

Shopify の API は常に最新バージョンに機能進化していますので[公式ドキュメント](https://shopify.dev/docs/admin-api)をご確認下さい。本記事では執筆時点では「2020-10」です。画像はすべて [shopify.dev](https://shopify.dev/) から引用をしております。

記載内容に誤りがあればご指摘下さい。

# 注文・支払いAPIの使い方
各APIでの注文・支払いの処理フローイメージです

## 注文（Order）API
1. 支払いを別の決済システムで行う
2. 注文APIを呼び出し、注文情報を作成する

## 下書き注文（DraftOrder）API
1. 下書き注文APIを呼び出し「draft_order_id」を取得
2. 請求メールをユーザーへ送信（send_invoice）
3. メール内のチェックアウトページURLへユーザーを誘導
4. ユーザー自身で「情報＞配送＞支払い」を入力し、支払い＋注文を行う

## チェックアウト（Checkout）API
1. チェックアウトAPI を呼び出し「web_url」を取得
2. チェックアウトページURLへユーザーを誘導
3. ユーザー自身で「情報＞配送＞支払い」を入力し、支払い＋注文を行う

## 支払い（Payment）API
1. チェックアウトAPI を呼び出し、チェックアウトを作成し「token」を取得
2. Shopify のセキュアなカード保管庫（card vault）にクレジットカード情報を送信し、支払いのためのセッションIDを取得
3. 支払いを行う
4. 注文APIを呼び出し、注文情報を作成する


# API 検証
プライベートアプリでAPIを呼び出しをしています。検証に用いたAPI呼び出しコードをサンプルで記載しますので、ご自身でレスポンス結果をご覧ください。

```node.js
const axiosBase = require('axios')

try{
    const axios = axiosBase.create({
        auth: {
            username: 'APIキー',
            password: 'パスワード'
        },        
        baseURL: 'https://ショップ名.myshopify.com',
        headers: {
          'Content-Type': 'application/json',
        },
        responseType: 'json'  
    });

    // GET Order https://shopify.dev/docs/admin-api/rest/reference/orders/order#index-2020-10
    axios.get('/admin/api/2020-10/orders.json?status=any')
        .then(res=>{
            console.log(res.data)
        })
        .catch(err=>{console.log(err)})

}catch(error){
    console.log(error)
}
```

以降、APIの説明を割愛します。[翻訳: WebAPI 設計のベストプラクティス](https://qiita.com/mserizawa/items/b833e407d89abd21ee72)をご覧頂くと理解が深まるかと思います。

# Order
注文情報の CRUD を扱います
https://shopify.dev/docs/admin-api/rest/reference/orders/order
![c1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/c03eac03-a2b8-d6d9-dedc-40e1d1a3f341.jpeg)

## 注意したいポイント
注文（Order）と支払い（Checkout）は分けて考えて下さい。
Order API で支払いを作成することは出来ません。支払いは [Checkout API](https://shopify.dev/tutorials/sell-through-the-checkout-api) を利用します。Order API で注文を作成すると注文が１件出来ますが、支払いをしたかどうかはわかりません。決済システムを Shopify 以外で持ち、その決済と注文情報を連動させるケースなどで利用します。


## GET /admin/api/2020-10/orders.json?status=any
注文一覧取得

``` 
axios.get('/admin/api/2020-10/orders.json?status=any')
    .then(res=>{console.log(res.data)})
    .catch(err=>{console.log(err)})
```

## POST /admin/api/2020-10/orders.json
注文の作成

```
axios.post('/admin/api/2020-10/orders.json',
    {
        "order": {
            "email":"user@email.com",
            "line_items": [
                {
                "variant_id": 36712106688680,
                "quantity": 1
                }
            ]
        }
    }).then(res=>{
        console.log(res.data)
    }).catch(err=>{console.log(err)})
```

## 他 Order API
GET /admin/api/2020-10/orders/{order_id}.json
GET /admin/api/2020-10/orders/count.json
POST /admin/api/2020-10/orders/{order_id}/close.json
POST /admin/api/2020-10/orders/{order_id}/open.json
POST /admin/api/2020-10/orders/{order_id}/cancel.json
POST /admin/api/2020-10/orders.json
PUT /admin/api/2020-10/orders/{order_id}.json
DELETE /admin/api/2020-10/orders/{order_id}.json


# DraftOrder
下書き注文情報のCRUDを扱います
https://shopify.dev/docs/admin-api/rest/reference/orders/draftorder

## 注意したいポイント
DraftOrder API を利用すると、支払い前の注文を作成することができます。ユーザー自身に支払い＋注文を行わせる場合はこちらを利用します。
ユースケースとしては以下があります。

・EC以外の販売経路の（電話・直接・チャット等）注文を作成する。
・安全なチェックアウトリンクを作成し、顧客に請求書をメール送信します。ユーザーはそのリンクから支払いと注文を行います。
・登録していない商品（カスタムアイテム）を作成し、追加注文や見積もり商品の支払い＋注文に利用します。
・誤った注文の再作成、割引・卸価格での販売・予約注文

## GET /admin/api/2020-10/draft_orders.json
下書き注文一覧

```
axios.get('/admin/api/2020-10/draft_orders.json')
    .then(res=>{console.log(res.data)})
    .catch(err=>{console.log(err)})
```

## POST /admin/api/2020-10/draft_orders.json
下書き注文作成

```
axios.post('/admin/api/2020-10/draft_orders.json',
    {
        "draft_order": {
            "email":"user@email.com",
            "line_items": [
                {
                "variant_id": 36712106688680,
                "quantity": 1
                }
            ]
        }
    }).then(res=>{console.log(res.data)
    }).catch(err=>{console.log(err)})
```

## POST /admin/api/2020-10/draft_orders/{draft_order_id}/send_invoice.json
請求メール送信
draft_order_id は下書き注文を作成すると発番されます。

```
axios.post('/admin/api/2020-10/draft_orders/2948752146600/send_invoice.json',
    {
        "draft_order_invoice": {
            "to": "customer@email.com",
            "from": "staff@email.com",
            "bcc": [
                "staff@email.com"
            ],
            "subject": "テスト商品の請求書",
            "custom_message": "ご注文ありがとうございました"
        }
    }).then(res=>{console.log(res.data)
    }).catch(err=>{console.log(err)})
```


## 他 DraftOrder API

PUT /admin/api/2020-10/draft_orders/{draft_order_id}.json
GET /admin/api/2020-10/draft_orders/{draft_order_id}.json
GET /admin/api/2020-10/draft_orders/count.json
DELETE /admin/api/2020-10/draft_orders/{draft_order_id}.json
PUT /admin/api/2020-10/draft_orders/{draft_order_id}/complete.json


# Checkout
支払い（Checkout）API を利用して、販売チャネル（Sales channel）をインストールしたShopifyストアからお客様は商品を購入できます。

https://shopify.dev/docs/admin-api/rest/reference/sales-channels/checkout

## Checkout の考え方
Checkout ページでは「情報＞配送＞支払い」の順に入力します
　情報：配送先住所の入力
　配送：配送方法の選択
　支払い：クレジットカード情報の入力

[Checkout API を使用して販売する](https://shopify.dev/tutorials/sell-through-the-checkout-api)
![c2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/ef331c86-5117-4985-afd9-65b41dcea6cb.jpeg)

[Checkout API を使用して販売チャネルを構築する](https://shopify.dev/tutorials/build-a-sales-channel-with-the-checkout-api)
![c3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127260/e9f7cbf6-6201-4930-5475-78da2b960ff8.jpeg)

Checkout API は Storefront API を用いて動かします。Storefront API を利用した [Sales ChannnelSDK](https://shopify.dev/tutorials/build-a-sales-channel-with-the-checkout-api) を使用してください。

以下、公式のドキュメントベースでの解説メモになります。

## POST /admin/api/2020-10/checkouts.json

チェックアウトを作成する

### リクエスト

- variant_id：商品のバリエーションID
- quantity：個数

```shell
POST /admin/api/2020-10/checkouts.json
{
  "checkout": {
    "line_items": [
      {
        "variant_id": 36712106688680,
        "quantity": 5
      }
    ]
  }
}
```

### レスポンス

- web_url：お客様が Web からアクセス可能な支払いページURL
- token：チェックアウトの一意の識別子
- payment_url：Shopify のセキュアなカード保管庫（card vault）にクレジットカード情報を保存するための URL

※一部抜粋していますので項目全体は公式ドキュメントを参照ください

```shell
HTTP/1.1 201 Created
Location: https://apple.myshopify.com/admin/api/2020-10/checkouts/0ad1852f1017d8dea0103a98a707204a.json
{
  "checkout": {
    "created_at": "2020-10-06T14:12:45-04:00",
    "currency": "USD",
    "name": "#1066348317",
    "payment_url": "https://elb.deposit.shopifycs.com/sessions",
    "token": "0ad1852f1017d8dea0103a98a707204a",
    "total_price": "995.00",
    "web_url": "https://apple.myshopify.com/690933842/checkouts/0ad1852f1017d8dea0103a98a707204a",
    "line_items": [
      {
        "id": "c19bd8c38b94c653edfa09582abe42ae",
        "key": "c19bd8c38b94c653edfa09582abe42ae",
        "product_id": 632910392,
        "variant_id": 39072856,
        "sku": "IPOD2008GREEN",
        "vendor": "Apple",
        "title": "IPod Nano - 8GB",
        "variant_title": "Green"
      }
    ]
  }
}
```

## 他 Checkout API
POST /admin/api/2020-10/checkouts/{token}/complete.json
GET /admin/api/2020-10/checkouts/{token}.json
PUT /admin/api/2020-10/checkouts/{token}.json
GET /admin/api/2020-10/checkouts/{token}/shipping_rates.json

# Payment
支払い（Payment）API

※日本語にするとまぎらわしいのですが、チェックアウト中にクレジットカード情報を扱う際の支払いAPIです

https://shopify.dev/docs/admin-api/rest/reference/sales-channels/payment

## POST https://elb.deposit.shopifycs.com/sessions
Shopify のセキュアなカード保管庫（card vault）にクレジットカード情報を送信すると、支払いのためのセッションIDを得ることができます。

### リクエスト

```
POST https://elb.deposit.shopifycs.com/sessions
{
  "credit_card": {
    "number": "1",
    "first_name": "John",
    "last_name": "Smith",
    "month": "5",
    "year": "15",
    "verification_value": "123"
  }
}
```

### レスポンス

```
HTTP/1.1 200 OK
{
  "id": "83hru3obno3hu434b3u"
}
```


## POST /admin/api/2020-10/checkouts/{token}/payments.json
返却されたセッションIDを使用して、チェックアウト時の支払いを作成します

### リクエスト

- unique_token：アプリによって生成される一意のトークン
- session_id：card vault が生成したセッションID
- amount：支払い金額
- request_details：リクエストの詳細

```
POST /admin/api/2020-10/checkouts/7yjf4v2we7gamku6a6h7tvm8h3mmvs4x/payments.json
{
  "payment": {
    "request_details": {
      "ip_address": "123.1.1.1",
      "accept_language": "en-US,en;q=0.8,fr;q=0.6",
      "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36"
    },
    "amount": "398.00",
    "session_id": "global-02692fce4bfd2a2f",
    "unique_token": "client-side-idempotency-token"
  }
}
```

### レスポンス

※一部抜粋

```
HTTP/1.1 202 Accepted
Location: https://apple.myshopify.com/admin/api/2020-10/checkouts/7yjf4v2we7gamku6a6h7tvm8h3mmvs4x/payments/1071573807.json
Retry-After: 1
{
  "payment": {
    "id": 1071573807,
    "unique_token": "client-side-idempotency-token",
    "payment_processing_error_message": null,
    "next_action": {
      "redirect_url": null
    },
    "credit_card": {
      "first_name": "Bob",
      "last_name": "Norman",
      "first_digits": "424242",
      "last_digits": "4242",
      "brand": "bogus",
      "expiry_month": 9,
      "expiry_year": 2021,
      "customer_id": 207119551
    },
    "checkout": {
      "completed_at": null,
      "created_at": "2012-10-12T07:05:27-04:00",
      "currency": "USD",
      ....
    }
  }
}
```

## 他 Payment API
GET /admin/api/2020-10/checkouts/{token}/payments.json
GET /admin/api/2020-10/checkouts/{token}/payments/{payment_id}.json
GET /admin/api/2020-10/checkouts/{token}/payments/count.json

以上となります。