如何使用 alipay.trade.page.pay 生成 GET 支付链接?
明确结论
这里的 "get" 是指通过 HTTP GET 请求访问支付宝网关。具体做法是将 alipay.trade.page.pay 需要的公共参数、业务参数和签名放入 URL 查询字符串,再让浏览器跳转到这个 URL。
完整链接大致如下:
https://openapi.alipay.com/gateway.do?app_id=...&method=alipay.trade.page.pay&...&biz_content=...&sign=...
建议直接使用支付宝开放平台 SDK 生成 GET 跳转地址,由 SDK 处理参数排序、签名和 URL 编码。不要先对参数进行 URL 编码再签名,也不要对完整的支付链接整体执行一次 UrlEncode。
"get" 方式具体指什么
alipay.trade.page.pay 是电脑网站支付接口。调用接口后,需要将用户的浏览器引导至支付宝收银台,常见方式有两种:
POST:SDK 返回一段自动提交的 HTML 表单,商户页面将其输出给浏览器。GET:SDK 返回一个带查询参数的支付宝网关地址,商户通过 HTTP 302 或前端跳转打开该地址。
因此,GET 方式并不是把接口调用改成普通的后端 JSON GET 请求,而是生成一个已经完成签名的收银台跳转链接。
例如:
https://openapi.alipay.com/gateway.do?app_id=2021...&method=alipay.trade.page.pay&charset=utf-8&sign_type=RSA2×tamp=2026-09-09+10%3A00%3A00&version=1.0&biz_content=%7B...%7D&sign=...
推荐做法:通过 SDK 生成链接
以 Java SDK 为例,调用 pageExecute(request, "GET") 后读取响应内容:
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
public class AlipayPagePayExample {
public static void main(String[] args) throws Exception {
String gatewayUrl = "https://openapi.alipay.com/gateway.do";
String appId = "你的应用APPID";
String appPrivateKey = "你的应用私钥";
String alipayPublicKey = "支付宝公钥";
AlipayClient alipayClient = new DefaultAlipayClient(
gatewayUrl,
appId,
appPrivateKey,
"json",
"UTF-8",
alipayPublicKey,
"RSA2"
);
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
// 支付完成后的同步跳转地址
request.setReturnUrl("https://www.example.com/alipay/return");
// 支付结果异步通知地址
request.setNotifyUrl("https://www.example.com/alipay/notify");
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
model.setOutTradeNo("ORDER_202609090001");
model.setTotalAmount("99.00");
model.setSubject("订单商品");
model.setProductCode("FAST_INSTANT_TRADE_PAY");
request.setBizModel(model);
AlipayTradePagePayResponse response =
alipayClient.pageExecute(request, "GET");
String paymentUrl = response.getBody();
System.out.println(paymentUrl);
}
}
通常可以直接使用 response.getBody() 返回的内容进行浏览器跳转:
response.sendRedirect(paymentUrl);
上面的代码假设当前支付宝 Java SDK 提供 pageExecute(request, "GET") 重载。不同语言或不同版本的 SDK 可能使用不同的方法名称,请以实际使用的 SDK 接口为准。如果 GET 重载不可用,也可以通过 SDK 生成签名参数,但不建议自行实现签名算法。
手工拼接时的正确顺序
如果确实需要手工构造链接,应按以下顺序处理:
- 准备公共请求参数。
- 将业务参数序列化为
biz_contentJSON 字符串。 - 排除
sign,按参数名排序并生成待签名字符串。 - 使用应用私钥进行 RSA2 签名。
- 将签名结果放入
sign参数。 - 分别对每个参数名和参数值进行 UTF-8 URL 编码。
- 使用
&连接参数,再拼接到支付宝网关地址后面。
示意代码如下:
Map<String, String> params = new HashMap<>();
params.put("app_id", "你的应用APPID");
params.put("method", "alipay.trade.page.pay");
params.put("format", "JSON");
params.put("charset", "UTF-8");
params.put("sign_type", "RSA2");
params.put("timestamp", "2026-09-09 10:00:00");
params.put("version", "1.0");
params.put("return_url", "https://www.example.com/alipay/return");
params.put("notify_url", "https://www.example.com/alipay/notify");
params.put(
"biz_content",
"{\"out_trade_no\":\"ORDER_202609090001\","
+ "\"total_amount\":\"99.00\","
+ "\"subject\":\"订单商品\","
+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}"
);
// 应使用支付宝 SDK 的签名函数,不建议自行编写 RSA2 实现。
String sign = signWithAlipaySdk(params, appPrivateKey, "UTF-8", "RSA2");
params.put("sign", sign);
String queryString = params.entrySet()
.stream()
.sorted(Map.Entry.comparingByKey())
.map(entry ->
urlEncode(entry.getKey()) + "=" + urlEncode(entry.getValue())
)
.collect(Collectors.joining("&"));
String paymentUrl =
"https://openapi.alipay.com/gateway.do?" + queryString;
URL 编码函数可以写成:
private static String urlEncode(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8);
}
上例中的 signWithAlipaySdk(...) 只是占位名称,并非可以直接调用的标准方法。实际项目应使用当前支付宝 SDK 提供的签名工具,以免参数过滤、字符集或 RSA2 实现差异导致验签失败。
为什么必须先签名,再做 URL 编码
签名使用的是参数原始值组成的待签名字符串。例如,原始时间参数是:
timestamp=2026-09-09 10:00:00
写入 URL 后可能变成:
timestamp=2026-09-09+10%3A00%3A00
两者的表现形式不同。签名时应使用原始参数值,生成 URL 时再进行编码。如果先编码后签名,支付宝解码收到的参数后,参与验签的内容可能与商户侧不一致,从而导致验签失败。
RSA2 签名通常还包含 +、/、= 等字符。这些字符写入 URL 时必须编码,例如:
+ -> %2B
/ -> %2F
= -> %3D
否则,+ 可能被当作空格,导致签名内容损坏。
不要对整个链接整体编码
下面这种写法是错误的:
String encodedUrl = URLEncoder.encode(paymentUrl, StandardCharsets.UTF_8);
它会将协议、斜杠、问号和参数分隔符一起编码,结果类似:
https%3A%2F%2Fopenapi.alipay.com%2Fgateway.do%3Fapp_id%3D...
浏览器不会将其识别为正常的支付宝跳转地址。
正确方式是只编码参数名和参数值,保留 URL 的结构字符:
https://openapi.alipay.com/gateway.do?key1=value1&key2=value2
网关地址需要区分环境
正式环境通常使用:
https://openapi.alipay.com/gateway.do
沙箱环境应使用沙箱配置中指定的网关地址,同时使用沙箱应用的 app_id、应用私钥和支付宝公钥。正式环境和沙箱环境的密钥、应用编号不能混用。
注意事项
- 优先使用支付宝 SDK 完成签名和 URL 编码,不要自行拼接签名字符串。
- 在电脑网站支付场景中,
product_code通常为FAST_INSTANT_TRADE_PAY。 out_trade_no必须由商户生成,并在商户系统中保持唯一。total_amount应使用符合接口要求的金额字符串,不要通过浮点运算拼接金额。notify_url必须是支付宝服务器能够访问的公网地址。- 判断支付是否成功时,不能只依赖
return_url的同步跳转结果。应以后端异步通知和主动查询结果为准,并对通知进行验签。 - 不要信任前端传来的订单金额和商品信息。生成支付链接前,服务端应根据订单号重新读取订单数据。
- GET 链接可能被记录在浏览器历史、代理日志或访问日志中,因此不要将私钥、身份证号等敏感信息放入参数。
- 如果业务参数过多,导致 URL 过长,应改用 SDK 返回的 POST 表单方式。
- SDK 已经生成的完整 URL 不要再次编码,也不要拆开后重复编码
biz_content或sign。
备注:内容仅供参考。
