微信的开发,需要利用公众平台上开发者设置的token, appID, EncodingAESKey,在程序内调用,
现在个人只能以订阅者的身份进行开发和调用,功能较少,以下是一个简单的例子,我建的是
ashx文件,Funtion:
Class:WeChat API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
/// <summary> /// 微信API,用于给用户发送消息 /// </summary> public class WXApi { #region 获取Token /// <summary> /// 获取Token /// </summary> public static string GetToken(string appid, string secret) { string strJson = HttpRequestUtil.RequestUrl(string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appid, secret)); return Tools.GetJsonValue(strJson, "access_token"); } #endregion #region 验证Token是否过期 /// <summary> /// 验证Token是否过期 /// </summary> public static bool TokenExpired(string access_token) { string jsonStr = HttpRequestUtil.RequestUrl(string.Format("https://api.weixin.qq.com/cgi-bin/menu/get?access_token={0}", access_token)); if (Tools.GetJsonValue(jsonStr, "errcode") == "42001") { return true; } return false; } #endregion #region 根据OpenID列表群发 /// <summary> /// 根据OpenID列表群发 /// </summary> public static string Send(string access_token, string postData) { return HttpRequestUtil.PostUrl(string.Format("https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token={0}", access_token), postData); } #endregion #region 上传媒体返回媒体ID /// <summary> /// 上传媒体返回媒体ID /// </summary> public static string UploadMedia(string access_token, string type, string path) { // 设置参数 string url = string.Format("http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token={0}&type={1}", access_token, type); return HttpRequestUtil.HttpUploadFile(url, path); } #endregion #region 获取关注者OpenID集合 /// <summary> /// 获取关注者OpenID集合 /// </summary> public static List<string> GetOpenIDs(string access_token) { List<string> result = new List<string>(); List<string> openidList = GetOpenIDs(access_token, null); result.AddRange(openidList); while (openidList.Count > 0) { openidList = GetOpenIDs(access_token, openidList[openidList.Count - 1]); result.AddRange(openidList); } return result; } /// <summary> /// 获取关注者OpenID集合 /// </summary> public static List<string> GetOpenIDs(string access_token, string next_openid) { // 设置参数 string url = string.Format("https://api.weixin.qq.com/cgi-bin/user/get?access_token={0}&next_openid={1}", access_token, string.IsNullOrEmpty(next_openid) ? "" : next_openid); string returnStr = HttpRequestUtil.RequestUrl(url); int count = int.Parse(Tools.GetJsonValue(returnStr, "count")); if (count > 0) { string startFlg = "\"openid\":["; int start = returnStr.IndexOf(startFlg) + startFlg.Length; int end = returnStr.IndexOf("]", start); string openids = returnStr.Substring(start, end - start).Replace("\"", ""); return openids.Split(',').ToList<string>(); } else { return new List<string>(); } } #endregion } |
Class:WXMsgUtil
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
/// <summary> /// 微信消息封装,用于给用户发送被动响应消息 /// </summary> public class WXMsgUtil { #region 生成文本消息 /// <summary> /// 生成文本消息 /// </summary> public static string CreateTextMsg(XmlDocument xmlDoc, string content) { string strTpl = string.Format(@"<xml> <ToUserName><![CDATA[{0}]]></ToUserName> <FromUserName><![CDATA[{1}]]></FromUserName> <CreateTime>{2}</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[{3}]]></Content> </xml>", GetFromXML(xmlDoc, "FromUserName"), GetFromXML(xmlDoc, "ToUserName"), DateTime2Int(DateTime.Now), content); return strTpl; } #endregion #region 生成图文消息 /// <summary> /// 生成图文消息 /// </summary> public static string CreateNewsMsg(XmlDocument xmlDoc, List<Dictionary<string, string>> dictList) { StringBuilder sbItems = new StringBuilder(); foreach (Dictionary<string, string> dict in dictList) { sbItems.Append(string.Format(@" <item> <Title><![CDATA[{0}]]></Title> <Description><![CDATA[{1}]]></Description> <PicUrl><![CDATA[{2}]]></PicUrl> <Url><![CDATA[{3}]]></Url> </item>", dict["Title"], dict["Description"], dict["PicUrl"], dict["Url"])); } string strTpl = string.Format(@" <xml> <ToUserName><![CDATA[{0}]]></ToUserName> <FromUserName><![CDATA[{1}]]></FromUserName> <CreateTime>{2}</CreateTime> <MsgType><![CDATA[news]]></MsgType> <ArticleCount>{3}</ArticleCount> <Articles> {4} </Articles> </xml> ", GetFromXML(xmlDoc, "FromUserName"), GetFromXML(xmlDoc, "ToUserName"), DateTime2Int(DateTime.Now), dictList.Count, sbItems.ToString()); return strTpl; } #endregion #region 时间转换成int /// <summary> /// 时间转换成int /// </summary> public static int DateTime2Int(DateTime dt) { DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); return (int)(dt - startTime).TotalSeconds; } #endregion #region 解析消息XML /// <summary> /// 解析消息XML /// </summary> public static string GetFromXML(XmlDocument xmlDoc, string name) { XmlNode node = xmlDoc.SelectSingleNode("xml/" + name); if (node != null && node.ChildNodes.Count > 0) { return node.ChildNodes[0].Value; } return ""; } #endregion #region 解析图灵消息 /// <summary> /// 解析图灵消息 /// </summary> public static string GetTulingMsg(string info) { string jsonStr = HttpRequestUtil.RequestTuling(info); if (Tools.GetJsonValue(jsonStr, "code") == "100000") { return Tools.GetJsonValue(jsonStr, "text"); } if (Tools.GetJsonValue(jsonStr, "code") == "200000") { return Tools.GetJsonValue(jsonStr, "text") + Tools.GetJsonValue(jsonStr, "url"); } return "不知道怎么回复你哎"; } #endregion #region 高级群发消息 #region 文本json /// <summary> /// 文本json /// </summary> public static string CreateTextJson(string text, List<string> openidList) { StringBuilder sb = new StringBuilder(); sb.Append("{\"touser\":["); sb.Append(string.Join(",", openidList.ConvertAll<string>(a => "\"" + a + "\"").ToArray())); sb.Append("],"); sb.Append("\"msgtype\":\"text\","); sb.Append("\"text\":{\"content\":\"" + text.Trim() + "\"}"); sb.Append("}"); return sb.ToString(); } #endregion #region 图片json /// <summary> /// 图片json /// </summary> public static string CreateImageJson(string media_id, List<string> openidList) { StringBuilder sb = new StringBuilder(); sb.Append("{\"touser\":["); sb.Append(string.Join(",", openidList.ConvertAll<string>(a => "\"" + a + "\"").ToArray())); sb.Append("],"); sb.Append("\"msgtype\":\"image\","); sb.Append("\"image\":{\"media_id\":\"" + media_id + "\"}"); sb.Append("}"); return sb.ToString(); } #endregion #region 图文消息json /// <summary> /// 图文消息json /// </summary> public static string CreateNewsJson(string media_id, List<string> openidList) { StringBuilder sb = new StringBuilder(); sb.Append("{\"touser\":["); sb.Append(string.Join(",", openidList.ConvertAll<string>(a => "\"" + a + "\"").ToArray())); sb.Append("],"); sb.Append("\"msgtype\":\"mpnews\","); sb.Append("\"mpnews\":{\"media_id\":\"" + media_id + "\"}"); sb.Append("}"); return sb.ToString(); } #endregion #endregion } |
Ashx:WechatIfe
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
public class WechatIfe : IHttpHandler { #region 变量 //公众平台上开发者设置的token, appID, EncodingAESKey string sToken = "CPP"; string sAppID = "XXXXXXXXXX"; string sEncodingAESKey = "abcdefghijklmnopqrstuvwxyz123456789"; #endregion #region ProcessRequest public void ProcessRequest(HttpContext context) { try { Stream stream = context.Request.InputStream; byte[] byteArray = new byte[stream.Length]; stream.Read(byteArray, 0, (int)stream.Length); string postXmlStr = System.Text.Encoding.UTF8.GetString(byteArray); if (!string.IsNullOrEmpty(postXmlStr)) { XmlDocument doc = new XmlDocument(); doc.LoadXml(postXmlStr); //没有AppID则不解密(订阅号没有AppID) if (!string.IsNullOrEmpty(sAppID)) { //解密 WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, sAppID); string signature = context.Request["msg_signature"]; string timestamp = context.Request["timestamp"]; string nonce = context.Request["nonce"]; string stmp = ""; int ret = wxcpt.DecryptMsg(signature, timestamp, nonce, postXmlStr, ref stmp); if (ret == 0) { doc = new XmlDocument(); doc.LoadXml(stmp); try { responseMsg(context, doc); } catch (Exception ex) { FileLogger.WriteErrorLog(context, ex.Message); } } else { FileLogger.WriteErrorLog(context, "解密失败,错误码:" + ret); } } else { responseMsg(context, doc); } } else { valid(context); } } catch (Exception ex) { FileLogger.WriteErrorLog(context, ex.Message); } } #endregion #region IsReusable public bool IsReusable { get { return false; } } #endregion #region valid public void valid(HttpContext context) { var echostr = context.Request["echoStr"].ToString(); if (checkSignature(context) && !string.IsNullOrEmpty(echostr)) { context.Response.Write(echostr); context.Response.Flush();//推送...不然微信平台无法验证token } } #endregion #region checkSignature public bool checkSignature(HttpContext context) { var signature = context.Request["signature"].ToString(); var timestamp = context.Request["timestamp"].ToString(); var nonce = context.Request["nonce"].ToString(); var token = "weixin"; string[] ArrTmp = { token, timestamp, nonce }; Array.Sort(ArrTmp); //字典排序 string tmpStr = string.Join("", ArrTmp); tmpStr = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1"); tmpStr = tmpStr.ToLower(); if (tmpStr == signature) { return true; } else { return false; } } #endregion #region responseMsg public void responseMsg(HttpContext context, XmlDocument xmlDoc) { XmlDocument xml = new XmlDocument(); string filepath = HttpContext.Current.Server.MapPath("~/data/phone.xml"); xml.Load(filepath); string result = ""; string msgType = WXMsgUtil.GetFromXML(xmlDoc, "MsgType"); switch (msgType) { case "event": switch (WXMsgUtil.GetFromXML(xmlDoc, "Event")) { case "subscribe": //订阅 result = WXMsgUtil.CreateNewsMsg(xmlDoc, WeatherUtil.GetWelcome()); break; case "unsubscribe": //取消订阅 break; case "CLICK": result = WXMsgUtil.CreateTextMsg(xmlDoc, "无此消息哦"); break; default: break; } break; case "text": string text = WXMsgUtil.GetFromXML(xmlDoc, "Content"); XmlNodeList xList = xml.SelectNodes(string.Format("/items/tel[contains(text,'{0}')]", text)); ; string xmlmsg = ""; if (xList.Count>0) { foreach (XmlNode i in xList) { xmlmsg += string.Format(@"[{0}:{1}]", i.ChildNodes[0].InnerText, i.ChildNodes[1].InnerText) + ","; } xmlmsg = xmlmsg.Substring(0, xmlmsg.Length - 1); result = WXMsgUtil.CreateTextMsg(xmlDoc, xmlmsg); } else if (text == "Hello") { result = WXMsgUtil.CreateNewsMsg(xmlDoc, WeatherUtil.GetSpecialMsg("你也Hello呀,HAHA!")); } else if (text == "Where") { result = WXMsgUtil.CreateNewsMsg(xmlDoc, WeatherUtil.GetSpecialMsg("I'm come from China!!")); } else { result = WXMsgUtil.CreateTextMsg(xmlDoc, WXMsgUtil.GetTulingMsg(text)); } break; default: break; } if (!string.IsNullOrEmpty(sAppID)) //没有AppID则不加密(订阅号没有AppID) { //加密 WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, sAppID); string sEncryptMsg = ""; //xml格式的密文 string timestamp = context.Request["timestamp"]; string nonce = context.Request["nonce"]; int ret = wxcpt.EncryptMsg(result, timestamp, nonce, ref sEncryptMsg); if (ret != 0) { FileLogger.WriteErrorLog(context, "加密失败,错误码:" + ret); return; } context.Response.Write(sEncryptMsg); context.Response.Flush(); } else { context.Response.Write(result); context.Response.Flush(); } } #endregion #region InterfaceTest public void InterfaceTest() { string token = "CPP"; if (string.IsNullOrEmpty(token)) { return; } string echoString = HttpContext.Current.Request.QueryString["echoStr"]; string signature = HttpContext.Current.Request.QueryString["signature"]; string timestamp = HttpContext.Current.Request.QueryString["timestamp"]; string nonce = HttpContext.Current.Request.QueryString["nonce"]; if (!string.IsNullOrEmpty(echoString)) { HttpContext.Current.Response.Write(echoString); HttpContext.Current.Response.End(); } } #endregion } |