.NET C# 服务端创建支付宝支付订单时如何加载公钥证书?
结论
支付宝证书模式并不是用一个证书文件同时替代 APP_PRIVATE_KEY 和 ALIPAY_PUBLIC_KEY。切换到证书模式后,各文件的用途如下:
- 应用私钥仍用于请求签名,通常通过
PrivateKey传入。 - 应用公钥证书用于提交应用公钥,以及确定应用证书序列号。
- 支付宝公钥证书用于验证支付宝响应的签名。
- 支付宝根证书用于校验证书链,并计算根证书序列号。
较新的支付宝 .NET SDK 通常通过 AlipayConfig 配置三个证书路径,再创建 DefaultAopClient。CertAlipayRequest 来自其他语言版本或某些特定版本的 SDK,并非所有 .NET SDK 都有这个类型,不能直接照搬相关示例。
使用证书模式创建客户端
先从支付宝开放平台下载证书模式需要的文件,通常包括:
appCertPublicKey_应用ID.crt
alipayCertPublicKey_RSA2.crt
alipayRootCert.crt
接着配置客户端:
using Alipay.AopSdk.Core;
using Alipay.AopSdk.Core.Domain;
using Alipay.AopSdk.Core.Request;
using Alipay.AopSdk.Core.Response;
var config = new AlipayConfig
{
ServerUrl = "https://openapi.alipay.com/gateway.do",
AppId = APPID,
PrivateKey = APP_PRIVATE_KEY,
Format = "json",
Version = "1.0",
SignType = "RSA2",
Charset = "UTF-8",
AppCertPath = Server.MapPath("~/App_Data/alipay/appCertPublicKey.crt"),
AlipayPublicCertPath = Server.MapPath("~/App_Data/alipay/alipayCertPublicKey_RSA2.crt"),
RootCertPath = Server.MapPath("~/App_Data/alipay/alipayRootCert.crt")
};
IAopClient client = new DefaultAopClient(config);
创建订单时不需要改用其他请求类型,仍然使用 AlipayTradeAppPayRequest 和 SdkExecute:
var request = new AlipayTradeAppPayRequest();
var model = new AlipayTradeAppPayModel
{
Body = "我是测试数据",
Subject = "App支付测试DoNet",
TotalAmount = "0.01",
ProductCode = "QUICK_MSECURITY_PAY",
OutTradeNo = "20170216test01",
TimeoutExpress = "30m"
};
request.SetBizModel(model);
request.SetNotifyUrl("https://example.com/alipay/notify");
AlipayTradeAppPayResponse response = client.SdkExecute(request);
string orderString = response.Body;
Response.Write(HttpUtility.HtmlEncode(orderString));
response.Body 就是客户端调用支付宝 App 支付接口所需的 orderString。不要再次对它进行 URL 编码、签名或参数拼接。
私钥从文件加载
证书模式不会从 appCertPublicKey.crt 中读取应用私钥。公钥证书中只有公钥和证书信息,不包含私钥。
如果不想把私钥直接写进配置文件或代码,可以读取私钥文件后再交给 SDK:
string privateKeyPath =
Server.MapPath("~/App_Data/alipay/app_private_key.pem");
string privateKey = File.ReadAllText(privateKeyPath);
var config = new AlipayConfig
{
ServerUrl = "https://openapi.alipay.com/gateway.do",
AppId = APPID,
PrivateKey = privateKey,
Format = "json",
Version = "1.0",
SignType = "RSA2",
Charset = "UTF-8",
AppCertPath = Server.MapPath("~/App_Data/alipay/appCertPublicKey.crt"),
AlipayPublicCertPath = Server.MapPath("~/App_Data/alipay/alipayCertPublicKey_RSA2.crt"),
RootCertPath = Server.MapPath("~/App_Data/alipay/alipayRootCert.crt")
};
IAopClient client = new DefaultAopClient(config);
私钥格式需要与当前 SDK 版本兼容,例如 PKCS#1 或 PKCS#8。除非已安装版本的 SDK 文档明确要求,否则不要删除换行或手工截断私钥内容。
为什么找不到 CertAlipayRequest
CertAlipayRequest 不是支付业务请求类,而是部分支付宝 SDK 用来封装证书配置的类型。不同语言、NuGet 包和 SDK 版本使用的证书模式入口可能不同。
.NET 项目无法使用该类,常见原因有:
- 参考的是 Java SDK 示例,而项目实际使用的是 .NET SDK。
- 当前安装的 .NET SDK 没有定义或公开
CertAlipayRequest。 - 项目引用的是旧版 SDK,尚不支持通过
AlipayConfig配置证书。 - 使用了名称相近但 API 不兼容的第三方 NuGet 包。
不要为了调用它而自行创建同名类型。这样做不会自动启用 SDK 的证书序列号计算和证书验签逻辑。
如果当前版本中没有 AlipayConfig.AppCertPath、AlipayPublicCertPath 或 RootCertPath,上述代码就不适用于该版本。可以升级到明确支持证书模式的支付宝官方 .NET SDK,也可以按照当前 SDK 实际提供的证书客户端构造方法进行配置。升级前应检查目标运行时的兼容性,旧版 .NET Framework 项目尤其需要注意。
注意事项
- 开放平台应用必须已经切换或配置为证书模式,密钥模式与证书模式不能混用。
AppCertPath必须指向应用公钥证书,不能指向应用私钥文件。AlipayPublicCertPath应指向 RSA2 对应的支付宝公钥证书。RootCertPath应指向支付宝根证书,不能用操作系统根证书替代。- 发布后应确认运行账户有权读取证书和私钥文件。
- 不要把私钥放在网站静态目录中,也不要提交到 Git 仓库。
- 在 ASP.NET 部署环境中应使用绝对路径。相对路径可能因工作目录变化而失效。
HttpUtility.HtmlEncode只用于在 HTML 页面中展示内容。实际返回给 App 时,应原样返回response.Body。- 生产环境必须使用唯一的
OutTradeNo,不能长期重复使用示例订单号。 - 更新证书后,应同步替换相应文件,并重启或重新创建客户端,避免进程继续使用缓存的旧证书。
备注:内容仅供参考。
