收藏
回答

微信支付分账接口,添加分账方时提示:平台证书序列号Wechatpay-Serial错误

问题:接口返回信息“平台证书序列号Wechatpay-Serial错误”

Wechatpay-Serial字段根据要求也进行了加密,但是一直提示这个错误,也没法校验到底哪出错了。申明一下加密用的是微信支付平台证书序列号,不是商户证书序列号;

请求参数

/// <summary>
        /// 添加分账接收方
        /// </summary>
        /// <param name="account"></param>
        /// <param name="name"></param>
        /// <param name="relation_type"></param>
        /// <returns></returns>
        public static string AddReceiver(string account, string name, string relation_type, string public_key)
        {
            // 敏感信息加密
            var enrypt_name = "pUrPcj/7VWvH11fBIE/KcMdt89KEcbnyEEGuVZ74jBGzskgPAaGl9VcF0Eagkx0EcSqWqHSZZy5+D91q2n4yk91jHIrCFEvLk4ZUVfljKvXcyZBZBXZYjjFFba3KoCEOjGFnhCJUHOfqnk0DVCxmqhHKQ6HwhvxhNWPjtrZ8s0PZXn3zrZtCsir3TeqpmqZLTgrIjJRlaJplwFMFl5iYuWJqZT1GTfMAVlRD/QiQTwjuxkPki40PYc/+HHVRiKz+6Jg6r0aHG7KWiM1r/QtUkNyLKKsIfGKMKllo8RJbgce7dz1VDTZah04jMtoxM9DjpnOb5qq6yCqlZjuutrPASQ==";
            SortedDictionary<string, object> dic = new SortedDictionary<string, object>();
            dic.Add("appid", WeChatConfig.APPID);
            dic.Add("type", "MERCHANT_ID");
            dic.Add("account", "15333560710");
            dic.Add("name", enrypt_name);
            dic.Add("relation_type", "PARTNER");
            var data = Newtonsoft.Json.JsonConvert.SerializeObject(dic);


            var url = "https://api.mch.weixin.qq.com/v3/profitsharing/receivers/add";
            var path = System.Environment.CurrentDirectory + "/wwwroot/apiclient_cert.p12";
            X509Certificate2 cert = new X509Certificate2(path, WeChatConfig.MCHID, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
            var serial_no = cert.SerialNumber;
            string result = RequestData(url, data, WeChatConfig.MCHID, serial_no, public_key);


            return result;
        }

发送请求

/// <summary>
        /// 发送请求至微信
        /// </summary>
        /// <param name="url"></param>
        /// <param name="data"></param>
        /// <param name="mchid"></param>
        /// <param name="serial_no"></param>
        /// <param name="public_key"></param>
        /// <returns></returns>
        public static string RequestData(string url, string data, string mchid, string serial_no, string public_key)
        {
            byte[] byte_public_key = Encoding.UTF8.GetBytes(public_key);
            var encrypt_serial_no = RSAEncrypt("1D99F55A2525B50D10571B129F274FB801769CBB", byte_public_key);
  
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = "application/json;";
            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, "POST", data, mchid, serial_no);
            request.Headers.Add("Authorization", authorization);
            request.Headers.Add("Wechatpay-Serial", encrypt_serial_no);


            byte[] paramJsonBytes;
            paramJsonBytes = Encoding.UTF8.GetBytes(data);
            request.ContentLength = paramJsonBytes.Length;


            Stream writer;
            try
            {
                writer = request.GetRequestStream();
            }
            catch (Exception)
            {
                writer = null;
            }
            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>
        /// <param name="text">微信支付平台证书序列号</param>
        /// <param name="publicKey">公钥</param>
        /// <returns></returns>
        public static string RSAEncrypt(string text, byte[] publicKey)
        {
            var cer = new X509Certificate2(publicKey);
            var rsaParam = cer.GetRSAPublicKey().ExportParameters(true);
            var rsa = new RSACryptoServiceProvider();
            rsa.ImportParameters(rsaParam);
            var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), true);


            return Convert.ToBase64String(buff);
        }

签名

protected static string Sign(string message)
        {
            var path = System.Environment.CurrentDirectory + "/wwwroot/apiclient_cert.p12";
            X509Certificate2 cert = new X509Certificate2(path, WeChatConfig.MCHID, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
            var privateKey = cert.PrivateKey.ToXmlString(true);


            using (RSACryptoServiceProvider sha256 = new RSACryptoServiceProvider())
            {
                byte[] dataInBytes = Encoding.UTF8.GetBytes(message);
                sha256.FromXmlString(privateKey);
                byte[] inArray = sha256.SignData(dataInBytes, CryptoConfig.MapNameToOID("SHA256"));
                string sign = Convert.ToBase64String(inArray);
                return sign;
            }
        }

获取签名

/// <summary>
        /// 获取签名认证
        /// </summary>
        /// <param name="url">请求URL</param>
        /// <param name="method">请求方法</param>
        /// <param name="data">数据对象</param>
        /// <param name="mchid">商户ID</param>
        /// <param name="serial_no">商户私钥证书对应的序列号</param>
        /// <returns></returns>
        protected static string GetAuthorization(string url, string method, string data, string mchid, string serial_no)
        {
            var uri = new Uri(url);
            string url_path = uri.PathAndQuery;
            string nonce = Guid.NewGuid().ToString();
            var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
            method = string.IsNullOrEmpty(method) ? "" : method;
            string message = string.Format("{0}\n{1}\n{2}\n{3}\n", method, url_path, timestamp, nonce);
            if (!string.IsNullOrEmpty(data))
            {
                message = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n", method, url_path, timestamp, nonce, data);
            }


            string sign = Sign(message);


            // 签名认证格式
            string authorization = string.Format("WECHATPAY2-SHA256-RSA2048 mchid=\"{0}\",nonce_str=\"{1}\",timestamp=\"{2}\",serial_no=\"{3}\",signature=\"{4}\"",
                mchid,
                nonce,
                timestamp,
                serial_no,
                sign
                );


            return authorization;
        }

111


回答关注问题邀请回答
收藏

1 个回答

  • Memory
    Memory
    2023-11-07

    你既然说你用的没错,放postman里面去验证,报错说明还是你用的不对

    2023-11-07
    有用
    回复 9
    • Adin
      Adin
      2023-11-07
      根据这个返回错误信息,没法知道具体问题出在哪啊?有可能是加密算法有问题,导致微信那边解析不出来,判定为平台证书序列号Wechatpay-Serial错误
      2023-11-07
      回复
    • Adin
      Adin
      2023-11-07
      不知道微信这边有没有敏感信息加密解密校验工具?
      2023-11-07
      回复
    • Memory
      Memory
      2023-11-07回复Adin
      用postman可以快速定位,你先去用postman验证一下,postman脚本里面有预置平台证书获取,可以直接用里面返回的序列号直接请求
      2023-11-07
      回复
    • Adin
      Adin
      2023-11-07
      我也试过微信官方POSTMAN脚本,也是返回此错误信息
      2023-11-07
      回复
    • Memory
      Memory
      2023-11-07回复Adin
      。。。
      2023-11-07
      回复
    查看更多(4)
登录 后发表内容