H5支付跳转后提示订单信息无法识别并返回INVALID_PARAMETER
结论
pageExecute() 返回 HTML,只能说明 SDK 已生成支付跳转表单,并不表示支付宝已经校验或接受了这笔订单。
跳转后出现“订单信息无法识别”并返回 INVALID_PARAMETER,通常表示支付接口或业务参数不符合要求。H5 支付应使用手机网站支付接口 alipay.trade.wap.pay。排查时主要检查以下内容:
- 请求类是否为
AlipayTradeWapPayRequest product_code是否为QUICK_WAP_WAYout_trade_no、total_amount、subject是否有效biz_content是否为合法 JSON- 应用、公私钥、网关和签名方式是否属于同一套环境
- 生成签名后,请求参数是否又被修改或二次编码
为什么返回了 HTML,跳转后仍然报错
DefaultAopClient.pageExecute() 负责组装参数、生成签名,并返回一段自动提交的 HTML 表单。部分业务参数只有在浏览器将表单提交到支付宝网关后,才会由支付宝服务端校验。
因此,以下两种情况可以同时出现:
pageExecute()正常返回 HTML。- 浏览器提交表单后,支付宝发现参数无效并返回
INVALID_PARAMETER。
排查时不能只确认 Java 方法有没有抛出异常,还要查看最终提交到网关的请求参数。
正确的 H5 支付调用方式
手机浏览器中的 H5 支付通常使用 AlipayTradeWapPayRequest:
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeWapPayRequest;
public class H5PayExample {
public String createPayForm() throws AlipayApiException {
AlipayClient alipayClient = new DefaultAopClient(
"https://openapi.alipay.com/gateway.do",
"YOUR_APP_ID",
"YOUR_APP_PRIVATE_KEY",
"json",
"UTF-8",
"ALIPAY_PUBLIC_KEY",
"RSA2"
);
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setReturnUrl("https://example.com/pay/return");
request.setNotifyUrl("https://example.com/pay/notify");
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo("ORDER_202609140001");
model.setTotalAmount("0.01");
model.setSubject("测试商品");
model.setProductCode("QUICK_WAP_WAY");
request.setBizModel(model);
return alipayClient.pageExecute(request).getBody();
}
}
不使用业务模型时,也可以直接传入 JSON,但要注意字段名称、数据类型和 JSON 转义:
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setReturnUrl("https://example.com/pay/return");
request.setNotifyUrl("https://example.com/pay/notify");
request.setBizContent("""
{
"out_trade_no": "ORDER_202609140001",
"total_amount": "0.01",
"subject": "测试商品",
"product_code": "QUICK_WAP_WAY"
}
""");
String form = alipayClient.pageExecute(request).getBody();
如果 Java 版本不支持文本块,可以使用 JSON 序列化工具构造 biz_content。不要手工拼接包含引号或换行符的商品名称。
排查步骤
1. 确认使用的是 H5 支付接口
请求对象应为:
AlipayTradeWapPayRequest
对应的方法应为:
alipay.trade.wap.pay
不要在 H5 支付中混用电脑网站支付的 AlipayTradePagePayRequest 或 APP 支付的 AlipayTradeAppPayRequest。这些请求类对应不同的产品和调用场景。
2. 检查 product_code
H5 手机网站支付通常要求使用:
QUICK_WAP_WAY
示例:
model.setProductCode("QUICK_WAP_WAY");
如果该参数缺失、拼写错误,或者填写了其他支付产品的 product_code,网关可能无法识别订单参数。
3. 检查必要的业务参数
至少核对以下字段:
| 参数 | 检查重点 |
|---|---|
out_trade_no | 商户订单号不能为空;同一商户订单号不要对应不同金额或商品 |
total_amount | 使用合法金额格式,如 0.01、100.00;不要带人民币符号、逗号或空格 |
subject | 商品标题不能为空,避免异常控制字符 |
product_code | H5 支付应与已签约产品一致,通常为 QUICK_WAP_WAY |
金额建议使用 BigDecimal 处理,避免直接使用 double 带来的精度问题:
BigDecimal amount = new BigDecimal("0.01");
model.setTotalAmount(amount.setScale(2, RoundingMode.HALF_UP).toPlainString());
4. 输出并核对最终请求内容
在调试环境中,可以记录以下信息:
- 请求使用的网关地址
app_id- 接口名称
charsetsign_typebiz_content- 支付宝返回的错误码、子错误码和错误描述
日志中不要记录应用私钥、完整签名或用户敏感信息。
如果返回内容是 HTML,可以在测试环境中查看表单的 action 和隐藏字段,确认以下事项:
method是alipay.trade.wap.paybiz_content没有被截断- 中文内容没有乱码
- 表单提交地址与当前环境一致
5. 检查签名配置
以下配置必须相互匹配:
app_id属于当前应用- 应用私钥与上传到该应用的公钥匹配
- SDK 中配置的是支付宝公钥,不是应用公钥
sign_type与应用配置一致,常见值为RSA2- 签名前后的参数内容完全一致
如果使用证书模式,应按照证书模式初始化客户端,不能混用普通公钥模式和证书模式的配置。
6. 检查正式环境和沙箱环境是否混用
正式环境与沙箱环境的应用 ID、密钥、账号和网关不能交叉使用。例如,不能把沙箱应用参数提交到正式网关:
https://openapi.alipay.com/gateway.do
具体的沙箱网关地址应以当前开放平台配置和所用 SDK 的说明为准。
7. 排除前端二次处理
pageExecute() 返回的是可以直接输出到浏览器的 HTML 表单。服务端通常可以直接将它写入响应:
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(form);
response.getWriter().flush();
不要对整段 HTML 再做 URL 编码、HTML 转义或 JSON 字符串化。例如:
URLEncoder.encode(form, StandardCharsets.UTF_8);
这些处理可能破坏表单字段,使网关实际收到的参数与签名时使用的参数不一致。
常见错误示例
在手机 H5 场景中错误使用电脑网站支付请求:
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
// 在手机 H5 场景中错误使用电脑网站支付请求
使用了与 H5 手机网站支付产品不匹配的 product_code:
model.setProductCode("FAST_INSTANT_TRADE_PAY");
// 与 H5 手机网站支付产品不匹配
金额格式不合法:
model.setTotalAmount("¥0.01");
model.setTotalAmount("1,000.00");
model.setTotalAmount("");
注意事项
return_url 只负责支付完成后的浏览器跳转,不能单独作为订单支付成功的依据。订单状态应以异步通知 notify_url 的验签结果为准,也可以主动调用交易查询接口确认。
如果请求类、必要参数、签名和环境都没有问题,但仍然返回 INVALID_PARAMETER,应保留网关返回的 code、sub_code、sub_msg、请求时间和支付宝请求标识。INVALID_PARAMETER 涉及的范围较大,需要结合更具体的 sub_code 和 sub_msg 定位出错字段。
备注:内容仅供参考。
