C# .Net Core开发微信转账到零钱遇到的坑

        首先,我要吐槽一下微信这些人办事的态度,真是不负责任,之前的【商家付款到零钱】用的好好的,强制换成这个东西,换了就换了吧,你把文档弄完善好吗,文档写的含糊不清,有些地方的链接点进去居然还是V2的东西,甚至404,我只能说呵呵了。

        话不多说,直接贴代码:  

     /// <summary>
        /// 获取authorzation 值
        /// </summary>
        /// <param name="url">微信的接口地址</param>
        /// <param name="method">请求的方式GET,POST,PUT</param>
        /// <param name="jsonParame">post请求的数据,json格式  ,get时传空</param>
        /// <param name="privateKey">apiclient_key.pem中的内容,不要-----BEGIN PRIVATE KEY-----  -----END PRIVATE KEY-----</param>
        /// <param name="merchantId">发起请求的商户(包括直连商户、服务商或渠道商)的商户号 mchid</param>
        /// <param name="serialNo">商户证书号</param>
        /// <returns></returns>
        protected string GetAuthorization(string url, string method, string jsonParame, string merchantId, string serialNo)
        {
            var uri = new Uri(url);
            string urlPath = uri.PathAndQuery;
            string nonce = Guid.NewGuid().ToString();
            var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
            //数据签名     HTTP请求方法n接口地址的urln请求时间戳n请求随机串n请求报文主体n
            method = string.IsNullOrEmpty(method) ? "" : method;
            string message = $"{method}\n{urlPath}\n{timestamp}\n{nonce}\n{jsonParame}\n";
            string signTxt = Sign(message);
            //Authorization和格式
            string authorzationTxt = $"mchid=\"{merchantId}\",nonce_str=\"{nonce}\",timestamp=\"{timestamp}\",serial_no=\"{serialNo}\",signature=\"{signTxt}\""; ;
            return authorzationTxt;
        }


/// <summary>
        /// V3版本请求接口
        /// </summary>
        /// <param name="url">微信的接口地址</param>
        /// <param name="postData">post请求的数据,json格式 </param>
        /// <param name="privateKey">apiclient_key.pem中的内容,不要-----BEGIN PRIVATE KEY-----  -----END PRIVATE KEY-----</param>
        /// <param name="merchantId">发起请求的商户(包括直连商户、服务商或渠道商)的商户号 mchid</param>
        /// <param name="serialNo">商户证书号</param>
        /// <param name="method"></param>
        /// <returns></returns>
        public string WxV3PostJson(string url, string postData, string merchantId, string serialNo, string method, string wxserial_no)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = method;
            request.ContentType = "application/json;charset=UTF-8";
            request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36";
            request.Accept = "application/json";
            string Authorization = GetAuthorization(url, method, postData, merchantId, serialNo);
            string value = $"WECHATPAY2-SHA256-RSA2048 {Authorization}";
            request.Headers.Add("Authorization", value);
            if (!string.IsNullOrEmpty(wxserial_no))
            {
                request.Headers.Add("Wechatpay-Serial", wxserial_no);

            }
            if (!string.IsNullOrEmpty(postData))
            {
                byte[] paramJsonBytes;
                paramJsonBytes = System.Text.Encoding.UTF8.GetBytes(postData);
                request.ContentLength = paramJsonBytes.Length;
                Stream writer;
                try
                {
                    writer = request.GetRequestStream();
                }
                catch (Exception e)
                {
                    writer = null;
                    _log.Info("请求接口失败:" + e.Message);
                }
                writer.Write(paramJsonBytes, 0, paramJsonBytes.Length);
                writer.Close();
            }

            HttpWebResponse response;
            try
            {
                response = (HttpWebResponse)request.GetResponse();
            }
            catch (WebException ex)
            {
                response = ex.Response as HttpWebResponse;
            }
            Stream resStream = response.GetResponseStream();
            StreamReader reader = new StreamReader(resStream);
            string text = reader.ReadToEnd();
            return text;
        }

      /// <summary>
        /// 获取签名
        /// </summary>
        protected string Sign(string message)
        {
            //加载证书 _apiCertPath API证书物理路径 _certPwd API证书密码(默认是商户号)

            string path = MyServiceProvider.ServiceProvider.GetRequiredService<IHostEnvironment>().ContentRootPath;
            X509Certificate2 cer = new X509Certificate2(path + SSLCERT_PATH, _settings.mchild, X509KeyStorageFlags.Exportable);
            if (cer != null)
            {
                RSA rsa = cer.GetRSAPrivateKey();  //获取私钥 //查看在不同平台上的具体类型
                byte[] data = Encoding.UTF8.GetBytes(message);
                return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
            }
            else
            {
                return "";
            }
        }

  public static string RSAEncrypt(string text, byte[] publicKey)
        {
            try
            {
                using (var x509 = new X509Certificate2(publicKey))
                {
                    var rsaParam = x509.GetRSAPublicKey().ExportParameters(false);
                    var rsa = new RSACryptoServiceProvider();
                    rsa.ImportParameters(rsaParam);
                    var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), true);
                    return Convert.ToBase64String(buff);

                }
            }
            catch (Exception ex)
            {

                throw;
            }
        }

[HttpPost]
        /// <summary>
        /// 商家转账到零钱
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ResultObj> WithDrawsToWx(PayReq dto)
        {
            try
            {
                var body = new
                {
                    appid = _settings.wxmp_appid,
                    out_batch_no = dto.out_batch_no,
                    batch_name = dto.batch_name,
                    batch_remark = dto.batch_remark,
                    total_amount = dto.total_amount,
                    total_num = dto.total_num,
                    transfer_scene_id = dto.transfer_scene_id,
                    transfer_detail_list = dto.transfer_detail_list

                };
                string Authorization2 = GetAuthorization2("/v3/certificates", "GET", _settings.mchild, _settings.api_serialNo);
                certificates certificate = JsonConvert.DeserializeObject<certificates>(Authorization2);

                if (certificate.data.Count == 0)
                {
                    _log.Info("获取支付平台证书序列号的时候出错了");
                }
                string publickey = AesGcmHelper.AesGcmDecrypt(certificate.data[0].encrypt_certificate.associated_data, certificate.data[0].encrypt_certificate.nonce, certificate.data[0].encrypt_certificate.ciphertext);
                foreach (Transfer_Detail_Item item in dto.transfer_detail_list)
                {
                    item.user_name = RSAEncrypt(item.user_name, Encoding.Default.GetBytes(publickey));
                }
                var url = "https://api.mch.weixin.qq.com/v3/transfer/batches";
                string transactionsResponse = WxV3PostJson(url, JsonConvert.SerializeObject(body), _settings.mchild, _settings.api_serialNo, "POST", certificate.data[0].serial_no);
                //_log.LogInformation("商户转账到零钱返回:" + transactionsResponse);
                //WithDrawsV3Back result =JsonConvert.DeserializeObject<WithDrawsV3Back>(transactionsResponse);

                return ResultObj.WebSuccess(transactionsResponse);
            }
            catch (Exception ex)
            {
                return ResultObj.WebSuccess(ex.Message);
                throw;
            }
        }

        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值