代理开放接口文档
更新时间
- 2026-05-25
适用范围
- 本文档面向代理系统开发人员。
- 当前已正式上线并可直接对接的开放能力有:
GET /openapi/agent/balanceGET /openapi/agent/countriesGET /openapi/agent/operatorsGET /openapi/agent/productsPOST /openapi/agent/ordersGET /openapi/agent/orders/{agent_order_id}- 平台状态回调:
POST <agent callback_url>
- 其它代理开放能力会在后续版本上线后补充到本文档。
接入概览
- 接口协议:HTTPS + JSON
- Base URL:由平台提供,例如
https://api.example.com - 当前可用前缀:
/openapi/agent - 鉴权方式:请求头
X-API-Key - 安全策略:
API Key + 白名单 IP- 若代理账号未配置启用中的白名单,只校验
X-API-Key - 若代理账号已配置启用中的白名单,来源 IP 必须命中白名单
- 若代理账号未配置启用中的白名单,只校验
统一请求规范
- 所有请求和响应均使用 UTF-8。
- 除
GET无请求体场景外,请求头建议固定带上:Content-Type: application/jsonAccept: application/jsonX-API-Key: <your_api_key>
- 所有金额字段使用十进制数字返回,当前示例以 JSON number 展示。
统一响应格式
- 所有接口统一返回:
{
"code": 0,
"message": "",
"data": {}
}
字段说明
code0表示成功- 非
0表示失败
message- 成功时通常为空字符串
- 失败时返回可直接排查的错误描述
data- 成功时为业务数据
- 失败时通常为
{}
常见错误码
40101:未授权- 常见原因:缺少
X-API-Key、X-API-Key无效、账号被禁用、账号不是代理账号
- 常见原因:缺少
40301:禁止访问- 常见原因:来源 IP 未命中已配置白名单
40401:资源不存在42201:请求参数错误50000:系统异常
时间字段格式约定
- 当前已上线的余额、国家、运营商、商品接口未返回时间字段。
- 后续若返回时间,统一使用 ISO 8601 格式,例如:
2026-03-17T08:30:00Z
订单号唯一性说明
- 下单接口使用
agent_order_id作为代理侧业务单号。 - 固定约束:
agent_order_id由代理系统生成- 同一代理下必须唯一
- 只要同一代理重复提交相同
agent_order_id,服务端都会返回冲突错误
鉴权说明
- Header 名称:
X-API-Key - Header 示例:
X-API-Key: agt_xxxxxxxxxxxxxxxxxxxx
- 白名单 IP 规则:
- 若未配置白名单,合法
X-API-Key可直接访问 - 若已配置白名单,只允许白名单中的出口 IP 访问
- 如代理服务器存在多个出口 IP,需全部加入白名单
- 若未配置白名单,合法
接口列表
- 获取代理账户余额
接口信息
- 方法:
GET - 路径:
/openapi/agent/balance - 描述:查询当前代理账户可用余额
- 鉴权:需要
X-API-Key - 请求体:无
请求头
X-API-Key: <your_api_key>Accept: application/json
成功响应
{
"code": 0,
"message": "",
"data": {
"balance": 1250.5
}
}
成功字段说明
data.balance- 类型:
number - 含义:当前代理账户可用余额
- 类型:
失败示例 1:缺少 API Key
{
"code": 40101,
"message": "缺少 api_key",
"data": {}
}
失败示例 2:API Key 无效
{
"code": 40101,
"message": "无效的 api_key",
"data": {}
}
失败示例 3:IP 未在白名单中
{
"code": 40301,
"message": "IP 未在白名单中",
"data": {}
}
curl
curl --request GET \
--url 'https://api.example.com/openapi/agent/balance' \
--header 'Accept: application/json' \
--header 'X-API-Key: agt_xxxxxxxxxxxxxxxxxxxx'
JavaScript
async function getAgentBalance() {
const response = await fetch("https://api.example.com/openapi/agent/balance", {
method: "GET",
headers: {
Accept: "application/json",
"X-API-Key": "agt_xxxxxxxxxxxxxxxxxxxx",
},
});
const result = await response.json();
if (result.code !== 0) {
throw new Error(result.message || "request failed");
}
return result.data.balance;
}
Python
import requests
def get_agent_balance():
response = requests.get(
"https://api.example.com/openapi/agent/balance",
headers={
"Accept": "application/json",
"X-API-Key": "agt_xxxxxxxxxxxxxxxxxxxx",
},
timeout=10,
)
result = response.json()
if result["code"] != 0:
raise RuntimeError(result["message"])
return result["data"]["balance"]
- 获取国家列表
接口信息
- 方法:
GET - 路径:
/openapi/agent/countries - 描述:返回当前可售国家列表
- 鉴权:需要
X-API-Key - 请求体:无
请求头
X-API-Key: <your_api_key>Accept: application/json
成功响应
{
"code": 0,
"message": "",
"data": [
{
"country_iso": "US",
"name_cn": "美国",
"name_en": "United States",
"area_code": "+1",
"flag_url": "https://api.example.com/static/flags/US.svg"
}
]
}
成功字段说明
data[].country_iso- 类型:
string - 含义:国家 ISO 编码
- 类型:
data[].name_cn- 类型:
string - 含义:国家中文名
- 类型:
data[].name_en- 类型:
string - 含义:国家英文名
- 类型:
data[].area_code- 类型:
string | null - 含义:国家区号
- 类型:
data[].flag_url- 类型:
string | null - 含义:国家旗帜图片地址
- 类型:
curl
curl --request GET \
--url 'https://api.example.com/openapi/agent/countries' \
--header 'Accept: application/json' \
--header 'X-API-Key: agt_xxxxxxxxxxxxxxxxxxxx'
JavaScript
async function getCountries() {
const response = await fetch("https://api.example.com/openapi/agent/countries", {
method: "GET",
headers: {
Accept: "application/json",
"X-API-Key": "agt_xxxxxxxxxxxxxxxxxxxx",
},
});
const result = await response.json();
if (result.code !== 0) {
throw new Error(result.message || "request failed");
}
return result.data;
}
Python
import requests
def get_countries():
response = requests.get(
"https://api.example.com/openapi/agent/countries",
headers={
"Accept": "application/json",
"X-API-Key": "agt_xxxxxxxxxxxxxxxxxxxx",
},
timeout=10,
)
result = response.json()
if result["code"] != 0:
raise RuntimeError(result["message"])
return result["data"]
- 获取运营商列表
接口信息
- 方法:
GET - 路径:
/openapi/agent/operators - 描述:根据国家代码返回该国家下可用运营商列表
- 鉴权:需要
X-API-Key - 请求体:无
查询参数
country_iso- 类型:
string - 必填:是
- 长度:
2-16 - 含义:国家 ISO 编码,例如
US
- 类型:
请求头
X-API-Key: <your_api_key>Accept: application/json
成功响应
{
"code": 0,
"message": "",
"data": [
{
"operator_code": "att",
"country_iso": "US",
"name_cn": "AT&T",
"name_en": "AT&T",
"imgurl": "https://api.example.com/static/operators/att.png"
}
]
}
成功字段说明
data[].operator_code- 类型:
string - 含义:运营商编码
- 类型:
data[].country_iso- 类型:
string - 含义:所属国家 ISO 编码
- 类型:
data[].name_cn- 类型:
string - 含义:运营商中文名
- 类型:
data[].name_en- 类型:
string - 含义:运营商英文名
- 类型:
data[].imgurl- 类型:
string | null - 含义:运营商图片地址
- 类型:
失败示例:缺少必填参数
{
"code": 42201,
"message": "请求参数错误",
"data": {}
}
curl
curl --request GET \
--url 'https://api.example.com/openapi/agent/operators?country_iso=US' \
--header 'Accept: application/json' \
--header 'X-API-Key: agt_xxxxxxxxxxxxxxxxxxxx'
JavaScript
async function getOperators(countryIso) {
const url = new URL("https://api.example.com/openapi/agent/operators");
url.searchParams.set("country_iso", countryIso);
const response = await fetch(url.toString(), {
method: "GET",
headers: {
Accept: "application/json",
"X-API-Key": "agt_xxxxxxxxxxxxxxxxxxxx",
},
});
const result = await response.json();
if (result.code !== 0) {
throw new Error(result.message || "request failed");
}
return result.data;
}
Python
import requests
def get_operators(country_iso: str):
response = requests.get(
"https://api.example.com/openapi/agent/operators",
params={"country_iso": country_iso},
headers={
"Accept": "application/json",
"X-API-Key": "agt_xxxxxxxxxxxxxxxxxxxx",
},
timeout=10,
)
result = response.json()
if result["code"] != 0:
raise RuntimeError(result["message"])
return result["data"]
- 获取商品列表
接口信息
- 方法:
GET - 路径:
/openapi/agent/products - 描述:根据国家和可选运营商条件返回代理可下单商品列表
- 鉴权:需要
X-API-Key - 请求体:无
查询参数
country_iso- 类型:
string - 必填:是
- 长度:
2-16 - 含义:国家 ISO 编码,例如
US
- 类型:
operator_code- 类型:
string - 必填:否
- 长度:
1-64 - 含义:运营商编码;不传时返回该国家全部在售商品
- 类型:
请求头
X-API-Key: <your_api_key>Accept: application/json
成功响应
{
"code": 0,
"message": "",
"data": [
{
"product_code": "us-att-10",
"country_iso": "US",
"operator_code": "att",
"name_cn": "美国 AT&T 10美金",
"name_en": "US AT&T 10 USD",
"product_type": "balance",
"price": 9.0,
"valid_days": 30,
"badge": "热卖",
"badge_en": "Hot"
}
]
}
成功字段说明
data[].product_code- 类型:
string - 含义:商品编码,后续下单接口将使用该字段
- 类型:
data[].country_iso- 类型:
string - 含义:国家 ISO 编码
- 类型:
data[].operator_code- 类型:
string | null - 含义:运营商编码;通用商品可能为
null
- 类型:
data[].name_cn- 类型:
string - 含义:商品中文名
- 类型:
data[].name_en- 类型:
string - 含义:商品英文名
- 类型:
data[].product_type- 类型:
string - 含义:商品类型,例如
balance、data、card
- 类型:
data[].price- 类型:
number - 含义:代理成交价
- 类型:
data[].valid_days- 类型:
integer | null - 含义:有效期天数
- 类型:
data[].badge- 类型:
string | null - 含义:商品中文标识
- 类型:
data[].badge_en- 类型:
string | null - 含义:商品英文标识
- 类型:
失败示例:缺少必填参数
{
"code": 42201,
"message": "请求参数错误",
"data": {}
}
curl
curl --request GET \
--url 'https://api.example.com/openapi/agent/products?country_iso=US&operator_code=att' \
--header 'Accept: application/json' \
--header 'X-API-Key: agt_xxxxxxxxxxxxxxxxxxxx'
JavaScript
async function getProducts(countryIso, operatorCode) {
const url = new URL("https://api.example.com/openapi/agent/products");
url.searchParams.set("country_iso", countryIso);
if (operatorCode) {
url.searchParams.set("operator_code", operatorCode);
}
const response = await fetch(url.toString(), {
method: "GET",
headers: {
Accept: "application/json",
"X-API-Key": "agt_xxxxxxxxxxxxxxxxxxxx",
},
});
const result = await response.json();
if (result.code !== 0) {
throw new Error(result.message || "request failed");
}
return result.data;
}
Python
import requests
def get_products(country_iso: str, operator_code: str | None = None):
params = {"country_iso": country_iso}
if operator_code:
params["operator_code"] = operator_code
response = requests.get(
"https://api.example.com/openapi/agent/products",
params=params,
headers={
"Accept": "application/json",
"X-API-Key": "agt_xxxxxxxxxxxxxxxxxxxx",
},
timeout=10,
)
result = response.json()
if result["code"] != 0:
raise RuntimeError(result["message"])
return result["data"]
- 代理下单
接口信息
- 方法:
POST - 路径:
/openapi/agent/orders - 描述:创建代理余额支付订单,并自动进入充值流程
- 鉴权:需要
X-API-Key - Content-Type:
application/json
请求体
agent_order_id- 类型:
string - 必填:是
- 长度:
1-64 - 含义:代理侧业务订单号,用于唯一性控制
- 类型:
product_code- 类型:
string - 必填:是
- 长度:
1-64 - 含义:商品编码
- 类型:
phone- 类型:
string | null - 必填:条件必填
- 长度:最大
32 - 含义:手机号;当商品类型不是
card时必须传
- 类型:
请求示例
{
"agent_order_id": "AGT-20260317-0001",
"product_code": "LA_UNITEL_5000",
"phone": "8562099810363"
}
成功响应
{
"code": 0,
"message": "",
"data": {
"agent_order_id": "AGT-20260317-0001",
"order_id": "202603170000000003",
"status": "processing",
"actual_amount": 9.0
}
}
成功字段说明
data.agent_order_id- 类型:
string - 含义:代理侧业务订单号
- 类型:
data.order_id- 类型:
string - 含义:平台订单号
- 类型:
data.status- 类型:
string - 含义:当前订单状态;当前接口正常创建后通常为
processing
- 类型:
data.actual_amount- 类型:
number - 含义:本次实际扣款金额
- 类型:
业务单号规则
- 若同一代理重复提交相同的
agent_order_id,服务端直接返回冲突错误。 - 服务端不会复用或返回旧订单数据,请代理侧自行保证
agent_order_id唯一。
常见失败场景
- 商品不存在或未在售:
40401 - 余额不足:
40000 - 非卡密商品未传手机号:
40000 agent_order_id重复:40901
失败示例:余额不足
{
"code": 40000,
"message": "余额不足",
"data": {}
}
失败示例:重复业务单号冲突
{
"code": 40901,
"message": "订单号重复",
"data": {}
}
curl
curl --request POST \
--url 'https://api.example.com/openapi/agent/orders' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: agt_xxxxxxxxxxxxxxxxxxxx' \
--data '{
"agent_order_id": "AGT-20260317-0001",
"product_code": "us-att-10",
"phone": "1234567890"
}'
JavaScript
async function createAgentOrder(payload) {
const response = await fetch("https://api.example.com/openapi/agent/orders", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"X-API-Key": "agt_xxxxxxxxxxxxxxxxxxxx",
},
body: JSON.stringify(payload),
});
const result = await response.json();
if (result.code !== 0) {
throw new Error(result.message || "request failed");
}
return result.data;
}
Python
import requests
def create_agent_order():
response = requests.post(
"https://api.example.com/openapi/agent/orders",
headers={
"Accept": "application/json",
"Content-Type": "application/json",
"X-API-Key": "agt_xxxxxxxxxxxxxxxxxxxx",
},
json={
"agent_order_id": "AGT-20260317-0001",
"product_code": "us-att-10",
"phone": "1234567890",
},
timeout=10,
)
result = response.json()
if result["code"] != 0:
raise RuntimeError(result["message"])
return result["data"]
- 查询订单状态
接口信息
- 方法:
GET - 路径:
/openapi/agent/orders/{agent_order_id} - 描述:根据代理侧业务订单号查询订单状态与结果
- 鉴权:需要
X-API-Key - 请求体:无
路径参数
agent_order_id- 类型:
string - 必填:是
- 长度:
1-64 - 含义:代理侧业务订单号
- 类型:
请求头
X-API-Key: <your_api_key>Accept: application/json
成功响应
{
"code": 0,
"message": "",
"data": {
"agent_order_id": "AGT-20260317-0001",
"order_id": "202603170000000003",
"status": "success",
"product_code": "us-att-10",
"quantity": 1,
"phone": "1234567890",
"actual_amount": 9.0,
"remark": "充值成功",
"remark_en": "Recharge succeeded",
"created_at": "2026-03-17T08:30:00Z"
}
}
成功字段说明
data.agent_order_id- 类型:
string - 含义:代理侧业务订单号
- 类型:
data.order_id- 类型:
string - 含义:平台订单号
- 类型:
data.status- 类型:
string - 含义:订单状态,可能值包括
processing、success、failed、refunding、refunded
- 类型:
data.product_code- 类型:
string | null - 含义:商品编码
- 类型:
data.quantity- 类型:
integer - 含义:下单数量;当前代理下单接口固定为
1
- 类型:
data.phone- 类型:
string - 含义:下单手机号
- 类型:
data.actual_amount- 类型:
number - 含义:实际扣款金额
- 类型:
data.remark- 类型:
string | null - 含义:中文备注,例如失败原因或处理说明
- 类型:
data.remark_en- 类型:
string | null - 含义:英文备注
- 类型:
data.created_at- 类型:
string - 含义:订单创建时间,ISO 8601 格式
- 类型:
注意事项
- 本接口按代理账号维度查询,只能查询当前
X-API-Key对应代理账号自己的订单。
失败示例:订单不存在
{
"code": 40401,
"message": "订单不存在",
"data": {}
}
curl
curl --request GET \
--url 'https://api.example.com/openapi/agent/orders/AGT-20260317-0001' \
--header 'Accept: application/json' \
--header 'X-API-Key: agt_xxxxxxxxxxxxxxxxxxxx'
JavaScript
async function getAgentOrder(agentOrderId) {
const response = await fetch(`https://api.example.com/openapi/agent/orders/${encodeURIComponent(agentOrderId)}`, {
method: "GET",
headers: {
Accept: "application/json",
"X-API-Key": "agt_xxxxxxxxxxxxxxxxxxxx",
},
});
const result = await response.json();
if (result.code !== 0) {
throw new Error(result.message || "request failed");
}
return result.data;
}
Python
import requests
def get_agent_order(agent_order_id: str):
response = requests.get(
f"https://api.example.com/openapi/agent/orders/{agent_order_id}",
headers={
"Accept": "application/json",
"X-API-Key": "agt_xxxxxxxxxxxxxxxxxxxx",
},
timeout=10,
)
result = response.json()
if result["code"] != 0:
raise RuntimeError(result["message"])
return result["data"]
对接建议
- 代理服务端应把
X-API-Key保存在服务端安全配置中,不要暴露到浏览器前端。 - 若启用了白名单,请在部署切换或扩容前确认出口 IP 是否变化。
- 建议调用方同时记录:
- HTTP 状态码
- 响应体
code - 响应体
message
- 状态回调通知
能力说明
- 方向:平台主动回调代理系统
- 方法:
POST - 回调地址:代理账号配置的固定
callback_url - Content-Type:
application/json - 触发时机:当代理订单状态发生结果性变化时,平台会主动推送最新状态
- 当前实现会在以下场景触发回调:
- 充值成功后状态变为
success - 充值失败并已原路退回余额后状态变为
refunded - 退款处理中时状态变为
refunding
- 充值成功后状态变为
回调请求头
Content-Type: application/jsonAccept: application/jsonX-Callback-Timestamp: <unix_timestamp_seconds>X-Callback-Signature: <hmac_sha256_hex>
回调请求体
agent_order_id- 类型:
string - 含义:代理侧业务订单号
- 类型:
order_id- 类型:
string - 含义:平台订单号
- 类型:
status- 类型:
string - 含义:最新订单状态
- 类型:
product_code- 类型:
string | null - 含义:商品编码
- 类型:
phone- 类型:
string - 含义:下单手机号
- 类型:
quantity- 类型:
integer - 含义:下单数量
- 类型:
actual_amount- 类型:
number - 含义:实际扣款金额
- 类型:
remark- 类型:
string | null - 含义:中文备注
- 类型:
remark_en- 类型:
string | null - 含义:英文备注
- 类型:
callback_time- 类型:
string - 含义:本次回调发起时间,ISO 8601 格式
- 类型:
回调示例
POST /agent/callback HTTP/1.1
Content-Type: application/json
Accept: application/json
X-Callback-Timestamp: 1773741600
X-Callback-Signature: 0f28d97b5d5d88e23bb9a5b6a8ce0d760dc8d2f5c44a6d9ac7e5705f0f3b4f6f
{
"agent_order_id": "AGT-20260317-0001",
"order_id": "202603170000000003",
"status": "success",
"product_code": "us-att-10",
"phone": "1234567890",
"quantity": 1,
"actual_amount": 9.0,
"remark": "充值成功",
"remark_en": "Recharge succeeded",
"callback_time": "2026-03-17T10:00:00Z"
}
签名算法
X-Callback-Signature = HMAC_SHA256_HEX(api_key, "timestamp.raw_body")- 其中:
timestamp为X-Callback-Timestamp头中的秒级 Unix 时间戳raw_body为回调请求体原始字节串api_key为该代理账号自己的X-API-Key
签名示例
timestamp = 1773741600
raw_body = {"agent_order_id":"AGT-20260317-0001","order_id":"202603170000000003","status":"success","product_code":"us-att-10","phone":"1234567890","quantity":1,"actual_amount":9.0,"remark":"充值成功","remark_en":"Recharge succeeded","callback_time":"2026-03-17T10:00:00Z"}
signing_text = "1773741600." + raw_body
signature = HMAC_SHA256_HEX(api_key, signing_text)
Python 验签示例
import hashlib
import hmac
def verify_callback(api_key: str, timestamp: str, raw_body: bytes, signature: str) -> bool:
expected = hmac.new(
api_key.encode("utf-8"),
timestamp.encode("utf-8") + b"." + raw_body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, signature)
JavaScript 验签示例
import crypto from "node:crypto";
function verifyCallback(apiKey, timestamp, rawBody, signature) {
const expected = crypto
.createHmac("sha256", apiKey)
.update(`${timestamp}.`)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
对接要求
- 代理回调地址必须可被平台服务访问,且建议使用 HTTPS。
- 代理服务端收到回调后,应先使用原始请求体做签名校验,再处理业务逻辑。
- 代理回调接口只要处理成功,就应返回任意
2xxHTTP 状态码。
重试规则
- 若代理回调接口返回非
2xx,或请求超时、网络异常,平台会自动重试。 - 当前默认重试参数为:
- 最大尝试次数:
5 - 单次请求超时:
10秒 - 相邻两次重试间隔:
3秒
- 最大尝试次数:
- 如代理已成功处理回调但响应异常,需保证自身按
agent_order_id做幂等处理。
变更说明
- 本文档当前版本已覆盖余额、国家、运营商、商品、下单、查单、状态回调和共享接入规范。