快递查询API

← 技术博客

微信小程序快递查询:密钥必须放服务端

2026-07-26 · 阅读约 6 分钟

在微信小程序里做「物流查询」页面很常见,但很多人第一版就踩同一个坑:直接在 wx.request 里拼上快递 API 的密钥。 这一步等于把密钥公开了。本文讲清楚为什么不能这么做,以及正确的两种代理架构——微信云函数自建服务器,各配一份可直接用的示例。

一、错误做法:在 wx.request 里直接调用快递 API

小程序的前端代码会随安装包下发到用户手机,可以被反编译,网络请求也能被抓包。任何写死在前端的东西——包括密钥——都视同公开。 下面这种写法千万别用:

// ❌ 错误示范:绝对不要这样写
// Secret Key 会随小程序包一起下发到手机,抓包或反编译即可读到
wx.request({
  url: 'https://api.kuaidichaxunapi.com/v1/tracking/trace',
  method: 'POST',
  header: {
    'Authorization': 'Bearer pk_xxx:sk_xxx', // 密钥暴露!
    'content-type': 'application/json',
  },
  data: { items: [{ courierCode: 'cainiao', trackingNumber: 'CGD0000123456' }] },
});

这样写有两个致命问题:一是 Secret Key 泄露,别人能拿你的额度刷到爆; 二是你还得把 api.kuaidichaxunapi.com 加进小程序的 request 合法域名,等于把调用入口也摆到明处。

二、正确架构:小程序 → 代理 → 快递 API

解决办法是加一层「代理」:小程序只跟你自己的代理说话,代理在服务端保管密钥、再去请求快递 API, 密钥永远不进入小程序包。代理有两种常见实现——微信云开发的云函数,或你自己的服务器

三、方案 A:微信云函数

如果项目用了微信云开发,这是最省事的方案。密钥配置在云函数的环境变量里,云函数内部去请求快递 API:

// cloudfunctions/kuaidi/index.js —— 微信云开发云函数
// 密钥配置在云函数「环境变量」里,不写进小程序前端
const AUTH = 'Bearer ' + process.env.KUAIDI_PK + ':' + process.env.KUAIDI_SK;

// 云函数运行时需 Node 18+ 才有全局 fetch;更低版本请改用 axios
exports.main = async (event) => {
  const items = (event.items || []).slice(0, 10);
  const res = await fetch('https://api.kuaidichaxunapi.com/v1/tracking/trace', {
    method: 'POST',
    headers: { 'Authorization': AUTH, 'Content-Type': 'application/json' },
    body: JSON.stringify({ items }),
  });
  const json = await res.json();
  return json.data; // 只回传 results / summary
};

小程序端用 wx.cloud.callFunction 调用,走的是微信内部通道, 不占用 request 合法域名,也就省去了域名配置:

// pages/chaxun/chaxun.js —— 调用云函数,走微信内部通道
// 无需在 request 合法域名里配置任何地址
wx.cloud.callFunction({
  name: 'kuaidi',
  data: { items: [{ courierCode: 'cainiao', trackingNumber: 'CGD0000123456' }] },
  success(res) {
    const r = res.result.results[0];
    if (r.success) {
      console.log(r.data.deliveryStatusText); // 例如「运输中」
    } else {
      console.warn(r.error.code);
    }
  },
});

四、方案 B:自建服务器

如果你已经有后端(要多端复用,或不想用云开发),就让小程序请求自己的服务器,服务器再转发。 服务端代码与 Node.js 篇 的 Express 代理完全一样,小程序端这样写:

// 方案 B:小程序请求「你自己的服务器」,而不是快递 API
wx.request({
  url: 'https://your-server.com/api/kuaidi', // 要加入 request 合法域名的是这个域名
  method: 'POST',
  header: { 'content-type': 'application/json' },
  data: { items: [{ courierCode: 'cainiao', trackingNumber: 'CGD0000123456' }] },
  success(res) {
    const r = (res.data.results || [])[0];
    if (r) console.log(r.success ? r.data.deliveryStatusText : r.error.code);
  },
});

这里有个最容易搞错的点,单独强调:需要加入 request 合法域名的,是你自己服务器的域名https://your-server.com),不是 api.kuaidichaxunapi.com—— 因为小程序端根本不直接访问快递 API。配置路径是「小程序管理后台 → 开发管理 → 开发设置 → 服务器域名 → request 合法域名」, 且该域名必须是 HTTPS、已完成 ICP 备案。

五、两种方案怎么选

对比项方案 A:云函数方案 B:自建服务器
密钥存放云函数环境变量服务器环境变量
request 合法域名无需配置(走微信通道)需加入你的服务器域名
是否需要服务器否,按调用计费是,自行部署维护
适合场景纯小程序、快速上线已有后端、多端复用

六、展示结果

两种方案拿到的都是同一份 data(含 results / summary)。展示时关注这几个字段:

  • deliveryStatusText:可直接显示的中文状态(如「运输中」「已签收」);
  • isDelivered:布尔值,做「待收货 / 已完成」分类时直接用它;
  • progresses:轨迹数组,最新在前,每条含 dateTimelocationstatusdescription

完整字段与错误码见接口文档;Node 服务端代理的写法见 用 Node.js 对接快递查询接口;支持的快递公司见快递公司页。 还没有密钥就先注册(邮箱即可,无需企业认证)。