用户登录

技术文章

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

微信小程序与 H5 调用第三方 API:先定密钥归属,再选直连或代理

一句话回答

小程序不走浏览器同源策略,卡点在后台配置的 request 合法域名与 HTTPS;H5 受浏览器 CORS 约束。两者共同的决定因素是密钥放在哪一侧:凡涉及 AppSecret 或长期 API Key,就应走自有服务端代理,而不是在客户端直连。

结论先给:微信小程序和 H5 调用第三方 API,失败原因通常不在写法,而在两件与代码无关的事——请求从哪个环境发出,以及密钥放在哪一侧。小程序没有浏览器的同源策略,真正的门槛是小程序后台配置的服务器域名白名单;H5 运行在浏览器里,真正门槛是第三方是否返回允许跨域的响应头。两者都涉及长期密钥时,正确姿势都是加一层自有服务端代理。

本文不针对某个具体接口的可用性下判断。API.PLUS 各接口是否支持浏览器直连、是否需要额外签名,需以其接口文档为准,本次未联网核验,相关细节待核实。

小程序:卡在白名单,不是 CORS#

小程序的网络请求由客户端发起,不受浏览器同源策略约束,因此不存在 CORS 预检。取而代之的是域名白名单机制:需要在微信公众平台后台为相应类目(如 request、uploadFile、downloadFile、socket)配置合法域名,且域名一般要求为 HTTPS、不能使用 IP 地址,备案等要求以微信官方文档为准。未配置的域名在真机上会直接失败,而开发者工具里勾选「不校验合法域名」后能跑通——这个开关只用于本地调试,不能作为上线依据。

需要强调的是,白名单只解决「能不能发出去」,不解决「该不该从这里发」。小程序代码包可以被解出,把 AppSecret 或长期有效的 API Key 写进前端,等同于公开。涉及签名的调用应放在服务端完成,客户端只拿短期凭证。

H5:CORS 是浏览器在执行#

CORS(Cross-Origin Resource Sharing,跨源资源共享)的检查由浏览器完成,服务端只是提供响应头。常见误区有三个:

  • 简单请求与预检请求不同。带自定义头(如 Authorization)或非简单 Content-Type 时,浏览器会先发 OPTIONS 预检,服务端必须正确响应,否则真实请求根本不会发出。
  • Access-Control-Allow-Origin 取 * 时不能同时携带凭证(cookies);需要凭证就要回显具体来源并配 Allow-Credentials。
  • 用 curl 或 Postman 调通,不能证明浏览器能调通——这些工具不执行 CORS 检查。

两种环境,同一套判断顺序#

判断项微信小程序H5
拦截面后台域名白名单、HTTPS浏览器同源策略与预检
密钥能否放前端不能不能
推荐的稳定形态客户端 → 自有服务端 → 第三方同左,或第三方明确支持且仅用公开只读凭证
调试期常用手段关闭域名校验(仅本地)关闭浏览器安全策略(仅本地)

表格最后一行值得单独说:两种「关闭校验」的做法都只应存在于开发机,不能进构建产物,也不能作为「线上也行」的证据。

代理链路的顺序#

如果决定走自有服务端,顺序建议是:客户端携带短期身份凭证 → 服务端校验身份与配额 → 服务端拼接第三方密钥并签名 → 请求第三方 → 服务端归一化响应后再返回客户端。这样客户端永远看不到长期密钥,CORS 与域名白名单问题也一并消解,因为客户端只和自己的域名通信。

需要一并定下的是失败路径:超时设多久、是否重试、重试是否会重复计费。第三方接口是否幂等通常未知,未确认前不宜自动重试写操作。

未执行的示例骨架

以下两段均为未执行的示例,仅示意结构,端点与字段均为占位,预期行为未经验证。

// 小程序端:只请求自己的域名,密钥不出现在这里
wx.request({
  url: 'https://api.example.com/proxy/query', // 占位
  method: 'POST',
  header: { 'content-type': 'application/json' },
  data: { q: 'demo', token: 'YOUR_SESSION_TOKEN' },
  success: (res) => { /* 按自有服务端的统一契约解析 */ },
  fail: (err) => { /* 网络失败与业务失败分开处理 */ }
});
// 服务端转发:密钥来自环境变量,不下发到客户端
app.post('/proxy/query', async (req, res) => {
  // 1) 校验 req.body.token 2) 配额与限流 3) 拼接第三方密钥
  const upstream = await fetch('https://third-party.example.com/v1/query', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${process.env.UPSTREAM_KEY}` },
    body: JSON.stringify({ q: req.body.q })
  });
  res.status(upstream.status).json(await upstream.json());
});

边界条件#

如果第三方 API 只提供浏览器端公开只读凭证、且明确声明支持跨域,H5 直连可以作为简化方案,但仍要接受它的限制:凭证公开、无法做服务端限流、第三方策略变更会直接影响前端。反过来,如果第三方完全不支持 CORS,那么无论 H5 代码怎么写都调不通,代理是唯一可行路径,这一点不需要反复尝试来确认。

最后,小程序域名白名单的具体规则、H5 各浏览器的预检缓存时长,均以微信官方文档与浏览器厂商文档为准,本文不给出具体数值。

作者:沐小悠

本文约 7 分钟读完 · 关键词:微信小程序 API 调用、H5 CORS、request 合法域名、第三方 API 代理、AppSecret 安全

更多文章 GET 示例接口

「」标签下的其他文章