shopify-api

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Shopify API Integration

Shopify API集成指南

Expert guidance for all Shopify APIs including GraphQL Admin API, REST Admin API, Storefront API, Ajax API, authentication, and webhooks.
针对所有Shopify API的专业指导,包括GraphQL Admin API、REST Admin API、Storefront API、Ajax API、认证和Webhook。

When to Use This Skill

适用场景

Invoke this skill when:
  • Making GraphQL or REST API calls to Shopify
  • Implementing OAuth 2.0 authentication for apps
  • Fetching product, collection, order, or customer data programmatically
  • Using Storefront API for headless commerce
  • Implementing Ajax cart operations in themes
  • Setting up webhooks for event handling
  • Working with API version 2025-10
  • Handling rate limiting and API errors
  • Building custom integrations with Shopify
  • Using Shopify Admin API from Node.js, Python, or other languages
在以下场景中使用本技能:
  • 向Shopify发起GraphQL或REST API调用
  • 为应用实现OAuth 2.0认证
  • 程序化获取商品、商品集合、订单或客户数据
  • 使用Storefront API实现无头电商
  • 在主题中实现Ajax购物车操作
  • 设置Webhook进行事件处理
  • 使用API版本2025-10
  • 处理速率限制和API错误
  • 构建与Shopify的自定义集成
  • 从Node.js、Python或其他语言调用Shopify Admin API

Core Capabilities

核心功能

1. GraphQL Admin API

1. GraphQL Admin API

Modern API for Shopify Admin operations with efficient data fetching.
Endpoint:
POST https://{store}.myshopify.com/admin/api/2025-10/graphql.json
Headers:
javascript
{
  'X-Shopify-Access-Token': 'shpat_...',
  'Content-Type': 'application/json'
}
Basic Query:
graphql
query GetProducts($first: Int!) {
  products(first: $first) {
    edges {
      node {
        id
        title
        handle
        status
        vendor
        productType

        # Pricing
        priceRange {
          minVariantPrice { amount currencyCode }
          maxVariantPrice { amount currencyCode }
        }

        # Images
        images(first: 5) {
          edges {
            node {
              id
              url
              altText
            }
          }
        }

        # Variants
        variants(first: 10) {
          edges {
            node {
              id
              title
              sku
              price
              inventoryQuantity
              available: availableForSale
            }
          }
        }
      }
    }

    pageInfo {
      hasNextPage
      hasPreviousPage
      startCursor
      endCursor
    }
  }
}
Variables:
json
{
  "first": 10
}
JavaScript Example:
javascript
async function getProducts(accessToken, store, limit = 10) {
  const query = `
    query GetProducts($first: Int!) {
      products(first: $first) {
        edges {
          node {
            id
            title
            handle
            priceRange {
              minVariantPrice { amount currencyCode }
            }
          }
        }
        pageInfo {
          hasNextPage
          endCursor
        }
      }
    }
  `;

  const response = await fetch(
    `https://${store}.myshopify.com/admin/api/2025-10/graphql.json`,
    {
      method: 'POST',
      headers: {
        'X-Shopify-Access-Token': accessToken,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        query,
        variables: { first: limit },
      }),
    }
  );

  const { data, errors } = await response.json();

  if (errors) {
    console.error('GraphQL Errors:', errors);
    throw new Error(errors[0].message);
  }

  return data.products;
}
Common Mutations:
Create product:
graphql
mutation CreateProduct($input: ProductInput!) {
  productCreate(input: $input) {
    product {
      id
      title
      handle
    }
    userErrors {
      field
      message
    }
  }
}
Update product:
graphql
mutation UpdateProduct($input: ProductInput!) {
  productUpdate(input: $input) {
    product {
      id
      title
      status
    }
    userErrors {
      field
      message
    }
  }
}
Set metafield:
graphql
mutation SetMetafield($input: MetafieldInput!) {
  metafieldSet(input: $input) {
    metafield {
      id
      namespace
      key
      value
      type
    }
    userErrors {
      field
      message
    }
  }
}
用于Shopify后台操作的现代化API,支持高效数据获取。
端点:
POST https://{store}.myshopify.com/admin/api/2025-10/graphql.json
请求头:
javascript
{
  'X-Shopify-Access-Token': 'shpat_...',
  'Content-Type': 'application/json'
}
基础查询:
graphql
query GetProducts($first: Int!) {
  products(first: $first) {
    edges {
      node {
        id
        title
        handle
        status
        vendor
        productType

        # Pricing
        priceRange {
          minVariantPrice { amount currencyCode }
          maxVariantPrice { amount currencyCode }
        }

        # Images
        images(first: 5) {
          edges {
            node {
              id
              url
              altText
            }
          }
        }

        # Variants
        variants(first: 10) {
          edges {
            node {
              id
              title
              sku
              price
              inventoryQuantity
              available: availableForSale
            }
          }
        }
      }
    }

    pageInfo {
      hasNextPage
      hasPreviousPage
      startCursor
      endCursor
    }
  }
}
变量:
json
{
  "first": 10
}
JavaScript示例:
javascript
async function getProducts(accessToken, store, limit = 10) {
  const query = `
    query GetProducts($first: Int!) {
      products(first: $first) {
        edges {
          node {
            id
            title
            handle
            priceRange {
              minVariantPrice { amount currencyCode }
            }
          }
        }
        pageInfo {
          hasNextPage
          endCursor
        }
      }
    }
  `;

  const response = await fetch(
    `https://${store}.myshopify.com/admin/api/2025-10/graphql.json`,
    {
      method: 'POST',
      headers: {
        'X-Shopify-Access-Token': accessToken,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        query,
        variables: { first: limit },
      }),
    }
  );

  const { data, errors } = await response.json();

  if (errors) {
    console.error('GraphQL Errors:', errors);
    throw new Error(errors[0].message);
  }

  return data.products;
}
常见变更操作:
创建商品:
graphql
mutation CreateProduct($input: ProductInput!) {
  productCreate(input: $input) {
    product {
      id
      title
      handle
    }
    userErrors {
      field
      message
    }
  }
}
更新商品:
graphql
mutation UpdateProduct($input: ProductInput!) {
  productUpdate(input: $input) {
    product {
      id
      title
      status
    }
    userErrors {
      field
      message
    }
  }
}
设置元字段:
graphql
mutation SetMetafield($input: MetafieldInput!) {
  metafieldSet(input: $input) {
    metafield {
      id
      namespace
      key
      value
      type
    }
    userErrors {
      field
      message
    }
  }
}

2. REST Admin API

2. REST Admin API

Traditional REST API for Shopify Admin operations.
Base URL:
https://{store}.myshopify.com/admin/api/2025-10/
Authentication:
javascript
headers: {
  'X-Shopify-Access-Token': 'shpat_...'
}
Common Endpoints:
Get products:
javascript
GET /admin/api/2025-10/products.json?limit=50&status=active

// JavaScript
const response = await fetch(
  `https://${store}.myshopify.com/admin/api/2025-10/products.json?limit=50`,
  {
    headers: {
      'X-Shopify-Access-Token': accessToken,
    },
  }
);

const { products } = await response.json();
Get single product:
javascript
GET /admin/api/2025-10/products/{product_id}.json
Create product:
javascript
POST /admin/api/2025-10/products.json

// Body
{
  "product": {
    "title": "New Product",
    "body_html": "<p>Description</p>",
    "vendor": "My Vendor",
    "product_type": "Shoes",
    "status": "draft"
  }
}
Update product:
javascript
PUT /admin/api/2025-10/products/{product_id}.json

// Body
{
  "product": {
    "id": 123456789,
    "title": "Updated Title"
  }
}
Get orders:
javascript
GET /admin/api/2025-10/orders.json?status=any&limit=50
Get customers:
javascript
GET /admin/api/2025-10/customers.json?limit=50
用于Shopify后台操作的传统REST API。
基础URL:
https://{store}.myshopify.com/admin/api/2025-10/
认证:
javascript
headers: {
  'X-Shopify-Access-Token': 'shpat_...'
}
常见端点:
获取商品:
javascript
GET /admin/api/2025-10/products.json?limit=50&status=active

// JavaScript
const response = await fetch(
  `https://${store}.myshopify.com/admin/api/2025-10/products.json?limit=50`,
  {
    headers: {
      'X-Shopify-Access-Token': accessToken,
    },
  }
);

const { products } = await response.json();
获取单个商品:
javascript
GET /admin/api/2025-10/products/{product_id}.json
创建商品:
javascript
POST /admin/api/2025-10/products.json

// 请求体
{
  "product": {
    "title": "New Product",
    "body_html": "<p>Description</p>",
    "vendor": "My Vendor",
    "product_type": "Shoes",
    "status": "draft"
  }
}
更新商品:
javascript
PUT /admin/api/2025-10/products/{product_id}.json

// 请求体
{
  "product": {
    "id": 123456789,
    "title": "Updated Title"
  }
}
获取订单:
javascript
GET /admin/api/2025-10/orders.json?status=any&limit=50
获取客户:
javascript
GET /admin/api/2025-10/customers.json?limit=50

3. OAuth 2.0 Authentication

3. OAuth 2.0认证

Complete OAuth flow for custom apps.
Step 1: Authorization Request
GET https://{shop}.myshopify.com/admin/oauth/authorize?
  client_id={api_key}&
  redirect_uri={redirect_uri}&
  scope={scopes}&
  state={random_state}
Scopes:
javascript
const scopes = [
  'read_products',
  'write_products',
  'read_orders',
  'write_orders',
  'read_customers',
  'write_customers',
  'read_inventory',
  'write_inventory',
  'read_metafields',
  'write_metafields',
].join(',');
Step 2: Handle Callback
javascript
// User approves, Shopify redirects to:
GET {redirect_uri}?code={auth_code}&state={state}&hmac={hmac}&shop={shop}

// Verify HMAC for security
function verifyHmac(query, secret) {
  const { hmac, ...params } = query;

  const message = Object.keys(params)
    .sort()
    .map(key => `${key}=${params[key]}`)
    .join('&');

  const hash = crypto
    .createHmac('sha256', secret)
    .update(message)
    .digest('hex');

  return hash === hmac;
}
Step 3: Exchange Code for Token
javascript
POST https://{shop}.myshopify.com/admin/oauth/access_token

// Body
{
  "client_id": "{api_key}",
  "client_secret": "{api_secret}",
  "code": "{auth_code}"
}

// Response
{
  "access_token": "shpat_...",
  "scope": "write_products,read_orders"
}

// Node.js example
async function getAccessToken(shop, code, apiKey, apiSecret) {
  const response = await fetch(
    `https://${shop}/admin/oauth/access_token`,
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        client_id: apiKey,
        client_secret: apiSecret,
        code,
      }),
    }
  );

  const { access_token, scope } = await response.json();
  return { access_token, scope };
}
自定义应用的完整OAuth流程。
步骤1:授权请求
GET https://{shop}.myshopify.com/admin/oauth/authorize?
  client_id={api_key}&
  redirect_uri={redirect_uri}&
  scope={scopes}&
  state={random_state}
权限范围:
javascript
const scopes = [
  'read_products',
  'write_products',
  'read_orders',
  'write_orders',
  'read_customers',
  'write_customers',
  'read_inventory',
  'write_inventory',
  'read_metafields',
  'write_metafields',
].join(',');
步骤2:处理回调
javascript
// 用户授权后,Shopify重定向至:
GET {redirect_uri}?code={auth_code}&state={state}&hmac={hmac}&shop={shop}

// 验证HMAC确保安全
function verifyHmac(query, secret) {
  const { hmac, ...params } = query;

  const message = Object.keys(params)
    .sort()
    .map(key => `${key}=${params[key]}`)
    .join('&');

  const hash = crypto
    .createHmac('sha256', secret)
    .update(message)
    .digest('hex');

  return hash === hmac;
}
步骤3:交换授权码获取访问令牌
javascript
POST https://{shop}.myshopify.com/admin/oauth/access_token

// 请求体
{
  "client_id": "{api_key}",
  "client_secret": "{api_secret}",
  "code": "{auth_code}"
}

// 响应
{
  "access_token": "shpat_...",
  "scope": "write_products,read_orders"
}

// Node.js示例
async function getAccessToken(shop, code, apiKey, apiSecret) {
  const response = await fetch(
    `https://${shop}/admin/oauth/access_token`,
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        client_id: apiKey,
        client_secret: apiSecret,
        code,
      }),
    }
  );

  const { access_token, scope } = await response.json();
  return { access_token, scope };
}

4. Rate Limiting

4. 速率限制

GraphQL uses points-based rate limiting.
Rate Limits:
  • 50 cost points per second maximum
  • Bucket refills at 50 points/second
  • Each query has a calculated cost
Check Rate Limit:
javascript
const response = await fetch(graphqlEndpoint, options);

const rateLimitHeader = response.headers.get('X-Shopify-GraphQL-Admin-Api-Call-Limit');
// Example: "42/50" (42 points used, 50 max)

const [used, limit] = rateLimitHeader.split('/').map(Number);

if (used > 40) {
  // Approaching limit, slow down
  await delay(1000);
}
Implement Retry Logic:
javascript
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url, options);

    if (response.status === 429) {
      // Rate limited
      const retryAfter = response.headers.get('Retry-After') || 2;
      await delay(retryAfter * 1000 * Math.pow(2, i)); // Exponential backoff
      continue;
    }

    return response;
  }

  throw new Error('Max retries exceeded');
}

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
GraphQL采用基于点数的速率限制机制。
速率限制规则:
  • 每秒最多50个点数
  • 点数桶每秒补充50个点数
  • 每个查询有对应的计算成本
检查速率限制:
javascript
const response = await fetch(graphqlEndpoint, options);

const rateLimitHeader = response.headers.get('X-Shopify-GraphQL-Admin-Api-Call-Limit');
// 示例:"42/50"(已使用42个点数,上限50)

const [used, limit] = rateLimitHeader.split('/').map(Number);

if (used > 40) {
  // 接近限制,放缓请求
  await delay(1000);
}
实现重试逻辑:
javascript
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url, options);

    if (response.status === 429) {
      // 触发速率限制
      const retryAfter = response.headers.get('Retry-After') || 2;
      await delay(retryAfter * 1000 * Math.pow(2, i)); // 指数退避
      continue;
    }

    return response;
  }

  throw new Error('Max retries exceeded');
}

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

5. Storefront API

5. Storefront API

Public API for headless/custom storefronts.
Endpoint:
POST https://{store}.myshopify.com/api/2025-10/graphql.json
Headers (Public Access):
javascript
{
  'Content-Type': 'application/json',
  'X-Shopify-Storefront-Access-Token': '{public_token}' // Optional for public stores
}
Query Products:
graphql
query GetProducts($first: Int!) {
  products(first: $first) {
    edges {
      node {
        id
        title
        handle
        description
        priceRange {
          minVariantPrice { amount currencyCode }
          maxVariantPrice { amount currencyCode }
        }
        images(first: 3) {
          edges {
            node {
              url
              altText
            }
          }
        }
        variants(first: 10) {
          edges {
            node {
              id
              title
              price { amount currencyCode }
              availableForSale
              sku
            }
          }
        }
      }
    }
  }
}
Cart Operations:
Create cart:
graphql
mutation CreateCart($input: CartInput!) {
  cartCreate(input: $input) {
    cart {
      id
      checkoutUrl
      lines(first: 10) {
        edges {
          node {
            id
            quantity
            merchandise {
              ... on ProductVariant {
                id
                title
                price { amount }
              }
            }
          }
        }
      }
      cost {
        totalAmount { amount currencyCode }
        subtotalAmount { amount }
        totalTaxAmount { amount }
      }
    }
  }
}
Add to cart:
graphql
mutation AddToCart($cartId: ID!, $lines: [CartLineInput!]!) {
  cartLinesAdd(cartId: $cartId, lines: $lines) {
    cart {
      id
      lines(first: 10) {
        edges {
          node {
            id
            quantity
          }
        }
      }
    }
  }
}
用于无头/自定义店铺前端的公开API。
端点:
POST https://{store}.myshopify.com/api/2025-10/graphql.json
请求头(公开访问):
javascript
{
  'Content-Type': 'application/json',
  'X-Shopify-Storefront-Access-Token': '{public_token}' // 公开店铺可选
}
查询商品:
graphql
query GetProducts($first: Int!) {
  products(first: $first) {
    edges {
      node {
        id
        title
        handle
        description
        priceRange {
          minVariantPrice { amount currencyCode }
          maxVariantPrice { amount currencyCode }
        }
        images(first: 3) {
          edges {
            node {
              url
              altText
            }
          }
        }
        variants(first: 10) {
          edges {
            node {
              id
              title
              price { amount currencyCode }
              availableForSale
              sku
            }
          }
        }
      }
    }
  }
}
购物车操作:
创建购物车:
graphql
mutation CreateCart($input: CartInput!) {
  cartCreate(input: $input) {
    cart {
      id
      checkoutUrl
      lines(first: 10) {
        edges {
          node {
            id
            quantity
            merchandise {
              ... on ProductVariant {
                id
                title
                price { amount }
              }
            }
          }
        }
      }
      cost {
        totalAmount { amount currencyCode }
        subtotalAmount { amount }
        totalTaxAmount { amount }
      }
    }
  }
}
添加商品到购物车:
graphql
mutation AddToCart($cartId: ID!, $lines: [CartLineInput!]!) {
  cartLinesAdd(cartId: $cartId, lines: $lines) {
    cart {
      id
      lines(first: 10) {
        edges {
          node {
            id
            quantity
          }
        }
      }
    }
  }
}

6. Ajax API (Theme-Only)

6. Ajax API(仅主题可用)

JavaScript API for cart operations in themes.
Get Cart:
javascript
fetch('/cart.js')
  .then(response => response.json())
  .then(cart => {
    console.log('Cart:', cart);
    console.log('Item count:', cart.item_count);
    console.log('Total:', cart.total_price);
    console.log('Items:', cart.items);
  });
Add to Cart:
javascript
fetch('/cart/add.js', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    id: variantId,              // Required: variant ID
    quantity: 1,                 // Optional: default 1
    properties: {                // Optional: custom data
      'Gift wrap': 'Yes',
      'Note': 'Happy Birthday!'
    }
  })
})
  .then(response => response.json())
  .then(item => {
    console.log('Added to cart:', item);
  })
  .catch(error => {
    console.error('Error:', error);
  });
Update Cart:
javascript
fetch('/cart/change.js', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    line: 1,          // Line item index (1-based)
    quantity: 2       // New quantity (0 = remove)
  })
})
  .then(response => response.json())
  .then(cart => console.log('Updated cart:', cart));
Clear Cart:
javascript
fetch('/cart/clear.js', { method: 'POST' })
  .then(response => response.json())
  .then(cart => console.log('Cart cleared'));
Update Cart Attributes:
javascript
fetch('/cart/update.js', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    attributes: {
      'gift_wrap': 'true',
      'gift_message': 'Happy Birthday!'
    },
    note: 'Please handle with care'
  })
})
  .then(response => response.json())
  .then(cart => console.log('Cart updated'));
用于主题中购物车操作的JavaScript API。
获取购物车信息:
javascript
fetch('/cart.js')
  .then(response => response.json())
  .then(cart => {
    console.log('Cart:', cart);
    console.log('Item count:', cart.item_count);
    console.log('Total:', cart.total_price);
    console.log('Items:', cart.items);
  });
添加商品到购物车:
javascript
fetch('/cart/add.js', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    id: variantId,              // 必填:商品变体ID
    quantity: 1,                 // 可选:默认1
    properties: {                // 可选:自定义数据
      'Gift wrap': 'Yes',
      'Note': 'Happy Birthday!'
    }
  })
})
  .then(response => response.json())
  .then(item => {
    console.log('Added to cart:', item);
  })
  .catch(error => {
    console.error('Error:', error);
  });
更新购物车:
javascript
fetch('/cart/change.js', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    line: 1,          // 商品行索引(从1开始)
    quantity: 2       // 新数量(0表示移除)
  })
})
  .then(response => response.json())
  .then(cart => console.log('Updated cart:', cart));
清空购物车:
javascript
fetch('/cart/clear.js', { method: 'POST' })
  .then(response => response.json())
  .then(cart => console.log('Cart cleared'));
更新购物车属性:
javascript
fetch('/cart/update.js', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    attributes: {
      'gift_wrap': 'true',
      'gift_message': 'Happy Birthday!'
    },
    note: 'Please handle with care'
  })
})
  .then(response => response.json())
  .then(cart => console.log('Cart updated'));

7. Webhooks

7. Webhook

Event-driven notifications for app integrations.
Common Webhooks:
javascript
// Product events
'products/create'
'products/update'
'products/delete'

// Order events
'orders/create'
'orders/updated'
'orders/paid'
'orders/fulfilled'
'orders/cancelled'

// Customer events
'customers/create'
'customers/update'
'customers/delete'

// Cart events
'carts/create'
'carts/update'

// Inventory events
'inventory_levels/update'

// App events
'app/uninstalled'
Register Webhook (GraphQL):
graphql
mutation CreateWebhook($input: WebhookSubscriptionInput!) {
  webhookSubscriptionCreate(input: $input) {
    webhookSubscription {
      id
      topic
      endpoint {
        __typename
        ... on WebhookHttpEndpoint {
          callbackUrl
        }
      }
    }
    userErrors {
      field
      message
    }
  }
}
Variables:
json
{
  "input": {
    "topic": "ORDERS_CREATE",
    "webhookSubscription": {
      "callbackUrl": "https://your-app.com/webhooks/orders",
      "format": "JSON"
    }
  }
}
Handle Webhook (Node.js/Express):
javascript
app.post('/webhooks/orders', async (req, res) => {
  // Verify webhook HMAC
  const hmac = req.headers['x-shopify-hmac-sha256'];
  const body = JSON.stringify(req.body);

  const hash = crypto
    .createHmac('sha256', SHOPIFY_WEBHOOK_SECRET)
    .update(body)
    .digest('base64');

  if (hash !== hmac) {
    return res.status(401).send('Invalid HMAC');
  }

  // Process order
  const order = req.body;
  console.log('New order:', order.id, order.email);

  // Respond quickly (within 5 seconds)
  res.status(200).send('OK');

  // Process in background
  await processOrder(order);
});
用于应用集成的事件驱动通知。
常见Webhook主题:
javascript
// 商品事件
'products/create'
'products/update'
'products/delete'

// 订单事件
'orders/create'
'orders/updated'
'orders/paid'
'orders/fulfilled'
'orders/cancelled'

// 客户事件
'customers/create'
'customers/update'
'customers/delete'

// 购物车事件
'carts/create'
'carts/update'

// 库存事件
'inventory_levels/update'

// 应用事件
'app/uninstalled'
注册Webhook(GraphQL):
graphql
mutation CreateWebhook($input: WebhookSubscriptionInput!) {
  webhookSubscriptionCreate(input: $input) {
    webhookSubscription {
      id
      topic
      endpoint {
        __typename
        ... on WebhookHttpEndpoint {
          callbackUrl
        }
      }
    }
    userErrors {
      field
      message
    }
  }
}
变量:
json
{
  "input": {
    "topic": "ORDERS_CREATE",
    "webhookSubscription": {
      "callbackUrl": "https://your-app.com/webhooks/orders",
      "format": "JSON"
    }
  }
}
处理Webhook(Node.js/Express):
javascript
app.post('/webhooks/orders', async (req, res) => {
  // 验证Webhook HMAC
  const hmac = req.headers['x-shopify-hmac-sha256'];
  const body = JSON.stringify(req.body);

  const hash = crypto
    .createHmac('sha256', SHOPIFY_WEBHOOK_SECRET)
    .update(body)
    .digest('base64');

  if (hash !== hmac) {
    return res.status(401).send('Invalid HMAC');
  }

  // 处理订单
  const order = req.body;
  console.log('New order:', order.id, order.email);

  // 快速响应(5秒内)
  res.status(200).send('OK');

  // 后台处理
  await processOrder(order);
});

Common Patterns

常见模式

Pagination (GraphQL)

分页(GraphQL)

javascript
async function getAllProducts(accessToken, store) {
  let allProducts = [];
  let hasNextPage = true;
  let cursor = null;

  while (hasNextPage) {
    const query = `
      query GetProducts($first: Int!, $after: String) {
        products(first: $first, after: $after) {
          edges {
            node { id title }
          }
          pageInfo {
            hasNextPage
            endCursor
          }
        }
      }
    `;

    const response = await fetch(endpoint, {
      method: 'POST',
      headers: {
        'X-Shopify-Access-Token': accessToken,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        query,
        variables: { first: 50, after: cursor },
      }),
    });

    const { data } = await response.json();
    allProducts.push(...data.products.edges.map(e => e.node));

    hasNextPage = data.products.pageInfo.hasNextPage;
    cursor = data.products.pageInfo.endCursor;
  }

  return allProducts;
}
javascript
async function getAllProducts(accessToken, store) {
  let allProducts = [];
  let hasNextPage = true;
  let cursor = null;

  while (hasNextPage) {
    const query = `
      query GetProducts($first: Int!, $after: String) {
        products(first: $first, after: $after) {
          edges {
            node { id title }
          }
          pageInfo {
            hasNextPage
            endCursor
          }
        }
      }
    `;

    const response = await fetch(endpoint, {
      method: 'POST',
      headers: {
        'X-Shopify-Access-Token': accessToken,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        query,
        variables: { first: 50, after: cursor },
      }),
    });

    const { data } = await response.json();
    allProducts.push(...data.products.edges.map(e => e.node));

    hasNextPage = data.products.pageInfo.hasNextPage;
    cursor = data.products.pageInfo.endCursor;
  }

  return allProducts;
}

Error Handling

错误处理

javascript
async function safeApiCall(query, variables) {
  try {
    const response = await fetch(endpoint, {
      method: 'POST',
      headers: {
        'X-Shopify-Access-Token': accessToken,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ query, variables }),
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const { data, errors } = await response.json();

    if (errors) {
      console.error('GraphQL Errors:', errors);
      throw new Error(errors[0].message);
    }

    return data;
  } catch (error) {
    console.error('API Error:', error);
    throw error;
  }
}
javascript
async function safeApiCall(query, variables) {
  try {
    const response = await fetch(endpoint, {
      method: 'POST',
      headers: {
        'X-Shopify-Access-Token': accessToken,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ query, variables }),
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const { data, errors } = await response.json();

    if (errors) {
      console.error('GraphQL Errors:', errors);
      throw new Error(errors[0].message);
    }

    return data;
  } catch (error) {
    console.error('API Error:', error);
    throw error;
  }
}

Best Practices

最佳实践

  1. Always check API version - Use latest stable (2025-10)
  2. Implement rate limit handling - Use exponential backoff
  3. Verify webhook HMAC - Security critical
  4. Use GraphQL over REST when possible - More efficient
  5. Request only needed fields - Reduce response size
  6. Handle errors gracefully - Check
    errors
    and
    userErrors
  7. Store access tokens securely - Never expose in client code
  8. Use minimum necessary scopes - Security best practice
  9. Implement retry logic - Handle transient failures
  10. Respond to webhooks quickly - Within 5 seconds
  1. 始终检查API版本 - 使用最新稳定版(2025-10)
  2. 实现速率限制处理 - 使用指数退避策略
  3. 验证Webhook HMAC - 安全关键步骤
  4. 优先使用GraphQL而非REST - 更高效
  5. 仅请求所需字段 - 减小响应体积
  6. 优雅处理错误 - 检查
    errors
    userErrors
  7. 安全存储访问令牌 - 绝不在客户端代码中暴露
  8. 使用最小必要权限范围 - 安全最佳实践
  9. 实现重试逻辑 - 处理临时故障
  10. 快速响应Webhook - 5秒内完成响应

Detailed References

详细参考

  • references/graphql-queries.md - Complete query examples
  • references/rest-endpoints.md - All REST endpoints
  • references/webhook-payloads.md - Webhook payload structures
  • references/graphql-queries.md - 完整查询示例
  • references/rest-endpoints.md - 所有REST端点
  • references/webhook-payloads.md - Webhook负载结构

Integration with Other Skills

与其他技能集成

  • shopify-app-dev - Use when building custom Shopify apps
  • shopify-liquid - Use when displaying API data in theme templates
  • shopify-debugging - Use when troubleshooting API errors
  • shopify-performance - Use when optimizing API request patterns
  • shopify-app-dev - 构建自定义Shopify应用时使用
  • shopify-liquid - 在主题模板中展示API数据时使用
  • shopify-debugging - 排查API错误时使用
  • shopify-performance - 优化API请求模式时使用

Quick Reference

快速参考

javascript
// GraphQL Admin API
POST https://{store}.myshopify.com/admin/api/2025-10/graphql.json
Headers: { 'X-Shopify-Access-Token': 'shpat_...' }

// REST Admin API
GET https://{store}.myshopify.com/admin/api/2025-10/products.json
Headers: { 'X-Shopify-Access-Token': 'shpat_...' }

// Storefront API
POST https://{store}.myshopify.com/api/2025-10/graphql.json
Headers: { 'X-Shopify-Storefront-Access-Token': 'token' }

// Ajax API (theme)
fetch('/cart.js')
fetch('/cart/add.js', { method: 'POST', body: ... })
fetch('/cart/change.js', { method: 'POST', body: ... })
javascript
// GraphQL Admin API
POST https://{store}.myshopify.com/admin/api/2025-10/graphql.json
Headers: { 'X-Shopify-Access-Token': 'shpat_...' }

// REST Admin API
GET https://{store}.myshopify.com/admin/api/2025-10/products.json
Headers: { 'X-Shopify-Access-Token': 'shpat_...' }

// Storefront API
POST https://{store}.myshopify.com/api/2025-10/graphql.json
Headers: { 'X-Shopify-Storefront-Access-Token': 'token' }

// Ajax API (主题)
fetch('/cart.js')
fetch('/cart/add.js', { method: 'POST', body: ... })
fetch('/cart/change.js', { method: 'POST', body: ... })