从一个需求说起
做跨境电商对账、旅行预算拆分或行情看板时,经常需要把一种货币金额换算成另一种。抛开手动查表的方案,最直接的做法是调用一个汇率接口:传入金额、源币种、目标币种,拿到换算结果。本文以实时汇率查询接口为例,从一条最小可用的 curl 命令开始,逐步扩展成一个带参数校验和错误处理的 Python 函数。
接口能力边界
这个接口提供 26 种主流货币的互转能力,覆盖 CNY、USD、EUR、GBP、JPY、HKD、KRW、AUD、CAD、SGD、CHF、TWD、THB、MYR、RUB、INR、BRL、ZAR、NZD、SEK、NOK、DKK、PHP、IDR、VND、AED。数据 1 分钟级更新,单个 key 的 QPS 限制为 5 次/秒。
两个值得注意的细节:
- 同币种快路径:当
from和to相同时,接口直接本地返回,不产生上游消耗。 - 货币列表子命令:传
action=currencies可获取全部支持的货币代码与中文名,便于做表单校验或下拉选项。
接口格式为GET https://v1.apizero.cn/api/exchange-rate,返回 JSON 数组,响应状态码与业务状态码分离(HTTP 200 不代表业务成功),这一点在后续错误处理部分会专门说明。
参数与鉴权说明
Query 参数
| 参数 | 必填 | 类型 | 说明 | 示例 |
|---|---|---|---|---|
money | 否 | number | 转换金额,必须 > 0,缺省为 1 | 12.5 |
from | 否 | string | 源货币代码,ISO 4217 三字母,缺省 CNY | CNY |
to | 否 | string | 目标货币代码,ISO 4217 三字母,缺省 USD | USD |
action | 否 | string | 传currencies返回支持货币列表 | currencies |
Header 参数
| 参数 | 必填 | 类型 | 说明 | 示例 |
|---|---|---|---|---|
Authorization | 否 | string | API Key 鉴权头,格式Bearer sk_live_xxx | Bearer sk_live_xxxxxxxxxxxxxx |
接口支持匿名调用(每日 50 次),需要更高调用量时在请求头中携带 API Key。考虑到 QPS 只有 5 次/秒,日常低频工具场景匿名调用通常够用。
第一次调用:从 curl 开始
先做最小验证。以下命令把 1 元人民币换算成美元:
curl -sS \ -X GET \ "https://v1.apizero.cn/api/exchange-rate?money=1&from=CNY&to=USD"携带 API Key 的版本:
curl -sS \ -X GET \ -H "Authorization: Bearer $APIZERO_API_KEY" \ "https://v1.apizero.cn/api/exchange-rate?from=CNY&to=USD&money=1"查看支持的货币列表:
curl -sS \ -X GET \ "https://v1.apizero.cn/api/exchange-rate?action=currencies"如果$APIZERO_API_KEY未设置,curl 会把空字符串作为 header 值发送,部分网关会拒绝。建议先export APIZERO_API_KEY=sk_live_xxx再执行。
返回结构解读
一次成功请求返回的 JSON 形如:
{ "code": 0, "data": { "from": "CNY", "from_name": "人民币", "money": 1, "rate": 0.146405, "result": 0.1464, "to": "USD", "to_name": "美元", "update_time": "2026-05-06 13:00:02" }, "msg": "成功", "request_id": "abc123def456" }关键字段说明:
| 字段 | 类型 | 含义 |
|---|---|---|
code | number | 业务状态码,0 表示成功 |
data.from/data.to | string | 源/目标货币代码 |
data.from_name/data.to_name | string | 货币中文名 |
data.rate | number | 原始汇率,未按金额放大 |
data.result | number | 实际换算结果,等于money * rate(按接口返回精度) |
data.update_time | string | 汇率更新时间 |
request_id | string | 请求唯一标识,排查问题时可回传 |
注意rate与result的精度差异:result是接口内部按货币精度处理后返回的值,直接用于展示即可,不要再自行四舍五入。
用 Python 封装成一个可复用函数
curl 验证通过后,用 Python 封装成函数,方便在脚本或服务中复用:
import os import requests API_URL = "https://v1.apizero.cn/api/exchange-rate" def convert_currency( amount: float, from_currency: str = "CNY", to_currency: str = "USD", api_key: str | None = None, ) -> dict: """实时汇率换算。""" if amount <= 0: raise ValueError("amount must be > 0") from_currency = from_currency.upper() to_currency = to_currency.upper() params = { "money": amount, "from": from_currency, "to": to_currency, } headers = {} if api_key: headers["Authorization"] = f"Bearer {api_key}" resp = requests.get(API_URL, params=params, headers=headers, timeout=5) resp.raise_for_status() # 只处理 HTTP 层错误 payload = resp.json() if payload.get("code") != 0: raise RuntimeError( f"API error: code={payload.get('code')}, msg={payload.get('msg')}" ) return payload["data"] # 使用示例 if __name__ == "__main__": result = convert_currency(100, "CNY", "JPY") print( f"{result['money']} {result['from_name']} = " f"{result['result']} {result['to_name']} " f"(rate={result['rate']}, updated at {result['update_time']})" )注意两点:
- 这里用
requests库发送 GET 请求,参数通过params传递,由库自动完成 URL 编码。 raise_for_status()只管 HTTP 状态码,业务层的code != 0需要单独判断。
常见错误与排查思路
1. HTTP 401 / 403
携带的 API Key 无效或未正确添加Authorization头。排查方式:先用 curl 不带 Key 调用一次,确认是否匿名配额耗尽;再用带 Key 的请求确认头格式是否为Bearer sk_live_xxx(Bearer 后有一个空格)。
2. 返回code非 0
业务层错误,常见原因:
money传了 0 或负数from/to不是 ISO 4217 三字母代码- 传入的货币代码不在 26 种支持列表内
先用action=currencies拉一次完整列表,核对代码拼写(例如印尼盾是IDR而非IDR的全称拼写)。
3. 响应超时
接口整体延迟低,但跨网络调用仍可能因网络抖动超时。建议客户端设置 5 秒超时,并配合指数退避重试(仅对幂等查询重试,重试次数 1-2 次即可)。
4. 数据精度问题
rate是原始汇率,位数较多;result是接口按货币精度处理后的结果。业务侧应根据result做展示,避免自行用round导致二次截断误差。
工程化注意事项
缓存策略
汇率数据 1 分钟级更新,同一个from/to对在 60 秒内的查询结果基本无变化。建议在本地做一层 TTL 缓存,key 设计为from:to,TTL 设 30-60 秒。这样既能减少上游调用量,又能规避 QPS 限制。
同币种短路
接口自身支持同币种快路径,但客户端仍建议在发起请求前判断from == to直接返回原金额,省一次网络往返。
货币列表预拉取
利用action=currencies在服务启动时拉取货币列表,缓存在内存中。用户输入币种时先做本地校验,减少无效请求。列表变更频率极低,可设置较长的 TTL(如 24 小时)。
请求频率控制
QPS 上限 5 次/秒,如果业务有批量换算需求(如一次转 100 对货币),要主动做请求间隔控制。一个简单做法是使用令牌桶或直接time.sleep(0.2)限速。
日志与链路追踪
每次请求都要记录request_id、from、to、result。排查问题时,把request_id与响应时间一并提供给接口维护方,能大幅缩短定位时间。
降级方案
汇率接口属于外部依赖,可能出现长时间不可用。核心交易场景建议内置一份每日更新的汇率快照做兜底,并在 UI 上标明“汇率时间”;非核心场景可接受直接报错。
小结
本文从一条 curl 命令出发,完成了实时汇率查询接口的最小可用验证,再扩展为带参数校验、错误处理和日志记录的 Python 函数。接入这类第三方汇率接口的关键点可以归纳为三条:理解业务状态码与 HTTP 状态码的分离、利用action=currencies做前置校验、通过缓存降低调用频率。把这三点做好,一个汇率换算工具就能稳定跑起来。
参考文档
- 接口文档:https://apizero.cn/aidocs/exchange-rate
- 原始文档:https://apizero.cn/aidocs/exchange-rate/raw.md