第三方app抽奖发送微信红包实现
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); } } } }