准备工作

  • 注册partner账号
    如果要进行shopify的开发需要先注册成为其partner,注册地址为:Shopify.
    在填写完邮箱、姓名、密码后完成注册,进入partner后台

  • 创建测试店铺
    通过Development stores - Create store 来创建新的店铺.
    要输入的信息依次为

    1. Store name (store domain) 全局唯一的店铺域名,这里填写lazygunners-shop后续会用到
    2. Login 店铺后台登录用户名,会继承partner账号的business email
    3. Password 店铺后台密码
    4. 店铺地址: 国家、省、市、区、地址、邮编
    5. 创建店铺的目的: 为客户创建店铺,为测试APP或主题创建店铺,就是随便玩一下

      填写好之后完成店铺创建
  • 在店铺中创建私有APP
    通过Apps - Manage private apps 进入私有应用管理页面

    进入私有应用管理页面之后,可以查看已有的应用和添加新应用。这里我们点击Create a new private app来创建新应用,接下来要填写私有APP的信息,接口权限按需勾选,后续也可调整:

    1. 私有应用名称
    2. 紧急联系开发人员邮箱
    3. Admin API 以及一些列权限
    4. Storefront API 以及一系列权限

      创建成功后,可以获取到Admin API和 Storefront API的认证密钥。其中Admin API用的是password字段中的值,Storefront API用的是Storefront access token中的值
  • 了解GraphQL
    GraphQL相关介绍GraphQL | 一种为你的 API 而生的查询语言

  • Shopify的API文档
    Storefront API Getting Started · Shopify Help Center

  • 下载GraphQL调试工具
    GitHub - graphql/graphiql: An in-browser IDE for exploring GraphQL.

开始动手调试API

Storefront API(店铺前台API)

文档

https://help.shopify.com/en/api/custom-storefronts/storefront-api/getting-started

API认证

打开下载好的GraphiQL,点击右上角的"Edit HTTP Headers"按钮,再新弹出的对话框中点击右上角的"Add Header"按钮。在Header name 输入框中输入X-Shopify-Storefront-Access-Token,在Header value输入框中输入上文提到的私有APP中的Storefront access token,之后保存,点击对话框之外回到主界面

Endpoint

在GraphQL Endpoint输入 https://<shop>.myshopify.com/api/graphql ,其中<shop> 为创建店铺时填写的store name也就是我们例子中的lazygunners-shop。同时保证Method为Post

获取店铺信息,其中包括专场(Collection)和商品(Product)

GraphQL的请求体如下:

{
  shop {
    name
    description
    primaryDomain {
      url
    }
    collections(first:2) {
      pageInfo {
        hasNextPage
      }      
      edges {
        node {
          id
          handle
          description
          descriptionHtml
          title
          image {
            id
          }
          products(first: 5) {
            edges {
              node {
                id
                handle
                collections(first:5) {
                  edges {
                    node {
                      id
                      title
                    }
                  }
                }
                priceRange{
                  minVariantPrice {
                    amount
                    currencyCode
                  }
                  maxVariantPrice {
                    amount
                    currencyCode
                  }
                }
                title
                onlineStoreUrl
                tags
                vendor
                variants(first: 5) {
                  edges {
                    node {
                      id
                      title
                      weight
                      weightUnit
                      price
                      compareAtPrice
                    }
                  }
                }
                options(first:5){
                  id
                  name
                  values          
                }
                images(first: 5) {
                  edges {
                    node {
                      originalSrc
                    }
                  }
                }
              }
            }
          }
        }
        cursor
      }
    } 
  }
}

返回值如下:

{
  "data": {
    "shop": {
      "name": "LazyGunner's Shop",
      "description": "",
      "primaryDomain": {
        "url": "https://shop.folo.xyz"
      },
      "collections": {
        "pageInfo": {
          "hasNextPage": false
        },
        "edges": [
          {
            "node": {
              "id": "Z2lkOi8vc2hvcGlmeS9Db2xsZWN0aW9uLzg0MzQ3MTI1ODM4",
              "handle": "frontpage",
              "description": "",
              "descriptionHtml": "",
              "title": "Home page",
              "image": null,
              "products": {
                "edges": [
                  {
                    "node": {
                      "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzIzODI2NjUwMjM1NjY=",
                      "handle": "pumpkin",
                      "collections": {
                        "edges": [
                          {
                            "node": {
                              "id": "Z2lkOi8vc2hvcGlmeS9Db2xsZWN0aW9uLzg0MzQ3MTI1ODM4",
                              "title": "Home page"
                            }
                          }
                        ]
                      },
                      "priceRange": {
                        "minVariantPrice": {
                          "amount": "1.0",
                          "currencyCode": "CNY"
                        },
                        "maxVariantPrice": {
                          "amount": "111.0",
                          "currencyCode": "CNY"
                        }
                      },
                      "title": "pumpkin",
                      "onlineStoreUrl": "https://shop.folo.xyz/products/pumpkin",
                      "tags": [],
                      "vendor": "LazyGunner's Shop",
                      "variants": {
                        "edges": [
                          {
                            "node": {
                              "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC8yMTIwOTM3MzIxMjc1MA==",
                              "title": "绿 / X",
                              "weight": 1,
                              "weightUnit": "KILOGRAMS",
                              "price": "111.00",
                              "compareAtPrice": "999.00"
                            }
                          },
                          {
                            "node": {
                              "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC8yMTIxNDQyNjE2OTQyMg==",
                              "title": "绿 / L",
                              "weight": 1,
                              "weightUnit": "KILOGRAMS",
                              "price": "1.00",
                              "compareAtPrice": "999.00"
                            }
                          },
                          {
                            "node": {
                              "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC8yMTIxNDQyNjIwMjE5MA==",
                              "title": "红 / X",
                              "weight": 1,
                              "weightUnit": "KILOGRAMS",
                              "price": "111.00",
                              "compareAtPrice": "999.00"
                            }
                          },
                          {
                            "node": {
                              "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC8yMTIxNDQyNjIzNDk1OA==",
                              "title": "红 / L",
                              "weight": 1,
                              "weightUnit": "KILOGRAMS",
                              "price": "111.00",
                              "compareAtPrice": "999.00"
                            }
                          }
                        ]
                      },
                      "options": [
                        {
                          "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0T3B0aW9uLzMyODc4MDkyMjg4Nzg=",
                          "name": "颜色",
                          "values": [
                            "绿",
                            "红"
                          ]
                        },
                        {
                          "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0T3B0aW9uLzMyOTA3MDgxODEwNzA=",
                          "name": "尺寸",
                          "values": [
                            "X",
                            "L"
                          ]
                        }
                      ],
                      "images": {
                        "edges": [
                          {
                            "node": {
                              "originalSrc": "https://cdn.shopify.com/s/files/1/0088/9002/4014/products/11108.png?v=1548303480"
                            }
                          },
                          {
                            "node": {
                              "originalSrc": "https://cdn.shopify.com/s/files/1/0088/9002/4014/products/avatar.jpg?v=1548303482"
                            }
                          }
                        ]
                      }
                    }
                  }
                ]
              }
            },
            "cursor": "eyJsYXN0X2lkIjo4NDM0NzEyNTgzOCwibGFzdF92YWx1ZSI6Ijg0MzQ3MTI1ODM4In0="
          }
        ]
      }
    }
  }
}

其中比较重要的信息是商品信息,其中包含了variantId也就是商品的最小购买单元,可用于下文的待支付订单的创建。

创建待支付订单(Checkout)

GraphQL的请求体如下:

mutation {
  checkoutCreate(input: {
    allowPartialAddresses: true,
    email: "test@gmail.com",
    lineItems: {
      variantId: "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC8yMTIwOTM3MzIxMjc1MA==",
      quantity: 2
    },
    note: "test111",
    shippingAddress: {
      province: "zhejiang",
      city: "hangzhou",
      country: "china",
      address1: "efc",
      zip: "311122",
      firstName: "gunner",
      lastName: "guan",
      phone: "+8613333333333"
    }
  }) {
    userErrors {
      field
      message
    }
    checkout {
      id
    }
    checkoutUserErrors {
      field
      message
    }
  }
}

返回值

{
  "data": {
    "checkoutCreate": {
      "userErrors": [],
      "checkout": {
        "id": "Z2lkOi8vc2hvcGlmeS9DaGVja291dC9jNjAxNTY5YzNmZGM4YzU3MTI4MTY2MjFiODNiNjI2MT9rZXk9YmE1YzliN2U4NzRmZDUzNDZkMWEyNGU2MGNhMGU4MzY="
      },
      "checkoutUserErrors": []
    }
  }
}

我们将得到一个checkout的Id,用于后续操作

更新待支付订单的折扣信息

请求体如下,其中checkoutId是上一个请求创建好返回的,discountCode是店铺后台创建的,也可以通过Admin API来创建,这个我在下文会提到:

mutation {
  checkoutDiscountCodeApplyV2(checkoutId:"Z2lkOi8vc2hvcGlmeS9DaGVja291dC9jNjAxNTY5YzNmZGM4YzU3MTI4MTY2MjFiODNiNjI2MT9rZXk9YmE1YzliN2U4NzRmZDUzNDZkMWEyNGU2MGNhMGU4MzY=", discountCode: "6RHWRC1V13PK") {
    userErrors {
      field
      message
    }
    checkout {
      id
    }
    checkoutUserErrors {
      field
      message
    }
  }
}

更新成功后返回值,如果没有error,说明更新成功:

{
  "data": {
    "checkoutDiscountCodeApplyV2": {
      "userErrors": [],
      "checkout": {
        "id": "Z2lkOi8vc2hvcGlmeS9DaGVja291dC9jNjAxNTY5YzNmZGM4YzU3MTI4MTY2MjFiODNiNjI2MT9rZXk9YmE1YzliN2U4NzRmZDUzNDZkMWEyNGU2MGNhMGU4MzY="
      },
      "checkoutUserErrors": []
    }
  }
}

查看待支付订单

请求体如下:

query {
  node(id:"Z2lkOi8vc2hvcGlmeS9DaGVja291dC9jNjAxNTY5YzNmZGM4YzU3MTI4MTY2MjFiODNiNjI2MT9rZXk9YmE1YzliN2U4NzRmZDUzNDZkMWEyNGU2MGNhMGU4MzY=" ) {
    ... on Checkout {
      id
      webUrl
    }
  }
}

返回值如下:

{
  "data": {
    "node": {
      "id": "Z2lkOi8vc2hvcGlmeS9DaGVja291dC9jNjAxNTY5YzNmZGM4YzU3MTI4MTY2MjFiODNiNjI2MT9rZXk9YmE1YzliN2U4NzRmZDUzNDZkMWEyNGU2MGNhMGU4MzY=",
      "webUrl": "https://lazygunners-shop.myshopify.com/8890024014/checkouts/c601569c3fdc8c5712816621b83b6261?key=ba5c9b7e874fd5346d1a24e60ca0e836"
    }
  }
}

其中比较重要的就是webUrl,通过浏览器打开该地址就可以完成后续的支付操作,当然也可以修改之前的信息。

到这里我们就通过Shopify的Storefront API走完了获取商品-创建待支付订单-更新待支付订单-获取待支付订单信息-去支付这个流程

GraphQL Admin API(店铺后台API)

文档

GraphQL Admin API · Shopify Help Center

API认证

参考Storefront API,不同的是Header name 填 X-Shopify-Access-Token ,Header value填店填私有APP中Admin模块的password

Endpoint

在GraphQL Endpoint输入 https://<shop>.myshopify.com/admin/api/graphql.json ,其中<shop> 为创建店铺时填写的store name也就是我们例子中的lazygunners-shop。同时保证Method为Post

创建价格规则(PriceRule)

数据如下:

mutation {
  priceRuleCreate(
    priceRule: {
      title: "testp",
      value: {
        fixedAmountValue: -20
      },
      target: LINE_ITEM,
      allocationMethod: EACH,
      customerSelection: {
        forAllCustomers:true
      },
      itemEntitlements: {
        targetAllLineItems:true
      },
      validityPeriod: {
        start: "2019-01-28T06:44Z "
      }
    }
  ) {
    userErrors {
      field
      message
    }
    priceRule {
      id
    }
    priceRuleDiscountCode {
      id
    }
    priceRuleUserErrors {
      field
      message
    }
  }
}

返回值:

{
  "data": {
    "priceRuleCreate": {
      "userErrors": [],
      "priceRule": {
        "id": "gid://shopify/PriceRule/357307809870"
      },
      "priceRuleDiscountCode": null,
      "priceRuleUserErrors": []
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 10,
      "actualQueryCost": 10,
      "throttleStatus": {
        "maximumAvailable": 1000,
        "currentlyAvailable": 990,
        "restoreRate": 50
      }
    }
  }
}

创建折扣代码(DiscountCode)

请求体:

mutation {
  priceRuleDiscountCodeCreate(
    priceRuleId: "gid://shopify/PriceRule/357319376974",
    code: "1234"
  ) {
    userErrors {
      field
      message
    }
    priceRule {
      id
    }
    priceRuleDiscountCode {
      id
    }
    priceRuleUserErrors {
      field
      message
    }
  }
}

返回值

{
  "data": {
    "priceRuleDiscountCodeCreate": {
      "userErrors": [],
      "priceRule": {
        "id": "gid://shopify/PriceRule/357319376974"
      },
      "priceRuleDiscountCode": {
        "id": "gid://shopify/PriceRuleDiscountCode/2060923076686"
      },
      "priceRuleUserErrors": []
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 10,
      "actualQueryCost": 10,
      "throttleStatus": {
        "maximumAvailable": 1000,
        "currentlyAvailable": 990,
        "restoreRate": 50
      }
    }
  }
}

这个时候我们可以在店铺后台看到这个折扣代码:

我们可以将这个刚生成的折扣代码"1234",用于前面的checkoutDiscountCodeApplyV2接口,之后再查看更新好的checkout就可以发现这个折扣被使用。

关于shopify基本的GraphQL API调试就先写到这里,后续会再更新一些高级接口。