PAYATHON 2026

alipay.data.bill.sell.query是否有Python开发案例?

支付阿杰

结论

Python 可以调用 alipay.data.bill.sell.query,但未必能找到这个接口专用的官方 Python 示例。一般有两种调用方式:

  1. 使用支付宝开放平台 Python SDK,通过对应的 Request 类发送请求。
  2. 如果当前 SDK 不包含该接口的 Request 类,则按照支付宝开放平台的签名规范直接发送 HTTP 请求。

alipay.data.bill.sell.query 是较早期的账单查询接口。开发前需要查阅支付宝开放平台的当前文档,确认该接口能否申请、应用是否已获得调用权限,以及接口使用 biz_content 还是旧式业务参数格式。下面的代码采用常见的 OpenAPI RSA2 调用方式。

调用前的准备

调用接口需要准备:

  • 支付宝应用的 app_id
  • 应用私钥
  • 支付宝公钥
  • 接口所需的产品权限
  • 接口文档规定的业务参数

安装依赖:

pip install requests cryptography

应用私钥通常采用 PKCS#8 格式,例如:

-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----

不要把私钥提交到代码仓库。可以通过环境变量或密钥管理服务读取私钥。

Python 请求示例

下面的示例会生成 RSA2 签名并请求支付宝网关。biz_content 中的字段必须按照当前接口文档填写,示例中的占位内容不是该接口的正式参数。

import base64
import json
import os
from datetime import datetime

import requests
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding


ALIPAY_GATEWAY = "https://openapi.alipay.com/gateway.do"
APP_ID = os.environ["ALIPAY_APP_ID"]
APP_PRIVATE_KEY = os.environ["ALIPAY_APP_PRIVATE_KEY"]


def rsa2_sign(unsigned_text: str, private_key_text: str) -> str:
    private_key = serialization.load_pem_private_key(
        private_key_text.encode("utf-8"),
        password=None,
    )

    signature = private_key.sign(
        unsigned_text.encode("utf-8"),
        padding.PKCS1v15(),
        hashes.SHA256(),
    )

    return base64.b64encode(signature).decode("utf-8")


def build_sign_content(params: dict) -> str:
    items = []

    for key in sorted(params):
        value = params[key]
        if value is None or value == "":
            continue
        items.append(f"{key}={value}")

    return "&".join(items)


def query_sell_bill(biz_content: dict) -> dict:
    params = {
        "app_id": APP_ID,
        "method": "alipay.data.bill.sell.query",
        "format": "JSON",
        "charset": "utf-8",
        "sign_type": "RSA2",
        "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "version": "1.0",
        "biz_content": json.dumps(
            biz_content,
            ensure_ascii=False,
            separators=(",", ":"),
        ),
    }

    sign_content = build_sign_content(params)
    params["sign"] = rsa2_sign(sign_content, APP_PRIVATE_KEY)

    response = requests.post(
        ALIPAY_GATEWAY,
        data=params,
        timeout=30,
    )
    response.raise_for_status()
    return response.json()


if __name__ == "__main__":
    # 请用接口文档中规定的真实业务参数替换。
    request_data = {
        # "字段名": "字段值",
    }

    result = query_sell_bill(request_data)
    print(json.dumps(result, ensure_ascii=False, indent=2))

这段代码没有假设 alipay.data.bill.sell.query 的具体业务字段。是否支持账单时间、页码和每页数量等参数,以及这些参数的字段名与格式,都要以开发者后台显示的当前接口文档为准。

使用支付宝 Python SDK

如果已安装的支付宝 Python SDK 包含该接口对应的 Request 类,可以优先使用 SDK。先尝试导入:

from alipay.aop.api.request.AlipayDataBillSellQueryRequest import (
    AlipayDataBillSellQueryRequest,
)

如果出现以下错误:

ModuleNotFoundError

通常说明当前 SDK 没有包含这个接口类,不代表 Python 无法调用该接口。可以继续检查:

  • 安装的 SDK 是否为支付宝开放平台提供或推荐的版本;
  • SDK 的 request 目录中是否存在对应类;
  • SDK 是否提供通用请求能力;
  • 是否可以使用前面的 HTTP 签名方式调用。

不要自行创建同名 Request 类,并据此认定 SDK 已经支持该接口。接口的参数序列化和响应映射也可能存在差异。

返回结果处理

成功响应的主体通常位于与方法名对应的节点中:

response_body = result.get("alipay_data_bill_sell_query_response", {})

code = response_body.get("code")
msg = response_body.get("msg")
sub_code = response_body.get("sub_code")
sub_msg = response_body.get("sub_msg")

if code == "10000":
    print("查询成功")
    print(response_body)
else:
    print(f"查询失败:code={code}, msg={msg}")
    print(f"业务错误:sub_code={sub_code}, sub_msg={sub_msg}")

响应节点名称和成功码仍要以该接口的当前文档为准。如果接口采用旧版协议,返回结构可能不同于上述 OpenAPI 格式。

常见问题

签名验证失败

可以逐项检查:

  • 待签名参数是否按参数名排序;
  • 签名前是否对签名原文中的值做了 URL 编码;
  • biz_content 在签名前后是否完全一致;
  • 是否使用 RSA2,也就是 SHA-256;
  • 应用私钥是否与开放平台配置的应用公钥匹配;
  • 请求字符集是否统一为 UTF-8。

签名时要使用原始参数值。传输阶段的 URL 编码交给 HTTP 客户端处理,不要先编码参数值再计算签名。

接口无权限

如果接口返回权限不足或产品未签约等错误,需要到支付宝开放平台检查应用的签约状态和接口权限。修改 Python 代码无法绕过权限限制。

查询不到历史账单

账单接口通常会限制可查询的时间范围、单次查询跨度、分页数量或账单生成时间。具体限制可能随产品调整,请以当前接口文档和实际返回的错误码为准。

生产环境必须验签

上面的示例主要用于说明请求签名。生产环境还要使用支付宝公钥验证响应签名,不能只根据返回 JSON 中的 code 判断响应是否可信。验签时需要保留网关返回的原始响应内容,以免重新序列化 JSON 后改变验签原文。

备注:内容仅供参考。