﻿# 用户商品权益查询接口

## 接口说明

接口名称：`alipay.aipay.nowpaydirect.purchase.consult`

查询指定应用用户是否拥有可使用的买断或时长包权益。需要购买且商品可购买时，同时返回支付宝托管购买页入口。

## 适用场景

- 买断或时长包用户进入付费功能前校验访问权限。
- 用户从支付页返回后重新确认权益。
- 时长包需要展示当前权益有效期。

## 注意事项

- 仅适用于 `ONE_TIME` 和 `ONE_TIME_DURATION`。`QUANTITY` 商品应使用 `quota.query`，并在消费时调用 `quota.verify`。
- 只有 decision=`ALLOW` 才放行。`PURCHASE_REQUIRED` 引导用户使用返回的购买入口；`DENY` 不放行、不展示新的购买入口。
- `callback_url` 只表示页面返回。用户返回后必须再次查询本接口；不要根据跳转、前端参数或本地缓存认定支付和权益成功。
- 时长包有效区间为 [`valid_from`, `valid_until`)，到达 `valid_until` 后不再有效；永久买断不返回这两个时间字段。已有有效买断或时长权益时不引导再次购买。
- 商品停止新增购买后，已有有效权益仍可能返回 `ALLOW`。放行以 decision 为准，不能仅按 `capability_status` 决定。
- 本接口不接收 `out_request_no`，多次查询不承诺复用同一购买链接。
- `callback_url` 建议统一使用完整 `HTTPS` 地址

## 公共请求参数

| 参数 | 类型 | 是否必选 | 长度/取值 | 描述 | 示例值 |
| --- | --- | --- | --- | --- | --- |
| `app_id` | String | 必选 | 32 | 支付宝分配给开发者的应用ID | `YOUR_APP_ID` |
| `method` | String | 必选 | 128 | 接口名称 | `alipay.aipay.nowpaydirect.purchase.consult` |
| `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-27 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；详见下表 | - |

## 业务请求参数

| 参数 | 类型 | 是否必选 | 长度/取值 | 描述 | 注意事项/枚举值 | 示例值 |
| --- | --- | --- | --- | --- | --- | --- |
| `out_product_id` | String | 必选 | 128 | 直连商品的外部商品 `ID`，从管理小程序商品详情页复制 | 使用当前商户创建的商品；不要自行生成或使用内部商品号 | `np_d_f83a7c91` |
| `external_buyer_id` | String | 必选 | 128 | 应用内稳定的权益受益人标识 | 与应用登录用户绑定；不等同于付款账号 | `user_001` |
| `callback_url` | String | 可选 | 128 | 购买完成返回地址 | 页面返回地址，不是异步通知地址；返回后重新查询状态 | `https://app.example.com/nowpay/purchase-return` |

## 常见请求示例

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

::::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.AlipayAipayNowpaydirectPurchaseConsultRequest;
import com.alipay.api.response.AlipayAipayNowpaydirectPurchaseConsultResponse;

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);

        AlipayAipayNowpaydirectPurchaseConsultRequest request = new AlipayAipayNowpaydirectPurchaseConsultRequest();
        request.setBizContent("{\"out_product_id\":\"np_d_f83a7c91\",\"external_buyer_id\":\"user_001\",\"callback_url\":\"https://app.example.com/nowpay/purchase-return\"}");
        // 仅在已获授权的第三方代调用场景设置 app_auth_token。
        String appAuthToken = System.getenv("ALIPAY_APP_AUTH_TOKEN");
        if (appAuthToken != null && !appAuthToken.isEmpty()) {
            request.putOtherTextParam("app_auth_token", appAuthToken);
        }
        AlipayAipayNowpaydirectPurchaseConsultResponse 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_product_id": "np_d_f83a7c91",
  "external_buyer_id": "user_001",
  "callback_url": "https://app.example.com/nowpay/purchase-return"
}'

# 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.nowpaydirect.purchase.consult' \
  --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_nowpaydirect_purchase_consult_response`。先完成验签并判断 `code`，再读取业务结果。

## 业务响应参数

| 参数 | 类型 | 是否必选 | 长度/取值 | 描述 | 注意事项/枚举值 | 示例值 |
| --- | --- | --- | --- | --- | --- | --- |
| `decision` | String | 必选 | 32 | 当前访问决策 | `ALLOW`：允许访问；`PURCHASE_REQUIRED`：需要购买；`DENY`：不允许访问且不引导购买 | `ALLOW` |
| `reason_code` | String | 可选 | 128 | 业务结果原因码 | 结合 decision 使用；不要按原因文案编写业务分支 | - |
| `valid_from` | String | 特殊可选 | 128 | 表示本次有效权益的生效时间；格式 `yyyy-MM-dd HH:mm:ss`，时区 `Asia/Shanghai` | 仅 `ONE_TIME_DURATION` 且 decision=`ALLOW` 时返回；有效区间 [`valid_from`, `valid_until`) | `2026-09-27 10:00:00` |
| `valid_until` | String | 特殊可选 | 128 | 表示本次有效权益的结束时间；格式 `yyyy-MM-dd HH:mm:ss`，时区 `Asia/Shanghai` | 仅 `ONE_TIME_DURATION` 且 decision=`ALLOW` 时返回；有效区间 [`valid_from`, `valid_until`) | `2026-10-27 10:00:00` |
| `product_name` | String | 可选 | 128 | 商品名称 | - | `智能写作助手` |
| `product_icon_url` | String | 可选 | 1024 | 商品图标 | - | `https://app.example.com/assets/writing.png` |
| `capability_status` | String | 必选 | 32 | 商品收费能力状态 | `NOT_CONFIGURED` / `CONFIGURING` / `PENDING` / `ENABLED` / `DISABLED` / `TERMINATED` | `ENABLED` |
| `purchase_url` | String | 特殊可选 | 512 | 购买链接 | `PURCHASE_REQUIRED` 返回 | `alipays://platformapi/startapp?appId=2021006180624128&page=pages%2Forder%2Findex%3FpurchaseLinkId%3DSAMPLE_LINK_ID` |
| `purchase_qr_code` | String | 特殊可选 | 512 | 购买二维码 | `PURCHASE_REQUIRED` 返回 | `https://mobilecodec.alipay.com/show.htm?code=SAMPLE_QR_CODE` |
| `charging_options` | Object[] | 必选 | - | 当前商品的收费档位列表 | 可能为空数组；子字段必选性适用于实际返回的档位元素 | - |
| `charging_options[].sku_id` | String | 必选 | 32 | 档位标识 | 按不透明标识保存和回传，不解析内容 | `S0806000200863004` |
| `charging_options[].display_name` | String | 必选 | 128 | 档位名称 | - | `月度使用包` |
| `charging_options[].price` | String | 必选 | 32 | 展示价格，十进制，单位元 | - | `9.90` |
| `charging_options[].duration_period` | String | 特殊可选 | 32 | 时长包周期类型 | `billing_mode`=`ONE_TIME_DURATION` 时返回；`WEEK` / `MONTH` / `QUARTER` / `YEAR` | `MONTH` |
| `charging_options[].quota_amount` | Number | 特殊可选 | 32 | 额度数量 | 通用档位结构保留字段；仅额度包适用，本接口不返回 | - |

## 结果处理

| decision | 应用处理 |
| --- | --- |
| `ALLOW` | 放行；时长包可展示 valid_from、valid_until |
| `PURCHASE_REQUIRED` | 使用 purchase_url 或 purchase_qr_code 引导购买；返回后重新查询 |
| `DENY` | 不放行、不新建购买入口；根据 reason_code 展示说明或稍后刷新 |

`reason_code` 是业务结果原因，不能代替 `decision`。常见拒绝原因包括权益暂不可用、商品已停用或需要创作者处理。

## 响应示例

以下示例仅使用公开预览定义的字段，并按单一业务场景整理。签名、链接令牌和二维码均为占位值，不可直接使用。

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

:::aipay-tab{key="正常示例" title="正常示例"}
```json
{
  "alipay_aipay_nowpaydirect_purchase_consult_response": {
    "code": "10000",
    "msg": "Success",
    "decision": "ALLOW",
    "valid_from": "2026-09-27 10:00:00",
    "valid_until": "2026-10-27 10:00:00",
    "product_name": "智能写作助手",
    "capability_status": "ENABLED",
    "charging_options": [
      {
        "sku_id": "S0806000200863004",
        "display_name": "月度使用包",
        "price": "9.90",
        "duration_period": "MONTH"
      }
    ]
  },
  "sign": "RESPONSE_SIGNATURE_PLACEHOLDER"
}
```
:::

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

::::

### 需要购买示例

```json
{
  "alipay_aipay_nowpaydirect_purchase_consult_response": {
    "code": "10000",
    "msg": "Success",
    "decision": "PURCHASE_REQUIRED",
    "capability_status": "ENABLED",
    "charging_options": [
      {
        "sku_id": "S0806000200863004",
        "display_name": "月度使用包",
        "price": "9.90",
        "duration_period": "MONTH"
      }
    ],
    "purchase_url": "alipays://platformapi/startapp?appId=2021006180624128&page=pages%2Forder%2Findex%3FpurchaseLinkId%3DSAMPLE_LINK_ID",
    "purchase_qr_code": "https://mobilecodec.alipay.com/show.htm?code=SAMPLE_QR_CODE"
  },
  "sign": "RESPONSE_SIGNATURE_PLACEHOLDER"
}
```

## 公共错误码

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

## 业务错误码

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

| 错误码 | 错误描述 | 解决方案 |
| --- | --- | --- |
| `SYSTEM_ERROR` | 系统繁忙 | 稍后使用原参数重试；消费结果未知时先查询原请求 |
| `INVALID_PARAMETER` | 参数有误 | 请根据接口返回的参数非法的具体错误信息，修改参数后进行重试 |
| `BILLING_MODE_NOT_SUPPORTED` | 当前商品收费模式不适用于访问决策 | 仅买断和时长包使用本接口；额度包改用 `quota.query` |
| `NOW_PAY_BINDING_INVALID` | 商品未绑定或未查到已上架商品 | 请核对商品是否已开通上架 |