You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Node应用中为Shopify Storefront API使用委托令牌

解决Shopify Storefront API限流:Node.js+AWS Lambda下用委托令牌传递客户端IP

核心逻辑

Shopify的委托令牌(Delegated Access Token)允许后端服务代表客户端发起Storefront API请求,同时通过请求头传递客户端真实IP,让Shopify基于客户端IP做限流判断,而非Lambda的固定出口IP。关键是两步:生成带权限的委托令牌,请求时附加客户端IP头。

步骤1:生成委托令牌

委托令牌需通过Shopify Admin API创建,指定权限、有效期和客户端标识符(用来关联请求发起者)。

代码示例(Node.js + Axios)

const axios = require('axios');

async function generateDelegatedToken(shopDomain, adminAccessToken, clientId) {
  try {
    const res = await axios.post(
      `https://${shopDomain}/admin/api/2024-07/access_tokens/delegate.json`,
      {
        delegate_access_token: {
          subject: clientId, // 用客户端会话ID/用户ID作为标识
          permissions: ['write_customers'], // 密码重置需该权限
          expires_in: 3600 // 令牌有效期1小时,可按需调整
        }
      },
      {
        headers: {
          'X-Shopify-Access-Token': adminAccessToken,
          'Content-Type': 'application/json'
        }
      }
    );
    return res.data.delegate_access_token.token;
  } catch (err) {
    console.error('生成委托令牌失败:', err.response?.data || err.message);
    throw err;
  }
}

步骤2:传递客户端IP发起Storefront请求

从Lambda事件中提取客户端真实IP,结合委托令牌调用Storefront API,同时添加Shopify-User-IP头(Shopify优先识别这个)。

提取客户端IP(Lambda APIGateway场景)

function getClientRealIp(event) {
  // 优先取X-Forwarded-For(CDN转发场景)
  const forwardedFor = event.headers?.['X-Forwarded-For'];
  if (forwardedFor) {
    // 格式通常为 "客户端IP, 代理IP1, 代理IP2",取第一个
    return forwardedFor.split(',')[0].trim();
  }
  // 直接取Lambda自带的源IP
  return event.requestContext?.http?.sourceIp;
}

密码重置请求示例(Storefront GraphQL API)

async function resetCustomerPassword(shopDomain, delegatedToken, clientIp, email) {
  const mutation = `
    mutation CustomerRecover($email: String!) {
      customerRecover(email: $email) {
        customerUserErrors {
          message
        }
      }
    }
  `;

  try {
    const res = await axios.post(
      `https://${shopDomain}/api/2024-07/graphql.json`,
      { query: mutation, variables: { email } },
      {
        headers: {
          'Authorization': `Bearer ${delegatedToken}`,
          'Content-Type': 'application/json',
          'Shopify-User-IP': clientIp, // 核心:传递客户端真实IP
          'X-Forwarded-For': clientIp // 备选,兼容部分场景
        }
      }
    );
    return res.data;
  } catch (err) {
    console.error('密码重置请求失败:', err.response?.data || err.message);
    throw err;
  }
}

优化建议

  • 令牌缓存:委托令牌有效期内可缓存(比如用DynamoDB或Lambda内存),避免重复调用Admin API
  • 权限最小化:令牌权限只申请需要的(比如密码重置仅需write_customers),降低安全风险
  • 错误重试:若仍触发限流,可针对客户端IP做本地重试延迟,避免频繁请求Shopify

内容的提问来源于stack exchange,提问作者Untoughtful

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 21:24:22