最后更新:2026-08-21
下载 Markdown

EasyCards VCC API 对接手册#

更新日期:2026-08-14

本文说明 EasyCards VCC API 的鉴权方式、调用顺序、资源状态和 Webhook 事件。字段类型、必填项和响应结构以 API 参考 为准;可执行请求以 Postman Collection 为准。

1. 接口环境#

环境 Base URL
沙箱 https://sandbox.easycards.io
生产 完成生产环境配置后在 EasyCards Portal 中获取

1.1 鉴权#

使用以下请求头:

Authorization: Bearer <PAYMENT_API_KEY>
Content-Type: application/json

1.2 权限#

权限 接口范围
payment.vcc.read 产品、客户、申请、卡片、余额、充值和交易查询
payment.vcc.customer.manage 创建或修改客户、上传私有文件
payment.vcc.card.create 提交开卡申请
payment.vcc.card.sensitive 获取加密卡敏感信息
payment.vcc.card.topup 提交卡充值
payment.vcc.card.withdraw 提交共享卡提现
payment.vcc.card.status 冻结和解冻卡片

2. 通用规则#

2.1 成功响应#

{
  "code": 0,
  "message": "OK",
  "data": {}
}

2.2 错误响应#

{
  "code": "VALIDATION_ERROR",
  "message": "One or more request fields are invalid.",
  "data": null
}

程序判断顺序:

  1. HTTP 状态码。
  2. 顶层 code
  3. 对应资源的状态字段。

2.3 状态字段#

资源 状态字段
客户 customer_status
开卡申请 application_status
卡片 card_status
充值 topup_status
共享卡提现 withdrawal_status
冻结、解冻响应 resource_status
交易 transaction_status

PENDING 为处理中,SUCCESSFAIL 为终态。卡片当前状态以 card_status 为准。

2.4 request_id#

所有写接口使用 request_id

  • 类型:字符串。
  • 长度:1–64 个字符。
  • 同一业务请求的重试使用相同 request_id 和相同参数。
  • 相同 request_id 配合不同参数时返回 IDEMPOTENCY_CONFLICT

示例:

merchant-customer-C202607280001
merchant-card-O202607280001
merchant-topup-T202607280001
merchant-withdrawal-W202608130001
merchant-freeze-F202607280001

2.5 金额与时间#

  • 金额字段使用字符串。
  • 金额响应保留两位小数。
  • 充值请求金额大于 0,最多两位小数。
  • 提现请求金额大于 0、最多两位小数,且不得超过共享卡当前未使用可用额度。
  • 币种使用大写代码。
  • 时间字段使用 Unix 秒级时间戳。

2.6 分页#

列表接口使用:

参数 默认值 范围
limit 20 1–200
offset 0 大于或等于 0

3. 账户#

账户接口使用与 VCC 接口相同的 Base URL 和 Bearer Token。账户余额是账户维度的资金余额,与单张卡片的余额不同。

3.1 查询当前账户#

GET /payment/account

请求不包含 Path、Query 或 Body 参数。成功响应的 data.account 包含:

字段 类型 说明
merchant_id string 商户标识
account_id string 当前账户标识
name string 账户名称
status string 账户状态
currencies array 支持的币种列表
default_currency string 默认币种
timezone string 账户时区
created_at / updated_at integer 创建 / 更新时间,Unix 秒

查看此接口的 API Reference →

3.2 查询账户余额#

GET /payment/balances

可选 Query 参数 currency 用于按币种筛选;不传时返回全部币种。响应的 data.balances 中每项包含:

字段 类型 说明
account_id string 账户标识
currency string 大写币种代码
currency_type string fiatcrypto
balance decimal 账户总余额
available decimal 可用余额
frozen decimal 冻结余额
updated_at integer 更新时间,Unix 秒

查看此接口的 API Reference →

3.3 查询入金记录#

GET /payment/deposits

请求参数:

字段 类型 必填 说明
currency string 币种筛选
network string 网络筛选
status string 入金状态筛选
start_at / end_at integer 开始 / 结束时间,Unix 秒
limit / offset integer 分页参数

响应的 data.deposits 为入金记录数组。每项包含 account_iddeposit_idcurrencynetworktxidamountstatusconfirmationsreferenceoccurred_atcreated_atdata.totaldata.total_pages 分别为总记录数和总页数。

查看此接口的 API Reference →

3.4 查询账本流水#

GET /payment/ledger

请求参数:

字段 类型 必填 说明
currency string 币种筛选
record_type string 业务记录类型筛选
start_at / end_at integer 开始 / 结束时间,Unix 秒
limit / offset integer 分页参数
sort_by string 排序字段
sort_order string 排序方向

响应的 data.entries 为账本流水数组。每项包含账户和流水标识、分录类型、业务类型、交易类型、业务记录类型、凭证字段、币种、变动金额、变动后余额、业务参考号和创建时间。data.totaldata.total_pages 分别为总记录数和总页数。

查看此接口的 API Reference →

4. 调用顺序#

4.1 开卡主流程#

图中实线表示同步 HTTP 请求或响应,虚线表示 EasyCards 主动发送的异步 Webhook 通知。PENDING 是同步响应中的业务状态,不代表 HTTP 请求仍未返回。

sequenceDiagram
    autonumber
    participant M as 商户系统
    participant E as EasyCards API

    Note over M,E: 阶段一:读取开卡要求
        M->>E: 查询可用产品及开卡要求 · GET /payment/vcc/products
        E->>M: [同步响应] product_code、card_mode、费用、限额、required_customer_fields

        opt 产品字段要求上传文件
            M->>E: 上传客户文件并取得文件标识 · POST /payment/vcc/files
            E->>M: [同步响应] file_id
        end

    Note over M,E: 阶段二:创建客户并提交开卡申请
        M->>E: 创建持卡人资料 · POST /payment/vcc/customers
        E->>M: [同步响应] customer_id、customer_status

        M->>E: 为客户提交开卡申请 · POST /payment/vcc/card-applications
        E->>M: [同步受理响应] application_id、application_status

    Note over M,E: 阶段三:接收状态通知并查询最终结果
        opt application_status = PENDING
            E-->>M: [异步通知] vcc.application.updated · 状态或 next_action 变化
        end

        M->>E: 查询开卡申请当前结果 · GET /payment/vcc/card-applications/{application_id}
        E->>M: [同步响应] application_status;成功时包含 card_id

        opt application_status = SUCCESS
            M->>E: 查询卡片状态与基本信息 · GET /payment/vcc/cards/{card_id}
            E->>M: [同步响应] card_status、卡片基本信息
        end

4.2 卡片后续操作#

充值、共享卡提现、冻结和解冻接口先同步返回受理结果;需要后续处理时,再通过对应 Webhook 通知状态变化。余额查询和敏感数据获取在当前 HTTP 请求内同步返回。

sequenceDiagram
    participant M as 商户系统
    participant E as EasyCards API

    opt 查询卡片资金信息
        M->>E: 查询单张卡片当前余额 · GET /payment/vcc/cards/{card_id}/balance
        E->>M: [同步响应] balance、available、frozen
    end

    opt 获取卡片敏感数据
        M->>E: 获取 RSA 加密卡数据 · POST /payment/vcc/cards/sensitive
        E->>M: [同步响应] encrypt_data
    end

    opt 卡片充值或共享卡额度调增
        M->>E: 通过统一充值接口提交金额 · POST /payment/vcc/cards/{card_id}/topups
        E->>M: [同步受理响应] topup_id、topup_status
        E-->>M: [异步通知] vcc.topup.updated · 充值状态变化
        M->>E: 查询充值当前结果 · GET /payment/vcc/topups/{topup_id}
        E->>M: [同步响应] topup_status、金额与费用
    end

    opt 撤回共享卡未使用额度
        M->>E: 提交共享卡提现 · POST /payment/vcc/cards/{card_id}/withdrawals
        E->>M: [同步受理响应] withdrawal_id、withdrawal_status
        E-->>M: [异步通知] vcc.withdrawal.updated · 提现状态变化
    end

    opt 冻结或解冻卡片
        M->>E: 提交卡片状态变更 · POST .../freeze 或 POST .../unfreeze
        E->>M: [同步受理响应] resource_status
        E-->>M: [异步通知] vcc.card.updated · 冻结或解冻终态
        M->>E: 查询卡片当前状态 · GET /payment/vcc/cards/{card_id}
        E->>M: [同步响应] card_status
    end

5. 产品#

5.1 查询可用产品#

GET /payment/vcc/products

权限:payment.vcc.read

请求参数:

位置 字段 类型 必填 说明
Query limit integer 最大返回记录数,默认 20,范围 1–200
Query offset integer 跳过的记录数,默认 0

响应中的 data.products 为产品数组,data.total 为符合条件的产品总数。每个产品包含:

字段 类型 说明
product_code string 产品代码,提交开卡申请时使用
product_name string 产品展示名称
card_form string 卡片形式:VIRTUALPHYSICAL
card_mode string 资金模式:PREPAID_CARD(预充值卡)或 BUDGET_CARD(共享卡)
settlement_currency string 大写结算币种代码
open_fee_amount string 开卡费,固定两位小数
kyc_fee_amount string KYC 费用,开卡成功时收取,固定两位小数
reversal_fee_amount string 每笔成功撤销交易的固定费用,固定两位小数
refund_fee_rate string 每笔成功退款的费率小数;0.01 表示 1%
cross_border_fee_rate string 确认跨境交易时收取的平台费率小数
three_ds_fee_amount string 每个唯一 3DS 挑战收取的固定费用,固定两位小数
platform_authorization_fee_amount string 每笔成功授权收取的平台固定费用,固定两位小数
initial_topup_amount string 开卡时预留的初始卡余额,固定两位小数
initial_topup_fee_amount string 初始充值手续费,固定两位小数
total_open_debit_amount string 开卡总扣款金额,固定两位小数
topup_fee_rate string 充值手续费率
min_topup_amount string 最低充值金额
max_topup_amount string 最高充值金额;0.00 表示未配置上限
required_customer_fields array 该产品要求的附加客户字段

required_customer_fields 中的字段定义:

字段 说明
field_name 提交到 additional_customer_data 的 Key
field_label 展示名称
value_type 字段值类型
field_hint 面向商户的输入提示
value_format 预期值格式
min_length / max_length 字符长度限制
accepted_values 可选值;提交其中的 value

card_mode 是资金路径的权威字段,商户应保存产品和卡详情返回的值:PREPAID_CARD 的主动充值从当前 API Key 所属账户钱包扣款;BUDGET_CARD 的主动充值表示共享卡额度调增,本金与费用走卡片绑定的共享账户。两种模式复用同一个充值接口、查询接口和 vcc.topup.updated 事件。

查看此接口的 API Reference →

6. 文件#

6.1 上传私有文件#

POST /payment/vcc/files
Content-Type: multipart/form-data

权限:payment.vcc.customer.manage

请求字段:

位置 字段 类型 必填 说明
Form Data file file JPG/JPEG、PNG 或 PDF;单个文件最大 2 MiB

成功响应的 data.file_id 是平台文件标识。产品要求文件类型的客户字段时,将该值提交到 additional_customer_data 对应的 field_name

{
  "code": 0,
  "message": "OK",
  "data": {
    "file_id": "file_0123456789abcdef"
  }
}

查看此接口的 API Reference →

7. 客户#

客户对象的主要字段:

字段 类型 说明
customer_id string 平台客户标识
first_name / last_name string 名字 / 姓氏
gender string malefemaleunknown
email string 电子邮箱
phone_country_code string 国际电话国家区号
mobile_number string 手机号,不包含国家区号
date_of_birth string 出生日期,格式 yyyy-MM-dd
city string 城市
state_or_province string 州或省
residence_country string 居住国家或地区代码
nationality string 国籍代码
street_address string 街道地址
postal_code string 邮政编码
customer_status string 客户状态
additional_customer_data object 产品要求的附加客户数据
created_at / updated_at integer 创建 / 更新时间,Unix 秒

7.1 创建客户#

POST /payment/vcc/customers

权限:payment.vcc.customer.manage

请求字段:

字段 类型 必填 说明
request_id string 本次创建请求的幂等标识
first_name string 客户名字
last_name string 客户姓氏
gender string malefemaleunknown
email string 客户电子邮箱
phone_country_code string 国际电话国家区号
mobile_number string 仅使用 ASCII 数字 0–9
date_of_birth string 格式 yyyy-MM-dd
city string 客户所在城市
state_or_province string 客户所在州或省
residence_country string 大写 ISO 3166-1 alpha-2 代码
nationality string 大写 ISO 3166-1 alpha-2 代码
street_address string Trim 后 2–40 个 ASCII 字符,正则:^[A-Za-z0-9 ]+$;仅允许英文字母、数字和普通半角空格,不允许任何连字符或其他符号
postal_code string 客户邮政编码
additional_customer_data object 按产品 required_customer_fields 提交的扩展字段

请求示例:

{
  "request_id": "merchant-customer-C202607280001",
  "first_name": "Alex",
  "last_name": "Chen",
  "gender": "male",
  "email": "alex.chen@example.com",
  "phone_country_code": "+86",
  "mobile_number": "13800138000",
  "date_of_birth": "1990-01-02",
  "city": "Shanghai",
  "state_or_province": "Shanghai",
  "residence_country": "CN",
  "nationality": "CN",
  "street_address": "100 Century Avenue",
  "postal_code": "200120",
  "additional_customer_data": {
    "id_type": "PASSPORT",
    "id_number": "TR1234567"
  }
}

成功响应返回 data.customer。保存其中的 customer_id;其余字段为已保存的客户资料和当前 customer_status

查看此接口的 API Reference →

7.2 查询客户列表#

GET /payment/vcc/customers?limit=20&offset=0

权限:payment.vcc.read

请求使用通用分页参数 limitoffset。响应字段:

字段 类型 说明
data.customers array 客户对象数组;列表响应不包含 additional_customer_data
data.total integer 客户总数

查看此接口的 API Reference →

7.3 查询客户详情#

GET /payment/vcc/customers/{customer_id}

权限:payment.vcc.read

Path 参数 customer_id 为必填的平台客户标识。响应的 data.customer 为客户对象;详情响应中的敏感附加值会被遮蔽,非敏感枚举值保留。

查看此接口的 API Reference →

7.4 修改客户#

PATCH /payment/vcc/customers/{customer_id}

权限:payment.vcc.customer.manage

Path 参数 customer_id 指定需要修改的客户。请求体提交新的 request_id 和完整客户资料;客户资料字段及格式与创建客户一致。additional_customer_data 用于新增或覆盖产品字段,枚举字段提交 accepted_values[].value

成功响应返回更新后的 data.customer,字段含义见本章“客户对象的主要字段”。

查看此接口的 API Reference →

8. 开卡申请#

8.1 提交申请#

POST /payment/vcc/card-applications

权限:payment.vcc.card.create

请求字段:

字段 类型 必填 说明
request_id string 本次开卡申请的幂等标识
customer_id string 已创建的平台客户标识
product_code string 产品查询接口返回的产品代码
{
  "request_id": "merchant-card-O202607280001",
  "customer_id": "cus_0123456789abcdef",
  "product_code": "1103"
}

成功响应的 data.application 包含:

字段 类型 说明
request_id string 请求中的幂等标识
application_id string 平台开卡申请标识
customer_id string 客户标识
product_code string 产品代码
application_status string PENDINGSUCCESSFAIL
created_at integer 创建时间,Unix 秒

查看此接口的 API Reference →

8.2 查询申请列表#

GET /payment/vcc/card-applications?limit=20&offset=0

权限:payment.vcc.read

请求使用通用分页参数。响应的 data.applications 为申请对象数组,data.total 为申请总数。每项包含申请标识、客户标识、产品代码、状态、金额、结果字段和时间字段。

查看此接口的 API Reference →

8.3 查询申请详情#

GET /payment/vcc/card-applications/{application_id}

权限:payment.vcc.read

Path 参数 application_id 为必填的平台开卡申请标识。响应的 data.application 主要字段:

字段 类型 说明
application_status string PENDINGSUCCESSFAIL
next_action object 待完成动作;没有待处理动作时为空
open_fee_amount string 开卡费金额快照
kyc_fee_amount string KYC 费用快照;仅开卡成功时收取
total_debit_amount string 总扣款金额快照
settlement_currency string 结算币种
card_id string 申请成功后生成的卡片标识
failure_code string 终态失败代码
failure_message string 终态失败信息
created_at / updated_at integer 创建 / 更新时间,Unix 秒

next_action.action_type 当前为 COMPLETE_LIVENESSADD_FUNDSADD_FUNDS 可包含 required_account_balancerequired_balance_currencyexpires_at

查看此接口的 API Reference →

9. 卡片#

卡片对象的主要字段:

字段 类型 说明
card_id string 平台卡片标识
customer_id string 客户标识
product_code string 产品代码
card_mode string 开卡时保存的资金模式:PREPAID_CARDBUDGET_CARD
masked_card_number string 脱敏卡号
last_four_digits string 卡号后四位
card_status string INACTIVEACTIVEFROZENCLOSED
settlement_currency string 卡片结算币种
accounting_currency string 开卡费用及共享账户账本扣款使用的账户币种;不适用时省略
created_at / updated_at integer 创建 / 更新时间,Unix 秒

后续充值和对账应以卡详情返回的 card_mode 快照为准,不要仅按产品名称或卡形式推断资金路径。

9.1 查询卡片列表#

GET /payment/vcc/cards?limit=20&offset=0

权限:payment.vcc.read

请求使用通用分页参数。响应的 data.cards 为卡片对象数组,data.total 为卡片总数。

查看此接口的 API Reference →

9.2 查询卡片详情#

GET /payment/vcc/cards/{card_id}

权限:payment.vcc.read

Path 参数 card_id 为必填的平台卡片标识。响应的 data.card 为卡片对象,字段含义见本章“卡片对象的主要字段”。

查看此接口的 API Reference →

9.3 查询卡片余额#

GET /payment/vcc/cards/{card_id}/balance

权限:payment.vcc.read

Path 参数 card_id 为必填的平台卡片标识。响应字段:

字段 类型 说明
data.card_id string 平台卡片标识
data.available_balance string 最近同步的可用余额,固定两位小数
data.balance_currency string 大写余额币种代码
data.accounting_currency string 共享账户账本扣款使用的账户币种;不适用时省略
data.updated_at integer 余额快照时间,Unix 秒

查看此接口的 API Reference →

9.4 获取敏感卡信息#

POST /payment/vcc/cards/sensitive

权限:payment.vcc.card.sensitive

请求字段:

字段 类型 必填 说明
card_id string 平台卡片标识
public_key string 可选的 Base64 编码 RSA-1024 X.509/SPKI 公钥 DER,不含 PEM 头尾和空白字符;商户后台已为当前 API Key 配置公钥时可以省略,省略后使用该配置
{
  "card_id": "card_0123456789abcdef"
}

如果请求中传入 public_key,仅本次请求使用该公钥覆盖 API Key 配置;否则使用商户后台为当前 API Key 保存的公钥。

成功响应的 data.encrypt_data 是 RSA-1024 加密后再进行 Base64 编码的敏感卡信息 JSON。使用对应的 PKCS#8 私钥和 PKCS#1 v1.5 填充解密后,JSON 包含 card_numberexpiry_datecvv

查看此接口的 API Reference →

10. 充值与共享卡提现#

同一个充值接口按卡详情中的 card_mode 自动选择业务路径:

card_mode 业务含义 本金与费用来源
PREPAID_CARD 向预充值卡主动充值 当前 API Key 所属账户钱包
BUDGET_CARD 调增共享卡可用额度 卡片绑定的共享账户

两种模式都返回相同的充值对象,并通过充值列表、详情和 vcc.topup.updated 确认终态。充值本金不会重复记为卡交易。

充值对象的主要字段:

字段 类型 说明
request_id string 提交充值时使用的幂等标识
topup_id string 平台充值标识
card_id string 平台卡片标识
topup_status string PENDINGSUCCESSFAIL
topup_amount string 充值本金快照
fee_amount string 充值手续费快照
total_debit_amount string 总扣款金额快照
settlement_currency string 结算币种
failure_code / failure_message string 终态失败代码 / 信息
created_at / updated_at integer 创建 / 更新时间,Unix 秒

10.1 提交充值#

POST /payment/vcc/cards/{card_id}/topups

权限:payment.vcc.card.topup

Path 参数 card_id 指定充值卡片。请求字段:

字段 类型 必填 说明
request_id string 本次充值请求的幂等标识
topup_amount string 大于 0、最多两位小数,并满足产品充值限额
{
  "request_id": "merchant-topup-T202607280001",
  "topup_amount": "10.00"
}

成功响应返回 data.topup,字段含义见本章“充值对象的主要字段”。

查看此接口的 API Reference →

10.2 查询充值列表#

GET /payment/vcc/topups?limit=20&offset=0

权限:payment.vcc.read

请求使用通用分页参数。响应的 data.topups 为充值对象数组,data.total 为充值总数。

查看此接口的 API Reference →

10.3 查询充值详情#

GET /payment/vcc/topups/{topup_id}

权限:payment.vcc.read

Path 参数 topup_id 为必填的平台充值标识。响应返回 data.topup,包括充值状态、金额、费用、失败信息和时间字段。

查看此接口的 API Reference →

10.4 提交共享卡提现#

该接口用于撤回 card_mode = BUDGET_CARD 共享卡尚未使用的可用额度;预充值卡不支持。提交后可通过提现列表或详情接口查询当前状态,提现状态变化仍会通过 vcc.withdrawal.updated Webhook 异步通知。

POST /payment/vcc/cards/{card_id}/withdrawals

权限:payment.vcc.card.withdraw

Path 参数 card_id 指定共享卡。请求字段:

字段 类型 必填 说明
request_id string 本次 API 调用的幂等标识,1–64 个字符
merchant_withdrawal_no string 商户提现订单号,当前商户账户内唯一;1–64 个字符,可使用字母、数字、_.:-
withdrawal_amount string 大于 0、最多两位小数,且不得超过当前未使用可用额度
{
  "request_id": "merchant-withdrawal-W202608130001",
  "merchant_withdrawal_no": "WD202608130001",
  "withdrawal_amount": "10.00"
}

成功受理后同步返回:

{
  "code": 0,
  "message": "OK",
  "data": {
    "withdrawal": {
      "request_id": "merchant-withdrawal-W202608130001",
      "withdrawal_id": "wd_0123456789abcdef",
      "merchant_withdrawal_no": "WD202608130001",
      "card_id": "card_0123456789abcdef",
      "withdrawal_status": "PENDING",
      "withdrawal_amount": "10.00",
      "settlement_currency": "USD",
      "created_at": 1786582800,
      "updated_at": 1786582800
    }
  }
}

PENDING 仅表示已受理,不代表提现成功。保存 withdrawal_idmerchant_withdrawal_no,并以 vcc.withdrawal.updatedresource_status 确认 SUCCESSFAIL 终态。

幂等规则:相同 request_id 必须使用相同参数;同一 merchant_withdrawal_no 再次提交相同 card_id 和金额时返回原提现记录,改用不同卡片或金额时返回 409 CARD_WITHDRAWAL_ORDER_CONFLICT。卡片存在其他额度变更操作时返回 409 CARD_OPERATION_IN_PROGRESS;非共享卡返回 422 CARD_WITHDRAWAL_NOT_SUPPORTED

查看此接口的 API Reference →

10.5 查询共享卡提现#

提交共享卡提现后,可以按商户提现单号、卡片或状态分页查询当前商户账户下的提现记录:

GET /payment/vcc/withdrawals?merchant_withdrawal_no=WD202608130001&card_id=card_0123456789abcdef&withdrawal_status=PENDING&limit=20&offset=0

权限:payment.vcc.read

所有 Query 参数均可选:merchant_withdrawal_no 为商户提现单号,card_id 为平台卡片标识,withdrawal_status 只接受 PENDINGSUCCESSFAILlimit 默认 20(范围 1–200),offset 默认 0

{
  "code": 0,
  "message": "OK",
  "data": {
    "withdrawals": [
      {
        "request_id": "merchant-withdrawal-W202608130001",
        "withdrawal_id": "wd_0123456789abcdef",
        "merchant_withdrawal_no": "WD202608130001",
        "card_id": "card_0123456789abcdef",
        "withdrawal_status": "PENDING",
        "withdrawal_amount": "10.00",
        "settlement_currency": "USD",
        "created_at": 1786582800,
        "updated_at": 1786582800
      }
    ],
    "total": 1
  }
}

按平台提现标识查询单笔详情:

GET /payment/vcc/withdrawals/{withdrawal_id}

权限:payment.vcc.read。响应返回 data.withdrawal,字段与提交接口中的 withdrawal 相同;不存在或不属于当前商户账户的提现返回 404 CARD_WITHDRAWAL_NOT_FOUND

查询接口返回当前状态;Webhook 用于异步通知状态变化,收到通知后可用详情接口再次确认。

查看提现列表 API Reference →

查看提现详情 API Reference →

11. 冻结和解冻#

11.1 冻结卡片#

POST /payment/vcc/cards/{card_id}/freeze

权限:payment.vcc.card.status

Path 参数 card_id 指定卡片。请求体的 request_id 为必填字符串,用于保证本次状态变更请求幂等。

响应包含 data.request_iddata.card_iddata.resource_statusresource_statusPENDINGSUCCESSFAIL

查看此接口的 API Reference →

11.2 解冻卡片#

POST /payment/vcc/cards/{card_id}/unfreeze

权限:payment.vcc.card.status

Path 参数和请求体与冻结接口相同。每次新的解冻业务请求使用新的 request_id。响应包含 request_idcard_idresource_status

查看此接口的 API Reference →

卡片当前状态通过卡片详情的 card_statusvcc.card.updated 事件取得。

12. 交易#

12.1 对外交易模型#

vcc.transaction.updated 最终只向商户推送以下四种交易类型:

transaction_type 说明 是否关联原交易
auth 消费授权账单。授权、结算和消费失败都更新同一笔账单,不单独暴露结算类型
void 结算前撤销或授权释放 是,通过 original_transaction_id
refund 结算后退款 是,通过 original_transaction_id
fee 独立费用交易,仅在卡管理费或 3DS 费成功扣收后生成;其他费用不单独生成 fee 交易

交易状态只使用:

transaction_status 说明
authorized 已授权、尚未完成最终结算
failed 当前交易处理失败;如上游后续纠正为成功,仍可能收到 succeed 更新
succeed 交易已完成,不应被较早的 authorizedfailed 通知回退

典型消费状态流为 auth / authorizedauth / succeedauth / failed。结算成功时沿用原 transaction_id,只更新状态、结算金额和费用总额。

交易查询对象的主要字段:

字段 类型 说明
transaction_id string 平台稳定的商户交易标识;同一消费从授权到结算保持不变
card_id string 平台卡片标识
card_last4 string 卡号后四位;有安全脱敏卡号时返回
product_code string 产品代码
three_ds_id string 独立 3DS 费关联的挑战标识;其他交易省略
deduction_source string 费用实际扣款来源:cardmerchant_wallet;其他交易省略
transaction_type string authvoidrefundfee
transaction_status string authorizedfailedsucceed
fee_type string 独立卡管理费返回 card_management,独立 3DS 费返回 three_ds;其他交易省略
transaction_amount string 刷卡或业务原始金额,固定两位小数
transaction_currency string 刷卡或业务原始币种
authorization_amount string 平台最终授权金额,固定两位小数
authorization_currency string 授权币种
fee_amount string 商户可见的已确认费用汇总,固定两位小数;独立费用为 0.00
fee_currency string 费用总额币种,当前为 USDT
settlement_amount string 平台最终结算/实际扣款金额,固定两位小数;授权阶段通常为 0.00,结算完成后更新为最终值
settlement_currency string 结算币种;可能与刷卡币种不同
merchant_name string 商户名称
merchant_descriptor string 账单商户描述
merchant_country string 商户国家或地区代码
merchant_category_code string 商户类别代码
original_transaction_id string 撤销或退款所关联的原消费交易标识;不适用时为空
occurred_at integer 交易时间,Unix 秒

fee_amount 为本笔交易返回的商户可见费用汇总。未配置或不适用的费用不会计入;商户接口和 Webhook 不返回费用拆分。

结算完成后请直接使用 settlement_amount 作为最终实际扣款金额;fee_amount 仅用于展示费用汇总,不要根据其他金额字段自行重算或重复相加。金额以平台返回的最终交易快照为准。

独立卡管理费使用 fee_type = card_management;扣款成功的 3DS 费使用 fee_type = three_ds。两者都使用 transaction_type = fee,应收金额放在 transaction_amountsettlement_amountfee_amount0.00,避免重复计算。3DS 扣费失败或结果未知时只保留费用业务任务,不生成成功交易;补偿成功后才出现该笔交易。

12.2 查询单卡交易#

GET /payment/vcc/cards/{card_id}/transactions

权限:payment.vcc.read

Path 参数 card_id 为必填。Query 参数:

字段 类型 必填 说明
transaction_type string authvoidrefundfee;不区分大小写
transaction_status string authorizedfailedsucceed;不区分大小写
start_at integer 最早交易时间,Unix 秒,包含边界
end_at integer 最晚交易时间,Unix 秒,包含边界
limit / offset integer 通用分页参数

响应的 data.transactions 为交易对象数组,data.total 为交易总数。

查看此接口的 API Reference →

12.3 查询全部 VCC 交易#

GET /payment/vcc/transactions

权限:payment.vcc.read

Query 参数:

字段 类型 必填 说明
transaction_id string 按 Webhook 返回的商户可见交易标识筛选
card_id string 按卡片标识筛选
product_code string 按产品代码筛选
transaction_type string authvoidrefundfee;不区分大小写
transaction_status string authorizedfailedsucceed;不区分大小写
start_at integer 最早交易时间,Unix 秒,包含边界
end_at integer 最晚交易时间,Unix 秒,包含边界
limit / offset integer 通用分页参数

响应的 data.transactions 为交易对象数组,字段含义见本章“交易对象的主要字段”;data.total 为交易总数。

查询结果是交易对账的最终依据。Webhook 和查询接口均使用 snake_case,共享字段保持同名。收到通知后应按 transaction_id 覆盖本地快照,并在需要对账时查询最新记录。

查询字段 Webhook 字段
transaction_id data.transaction_id
card_id data.card_id
product_code data.product_code
transaction_type data.transaction_type
transaction_status data.transaction_status
transaction_amount / transaction_currency data.transaction_amount / data.transaction_currency
authorization_amount / authorization_currency data.authorization_amount / data.authorization_currency(平台最终授权金额和币种)
settlement_amount / settlement_currency data.settlement_amount / data.settlement_currency(平台最终结算/实际扣款金额和币种)
fee_amount / fee_currency data.fee_amount / data.fee_currency(商户可见费用汇总和币种,不返回费用明细)
original_transaction_id data.original_transaction_id

查看此接口的 API Reference →

12.4 模拟交易(仅 Sandbox / 本地环境)#

POST /payment/vcc/transactions/simulate

此接口用于在不调用发卡行的情况下验证交易入账、卡余额变化、费用处理和 vcc.transaction.updated Webhook。接口仅在非生产环境开放;生产环境调用返回 403 CARD_TRANSACTION_SIMULATION_DISABLED

接口仍要求正常的 Payment API Bearer Token,并按当前 API Key 的账户范围校验卡片归属,但不要求额外的业务权限。请求体:

请求无需提供 merchant_data。模拟器会自动使用固定测试商户 Local transaction simulation、MCC 5734、国家代码 US;HTTP 响应以平铺字段 merchant_name / merchant_category_code / merchant_country 返回,交易 Webhook 则放在 data.merchant_data.name / category_code / country 中。

字段 类型 必填 说明
request_id string 1–64 个字符的幂等标识;相同参数重放返回原交易,不同参数重用返回 IDEMPOTENCY_CONFLICT
card_id string 当前账户下状态为 ACTIVE 的卡片标识
original_transaction_id string 结算、撤销或退款关联已有本地模拟账单时传入原交易标识;结算使用 AUTH 搭配该字段
transaction_type string 统一账单动作:AUTHVOIDREFUNDAUTH 不带原交易号创建授权,带原交易号完成结算;必须大写
amount string 大于 0、最多两位小数的 USD 金额
模拟动作码(transaction_type 商户可见结果 本金或授权变化 费用展示
AUTH auth / authorized 卡可用额度减少,授权占用增加 授权账单按当前产品配置评估普通费用并写入 fee_amount;不创建独立费用交易
AUTH(带 original_transaction_id auth / succeed 结算本金扣款并更新原 auth 沿用原账单更新最终 fee_amountsettlement_amount;不创建独立结算或费用交易
VOID void / succeed 释放尚未释放的本地模拟授权 适用撤销费写入该 void 账单的 fee_amount,不创建独立费用交易
REFUND refund / succeed 退回尚未退回的本地模拟结算本金 适用退款费写入该 refund 账单的 fee_amount,不创建独立费用交易

费用不是模拟接口的请求动作。模拟接口仅用于验证账单生命周期;费用是否收取由当前卡产品配置决定,未配置或配置为 0 时不收取。普通消费最多发送两次交易 Webhook:授权时的 auth / authorized,以及结算时同一 transaction_idauth / succeed;费用随交易账单快照返回,不会追加独立普通费用 Webhook。3DS 费用仅由真实 3DS 事件触发。

请求示例:

{
  "request_id": "merchant-sim-A202608140001",
  "card_id": "card_0123456789abcdef",
  "transaction_type": "AUTH",
  "amount": "10.00"
}

响应关键字段:

{
  "data": {
    "transaction": {
      "transaction_id": "sim_auth_934dea33",
      "transaction_type": "auth",
      "transaction_status": "authorized",
      "transaction_amount": "10.00",
      "transaction_currency": "USD",
      "authorization_amount": "10.00",
      "authorization_currency": "USD",
      "fee_amount": "0.00",
      "fee_currency": "USDT",
      "settlement_amount": "0.00",
      "settlement_currency": "USD",
      "merchant_name": "Local transaction simulation",
      "merchant_descriptor": "Local transaction simulation",
      "merchant_country": "US",
      "merchant_category_code": "5734"
    }
  }
}

保存 sim_auth_934dea33,用于后续结算或撤销。

步骤 2A:把原授权结算为成功消费#

{
  "request_id": "merchant-sim-C202608140002",
  "card_id": "card_0123456789abcdef",
  "original_transaction_id": "sim_auth_934dea33",
  "transaction_type": "AUTH",
  "amount": "10.00"
}

响应仍返回 transaction_id = sim_auth_934dea33,但状态变为 transaction_type = authtransaction_status = succeed。平台为同一 data.transaction_id 发送第二次完整交易 Webhook,更新最终 fee_amountsettlement_amount,不产生独立结算账单或普通费用交易。未配置的费用不会收取。

步骤 2B:撤销尚未结算的授权#

这是步骤 2A 的替代分支,必须对另一笔仍为 authorized 的模拟授权调用:

{
  "request_id": "merchant-sim-V202608140003",
  "card_id": "card_0123456789abcdef",
  "original_transaction_id": "sim_auth_another",
  "transaction_type": "VOID",
  "amount": "10.00"
}

响应生成一笔新的 void / succeed 交易,original_transaction_id = sim_auth_another

步骤 3:对已结算消费退款#

{
  "request_id": "merchant-sim-R202608140004",
  "card_id": "card_0123456789abcdef",
  "original_transaction_id": "sim_auth_934dea33",
  "transaction_type": "REFUND",
  "amount": "4.00"
}

响应生成一笔新的 refund / succeed 交易,original_transaction_id = sim_auth_934dea33,成功时 settlement_amount = 4.00

成功响应的 data.transaction 始终使用本章的商户交易结构。VOID 金额不能超过可释放授权,REFUND 金额不能超过可退款本金;不满足条件时返回对应业务错误。模拟交易不会关联或改动发卡行真实交易。

模拟接口常见错误:

HTTP code 说明
403 CARD_TRANSACTION_SIMULATION_DISABLED 生产环境禁止调用
404 ORIGINAL_TRANSACTION_NOT_FOUND 当前账户和卡片下找不到指定原模拟交易
409 ORIGINAL_TRANSACTION_INVALID 原交易状态、类型或剩余金额不允许当前动作
409 CARD_STATUS_NOT_ALLOWED 卡片不是可执行模拟交易的状态
422 INSUFFICIENT_CARD_BALANCE 卡余额、可释放授权或可退款本金不足

主交易完全在平台本地入库并发送 vcc.transaction.updated Webhook。模拟本金会更新预付卡余额或共享卡额度;命中正费率时,费用事件仍进入正常费用处理、卡扣减和共享账户归集链路,因此该接口会真实改变测试环境的资金投影,不是只返回假响应的预览接口。

查看此接口的 API Reference →

13. Webhook#

13.1 配置与订阅#

Webhook 配置包含:

  • 公网 HTTPS 回调地址。
  • Webhook Secret。
  • VCC 事件订阅。

推荐订阅 vcc.*,等价于订阅以下六类事件:

vcc.application.updated
vcc.card.updated
vcc.topup.updated
vcc.withdrawal.updated
vcc.transaction.updated
vcc.3ds.required

创建或轮换 Webhook 后,立即保存接口响应或 Portal 最终展示的 secret。该值是实际验签密钥;签名密钥不会在 Webhook 列表中再次返回,丢失后需要轮换。

13.2 事件目录#

事件类型 子类型 / 交易类型 触发结果 对账标识
vcc.application.updated KYC_REQUIRED 申请等待完成活体 application_id
vcc.application.updated FUNDS_REQUIRED 申请等待补充账户余额 application_id
vcc.application.updated CARD_READY 卡片已进入可用状态 application_idcard_id
vcc.application.updated APPLICATION_FAILED 开卡申请失败 application_id
vcc.card.updated CARD_FROZEN 冻结成功 card_id
vcc.card.updated CARD_UNFROZEN 解冻成功 card_id
vcc.card.updated CARD_FREEZE_FAILED 冻结失败 card_id
vcc.card.updated CARD_UNFREEZE_FAILED 解冻失败 card_id
vcc.topup.updated NORMAL_TOPUP 主动充值状态变化 topup_id
vcc.withdrawal.updated CARD_WITHDRAWAL 共享卡提现状态变化 withdrawal_idmerchant_withdrawal_no
vcc.transaction.updated data.transaction_typeauthvoidrefundfee 交易新增或数据变化 data.transaction_iddata.card_id
vcc.3ds.required CHALLENGE_REQUIRED 需要处理 3DS 验证码 three_ds_id

充值本金不会作为卡交易出现在 vcc.transaction.updated 中,主动充值状态只通过 vcc.topup.updated 和充值查询接口返回。独立费用交易当前展示卡管理费和扣款成功的 3DS 费。

13.3 请求头与验签#

VCC 的所有事件统一使用以下投递头部,不区分渠道或平台:Content-TypeX-Delivery-IdX-Webhook-EventX-Webhook-IdX-Webhook-Signature

Header 说明
Content-Type 固定为 application/json
X-Webhook-Signature 原始 Body 的 HMAC-SHA256 小写十六进制签名
X-Webhook-Id Webhook 配置 ID
X-Delivery-Id 本次投递记录 ID
X-Webhook-Event event_type

创建或轮换 Webhook 后,必须使用接口响应或 Portal 最终展示的 secret 验签;不要直接使用创建请求中提交的原始自定义 Secret。

签名计算:

expected_signature = hex(HMAC_SHA256(raw_request_body, webhook_secret))

处理顺序:

  1. 读取并保留 HTTP 原始 Body 字节。
  2. 不要先格式化、排序字段或重新序列化 JSON。
  3. 使用 Webhook Secret 计算 HMAC-SHA256。
  4. 将结果编码为小写十六进制字符串。
  5. 使用常量时间比较校验 X-Webhook-Signature
  6. 验签失败返回非 2xx,不得更新业务状态。

13.4 事件字段#

所有 VCC 事件均使用 snake_case。交易事件保留独立的 data 安全快照结构,完整字段见 13.10。

字段 返回范围 说明
event_id 所有事件 事件去重键;重试沿用同一值
event_type 所有事件 事件大类
event_subtype 非交易事件 具体状态或动作
event_version 非交易事件 当前固定为 v1
account_id 非交易事件 事件所属账户标识
product_code 非交易事件 卡产品代码
request_id 关联写请求的事件 写接口使用的幂等标识
application_id 申请事件 开卡申请标识
customer_id CARD_READY 客户标识
card_id 卡、充值、提现、3DS、CARD_READY 卡片标识
card_last4 3DS 卡号后四位;可安全取得时返回
topup_id 充值事件 充值标识
withdrawal_id 提现事件 平台提现标识
merchant_withdrawal_no 提现事件 商户提现订单号
withdrawal_amount / settlement_currency 提现事件 提现金额和结算币种
three_ds_id 3DS 事件 3DS 挑战标识
fee_transaction_id / fee_type 3DS 事件 预计生成的独立费用交易标识和固定值 three_ds
assessed_fee_amount / fee_currency 3DS 事件 本次 3DS 费用评估金额和扣费币种;不代表已经扣款成功
resource_status 申请、充值、提现、卡、3DS 资源或动作状态
next_action KYC_REQUIREDFUNDS_REQUIRED 下一步动作
failure_code / failure_message 失败事件 失败代码 / 信息
occurred_at 所有事件 业务发生时间;交易事件为 RFC 3339,其他事件为 Unix 秒

3DS 事件包含 verification_code,并可包含交易金额、币种、商户名称、商户国家或地区和 MCC。fee_transaction_id 用于关联后续扣费成功的 vcc.transaction.updated;收到 3DS 事件本身不代表费用已扣除。

13.5 通知处理规则#

接收 HTTP 请求
  -> 保留原始 Body
  -> 验证 HMAC 签名
  -> 解析 JSON
  -> 按 X-Webhook-Event 选择事件合同
  -> 交易事件校验 event_type、data.transaction_id 和 data.card_id;其他事件校验 event_type、event_subtype 和 account_id
  -> 以 event_id 写入事件表(唯一键)
  -> 重复事件直接返回 2xx
  -> 交易事件按 data.transaction_id 幂等更新本地账单
  -> 提现事件按 withdrawal_id 幂等更新 resource_status
  -> 其他非 3DS 事件按资源 ID 查询平台当前状态
  -> 在事务中更新本地业务状态
  -> 安全持久化完成后返回 2xx

必须遵守:

  • 只有事件已经安全持久化后才返回 HTTP 2xx
  • 同一 event_id 可能多次投递,接收方必须幂等。
  • 不保证事件按业务发生顺序到达。
  • 非 3DS 资源以查询接口返回的当前状态为最终处理依据;Webhook 用于异步通知,提现收到通知后可再查询详情确认。
  • 对包含 account_id 的非交易事件,校验其是否属于当前接收系统的账户范围。
  • verification_code 不得写入普通业务日志、错误信息或监控标签。

13.6 开卡申请事件示例#

13.6.1 需要活体:KYC_REQUIRED#

{
  "event_id": "vcc_evt_0123456789abcdef",
  "event_type": "vcc.application.updated",
  "event_subtype": "KYC_REQUIRED",
  "event_version": "v1",
  "account_id": "acct_example",
  "request_id": "merchant-card-O202607280001",
  "product_code": "1103",
  "application_id": "app_0123456789abcdef",
  "resource_status": "PENDING",
  "next_action": {
    "action_type": "COMPLETE_LIVENESS"
  },
  "occurred_at": 1784995200
}

13.6.2 需要补充余额:FUNDS_REQUIRED#

{
  "event_id": "vcc_evt_0a23456789abcdef",
  "event_type": "vcc.application.updated",
  "event_subtype": "FUNDS_REQUIRED",
  "event_version": "v1",
  "account_id": "acct_example",
  "request_id": "merchant-card-O202607280001",
  "product_code": "1103",
  "application_id": "app_0123456789abcdef",
  "resource_status": "PENDING",
  "next_action": {
    "action_type": "ADD_FUNDS",
    "required_account_balance": "6.01",
    "required_balance_currency": "USDT",
    "expires_at": 1785254400
  },
  "occurred_at": 1784995300
}

13.6.3 卡片可用:CARD_READY#

{
  "event_id": "vcc_evt_1234567890abcdef",
  "event_type": "vcc.application.updated",
  "event_subtype": "CARD_READY",
  "event_version": "v1",
  "account_id": "acct_example",
  "request_id": "merchant-card-O202607280001",
  "application_id": "app_0123456789abcdef",
  "customer_id": "cus_0123456789abcdef",
  "product_code": "1103",
  "card_id": "card_0123456789abcdef",
  "masked_card_number": "409636******2420",
  "resource_status": "SUCCESS",
  "occurred_at": 1784995500
}

13.6.4 申请失败:APPLICATION_FAILED#

{
  "event_id": "vcc_evt_2345678901abcdef",
  "event_type": "vcc.application.updated",
  "event_subtype": "APPLICATION_FAILED",
  "event_version": "v1",
  "account_id": "acct_example",
  "request_id": "merchant-card-O202607280001",
  "product_code": "1103",
  "application_id": "app_0123456789abcdef",
  "resource_status": "FAIL",
  "failure_code": "<failure_code>",
  "failure_message": "<failure_message>",
  "occurred_at": 1784995500
}

13.7 卡片事件示例#

13.7.1 冻结成功:CARD_FROZEN#

{
  "event_id": "vcc_evt_3456789012abcdef",
  "event_type": "vcc.card.updated",
  "event_subtype": "CARD_FROZEN",
  "event_version": "v1",
  "account_id": "acct_example",
  "request_id": "merchant-freeze-F202607280001",
  "product_code": "1103",
  "card_id": "card_0123456789abcdef",
  "resource_status": "SUCCESS",
  "occurred_at": 1784995800
}

13.7.2 解冻成功:CARD_UNFROZEN#

{
  "event_id": "vcc_evt_3567890123abcdef",
  "event_type": "vcc.card.updated",
  "event_subtype": "CARD_UNFROZEN",
  "event_version": "v1",
  "account_id": "acct_example",
  "request_id": "merchant-unfreeze-U202607280001",
  "product_code": "1103",
  "card_id": "card_0123456789abcdef",
  "resource_status": "SUCCESS",
  "occurred_at": 1784995900
}

13.7.3 冻结失败:CARD_FREEZE_FAILED#

{
  "event_id": "vcc_evt_3678901234abcdef",
  "event_type": "vcc.card.updated",
  "event_subtype": "CARD_FREEZE_FAILED",
  "event_version": "v1",
  "account_id": "acct_example",
  "request_id": "merchant-freeze-F202607280002",
  "product_code": "1103",
  "card_id": "card_0123456789abcdef",
  "resource_status": "FAIL",
  "failure_code": "<failure_code>",
  "failure_message": "<failure_message>",
  "occurred_at": 1784996000
}

13.7.4 解冻失败:CARD_UNFREEZE_FAILED#

{
  "event_id": "vcc_evt_3789012345abcdef",
  "event_type": "vcc.card.updated",
  "event_subtype": "CARD_UNFREEZE_FAILED",
  "event_version": "v1",
  "account_id": "acct_example",
  "request_id": "merchant-unfreeze-U202607280002",
  "product_code": "1103",
  "card_id": "card_0123456789abcdef",
  "resource_status": "FAIL",
  "failure_code": "<failure_code>",
  "failure_message": "<failure_message>",
  "occurred_at": 1784996100
}

冻结和解冻只发送 SUCCESSFAIL 终态 Webhook,不发送 PENDING Webhook。实际卡状态通过卡片详情接口确认。

13.8 充值事件示例#

event_subtype 固定为 NORMAL_TOPUP,通过 resource_status 区分状态。

13.8.1 处理中#

{
  "event_id": "vcc_evt_4567890123abcdef",
  "event_type": "vcc.topup.updated",
  "event_subtype": "NORMAL_TOPUP",
  "event_version": "v1",
  "account_id": "acct_example",
  "request_id": "merchant-topup-T202607280001",
  "product_code": "1103",
  "topup_id": "top_0123456789abcdef",
  "card_id": "card_0123456789abcdef",
  "resource_status": "PENDING",
  "occurred_at": 1784995700
}

13.8.2 成功#

{
  "event_id": "vcc_evt_4678901234abcdef",
  "event_type": "vcc.topup.updated",
  "event_subtype": "NORMAL_TOPUP",
  "event_version": "v1",
  "account_id": "acct_example",
  "request_id": "merchant-topup-T202607280001",
  "product_code": "1103",
  "topup_id": "top_0123456789abcdef",
  "card_id": "card_0123456789abcdef",
  "resource_status": "SUCCESS",
  "occurred_at": 1784995800
}

13.8.3 失败#

{
  "event_id": "vcc_evt_4789012345abcdef",
  "event_type": "vcc.topup.updated",
  "event_subtype": "NORMAL_TOPUP",
  "event_version": "v1",
  "account_id": "acct_example",
  "request_id": "merchant-topup-T202607280001",
  "product_code": "1103",
  "topup_id": "top_0123456789abcdef",
  "card_id": "card_0123456789abcdef",
  "resource_status": "FAIL",
  "failure_code": "<failure_code>",
  "failure_message": "<failure_message>",
  "occurred_at": 1784995800
}

13.9 共享卡提现事件示例#

event_subtype 固定为 CARD_WITHDRAWALresource_statusPENDINGSUCCESSFAIL。以下为成功终态示例:

{
  "event_id": "vcc_evt_5890123456abcdef",
  "event_type": "vcc.withdrawal.updated",
  "event_subtype": "CARD_WITHDRAWAL",
  "event_version": "v1",
  "account_id": "acct_example",
  "request_id": "merchant-withdrawal-W202608130001",
  "product_code": "1103",
  "card_id": "card_0123456789abcdef",
  "withdrawal_id": "wd_0123456789abcdef",
  "merchant_withdrawal_no": "WD202608130001",
  "withdrawal_amount": "10.00",
  "settlement_currency": "USD",
  "resource_status": "SUCCESS",
  "occurred_at": 1786582860
}

失败事件还包含 failure_codefailure_message。按 event_id 去重,并按 withdrawal_id 幂等更新;终态 SUCCESSFAIL 不得被迟到的 PENDING 覆盖。

13.10 交易事件示例#

交易事件使用 snake_case,并在 data 中发送安全账单快照;不包含 event_versionaccount_id、费用拆分或平台资金日记账。data.card_iddata.product_code 在所有交易通知中稳定返回,3DS 独立费用还会返回实际扣款来源。完整字段如下:

字段 说明
event_id 本次交易快照事件的去重键;同一次投递重试保持不变
event_type 固定为 vcc.transaction.updated
occurred_at 该事件发生时间,RFC 3339
data.transaction_id 稳定交易标识;同一消费授权到结算保持不变
data.card_id / data.product_code 平台卡片标识和产品代码;所有交易通知均返回
data.card_last4 卡号后四位;可安全取得时返回
data.three_ds_id 3DS 独立费用关联的挑战标识
data.deduction_source 3DS 费实际扣款来源:cardmerchant_wallet
data.transaction_type authvoidrefundfee
data.fee_type 独立卡管理费返回 card_management;独立 3DS 费返回 three_ds
data.transaction_status authorizedfailedsucceed
data.transaction_amount / data.transaction_currency 刷卡或业务原始金额和币种
data.authorization_amount / data.authorization_currency 平台最终授权金额和授权币种
data.settlement_amount / data.settlement_currency 结算金额和币种;授权阶段可为 0.00,后续可能更新
data.fee_amount / data.fee_currency 关联费用总额和币种;只给总额,不拆分明细
data.original_transaction_id 撤销或退款关联的原消费交易标识;不适用时省略
data.merchant_data 商户名称、MCC、城市和国家或地区;无数据时省略
data.authorization_code 授权码;无数据时省略
data.transaction_time 交易时间,RFC 3339
data.updated_time 当前账单快照更新时间,RFC 3339

不同业务步骤的展示规则:

步骤 data.transaction_type data.transaction_status 关键金额 交易关联
消费授权成功 auth authorized settlement_amount 通常为 0.00fee_amount 为授权账单当前已确认的适用普通费用总额 使用消费 transaction_id
消费授权失败 auth failed 返回当前已知金额和费用 与授权请求同一 transaction_id
消费结算成功 auth succeed settlement_amountsettlement_currencyfee_amount 更新为当前最终值 沿用授权的 transaction_id,不新增结算账单或普通费用交易
授权撤销 void succeedfailed 授权和结算金额为 0.00;适用撤销费写入该 void 账单的 fee_amount transaction_id,并返回 original_transaction_id
结算后退款 refund succeedfailed 成功时 settlement_amount 为退款金额;适用退款费写入该 refund 账单的 fee_amount transaction_id,并返回 original_transaction_id
卡管理费 fee succeed transaction_amountsettlement_amount 为卡管理费,fee_amount0.00 fee_type = card_management
3DS 费扣款成功 fee succeed transaction_amountsettlement_amount 为 3DS 费,fee_amount0.00 fee_type = three_dstransaction_id 等于 3DS 事件的 fee_transaction_id

消费授权通知示例(真实渠道回调样例):

下面的 ANTHROPIC* CLAUDE SUB 仅用于展示真实渠道可能返回的商户资料,不是本地模拟交易的返回值。模拟交易的 Webhook 必须使用 Local transaction simulation、MCC 5734、国家代码 US;嵌套位置仍是 data.merchant_data

{
  "event_id": "vcc_evt_6789012345abcdef",
  "event_type": "vcc.transaction.updated",
  "occurred_at": "2026-08-24T10:20:15Z",
  "data": {
    "transaction_id": "934dea33-6ee0-44a0-baf8-fb36b4d2fe6d",
    "card_id": "card_0123456789abcdef",
    "product_code": "1103",
    "transaction_type": "auth",
    "transaction_status": "authorized",
    "transaction_amount": "16.20",
    "transaction_currency": "GBP",
    "authorization_amount": "22.57",
    "authorization_currency": "USD",
    "settlement_amount": "0.00",
    "settlement_currency": "USD",
    "fee_amount": "0.52",
    "fee_currency": "USDT",
    "merchant_data": {
      "name": "ANTHROPIC* CLAUDE SUB",
      "category_code": "5734",
      "city": "SAN FRANCISCO",
      "country": "US"
    },
    "authorization_code": "76U47U",
    "transaction_time": "2026-08-24T10:20:15Z",
    "updated_time": "2026-08-24T10:20:16Z"
  }
}

结算后,平台会使用新的 event_id 再次推送完整快照,但 data.transaction_id 保持不变,例如:

本例仅展示结算后的最终账单快照。商户应直接使用返回的 settlement_amount 作为实际扣款金额,不要根据 authorization_amountfee_amount 自行重算。

{
  "event_id": "vcc_evt_7890123456abcdef",
  "event_type": "vcc.transaction.updated",
  "occurred_at": "2026-08-25T03:12:40Z",
  "data": {
    "transaction_id": "934dea33-6ee0-44a0-baf8-fb36b4d2fe6d",
    "card_id": "card_0123456789abcdef",
    "product_code": "1103",
    "transaction_type": "auth",
    "transaction_status": "succeed",
    "transaction_amount": "16.20",
    "transaction_currency": "GBP",
    "authorization_amount": "22.57",
    "authorization_currency": "USD",
    "settlement_amount": "22.81",
    "settlement_currency": "USD",
    "fee_amount": "0.52",
    "fee_currency": "USDT",
    "merchant_data": {
      "name": "ANTHROPIC* CLAUDE SUB",
      "category_code": "5734",
      "city": "SAN FRANCISCO",
      "country": "US"
    },
    "authorization_code": "76U47U",
    "transaction_time": "2026-08-24T10:20:15Z",
    "updated_time": "2026-08-25T03:12:40Z"
  }
}

接收方必须先按 event_id 去重,再按 data.transaction_id 覆盖本地交易快照。交易发生实际变化时会生成新的 event_id,投递重试则沿用原 event_id。通知不保证顺序;不要让迟到的 authorized 覆盖 failedsucceed,也不要让 failed 覆盖已存在的 succeed。如状态或金额存在冲突,以交易查询接口的最新结果为准。

13.11 3DS 事件示例#

{
  "event_id": "vcc_evt_7890123456abcdef",
  "event_type": "vcc.3ds.required",
  "event_subtype": "CHALLENGE_REQUIRED",
  "event_version": "v1",
  "account_id": "acct_example",
  "product_code": "1103",
  "three_ds_id": "3ds_0123456789abcdef",
  "card_id": "card_0123456789abcdef",
  "card_last4": "4242",
  "resource_status": "REQUIRED",
  "verification_code": "123456",
  "transaction_amount": "88.00",
  "transaction_currency": "USD",
  "merchant_name": "Example Store",
  "merchant_country": "SG",
  "merchant_category_code": "5411",
  "fee_transaction_id": "txn_fee_3ds_fee_0123456789abcdef",
  "fee_type": "three_ds",
  "assessed_fee_amount": "0.37",
  "fee_currency": "USDT",
  "occurred_at": 1784995900
}

verification_code 按当前契约直接返回,不做 RSA 加密。必须先完成 HMAC-SHA256 验签,再读取和处理验证码。assessed_fee_amount 只是计费快照,不是扣款结果。

当卡余额扣款或商户钱包兜底扣款真正成功后,平台使用同一个 fee_transaction_id 发送独立费用交易:

{
  "event_id": "vcc_evt_89abcdef01234567",
  "event_type": "vcc.transaction.updated",
  "occurred_at": "2026-08-24T12:00:02Z",
  "data": {
    "transaction_id": "txn_fee_3ds_fee_0123456789abcdef",
    "card_id": "card_0123456789abcdef",
    "card_last4": "4242",
    "product_code": "1103",
    "three_ds_id": "3ds_0123456789abcdef",
    "deduction_source": "card",
    "transaction_type": "fee",
    "fee_type": "three_ds",
    "transaction_status": "succeed",
    "transaction_amount": "0.37",
    "transaction_currency": "USDT",
    "authorization_amount": "0.00",
    "authorization_currency": "USDT",
    "settlement_amount": "0.37",
    "settlement_currency": "USDT",
    "fee_amount": "0.00",
    "fee_currency": "USDT",
    "merchant_data": {"name": "Example Store"},
    "transaction_time": "2026-08-24T12:00:02Z",
    "updated_time": "2026-08-24T12:00:02Z"
  }
}

扣费失败或结果未知时不会伪造 succeed 交易通知;费用留在业务任务中,待系统重试或后台从失败步骤继续。补偿成功后才发送上面的交易事件。

13.12 响应、重试和乱序规则#

规则 当前行为
成功确认 接收方返回任意 HTTP 2xx
首次投递 事件生成后立即投递
最大投递次数 首次 1 次,加失败重试最多 9 次;总计最多 10 次
默认重试间隔 1、2、5、10、20、40、80、240、1020 分钟
默认累计窗口 约 23 小时 38 分钟,实际时间可能有少量偏差
自定义计划上限 72 小时硬上限;不表示默认计划持续 72 小时
重复投递 同一事件重试沿用同一 event_id;必须幂等处理
到达顺序 不保证按业务发生顺序到达
状态确认 交易、共享卡提现及其他有查询接口的资源以查询结果为准;3DS 按对应事件规则处理

网络超时、连接失败或非 2xx 响应按失败投递处理,并进入重试计划。不要在业务处理完成前提前返回 2xx

14. 接口总表#

# 方法 路径 API Reference
1 GET /payment/account 查看
2 GET /payment/balances 查看
3 GET /payment/deposits 查看
4 GET /payment/ledger 查看
5 GET /payment/vcc/products 查看
6 POST /payment/vcc/files 查看
7 POST /payment/vcc/customers 查看
8 GET /payment/vcc/customers 查看
9 GET /payment/vcc/customers/{customer_id} 查看
10 PATCH /payment/vcc/customers/{customer_id} 查看
11 POST /payment/vcc/card-applications 查看
12 GET /payment/vcc/card-applications 查看
13 GET /payment/vcc/card-applications/{application_id} 查看
14 GET /payment/vcc/cards 查看
15 GET /payment/vcc/cards/{card_id} 查看
16 POST /payment/vcc/cards/sensitive 查看
17 GET /payment/vcc/cards/{card_id}/balance 查看
18 POST /payment/vcc/cards/{card_id}/topups 查看
19 GET /payment/vcc/topups 查看
20 GET /payment/vcc/topups/{topup_id} 查看
21 POST /payment/vcc/cards/{card_id}/withdrawals 查看
22 GET /payment/vcc/withdrawals 查看
23 GET /payment/vcc/withdrawals/{withdrawal_id} 查看
24 POST /payment/vcc/cards/{card_id}/freeze 查看
25 POST /payment/vcc/cards/{card_id}/unfreeze 查看
26 GET /payment/vcc/cards/{card_id}/transactions 查看
27 GET /payment/vcc/transactions 查看
28 POST /payment/vcc/transactions/simulate 查看

15. 超时与重试#

GET 请求可直接重试。

POST 或 PATCH 请求超时后,使用原 request_id 和原请求参数重试。已经取得资源 ID 时,使用对应查询接口读取当前状态;共享卡提现可用 GET /payment/vcc/withdrawals/{withdrawal_id} 查询,或使用提现列表按商户提现单号检索。Webhook 到达后可再查询详情确认。

16. 契约文件#