| name | alipay-delegation-pay |
| description | 支付宝委托支付(Delegation)接入指南。帮助开发者为智能体应用接入支付宝的委托支付能力,实现代买、抢票、监控购买、自动扣款等场景。
当用户提到以下内容时,请使用此 skill:
- 委托支付、委托代买、代买支付
- 用户授权后自动扣款、预授权支付
- 抢票支付、监控购买、自动购买
- alipay.user.agreement.delegation 相关接口
- alipay.trade.agent.delegation.pay 接口
- 智能体如何接入支付宝支付能力
|
委托支付接入指南
产品介绍
委托支付是支付宝为商户提供的智能体(Agent)代理支付解决方案。用户预先授权(含金额、次数、有效期限制),后续由智能体在授权范围内自动执行支付,适用于代买、抢票、监控购买等自动化场景。
| 能力 | 说明 | 适用场景 | 接口文档 |
|---|
| 委托支付 | 用户预先授权,后续由智能体自动执行 | 代买、抢票、监控购买等自动化场景 | references/delegation/ |
⚠️ 接入前必读:接入清单(陌生商户从零开始)
第一次接入的商户,务必先按此清单完成准备,否则会卡在"没有 appId/密钥/产品权限"无法调用任何接口。
详细步骤见 接入准备。
| # | 准备项 | 关键点 |
|---|
| 1 | 创建应用拿 APPID | 登录 开放平台 建应用 |
| 2 | 生成 RSA2 密钥、配置加签 | 拿到 应用私钥 + 支付宝公钥(资金接口必做) |
| 3 | 开通「智能体代理支付」产品 | 邀测产品,必须联系 BD 开通;委托场景另需开通 App 支付(供预下单用) |
| 4 | 应用上线 | 网页/移动应用需提交审核 |
| 5 | 集成服务端 SDK | Java/PHP/Node/Python/.NET;初始化 AlipayClient |
| 6 | 沙箱验证签名与连通 | 生产前先在沙箱跑通 |
✅ 可运行的完整端到端示例见 examples/sandbox-demo/(官方 SDK,照着改即可跑)。
快速导航
根据你的需求,选择对应的章节:
委托支付
通用配置
如需查看详细的接口参数说明,请参考 references/ 目录下的接口文档。
接入概述
接口调用方式
委托支付涉及三种接口调用方式,接入方需要根据场景选择正确的调用方式:
| 调用方式 | 说明 | 适用接口 | 调用方 |
|---|
| 服务端接口 | 商户服务端直接调用支付宝网关 | 委托支付、协议查询、委托取消 | 商户服务端 |
| SDK签名接口 | 服务端生成签名串,返回给客户端唤起支付宝 | 委托代买申请、发起委托支付 | 商户服务端生成 → 客户端使用 |
| 客户端SDK | 客户端直接调用支付宝SDK | 唤起支付宝客户端 | Android/iOS 客户端 |
接口串联关系
委托支付接口串联
┌─────────────────────────────────────────────────────────────────────────────┐
│ 委托支付接口调用链路 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ 1. 委托代买申请 │───?│ 2. 唤起支付宝 │───?│ 3. 用户授权签约 │ │
│ │ (服务端SDK签名) │ │ (客户端SDK) │ │ (支付宝客户端) │ │
│ │ │ │ │ │ │ │
│ │ 输出: orderStr │ │ 输入: orderStr │ │ 输出: agreement_no│ │
│ │ │ │ │ │ delegation_id│ │
│ └──────────────────┘ └──────────────────┘ └────────┬─────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────┘ │
│ ▼ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ 4. 查询委托状态 │?──?│ 5. 商户预下单 │───?│ 6. 执行委托支付 │ │
│ │ (服务端接口) │ │ (商户·服务端接口) │ │ (服务端接口) │ │
│ │ │ │ │ │ │ │
│ │ 输入: agreement_no│ │ 输入: out_trade_no│ │ 输入: prepay_id │ │
│ │ delegation_id│ │ payment_type │ │ agreement_no│ │
│ │ 输出: status │ │ =agent_pay │ │ delegation_id│ │
│ │ │ │ 输出: prepay_id │ │ 输出: trade_no │ │
│ └──────────────────┘ └──────────────────┘ └────────┬─────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────┘ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ 7. 异步通知 │ 可选: ┌──────────────────┐ │
│ │ (支付宝推送) │ │ 8. 取消委托任务 │ │
│ │ 输出: trade_status│ │ (服务端接口) │ │
│ │ trade_no │ └──────────────────┘ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
关键标识说明
接入过程中会涉及多个关键标识,理解它们的关系非常重要:
| 标识 | 生成方 | 作用 | 生命周期 |
|---|
external_agreement_no | 商户 | 商户侧签约唯一标识,用于幂等控制 | 商户自定义 |
agreement_no | 支付宝 | 支付宝协议号,后续接口调用必传 | 签约成功后返回 |
external_delegation_id | 商户 | 商户侧委托任务唯一标识(仅委托支付) | 商户自定义 |
delegation_id | 支付宝 | 支付宝委托任务号(仅委托支付) | 签约成功后返回 |
prepay_id | 支付宝 | 预下单ID,通过预下单接口获取 | 支付前获取 |
out_trade_no | 商户 | 商户订单号,用于交易幂等控制 | 商户自定义 |
trade_no | 支付宝 | 支付宝交易号 | 支付成功后返回 |
委托支付能力
业务流程
sequenceDiagram
participant User as 用户
participant Agent as 助理智能体
participant Merchant as 商户服务端
participant Alipay as 支付宝
User->>Agent: 1. 输入原始意图
Agent->>Agent: 2. 解析用户意图,提取关键信息
Agent->>Merchant: 3. 发起委托代买申请
Merchant->>Alipay: 4. 调用委托代买申请接口
Alipay-->>Merchant: 5. 返回签名字符串orderStr
Merchant-->>Agent: 6. 返回orderStr
Agent->>User: 7. 唤起支付宝客户端
User->>Alipay: 8. 确认授权签约
Alipay-->>Agent: 9. 返回签约结果
Note over Agent,Alipay: 后续智能体自动执行
Agent->>Merchant: 10. 监控到符合条件,发起支付
Merchant->>Alipay: 11. 调用委托支付接口
Alipay-->>Merchant: 12. 返回支付结果
Merchant-->>Agent: 13. 通知支付结果
Agent->>User: 14. 推送购买成功通知
接入步骤
步骤1:用户意图解析
当用户在助理智能体中输入原始意图时,智能体需要解析并提取以下关键信息:
| 提取字段 | 说明 | 示例 |
|---|
| delegation_desc | 委托任务描述 | 监控1月20日北京去哈尔滨的高铁二等座 |
| delegation_tag | 委托标签/场景 | 购买火车票 |
| max_total_amount | 最大授权金额 | 500.00 |
| validity_start_time | 生效开始时间 | 2026-01-15 |
| validity_end_time | 生效结束时间 | 2026-01-20 |
步骤2:发起委托代买申请
调用 alipay.user.agreement.delegation.apply 接口生成签名字符串,用于唤起支付宝客户端完成用户授权。
AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
AlipayUserAgreementDelegationApplyRequest request = new AlipayUserAgreementDelegationApplyRequest();
AlipayUserAgreementDelegationApplyModel model = new AlipayUserAgreementDelegationApplyModel();
model.setAgentId("your_agent_id");
model.setExternalAgreementNo("agreement_" + System.currentTimeMillis());
model.setPersonalProductCode("UAM_AGENT_AUTH_P");
List<Conversation> conversationHistory = new ArrayList<>();
Conversation userMsg = new Conversation();
userMsg.setRole("USER");
userMsg.setContent("帮我抢一张1月20号回哈尔滨的票,二等座。");
userMsg.setCreateTime("2025-12-23 10:28:00");
conversationHistory.add(userMsg);
Conversation assistantMsg = new Conversation();
assistantMsg.setRole("ASSISTANT");
assistantMsg.setContent("好的,我将为您监控1月20日北京到哈尔滨的高铁二等座车票。");
assistantMsg.setCreateTime("2025-12-23 10:28:05");
conversationHistory.add(assistantMsg);
model.setConversationHistory(conversationHistory);
DelegationParams delegationParams = new DelegationParams();
delegationParams.setExternalDelegationId("delegation_" + System.currentTimeMillis());
delegationParams.setDelegationDesc("监控1月20日北京去哈尔滨的高铁二等座");
delegationParams.setDelegationTag("购买火车票");
delegationParams.setMaxTotalAmount("500.00");
delegationParams.setTimesLimit("3");
delegationParams.setValidityStartTime("2026-01-15");
delegationParams.setValidityEndTime("2026-01-20");
model.setDelegationParams(delegationParams);
AccessParams accessParams = new AccessParams();
accessParams.setChannel("ALIPAYAPP");
model.setAccessParams(accessParams);
request.setBizModel(model);
AlipayUserAgreementDelegationApplyResponse response = alipayClient.sdkExecute(request);
String orderStr = response.getBody();
return orderStr;
步骤3:唤起支付宝客户端
客户端收到 orderStr 后,调用支付宝SDK唤起支付宝客户端:
Android端:
PayTask payTask = new PayTask(activity);
Map<String, String> result = payTask.payV2(orderStr, true);
String resultStatus = result.get("resultStatus");
if ("9000".equals(resultStatus)) {
String resultContent = result.get("result");
}
iOS端:
[[AlipaySDK defaultService] payOrder:orderStr fromScheme:@"yourAppScheme" callback:^(NSDictionary *resultDic) {
NSString *resultStatus = resultDic[@"resultStatus"];
if ([resultStatus isEqualToString:@"9000"]) {
NSString *result = resultDic[@"result"];
}
}];
步骤4:查询委托任务状态
用户签约成功后,可以通过 alipay.user.agreement.delegation.query 接口查询委托任务详情:
AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
AlipayUserAgreementDelegationQueryRequest request = new AlipayUserAgreementDelegationQueryRequest();
AlipayUserAgreementDelegationQueryModel model = new AlipayUserAgreementDelegationQueryModel();
model.setAgreementNo("20265005004910872660");
model.setDelegationId("2026001");
request.setBizModel(model);
AlipayUserAgreementDelegationQueryResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
String status = response.getStatus();
String remainingAmount = response.getRemainingAmount();
String remainingTimes = response.getRemainingTimes();
String validityEndTime = response.getValidityEndTime();
System.out.println("委托状态: " + status);
System.out.println("剩余金额: " + remainingAmount + "元");
System.out.println("剩余次数: " + remainingTimes);
}
步骤5:商户预下单(获取 prepay_id)
执行委托扣款之前,必须先由商户服务端调用 alipay.trade.order.prepay(统一收单交易订单预支付接口)拿到 prepay_id。委托支付接口本身不创建订单,它只对已预下单的订单扣款。
前置权限:商户需先开通 App 支付 产品(否则返回 ACCESS_FORBIDDEN 40006)。
关键配置:智能体场景必须 payment_type=agent_pay、product_code=QUICK_MSECURITY_PAY,否则不返回 prepay_id。
AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
AlipayTradeOrderPrepayRequest request = new AlipayTradeOrderPrepayRequest();
AlipayTradeOrderPrepayModel model = new AlipayTradeOrderPrepayModel();
model.setOutTradeNo("20150320010101001");
model.setTotalAmount("88.88");
model.setSubject("早餐盲盒");
model.setProductCode("QUICK_MSECURITY_PAY");
model.setPaymentType("agent_pay");
request.setBizModel(model);
AlipayTradeOrderPrepayResponse response = alipayClient.execute(request);
String prepayId = response.getPrepayId();
详细字段见 预下单接口.md。
步骤6:执行委托支付
商户预下单拿到 prepay_id 后,智能体监控到符合条件的商品时,调用 alipay.trade.agent.delegation.pay 接口完成扣款:
前置条件:已通过步骤5:商户预下单获取 prepay_id(默认有效期 2 小时)。
AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
AlipayTradeAgentDelegationPayRequest request = new AlipayTradeAgentDelegationPayRequest();
AlipayTradeAgentDelegationPayModel model = new AlipayTradeAgentDelegationPayModel();
model.setPrepayId("your_prepay_id");
model.setAgreementNo("20170322450983769228");
model.setDelegationId("2026001123456789");
request.setBizModel(model);
AlipayTradeAgentDelegationPayResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
String tradeNo = response.getTradeNo();
System.out.println("支付成功,支付宝交易号: " + tradeNo);
} else {
String errorCode = response.getSubCode();
String errorMsg = response.getSubMsg();
System.out.println("支付失败: " + errorCode + " - " + errorMsg);
}
步骤7:取消委托任务(可选)
如需取消进行中的委托任务,调用 alipay.user.agreement.delegation.cancel 接口:
AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
AlipayUserAgreementDelegationCancelRequest request = new AlipayUserAgreementDelegationCancelRequest();
AlipayUserAgreementDelegationCancelModel model = new AlipayUserAgreementDelegationCancelModel();
model.setAgreementNo("20265002005167619007");
model.setDelegationId("20260202002630110000070000000001");
request.setBizModel(model);
AlipayUserAgreementDelegationCancelResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
System.out.println("委托任务取消成功");
} else {
System.out.println("取消失败: " + response.getSubCode() + " - " + response.getSubMsg());
}
SDK配置
AlipayClient初始化
private AlipayConfig getAlipayConfig() {
AlipayConfig alipayConfig = new AlipayConfig();
alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
alipayConfig.setAppId("your_app_id");
alipayConfig.setPrivateKey("your_private_key");
alipayConfig.setAlipayPublicKey("alipay_public_key");
alipayConfig.setCharset("UTF-8");
alipayConfig.setSignType("RSA2");
return alipayConfig;
}
Maven依赖
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.40.852.ALL</version>
</dependency>
常见错误码
委托代买申请接口
| 错误码 | 说明 | 处理建议 |
|---|
| SYSTEM_ERROR | 系统繁忙 | 重试请求 |
| INVALID_PARAMETER | 参数有误 | 检查请求参数 |
委托支付接口
| 错误码 | 说明 | 处理建议 |
|---|
| ACQ.AGREEMENT_NOT_EXIST | 协议不存在或已解约 | 引导用户重新签约 |
| ACQ.AGREEMENT_INVALID | 用户协议失效 | 引导用户重新签约 |
| ACQ.BUYER_BALANCE_NOT_ENOUGH | 买家余额不足 | 提示用户充值 |
| ACQ.ORDER_NOT_EXIST | 订单不存在 | 检查prepay_id是否正确 |
| ACQ.TRADE_HAS_SUCCESS | 交易已支付成功 | 避免重复支付 |
| ACQ.TRADE_HAS_CLOSE | 交易已关闭 | 重新创建预下单 |
委托任务查询接口
| 错误码 | 说明 | 处理建议 |
|---|
| DELEGATION_NOT_EXIST | 委托任务不存在 | 检查委托号是否正确 |
| USER_AGREEMENT_NOT_EXIST | 用户协议不存在 | 检查协议号或引导重新签约 |
签名类错误
| 错误码 | 说明 | 处理建议 |
|---|
| 无效签名 / INVALID_SIGNATURE | 签名校验不通过 | 使用官方 SDK 一般不会出现;如手工拼签名串,检查签名内容和实际发送的请求参数是否完全一致(发什么签什么),详见 故障排查 §1 |
状态流转
委托任务状态流转
stateDiagram-v2
[*] --> SIGNING: 发起委托申请
SIGNING --> NORMAL: 用户授权成功
SIGNING --> INVALID: 用户拒绝/超时
NORMAL --> NORMAL: 执行支付(次数/金额未用完)
NORMAL --> FINISHED: 次数/金额用完
NORMAL --> CANCELLED: 商户取消
NORMAL --> EXPIRED: 有效期到期
NORMAL --> TERMINATE: 用户解约
FINISHED --> [*]
CANCELLED --> [*]
EXPIRED --> [*]
TERMINATE --> [*]
INVALID --> [*]
| 状态 | 说明 | 可执行操作 |
|---|
| SIGNING | 签约中,等待用户授权 | 等待用户操作 |
| NORMAL | 正常,可执行支付 | 执行支付、查询、取消 |
| FINISHED | 已完成,次数或金额已用完 | 仅查询 |
| CANCELLED | 已取消,商户主动取消 | 仅查询 |
| EXPIRED | 已过期,超过有效期 | 仅查询 |
| TERMINATE | 已终止,用户解约 | 仅查询 |
| INVALID | 无效,用户拒绝或超时 | 无 |
交易状态流转
stateDiagram-v2
[*] --> WAIT_BUYER_PAY: 创建预下单
WAIT_BUYER_PAY --> TRADE_SUCCESS: 支付成功
WAIT_BUYER_PAY --> TRADE_CLOSED: 超时关闭
TRADE_SUCCESS --> TRADE_FINISHED: 交易完结(不可退款)
TRADE_SUCCESS --> TRADE_CLOSED: 全额退款
| 状态 | 说明 | 商户处理 |
|---|
| WAIT_BUYER_PAY | 等待付款 | 等待支付结果 |
| TRADE_SUCCESS | 支付成功 | 发货/提供服务 |
| TRADE_FINISHED | 交易完结 | 交易结束,不可退款 |
| TRADE_CLOSED | 交易关闭 | 超时或退款导致关闭 |
异步消息
消息类型
| 消息类型 | 触发时机 | 通知地址配置 |
|---|
| 签约成功通知 | 用户完成签约授权 | 应用网关 |
| 签约解约通知 | 用户或商户解约 | 应用网关 |
| 支付结果通知 | 支付完成(成功/失败) | 接口中指定 notify_url |
| 委托任务状态变更 | 委托任务状态变化 | 应用网关 |
异步通知接入流程
sequenceDiagram
participant Alipay as 支付宝
participant Merchant as 商户服务端
participant DB as 商户数据库
Alipay->>Merchant: 1. POST 异步通知
Merchant->>Merchant: 2. 验证签名
alt 验签成功
Merchant->>DB: 3. 查询订单状态
alt 订单未处理
Merchant->>DB: 4. 更新订单状态
Merchant->>Merchant: 5. 执行业务逻辑
Merchant-->>Alipay: 6. 返回 "success"
else 订单已处理(幂等)
Merchant-->>Alipay: 6. 返回 "success"
end
else 验签失败
Merchant-->>Alipay: 返回 "failure"
end
Note over Alipay,Merchant: 支付宝会重试直到收到 "success"
通知处理要点
- 验签必做:所有异步通知必须验证签名,防止伪造请求
- 幂等处理:同一通知可能重复发送,需根据订单号做幂等判断
- 快速响应:处理完成后立即返回
success,业务逻辑异步处理
- 重试机制:支付宝会按照一定间隔重试,直到收到
success 或超过重试次数
委托支付异步通知处理
@RequestMapping("/delegation/notify")
public String handleDelegationNotify(HttpServletRequest request) {
Map<String, String> params = getAllRequestParams(request);
boolean signVerified = AlipaySignature.rsaCheckV1(
params, alipayPublicKey, "UTF-8", "RSA2"
);
if (!signVerified) {
return "failure";
}
String notifyType = params.get("notify_type");
switch (notifyType) {
case "dut_user_sign":
handleSignSuccess(params);
break;
case "dut_user_unsign":
handleUnsign(params);
break;
case "dut_delegation_status_change":
handleDelegationStatusChange(params);
break;
default:
log.warn("未知通知类型: " + notifyType);
}
return "success";
}
private void handleSignSuccess(Map<String, String> params) {
String agreementNo = params.get("agreement_no");
String externalAgreementNo = params.get("external_agreement_no");
String delegationId = params.get("delegation_id");
delegationService.updateSignStatus(externalAgreementNo, agreementNo, delegationId, "SIGNED");
}
private void handleDelegationStatusChange(Map<String, String> params) {
String delegationId = params.get("delegation_id");
String status = params.get("status");
delegationService.updateDelegationStatus(delegationId, status);
}
幂等控制
幂等设计原则
| 场景 | 幂等键 | 处理策略 |
|---|
| 签约申请 | external_agreement_no | 相同签约号返回已有协议 |
| 委托创建 | external_delegation_id | 相同委托号返回已有委托 |
| 支付请求 | out_trade_no | 相同订单号返回已有交易 |
| 异步通知 | trade_no + trade_status | 已处理的通知直接返回成功 |
商户侧幂等实现
public PayResult executePayWithIdempotent(String outTradeNo, String agreementNo,
String delegationId, String amount) {
Order order = orderRepository.findByOutTradeNo(outTradeNo);
if (order != null) {
if ("PAID".equals(order.getStatus())) {
return PayResult.success(order.getTradeNo());
} else if ("PAYING".equals(order.getStatus())) {
return queryAndSyncTradeStatus(outTradeNo);
}
}
order = createOrder(outTradeNo, amount, "PAYING");
try {
AlipayTradeAgentDelegationPayResponse response = executePayment(
outTradeNo, agreementNo, delegationId, amount
);
if (response.isSuccess()) {
order.setTradeNo(response.getTradeNo());
order.setStatus("PAID");
orderRepository.save(order);
return PayResult.success(response.getTradeNo());
} else {
order.setStatus("FAILED");
order.setErrorCode(response.getSubCode());
orderRepository.save(order);
return PayResult.fail(response.getSubCode(), response.getSubMsg());
}
} catch (Exception e) {
return queryAndSyncTradeStatus(outTradeNo);
}
}
委托支付最佳实践
- 幂等性处理:使用唯一的
external_agreement_no 和 external_delegation_id,避免重复创建
- 状态校验:支付前先查询委托任务状态,确保状态为
NORMAL
- 金额校验:支付前检查
remaining_amount 是否足够
- 次数校验:支付前检查
remaining_times 是否大于0
- 有效期校验:支付前检查当前时间是否在有效期内
- 异常处理:妥善处理各类错误码,给用户友好的提示
- 日志记录:记录完整的请求响应日志,便于问题排查
接口文档参考
当需要查看详细的接口参数、请求/响应字段说明时,请读取以下参考文档:
接入准备(第一次接入必读)
| 文档 | 参考文档路径 |
|---|
| 接入准备(注册/密钥/开通产品/沙箱) | references/00-接入准备.md |
委托支付(Delegation)
| 接口 | 参考文档路径 |
|---|
| 委托代买申请 | references/delegation/委托代买申请接口.md |
| 商户预下单 | references/delegation/预下单接口.md |
| 委托支付 | references/delegation/委托支付接口.md |
| 委托任务查询 | references/delegation/委托任务查询接口.md |
| 委托任务取消 | references/delegation/委托任务取消接口.md |
| 故障排查(无效签名、联调排错) | references/故障排查.md |