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

Shopify自定义应用前端如何更新即将过期的Access Token?

Shopify自定义应用前端更新Access Token方案

核心逻辑

前端无法直接完成token刷新——因为Shopify的token刷新依赖客户端密钥(Client Secret),这个敏感信息绝对不能暴露在前端代码中。正确流程是:前端检测token过期/失效 → 请求后端服务执行刷新逻辑 → 后端返回新token → 前端更新本地存储的token。

具体实现步骤

1. 前端检测token状态

针对Session Token(JWT)

如果使用Shopify嵌入式应用的Session Token,可以解码JWT的exp字段判断过期时间:

// 解码JWT获取过期时间(转换为毫秒)
function getTokenExpiration(token) {
  const payload = JSON.parse(atob(token.split('.')[1]));
  return payload.exp * 1000;
}

// 提前1分钟触发刷新
const currentToken = localStorage.getItem('shopify_access_token');
if (currentToken) {
  const expTime = getTokenExpiration(currentToken);
  if (Date.now() >= expTime - 60000) {
    refreshToken();
  }
}

针对在线访问模式的OAuth Token

后端返回token时需附带过期时间戳,前端存储后定期检查:

const expiresAt = localStorage.getItem('shopify_token_expires_at');
if (Date.now() >= expiresAt - 60000) {
  refreshToken();
}

2. 后端实现刷新接口

只有开启在线访问模式的Shopify应用才会返回refresh token,后端通过Shopify的OAuth接口完成刷新:

// Express示例
app.post('/api/refresh-shopify-token', async (req, res) => {
  const { shopDomain, refreshToken } = req.body;
  
  try {
    const response = await fetch(`https://${shopDomain}/admin/oauth/access_token`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        client_id: process.env.SHOPIFY_API_KEY,
        client_secret: process.env.SHOPIFY_API_SECRET,
        refresh_token: refreshToken,
        grant_type: 'refresh_token'
      })
    });
    
    const data = await response.json();
    res.json({
      accessToken: data.access_token,
      refreshToken: data.refresh_token || refreshToken,
      expiresAt: Date.now() + (data.expires_in * 1000)
    });
  } catch (err) {
    res.status(500).json({ error: 'Token刷新失败' });
  }
});

3. 前端调用刷新接口并更新token

async function refreshToken() {
  const shop = localStorage.getItem('shopify_shop_domain');
  const refreshToken = localStorage.getItem('shopify_refresh_token');
  
  try {
    const response = await fetch('/api/refresh-shopify-token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ shopDomain: shop, refreshToken })
    });
    
    const result = await response.json();
    // 更新本地存储
    localStorage.setItem('shopify_access_token', result.accessToken);
    localStorage.setItem('shopify_refresh_token', result.refreshToken);
    localStorage.setItem('shopify_token_expires_at', result.expiresAt);
  } catch (err) {
    // 刷新失败则引导用户重新授权
    window.location.href = '/auth';
  }
}

4. 处理API调用时的401错误

提前检测仍可能出现token过期,需捕获API返回的401状态并重试:

async function callShopifyApi(endpoint, options = {}) {
  const token = localStorage.getItem('shopify_access_token');
  const shop = localStorage.getItem('shopify_shop_domain');
  const headers = {
    'X-Shopify-Access-Token': token,
    ...options.headers
  };
  
  try {
    const response = await fetch(`https://${shop}/admin/api/2024-07/${endpoint}`, {
      ...options,
      headers
    });
    
    if (response.status === 401) {
      await refreshToken();
      return callShopifyApi(endpoint, options); // 刷新后重试请求
    }
    
    return response.json();
  } catch (err) {
    throw err;
  }
}

特殊情况:Session Token刷新

如果使用Shopify嵌入式应用的Session Token(有效期24小时),无法通过refresh token刷新,需通过App Bridge重新获取:

import { getSessionToken } from '@shopify/app-bridge-utils';
import createApp from '@shopify/app-bridge';

const app = createApp({
  apiKey: 'YOUR_API_KEY',
  shopOrigin: localStorage.getItem('shopify_shop_domain')
});

async function refreshSessionToken() {
  const newToken = await getSessionToken(app);
  localStorage.setItem('shopify_access_token', newToken);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 23:52:18