支付宝客户端代扣解约的异步通知地址是什么?
结论
通过支付宝客户端发起代扣解约时,异步通知通常发送到该应用在支付宝开放平台配置的应用网关地址,不会发送到商户调用解约接口时传入的 notify_url。
原因是客户端解约属于用户在支付宝侧主动发起的协议状态变更,并不存在对应的商户解约请求,因此也没有可供支付宝使用的请求级 notify_url。只有商户主动调用某个接口,并且该接口明确支持 notify_url 时,请求中的通知地址才可能生效。
原因说明
需要区分两种解约方式:
用户在支付宝客户端解约
用户进入支付宝客户端的签约管理页面并解除代扣协议。该操作由支付宝侧发起,支付宝会根据应用配置发送协议解约通知。
此场景应检查开放平台中对应应用配置的应用网关,并确保该地址能够接收支付宝发送的通知。
商户通过接口发起解约
商户调用类似 alipay.user.agreement.unsign 的解约接口时,应以该接口当前版本的官方文档为准:
- 如果接口支持请求级
notify_url,通知可能发送到该地址。 - 如果接口不支持
notify_url,传入该参数不会改变客户端解约通知的接收地址。 - 接口同步返回成功,只表示该次接口调用得到响应,商户仍应根据业务要求确认最终协议状态。
因此,不能把“商户接口请求中的 notify_url”理解为所有解约事件的统一通知地址。
处理步骤
1. 配置应用网关
在支付宝开放平台对应应用的开发配置中填写可公网访问的 HTTPS 地址,例如:
https://merchant.example.com/alipay/gateway
该地址应满足以下条件:
- 可被支付宝服务器访问。
- 支持
POST请求。 - 不依赖浏览器 Cookie 或登录状态。
- 不执行页面跳转。
- 能在较短时间内完成验签并返回响应。
- 生产环境使用有效的 HTTPS 证书。
2. 接收并验证通知
收到请求后,不要直接信任通知中的协议号、商户编号或解约状态。应先使用支付宝公钥验签,再处理业务。
以下为 Java 示例,具体字段名称应以实际收到的通知及对应产品文档为准:
@PostMapping("/alipay/gateway")
public String receiveAlipayNotification(HttpServletRequest request) throws Exception {
Map<String, String> params = new HashMap<>();
request.getParameterMap().forEach((name, values) -> {
if (values != null && values.length > 0) {
params.put(name, values[0]);
}
});
boolean verified = AlipaySignature.rsaCheckV1(
params,
ALIPAY_PUBLIC_KEY,
"UTF-8",
"RSA2"
);
if (!verified) {
return "failure";
}
String agreementNo = params.get("agreement_no");
String status = params.get("status");
// 根据实际通知字段判断是否为解约事件。
// 更新时应使用 agreementNo 等唯一标识进行幂等处理。
agreementService.handleStatusChange(agreementNo, status, params);
return "success";
}
如果使用支付宝公钥证书模式,应采用与证书模式匹配的 SDK 验签方法,不能直接套用普通公钥模式的配置。
3. 做好幂等处理
支付宝可能因网络超时或未收到预期响应而重复发送通知。业务处理应以协议号或通知中的唯一业务标识作为幂等键,例如:
UPDATE user_agreement
SET agreement_status = 'UNSIGNED',
updated_at = CURRENT_TIMESTAMP
WHERE agreement_no = ?
AND agreement_status <> 'UNSIGNED';
不要因为重复通知而重复关闭服务、重复退款或重复写入流水。
4. 必要时主动查询协议状态
异步通知可能因网关配置错误、网络异常或验签失败而没有被成功处理。对于状态敏感的业务,建议结合支付宝提供的协议查询能力进行补偿核对。
可采用以下思路:
接收解约通知
↓
验签并记录原始通知
↓
更新本地协议状态
↓
定时查询长期处于处理中或状态不一致的协议
注意事项
- 应用网关与授权回调地址、支付回跳地址、接口
notify_url不是同一个概念,不要混用。 - 客户端解约没有商户侧的本次接口请求,因此不会沿用商户以前调用解约接口时设置的
notify_url。 - 不要仅根据同步页面跳转或前端结果更新协议状态,应以后端验签后的通知或主动查询结果为准。
- 接收通知后应先保存必要的原始参数和处理日志,便于排查漏单及验签问题,但不要在日志中暴露私钥等敏感信息。
- 通知参数、事件类型和成功响应格式可能因代扣产品及接入方式不同而有差异。若当前产品文档明确指定了独立的协议通知地址或特殊响应内容,应以该产品的官方接口文档和应用配置为准。
备注:内容仅供参考。
