调用微信支付接口其实主要需要两个部分,一个是需要证书,二是组织参数
1.证书,在微信商户中将证书下载到测试机,注意的是,如果用.NET的话,一定要双击下载的证书并安装,否则后期调试接口的时候会报错,错误为:CA证书出错,请登录微信支付商户平台下载证书;
2.组织参数的时候主要的就是签名的生成,其实只要按照接口文档的步骤,一个个写下来,是没有任何问题的,容易出错的是当参数有中文的时候,容易出现错误,错误为:签名错误
下面是我写的主要的代码,以一段段的函数呈现:
1.组织参数,以字典的结构存储参数:
public string Create() { Dictionary<string, string> nativeObj = new Dictionary<string, string>(); nativeObj.Add("nonce_str", "3857F5B380EA425B91D4DD3D5F5A6594"); nativeObj.Add("mch_id", "商户号"); nativeObj.Add("mch_billno",“自己按照接口文档写的”); nativeObj.Add("wxappid", "微信公众平台id"); nativeObj.Add("nick_name", "自定义"); nativeObj.Add("send_name", "自定义"); nativeObj.Add("re_openid", "用户的openid"); nativeObj.Add("total_amount", "100"); nativeObj.Add("min_value", "100"); nativeObj.Add("max_value", "100"); nativeObj.Add("total_num", "1"); nativeObj.Add("wishing", "感谢您参加猜灯谜活动,祝您元宵节快乐!"); nativeObj.Add("client_ip", "本机的ip地址"); nativeObj.Add("act_name", "猜灯谜抢红包活动 "); nativeObj.Add("remark", "猜越多得越多,快来抢!"); //用来生成签名的方法,具体见下面 string sign = GetSign(nativeObj); nativeObj.Add("sign", sign); //将参数组织成xml形式的字符串 return ToXml(nativeObj); } |
2.生成签名:
public string GetSign(Dictionary<string, string> nativeObj) { string sign = ""; Dictionary<string, string> newobj = new Dictionary<string, string>(); string temp = ""; //参数的排序及去空 var dicSort = from objDic in nativeObj where objDic.Value != "" orderby objDic.Key select objDic; foreach (var item in dicSort) { if (temp != "") temp += "&"; temp += item.Key + "=" + item.Value; } temp += "&key=api密钥"; //MD5加密 sign = StringToMD5(temp,32).ToUpper(); return sign; } public string StringToMD5(string str, int i) { //获取要加密的字段,并转化为Byte[]数组 byte[] data = System.Text.Encoding.Unicode.GetBytes(str.ToCharArray()); //建立加密服务 System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); //加密Byte[]数组 byte[] result = md5.ComputeHash(data); //将加密后的数组转化为字段 if (i == 16 && str != string.Empty) { return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "MD5").ToLower().Substring(8, 16); } else if (i == 32 && str != string.Empty) { return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "MD5").ToLower(); } else { switch (i) { case 16: return "000000000000000"; case 32: return "000000000000000000000000000000"; default: return "请确保调用函数时第二个参数为16或32"; } } } |
3. 将参数组织成要提交的数据
public string ToXml(Dictionary<string, string> arr) { String xml = "<xml>"; foreach (KeyValuePair<string, string> pair in arr) { String key = pair.Key; String val = pair.Value; if (IsNumeric(val)) { xml += "<" + key + ">" + val + "</" + key + ">"; } else xml += "<" + key + "><![CDATA[" + val + "]]></" + key + ">"; } xml += "</xml>"; return xml; } public bool IsNumeric(String str) { try { int.Parse(str); return true; } catch { return false; } } |
4.模拟post请求提交
public string Pay() { int dt = DateTime.Now.Millisecond; string url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack"; string cert = @"D:\cert\apiclient_cert.p12";//这里是你存储证书的位置 string password = "**********";//证书密码 //这一段借鉴的是微信官方提供的DEMO ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); X509Certificate cer = new X509Certificate(cert, password); HttpWebRequest webrequest = (HttpWebRequest)HttpWebRequest.Create(url); webrequest.ClientCertificates.Add(cer); webrequest.Method = "post"; webrequest.ContentType = "text/xml"; //这一段是自己写的添加post数据的方法 string postData = CreateNativePackage(); StreamWriter myWriter = null; //// 要注意的这是这个编码方式,还有内容的Xml内容的编码方式 //Encoding encoding = Encoding.GetEncoding("UTF-8"); try { myWriter = new StreamWriter(webrequest.GetRequestStream()); myWriter.Write(postData); } catch (Exception e) { } finally { myWriter.Close(); } HttpWebResponse webreponse = (HttpWebResponse)webrequest.GetResponse(); Stream stream = webreponse.GetResponseStream(); string resp = string.Empty; using (StreamReader reader = new StreamReader(stream)) { resp = reader.ReadToEnd(); } string msg = resp; return msg; } private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { if (errors == SslPolicyErrors.None) return true; return false; } |