.NET C# App支付创建订单时如何使用公钥证书加签
结论
.NET SDK 通常不使用 Java SDK 中的 CertAlipayRequest。在 .NET SDK 中,证书模式一般通过 AlipayConfig 配置。填入应用私钥、应用公钥证书、支付宝公钥证书和支付宝根证书后,再用该配置创建 DefaultAopClient。
“公钥证书加签”并不是用公钥证书生成签名。请求仍由应用私钥签名,证书模式负责:
- 根据应用公钥证书生成并提交
app_cert_sn - 根据支付宝根证书生成并提交
alipay_root_cert_sn - 从支付宝公钥证书中读取支付宝公钥,用于验签
因此,使用证书模式时,不要再把普通公钥字符串作为 ALIPAY_PUBLIC_KEY 传给旧版构造函数。
.NET 证书模式示例
下面的写法适用于支持通过 AlipayConfig 配置证书路径的 .NET SDK。不同版本的属性名称可能略有区别,请以项目当前引用版本的 API 为准。
using Aop.Api;
using Aop.Api.Domain;
using Aop.Api.Request;
using Aop.Api.Response;
AlipayConfig config = new AlipayConfig
{
ServerUrl = "https://openapi.alipay.com/gateway.do",
AppId = APPID,
// 应用私钥内容,不是应用公钥,也不是证书内容
PrivateKey = APP_PRIVATE_KEY,
Format = "json",
Charset = "UTF-8",
SignType = "RSA2",
// 应用公钥证书
AppCertPath = @"D:\alipay\appCertPublicKey_APPID.crt",
// 支付宝公钥证书
AlipayPublicCertPath = @"D:\alipay\alipayCertPublicKey_RSA2.crt",
// 支付宝根证书
RootCertPath = @"D:\alipay\alipayRootCert.crt"
};
IAopClient client = new DefaultAopClient(config);
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel
{
Body = "我是测试数据",
Subject = "App支付测试DoNet",
TotalAmount = "0.01",
ProductCode = "QUICK_MSECURITY_PAY",
OutTradeNo = "202609090001",
TimeoutExpress = "30m"
};
request.SetBizModel(model);
request.SetNotifyUrl("https://example.com/alipay/notify");
AlipayTradeAppPayResponse response = client.SdkExecute(request);
// response.Body 即客户端调起支付宝所需的 orderString。
// 传给 App 客户端时不要反序列化、重新排序或再次签名。
string orderString = response.Body;
SDK 会计算证书序列号,并把证书相关的公共参数加入待签名内容。业务代码仍然调用 SdkExecute,无需自行拼接 app_cert_sn,也不必重新实现 RSA2 签名。
为什么没有 CertAlipayRequest
CertAlipayRequest 是部分 Java SDK 版本用来封装证书模式初始化参数的类型,并非支付宝开放平台接口的业务请求类。
.NET SDK 的类设计不同,一般通过:
AlipayConfig
配合:
new DefaultAopClient(config)
完成相同的配置。不同语言的 SDK 不一定使用相同的辅助类名称,因此不能照着 Java 类名在 .NET SDK 中查找。
如果当前引用的 .NET SDK 没有 AlipayConfig、AppCertPath、AlipayPublicCertPath 或 RootCertPath,通常是因为 SDK 版本较早,或者使用的 SDK 包不支持证书模式。应先升级到支持公钥证书模式的官方 .NET SDK,再根据该版本提供的构造函数或配置类完成初始化。
不建议从其他版本中复制 SDK 内部的证书序列号计算代码。证书解析、根证书序列号拼接和验签处理都可能出现兼容问题。
需要准备的文件
证书模式一般需要三份证书:
-
应用公钥证书
文件名通常类似:
appCertPublicKey_APPID.crt -
支付宝公钥证书
文件名通常类似:
alipayCertPublicKey_RSA2.crt -
支付宝根证书
文件名通常类似:
alipayRootCert.crt
此外,还需要应用私钥。应用私钥与应用公钥证书必须来自同一密钥对,否则支付宝无法正确验证请求签名。
普通公钥模式与证书模式不要混用
原代码使用的是普通公钥模式:
new DefaultAopClient(
"https://openapi.alipay.com/gateway.do",
APPID,
APP_PRIVATE_KEY,
"json",
"1.0",
"RSA2",
ALIPAY_PUBLIC_KEY,
CHARSET,
false
);
这里的 ALIPAY_PUBLIC_KEY 应是普通公钥模式下的支付宝公钥字符串,不能用它代替支付宝公钥证书路径,也不能把这种初始化方式与证书模式配置混用。
如果支付宝开放平台中的应用接口加签方式已设置为“公钥证书”,服务端也必须按证书模式初始化 SDK。平台配置为“公钥”时,则继续使用普通公钥模式。
常见错误排查
1. 把应用公钥当作应用私钥
请求必须使用应用私钥签名:
PrivateKey = APP_PRIVATE_KEY
应用公钥证书用于标识和验证对应的密钥,不能代替应用私钥完成签名。
2. 使用了错误环境的证书
沙箱和正式环境的网关、应用配置及密钥必须相互对应。正式环境网关为:
https://openapi.alipay.com/gateway.do
不要在当前应用中使用其他应用或其他环境下载的证书。
3. 三份证书不配套
应用公钥证书、支付宝公钥证书和支付宝根证书,应从当前应用对应的开放平台配置中获取。更换密钥或重新配置证书后,也要同步更新服务端的证书文件。
4. 私钥格式不符合 SDK 要求
有些 SDK 版本接受不带 PEM 头尾的私钥正文,有些版本可以直接处理 PEM 格式。具体格式应以当前 SDK 的配置说明为准。
常见问题包括重复进行 Base64 解码、把换行符写成字面量 \n,以及误把 .crt 文件内容当作私钥传入。
5. 修改了 response.Body
SdkExecute 返回的 response.Body 已经是完整的 orderString。服务端不要再对它进行 URL 解码、参数排序或二次签名,原样返回给 App 客户端即可。
HttpUtility.HtmlEncode 只适合在 HTML 页面中显示字符串,编码后的结果不能作为实际的 orderString 传给客户端。通过 JSON 或 HTTP 接口返回时,应保留原字符串,由正常的响应序列化过程处理转义。
备注:内容仅供参考。
