1、控制器方法:
private string SendRedPackge(string OpenId, int Amount, string LuckyCode) { Models.PayWeiXinModel pModel = new Models.PayWeiXinModel(); Html_Tools.Common.PayForWeiXinHelp PayHelp = new Html_Tools.Common.PayForWeiXinHelp(); string result = string.Empty; //接叐收紅包的用戶 用戶在wxappid下的openid pModel.re_openid = OpenId;//"oFIYdszuDXVqVCtwZ-yIcbIS262k"; //付款金額,單位分 pModel.total_amount = Amount; //最小紅包金額,單位分 pModel.min_value = Amount; //最大紅包金額,單位分 pModel.max_value = Amount; //商戶訂單號 pModel.mch_billno = LuckyCode; //調用方法 string postData = PayHelp.DoDataForPayWeiXin(pModel); //發送 result = PayHelp.PayForWeiXin(postData); XmlDocument doc = new XmlDocument(); doc.LoadXml(result); var rmodel=new Models.WeiXinRedPackgeResultModel(); Html_Tools.Common.WeiXinMPHelper.FillEntityFromXml(rmodel, doc); if (rmodel.result_code.Equals("SUCCESS")) { return "紅包已成功發放,請及時領取"; } else { Html_Tools.Common.ToolsHelper.WriteLog(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " 發送紅包異常信息:" + result + "\r\n");
pBll.DrawPrize(OpenId, LuckyCode, false); return "不好意思,紅包發送出錯啦。"; } }
2、工具類PayForWeiXinHelp方法:
public class PayForWeiXinHelp { /// <summary> /// 調用微信支付接口前處理數據,包括sign驗證等 /// </summary> /// <param name="payForWeiXin"></param> /// <returns></returns> public string DoDataForPayWeiXin(Models.PayWeiXinModel payForWeiXin) { #region 處理nonce_str隨機字符串,不長於 32 位(本程序生成長度為16位的) string str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; payForWeiXin.nonce_str = RandomStr(str, 16); #endregion #region 商戶信息從config文件中讀取 //商戶支付密鑰key string key = WeiXinConfig.key; //商戶號 payForWeiXin.mch_id = WeiXinConfig.mch_id; //商戶 appid payForWeiXin.wxappid = WeiXinConfig.wxappid; //提供方名稱 payForWeiXin.nick_name = WeiXinConfig.nick_name; //紅包収送者名稱 payForWeiXin.send_name = WeiXinConfig.send_name; //紅包収放總人數 payForWeiXin.total_num = int.Parse(WeiXinConfig.total_num); //紅包祝福詫 payForWeiXin.wishing = WeiXinConfig.wishing; //活勱名稱 payForWeiXin.act_name = WeiXinConfig.act_name; payForWeiXin.act_id = "act_id"; //備注信息 payForWeiXin.remark = WeiXinConfig.remark; //商戶logo的url payForWeiXin.logo_imgurl = WeiXinConfig.logo_imgurl; //分享文案 payForWeiXin.share_content = WeiXinConfig.share_content; //分享鏈接 payForWeiXin.share_url = WeiXinConfig.share_url; //分享的圖片url payForWeiXin.share_imgurl = WeiXinConfig.share_imgurl; //調用接口的機器 Ip 地址 payForWeiXin.client_ip = WeiXinConfig.client_ip; #endregion #region 訂單信息 //生成訂單號組成: mch_id+yyyymmdd+10 位一天內不能重復的數字 //生成10位不重復的數字 payForWeiXin.mch_billno = payForWeiXin.mch_billno+System.DateTime.Now.ToString("yyyyMMddHHmmss"); #endregion string postData = @"<xml> <mch_billno><![CDATA[{0}]]></mch_billno> <mch_id><![CDATA[{1}]]></mch_id> <wxappid><![CDATA[{2}]]></wxappid> <send_name><![CDATA[{3}]]></send_name> <re_openid><![CDATA[{4}]]></re_openid> <total_amount><![CDATA[{5}]]></total_amount> <total_num><![CDATA[{6}]]></total_num> <wishing><![CDATA[{7}]]></wishing> <client_ip><![CDATA[{8}]]></client_ip> <act_name><![CDATA[{9}]]></act_name> <remark><![CDATA[{10}]]></remark> <nonce_str><![CDATA[{11}]]></nonce_str>"; postData = string.Format(postData, payForWeiXin.mch_billno, payForWeiXin.mch_id, payForWeiXin.wxappid, payForWeiXin.send_name, payForWeiXin.re_openid, payForWeiXin.total_amount, payForWeiXin.total_num, payForWeiXin.wishing, payForWeiXin.client_ip, payForWeiXin.act_name, payForWeiXin.remark, payForWeiXin.nonce_str ); //原始傳入參數 string[] signTemp = { "mch_billno=" + payForWeiXin.mch_billno, "mch_id=" + payForWeiXin.mch_id, "wxappid=" + payForWeiXin.wxappid, "send_name=" + payForWeiXin.send_name, "re_openid=" + payForWeiXin.re_openid, "total_amount=" + payForWeiXin.total_amount, "total_num=" + payForWeiXin.total_num, "wishing=" + payForWeiXin.wishing, "client_ip=" + payForWeiXin.client_ip, "act_name=" + payForWeiXin.act_name, "remark=" + payForWeiXin.remark, "nonce_str=" + payForWeiXin.nonce_str }; List<string> signList = signTemp.ToList(); #region 處理支付簽名 //對signList按照ASCII碼從小到大的順序排序 signList.Sort(); string signOld = string.Empty; //string payForWeiXinOld = string.Empty; int i = 0; foreach (string temp in signList) { signOld += temp + "&"; i++; } //signOld = signOld.Substring(0, signOld.Length - 1); //拼接Key signOld += "key=" + key; //處理支付簽名 payForWeiXin.sign = GetMD5Hash(signOld).ToUpper(); #endregion postData += "<sign><![CDATA[{0}]]></sign></xml>"; postData = string.Format(postData, payForWeiXin.sign); return postData; } /// <summary> /// 調用微信支付接口 /// </summary> /// <param name="payForWeiXin"></param> /// <returns></returns> public string PayForWeiXin(string postData) { string result = string.Empty; try { result = PostPage("https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack", postData); } catch (Exception ex) { } return result; } /// <summary> /// post微信請求 /// </summary> /// <param name="posturl"></param> /// <param name="postData"></param> /// <returns></returns> public string PostPage(string posturl, string postData) { Stream outstream = null; Stream instream = null; StreamReader sr = null; HttpWebResponse response = null; HttpWebRequest request = null; Encoding encoding = Encoding.UTF8; byte[] data = encoding.GetBytes(postData); // 准備請求... try { //CerPath證書路徑 string certPath = WeiXinConfig.certPath; //證書密碼 string password = WeiXinConfig.password; X509Certificate2 cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(certPath, password, X509KeyStorageFlags.MachineKeySet); // 設置參數 request = WebRequest.Create(posturl) as HttpWebRequest; CookieContainer cookieContainer = new CookieContainer(); request.CookieContainer = cookieContainer; request.AllowAutoRedirect = true; request.Method = "POST"; request.ContentType = "text/xml"; request.ContentLength = data.Length; request.ClientCertificates.Add(cert); outstream = request.GetRequestStream(); outstream.Write(data, 0, data.Length); outstream.Close(); //發送請求並獲取相應回應數據 response = request.GetResponse() as HttpWebResponse; //直到request.GetResponse()程序才開始向目標網頁發送Post請求 instream = response.GetResponseStream(); sr = new StreamReader(instream, encoding); //返回結果網頁(html)代碼 string content = sr.ReadToEnd(); string err = string.Empty; return content; } catch (Exception ex) { string err = ex.Message; return string.Empty; } } public string RandomStr(string str, int Length) { string result = string.Empty; Random rd = new Random(); for (int i = 0; i < Length; i++) { result += str[rd.Next(str.Length)]; } return result; } /// <summary> /// Md5加密 /// </summary> /// <param name="s"></param> /// <returns></returns> public static String Encrypt(String s) { MD5 md5 = new MD5CryptoServiceProvider(); byte[] bytes = System.Text.Encoding.UTF8.GetBytes(s); bytes = md5.ComputeHash(bytes); md5.Clear(); string ret = ""; for (int i = 0; i < bytes.Length; i++) { ret += Convert.ToString(bytes[i], 16).PadLeft(2, '0'); } return ret.PadLeft(32, '0'); } public static string GetMD5Hash(string value) { var md5 = MD5.Create(); var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(value)); var sb = new StringBuilder(); foreach (byte b in bs) { sb.Append(b.ToString("x2")); } //所有字符轉為大寫 return sb.ToString(); } public static void FillEntityFromXml<T>(this T entity, System.Xml.XmlDocument doc) { Dictionary<string, string> Dic = new Dictionary<string, string>(); System.Xml.XmlNodeList nodelist = doc.DocumentElement.ChildNodes; if (nodelist.Count > 0) { Type t = entity.GetType(); foreach (System.Xml.XmlElement el in nodelist)//讀元素值 { System.Reflection.PropertyInfo proInfo = t.GetProperty(el.Name);//訪問Obj的類型的屬性Value的屬性信息(propertyInfo) if (proInfo != null) { string str2 = proInfo.PropertyType.Name; if (str2 == null) { goto Label_018A; } if (!(str2 == "DateTime")) { if (str2 == "Boolean") { goto Label_00E9; } if (str2 == "Int64") { goto Label_0134; } goto Label_018A; } proInfo.SetValue(entity, new DateTime(long.Parse(el.InnerText)), null); } continue; Label_00E9: proInfo.SetValue(entity, el.InnerText == "1", null); continue; Label_0134: proInfo.SetValue(entity, long.Parse(el.InnerText), null); continue; Label_018A: proInfo.SetValue(entity, el.InnerText, null); } } } }