用户登录

技术文章

外部链接将在新标签页打开。

微信小程序与 H5 调用第三方 API 的正确姿势:把平台差异收敛到一个请求层

一句话回答

业务代码应只依赖统一的内部请求契约,由薄适配层吸收小程序请求域名配置与 H5 CORS 等平台差异;长期密钥不进入前端,超时、错误映射和幂等重试在上线前统一定义。具体平台规则与 API.PLUS 接入参数需以官方文档为准。

正确姿势可以概括为一句话:业务代码只依赖一个内部请求契约,平台差异由薄适配层吸收,长期密钥不进入小程序包或 H5 静态资源。小程序侧的请求域名配置与 H5 侧的 CORS(跨源资源共享)属于两类不同约束,材料标题层面已点出这两个概念,但具体配置口径需以平台官方文档为准;本次材料未提供可核验正文与链接,因此不展开具体规则,也不声称已联网核验。

先定三个边界,再写请求代码#

  • 密钥边界。前端可见的内容都应视为可被提取。建议服务端持有长期密钥,前端只拿短期令牌,或改为调用自家代理。示例中的 YOUR_KEY 仅作占位,不是真实密钥。
  • 请求边界。小程序与 H5 的底层请求 API 不同,但入参、出参和错误结构可以统一,避免业务层出现两套分支。
  • 失败边界。网络失败、超时、HTTP 4xx/5xx 与业务错误码要分层表达。否则页面只能显示“请求失败”,无法决定是否重试或提示用户。

内部请求契约#

适配层对业务层暴露一个函数,入参至少包含以下字段:

字段含义注意
path相对路径不要由调用方拼接完整域名
methodHTTP 方法默认 GET,写操作显式声明
timeoutMs超时时间应小于页面或交互可等待的时长
idempotencyKey幂等键仅对可安全重试的写操作使用
requestId请求标识用于日志关联,不要记录密钥

统一返回结构建议固定为 { ok, data, error, requestId },其中 error.kind 取有限枚举,例如 network、timeout、auth、rate_limit、server、business。这样重试策略可以按 kind 分支,而不是散落在页面代码里。

适配层示意:同一个入口,两种实现#

下面的代码是结构示意,未在真实小程序或浏览器环境执行;域名、响应结构和状态码映射均为占位,接入时应按实际接口契约替换。

const API_BASE = 'https://api.example.com'; // 占位域名

function normalize(status, body) {
  if (status >= 200 && status < 300) {
    return { ok: true, data: body, error: null };
  }
  const kind = status === 401 || status === 403 ? 'auth'
    : status === 429 ? 'rate_limit'
    : status >= 500 ? 'server'
    : 'business';
  return { ok: false, data: null, error: { kind, status, body } };
}

// H5:受同源策略约束,跨域需要服务端 CORS 配合
async function requestH5(opts) {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), opts.timeoutMs);
  try {
    const res = await fetch(API_BASE + opts.path, {
      method: opts.method,
      headers: opts.headers,
      body: opts.body,
      signal: controller.signal
    });
    return normalize(res.status, await res.json());
  } catch (e) {
    return { ok: false, data: null, error: { kind: 'network', message: String(e) } };
  } finally {
    clearTimeout(timer);
  }
}

// 小程序:使用平台请求 API,域名需按官方文档配置
function requestMP(opts) {
  return new Promise((resolve) => {
    wx.request({
      url: API_BASE + opts.path,
      method: opts.method,
      data: opts.body,
      header: opts.headers,
      timeout: opts.timeoutMs,
      success: (res) => resolve(normalize(res.statusCode, res.data)),
      fail: (err) => resolve({
        ok: false, data: null,
        error: { kind: 'network', message: err.errMsg }
      })
    });
  });
}

错误映射与重试的边界#

  • 网络错误与超时:只对幂等请求做有限次退避重试;非幂等写操作需要幂等键才能重试。
  • 401/403:不要自动循环重试。若需要刷新令牌,应做单飞控制,避免并发请求同时刷新。
  • 429:若响应提供 Retry-After,可按其指示等待;否则采用有上限的指数退避并加入抖动。
  • 5xx:可做少量退避重试,但要把最终失败明确交给页面。
  • 业务错误:通常不重试,按契约提示用户或修正入参。

上线前检查清单#

  1. 长期密钥是否只存在于服务端,前端仅持有短期凭证或代理地址。
  2. 小程序请求域名与 H5 允许来源是否按各自官方文档配置;具体位置与最新规则待核实。
  3. 超时时间是否小于页面可等待时长,取消请求后是否清理定时器。
  4. 重试是否只覆盖幂等请求,是否设置最大次数和总时长。
  5. 日志是否记录 requestId,是否避免写入密钥、令牌和完整敏感响应。
  6. 若使用代理,是否限制可转发的目标域,并只透传必要的请求头。

本文给出的是结构建议,不是对某个平台最新规则的复述。微信小程序当前的域名配置要求、H5 的 CORS 细节,以及 API.PLUS 的实际端点、配额与鉴权参数,本次材料均未提供可核验正文,需查阅对应官方文档后再落地。

作者:沐小悠

本文约 8 分钟读完 · 关键词:微信小程序调用API、H5跨域请求、请求适配层、API密钥安全、错误契约

更多文章 GET 示例接口

「」标签下的其他文章