docs/NET9_CERTIFICATE_COMPATIBILITY.md
在升级到 .NET 9.0 后,TenPayV3 退款操作可能会遇到 SSL 证书错误:
Senparc.Weixin.Exceptions.WeixinException: The SSL connection could not be established, see inner exception
.NET 9.0 对 X509Certificate2 的加载和处理进行了更严格的验证,特别是:
本项目已经实现了以下兼容性修复:
X509KeyStorageFlags storageFlags;
#if NET9_0_OR_GREATER
// .NET 9.0+: 使用更兼容的标志组合
storageFlags = X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet;
if (System.OperatingSystem.IsWindows())
{
// 仅在 Windows 上使用 MachineKeySet
storageFlags |= X509KeyStorageFlags.MachineKeySet;
}
#else
// 旧版本 .NET: 保持原有行为
storageFlags = X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet;
#endif
var cert = new X509Certificate2(certPath, certPassword, storageFlags);
#if NET9_0_OR_GREATER
// 显式支持 TLS 1.2 和 TLS 1.3
httpClientHandler.SslProtocols = System.Security.Authentication.SslProtocols.Tls12
| System.Security.Authentication.SslProtocols.Tls13;
// 确保证书选择回调正确处理客户端证书
httpClientHandler.ClientCertificateOptions = System.Net.Http.ClientCertificateOption.Manual;
#endif
如问题中 @JeffreySu 所建议,.NET 8.0 是长期支持(LTS)版本,推荐用于生产环境:
确保:
# 验证证书是否有效(Windows PowerShell)
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("apiclient_cert.p12", "password")
$cert | Format-List
# 验证证书是否有效(Linux/macOS)
openssl pkcs12 -info -in apiclient_cert.p12
在配置中启用 Senparc.Weixin 的详细日志,查看证书加载过程:
// appsettings.json
{
"SenparcWeixinSetting": {
"IsDebug": true,
// ...其他配置
}
}
| 错误信息 | 可能原因 | 解决方案 |
|---|---|---|
| "The SSL connection could not be established" | 证书加载失败 | 检查证书路径、密码、格式 |
| "Unable to read data from the transport connection" | TLS 协议不匹配 | 更新到包含 .NET 9.0 修复的版本 |
| "The credentials supplied to the package were not recognized" | 证书私钥权限问题 | 在 Linux/macOS 上检查文件权限 |
| 标志 | .NET 8.0 | .NET 9.0 | 说明 |
|---|---|---|---|
| Exportable | 可选 | 推荐 | 允许私钥导出,提高跨平台兼容性 |
| PersistKeySet | 必需 | 必需 | 将密钥持久化到密钥存储 |
| MachineKeySet | 推荐 | 仅 Windows | 在机器级别存储密钥(非 Windows 平台不支持) |
After upgrading to .NET 9.0, TenPayV3 refund operations may encounter SSL certificate errors:
Senparc.Weixin.Exceptions.WeixinException: The SSL connection could not be established, see inner exception
.NET 9.0 introduced stricter validation for X509Certificate2 loading and handling:
This project has implemented the following compatibility fixes:
X509KeyStorageFlags storageFlags;
#if NET9_0_OR_GREATER
// .NET 9.0+: Use more compatible flag combination
storageFlags = X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet;
if (System.OperatingSystem.IsWindows())
{
// Only use MachineKeySet on Windows
storageFlags |= X509KeyStorageFlags.MachineKeySet;
}
#else
// Older .NET versions: Maintain original behavior
storageFlags = X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet;
#endif
var cert = new X509Certificate2(certPath, certPassword, storageFlags);
#if NET9_0_OR_GREATER
// Explicitly support TLS 1.2 and TLS 1.3
httpClientHandler.SslProtocols = System.Security.Authentication.SslProtocols.Tls12
| System.Security.Authentication.SslProtocols.Tls13;
// Ensure certificate selection callback handles client certificates correctly
httpClientHandler.ClientCertificateOptions = System.Net.Http.ClientCertificateOption.Manual;
#endif
As suggested by @JeffreySu in the issue, .NET 8.0 is the Long-Term Support (LTS) version recommended for production:
Ensure:
# Verify certificate (Windows PowerShell)
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("apiclient_cert.p12", "password")
$cert | Format-List
# Verify certificate (Linux/macOS)
openssl pkcs12 -info -in apiclient_cert.p12
Enable detailed logging in Senparc.Weixin configuration:
// appsettings.json
{
"SenparcWeixinSetting": {
"IsDebug": true,
// ...other settings
}
}
| Error Message | Possible Cause | Solution |
|---|---|---|
| "The SSL connection could not be established" | Certificate loading failed | Check certificate path, password, format |
| "Unable to read data from the transport connection" | TLS protocol mismatch | Update to version with .NET 9.0 fixes |
| "The credentials supplied to the package were not recognized" | Certificate private key permission issue | Check file permissions on Linux/macOS |
| Flag | .NET 8.0 | .NET 9.0 | Description |
|---|---|---|---|
| Exportable | Optional | Recommended | Allows private key export, improves cross-platform compatibility |
| PersistKeySet | Required | Required | Persists keys to key storage |
| MachineKeySet | Recommended | Windows Only | Stores keys at machine level (not supported on non-Windows platforms) |