PAYATHON 2026

新版 EasySDK 如何支持网页版网银支付及 GET 支付链接

支付阿杰

结论

EasySDK 的 page.pay 和 wap.pay 主要用于生成支付宝收银台表单。服务端通常会把返回的 HTML 表单输出到浏览器,由浏览器自动提交,因此不适合用来在服务端生成 GET 支付链接,再交给前端跳转。

如需 GET 支付链接,可以使用支付宝通用 SDK,创建 AlipayTradePagePayRequest,并在调用 pageExecute 时指定 GET。手机网站支付则使用 AlipayTradeWapPayRequest。

用户能否在充值页面预先选择银行,并不由 SDK 决定。SDK 只负责请求签名和调用支付接口,支付宝收银台支持哪些银行、是否允许指定银行,取决于商户签约的支付产品及当前接口文档。新版 alipay.trade.page.pay 通常会跳转到支付宝收银台,由用户选择可用的支付方式,不能直接套用旧版接口中的银行代码参数。

推荐的支付流程

可以按以下流程处理:

  1. 前端展示充值金额、银行卡等选项。
  2. 前端向服务端提交充值请求。
  3. 服务端创建本地充值订单,并生成唯一的 out_trade_no。
  4. 服务端通过通用 SDK 生成支付宝 GET 支付链接。
  5. 服务端把链接返回给前端。
  6. 前端通过 window.location.href 跳转到支付宝收银台。
  7. 支付结果以支付宝异步通知为准,不能只看同步跳转结果。

如果前端选择的“银行卡类型”仅用于业务记录,可以将其保存到本地订单中。在支付宝没有明确支持相关参数的情况下,不要自行拼接 bank_code、defaultbank 等字段。

PHP 通用 SDK 示例

下面使用通用版支付宝 PHP SDK。示例中的类名和基本调用方式适用于常见版本,实际命名空间和证书配置仍应以项目安装的 SDK 版本为准。

<?php

$aop = new AopClient();

$aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
$aop->appId = 'your_app_id';
$aop->rsaPrivateKey = 'your_merchant_private_key';
$aop->alipayrsaPublicKey = 'your_alipay_public_key';
$aop->signType = 'RSA2';
$aop->format = 'json';
$aop->charset = 'UTF-8';

$request = new AlipayTradePagePayRequest();

$request->setNotifyUrl('https://example.com/alipay/notify');
$request->setReturnUrl('https://example.com/alipay/return');

$request->setBizContent(json_encode([
    'out_trade_no' => 'RECHARGE_202609090001',
    'total_amount' => '100.00',
    'subject' => '账户充值',
    'product_code' => 'FAST_INSTANT_TRADE_PAY',
], JSON_UNESCAPED_UNICODE));

// 指定 GET,返回已经完成签名的支付链接
$payUrl = $aop->pageExecute($request, 'GET');

// 以 JSON 形式返回给前端
header('Content-Type: application/json; charset=utf-8');

echo json_encode([
    'pay_url' => $payUrl,
], JSON_UNESCAPED_UNICODE);

前端收到链接后跳转:

const response = await fetch('/api/recharge', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    amount: '100.00',
    bankType: 'ICBC'
  })
});

const result = await response.json();

if (result.pay_url) {
  window.location.href = result.pay_url;
}

手机网站支付的写法相近:

$request = new AlipayTradeWapPayRequest();

$request->setNotifyUrl('https://example.com/alipay/notify');
$request->setReturnUrl('https://example.com/alipay/return');

$request->setBizContent(json_encode([
    'out_trade_no' => 'RECHARGE_202609090002',
    'total_amount' => '100.00',
    'subject' => '账户充值',
    'product_code' => 'QUICK_WAP_WAY',
    'quit_url' => 'https://example.com/recharge',
], JSON_UNESCAPED_UNICODE));

$payUrl = $aop->pageExecute($request, 'GET');

如果当前 PHP SDK 的 pageExecute() 不接受第二个参数,需要检查项目实际安装版本的方法签名,不能假定所有版本的调用方式完全一致。

EasySDK 应该怎么处理

如果项目已经在使用 EasySDK,可以继续通过它完成普通的支付创建、查询、退款和通知验签。但在必须返回 GET URL 的场景中,直接使用通用 SDK 会更清楚。

如果 EasySDK 的高级封装只提供 POST 表单,不建议直接修改 vendor 目录中的源码,原因包括:

  • Composer 更新后,本地修改可能被覆盖。
  • 团队难以区分官方代码和本地补丁。
  • 后续切换 SDK 版本时容易遇到兼容问题。
  • 手工拼接支付链接可能遗漏签名、编码或公共参数。

如果必须保留 EasySDK,可以让它与通用 SDK 并存。两者使用同一个 app_id、商户私钥和支付宝公钥,GET 支付链接则单独通过通用 SDK 生成。

关于预先指定银行卡

这里要区分两个概念:

  • “页面上让用户选择银行卡”属于商户自己的交互,可用于展示、统计或后续业务判断。
  • “让支付宝收银台直接进入某家银行”属于支付宝支付产品提供的能力,无法由 SDK 的封装方式决定。

旧接口中曾有直接指定网银或默认银行的参数,但不能在未经确认的情况下将这些参数用于 alipay.trade.page.pay。即使参数可以正常签名并发送,支付宝网关仍可能忽略或拒绝它。

建议先确认以下内容:

  1. 商户账号签约的是电脑网站支付、手机网站支付,还是单独的网银支付产品。
  2. 当前签约产品是否支持直接指定银行。
  3. 对应接口是否明确提供了银行代码字段及其可用值。
  4. 这项能力是否需要单独申请或开通。

如果当前产品只支持标准电脑网站支付,就应跳转到支付宝收银台,由收银台展示该用户可用的付款方式。

异步通知必须作为支付依据

前端跳转回来只能说明用户返回了商户页面,并不表示付款已经成功。订单入账必须以异步通知验签和订单查询结果为准。

处理通知时至少需要核对:

  • 通知签名是否合法。
  • app_id 是否属于当前应用。
  • out_trade_no 是否存在。
  • total_amount 是否与本地订单金额一致。
  • seller_id 是否符合预期。
  • trade_status 是否属于可入账状态。
  • 同一订单是否已经处理,以免重复充值。

异步通知处理必须具备幂等性。业务处理完成后,再按照支付宝接口要求返回成功响应。

关于 GitHub 项目是否仍在维护

某个 2021 年提交的 PR 长期没有合并,并不足以证明项目已经停止维护。PR 未被采纳也可能与接口设计、兼容性、产品策略或维护优先级有关。

判断项目目前是否仍由官方持续维护,需要查看仓库最近的 release、commit、issue 回复情况,以及支付宝开放平台公布的 SDK 下载入口。如果业务需要 GET 跳转,无需等待 EasySDK 合并相关改动,可以直接使用通用 SDK 的 pageExecute($request, 'GET')。

备注:内容仅供参考。