通過幾天的開發、測試微信點餐demo終於完成了,特在此分享下,很差的地方請你們多指正下哈!一開始,就想這東西出來這麼久了,網上應該有不少現成的東西,因而,baidu、google了半天,基本沒發現現成的東西,也許是我搜索不得其道,也有可能你們都不肯意分享吧...因而,還得本身動手,豐衣足食!html
仍是先交代下背景:所謂「微信點餐」,其實就是用戶經過微信app,關注公衆號,發送指定類型的信息,如地理位置信息,網站返回相關連接到微信上,經過這些連接進入wap或者html5網站,而後開始選擇商家、點餐、提交訂單等。關於微信app,與訂餐網站的關係,我簡單的畫了一個圖,比較潦草,請別噴得太厲害了!如圖1,說簡單點:微信app經過微信服務器,傳給訂餐網站(申請公衆號時,會輸入一個地址,微信服務器就是經過此地址post,get消息的),網站根據收到的消息,返回具體信息,再經過某些信息的連接進入wap或者html5站點。微信公衆平臺地址:https://mp.weixin.qq.com/ ,這幾天好像升級了,不叫公衆號了,叫訂閱號。html5
(圖1)服務器
至於,如何申請、如何關注,這裏就不贅述了,你懂的。要說明的是:關注後,訂餐網站會收到一個用戶關注的消息,網站返回一段說明文字,提示如何操做等信息,如圖2:
微信
(圖2)app
下面,我就把我本身設計的處理微信消息的代碼介紹下吧,很差的地方,請大夥兒多給我指正指正。仍是先上一張UML模型圖吧,關於依賴和關聯的關係,真不怎麼弄得明白,因此都有依賴的關係表示了下,這張圖片不是很清晰,有興趣的能夠下載源文件看下uml.rar,見圖3:微信公衆平臺
下面仍是簡單對幾個類進行說明下吧,這樣你們看得明白點。ide
BaseNotice.cs,此類表示消息基類,由於每一個消息都有幾個字段是相同的,如ToUserName、FromUserName、CreateTime、MsgType等,全部抽象出一個基類,此類還有一個抽象方法LoadXml,根據xml返回類的對像的實例。其餘具體消息繼承此類,加上本身特定的信息。post
text.cs ,此類表示文本消息類,除了有BaseNotice中有的屬性外,還有一個Content,表示文本信息內容。且實現LoadXml方法,返回一個text實例,代碼以下:測試
/// <summary> /// 文本消息 /// </summary> public class text : BaseNotice { /// <summary> /// 根據xml返回對像 /// </summary> /// <param name="xml"></param> /// <returns></returns> public override BaseNotice LoadXml(string xml) { text notice = new text(); //<xml> //<ToUserName><![CDATA[toUser]]></ToUserName> //<FromUserName><![CDATA[fromUser]]></FromUserName> //<CreateTime>1348831860</CreateTime> //<MsgType><![CDATA[text]]></MsgType> //<Content><![CDATA[this is a test]]></Content> //<MsgId>1234567890123456</MsgId> //</xml> System.Xml.XmlDocument d = new System.Xml.XmlDocument(); d.LoadXml(xml); System.Xml.XmlCDataSection n = d.SelectSingleNode("/xml/ToUserName").FirstChild as System.Xml.XmlCDataSection; notice.ToUserName = n.Value; n = d.SelectSingleNode("/xml/FromUserName").FirstChild as System.Xml.XmlCDataSection; notice.FromUserName = n.Value; //n = d.SelectSingleNode("/xml/CreateTime").FirstChild as System.Xml.XmlCDataSection; //notice.CreateTime = n.Value; n = d.SelectSingleNode("/xml/MsgType").FirstChild as System.Xml.XmlCDataSection; notice.MsgType = n.Value; n = d.SelectSingleNode("/xml/Content").FirstChild as System.Xml.XmlCDataSection; notice.Content = n.Value; //n = d.SelectSingleNode("/xml/MsgId").FirstChild as System.Xml.XmlCDataSection; //notice.MsgId = n.Value; return notice; } /// <summary> /// 消息內容 /// </summary> public string Content { get; set; } }
location.cs,此類表示地理位置消息類,除了有BaseNotice中有的屬性外,還有Location_X(緯度),Location_Y(經度)等信息。實現代碼與text.cs差很少,這裏就再也不貼了。網站
BaseHandler.cs,表示處理消息的基類,定義了一個抽象方法HandleNotice,由具體處理類,去實現,代碼比較簡單,以下:
/// <summary> /// 處理消息基類 /// </summary> public abstract class BaseHandler { protected BaseNotice notice; public BaseHandler(BaseNotice _notice) { notice = _notice; } /// <summary> /// 處理消息,每一個子類重寫此法 /// </summary> /// <returns></returns> public abstract string HandleNotice(); }
TextHandler.cs,此類表示處理文本信息的類,對用戶發送的文本進行處理,而後返回相關信息。按上面的描述,發送「d」或者「訂單」,返回今天的訂單,其餘文本,直接返回說明信息。代碼以下:
/// <summary> /// 文本信息處理類 /// </summary> public class TextHandler : BaseHandler { public TextHandler(BaseNotice _notice) : base(_notice) { } /// <summary> /// 文本信息處理方法,若是文本信息 = d,返回今天訂單 /// </summary> /// <returns></returns> public override string HandleNotice() { StringBuilder backmsg = new StringBuilder(); text model = (text)base.notice; backmsg.Append("<xml>"); backmsg.Append("<ToUserName><![CDATA[" + model.FromUserName + "]]></ToUserName>"); backmsg.Append("<FromUserName><![CDATA[" + model.ToUserName + "]]></FromUserName>"); backmsg.Append("<CreateTime>" + DateTime.Now.Ticks + "</CreateTime>"); string Content = ""; if (model.Content.ToLower().Trim() == "d" || model.Content.ToLower().IndexOf("訂單") >= 0) { ETogoOrder dal = new ETogoOrder(); StringBuilder ordermsg = new StringBuilder(""); IList<ETogoOrderInfo> orderlist = dal.GetList(3, 1, " tempcode='" + model.ToUserName + "' and ordertime > '"+DateTime.Now.ToShortDateString()+"' ", "dataid", 1); if (orderlist.Count > 0) { ordermsg.Append("今日訂單"); foreach (var item in orderlist) { ordermsg.Append("\r\n訂單號:"); ordermsg.Append("\r\n" + item.OrderID); ordermsg.Append("\r\n訂單時間:" + item.orderTime.ToShortTimeString()); ordermsg.Append("\r\n訂單狀態:" + ConfigHelper.TurnOrderState(item.State)); IList<FoodInOrderInfo> foodlist = new EOrderFood().GetAllByOrderID(item.OrderID); foreach (var food in foodlist) { ordermsg.Append("\r\n" + food.FoodName + "(" + food.FoodPrice + "x" + food.Num + ")"); } ordermsg.Append("\r\n=================="); } } else { ordermsg.Append("您今天尚未訂餐點哦"); ordermsg.Append("\r\n=================="); } Content = ordermsg.ToString(); } else//其餘地方返回原信息 { Content = ConfigHelper.GetConfigBackMsg(); } backmsg.Append("<Content><![CDATA[" + Content.ToString() + "]]></Content>"); backmsg.Append(" <MsgType><![CDATA[text]]></MsgType>"); backmsg.Append(" </xml> "); return backmsg.ToString(); } }
LocationHandler.cs,此類用於處理地理位置信息,和TextHandler.cs代碼差很少,就是實現了HandleNotice方法。
NoticeFactory.cs,此類表示根據消息類型,返回具體處理類,用了簡單工廠,每次要增長具體消息處理類,這還要加個分支,有點糾結,代碼以下:
/// <summary> /// 根據消息類型,返回對像 /// </summary> public class NoticeFactory { const string AssemblyPath = "Hangjing.Weixin";//用於反射 public static BaseHandler CreateInstance(string xml) { BaseHandler handler = null; //解析數據 System.Xml.XmlDocument d = new System.Xml.XmlDocument(); d.LoadXml(xml); System.Xml.XmlCDataSection n = d.SelectSingleNode("/xml/MsgType").FirstChild as System.Xml.XmlCDataSection; HJlog.toLog("MsgType=" + n.Value); Type type = Type.GetType(string.Format(AssemblyPath + ".{0}," + AssemblyPath, n.Value.Trim()), false, true); BaseNotice noticemodel = (BaseNotice)Activator.CreateInstance(type); if (noticemodel != null) { noticemodel = noticemodel.LoadXml(xml); switch (noticemodel.MsgType) { case "text": handler = new TextHandler(noticemodel); break; case "event": handler = new EventHandler(noticemodel); break; case "location": handler = new LocationHandler(noticemodel); break; default: break; } } else { HJlog.toLog("noticemodel=mull"); } return handler; } }
weixinHelper.cs,此類封裝了一些基本操做,如驗證消息是否來來自微信服務器,獲取微信服務器post來的消息,最主要的仍是處理消息的地方,無論添加多少消息類型,這裏都不用修改,代碼以下:
/// <summary> /// 根據接到的信息,返回內容 /// </summary> /// <returns></returns> public string HandleData() { string userdata = reciveData(); string backmsg = ""; BaseHandler handler = NoticeFactory.CreateInstance(userdata);//根據不一樣消息類型,返回具體處理類, if (handler != null) { backmsg = handler.HandleNotice(); HJlog.toLog("handler != null " + backmsg); } else { HJlog.toLog("handler == null "); } return backmsg.ToString(); }
客戶端(指在公衆平臺設置的那個連接)代碼就相對簡單了(不過判斷是否網站接入的不知道是什麼時間調用的),代碼以下:
protected void Page_Load(object sender, EventArgs e) { weixinHelper wx = new weixinHelper(Context); if (wx.isJoin())//若是是網站接入 { Response.Write(wx.isValidRequest()); Response.End(); //HJlog.toLog("若是是網站接入"); return; } else//接收消息 { Response.Write(wx.HandleData()); //HJlog.toLog("接收消息"); Response.End(); return; } }
經過返回的連接,進入網站後,就全是html5的事兒了,第一次寫,還真是用了很多時間。寫得很差,代碼就不貼了,上幾個截圖吧【html5界面爲我家妞妞製做,妞妞辛苦了^_^】:
以上就是微信點餐相關內容了,其實也就那點事兒,寫得很差,見諒,有興趣的就掃一掃吧,若是你也開發這方便的,一塊兒交流下: