PAYATHON 2026

支付宝支付如何使用公钥证书模式并支持提现

支付小周

结论

支付宝支持公钥证书模式,支付接口也可以通过这种模式调用。如果提现或转账接口明确要求使用公钥证书模式,建议将同一应用的支付宝客户端整体切换到证书模式,让支付、查询、退款、转账和异步通知验签共用一套证书配置。

公钥证书模式并非另一套支付接口。alipay.trade.page.pay、alipay.trade.app.pay、alipay.trade.wap.pay 等接口通常无须更换,只需调整签名和验签配置。

还要注意,“提现”可能指商家转账、余额转出或其他资金产品。具体接口名称和准入条件,应以该应用在支付宝开放平台已签约的产品为准,不能只根据“提现”这个名称判断接口。

为什么支付能用公钥模式,提现却要求证书模式

支付宝开放平台常见的接口加签方式有两种:

  • 普通公钥模式:使用应用私钥签名,通过已配置的支付宝公钥验签。
  • 公钥证书模式:除应用私钥外,还需要应用公钥证书、支付宝公钥证书和支付宝根证书。

部分资金类接口要求使用公钥证书模式,以便通过证书序列号识别签名主体,同时支持证书链校验和证书更新。因此,支付接口能够通过普通公钥模式调用,不代表资金类接口也支持相同的模式。

切换后,SDK通常会自动在请求中携带 app_cert_sn 和 alipay_root_cert_sn,业务代码仍然调用原来的支付或资金接口。

需要准备的证书

进入支付宝开放平台中的对应应用,找到“接口加签方式”或相关开发设置,选择公钥证书模式。按照平台指引生成并上传应用公钥证书,然后下载以下文件:

  1. 应用公钥证书,例如 appCertPublicKey_应用APPID.crt
  2. 支付宝公钥证书,例如 alipayCertPublicKey_RSA2.crt
  3. 支付宝根证书,例如 alipayRootCert.crt

还需要保留生成应用公钥证书时所对应的应用私钥。私钥应存放在服务端,不能上传到代码仓库,也不能放进前端、客户端安装包或公开配置文件。

这些证书必须属于当前调用所使用的 app_id,沙箱应用和正式应用的证书不能混用。

Java SDK 配置示例

支付宝 Java SDK的不同版本,在配置类和字段名称上可能略有区别。较新的版本通常使用 AlipayConfig:

import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;

AlipayConfig config = new AlipayConfig();
config.setServerUrl("https://openapi.alipay.com/gateway.do");
config.setAppId("YOUR_APP_ID");
config.setPrivateKey("YOUR_APP_PRIVATE_KEY");
config.setFormat("json");
config.setCharset("UTF-8");
config.setSignType("RSA2");

config.setAppCertPath("/secure/alipay/appCertPublicKey.crt");
config.setAlipayPublicCertPath("/secure/alipay/alipayCertPublicKey_RSA2.crt");
config.setRootCertPath("/secure/alipay/alipayRootCert.crt");

AlipayClient alipayClient = new DefaultAlipayClient(config);

部分旧版 SDK使用 CertAlipayRequest:

import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;

CertAlipayRequest config = new CertAlipayRequest();
config.setServerUrl("https://openapi.alipay.com/gateway.do");
config.setAppId("YOUR_APP_ID");
config.setPrivateKey("YOUR_APP_PRIVATE_KEY");
config.setFormat("json");
config.setCharset("UTF-8");
config.setSignType("RSA2");

config.setCertPath("/secure/alipay/appCertPublicKey.crt");
config.setAlipayPublicCertPath("/secure/alipay/alipayCertPublicKey_RSA2.crt");
config.setRootCertPath("/secure/alipay/alipayRootCert.crt");

AlipayClient alipayClient = new DefaultAlipayClient(config);

请根据项目实际使用的支付宝 SDK版本选择一种写法,不要混用两套配置。

使用证书客户端调用支付接口

初始化客户端后,支付接口的调用方式基本不变:

import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;

AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setReturnUrl("https://example.com/alipay/return");
request.setNotifyUrl("https://example.com/alipay/notify");

request.setBizContent("""
{
  "out_trade_no": "ORDER_202609090001",
  "total_amount": "99.00",
  "subject": "订单支付",
  "product_code": "FAST_INSTANT_TRADE_PAY"
}
""");

AlipayTradePagePayResponse response = alipayClient.pageExecute(request);

if (response.isSuccess()) {
    String paymentForm = response.getBody();
    // 将 paymentForm 返回给浏览器或写入 HTTP 响应
} else {
    throw new IllegalStateException(
        response.getCode() + ": " + response.getSubMsg()
    );
}

这里调用的仍是 alipay.trade.page.pay。证书模式客户端会处理证书序列号和请求签名,无须在业务参数中手工拼接。

接入提现或转账接口

接入前,先在支付宝开放平台确认以下信息:

  • 应用是否已签约对应的资金产品;
  • 实际开放的 API 名称;
  • 收款方身份类型和必填字段;
  • 是否需要资金授权、审核、额度或其他准入条件;
  • 当前应用是否被要求使用公钥证书模式。

如果实际使用商家转账类接口,应复用前面创建的 AlipayClient,不要为支付和转账分别维护普通公钥客户端和证书客户端。

下面只展示调用结构。具体请求类和业务字段,必须以已签约产品对应的接口文档为准:

AlipayFundTransUniTransferRequest request =
    new AlipayFundTransUniTransferRequest();

request.setBizContent("""
{
  "out_biz_no": "TRANSFER_202609090001",
  "trans_amount": "10.00",
  "product_code": "TRANS_ACCOUNT_NO_PWD",
  "biz_scene": "DIRECT_TRANSFER",
  "order_title": "用户提现",
  "payee_info": {
    "identity": "receiver@example.com",
    "identity_type": "ALIPAY_LOGON_ID"
  }
}
""");

AlipayFundTransUniTransferResponse response =
    alipayClient.certificateExecute(request);

if (!response.isSuccess()) {
    throw new IllegalStateException(
        response.getCode() + ": " + response.getSubMsg()
    );
}

alipay.fund.trans.uni.transfer 是否适用于当前业务、是否仍向该应用开放,以及应该使用 execute 还是 certificateExecute,都取决于当前 SDK版本和支付宝为该应用开通的产品。请以开放平台控制台生成的接口示例和当前 SDK文档为准。

异步通知也要改为证书验签

切换到证书模式后,支付和资金接口的异步通知也应通过支付宝公钥证书验签。Java SDK中的常见写法如下:

import com.alipay.api.internal.util.AlipaySignature;

boolean verified = AlipaySignature.rsaCertCheckV1(
    requestParams,
    "/secure/alipay/alipayCertPublicKey_RSA2.crt",
    "UTF-8",
    "RSA2"
);

if (!verified) {
    throw new SecurityException("支付宝异步通知验签失败");
}

requestParams 必须使用支付宝通知中的原始参数构造。验签前不要对参数值进行 URL 解码、JSON重组、格式化或字段删改,否则可能导致验签失败。

验签通过后,还需要核对:

  • app_id 是否属于当前应用;
  • out_trade_no 或业务单号是否存在;
  • 金额和币种是否与本地订单一致;
  • 交易状态是否符合处理条件;
  • 该通知是否已经处理,避免重复入账或重复发货。

切换时的注意事项

证书模式通常属于应用级配置。启用后,不要默认原有普通公钥模式可以长期与证书模式并行使用。支付请求、查询、退款、关闭订单、转账和异步通知验签都要一并检查。

上线前建议完成以下验证:

  • 使用正式应用对应的三份证书和私钥;
  • 确认私钥与应用公钥证书匹配;
  • 检查部署环境能否读取证书路径;
  • 确认证书文件内容没有被当作普通支付宝公钥使用;
  • 验证支付下单、同步跳转和异步通知;
  • 验证查询、退款和资金类接口;
  • 对相同业务单号实施幂等控制;
  • 记录支付宝返回的 code、sub_code、msg 和 sub_msg,但不要记录私钥或完整的敏感信息;
  • 建立证书更新机制,避免证书更换后,请求或通知突然无法通过验签。

较稳妥的做法是将整个应用的支付宝 SDK初始化和验签逻辑统一迁移到公钥证书模式,再通过同一个证书客户端调用支付接口和已获准使用的资金接口。

备注:内容仅供参考。