📦

【Shopify.dev和訳】Apps/Fulfillments/Fulfillment service apps

2021/09/17に公開

この記事について

この記事は、Apps/Fulfillment/Fulfillment service appsの記事を和訳したものです。

記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。

Shopify アプリのご紹介

Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。

https://apps.shopify.com/shopify-application-314?locale=ja&from=daniel

Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。

https://apps.shopify.com/font-picker-1?locale=ja&from=daniel

フルフィルメントサービスアプリとしてフルフィルメントを管理

このガイドでは、フルフィルメントサービスアプリが Shopify でフルフィルメントを管理するために Admin API を使用する方法について説明します。

あなたのアプリが FulfillmentService の場所を管理する場合(ストアオーナーに代わって注文を準備して出荷するサードパーティの倉庫など)、このガイドに従ってください。

お使いのアプリが FulfillmentService ロケーションを管理しておらず、マーチャントまたはサードパーティのロケーションで処理される注文を割り当てている場合は、注文管理アプリとしてフルフィルメントを管理するためのガイドに従うことができます

概要

フルフィルメントサービスとは、店舗オーナーに代わって注文の準備や発送を行う、サードパーティのウェアハウジング、プリントオンデマンド、フルフィルメントサービスのことです。

Shopify では、各フルフィルメントサービスは専用の場所を持っています。フルフィルメントサービスを作成すると、Shopify は自動的にそのための新しいロケーションを作成します。

フルフィルメントサービスは、GraphQL Admin API では FulfillmentService オブジェクトとして表されます。

フルフィルメントサービスは、マーチャントからフルフィルメントサービスに送信された特定のリクエストを表す FulfillmentOrderMerchantRequest をリッスンすることで、何をいつ処理するかを知ることができます。

例えば、マーチャントがフルフィルメントサービスに所定のフルフィルメントオーダーを満たすためのリクエストを提出したとします。マーチャントが提供したメモを含むリクエストデータは、FulfillmentOrderの一部として利用可能なFulfillmentOrderMerchantRequestを通じて API アクセスが可能になります。

FulfillmentService アプリの機能

フルフィルメントサービスとして登録されているアプリは、フルフィルメントオーダーを使って以下のことができます。

  • フルフィルメントリクエストとキャンセルリクエストを、Webhooks に頼らず、登録されたコールバック URL(callback_url/fulfillment_order_notification)で受け取る。これは、Shopify からのリクエストを受け取るための要件です。この仕組みの詳細については、Receiving FULFILLMENT_REQUEST and CANCELLATION_REQUEST notificationsをご覧ください。
  • フルフィルメント要求を明示的に受け入れるか拒否することで、アプリがフルフィルメントを実行する意図があるかどうかをマーチャントに示す。
  • マーチャントから送られてきたフルフィルメントのキャンセル要求を受理または拒否する。
  • フルフィルメントを受理、拒否、または作成する際に、マーチャントとフルフィルメント リクエスト ノートを交換し、コミュニケーションを促進する。
  • 複数のパッケージを表現するために、所定のフルフィルメントオーダーに対して複数のフルフィルメントを作成する。
  • 自分に割り当てられた仕事に対してのみフルフィルメントを実行する
  • アプリがフルフィルメント要求を受け入れた後、いつでもフルフィルメントを作成し、それをフルフィルメントとしてマークする。
  • 一部の作業のみを実行した後、フルフィルメントオーダーを閉じる。

はじめに

フルフィルメントリクエストを受信する前に、まずテストストアにいくつかの未達成の注文がある必要があります。テスト注文を作成する方法については、チュートリアルManage test orders with the REST Admin APIを参照してください。

また、このカテゴリに該当するアプリは、OAuthを使用して以下のパーミッションを要求する必要があります。

  • 自分のロケーションに割り当てられたフルフィルメント注文を管理するためのwrite_assigned_fulfillment_ordersの読み取りおよび書き込み権限

登録

最初のステップは、フルフィルメントリクエストを受け付けるコールバック URL を持つフルフィルメントサービスを Shopify に作成することです。

新しいフルフィルメントサービスを作成する手順は、GraphQLRESTのリファレンスドキュメントに記載されています。

フルフィルメントサービスは、注文ベースのフルフィルメントではなく FulfillmentOrder ベースのフルフィルメントを実行する準備ができていることを Shopify に知らせることで、注文のフルフィルメントを選択する必要があります。これは 1 つのリクエストで行われ、私たちの移行ガイドで詳しく説明されています。

FULFILLMENT_REQUEST および CANCELLATION_REQUEST 通知の受信

アプリは、Shopify がフルフィルメントリクエストの通知を送信するコールバック URL のエンドポイントを設定する必要があります。このエンドポイントは以下の形式で構成する必要があります。<callback_url>/fulfillment_order_notification.

このエンドポイントが受け取るペイロードには、FULFILLMENT_REQUEST または CANCELLATION_REQUEST のいずれかである kind というフィールドが含まれています。マーチャントが Shopify 管理者からフルフィルメントを要求した場合、Shopify はフルフィルメントサービスに種類がFULFILLMENT_REQUESTに設定された通知を送ります。この場合、コールバック URL に送信されるリクエストのボディには、{"kind": "FULFILLMENT_REQUEST"}が含まれています。マーチャントがキャンセルリクエストを送信した場合、ボディには{"kind": "CANCELLATION_REQUEST"}が含まれます。

以下に、各タイプのリクエストに対するペイロードの例を示します。

FULFILLMENT_REQUEST

{
  "kind": "FULFILLMENT_REQUEST"
}

CANCELLATION_REQUEST

{
  "kind": "CANCELLATION_REQUEST"
}

FULFILLMENT_REQUEST の通知を受けての行動

FULFILLMENT_REQUESTのフルフィルメントオーダー通知は、サービスに割り当てられた新しいフルフィルメントオーダーがあり、それが(マーチャントがフルフィルメントを要求したので)行動する準備ができていることを示します。

フルフィルメント・サービスは、shopオブジェクトの下で公開されている assignedFulfillmentOrders コネクションを照会し、オプションとして、FULFILLMENT_REQUESTED に設定された assignmentStatus を渡すことが期待されます。

フルフィルメントサービスは、指定されたフルフィルメントリクエストを受け入れるか拒否するかを決定するために必要なフィールドを指定することができます。

次の例では、クエリはフルフィルメントオーダーの宛先、ラインアイテム、ラインアイテムの SKU を要求し、マーチャントのリクエストには、マーチャントがリクエストを送信した際に提供したメモが含まれています。

GraphQL

POST https://{shop}.myshopify.com/admin/api/2021-07/graphql.json

Request

query {
  shop {
    assignedFulfillmentOrders(first: 10, assignmentStatus: FULFILLMENT_REQUESTED) {
      edges {
        node {
          id
          destination {
            firstName
            lastName
            address1
            city
            province
            zip
            countryCode
            phone
          }
          lineItems(first: 10) {
            edges {
              node {
                id
                lineItem {
                  name
                  sku
                }
                remainingQuantity
              }
            }
          }
          merchantRequests(first: 10, kind: FULFILLMENT_REQUEST) {
            edges {
              node {
                message
              }
            }
          }
        }
      }
    }
  }
}

Response

{
  "data": {
    "shop": {
      "assignedFulfillmentOrders": {
        "edges": [
          {
            "node": {
              "id": "gid://shopify/FulfillmentOrder/5018595819542",
              "destination": {
                "firstName": "Benedict",
                "lastName": "Ankunding",
                "address1": "1318 Bloor St.",
                "city": "Innisfree",
                "province": "Alberta",
                "zip": "T0B2G0",
                "countryCode": "CA",
                "phone": null
              },
              "lineItems": {
                "edges": [
                  {
                    "node": {
                      "id": "gid://shopify/FulfillmentOrderLineItem/10926793228310",
                      "lineItem": {
                        "name": "Billowing Brook Cap",
                        "sku": "BBC-1"
                      },
                      "remainingQuantity": 3
                    }
                  }
                ]
              },
              "merchantRequests": {
                "edges": [
                  {
                    "node": {
                      "message": "Please fulfill ASAP"
                    }
                  }
                ]
              }
            }
          }
        ]
      }
    }
  }
}
REST API

GET https://{shop}.myshopify.com/admin/api/2021-07/assigned_fulfillment_orders.json?assignment_status=fulfillment_requested

Response

{
  "fulfillment_orders": [
    {
      "id": 5018595819542,
      "shop_id": 6587023382,
      "order_id": 4063714836502,
      "assigned_location_id": 61208625174,
      "request_status": "submitted",
      "status": "open",
      "supported_actions": ["cancel_fulfillment_order"],
      "destination": {
        "id": 4793449578518,
        "address1": "1318 Bloor St.",
        "address2": "",
        "city": "Innisfree",
        "company": "",
        "country": "Canada",
        "email": "benedict.ankunding@testemail.com",
        "first_name": "Benedict",
        "last_name": "Ankunding",
        "phone": null,
        "province": "Alberta",
        "zip": "T0B2G0"
      },
      "line_items": [
        {
          "id": 10926793228310,
          "shop_id": 6587023382,
          "fulfillment_order_id": 5018595819542,
          "quantity": 3,
          "line_item_id": 10840452497430,
          "inventory_item_id": 19848968437782,
          "fulfillable_quantity": 3,
          "variant_id": 19523142352918
        }
      ],
      "outgoing_requests": [
        {
          "message": "Please fulfill ASAP",
          "request_options": {
            "notify_customer": false
          },
          "sent_at": "2021-06-24T15:02:03-04:00",
          "kind": "fulfillment_request"
        }
      ],
      "fulfill_at": null,
      "international_duties": null,
      "delivery_method": null,
      "assigned_location": {
        "address1": null,
        "address2": null,
        "city": null,
        "country_code": "CA",
        "location_id": 61208625174,
        "name": "Very Good Fulfillment Company",
        "phone": null,
        "province": null,
        "zip": null
      }
    }
  ]
}

フルフィルメントサービスは、上記で要求された各フルフィルメントオーダーを検討し、それが履行可能かどうかを決定することができる。与えられたフルフィルメントオーダーを受諾するために、フルフィルメントサービスは、fillupmentOrderAcceptFulfillmentRequestミューテーションを使用して、accept要求を送信しなければならない。また、オプションのメッセージを送信することもできる。

GraphQL

POST https://{shop}.myshopify.com/admin/api/2021-07/graphql.json

Request

mutation acceptFulfillmentRequest($id: ID!, $message: String) {
  fulfillmentOrderAcceptFulfillmentRequest(id: $id, message: $message) {
    fulfillmentOrder {
      status
      requestStatus
    }
  }
}

Variables

{
  "id": "gid://shopify/FulfillmentOrder/5014440902678",
  "message": "Reminder that tomorrow is a holiday, we won't be able to ship this until Monday"
}

Response

{
  "data": {
    "fulfillmentOrderAcceptFulfillmentRequest": {
      "fulfillmentOrder": {
        "status": "IN_PROGRESS",
        "requestStatus": "ACCEPTED"
      },
      "userErrors": []
    }
  }
}
REST API

POST https://{shop}.myshopify.com/admin/api/2021-07/fulfillment_orders/{fulfillment_order_id}/fulfillment_request/accept.json

{
  "fulfillment_request": {
    "message": "Reminder that tomorrow is a holiday, we won't be able to ship this until Monday"
  }
}

Response

{
  "fulfillment_order": {
    "id": 5019418001430,
    "shop_id": 6587023382,
    "order_id": 4064536756246,
    "assigned_location_id": 61208625174,
    "request_status": "accepted",
    "status": "in_progress",
    "supported_actions": ["request_cancellation", "create_fulfillment"],
    "destination": {
      "id": 4794270547990,
      "address1": "1318 Bloor St.",
      "address2": "",
      "city": "Innisfree",
      "company": "",
      "country": "Canada",
      "email": "benedict.ankunding@testemail.com",
      "first_name": "Benedict",
      "last_name": "Ankunding",
      "phone": null,
      "province": "Alberta",
      "zip": "T0B2G0"
    },
    "origin": {
      "address1": null,
      "address2": null,
      "city": null,
      "country_code": "CA",
      "location_id": 61208625174,
      "name": "Very Good Fulfillment Company",
      "phone": null,
      "province": null,
      "zip": null
    },
    "line_items": [
      {
        "id": 10927617310742,
        "shop_id": 6587023382,
        "fulfillment_order_id": 5019418001430,
        "quantity": 3,
        "line_item_id": 10841276022806,
        "inventory_item_id": 19848968437782,
        "fulfillable_quantity": 3,
        "variant_id": 19523142352918
      }
    ],
    "outgoing_requests": [
      {
        "message": "",
        "request_options": {
          "notify_customer": false
        },
        "sent_at": "2021-06-24T15:38:21-04:00",
        "kind": "fulfillment_request"
      }
    ],
    "fulfillment_service_handle": "very-good-fulfillment-company",
    "fulfill_at": null,
    "delivery_method": null
  }
}

フルフィルメントサービスがアクセプトリクエストを送信した後、Shopify 管理画面のフルフィルメントオーダーカードには、リクエストがacceptされたことがマーチャントに表示されます。

フルフィルメントサービスが注文を満たすことができないと判断した場合、フルフィルメントOrderRejectFulfillmentRequestミューテーションを使用してフルフィルメントリクエストを拒否する。

GraphQL

POST https://{shop}.myshopify.com/admin/api/2021-07/graphql.json

Request

mutation rejectFulfillmentRequest($id: ID!, $message: String) {
  fulfillmentOrderRejectFulfillmentRequest(id: $id, message: $message) {
    fulfillmentOrder {
      status
      requestStatus
    }
  }
}

Variables

{
  "id": "gid://shopify/FulfillmentOrder/5014440902678",
  "message": "We weren't able to find this product in the warehouse, sorry!"
}

Response

{
  "data": {
    "fulfillmentOrderRejectFulfillmentRequest": {
      "fulfillmentOrder": {
        "status": "OPEN",
        "requestStatus": "REJECTED"
      },
      "userErrors": []
    }
  }
}
REST API

POST https://{shop}.myshopify.com/admin/api/2021-07/fulfillment_orders/{fulfillment_order_id}/fulfillment_request/reject.json

{
  "fulfillment_request": {
    "message": "We weren't able to find this product in the warehouse, sorry!"
  }
}

Response

{
  "fulfillment_order": {
    "id": 5019418263574,
    "shop_id": 6587023382,
    "order_id": 4064537018390,
    "assigned_location_id": 61208625174,
    "request_status": "rejected",
    "status": "open",
    "supported_actions": ["request_fulfillment", "create_fulfillment"],
    "destination": {
      "id": 4794270679062,
      "address1": "1318 Bloor St.",
      "address2": "",
      "city": "Innisfree",
      "company": "",
      "country": "Canada",
      "email": "benedict.ankunding@testemail.com",
      "first_name": "Benedict",
      "last_name": "Ankunding",
      "phone": null,
      "province": "Alberta",
      "zip": "T0B2G0"
    },
    "origin": {
      "address1": null,
      "address2": null,
      "city": null,
      "country_code": "CA",
      "location_id": 61208625174,
      "name": "Very Good Fulfillment Company",
      "phone": null,
      "province": null,
      "zip": null
    },
    "line_items": [
      {
        "id": 10927617769494,
        "shop_id": 6587023382,
        "fulfillment_order_id": 5019418263574,
        "quantity": 3,
        "line_item_id": 10841276481558,
        "inventory_item_id": 19848968437782,
        "fulfillable_quantity": 3,
        "variant_id": 19523142352918
      }
    ],
    "outgoing_requests": [
      {
        "message": "",
        "request_options": {
          "notify_customer": false
        },
        "sent_at": "2021-06-24T15:41:44-04:00",
        "kind": "fulfillment_request"
      },
      {
        "message": "",
        "request_options": {
          "notify_customer": false
        },
        "sent_at": "2021-06-24T15:45:10-04:00",
        "kind": "fulfillment_request"
      }
    ],
    "fulfillment_service_handle": "very-good-fulfillment-company",
    "fulfill_at": null,
    "delivery_method": null
  }
}

この場合、Shopify 管理画面のフルフィルメントオーダーカードには、リクエストが拒否されたことがマーチャントに表示されます。

フルフィルメントの作成

フルフィルメントリクエストを受理した後、フルフィルメントサービスはフルフィルメントの作成を開始することができます。

フルフィルメントサービスがフルフィルメント要求を受諾する前に、フルフィルメントをフルフィルメント注文に対して作成することはできないことに留意されたい。

フルフィルメントサービスは、必要に応じて、出荷される複数のパッケージを表すために、特定のフルフィルメントオーダーに対して複数のフルフィルメントを作成することができる。

アプリがフルフィルメント要求を受け入れると、フルフィルメントオーダーのステータスはIN_PROGRESSに遷移します。

フルフィルメントオーダー上のすべてのラインアイテムが完全に満たされた後、フルフィルメントオーダーステータスはCLOSED状態に移行します。

個々の lineItemsByFulfillmentOrder.fulfillmentOrderLineItems が提供されていない場合、アプリは残りのすべてのラインアイテムに対してフルフィルメントを作成します。

GraphQL

POST https://{shop}.myshopify.com/admin/api/2021-07/graphql.json

Request

mutation fulfillmentCreateV2($fulfillment: FulfillmentV2Input!) {
  fulfillmentCreateV2(fulfillment: $fulfillment) {
    fulfillment {
      id
      status
      trackingInfo {
        company
        number
        url
      }
    }
    userErrors {
      field
      message
    }
  }
}

Varibales

{
  "fulfillment": {
    "notifyCustomer": false,
    "trackingInfo": {
      "company": "my-shipping-company",
      "number": "1562678",
      "url": "https://www.my-shipping-company.com"
    },
    "lineItemsByFulfillmentOrder": [
      {
        "fulfillmentOrderId": "gid://shopify/FulfillmentOrder/5018595819542",
        "fulfillmentOrderLineItems": {
          "id": "gid://shopify/FulfillmentOrderLineItem/10926793228310",
          "quantity": 3
        }
      }
    ]
  }
}

Response

{
  "data": {
    "fulfillmentCreateV2": {
      "fulfillment": {
        "id": "gid://shopify/Fulfillment/3286469410838",
        "status": "SUCCESS",
        "trackingInfo": [
          {
            "company": "my-shipping-company",
            "number": "1562678",
            "url": "https://www.my-shipping-company.com"
          }
        ]
      },
      "userErrors": []
    }
  }
}
REST API

POST https://{shop}.myshopify.com/admin/api/2021-07/fulfillments.json

{
  "fulfillment": {
    "message": "The package was shipped this morning.",
    "notify_customer": false,
    "tracking_info": {
      "number": 1562678,
      "url": "https://www.my-shipping-company.com",
      "company": "my-shipping-company"
    },
    "line_items_by_fulfillment_order": [
      {
        "fulfillment_order_id": 5019418001430,
        "fulfillment_order_line_items": [
          {
            "id": 10927617310742,
            "quantity": 3
          }
        ]
      }
    ]
  }
}

Response

{
  "fulfillment": {
    "id": 3286471016470,
    "order_id": 4064536756246,
    "status": "success",
    "created_at": "2021-06-24T16:24:15-04:00",
    "service": "very-good-fulfillment-company",
    "updated_at": "2021-06-24T16:24:15-04:00",
    "tracking_company": "my-shipping-company",
    "shipment_status": null,
    "location_id": 61208625174,
    "line_items": [
      {
        "id": 10841276022806,
        "variant_id": 19523142352918,
        "title": "Billowing Brook Cap",
        "quantity": 3,
        "sku": "BBC-1",
        "variant_title": "",
        "vendor": "graphql-admin",
        "fulfillment_service": "very-good-fulfillment-company",
        "product_id": 1974227435542,
        "requires_shipping": true,
        "taxable": true,
        "gift_card": false,
        "name": "Billowing Brook Cap",
        "variant_inventory_management": "shopify",
        "properties": [],
        "product_exists": true,
        "fulfillable_quantity": 0,
        "grams": 500,
        "price": "120.00",
        "total_discount": "0.00",
        "fulfillment_status": "fulfilled",
        "price_set": {
          "shop_money": {
            "amount": "120.00",
            "currency_code": "CAD"
          },
          "presentment_money": {
            "amount": "120.00",
            "currency_code": "CAD"
          }
        },
        "total_discount_set": {
          "shop_money": {
            "amount": "0.00",
            "currency_code": "CAD"
          },
          "presentment_money": {
            "amount": "0.00",
            "currency_code": "CAD"
          }
        },
        "discount_allocations": [],
        "duties": [],
        "admin_graphql_api_id": "gid://shopify/LineItem/10841276022806",
        "tax_lines": [],
        "origin_location": {
          "id": 2849710276630,
          "country_code": "CA",
          "province_code": "ON",
          "name": "graphql-admin",
          "address1": "151 O'Connor Street",
          "address2": "1st Floor",
          "city": "Ottawa",
          "zip": "K2P 2L8"
        },
        "destination_location": {
          "id": 2849710309398,
          "country_code": "CA",
          "province_code": "AB",
          "name": "Benedict Ankunding",
          "address1": "1318 Bloor St.",
          "address2": "",
          "city": "Innisfree",
          "zip": "T0B2G0"
        }
      }
    ],
    "tracking_number": "1562678",
    "tracking_numbers": ["1562678"],
    "tracking_url": "https://www.my-shipping-company.com",
    "tracking_urls": ["https://www.my-shipping-company.com"],
    "receipt": {},
    "name": "#1015.1",
    "admin_graphql_api_id": "gid://shopify/Fulfillment/3286471016470"
  }
}

CANCEL_REQUEST 通知の受信

キャンセルのリクエストは、<callback_url>/fulfillment_order_notification の通知エンドポイント URL にも送信できます。リクエストのペイロードには、CANCELLATION_REQUESTという値を持つ種類が含まれています。マーチャントは Shopify の管理画面で、以下のメニューを使ってキャンセルを要求することができます。

これにより、キャンセル要求を送信するためのモーダルが表示され、マーチャントはフルフィルメントサービスにこのキャンセル要求に関する具体的なメモを追加することができます。

モーダルが送信された後、フルフィルメントオーダーカードは、この仕事が現在キャンセル待ちであることを示します。

マーチャントが発行する CANCEL_REQUEST 通知への対応

CANCELLATION_REQUEST タイプのフルフィルメントオーダー通知を受信すると、マーチャントがフルフィルメントオーダーのキャンセルを要求したことを示します。フルフィルメント要求に対処するのと同様に、フルフィルメントサービスは assignedFulfillmentOrdersを照会し、引数assignmentStatusを渡すべきですが、代わりに CANCELLATION_REQUESTED を設定してください。

GraphQL

POST https://{shop}.myshopify.com/admin/api/2021-07/graphql.json

Request

query {
  shop {
    assignedFulfillmentOrders(first: 10, assignmentStatus: CANCELLATION_REQUESTED) {
      edges {
        node {
          id
          destination {
            firstName
            lastName
            address1
            city
            province
            zip
            countryCode
            phone
          }
          lineItems(first: 10) {
            edges {
              node {
                id
                lineItem {
                  name
                  sku
                }
                remainingQuantity
              }
            }
          }
          merchantRequests(first: 10, kind: CANCELLATION_REQUEST) {
            edges {
              node {
                message
              }
            }
          }
        }
      }
    }
  }
}

Response

{
  "data": {
    "shop": {
      "assignedFulfillmentOrders": {
        "edges": [
          {
            "node": {
              "id": "gid://shopify/FulfillmentOrder/5018595819542",
              "destination": {
                "firstName": "Benedict",
                "lastName": "Ankunding",
                "address1": "1318 Bloor St.",
                "city": "Innisfree",
                "province": "Alberta",
                "zip": "T0B2G0",
                "countryCode": "CA",
                "phone": null
              },
              "lineItems": {
                "edges": [
                  {
                    "node": {
                      "id": "gid://shopify/FulfillmentOrderLineItem/10926793228310",
                      "lineItem": {
                        "name": "Billowing Brook Cap",
                        "sku": "BBC-1"
                      },
                      "remainingQuantity": 3
                    }
                  }
                ]
              },
              "merchantRequests": {
                "edges": [
                  {
                    "node": {
                      "message": "Please cancel, the customer changed their mind!"
                    }
                  }
                ]
              }
            }
          }
        ]
      }
    }
  }
}
REST API

GET https://{shop}.myshopify.com/admin/api/2021-07/assigned_fulfillment_orders.json?assignment_status=cancellation_requested

Response

{
  "fulfillment_orders": [
    {
      "id": 5019418263574,
      "shop_id": 6587023382,
      "order_id": 4064537018390,
      "assigned_location_id": 61208625174,
      "request_status": "cancellation_requested",
      "status": "in_progress",
      "supported_actions": ["cancel_fulfillment_order", "create_fulfillment"],
      "destination": {
        "id": 4793449578518,
        "address1": "1318 Bloor St.",
        "address2": "",
        "city": "Innisfree",
        "company": "",
        "country": "Canada",
        "email": "benedict.ankunding@testemail.com",
        "first_name": "Benedict",
        "last_name": "Ankunding",
        "phone": null,
        "province": "Alberta",
        "zip": "T0B2G0"
      },
      "line_items": [
        {
          "id": 10926793228310,
          "shop_id": 6587023382,
          "fulfillment_order_id": 5018595819542,
          "quantity": 3,
          "line_item_id": 10840452497430,
          "inventory_item_id": 19848968437782,
          "fulfillable_quantity": 3,
          "variant_id": 19523142352918
        }
      ],
      "outgoing_requests": [
        {
          "message": "Please fulfill ASAP",
          "request_options": {
            "notify_customer": false
          },
          "sent_at": "2021-06-24T15:02:03-04:00",
          "kind": "fulfillment_request"
        },
        {
          "message": "Please cancel, the customer changed their mind!",
          "request_options": {},
          "sent_at": "2021-06-24T16:36:56-04:00",
          "kind": "cancellation_request"
        }
      ],
      "fulfill_at": null,
      "international_duties": null,
      "delivery_method": null,
      "assigned_location": {
        "address1": null,
        "address2": null,
        "city": null,
        "country_code": "CA",
        "location_id": 61208625174,
        "name": "Very Good Fulfillment Company",
        "phone": null,
        "province": null,
        "zip": null
      }
    }
  ]
}

フルフィルメントサービスは、キャンセル要求を受け入れるか拒否するまで、このリストに返されたフルフィルメントオーダーに対してフルフィルメントを作成することはできません。フルフィルメントサービスは、各フルフィルメントオーダーを確認し、それらがキャンセルできるかどうかを判断することができる。もし可能であれば、フルフィルメントサービスは、オプションのメッセージとともにフルフィルメントオーダーのキャンセルを受け入れるために、fruffmentOrderAcceptCancellationRequestミューテーションを使用してリクエストを提出することができる。これはrequestStatusCANCELLATION_ACCEPTED であるフルフィルメントオーダーの結果です。

GraphQL

POST https://{shop}.myshopify.com/admin/api/2021-07/graphql.json

Request

mutation acceptCancellationRequest($id: ID!, $message: String) {
  fulfillmentOrderAcceptCancellationRequest(id: $id, message: $message) {
    fulfillmentOrder {
      status
      requestStatus
    }
  }
}

Varibales

{
  "id": "gid://shopify/FulfillmentOrder/5019418263574",
  "message": "Item was not picked and packed yet, cancelling as requested"
}

Response

{
  "data": {
    "fulfillmentOrderAcceptCancellationRequest": {
      "fulfillmentOrder": {
        "status": "CANCELLED",
        "requestStatus": "CANCELLATION_ACCEPTED"
      }
    }
  }
}
REST API

POST https://{shop}.myshopify.com/admin/api/2021-07/fulfillment_orders/{fulfillment_order_id}/fulfillment_request/accept.json

{
  "fulfillment_request": {
    "message": "Item was not picked and packed yet, cancelling as requested"
  }
}

Response

{
  "fulfillment_order": {
    "id": 5020241428502,
    "shop_id": 6587023382,
    "order_id": 4064537018390,
    "assigned_location_id": 61208625174,
    "request_status": "cancellation_accepted",
    "status": "cancelled",
    "supported_actions": ["request_fulfillment", "create_fulfillment"],
    "destination": {
      "id": 4795091025942,
      "address1": "1318 Bloor St.",
      "address2": "",
      "city": "Innisfree",
      "company": "",
      "country": "Canada",
      "email": "benedict.ankunding@testemail.com",
      "first_name": "Benedict",
      "last_name": "Ankunding",
      "phone": null,
      "province": "Alberta",
      "zip": "T0B2G0"
    },
    "origin": {
      "address1": null,
      "address2": null,
      "city": null,
      "country_code": "CA",
      "location_id": 61208625174,
      "name": "Very Good Fulfillment Company",
      "phone": null,
      "province": null,
      "zip": null
    },
    "line_items": [
      {
        "id": 10928446242838,
        "shop_id": 6587023382,
        "fulfillment_order_id": 5020241428502,
        "quantity": 3,
        "line_item_id": 10841276481558,
        "inventory_item_id": 19848968437782,
        "fulfillable_quantity": 3,
        "variant_id": 19523142352918
      }
    ],
    "outgoing_requests": [
      {
        "message": "",
        "request_options": {
          "notify_customer": false
        },
        "sent_at": "2021-06-24T16:45:53-04:00",
        "kind": "fulfillment_request"
      },
      {
        "message": "Customer changed their mind!",
        "request_options": {},
        "sent_at": "2021-06-24T16:46:38-04:00",
        "kind": "cancellation_request"
      }
    ],
    "fulfillment_service_handle": "very-good-fulfillment-company",
    "fulfill_at": null,
    "delivery_method": null
  }
}

フルフィルメントサービスがキャンセル依頼を受理した後、Shopify 管理画面のフルフィルメントオーダーカードに、キャンセル依頼が受理されたことがマーチャントに表示されます。

フルフィルメントサービスが、フルフィルメントオーダーのキャンセルを受け入れることができないと判断した場合、fulfillmentOrderRejectCancellationRequestミューテーションを使用してキャンセル要求を拒否する。これは requestStatusCANCELLATION_REJECTED であるフルフィルメントオーダーの結果である。フルフィルメントサービスは、キャンセルを拒否した後もフルフィルメントの作成を続けることができる。

GraphQL

POST https://{shop}.myshopify.com/admin/api/2021-07/graphql.json

Request

mutation rejectCancellationRequest($id: ID!, $message: String) {
  fulfillmentOrderRejectCancellationRequest(id: $id, message: $message) {
    fulfillmentOrder {
      status
      requestStatus
    }
  }
}

Variables

{
  "id": "gid://shopify/FulfillmentOrder/5020276391958",
  "message": "This was already picked up by the courier"
}

Response

{
  "data": {
    "fulfillmentOrderRejectCancellationRequest": {
      "fulfillmentOrder": {
        "status": "IN_PROGRESS",
        "requestStatus": "CANCELLATION_REJECTED"
      }
    }
  }
REST API

POST https://{shop}.myshopify.com/admin/api/2021-07/fulfillment_orders/{fulfillment_order_id}/fulfillment_request/reject.json

{
  "fulfillment_request": {
    "message": "This was already picked up by the courier"
  }
}

Response

{
  "fulfillment_order": {
    "id": 5020795797526,
    "shop_id": 6587023382,
    "order_id": 4064537018390,
    "assigned_location_id": 61208625174,
    "request_status": "cancellation_rejected",
    "status": "in_progress",
    "supported_actions": ["create_fulfillment"],
    "destination": {
      "id": 4795644182550,
      "address1": "1318 Bloor St.",
      "address2": "",
      "city": "Innisfree",
      "company": "",
      "country": "Canada",
      "email": "benedict.ankunding@testemail.com",
      "first_name": "Benedict",
      "last_name": "Ankunding",
      "phone": null,
      "province": "Alberta",
      "zip": "T0B2G0"
    },
    "origin": {
      "address1": null,
      "address2": null,
      "city": null,
      "country_code": "CA",
      "location_id": 61208625174,
      "name": "Very Good Fulfillment Company",
      "phone": null,
      "province": null,
      "zip": null
    },
    "line_items": [
      {
        "id": 10931208618006,
        "shop_id": 6587023382,
        "fulfillment_order_id": 5020795797526,
        "quantity": 3,
        "line_item_id": 10841276481558,
        "inventory_item_id": 19848968437782,
        "fulfillable_quantity": 3,
        "variant_id": 19523142352918
      }
    ],
    "outgoing_requests": [
      {
        "message": "Please fulfill ASAP!",
        "request_options": {
          "notify_customer": false
        },
        "sent_at": "2021-06-24T17:18:23-04:00",
        "kind": "fulfillment_request"
      },
      {
        "message": "Customer changed their mind!",
        "request_options": {},
        "sent_at": "2021-06-24T17:19:10-04:00",
        "kind": "cancellation_request"
      }
    ],
    "fulfillment_service_handle": "very-good-fulfillment-company",
    "fulfill_at": null,
    "delivery_method": null
  }
}

この場合、Shopify 管理画面のフルフィルメントオーダーカードには、マーチャントにキャンセル要求が拒否されたことが表示されます。

フルフィルメントオーダーを強制的にキャンセルするマーチャント

マーチャントは、フルフィルメントサービスがキャンセル要求に応答する前にフルフィルメント注文をキャンセルすることができます。

このオプションは、キャンセルを要求した直後に提供されます。

また、フルフィルメントオーダーを強制的にキャンセルしても、フルフィルメントサービスが商品を出荷しないことを保証するものではないことを示す警告メッセージがマーチャントに表示されます。

フルフィルメントサービスがキャンセル要求を拒否または受け入れることによって応答すると、オプションはもはやマーチャントに提供されません。フルフィルメントサービスは、マーチャントによってキャンセルされたフルフィルメントオーダーに対してフルフィルメントを作成することはできません。

フルフィルメントサービスによるフルフィルメントオーダーの閉鎖

いくつかのケースでは、フルフィルメントサービスは、それがすでにフルフィルメント注文の要求を受け入れた後にのみ、要求された項目を満たすことができないことを実現しています。

フルフィルメントサービスは、フルフィルメントオーダーをクローズするコールを行い、フルフィルメントを行わないことをマーチャントに示すことができます。これは、statusINCOMPLETEで、requestStatusCLOSEDであるフルフィルメントオーダーの結果です。

GraphQL

POST https://{shop}.myshopify.com/admin/api/2021-07/graphql.json

Request

mutation closeFulfillmentOrder($id: ID!, $message: String) {
  fulfillmentOrderClose(id: $id, message: $message) {
    fulfillmentOrder {
      status
      requestStatus
    }
  }
}

Variables

{
  "id": "gid://shopify/FulfillmentOrder/5020795797526",
  "message": "Apologies but it appears we are out of stock."
}

Response

{
  "data": {
    "fulfillmentOrderClose": {
      "fulfillmentOrder": {
        "status": "INCOMPLETE",
        "requestStatus": "CLOSED"
      }
    }
  }
}
REST API

POST https://{shop}.myshopify.com/admin/api/2021-04/fulfillment_orders//close.json

{
  "message": "Unfortunately we are out of stock"
}

Response

{
  "fulfillment_order": {
    "id": 5021063905302,
    "shop_id": 6587023382,
    "order_id": 4064537018390,
    "assigned_location_id": 61208625174,
    "request_status": "closed",
    "status": "incomplete",
    "supported_actions": ["request_fulfillment", "create_fulfillment"],
    "destination": {
      "id": 4795912224790,
      "address1": "1318 Bloor St.",
      "address2": "",
      "city": "Innisfree",
      "company": "",
      "country": "Canada",
      "email": "benedict.ankunding@testemail.com",
      "first_name": "Benedict",
      "last_name": "Ankunding",
      "phone": null,
      "province": "Alberta",
      "zip": "T0B2G0"
    },
    "line_items": [
      {
        "id": 10932546633750,
        "shop_id": 6587023382,
        "fulfillment_order_id": 5021063905302,
        "quantity": 3,
        "line_item_id": 10841276481558,
        "inventory_item_id": 19848968437782,
        "fulfillable_quantity": 3,
        "variant_id": 19523142352918
      }
    ],
    "fulfillment_service_handle": "very-good-fulfillment-company",
    "fulfill_at": null,
    "delivery_method": null,
    "assigned_location": {
      "address1": null,
      "address2": null,
      "city": null,
      "country_code": "CA",
      "location_id": 61208625174,
      "name": "Very Good Fulfillment Company",
      "phone": null,
      "province": null,
      "zip": null
    },
    "merchant_requests": [
      {
        "message": "Please fulfill ASAP!",
        "request_options": {
          "notify_customer": false
        },
        "sent_at": "2021-06-24T17:27:24-04:00",
        "kind": "fulfillment_request"
      }
    ]
  }
}

フルフィルメントサービスがフルフィルメントをキャンセルすると、Shopify 管理画面のフルフィルメントオーダーカードは、フルフィルメントリクエストがキャンセルされたことをマーチャントに通知します。

フルフィルメントのキャンセル

フルフィルメントは fulfillmentCancel ミューテーションを使用して API を通してキャンセルすることができます。ただし、フルフィルメントが作成されたすべてのフルフィルメント注文が影響を受けます。

  • 基礎となるフルフィルメント注文が完全に満たされていた場合、その注文は自動的にCLOSEDされます。
  • 関連するフルフィルメントがキャンセルされると、キャンセルされたフルフィルメントのラインアイテムで構成される新しいフルフィルメントオーダーが作成されます。この新規受注は、元の受注と同じ場所に在庫がある場合は、そこに割り当てられます。
  • キャンセルされたフルフィルメントのすべてのアイテムが同じ場所から調達できない場合、新しいフルフィルメントオーダーは、ショップのフルフィルメントの優先順位設定を考慮して、アイテムがストックされている場所に割り当てられます。これにより、異なるロケーションに対して複数の新規フルフィルメントオーダーが発生する場合があります。
  • フルフィルメントオーダーが部分的に履行されていた場合、fulfillmentOrderLineItem remainingQuantity は、キャンセルされたフルフィルメントのラインアイテムに基づいて調整されます。

GraphQL

POST https://{shop}.myshopify.com/admin/api/2021-07/graphql.json

Request

mutation cancelFulfillment($id: ID!) {
  fulfillmentCancel(id: $id) {
    fulfillment {
      id
      status
      fulfillmentOrders(first: 10) {
        edges {
          node {
            id
            status
          }
        }
      }
    }
  }
}

Variables

{
  "id": "gid://shopify/Fulfillment/3286482681878"
}

Response

{
  "data": {
    "fulfillmentCancel": {
      "fulfillment": {
        "id": "gid://shopify/Fulfillment/3286482681878",
        "status": "CANCELLED",
        "fulfillmentOrders": {
          "edges": [
            {
              "node": {
                "id": "gid://shopify/FulfillmentOrder/5021075374102",
                "status": "CLOSED"
              }
            }
          ]
        }
      }
    }
  }
}
REST API

POST https://{shop}.myshopify.com/admin/api/2021-04/fulfillments/{ fulfillment_id }/cancel.json

{}

Response

{
  "fulfillment": {
    "order_id": 4064537018390,
    "status": "cancelled",
    "location_id": 61208625174,
    "id": 3286482747414,
    "created_at": "2021-06-24T21:20:17-04:00",
    "service": "very-good-fulfillment-company",
    "updated_at": "2021-06-24T21:25:15-04:00",
    "tracking_company": "my-shipping-company",
    "shipment_status": null,
    "line_items": [
      {
        "id": 10841276481558,
        "variant_id": 19523142352918,
        "title": "Billowing Brook Cap",
        "quantity": 3,
        "sku": "BBC-1",
        "variant_title": "",
        "vendor": "graphql-admin",
        "fulfillment_service": "very-good-fulfillment-company",
        "product_id": 1974227435542,
        "requires_shipping": true,
        "taxable": true,
        "gift_card": false,
        "name": "Billowing Brook Cap",
        "variant_inventory_management": "shopify",
        "properties": [],
        "product_exists": true,
        "fulfillable_quantity": 0,
        "grams": 500,
        "price": "120.00",
        "total_discount": "0.00",
        "fulfillment_status": "fulfilled",
        "price_set": {
          "shop_money": {
            "amount": "120.00",
            "currency_code": "CAD"
          },
          "presentment_money": {
            "amount": "120.00",
            "currency_code": "CAD"
          }
        },
        "total_discount_set": {
          "shop_money": {
            "amount": "0.00",
            "currency_code": "CAD"
          },
          "presentment_money": {
            "amount": "0.00",
            "currency_code": "CAD"
          }
        },
        "discount_allocations": [],
        "duties": [],
        "admin_graphql_api_id": "gid://shopify/LineItem/10841276481558",
        "tax_lines": [],
        "origin_location": {
          "id": 2849710276630,
          "country_code": "CA",
          "province_code": "ON",
          "name": "graphql-admin",
          "address1": "151 O'Connor Street",
          "address2": "1st Floor",
          "city": "Ottawa",
          "zip": "K2P 2L8"
        },
        "destination_location": {
          "id": 2849710309398,
          "country_code": "CA",
          "province_code": "AB",
          "name": "Benedict Ankunding",
          "address1": "1318 Bloor St.",
          "address2": "",
          "city": "Innisfree",
          "zip": "T0B2G0"
        }
      }
    ],
    "tracking_number": "1562678",
    "tracking_numbers": ["1562678"],
    "tracking_url": "https://www.my-shipping-company.com",
    "tracking_urls": ["https://www.my-shipping-company.com"],
    "receipt": {},
    "name": "#1016.3",
    "admin_graphql_api_id": "gid://shopify/Fulfillment/3286482747414"
  }
}

在庫の管理

API による在庫管理の詳細については、在庫の更新のガイドをご覧ください。

API リファレンス

Shopify アプリのご紹介

Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。

https://apps.shopify.com/shopify-application-314?locale=ja&from=daniel

Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。

https://apps.shopify.com/font-picker-1?locale=ja&from=daniel

Discussion

ログインするとコメントできます