訂餐系統之微信點餐


訂餐系統之微信點餐

經過幾天的開發、測試微信點餐demo終於完成了,特在此分享下,不好的地方請大家多指正下哈!一開始,就想這東西出來這么久了,網上應該有很多現成的東西,於是,baidu、google了半天,基本沒發現現成的東西,也許是我搜索不得其道,也有可能大家都不願意分享吧...於是,還得自己動手,豐衣足食!

  還是先交代下背景:所謂“微信點餐”,其實就是用戶通過微信app,關注公眾號,發送指定類型的信息,如地理位置信息,網站返回相關鏈接到微信上,通過這些鏈接進入wap或者html5網站,然后開始選擇商家、點餐、提交訂單等。關於微信app,與訂餐網站的關系,我簡單的畫了一個圖,比較潦草,請別噴得太厲害了!如圖1,說簡單點:微信app通過微信服務器,傳給訂餐網站(申請公眾號時,會輸入一個地址,微信服務器就是通過此地址post,get消息的),網站根據收到的消息,返回具體信息,再通過某些信息的鏈接進入wap或者html5站點。微信公眾平台地址:https://mp.weixin.qq.com/ ,這幾天好像升級了,不叫公眾號了,叫訂閱號。

     

                                  (圖1)

  至於,如何申請、如何關注,這里就不贅述了,你懂的。要說明的是:關注后,訂餐網站會收到一個用戶關注的消息,網站返回一段說明文字,提示如何操作等信息,如圖2:

          

                                                 (圖2)

  

  下面,我就把我自己設計的處理微信消息的代碼介紹下吧,不好的地方,請大伙兒多給我指正指正。還是先上一張UML模型圖吧,關於依賴和關聯的關系,真不怎么弄得明白,所以都有依賴的關系表示了下,這張圖片不是很清晰,有興趣的可以下載源文件看下uml.rar,見圖3:

      

  

  下面還是簡單對幾個類進行說明下吧,這樣大家看得明白點。

  BaseNotice.cs,此類表示消息基類,因為每個消息都有幾個字段是相同的,如ToUserName、FromUserName、CreateTime、MsgType等,所有抽象出一個基類,此類還有一個抽象方法LoadXml,根據xml返回類的對像的實例。其他具體消息繼承此類,加上自己特定的信息。

     text.cs ,此類表示文本消息類,除了有BaseNotice中有的屬性外,還有一個Content,表示文本信息內容。且實現LoadXml方法,返回一個text實例,代碼如下:

  View Code

/// <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,由具體處理類,去實現,代碼比較簡單,如下:

  View Code

/// <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”或者“訂單”,返回今天的訂單,其他文本,直接返回說明信息。代碼如下:

  View Code

/// <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,此類表示根據消息類型,返回具體處理類,用了簡單工廠,每次要增加具體消息處理類,這還要加個分支,有點糾結,代碼如下:

  View Code

/// <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來的消息,最主要的還是處理消息的地方,不管添加多少消息類型,這里都不用修改,代碼如下:

  View Code

/// <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();
}

  客戶端(指在公眾平台設置的那個鏈接)代碼就相對簡單了(不過判斷是否網站接入的不知道是什么時間調用的),代碼如下:

  View Code

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界面為我家妞妞制作,妞妞辛苦了^_^】:

        

  以上就是微信點餐相關內容了,其實也就那點事兒,寫得不好,見諒,有興趣的就掃一掃吧,如果你也開發這方便的,一起交流下:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM