﻿## 接口说明

接口名称：`alipay.aipay.nowpay.quota.verify`

按平台提供的消费请求号直接核销指定数量的次数或积分。核销成功即正式扣减；平台需结合服务交付时点调用，并保存消费请求与核销结果的对应关系。

支持已获授权的第三方代理调用。所有接口由平台服务端调用。

## 适用场景

- 一次服务需要正式消耗次数或积分。
- 同一消费请求因网络异常需要重试。

## 注意事项

- amount 必须显式传入正整数；一次扣 1 次时传 1，不依赖服务端默认补值。积分按平台服务规则计算后传入。
- 平台在调用前持久化 `out_request_no`、商品、受益人、amount 和 `consume_reason`。重试保持这些字段一致；不同消费使用不同请求号。
- `consume_reason` 使用不超过 256 字符的简洁业务文本，用于说明本次消费。平台自行保存审计记录，不依赖结果查询接口回传此字段来恢复原始业务上下文。
- 先检查 code，再读取 `consume_status`。只有 `SUCCEEDED` 表示扣减成功；`PROCESSING`、网络超时或系统错误都不能直接当作失败换号重扣。
- 余额不足可能通过业务错误码 `NOW_PAY_QUOTA_INSUFFICIENT` 返回；也需兼容 `FAILED` 与 `reason_code` 的结果表达。额度不足整笔失败，不按部分扣减处理。
- 核销成功后不提供核销撤销、预占释放或服务失败自动返还。平台应事先确定服务交付与核销的时点，并对服务执行本身做好幂等。

## 公共请求参数

| 参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
| --- | --- | --- | --- | --- | --- |
| `app_id` | String | 必选 | 32 | 支付宝分配给开发者的应用ID | `YOUR_APP_ID` |
| `method` | String | 必选 | 128 | 接口名称 | `alipay.aipay.nowpay.quota.verify` |
| `format` | String | 可选 | 40 | 仅支持JSON | `JSON` |
| `charset` | String | 必选 | 10 | 请求使用的编码格式，如utf-8,gbk,gb2312等 | `utf-8` |
| `sign_type` | String | 必选 | 10 | 请求签名算法，推荐 RSA2 | `RSA2` |
| `sign` | String | 必选 | 344 | 商户请求参数的签名串，详见[签名](https://opendocs.alipay.com/common/02khjm) | `详见示例` |
| `timestamp` | String | 必选 | 19 | 发送请求的时间，格式"yyyy-MM-dd HH:mm:ss" | `2026-09-07 10:00:00` |
| `version` | String | 必选 | 3 | 调用的接口版本，固定为：1.0 | `1.0` |
| `app_auth_token` | String | 可选 | 40 | 已获授权的第三方代调用场景使用的应用授权令牌，详见[应用授权概述](https://opendocs.alipay.com/isv/10467/xldcyq) | - |
| `biz_content` | String | 必选 | - | 业务请求参数的 JSON 字符串，字段使用 snake_case；详见下表 | - |

## 业务请求参数

业务字段统一放入 `biz_content`。下表数组子字段使用 `[]` 表示元素路径。

| 参数 | 类型 | 是否必选 | 最大长度 | 描述 | 注意事项/枚举值 | 示例值 |
| --- | --- | --- | --- | --- | --- | --- |
| `out_request_no` | String | 必选 | 128 | 平台生成的幂等请求号 | 重试保持原值与原业务参数；不同请求使用不同值 | `consume_20260907_000001` |
| `out_product_id` | String | 必选 | 128 | 平台内稳定的商品或应用标识 | - | `app_writing_001` |
| `external_owner_id` | String | 可选 | 128 | 平台内稳定的创作者或商品所有者标识 | 与配置时使用的标识一致；不是必须填写支付宝账号 | `creator_001` |
| `external_buyer_id` | String | 必选 | 128 | 平台内稳定的权益受益人标识 | 与平台登录用户绑定；不等同于付款账号 | `user_001` |
| `amount` | Number | 必选 | - | 本次核销数量，单位次数或积分 | 显式传入正整数；`COUNT` 单次扣减传 1；当前预览“长度/取值”为 99999999 | `1` |
| `consume_reason` | String | 必选 | 256 | 本次业务消费的简洁原因文本 | 必传普通文本，最长 256 字符；不传 `JSON`、用户隐私或提示词 | `生成一篇文章` |

## 常见请求示例

示例商品、用户、域名及请求号均为演示值。Java 使用包含该接口请求类的支付宝服务端 SDK；示例按公钥模式初始化，私钥仅保存在平台服务端。cURL 中的签名需在发送前按全部实际参数生成；如增加 `app_auth_token`，应一起参与签名。

::::aipay-tabs{defaultActiveKey="Java"}

:::aipay-tab{key="Java" title="Java"}
```java
import com.alipay.api.AlipayConfig;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayAipayNowpayQuotaVerifyRequest;
import com.alipay.api.response.AlipayAipayNowpayQuotaVerifyResponse;

public class NowpayExample {
    public static void main(String[] args) throws Exception {
        AlipayConfig config = new AlipayConfig();
        config.setServerUrl("https://openapi.alipay.com/gateway.do");
        config.setAppId(System.getenv("ALIPAY_APP_ID"));
        config.setPrivateKey(System.getenv("ALIPAY_PRIVATE_KEY"));
        config.setAlipayPublicKey(System.getenv("ALIPAY_PUBLIC_KEY"));
        config.setFormat("json");
        config.setCharset("UTF-8");
        config.setSignType("RSA2");
        AlipayClient client = new DefaultAlipayClient(config);

        AlipayAipayNowpayQuotaVerifyRequest request = new AlipayAipayNowpayQuotaVerifyRequest();
        request.setBizContent("{\"out_request_no\":\"consume_20260907_000001\",\"out_product_id\":\"app_writing_001\",\"external_owner_id\":\"creator_001\",\"external_buyer_id\":\"user_001\",\"amount\":1,\"consume_reason\":\"生成一篇文章\"}");
        // 仅在已获授权的第三方代调用场景设置 app_auth_token。
        String appAuthToken = System.getenv("ALIPAY_APP_AUTH_TOKEN");
        if (appAuthToken != null && !appAuthToken.isEmpty()) {
            request.putOtherTextParam("app_auth_token", appAuthToken);
        }
        AlipayAipayNowpayQuotaVerifyResponse response = client.execute(request);
        if (!response.isSuccess()) {
            // 按 code/sub_code 处理；结果未知时保留原业务请求号。
            System.out.println(response.getCode() + ":" + response.getSubCode());
            return;
        }
        // 网关成功后，按本页“结果处理”读取业务字段。
        System.out.println(response.getBody());
    }
}
```
:::

:::aipay-tab{key="cURL" title="cURL"}
```bash
biz_content='{
  "out_request_no": "consume_20260907_000001",
  "out_product_id": "app_writing_001",
  "external_owner_id": "creator_001",
  "external_buyer_id": "user_001",
  "amount": 1,
  "consume_reason": "生成一篇文章"
}'

# app_id、timestamp、sign 由平台准备；sign 必须基于本次完整参数生成。
curl --request POST 'https://openapi.alipay.com/gateway.do' \
  --data-urlencode "app_id=${app_id}" \
  --data-urlencode 'method=alipay.aipay.nowpay.quota.verify' \
  --data-urlencode 'format=json' \
  --data-urlencode 'charset=UTF-8' \
  --data-urlencode 'sign_type=RSA2' \
  --data-urlencode "timestamp=${timestamp}" \
  --data-urlencode 'version=1.0' \
  --data-urlencode "biz_content=${biz_content}" \
  --data-urlencode "sign=${sign}"
```
:::

::::

## 公共响应参数

| 参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
| --- | --- | --- | --- | --- | --- |
| `code` | String | 必选 | - | 网关返回码；10000 表示接口调用成功 | `10000` |
| `msg` | String | 必选 | - | 网关返回码说明 | `Success` |
| `sub_code` | String | 可选 | - | 业务错误码；仅用于接口失败处理 | - |
| `sub_msg` | String | 可选 | - | 业务错误说明；不用于编写固定业务分支 | - |
| `sign` | String | 必选 | - | 响应签名，位于响应根对象；由 SDK 按配置验签 | - |

响应业务对象名为 `alipay_aipay_nowpay_quota_verify_response`。先完成验签并判断 `code`，再读取业务结果。

## 业务响应参数

| 参数 | 类型 | 是否必选 | 最大长度 | 描述 | 注意事项/枚举值 | 示例值 |
| --- | --- | --- | --- | --- | --- | --- |
| `consume_status` | String | 必选 | 32 | `SUCCEEDED`/`FAILED`/`PROCESSING` | 成功:`SUCCEEDED`；失败:`FAILED`；进行中:`PROCESSING` | `SUCCEEDED` |
| `consume_order_id` | String | 可选 | 128 | 消费流水标识 | - | `202609071000000001` |
| `consume_reason` | String | 必选 | 256 | 消费原因 | 平台应持久化原始原因；查询结果可能不返回 | `生成一篇文章` |
| `quota_unit` | String | 必选 | 32 | 次数或积分，`COUNT`/`POINT` | `COUNT`：次数；`POINT`：积分 | `COUNT` |
| `consumed` | Number | 必选 | 32 | 本次实际扣减量，单位次数或积分 | 非成功状态按 0 处理，不据此确认成功 | `1` |
| `remaining` | Number | 特殊可选 | 32 | 本次核销成功时，原子扣减后的可消费余额 | 仅 `SUCCEEDED` 时使用；不是当前实时余额 | `19` |
| `reason_code` | String | 可选 | 128 | 业务结果原因码 | 结合 decision 或 `consume_status` 使用；不要按原因文案编写业务分支 | - |
| `update_time` | String | 必选 | 32 | 更新时间；格式 `yyyy-MM-dd HH:mm:ss`，时区 `Asia/Shanghai` | - | `2026-09-07 10:05:00` |

## 结果处理

| 情况 | 平台处理 |
| --- | --- |
| `code=10000` 且 `consume_status=SUCCEEDED` | 确认本次扣减，保存 consumed、remaining、consume_order_id；避免重复交付 |
| `code=10000` 且 `consume_status=FAILED` | 按 reason_code 处理，不标记核销成功 |
| `code=10000` 且 `consume_status=PROCESSING` | 保留原请求号，调用 quota.refresh 查询 |
| 余额不足业务错误 | 提示购买或补充额度，不标记消费成功 |
| 超时、系统错误、未知状态 | 标记本地待确认，使用原请求查询或重试，不换号 |

`code=10000` 不能单独作为扣减成功依据；同样不能只处理 `consume_status` 而忽略网关失败。

## 响应示例

以下为按单一业务场景整理的示例。签名、链接令牌和二维码均为占位值，不可直接使用。

::::aipay-tabs{defaultActiveKey="正常示例"}

:::aipay-tab{key="正常示例" title="正常示例"}
```json
{
  "alipay_aipay_nowpay_quota_verify_response": {
    "code": "10000",
    "msg": "Success",
    "consume_status": "SUCCEEDED",
    "consume_order_id": "202609071000000001",
    "quota_unit": "COUNT",
    "consumed": 1,
    "remaining": 19,
    "update_time": "2026-09-07 10:05:00",
    "consume_reason": "生成一篇文章"
  },
  "sign": "RESPONSE_SIGNATURE_PLACEHOLDER"
}
```
:::

:::aipay-tab{key="异常示例" title="异常示例"}
```json
{
  "alipay_aipay_nowpay_quota_verify_response": {
    "code": "20000",
    "msg": "Service Currently Unavailable",
    "sub_code": "isp.unknow-error",
    "sub_msg": "系统繁忙"
  },
  "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}
```
:::

::::

### 余额不足错误示例

```json
{
  "alipay_aipay_nowpay_quota_verify_response": {
    "code": "40004",
    "msg": "Business Failed",
    "sub_code": "NOW_PAY_QUOTA_INSUFFICIENT",
    "sub_msg": "额度不足"
  },
  "sign": "RESPONSE_SIGNATURE_PLACEHOLDER"
}
```

## 公共错误码

参见[支付宝公共错误码](https://opendoc.alipay.com/common/02km9f)。网关或系统异常时，按原请求查询或重试；写操作不能在结果未确认时更换幂等号。

## 业务错误码

以下保留当前开放平台预览已列出的错误码，并补充平台处理建议。错误码列表可能扩展，平台应保留未知错误的待确认处理。

| 错误码 | 错误描述 | 解决方案 |
| --- | --- | --- |
| `SYSTEM_ERROR` | 系统繁忙 | 稍后使用原参数重试；消费结果未知时先查询原请求 |
| `INVALID_PARAMETER` | 参数有误 | 请根据接口返回的参数非法的具体错误信息，修改参数后进行重试 |
| `BILLING_MODE_NOT_SUPPORTED` | 商品不是额度包模式 | 请核对入参参数相关的商品配置信息 |
| `CONSUME_REQUEST_NOT_FOUND` | 未找到匹配的幂等请求记录，请确认幂等号和请求状态 | 核对原请求号与商品；继续查询或原参数重试核销，不因未找到记录直接换号 |
| `NOW_PAY_QUOTA_INSUFFICIENT` | 额度不足 | 提示购买或补充额度；本次不记为核销成功 |
