PAYATHON 2026

支付宝个人协议页面签约接口在沙盒中不显示二维码

支付小周

结论

alipay.user.agreement.page.sign 在沙盒网关中“调用成功”,只能说明网关接受了请求参数和签名,不代表后续的签约页面、二维码和代扣流程都能在沙盒中正常运行。

如果页面可以跳转到沙盒支付宝,但签约页没有显示二维码,通常是因为沙盒尚未完整开放该签约产品或对应的页面渠道。更换浏览器一般解决不了这类问题。应先确认当前应用、签约产品和渠道是否支持沙盒。如果支付宝开放平台确认沙盒不支持,就需要先在生产环境完成产品签约,再进行受控测试。

这个接口用于开通个人协议,并不是支付接口。签约成功后,需要调用相应的支付或代扣接口完成扣款,无法通过签约页面直接支付。

为什么调试工具成功,页面仍然不可用

开放平台的 API 调试工具主要检查以下内容:

  • 请求能否到达支付宝网关;
  • app_id、签名、字符集等公共参数是否正确;
  • biz_content 是否通过基础校验;
  • 接口是否返回页面跳转所需的 HTML。

二维码由跳转后的支付宝签约页面生成,不在最初的 API 响应中。进入后续页面后,系统还会检查:

  • 应用是否开通了对应的签约或代扣产品;
  • personal_product_code、sign_scene 等业务参数是否匹配;
  • 当前渠道是否支持电脑端二维码签约;
  • 沙盒是否实现了该产品的完整签约流程;
  • 测试账号是否为有效的沙盒买家账号;
  • 协议号是否重复、失效或已经处于其他状态。

所以,即使接口返回 code=10000,或者已经生成跳转表单,后续页面仍可能无法生成二维码。

建议的排查顺序

1. 确认调用的是沙盒网关

沙盒应用必须使用沙盒网关和沙盒应用配置,不能混用生产环境的应用、密钥或账号。

常见的沙盒网关配置如下:

https://openapi-sandbox.dl.alipaydev.com/gateway.do

API 调试页面位于 open.alipay.com,但这个页面地址不是业务网关地址。

重点核对以下配置:

  • 沙盒 app_id;
  • 沙盒应用公钥和支付宝公钥;
  • sign_type,通常为 RSA2;
  • SDK 中配置的支付宝网关;
  • 登录或扫码时使用的账号是否为沙盒买家账号。

2. 确认沙盒是否支持当前签约产品

查看 alipay.user.agreement.page.sign 的接口文档和应用控制台,确认当前使用的以下内容是否明确支持沙盒:

  • personal_product_code;
  • sign_scene;
  • 签约渠道;
  • 代扣或免密支付产品。

沙盒能力可能会随产品和接入权限调整。接口能够返回 HTML,不等于沙盒支持完整的签约流程。如果文档没有明确说明,可以向支付宝开放平台技术支持提供 app_id、调用时间和请求流水号,确认该产品目前是否支持沙盒二维码签约。

3. 检查同步响应和页面错误

记录 SDK 返回的完整响应,尤其要保留以下字段:

code
msg
sub_code
sub_msg
out_request_no

如果初始响应没有业务错误,再打开浏览器开发者工具,检查:

  • Console 中是否有 JavaScript 异常;
  • Network 中是否发出了二维码相关请求;
  • 请求是否返回 4xx、5xx 或业务错误;
  • 页面是否提示产品未开通、账号不支持或协议已存在;
  • 是否发生 HTTP 与 HTTPS 混合内容拦截。

如果二维码请求根本没有发出,而且多个浏览器的表现相同,应优先检查支付宝沙盒能力和产品权限,而不是浏览器兼容性。

4. 不要修改或转义支付宝返回的 HTML

页面类接口通常返回一个自动提交的 HTML 表单。服务端应直接将其作为 HTML 响应返回,不要使用 JSON 包装,不要进行 HTML 转义,也不要只提取其中一部分。

以 Java SDK 为例:

AlipayClient alipayClient = new DefaultAlipayClient(
    "https://openapi-sandbox.dl.alipaydev.com/gateway.do",
    appId,
    merchantPrivateKey,
    "json",
    "UTF-8",
    alipayPublicKey,
    "RSA2"
);

AlipayUserAgreementPageSignRequest request =
    new AlipayUserAgreementPageSignRequest();

request.setReturnUrl(returnUrl);
request.setNotifyUrl(notifyUrl);
request.setBizContent(bizContent);

AlipayUserAgreementPageSignResponse response =
    alipayClient.pageExecute(request, "POST");

String formHtml = response.getBody();

Web 接口应直接返回这段 HTML:

response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(formHtml);

不要采用下面这种返回方式:

response.getWriter().write(
    "{\"html\":\"" + formHtml + "\"}"
);

也不要先对 formHtml 做 HTML 转义,否则自动提交表单可能失效。

把返回内容保存为静态 HTML 后再访问,有时也能完成跳转,但不适合作为正式接入方式。页面参数可能有时效限制,重复打开旧页面也可能触发异常状态。

5. 检查业务参数和协议号

每次测试都应使用唯一的商户协议号,例如 external_agreement_no,不要反复使用同一个协议号创建签约请求。

示意结构如下,具体字段和值应以当前接口文档和应用已开通的产品为准:

{
  "personal_product_code": "已开通产品对应的编码",
  "sign_scene": "已开通产品支持的签约场景",
  "external_agreement_no": "AGREEMENT_20260908_000001"
}

不要直接照搬其他产品示例中的 personal_product_code 或 sign_scene。如果这些参数与应用实际开通的产品不一致,网关仍可能返回页面,但后续签约流程无法完成。

生产环境如何验证

如果已经确认沙盒不支持这条签约链路,应先完成生产应用的产品签约和权限配置,再进行小范围受控验证:

  1. 使用生产 app_id、生产密钥和生产网关。
  2. 确认应用已经正式开通对应的签约或代扣产品。
  3. 使用唯一的商户协议号发起签约。
  4. 配置可以通过公网访问的 HTTPS notify_url。
  5. 对异步通知验签,并校验应用、协议号和签约状态。
  6. 使用 alipay.user.agreement.query 查询最终协议状态,不要只依赖浏览器返回页。
  7. 签约成功后,再按照已开通产品的规则测试扣款接口。

生产验证可能产生真实协议或真实资金行为,因此要使用已明确授权的测试账号、受控金额,并提前准备可执行的解约方案。

注意事项

  • return_url 只负责将用户浏览器带回商户页面,不能作为判断签约成功的唯一依据。
  • 异步通知必须验签,签约结果还要通过协议查询接口复核。
  • 不要在公开工单中提交私钥、完整身份证号、手机号或用户标识。
  • 向支付宝技术支持反馈时,建议提供 app_id、接口名、网关环境、调用时间、请求流水号、sub_code、sub_msg 和页面 Network 截图。
  • 如果生产环境也没有显示二维码,应继续检查产品权限、签约场景和电脑端渠道的支持情况,不能直接归因于沙盒。

备注:内容仅供参考。