单项权益分销系统 · 开放 API

版本 v1 更新 2026-02-02 基础路径 /api/open/v1 通过 API 网关调用

概述

接口规范

  • 协议:HTTPS
  • 请求格式:JSON(Content-Type: application/json)
  • 响应格式:JSON
  • 字符编码:UTF-8
  • 时间格式:YYYY-MM-DD HH:mm:ss

通用响应结构

{
  "code": 0,
  "message": "success",
  "data": { ... },
  "timestamp": 1704355200
}
字段类型说明
codeint状态码,0 表示成功,非 0 表示失败
messagestring状态描述
dataobject业务数据
timestampint响应时间戳

错误码定义

错误码说明处理建议
0成功
1001参数错误检查请求参数
1002数据不存在检查资源是否存在
1003重复操作幂等处理,可忽略
1006未授权检查 AppId 和签名
1007禁止访问账户可能被停用
2001余额不足提醒用户充值
2002超过限量次日重试或联系客服
3001商品不存在检查商品编码
3002商品已下架选择其他商品
3003商品缺货稍后重试
4001订单不存在检查订单号
4002订单重复幂等处理,返回原订单
5001系统错误联系技术支持

对接前需准备的信息

外部分销商接入开放 API 前,双方需交换以下信息,以便完成网关授权与联调。

分销商需向 vipsys 提供

项目说明
公司/主体名称用于开通分销商账号
技术联系人姓名、邮箱、手机,用于接口联调与问题排查
回调通知地址(notify_url)订单状态变更时的 HTTP POST 接收地址,需可公网访问;若暂不确定,可先使用默认或后续在请求中按单传递
IP 白名单地址调用方的发起调用的服务器 IP,用于加入白名单,在 IP 白名单内,方可调用相关接口
业务说明(可选)接入场景、预估量级等,便于配置限流与支持

vipsys 将向分销商提供

项目说明
API 网关地址调用入口 Base URL,所有接口均通过该地址访问
AppId(x-ca-key)网关 APP Key,作为请求头 x-ca-key 传递
AppSecret网关 APP Secret,用于计算摘要签名,请妥善保管、勿泄露
商品编码表或商品列表接口说明可供采购的商品及 product_code,用于创建订单时填写

完成上述信息对接并完成网关授权后,即可按本文档「鉴权说明」与「接口列表」进行开发与联调。

以上信息会发送至调用方对接人邮箱。

鉴权说明

分销商仅通过阿里云 API 网关调用开放 API:请求先经网关(安全认证类型为「阿里云 APP」)校验签名,通过后再转发至业务后端。请勿直连业务后端。

参考文档:使用摘要签名认证方式调用 API - 阿里云

请求头(必传)

Header必填说明
x-ca-keyAPP Key,即分销商 AppId
X-Ca-Signature对签名串做 HmacSHA256/HmacSHA1 后 Base64
x-ca-signature-methodHmacSHA256 或 HmacSHA1,默认 HmacSHA256
X-Ca-Signature-Headers参与签名的 Header 的 Key,英文逗号分隔
Accept建议建议显式设置,如 application/json;为空时部分客户端会填 */* 导致验签失败
Content-Type按需如 application/json
Content-MD5按需有 Body 且非 Form 时可传 Body 的 MD5 的 Base64
Date按需HTTP 标准 Date 头

网关签名串(StringToSign)格式

签名串由以下 7 个字段用换行符 \n拼接,字段为空也保留 \n,大小写敏感:

HTTPMethod
Accept
Content-MD5
Content-Type
Date
Headers
PathAndParameters

计算签名

  1. 按上述规则拼出 StringToSign(UTF-8)。
  2. 使用 APP Secret 对 StringToSign 做 HmacSHA256(或 HmacSHA1)。
  3. 将结果做 Base64 编码,即为 X-Ca-Signature 的值。

签名示例(供对照验算)

以下为 GET /api/open/v1/balance、无 Query、无参与签名的自定义头时的示例。

项目取值
HTTPMethodGET
Acceptapplication/json
Content-MD5(空)
Content-Type(空)
Date(空)
Headers(无自定义头,空)
PathAndParameters/api/open/v1/balance
AppSecret(示例)test_secret_123

StringToSign(共 7 行,第 3~6 行为空行):

GET
application/json



/api/open/v1/balance

计算步骤:使用 AppSecret test_secret_123 对上述 StringToSign(UTF-8 编码)做 HmacSHA256,再对二进制结果做 Base64 编码。

得到的 X-Ca-Signature 示例值:

+UA1tPK41ggA7Ufd6SEHW9rITTnahv50U5OggO7h+Fc=
说明:上述签名为基于示例 AppSecret 计算所得,仅供格式与算法对照;实际调用请使用 vipsys 分配的网关 AppId 与 AppSecret,并在网关控制台配置一致的安全认证方式。

Java 签名示例代码

以下为阿里云 API 网关摘要签名(HmacSHA256 + Base64)的 Java 实现示例,可直接用于生成请求头 X-Ca-Signature

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

public class ApiGatewaySign {

    /**
     * 生成 X-Ca-Signature 头
     *
     * @param method       HTTP 方法,如 GET、POST(大写)
     * @param path         路径,如 /api/open/v1/balance
     * @param queryParams  Query 参数,Key 会按字典序参与 PathAndParameters;可为 null
     * @param headersForSign 参与签名的自定义头,Key 会按字典序参与 Headers 段;可为 null
     * @param accept       Accept 头
     * @param contentMd5B64 Content-MD5 的 Base64,无 Body 时传空字符串
     * @param contentType  Content-Type,无 Body 时传空字符串
     * @param date         Date 头,可不传时传空字符串
     * @param appSecret    网关 AppSecret
     * @return Base64 编码的签名,即 X-Ca-Signature 的值
     */
    public static String sign(String method,
                             String path,
                             Map<String, String> queryParams,
                             Map<String, String> headersForSign,
                             String accept,
                             String contentMd5B64,
                             String contentType,
                             String date,
                             String appSecret) throws Exception {
        // PathAndParameters
        String pathAndParams = path;
        if (queryParams != null && !queryParams.isEmpty()) {
            String query = new TreeMap<>(queryParams).entrySet().stream()
                    .filter(e -> e.getValue() != null && !e.getValue().isEmpty())
                    .map(e -> e.getKey() + "=" + e.getValue())
                    .collect(Collectors.joining("&"));
            if (!query.isEmpty()) {
                pathAndParams = path + "?" + query;
            }
        }

        // Headers 段:参与签名的头按 Key 字典序,格式 Key:Value\n
        StringBuilder headersSb = new StringBuilder();
        if (headersForSign != null && !headersForSign.isEmpty()) {
            for (Map.Entry<String, String> e : new TreeMap<>(headersForSign).entrySet()) {
                headersSb.append(e.getKey()).append(":").append(e.getValue() != null ? e.getValue() : "").append("\n");
            }
        }

        String stringToSign =
                (method != null ? method.toUpperCase() : "") + "\n"
                        + (accept != null ? accept : "") + "\n"
                        + (contentMd5B64 != null ? contentMd5B64 : "") + "\n"
                        + (contentType != null ? contentType : "") + "\n"
                        + (date != null ? date : "") + "\n"
                        + headersSb
                        + pathAndParams;

        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(appSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signBytes = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(signBytes);
    }

    // 示例:GET /api/open/v1/balance,无 Query、无自定义头
    public static void main(String[] args) throws Exception {
        String signature = sign(
                "GET",
                "/api/open/v1/balance",
                null,
                null,
                "application/json",
                "",
                "",
                "",
                "test_secret_123"
        );
        System.out.println("X-Ca-Signature: " + signature);
        // 输出应与文档示例一致: +UA1tPK41ggA7Ufd6SEHW9rITTnahv50U5OggO7h+Fc=
    }
}

调用示例(GET 余额):

String xCaSignature = ApiGatewaySign.sign(
    "GET",
    "/api/open/v1/balance",
    null,           // 无 Query
    null,           // 无参与签名的自定义头
    "application/json",
    "",
    "",
    "",
    "your_app_secret"
);
// 请求头: x-ca-key: your_app_id, X-Ca-Signature: xCaSignature, Accept: application/json

POST 带 Body 时,若网关要求对 Body 做 Content-MD5,可先对 Body 的 UTF-8 字节做 MD5 再 Base64,再传入 contentMd5B64path 仍为路径不含 Query,如 /api/open/v1/orders

时间戳与防重放

网关侧可配置时间戳、Nonce 等防重放策略,具体以阿里云控制台为准。

接口列表

POST /api/open/v1/orders

1. 创建订单

创建充值订单,系统自动发起发货。

请求参数(Body)

参数类型必填说明
merchant_order_nostring分销商订单号,需保证唯一,最长 64 字符
product_codestring平台商品编码
recharge_accountstring充值账号(手机号/QQ号等)
notify_urlstring回调通知地址,不传则使用默认配置

请求示例(通过 API 网关)

curl -X POST "https://your-gateway.aliyuncs.com/api/open/v1/orders" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "x-ca-key: your_app_id" \
  -H "X-Ca-Signature: your_computed_signature" \
  -d '{
    "merchant_order_no": "M20260104001",
    "product_code": "HF-100-0001",
    "recharge_account": "13800138000"
  }'
请求头中的 X-Ca-Signature 需按「鉴权说明」中的阿里云摘要签名规则计算;x-ca-key 为 vipsys 分配的 AppId。网关地址以 vipsys 提供的为准。

响应参数

参数类型说明
order_nostring平台订单号
merchant_order_nostring分销商订单号
product_codestring商品编码
product_namestring商品名称
face_valuestring面值
amountstring订单金额(扣款金额)
recharge_accountstring充值账号
order_statusstring订单状态文本
order_status_codeint订单状态码
delivery_statusstring发货状态文本
delivery_status_codeint发货状态码
create_timestring创建时间

响应示例

{
    "code": 0,
    "message": "订单创建成功",
    "data": {
        "order_no": "ORDER-20260104-A1B2C3D4",
        "merchant_order_no": "M20260104001",
        "product_code": "HF-100-0001",
        "product_name": "话费充值100元",
        "face_value": "100.00",
        "amount": "95.00",
        "recharge_account": "13800138000",
        "order_status": "PAID",
        "order_status_code": 2,
        "delivery_status": "WAITING",
        "delivery_status_code": 0,
        "create_time": "2026-01-04 10:00:00",
        "complete_time": null,
        "refund_reason": null
    },
    "timestamp": 1704355200
}

幂等性:相同 merchant_order_no 重复提交,返回原订单信息;不会重复扣款。

GET /api/open/v1/orders/{order_no}

2. 查询订单(平台订单号)

通过平台订单号查询订单详情。

路径参数

参数类型必填说明
order_nostring平台订单号

请求示例(通过 API 网关)

curl -X GET "https://your-gateway.aliyuncs.com/api/open/v1/orders/ORDER-20260104-A1B2C3D4" \
  -H "Accept: application/json" \
  -H "x-ca-key: your_app_id" \
  -H "X-Ca-Signature: your_computed_signature"

响应参数:同「创建订单」响应参数。

GET /api/open/v1/orders?merchant_order_no={merchant_order_no}

3. 查询订单(分销商订单号)

通过分销商订单号查询订单详情。

查询参数

参数类型必填说明
merchant_order_nostring分销商订单号

请求示例(通过 API 网关)

curl -X GET "https://your-gateway.aliyuncs.com/api/open/v1/orders?merchant_order_no=M20260104001" \
  -H "Accept: application/json" \
  -H "x-ca-key: your_app_id" \
  -H "X-Ca-Signature: your_computed_signature"

响应参数:同「创建订单」响应参数。

GET /api/open/v1/balance

4. 查询余额

查询当前账户余额信息。

请求示例(通过 API 网关)

curl -X GET "https://your-gateway.aliyuncs.com/api/open/v1/balance" \
  -H "Accept: application/json" \
  -H "x-ca-key: your_app_id" \
  -H "X-Ca-Signature: your_computed_signature"

响应参数

参数类型说明
cash_balancestring现金余额
credit_limitstring授信额度
used_creditstring已用授信
available_creditstring可用授信
available_balancestring可用余额(现金+可用授信)
frozen_amountstring冻结金额

响应示例

{
    "code": 0,
    "message": "success",
    "data": {
        "cash_balance": "10000.00",
        "credit_limit": "5000.00",
        "used_credit": "1000.00",
        "available_credit": "4000.00",
        "available_balance": "14000.00",
        "frozen_amount": "0.00"
    },
    "timestamp": 1704355200
}
GET /api/open/v1/products

5. 查询商品列表

查询当前可用的商品列表。

查询参数

参数类型必填说明
pageint页码,默认 1
page_sizeint每页数量,默认 20,最大 100

请求示例(通过 API 网关)

curl -X GET "https://your-gateway.aliyuncs.com/api/open/v1/products?page=1&page_size=20" \
  -H "Accept: application/json" \
  -H "x-ca-key: your_app_id" \
  -H "X-Ca-Signature: your_computed_signature"

响应参数

参数类型说明
listarray商品列表
list[].product_codestring商品编码
list[].product_namestring商品名称
list[].categorystring商品分类(部分商品可能为 null)
list[].face_valuestring面值
list[].supply_pricestring供货价(您的采购价)
list[].delivery_typeint发货类型:1=直充,2=券码
list[].recharge_account_typeint充值账号类型
list[].stock_statusint库存状态:1=有货,2=缺货
list[].daily_limitint日限量(null=不限)
list[].daily_remainingint今日剩余(null=不限)
paginationobject分页信息

说明:仅返回「分销商已启用」且「平台商品已上架」的商品。

响应示例

{
    "code": 0,
    "message": "success",
    "data": {
        "list": [
            {
                "product_code": "HF-100-0001",
                "product_name": "话费充值100元",
                "category": "话费充值",
                "face_value": "100.00",
                "supply_price": "95.00",
                "delivery_type": 1,
                "recharge_account_type": 2,
                "stock_status": 1,
                "daily_limit": 1000,
                "daily_remaining": 800
            }
        ],
        "pagination": {
            "total": 50,
            "page": 1,
            "page_size": 20,
            "total_pages": 3
        }
    },
    "timestamp": 1704355200
}

回调通知

订单状态变更时,系统会向 notify_url 发送 HTTP POST 请求。

回调请求

请求方式:POST · Content-Type:application/json

回调参数

参数类型说明
order_nostring平台订单号
merchant_order_nostring分销商订单号
order_statusstring订单状态
order_status_codeint订单状态码
delivery_statusstring发货状态
delivery_status_codeint发货状态码
complete_timestring完成时间(成功时返回)
refund_reasonstring退款原因(退款时返回)
timestampint回调时间戳
signstring回调签名

回调示例

{
    "order_no": "ORDER-20260104-A1B2C3D4",
    "merchant_order_no": "M20260104001",
    "order_status": "COMPLETED",
    "order_status_code": 5,
    "delivery_status": "SUCCESS",
    "delivery_status_code": 2,
    "complete_time": "2026-01-04 10:05:00",
    "refund_reason": null,
    "timestamp": 1704355500,
    "sign": "a1b2c3d4e5f6..."
}

回调签名验证

使用与请求签名相同的算法验证回调签名:

# 去掉 sign 参数后验证
params = {k: v for k, v in callback_data.items() if k != 'sign'}
expected_sign = generate_sign(params, app_secret)
is_valid = callback_data['sign'].lower() == expected_sign.lower()

响应要求

返回 JSON 格式:

{
    "code": 0,
    "message": "success"
}

重试机制

次数间隔
第1次1秒
第2次5秒
第3次30秒
第4次5分钟
第5次30分钟

最多重试 10 次,建议实现幂等处理。

状态码说明

订单状态(order_status)

状态码状态值说明
0PENDING待支付
1PAYING支付中
2PAID已支付
3PROCESSING处理中
4DELIVERED已发货
5COMPLETED已完成
6CANCELLED已取消
7REFUNDED已退款

发货状态(delivery_status)

状态码状态值说明
0WAITING待发货
1DELIVERING发货中
2SUCCESS已成功
3FAILED已失败

发货类型(delivery_type)

类型值说明
1直充
2券码

充值账号类型(recharge_account_type)

类型值说明
1平台账号
2手机号
3QQ号
4手机+QQ
5QQ+微信

最佳实践

1. 订单创建

2. 状态查询

3. 回调处理

4. 异常处理

技术支持

技术文档:https://docs.itbooster.cn

技术支持:itbooster@163.com

在线客服:工作时间 9:00-18:00