支付宝沙箱手机网站支付提示商户合作协议已到期
结论
出现”商户合作协议已到期”,通常不是支付代码或签名算法的问题,而是沙箱商家账号(PID:2088621987755475)对应的产品协议状态异常或已经失效。
先确认请求发送到了支付宝沙箱网关,再检查 appid、商家 PID 和应用密钥是否属于同一套沙箱环境。如果配置一致后仍然报错,问题很可能出在支付宝沙箱侧,无法通过修改代码续签协议。可以在开放平台重新配置沙箱应用、重置沙箱环境,或者向支付宝开放平台技术支持提交该 appid 和 PID,请其处理。
原因分析
手机网站支付使用 alipay.trade.wap.pay 接口。支付宝收到请求后,不仅会校验签名,还会检查以下内容:
- 应用是否有效;
- 应用绑定的商家账号是否有效;
- 商家是否具备手机网站支付权限;
- 对应产品协议是否有效;
appid、seller_id和收款账号是否匹配。
当前涉及的账号信息如下:
appid: 2021000121635859
商家 PID: 2088621987755475
如果返回信息明确显示”商户合作协议已到期”,一般说明支付宝已经完成了基础解析和身份识别,但商家侧的产品协议没有通过状态检查。这和”验签失败""应用不存在”是不同类型的问题,不应优先尝试修改签名代码。
排查步骤
1. 确认使用沙箱网关
沙箱请求地址应为:
https://openapi-sandbox.dl.alipaydev.com/gateway.do
不要把沙箱 appid 和沙箱私钥发送到正式环境网关:
https://openapi.alipay.com/gateway.do
还要检查 SDK 初始化代码,确认配置文件、环境变量或部署参数没有覆盖网关地址,导致程序实际使用了正式网关。
2. 核对整套沙箱配置
以下配置必须来自同一个沙箱应用:
appid;- 应用私钥;
- 支付宝公钥;
- 沙箱商家账号;
- 商家 PID;
- 沙箱买家账号。
不要混用正式环境的应用密钥、PID 或买家账号。
如果请求中传递了 seller_id,它必须和当前应用绑定的商家 PID 一致,即:
2088621987755475
如果业务不需要指定收款方,可以暂时删除 seller_id,让支付宝根据 appid 识别默认商家。这样可以排除 PID 填写错误或配置被覆盖的问题。
3. 检查手机网站支付产品状态
进入支付宝开放平台的沙箱环境,查看对应应用是否仍有手机网站支付能力,并确认沙箱商家账号的产品协议是否有效。
应用存在,不代表对应的支付产品协议一定有效。即使 appid 和签名都正确,商家协议异常仍会导致交易创建失败。
如果页面提供重新签约、重新授权或重置沙箱环境的入口,可以按照页面提示操作。开放平台界面可能随时间调整,应以当前控制台显示的内容为准。
4. 检查接口返回的完整错误信息
不要只记录页面上的中文提示,还应保存支付宝返回的完整字段,例如:
code
msg
sub_code
sub_msg
排查时应重点查看 sub_code。相同的中文提示可能对应不同的 sub_code,处理方式也可能不同。
建议记录以下信息:
appid
method
seller_id
out_trade_no
code
sub_code
sub_msg
支付宝返回的 request_id(如果有)
不要在日志或工单中公开应用私钥、完整签名串、买家密码等敏感信息。
5. 重新生成沙箱配置后再测试
如果控制台允许重置或重新生成沙箱配置,可以按以下顺序操作:
- 保存现有配置,避免误影响其他测试人员;
- 重置沙箱环境或重新生成应用密钥;
- 更新项目中的应用私钥和支付宝公钥;
- 再次核对沙箱
appid和商家 PID; - 使用新的
out_trade_no发起测试。
不要反复使用已经失败或已存在的商户订单号,否则可能产生”订单号重复”等额外错误,影响判断。
6. 提交支付宝技术支持
如果以下条件都已满足,但错误依然存在:
- 请求发送到沙箱网关;
appid为2021000121635859;- PID 为
2088621987755475; - 密钥属于该沙箱应用;
- 接口为
alipay.trade.wap.pay; - 控制台没有可用的重新签约入口;
则需要由支付宝检查或恢复该沙箱商家账号的协议状态。提交问题时,建议附上:
- 沙箱
appid; - 沙箱商家 PID;
- 完整的
code、sub_code、sub_msg; - 请求发生时间;
- 接口名称;
- 脱敏后的请求参数;
- 问题页面截图。
Java 调用示例
下面的示例用于确认基本调用方式。密钥、回调地址和订单信息需要替换为实际的测试配置。
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeWapPayRequest;
public class AlipayWapPayExample {
public static void main(String[] args) throws Exception {
String gatewayUrl =
"https://openapi-sandbox.dl.alipaydev.com/gateway.do";
String appId = "2021000121635859";
String merchantPrivateKey = "YOUR_APP_PRIVATE_KEY";
String alipayPublicKey = "YOUR_ALIPAY_PUBLIC_KEY";
AlipayClient alipayClient = new DefaultAlipayClient(
gatewayUrl,
appId,
merchantPrivateKey,
"json",
"UTF-8",
alipayPublicKey,
"RSA2"
);
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setReturnUrl("https://example.com/alipay/return");
request.setNotifyUrl("https://example.com/alipay/notify");
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo("SANDBOX_" + System.currentTimeMillis());
model.setTotalAmount("0.01");
model.setSubject("沙箱手机网站支付测试");
model.setProductCode("QUICK_WAP_WAY");
// 一般可不设置 seller_id,由 appid 关联的商家账号收款。
// 如必须设置,其值应与应用绑定的沙箱商家 PID 一致。
// model.setSellerId("2088621987755475");
request.setBizModel(model);
String paymentForm = alipayClient.pageExecute(request).getBody();
System.out.println(paymentForm);
}
}
pageExecute() 成功生成 HTML 表单,不等于交易已经创建成功。浏览器跳转到支付宝后,支付宝仍会检查商家协议、产品权限和账号状态。
注意事项
- 不要尝试通过修改订单金额、回调地址或签名算法绕过协议到期错误,这些参数与协议状态没有直接关系。
- 沙箱账号和正式商家账号相互独立。正式环境已经签约,不代表沙箱环境的状态一定正常。
- 重新生成密钥只能解决密钥配置问题,不能保证商家协议状态恢复正常。
- 重置沙箱环境可能改变原有测试账号、密钥或测试数据。操作前应确认是否有其他项目共用该环境。
- 最终应以接口返回的
sub_code和支付宝开放平台对该沙箱账号的实际查询结果为准。仅凭中文提示,无法判断究竟是协议自然失效、产品权限被回收,还是沙箱数据异常。
备注:内容仅供参考。
