用户登录

技术文章

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

微信小程序与 H5 调用第三方 API:把密钥留在服务端,再处理跨域与域名

一句话回答

小程序与 H5 直连第三方 API 会同时遇到密钥暴露、跨域或域名白名单限制以及无法统一限流的问题。更稳妥的做法是让客户端只调用自己的后端,由后端持密钥、做超时与错误映射,再按平台规则处理小程序合法域名与 H5 的 CORS。具体平台规则与第三方接口细节需以其官方文档为准,本文未做核验。

核心要点 TL;DR
  • 客户端不持有第三方长期密钥,密钥只放在服务端环境变量里。
  • 小程序受合法域名等平台配置约束,H5 受浏览器同源策略与 CORS 约束,两者都不该用客户端直连来绕过。
  • 后端中转要显式设置超时、把上游错误映射成自己的错误码,并给出降级路径。

简短回答:不要把第三方 API 的调用写在微信小程序或 H5 的前端代码里。让客户端只请求你自己的后端,由后端持有密钥、发起上游请求、统一超时与错误处理,再决定小程序侧的合法域名配置和 H5 侧的跨域策略。本文只讨论这一层的工程判断;微信平台的具体规则、第三方服务的鉴权方式与配额,均需以其官方文档为准,本次未核验。

直连的三个问题#

密钥暴露。小程序包可被解包,H5 的请求在浏览器网络面板里一览无余。任何写进前端的 AppKey、Token 都应视为已公开。

运行环境限制。H5 受同源策略约束:浏览器是否允许页面直接读取第三方响应,取决于对方是否返回合适的 CORS 响应头,以及预检请求(OPTIONS)是否被正确处理。这不是前端代码能单方面决定的事。

失去控制点。直连意味着限流、缓存、审计、故障降级都散落在客户端,出问题时既无法统一关闭,也无法统计。

小程序侧:先看平台规则,再谈代码#

小程序的网络请求走宿主提供的 API,而不是浏览器 fetch,因此不适用 CORS,但通常受平台侧的网络请求域名配置约束,且一般要求 HTTPS。具体是哪些域名需要提前配置、是否支持通配、开发与体验版是否放宽,属于平台规则,请以微信官方文档为准;本文不给出未经核验的结论。

可以确定的工程结论是:既然域名需要提前登记,就更应把登记对象设为你自己的后端域名,而不是随第三方变更而变动的外部域名。也不要试图用内嵌网页等方式绕过请求约束——那只是把同一个问题挪到另一个运行环境里。

H5 侧:跨域是对方的策略,不是你的配置#

如果第三方明确为浏览器场景提供 CORS 支持,直连在技术上可行;但此时密钥依然暴露,通常仍建议中转。若对方未开放跨域,前端无论如何配置都拿不到响应体,只能看到被浏览器拦截的失败。判断依据是对方文档与响应头,而不是本地试出来的结果。

推荐结构:客户端 → 你的后端 → 第三方#

  1. 密钥放在服务端环境变量,不进仓库、不进构建产物。
  2. 后端为每个上游接口设置显式超时,并使用可取消的请求。
  3. 把上游状态码与业务错误码翻译成你自己稳定的错误码,客户端只认这一套。
  4. 在网关上做限流与缓存,客户端不承担这部分逻辑。
  5. 为客户端定义降级行为:返回缓存、占位内容,或明确的“稍后重试”。
// 未执行示例:Node.js + Express 结构示意,未实际运行
app.get('/api/quote', async (req, res) => {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), 5000);
  try {
    const r = await fetch('https://api.example.com/v1/quote', {
      headers: { Authorization: 'Bearer ' + process.env.UPSTREAM_KEY },
      signal: controller.signal
    });
    if (!r.ok) return res.status(502).json({ code: 'UPSTREAM_ERROR' });
    res.json(await r.json());
  } catch (e) {
    res.status(504).json({ code: 'UPSTREAM_TIMEOUT' });
  } finally {
    clearTimeout(timer);
  }
});
// 未执行示例:微信小程序端调用自己的后端
wx.request({
  url: 'https://your-domain.example.com/api/quote',
  method: 'GET',
  timeout: 6000,
  success(res) { /* 只依赖自己的返回结构与错误码 */ },
  fail() { /* 走降级:缓存内容或占位提示 */ }
});

示例中的 example.com、your-domain.example.com 与 UPSTREAM_KEY 均为占位,需替换为已核实的真实地址与密钥管理方式。两段代码均未执行,不构成实测结论。

上线前的核对项#

核对项要确认什么
密钥位置前端产物、日志、错误上报中均不出现密钥
平台配置小程序侧域名是否已按平台要求登记,以官方文档为准
跨域若前端需直连,对方是否明确支持 CORS;否则不列入方案
超时与重试超时值、是否幂等、重试次数上限是否有明确约定
错误语义客户端是否能区分“暂时失败”和“请求本身有错”

若你接入的是 API.PLUS 这类第三方接口服务,鉴权方式、请求配额、返回结构与是否允许浏览器直连,都要以其文档为准;本文材料未包含这些细节,均待核实。可以先行确定的是架构边界:密钥留在服务端,客户端只面对你定义的接口契约,平台规则与上游变更就不会直接传导到用户界面。

作者:沐小悠

本文约 6 分钟读完 · 关键词:微信小程序调用第三方API、H5 跨域 CORS、服务端中转、BFF、API 密钥安全

更多文章 GET 示例接口

「」标签下的其他文章