> ## Documentation Index
> Fetch the complete documentation index at: https://developers.uqpay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 虚拟账户 API 生命周期

> 通过 Global Account API 创建、跟踪、查询并使用虚拟账户收款。

当你通过 API 而不是控制台创建虚拟账户时，请使用本指南。虚拟账户申请是异步流程：创建请求会先被受理，可用的账户信息会在后续返回，资金到账后再通过充值记录单独对账。

<h2 id="lifecycle-overview">
  生命周期概览
</h2>

```mermaid theme={null}
sequenceDiagram
    participant You as 你的系统
    participant UQPAY
    participant Payer as 付款人

    You->>UQPAY: Create Virtual Account
    UQPAY-->>You: SUCCESS 受理结果
    UQPAY-->>You: virtual.account.create
    UQPAY-->>You: virtual.account.update status=Active
    You->>UQPAY: List Virtual Accounts
    UQPAY-->>You: Active 账户信息和 capability
    Payer->>UQPAY: 使用 VA 账户信息发起银行转账
    UQPAY-->>You: deposit.pending / deposit.completed / deposit.compliance.rejected
    You->>UQPAY: Retrieve Deposit
```

<Warning>
  不要把 [Create Virtual Account](/zh/global-account/v1.6/api-reference/create-virtual-account) 的同步 `SUCCESS` 响应当作虚拟账户已经可以收款的证明。它只表示 UQPAY 已受理请求并开始处理。
</Warning>

<h2 id="prerequisites">
  前置条件
</h2>

通过 API 创建虚拟账户前，请先确认：

* 已完成所需的入驻流程，并为目标账户启用 Global Account 产品。
* 已确认该账户支持所请求的币种和收款方式。参见[支持的地区与币种](/zh/global-account/v1.6/guide/supported-regions-and-currencies)。
* 已决定虚拟账户属于主账户还是子账户。如果为子账户创建虚拟账户，请在 `x-on-behalf-of` 请求头中传入该子账户的 `account_id`。
* 已配置并测试[虚拟账户创建 / 更新 Webhook](/zh/global-account/v1.6/webhooks/virtual-account-create-update)，再发送生产环境创建请求。
* 每次创建请求都生成唯一的 `x-idempotency-key`。如果同时传入 `x-request-id`，请保存该值，因为它会在虚拟账户 Webhook 的 `request_id` 中返回。

<h2 id="step-1-submit-the-create-request">
  步骤 1：提交创建请求
</h2>

为应接收该虚拟账户的账户调用 [Create Virtual Account](/zh/global-account/v1.6/api-reference/create-virtual-account)。

| 输入                  | 使用方式                                        |
| ------------------- | ------------------------------------------- |
| `x-on-behalf-of`    | 为子账户创建虚拟账户时使用此请求头。为主账户创建时可省略。               |
| `x-idempotency-key` | 必填。使用唯一 UUID，确保重试不会创建重复申请。                  |
| `x-request-id`      | 可选。使用你自己的请求标识，用于将创建请求与后续 Webhook 事件关联。      |
| `currency`          | 必填。传入一个或多个受支持的币种代码；请求多个币种时用英文逗号分隔。          |
| `payment_method`    | 可选。当你需要指定收款能力且对应币种支持时，传入 `LOCAL` 或 `SWIFT`。 |

接口响应中的 `message = SUCCESS` 表示请求已被受理并进入处理流程。它不表示虚拟账户已经开通完成，也不应在此时向付款人展示付款指引。

<h2 id="step-2-track-provisioning-status-by-webhook">
  步骤 2：通过 Webhook 跟踪开通状态
</h2>

虚拟账户创建会通过[虚拟账户创建 / 更新 Webhook](/zh/global-account/v1.6/webhooks/virtual-account-create-update) 异步完成。

| 事件                                           | 含义                                                                      | 处理方式                                                                                               |
| -------------------------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `virtual.account.create`                     | UQPAY 已受理对应币种的申请。Webhook 数据中的 `status` 可能仍为 `Processing`，银行账户信息也可能尚不完整。 | 保存事件并继续等待更新。                                                                                       |
| `virtual.account.update` 且 `status = Active` | 虚拟账户已经可以使用，银行账户信息和收款能力已经可用。                                             | 调用 [List Virtual Accounts](/zh/global-account/v1.6/api-reference/list-virtual-accounts) 并保存最新账户信息。 |
| `virtual.account.closed`                     | 虚拟账户已关闭。                                                                | 停止向付款人展示该账户信息，并禁止新的收款指引用到该账户。                                                                      |

<Warning>
  虚拟账户申请失败时不会发送 Webhook。如果在预期时间内没有收到 Active 更新，请查询 [List Virtual Accounts](/zh/global-account/v1.6/api-reference/list-virtual-accounts) 并联系 UQPAY support。
</Warning>

Webhook payload 中包含以下应保存的标识：

| 字段                          | 作用                                 |
| --------------------------- | ---------------------------------- |
| `account_id`                | 标识拥有该虚拟账户的主账户或子账户。                 |
| `account_bank_id`           | 标识已开通的虚拟银行账户信息记录。                  |
| `account_number`            | 账户激活后向付款人展示的账号或 IBAN。              |
| `currency`                  | 收款币种。                              |
| `capability.payment_method` | 该银行账户信息支持的收款方式。                    |
| `request_id`                | 如果创建请求中传入了 `x-request-id`，这里会返回该值。 |

<h2 id="step-3-query-active-virtual-accounts">
  步骤 3：查询可用虚拟账户
</h2>

收到 Active Webhook 后、服务启动时，或需要刷新已保存账户信息时，调用 [List Virtual Accounts](/zh/global-account/v1.6/api-reference/list-virtual-accounts)。

你可以按 `currency` 筛选。查询子账户时，请传入与创建或代该子账户操作时相同的 `x-on-behalf-of` 值。

请在你的系统中保存返回的信息：

| 字段                                               | 用途                          |
| ------------------------------------------------ | --------------------------- |
| `account_bank_id`                                | 银行账户信息记录的稳定标识。              |
| `account_holder`                                 | 付款指引中展示的账户持有人名称。            |
| `account_number`                                 | 向付款人展示的账号或 IBAN。            |
| `country_code`                                   | 账户所在国家。                     |
| `currency`                                       | 账户可接收的币种。                   |
| `bank_name` 和 `bank_address`                     | 付款指引中的银行信息。                 |
| `clearing_system.type` 和 `clearing_system.value` | 本地清算代码或 BIC/SWIFT 标识等路由信息。  |
| `capability.payment_method`                      | 账户通过 `LOCAL` 还是 `SWIFT` 收款。 |
| `status`                                         | 只应使用已激活账户生成新的付款指引。          |

<Note>
  Webhook 状态值和 List API 状态值的大小写不同。例如 Webhook 可能发送 `Active`，而 List API 可能返回 `ACTIVE`。请在你的系统中先统一状态值，再执行业务判断。
</Note>

<h2 id="step-4-use-the-receiving-capability">
  步骤 4：使用正确的收款能力
</h2>

每条返回的虚拟银行账户信息都有对应收款能力。请根据预期支付通道展示匹配的付款指引。

| Capability | 适用场景                  | 实现说明                                                                            |
| ---------- | --------------------- | ------------------------------------------------------------------------------- |
| `LOCAL`    | 受支持市场内的本地或境内清算转账。     | 展示 API 返回的本地账号和 `clearing_system` 信息。除非返回了支持 SWIFT 的账户记录，不要假设同一账户也能接收 SWIFT 转账。 |
| `SWIFT`    | 通过 SWIFT 网络发起的跨境银行转账。 | 展示 API 返回的 SWIFT 收款账户信息。请确保付款人严格使用返回的币种和银行账户信息。                                 |

如果某个币种同时支持本地收款和 SWIFT 收款，请将每条返回的银行账户信息视为独立记录。你应向付款人展示与预期收款能力匹配的指引。

<h2 id="step-5-reconcile-deposits-against-virtual-accounts">
  步骤 5：将充值与虚拟账户对账
</h2>

虚拟账户用于标识资金应汇入哪里。[充值](/zh/global-account/v1.6/guide/deposit) 是资金到达并被处理后生成的交易记录。

对账时：

1. 虚拟账户激活后，保存账户映射关系。
2. 监听[充值状态](/zh/global-account/v1.6/webhooks/deposit-pending-rejected-completed) Webhook 事件。
3. 如果是子账户充值，使用 Webhook 中的 `account_id` 作为 `x-on-behalf-of` 查询充值详情。
4. 使用 `deposit_id` 调用 [Retrieve Deposit](/zh/global-account/v1.6/api-reference/retrieve-deposit)。
5. 使用充值详情中的 `receiver_account_number`、`currency` 和所属 `account_id` 匹配到你的虚拟账户映射。可在有值时结合付款人信息和 `deposit_reference` 做辅助对账。

<Tip>
  虚拟账户激活后请缓存账户映射。充值 Webhook 会标识收款账户和充值交易；保存这份映射后，你可以把充值匹配到具体虚拟账户、子账户和收款方式，减少每次对账时重新查询虚拟账户列表。
</Tip>

<h2 id="api-and-webhook-map">
  API 与 Webhook 对照
</h2>

| 需求           | 公开接口 / 文档                                                                                                                                         |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| 提交虚拟账户申请     | [Create Virtual Account](/zh/global-account/v1.6/api-reference/create-virtual-account)                                                            |
| 查询已开通的虚拟账户信息 | [List Virtual Accounts](/zh/global-account/v1.6/api-reference/list-virtual-accounts)                                                              |
| 接收开通状态事件     | [虚拟账户创建 / 更新 Webhook](/zh/global-account/v1.6/webhooks/virtual-account-create-update)                                                             |
| 跟踪入账资金       | [充值状态 Webhook](/zh/global-account/v1.6/webhooks/deposit-pending-rejected-completed)                                                               |
| 查询已入账资金      | [List Deposits](/zh/global-account/v1.6/api-reference/list-deposits) 和 [Retrieve Deposit](/zh/global-account/v1.6/api-reference/retrieve-deposit) |
