public async Task <T> ExecuteAsync <T>(IWeChatPayRequest <T> request) where T : WeChatPayResponse
        {
            try
            {
                // 字典排序
                var sortedTxtParams = new WeChatPayDictionary(request.GetParameters())
                {
                    { mch_id, Options.MchId },
                    { nonce_str, Guid.NewGuid().ToString("N") },
                    { notify_url, Options.NotifyUrl }
                };

                if (string.IsNullOrEmpty(sortedTxtParams.GetValue(appid)))
                {
                    sortedTxtParams.Add(appid, Options.AppId);
                }

                sortedTxtParams.Add(sign, WeChatPaySignature.SignWithKey(sortedTxtParams, Options.Key));
                var content = HttpClientEx.BuildContent(sortedTxtParams);

                var body = await Client.DoPostAsync(request.GetRequestUrl(), content);

                var parser = new WeChatPayXmlParser <T>();
                var rsp    = parser.Parse(body);
                CheckResponseSign(rsp);
                return(rsp);
            }
            catch (Exception ex)
            {
                logger?.LogError($"{DateTime.Now} ExecuteAsync(1)", ex.Message);
                return(null);
            }
        }
        public Task <WeChatPayDictionary> ExecuteAsync(IWeChatPayCalcRequest request)
        {
            try
            {
                var sortedTxtParams = new WeChatPayDictionary(request.GetParameters());
                if (request is WeChatPayAppCallPaymentRequest)
                {
                    if (string.IsNullOrEmpty(sortedTxtParams.GetValue(appid)))
                    {
                        sortedTxtParams.Add(appid, Options.AppId);
                    }

                    if (string.IsNullOrEmpty(sortedTxtParams.GetValue(partnerid)))
                    {
                        sortedTxtParams.Add(partnerid, Options.MchId);
                    }
                    sortedTxtParams.Add(noncestr, Guid.NewGuid().ToString("N"));
                    sortedTxtParams.Add(timestamp, WeChatPayUtility.GetTimeStamp());
                    sortedTxtParams.Add(sign, WeChatPaySignature.SignWithKey(sortedTxtParams, Options.Key));
                }
                else if (request is WeChatPayLiteAppCallPaymentRequest || request is WeChatPayH5CallPaymentRequest)
                {
                    if (string.IsNullOrEmpty(sortedTxtParams.GetValue(appId)))
                    {
                        sortedTxtParams.Add(appId, Options.AppId);
                    }

                    sortedTxtParams.Add(timeStamp, WeChatPayUtility.GetTimeStamp());
                    sortedTxtParams.Add(nonceStr, Guid.NewGuid().ToString("N"));
                    sortedTxtParams.Add(signType, "MD5");
                    sortedTxtParams.Add(paySign, WeChatPaySignature.SignWithKey(sortedTxtParams, Options.Key));
                }
                return(Task.FromResult(sortedTxtParams));
            }
            catch (Exception ex)
            {
                logger?.LogError($"{DateTime.Now} ExecuteAsync", ex.Message);
                return(null);
            }
        }
        public async Task <T> ExecuteAsync <T>(IWeChatPayCertificateRequest <T> request) where T : WeChatPayResponse
        {
            try
            {
                var signType        = true; // ture:MD5,false:HMAC-SHA256
                var excludeSignType = true;

                if (CertificateClient == null)
                {
                    throw new ArgumentNullException(nameof(Options.Certificate));
                }

                // 字典排序
                var sortedTxtParams = new WeChatPayDictionary(request.GetParameters());
                if (request is WeChatPayTransfersRequest)
                {
                    if (string.IsNullOrEmpty(sortedTxtParams.GetValue(mch_appid)))
                    {
                        sortedTxtParams.Add(mch_appid, Options.AppId);
                    }

                    sortedTxtParams.Add(mchid, Options.MchId);
                }
                else if (request is WeChatPayGetPublicKeyRequest)
                {
                    sortedTxtParams.Add(mch_id, Options.MchId);
                    sortedTxtParams.Add(sign_type, "MD5");
                    excludeSignType = false;
                }
                else if (request is WeChatPayPayBankRequest)
                {
                    if (PublicKey == null)
                    {
                        throw new ArgumentNullException(nameof(Options.RsaPublicKey));
                    }

                    var no = RSA_ECB_OAEPWithSHA1AndMGF1Padding.Encrypt(sortedTxtParams.GetValue(enc_bank_no), PublicKey);
                    sortedTxtParams.SetValue(enc_bank_no, no);

                    var name = RSA_ECB_OAEPWithSHA1AndMGF1Padding.Encrypt(sortedTxtParams.GetValue(enc_true_name), PublicKey);
                    sortedTxtParams.SetValue(enc_true_name, name);

                    sortedTxtParams.Add(mch_id, Options.MchId);
                    sortedTxtParams.Add(sign_type, "MD5");
                }
                else if (request is WeChatPayQueryBankRequest)
                {
                    sortedTxtParams.Add(mch_id, Options.MchId);
                    sortedTxtParams.Add(sign_type, "MD5");
                }
                else if (request is WeChatPayGetTransferInfoRequest)
                {
                    if (string.IsNullOrEmpty(sortedTxtParams.GetValue(appid)))
                    {
                        sortedTxtParams.Add(appid, Options.AppId);
                    }

                    sortedTxtParams.Add(mch_id, Options.MchId);
                    sortedTxtParams.Add(sign_type, "MD5");
                }
                else if (request is WeChatPayDownloadFundFlowRequest)
                {
                    if (string.IsNullOrEmpty(sortedTxtParams.GetValue(appid)))
                    {
                        sortedTxtParams.Add(appid, Options.AppId);
                    }

                    sortedTxtParams.Add(mch_id, Options.MchId);
                    signType = false; // HMAC-SHA256
                }
                else if (request is WeChatPayRefundRequest)
                {
                    if (string.IsNullOrEmpty(sortedTxtParams.GetValue(appid)))
                    {
                        sortedTxtParams.Add(appid, Options.AppId);
                    }

                    sortedTxtParams.Add(notify_url, Options.RefundNotifyUrl);
                    sortedTxtParams.Add(mch_id, Options.MchId);
                }
                else if (request is WeChatPaySendRedPackRequest || request is WeChatPaySendGroupRedPackRequest)
                {
                    if (string.IsNullOrEmpty(sortedTxtParams.GetValue(wxappid)))
                    {
                        sortedTxtParams.Add(wxappid, Options.AppId);
                    }

                    sortedTxtParams.Add(mch_id, Options.MchId);
                }
                else // 其他接口
                {
                    if (string.IsNullOrEmpty(sortedTxtParams.GetValue(appid)))
                    {
                        sortedTxtParams.Add(appid, Options.AppId);
                    }

                    sortedTxtParams.Add(mch_id, Options.MchId);
                }

                sortedTxtParams.Add(nonce_str, Guid.NewGuid().ToString("N"));
                sortedTxtParams.Add(sign, WeChatPaySignature.SignWithKey(sortedTxtParams, Options.Key, signType, excludeSignType));

                var content = HttpClientEx.BuildContent(sortedTxtParams);

                logger.LogInformation($"{DateTime.Now} content:{content}");
                logger.LogInformation($"{DateTime.Now} GetRequestUrl:{request.GetRequestUrl()}");

                var body = await CertificateClient.DoPostAsync(request.GetRequestUrl(), content);

                logger.LogInformation($"{DateTime.Now} body:{body}");

                var parser = new WeChatPayXmlParser <T>();
                var rsp    = parser.Parse(body);
                CheckResponseSign(rsp, signType, excludeSignType);
                return(rsp);
            }
            catch (Exception ex)
            {
                logger.LogInformation($"{DateTime.Now} ExecuteAsync6666:{ex.Message}", ex.Message);
                return(null);
            }
        }