1 using System; 2 using System.Collections; 3 using System.Configuration; 4 using System.Data; 5 using System.Linq; 6 using System.Web; 7 using System.Web.Security; 8 using System.Web.UI; 9 using System.Web.UI.HtmlControls; 10 using System.Web.UI.WebControls; 11 using System.Web.UI.WebControls.WebParts; 12 using System.Xml.Linq; 13 using System.Xml; 14 using System.IO; 15 using System.Text; 16 using System.Collections.Generic; 17 using System.Net; 18 19 20 namespace weixin 21 { 22 public partial class index : System.Web.UI.Page 23 { 24 const string Token = "token"; //与那边填写的token一致 25 protected void Page_Load(object sender, EventArgs e) 26 { 27 string postStr = ""; 28 if (Request.HttpMethod.ToLower() == "post") 29 { 30 Stream s = System.Web.HttpContext.Current.Request.InputStream; 31 byte[] b = new byte[s.Length]; 32 s.Read(b, 0, (int)s.Length); 33 postStr = Encoding.UTF8.GetString(b); 34 35 36 if (!string.IsNullOrEmpty(postStr)) 37 { 38 //封装请求类 39 XmlDocument doc = new XmlDocument(); 40 doc.LoadXml(postStr); 41 XmlElement rootElement = doc.DocumentElement; 42 43 44 XmlNode MsgType = rootElement.SelectSingleNode("MsgType"); 45 46 47 RequestXML requestXML = new RequestXML(); 48 requestXML.ToUserName = rootElement.SelectSingleNode("ToUserName").InnerText; 49 requestXML.FromUserName = rootElement.SelectSingleNode("FromUserName").InnerText; 50 requestXML.CreateTime = rootElement.SelectSingleNode("CreateTime").InnerText; 51 requestXML.MsgType = MsgType.InnerText; 52 53 54 if (requestXML.MsgType == "text") 55 { 56 requestXML.Content = rootElement.SelectSingleNode("Content").InnerText; 57 } 58 else if (requestXML.MsgType == "location") 59 { 60 requestXML.Location_X = rootElement.SelectSingleNode("Location_X").InnerText; 61 requestXML.Location_Y = rootElement.SelectSingleNode("Location_Y").InnerText; 62 requestXML.Scale = rootElement.SelectSingleNode("Scale").InnerText; 63 requestXML.Label = rootElement.SelectSingleNode("Label").InnerText; 64 } 65 else if (requestXML.MsgType == "image") 66 { 67 requestXML.PicUrl = rootElement.SelectSingleNode("PicUrl").InnerText; 68 } 69 70 71 //回复消息 72 ResponseMsg(requestXML); 73 } 74 } 75 else 76 { 77 Valid(); 78 } 79 } 80 81 82 /// <summary> 83 /// 验证微信签名 84 /// </summary> 85 /// * 将token、timestamp、nonce三个参数进行字典序排序 86 /// * 将三个参数字符串拼接成一个字符串进行sha1加密 87 /// * 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信。 88 /// <returns></returns> 89 private bool CheckSignature() 90 { 91 string signature = Request.QueryString["signature"]; 92 string timestamp = Request.QueryString["timestamp"]; 93 string nonce = Request.QueryString["nonce"]; 94 string[] ArrTmp = { Token, timestamp, nonce }; 95 Array.Sort(ArrTmp); //字典排序 96 string tmpStr = string.Join("", ArrTmp); 97 tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1"); 98 tmpStr = tmpStr.ToLower(); 99 if (tmpStr == signature) 100 { 101 return true; 102 } 103 else 104 { 105 return false; 106 } 107 } 108 109 110 private void Valid() 111 { 112 string echoStr = Request.QueryString["echoStr"]; 113 if (CheckSignature()) 114 { 115 if (!string.IsNullOrEmpty(echoStr)) 116 { 117 Response.Write(echoStr); 118 Response.End(); 119 } 120 } 121 } 122 123 124 /// <summary> 125 /// 回复消息(微信信息返回) 126 /// </summary> 127 /// <param name="weixinXML"></param> 128 private void ResponseMsg(RequestXML requestXML) 129 { 130 try 131 { 132 string resxml = ""; 133 if (requestXML.MsgType == "text") 134 { 135 resxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[正在建设中,稍等时日,更多精彩……]]></Content><FuncFlag>0</FuncFlag></xml>"; 136 } 137 else if (requestXML.MsgType == "location") 138 { 139 string city = GetMapInfo(requestXML.Location_X, requestXML.Location_Y); 140 if (city == "0") 141 { 142 resxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[Sorry,没有找到" + city + " 的相关产品信息]]></Content><FuncFlag>0</FuncFlag></xml>"; 143 } 144 else 145 { 146 resxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[Sorry,这是 " + city + " 的产品信息:圈圈叉叉]]></Content><FuncFlag>0</FuncFlag></xml>"; 147 } 148 } 149 else if (requestXML.MsgType == "image") 150 { 151 //返回10以内条 152 int size = 10; 153 resxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDateTimeInt(DateTime.Now) + "</CreateTime><MsgType><![CDATA[news]]></MsgType><Content><![CDATA[]]></Content><ArticleCount>" + size + "</ArticleCount><Articles>"; 154 List<string> list = new List<string>(); 155 //假如有20条查询的返回结果 156 for (int i = 0; i < 20; i++) 157 { 158 list.Add("1"); 159 } 160 string[] piclist = new string[] { "/Abstract_Pencil_Scribble_Background_Vector_main.jpg", "/balloon_tree.jpg", "/bloom.jpg", "/colorful_flowers.jpg", "/colorful_summer_flower.jpg", "/fall.jpg", "/fall_tree.jpg", "/growing_flowers.jpg", "/shoes_illustration.jpg", "/splashed_tree.jpg" }; 161 162 163 for (int i = 0; i < size && i < list.Count; i++) 164 { 165 resxml += "<item><Title><![CDATA[沈阳-黑龙江]]></Title><Description><![CDATA[元旦特价:¥300 市场价:¥400]]></Description><PicUrl><![CDATA[" + "http://www.hougelou.com" + piclist[i] + "]]></PicUrl><Url><![CDATA[http://www.hougelou.com]]></Url></item>"; 166 } 167 resxml += "</Articles><FuncFlag>1</FuncFlag></xml>"; 168 } 169 WriteTxt(resxml); 170 Response.Write(resxml); 171 } 172 catch (Exception ex) 173 { 174 WriteTxt("异常:" + ex.Message + "Struck:" + ex.StackTrace.ToString()); 175 } 176 } 177 178 179 180 181 182 183 /// <summary> 184 /// unix时间转换为datetime 185 /// </summary> 186 /// <param name="timeStamp"></param> 187 /// <returns></returns> 188 private DateTime UnixTimeToTime(string timeStamp) 189 { 190 DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); 191 long lTime = long.Parse(timeStamp + "0000000"); 192 TimeSpan toNow = new TimeSpan(lTime); 193 return dtStart.Add(toNow); 194 } 195 196 197 /// <summary> 198 /// datetime转换为unixtime 199 /// </summary> 200 /// <param name="time"></param> 201 /// <returns></returns> 202 private int ConvertDateTimeInt(System.DateTime time) 203 { 204 System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); 205 return (int)(time - startTime).TotalSeconds; 206 } 207 208 209 /// <summary> 210 /// 记录bug,以便调试 211 /// </summary> 212 /// <returns></returns> 213 public bool WriteTxt(string str) 214 { 215 try 216 { 217 FileStream fs = new FileStream(Server.MapPath("/bugLog.txt"), FileMode.Append); 218 StreamWriter sw = new StreamWriter(fs); 219 //开始写入 220 sw.WriteLine(str); 221 //清空缓冲区 222 sw.Flush(); 223 //关闭流 224 sw.Close(); 225 fs.Close(); 226 } 227 catch (Exception) 228 { 229 return false; 230 } 231 return true; 232 } 233 234 235 /// <summary> 236 /// 调用百度地图,返回坐标信息 237 /// </summary> 238 /// <param name="y">经度</param> 239 /// <param name="x">纬度</param> 240 /// <returns></returns> 241 public string GetMapInfo(string x, string y) 242 { 243 try 244 { 245 string res = string.Empty; 246 string parame = string.Empty; 247 string url = "http://maps.googleapis.com/maps/api/geocode/xml"; 248 parame = "latlng=" + x + "," + y + "&language=zh-CN&sensor=false";//此key为个人申请 249 res = webRequestPost(url, parame); 250 251 252 XmlDocument doc = new XmlDocument(); 253 254 255 doc.LoadXml(res); 256 XmlElement rootElement = doc.DocumentElement; 257 string Status = rootElement.SelectSingleNode("status").InnerText; 258 if (Status == "OK") 259 { 260 //仅获取城市 261 XmlNodeList xmlResults = rootElement.SelectSingleNode("/GeocodeResponse").ChildNodes; 262 for (int i = 0; i < xmlResults.Count; i++) 263 { 264 XmlNode childNode = xmlResults[i]; 265 if (childNode.Name == "status") 266 { 267 continue; 268 } 269 270 271 string city = "0"; 272 for (int w = 0; w < childNode.ChildNodes.Count; w++) 273 { 274 for (int q = 0; q < childNode.ChildNodes[w].ChildNodes.Count; q++) 275 { 276 XmlNode childeTwo = childNode.ChildNodes[w].ChildNodes[q]; 277 278 279 if (childeTwo.Name == "long_name") 280 { 281 city = childeTwo.InnerText; 282 } 283 else if (childeTwo.InnerText == "locality") 284 { 285 return city; 286 } 287 } 288 } 289 return city; 290 } 291 } 292 } 293 catch (Exception ex) 294 { 295 WriteTxt("map异常:" + ex.Message.ToString() + "Struck:" + ex.StackTrace.ToString()); 296 return "0"; 297 } 298 299 300 return "0"; 301 } 302 303 304 /// <summary> 305 /// Post 提交调用抓取 306 /// </summary> 307 /// <param name="url">提交地址</param> 308 /// <param name="param">参数</param> 309 /// <returns>string</returns> 310 public string webRequestPost(string url, string param) 311 { 312 byte[] bs = System.Text.Encoding.UTF8.GetBytes(param); 313 314 315 HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url + "?" + param); 316 req.Method = "Post"; 317 req.Timeout = 120 * 1000; 318 req.ContentType = "application/x-www-form-urlencoded;"; 319 req.ContentLength = bs.Length; 320 321 322 using (Stream reqStream = req.GetRequestStream()) 323 { 324 reqStream.Write(bs, 0, bs.Length); 325 reqStream.Flush(); 326 } 327 using (WebResponse wr = req.GetResponse()) 328 { 329 //在这里对接收到的页面内容进行处理 330 331 332 Stream strm = wr.GetResponseStream(); 333 334 335 StreamReader sr = new StreamReader(strm, System.Text.Encoding.UTF8); 336 337 338 string line; 339 340 341 System.Text.StringBuilder sb = new System.Text.StringBuilder(); 342 343 344 while ((line = sr.ReadLine()) != null) 345 { 346 sb.Append(line + System.Environment.NewLine); 347 } 348 sr.Close(); 349 strm.Close(); 350 return sb.ToString(); 351 } 352 } 353 354 355 356 357 } 358 359 360 //微信请求类 361 public class RequestXML 362 { 363 private string toUserName; 364 /// <summary> 365 /// 消息接收方微信号,一般为公众平台账号微信号 366 /// </summary> 367 public string ToUserName 368 { 369 get { return toUserName; } 370 set { toUserName = value; } 371 } 372 373 374 private string fromUserName; 375 /// <summary> 376 /// 消息发送方微信号 377 /// </summary> 378 public string FromUserName 379 { 380 get { return fromUserName; } 381 set { fromUserName = value; } 382 } 383 384 385 private string createTime; 386 /// <summary> 387 /// 创建时间 388 /// </summary> 389 public string CreateTime 390 { 391 get { return createTime; } 392 set { createTime = value; } 393 } 394 395 396 private string msgType; 397 /// <summary> 398 /// 信息类型 地理位置:location,文本消息:text,消息类型:image 399 /// </summary> 400 public string MsgType 401 { 402 get { return msgType; } 403 set { msgType = value; } 404 } 405 406 407 private string content; 408 /// <summary> 409 /// 信息内容 410 /// </summary> 411 public string Content 412 { 413 get { return content; } 414 set { content = value; } 415 } 416 417 418 private string location_X; 419 /// <summary> 420 /// 地理位置纬度 421 /// </summary> 422 public string Location_X 423 { 424 get { return location_X; } 425 set { location_X = value; } 426 } 427 428 429 private string location_Y; 430 /// <summary> 431 /// 地理位置经度 432 /// </summary> 433 public string Location_Y 434 { 435 get { return location_Y; } 436 set { location_Y = value; } 437 } 438 439 440 private string scale; 441 /// <summary> 442 /// 地图缩放大小 443 /// </summary> 444 public string Scale 445 { 446 get { return scale; } 447 set { scale = value; } 448 } 449 450 451 private string label; 452 /// <summary> 453 /// 地理位置信息 454 /// </summary> 455 public string Label 456 { 457 get { return label; } 458 set { label = value; } 459 } 460 461 462 private string picUrl; 463 /// <summary> 464 /// 图片链接,开发者可以用HTTP GET获取 465 /// </summary> 466 public string PicUrl 467 { 468 get { return picUrl; } 469 set { picUrl = value; } 470 } 471 } 472 }