把能力包成支付宝 402 付费接口
把一个确定性能力(一段脚本、一个算法、一次查询)包成支付宝 Agent 支付按量付费的 HTTP 接口。产出是一套可以直接启动的 Python 服务工程:402 响应、账单构造与 RSA2 加签、Payment-Proof 验签、订单账本、幂等重放、频率限制、履约回执重试全部就绪,能力实现只占一个插槽。
何时使用
用户要把某个能力做成按次收费的接口、接入支付宝 AI 付、给现有 API 加 402 收款、把脚本变成付费服务时使用。
不适用:包月订阅与会员体系、小程序或 APP 内支付、代办商户资质审核、把非确定性结果(每次输出都不同的模型生成内容)按固定单价售卖。
交付物
一份 python app.py 就能启动的工程:
| 文件 | 作用 | 是否要改 |
|---|---|---|
app.py |
服务骨架:HTTP 路由、402 响应、凭证校验、账本、限流、履约 | 不改 |
bill.py |
账单构造、RSA2 加签、Base64URL 编解码、Payment-Proof 解析 | 不改 |
alipay_client.py |
支付宝网关客户端:验证支付、确认履约、响应验签 | 不改 |
capability.py |
能力插槽,四个函数 | 改成用户的真实能力 |
config.json |
应用 ID、服务 ID、单价、路由、网关 | 填 5 个必填项 |
tests/ |
协议层与流程层测试 | 换成能力的用例 |
前置:先做环境检查
生成工程前跑一次只读检查,不改配置、不登录、不输出凭据值:
python scripts/check_environment.py --capability scaffold-project
| 状态 | 处理 |
|---|---|
| ready | 跳过配置讲解,直接进入主流程 |
| partial | 进入主流程,在交付说明里标注受影响的环节 |
| needs_setup | 只展示缺失必需项的配置入口,配好后重新检查 |
| unavailable | 说明是版本、权限还是网络问题;Python 运行时缺失时停止生成 |
要让工程真正收到钱,还必须有支付宝应用凭据和一个公网 HTTPS 地址。这两项在生成阶段不是必需,在联调上线阶段必需:
python scripts/check_environment.py --capability gateway-interaction --capability integration-guidance
缺失时读 references/setup-guide.md。不要在对话里要求用户粘贴私钥或公钥正文。
主流程
第一步 问清三件事
只问这三件,不问别的:
- 能力是什么:一句话说清输入什么、输出什么。要确定性——同样的输入必须给同样的输出,否则按次收费会产生争议。
- 计费单元是什么:一单收一次,还是按条数、字数、调用次数收。这个定义决定
units()返回什么。 - 单价与路由:每次收多少元、对外暴露的路径是什么,例如
/v1/leads/score。
计费单元说不清时,默认按「每次请求 = 1 个单元」处理,并明确告知用户。
第二步 生成工程
先不加 --write-confirmed 看计划,确认后再加:
python scripts/scaffold.py --name lead-scoring-api --label "线索打分排序" \
--route /v1/leads/score --amount 1.00 --output-dir <父目录>
--name同时是目录名和环境变量前缀,kebab-case。--label是收银台上展示给买家的商品名。--amount必须与控制台「注册新服务」时填的单价一致,否则买家无法完成支付。- 目标目录已存在时脚本拒绝写入,不覆盖任何已有内容。
生成后脚本会自动编译校验 app.py 与 capability.py,编译不过直接报错,不会留下半成品。
第三步 写能力插槽
把 capability.py 改成用户的真实能力。四个函数的契约、参数、返回值、错误约定见 references/capability-contract.md。
改动只允许落在这个文件里。app.py、bill.py、alipay_client.py 不建议修改,改了要同步更新 tests/。
第四步 自检与实测
python app.py --check # 配置完整性、密钥可读性、自签自验
python -m unittest discover -s tests -t . # 协议层与流程层测试
--check 必须看到 ready: true 与 self_check.ok: true。然后按 README.md 的方式真启动一次服务,发一个不带支付凭证的请求,确认收到的确实是 402 且响应头里带 Payment-Needed。
真实收款链路的联调步骤见 references/console-registration.md。
第五步 交付
给用户这四样:
- 工程目录,
config.json里 5 个必填项标出来源。 - 启动命令、自检命令、测试命令。
- 控制台注册服务要填的字段与值的对应表。
- 未覆盖范围:没有真实网关联调、没有真实收款验证、部署与域名备案不在范围内。
价格口径
- 默认单一固定价:任何计费单元数都收
amount。控制台单价只能填一个数,阶梯价会出现「注册一个价、实收另一个价」的偏差,默认不启用。 price_tiers是可选阶梯价。启用前先用一笔真实小额订单确认控制台不拦,并确认amount已设成超出最大阶梯后的价格。- 金额一律用字符串写进配置,避免浮点误差;比较金额时按分对齐。
- 支付宝按笔收服务费,费率与阶段性优惠以官方产品页当前公示为准,不要凭记忆报数。
输出前自查
- [ ] 工程的 5 个必填项都有明确来源,没有留空就交付
- [ ]
python app.py --check输出ready: true且self_check.ok: true - [ ] 测试全绿,失败项逐个说明原因,不跳过
- [ ] 一次真实请求确认返回 402 且带
Payment-Needed头 - [ ]
config.json的amount与控制台填的单价一致 - [ ] 私钥、公钥没有出现在任何工程文件、日志和对话里
- [ ] 未实测的部分已明确标注,没有说成已通过
绝不做什么
- 不代替用户注册支付宝服务、不代提交审核、不代办资质。
- 不要求也不接收用户在对话里粘贴私钥明文;只接受环境变量或本机文件路径。
- 不生成绕过支付宝校验、伪造履约回执或伪造支付凭证的代码。
- 不在未获确认时覆盖已存在的目录或文件。
- 不承诺上线结果;生产网关联调结论以实际调用为准。
- 不把推断写成事实:没跑过的测试标未实测,没联调过的链路标未验证。
停止条件
出现以下任一情况时停下来说明原因,不用低可信结果顶替:
- 用户要按固定单价售卖非确定性结果,且不接受改为按次固定价加结果说明。
- 用户说不出计费单元,也不接受默认的「一次请求一个单元」。
- 用户要求跳过自检与测试直接上线。
- 用户要求把私钥写进代码、配置文件或提交进版本库。
- 用户要求实现绕过平台校验或伪造回执的逻辑。