alipay.data.bill.sell.query是否有Python开发案例?
结论
Python 可以调用 alipay.data.bill.sell.query,但未必能找到这个接口专用的官方 Python 示例。一般有两种调用方式:
- 使用支付宝开放平台 Python SDK,通过对应的 Request 类发送请求。
- 如果当前 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 后改变验签原文。
备注:内容仅供参考。
