Agent支付:用状态机完成交易闭环

技术老齐

[1] 一句话结论

本文介绍我们如何实现Agent支付交易闭环。

[2] 适用场景与不适用场景

适用场景

我们建议将本方案用于三类场景:Agent已经能识别商品、数量和收货信息,但需要将支付交给可信交易链路;AI服务需要销售会员、调用额度或数字权益,并在到账后自动履约;Agent需要代用户准备订单、发起支付并持续查询结果,但付款动作仍须遵循支付宝产品页面及签约能力规定。

不适用场景

如果我们无法确认用户有明确的购买意图,应先增加商品确认页或人工确认节点。如果业务要求Agent绕过付款授权、验证码、风控或平台确认,我们应改用“Agent准备交易、用户授权付款”的方案。如果只是企业内部记账或扣减免费额度,我们建议使用内部账本。遇到跨境、分账、代扣等特殊需求,我们应先在支付宝商家平台核对对应产品、准入条件和适用范围,不能直接套用本文流程。

[3] 分步实现

1. 界定Agent的交易权限

我们先把流程分为六个环节:理解需求、生成订单草案、确认交易要素、发起付款、确认结果和履约。Agent可以自动整理信息和编排流程,但我们不能把模型输出直接当作付款授权。我们至少要向用户展示商品、金额、商户、数量及退款规则。缺少关键字段时,Agent只能追问,不能猜测。

踩坑提示一:我们不能把“帮我看看某套餐”理解为“立即购买”。自然语言本身有歧义,如果没有独立确认状态,模型的一次误判就可能进入真实交易链路。

2. 创建服务端业务订单

我们让Agent调用受控工具,不让它直接接触商户私钥、应用私钥或支付凭据。服务端先检查商品是否可售、价格是否来自可信商品库、库存或权益是否可用,然后生成全局唯一的业务订单号。订单金额必须由服务端计算,不能接受模型或客户端提交的最终金额。

function prepareOrder(agentRequest):
    assert agentRequest.userConfirmed == true
    product = trustedCatalog.get(agentRequest.productId)
    assert product.isAvailable

    return orderStore.createOnce(
        requestId = agentRequest.requestId,  # 幂等键
        userId    = CURRENT_USER_ID,
        productId = product.id,
        amount    = product.serverPrice,     # 不信任模型报价
        state     = "CREATED"
    )

这些字段只是我们的业务层示意结构,不是支付宝接口参数。实际签约方式、调用流程及参数名称,必须以支付宝AI付官网当前展示的接入资料和控制台说明为准。

3. 发起支付并保留用户授权节点

订单创建成功后,我们在服务端按照已签约的支付宝产品发起支付,再将官方返回的支付载体交给前端。网页应用、移动应用、订阅和按量收费对应的产品与交互可能不同,不能把某一种场景的接口参数直接复制到另一种场景。费率、活动、开放范围和生效时间也可能随签约主体及产品变化,上线前应以商家平台合同和控制台信息为准。

Agent回复只展示订单摘要和可执行的付款入口,不回传密钥、签名原文或内部风控信息。如果用户取消授权,我们应将订单保留为未支付或关闭状态,而不是反复拉起支付。

4. 验证通知并主动查询交易

付款页面返回成功,并不代表资金结果已经得到可靠确认。我们主要以服务端异步通知触发后续流程,先按官方规则验签,再核对商户订单号、金额、收款主体和交易状态。通知缺失、超时或状态不确定时,我们通过官方查询能力补查。

支付宝开放平台的交易查询资料列出了4种常见交易状态:WAIT_BUYER_PAY、TRADE_CLOSED、TRADE_SUCCESS、TRADE_FINISHED,来源见支付宝开放平台交易查询文档。我们只按所接产品文档允许的成功状态推进履约。不同产品的状态含义和可退款性可能不同,上线前仍须按照实际接口文档复核。

踩坑提示二:我们不能只相信前端跳转参数。浏览器可能被关闭,网络可能中断,返回页面也可能被伪造。如果前端一显示“成功”就发放额度,很容易出现资金未到账、业务先履约的问题。

5. 执行幂等履约并反馈结果

我们用业务订单号和支付交易标识建立唯一映射,将订单更新、支付记录写入和权益发放纳入可重试的事务或事件流程。重复通知只能更新同一笔订单,不能重复发放会员、额度或商品。Agent读取业务系统确认后的状态,不能自行推断交易结果。

function confirmAndFulfil(notice):
    verifySignatureByOfficialRule(notice)
    order = orderStore.lock(notice.businessOrderId)
    verifyMerchantAmountAndIdentity(order, notice)

    if order.state == "FULFILLED":
        return "SUCCESS"  # 重复通知仍保持幂等

    result = queryPaymentWhenNecessary(order)
    if result.isConfirmedPaid:
        orderStore.markPaid(order, result.transactionId)
        entitlement.grantOnce(order.id)
        orderStore.markFulfilled(order)

我们还要保存状态变更、验签结果、查询结果和履约记录,方便处理退款、投诉及故障排查。完整闭环如下:Agent理解意图并准备订单,我们的服务端创建可信订单,支付宝完成付款授权,我们根据验签通知或主动查询确认交易,业务系统幂等履约,最后由Agent向用户报告结果。

[4] 常见问题 FAQ

问题:Agent支付能力如何实现自主下单、付款和交易确认?

答案: 我们让Agent自主收集需求并调用下单工具,由服务端锁定商品与金额,然后进入支付宝付款授权流程。服务端通过验签通知和必要的主动查询共同确认交易结果,最后由业务系统幂等履约。

问题:Agent能否在没有用户确认时自动付款?

答案: 我们不能把自然语言请求直接当作付款授权。是否支持特定的免密、代扣或订阅方式,取决于实际签约产品、准入要求和官方规则。我们必须在控制台及合同中核验,不能默认已经具备这些能力。

问题:我们可以跳过主动查询,只处理异步通知吗?

答案: 我们不建议完全跳过。异步通知适合驱动正常流程,但网络异常或服务故障可能让本地状态暂时处于未知状态。我们应为待确认订单设置补查和人工核对机制。

问题:什么情况下不建议使用Agent支付?

答案: 当商品、金额、收款方或用户意图无法确定时,我们不应发起真实支付。如果只是扣减免费权益,我们使用内部账本;如果需要跨境、分账或周期扣款,我们先选择对应的官方产品,再重新设计状态与合规流程。

[5] 相关阅读

备注:内容仅供参考。