JeffreySu/WeiXinMPSDK · error · WeixinException

没有设置证书加密类型(EncryptionType)

Error message

没有设置证书加密类型(EncryptionType)

What it means

TenPayHttpClient's constructor requires the TenpayV3Setting to specify EncryptionType (RSA or SM certificate scheme), because it uses that value to select the signer/verifier via TenPayCertFactory. If SenparcWeixinSetting.TenpayV3Setting has no EncryptionType set, the client cannot be constructed and a WeixinException is thrown immediately.

Solutions

  1. Set EncryptionType on your TenpayV3Setting (RSA for standard certificates, SM for 国密) in appsettings.json or in code before constructing the client.
  2. If configuring via SenparcWeixinSetting, verify the bound section actually contains the EncryptionType field and that binding succeeds.
  3. After upgrading the package, migrate your config to include the newly required EncryptionType key.

Example fix

// before (appsettings.json)
"TenpayV3Setting": {
  "TenPayV3_MchId": "1900000001",
  "TenPayV3_APIv3Key": "..."
}
// after
"TenpayV3Setting": {
  "TenPayV3_MchId": "1900000001",
  "TenPayV3_APIv3Key": "...",
  "EncryptionType": "RSA"
}
Defensive patterns

Strategy: validation

Validate before calling

if (!setting.TenpayV3Setting.EncryptionType.HasValue)
    throw new InvalidOperationException("Configure TenpayV3Setting.EncryptionType (RSA|SM) before creating TenPayHttpClient.");

Type guard

bool HasEncryptionType(SenparcWeixinSetting s) => s?.TenpayV3Setting?.EncryptionType is CertType t and (CertType.RSA or CertType.SM);

Try / catch

try { var client = new TenPayHttpClient(httpClientFactory, setting); }
catch (WeixinException ex) { logger.LogCritical(ex, "TenPayV3 misconfigured"); throw; }

Prevention

When it happens

Trigger: Creating TenPayHttpClient (directly or via GetInstance) while the bound SenparcWeixinSetting has EncryptionType == null — e.g. the TenpayV3Setting section was not populated with the EncryptionType key.

Common situations: Upgrading from older Senparc.Weixin versions that predate the EncryptionType setting; copying appsettings from an older sample; configuring TenPayV3 via code but forgetting to assign EncryptionType; running under the SM (国密) pilot without setting the enum.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of JeffreySu/WeiXinMPSDK@be573f6f94 (2026-09-12). Data as JSON: /api/errors/ef3bd2b97fb9a98f. Report an issue: GitHub.

Appendix: source

Thrown at src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/TenPayHttpClient/TenPayHttpClient.cs:132

        {
            NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore
        };
        private readonly SenparcHttpClient _httpClient;
        private ISenparcWeixinSettingForTenpayV3 _tenpayV3Setting;
        private readonly HttpClient _client;
        private readonly ISigner _signer;
        private readonly IVerifier _verifier;
        private CertType CertType => _tenpayV3Setting.EncryptionType.Value;

        public TenPayHttpClient(SenparcHttpClient httpClient, ISenparcWeixinSettingForTenpayV3 senparcWeixinSettingForTenpayV3 = null)
        {
            this._httpClient = httpClient;
            this._client = this._httpClient.Client;
            _tenpayV3Setting = senparcWeixinSettingForTenpayV3 ?? Senparc.Weixin.Config.SenparcWeixinSetting.TenpayV3Setting;

            if (!_tenpayV3Setting.EncryptionType.HasValue)
            {
                throw new Senparc.Weixin.Exceptions.WeixinException("没有设置证书加密类型(EncryptionType)");
            }

            //从工厂获得签名和验签的方法类
            _signer = TenPayCertFactory.GetSigner(CertType);
            _verifier = TenPayCertFactory.GetVerifier(CertType);

        }

        public Task<T> SendAsync<T>(string url, object data, int timeOut = Senparc.Weixin.Config.TIME_OUT, ApiRequestMethod requestMethod = ApiRequestMethod.POST, bool checkSign = true, Func<T> createDefaultInstance = null)
                   where T : ReturnJsonBase/*, new()*/
        {
            return SendAsync(url, data, CancellationToken.None, timeOut, requestMethod, checkSign, createDefaultInstance);
        }

        public async Task<T> SendAsync<T>(string url, object data, CancellationToken cancellationToken, int timeOut = Senparc.Weixin.Config.TIME_OUT, ApiRequestMethod requestMethod = ApiRequestMethod.POST, bool checkSign = true, Func<T> createDefaultInstance = null)
                   where T : ReturnJsonBase/*, new()*/
        {
            T result = null;

View on GitHub (pinned to be573f6f94)