不知道为什么网上资料好少,有也是java的。 也不知道是不是我太菜了搞了一天才搞定,最后发现是被自己坑了。。。。借助于fiddler才找的问题。
A. V3加密使用的是 SHA256-RSA 直接代码,我用的是p12直接解析。
// 1- 拼接待加密的字符串 string timestamp = GetTimeStamp(); //获取时间戳 string body = "{\"stock_id\": \"\",\"out_request_no\": \"\",\"appid\": \"\",\"stock_creator_mchid\": \"\"\"coupon_value\": null,\"coupon_minimum\": null}" ; //这里只是一个例子 string method = "POST" ; string apiurl = "/v3/marketing/favor/users/1211111/coupons" ; // string nonce_str = "3fefdfc321ba5bfb60849d8d0f4ebf08" ; //32位的随机字符串 StringBuilder sbstrhead = new StringBuilder(); sbstrhead.Append(method + "\n" ); sbstrhead.Append(apiurl + "\n" ); sbstrhead.Append(timestamp + "\n" ); sbstrhead.Append(nonce_str + "\n" ); sbstrhead.Append(body + "\n" );
string pfxFilePath =@"F:\";
// 2- 调用加密方法传入 string signstr =SHA256Encrypt(sbstrhead.ToString(), pfxFilePath, "1234567" ); /// <summary> /// Allen -获取时间戳 /// </summary> /// <returns></returns> public static string GetTimeStamp() { //生成1970年到现在的秒数 TimeSpan timeSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1)); //TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(timeSpan.TotalSeconds).ToString(); } /// <summary> /// Allen - sha256签名带密钥 /// </summary> /// <param name="data2">加密数据</param> /// <param name="pfxFilePath">P12对应的物理地址 @"F:\key\xxxxxx_cert.p12";</param> /// <param name="pwd">证书密码微信一般是商户号</param> /// <returns></returns> public static string SHA256Encrypt( string data2, string pfxFilePath, string pwd) { X509Certificate2 privateCert = new X509Certificate2(pfxFilePath, pwd, X509KeyStorageFlags.Exportable); RSACryptoServiceProvider privateKey = (RSACryptoServiceProvider)privateCert.PrivateKey; // This one can: RSACryptoServiceProvider privateKey1 = new RSACryptoServiceProvider(); privateKey1.ImportParameters(privateKey.ExportParameters( true )); byte [] data = Encoding.UTF8.GetBytes(data2); byte [] signature = privateKey1.SignData(data, "SHA256" ); //密文 string sign = Convert.ToBase64String(signature); return sign; } |
B - 请求方法
//请求 Authorization 信息 var authormessage = "WECHATPAY2-SHA256-RSA2048 mchid=\"\",serial_no=\"\",nonce_str=\"" + nonce_str + "\",timestamp=\"" + timestamp + "\",signature=\"" + signstr + "\"" ; /// <summary> /// Allen - POST V3 微信请求代码上叠加修正 /// </summary> /// <param name="json"></param> /// <param name="url"></param> /// <param name="timeout"></param> /// <param name="encoding"></param> /// <param name="authormessage"></param> /// <param name="method"></param> /// <returns></returns> public static string PostV3( string json, string url, int timeout, Encoding encoding, string authormessage, string method) { System.GC.Collect(); //垃圾回收,回收没有正常关闭的http连接 string result = "" ; //返回结果 HttpWebRequest request = null ; HttpWebResponse response = null ; Stream reqStream = null ; try { //设置最大连接数 ServicePointManager.DefaultConnectionLimit = 200; //设置https验证方式 if (url.StartsWith( "https" , StringComparison.OrdinalIgnoreCase)) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls; ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); } /*************************************************************** * 下面设置HttpWebRequest的相关属性 * ************************************************************/ request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST" ; request.Timeout = timeout * 1000; //设置代理服务器 //WebProxy proxy = new WebProxy(); //定义一个网关对象 //proxy.Address = new Uri(WxPayConfig.PROXY_URL); //网关服务器端口:端口 //request.Proxy = proxy; //设置POST的数据类型和长度 request.ContentType = "application/json" ; request.Accept = "application/json" ; request.UserAgent= "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36" ; request.Headers.Add( "Authorization" , authormessage); //request. byte [] data = System.Text.Encoding.UTF8.GetBytes(json); request.ContentLength = data.Length; //往服务器写入数据 reqStream = request.GetRequestStream(); reqStream.Write(data, 0, data.Length); reqStream.Close(); //获取服务端返回 response = (HttpWebResponse)request.GetResponse(); // WebResponse response2 = request.GetResponseAsync(); //获取服务端返回数据 StreamReader sr = new StreamReader(response.GetResponseStream(), encoding); result = sr.ReadToEnd().Trim(); sr.Close(); } catch (System.Threading.ThreadAbortException e) { System.Threading.Thread.ResetAbort(); } catch (WebException e) { //这里有异常的这里最重要因为非200返回的时候这里可以知道什么原因 response = (HttpWebResponse)e.Response; //获取服务端返回数据 StreamReader sr = new StreamReader(response.GetResponseStream(), encoding); result = sr.ReadToEnd().Trim(); sr.Close(); } catch (Exception e) { throw new Exception(e.ToString()); } finally { //关闭连接和流 if (response != null ) { response.Close(); } if (request != null ) { request.Abort(); } } return result; } |
希望能帮到某些人。
非常感谢。
Node.js 版本可以参考 此篇文章
Java 版本可以参考 此篇文章
文章评论区有源码链接
如果对你有帮助请点击「有用」告知