小程序与 H5 调用第三方 API:前端不持密钥的调用边界
一句话回答
正文结论:除非接口完全公开且无凭据风险,小程序与 H5 不应在前端直接持有第三方 API 密钥;更稳妥的是前端调用自有后端,由后端完成鉴权、转发、限流与日志脱敏。小程序合法域名和 H5 跨域要求需以平台文档核实。
小程序和 H5 调用第三方 API,关键不在“用哪个请求函数”,而在信任边界:前端不应持有第三方 API 密钥。更稳妥的做法是让前端只调用自有后端,由后端持有凭据并转发请求。若接口完全公开、无凭据、无配额风险,直连才值得评估;是否允许跨域仍需核实。
为什么不要把密钥放在前端#
小程序包和 H5 资源都会到达用户设备,代码、配置和网络请求可被查看。把 YOUR_KEY 写进前端,等同于把调用权限交给任何能打开调试工具的人。即使第三方接口允许浏览器跨域调用,也不代表应该在前端放密钥。
三段式调用链#
- 前端:小程序或 H5 只请求自有后端接口,例如
/api/quote。 - 自有后端:读取环境变量中的密钥,完成鉴权、参数校验、限流、缓存和日志脱敏。
- 第三方 API:后端向服务商发起请求,把必要结果和错误码映射后返回前端。
对 API.PLUS 或任何第三方 API,接入前先核对接口契约:鉴权方式、配额、错误码、是否允许浏览器跨域调用。本文不假设具体端点或免费政策;这些信息以服务商文档为准(待核实)。
小程序与 H5 的差异#
H5 受浏览器同源策略和 CORS(跨源资源共享)约束。第三方未返回合适的 CORS 响应头时,浏览器会拦截读取结果;此时服务端中转通常比在前端“绕过”更可控。
微信小程序通常需要把请求域名配置为合法域名,具体入口、校验规则和开发阶段限制应以微信官方文档为准(本文未联网核验)。因此,小程序请求自有后端时,也要确认该后端域名已按要求配置。
未执行示例:前端只调自有后端#
// 未执行示例:H5 调用同源后端
const res = await fetch("/api/quote");
const data = await res.json();
// 未执行示例:小程序调用自有后端
// backend.example.com 为占位域名;合法域名需按平台要求配置
wx.request({
url: "https://backend.example.com/api/quote",
success(res) {
console.log(res.data);
}
});
下面的服务端示例仅说明结构,未实际运行;运行环境需提供 fetch。密钥放在环境变量中,不写入代码仓库。
// 未执行示例:服务端中转,api.example.com 与 YOUR_KEY 均为占位
app.get("/api/quote", async (req, res) => {
const upstream = await fetch("https://api.example.com/v1/quote", {
headers: { Authorization: `Bearer ${process.env.THIRD_PARTY_KEY}` }
});
if (!upstream.ok) {
return res.status(502).json({ error: "upstream_error" });
}
res.json(await upstream.json());
});
上线前检查#
- 前端包、日志和错误页中没有第三方密钥。
- 后端设置超时、有限重试和幂等边界;不要无限重试。
- 按接口用途限制 CORS,而不是对全部来源开放。
- 记录调用量、失败率和延迟,但对请求头与参数做脱敏。
- 服务端中转会增加一跳延迟和运维成本,需要监控单点故障。
结论是:小程序与 H5 的“正确姿势”应先确定谁能持有凭据。把密钥留在服务端,前端只消费自有接口,通常比前端直连第三方更安全、也更便于限流和排错。