訂餐系統之同步美團商家訂單
引子
早上和往常一樣去工商大學打球,除了今天三分比較準外,一切都還是那樣的循規蹈矩。
也許股子裏還有那麽一些不甘平庸,總想著能改變一下如此無趣的按部就班。
轉過行政樓,一波一波的學生在談笑風生。哦,是了,又到拍畢業照片的時間了。
又是一年過去了(也不知從何時起,開始以畢業來計年了),彈指一揮間,已經在這裏工作7年半了。
一份工作越是做得久,反到越羞於提起。也許是羞於現狀,也是羞於未來的我吧。說不清,道不明,有點亂...
腳步也隨著不安的思緒加快了頻率,迅速的穿過了人群...未來還需多努力,希望明年此時,能多一份從容。
——————————觸景生情,些許傷感,回歸主題——————————
背景
之前寫過一篇關於同步餓了麽訂單的文章《訂餐系統之同步餓了麽商家訂單》,有不少人加我咨詢,感覺有這方面需求的人還是滿多的,畢竟現在2家幾乎瓜分了市場,再做平臺已然機會渺茫了,但是商戶畢竟需要服務,訂單還得配送出去。然後餓了
麽,美團外賣都提供了面向供應商的api的權限的申請,這對我們做配送系統的說,真是一大利好。以前都是讓商戶手動錄入其他平臺的訂單,費力還容易出錯。還得在多個app之間來回切換,商戶也是抱怨滿天。有了這些接口,商戶可以選擇自動接單,
自動同步訂單,再也不用幾個app來回切換了。餓了麽同步訂單,在上面的文章中已經介紹了,雖然接口現在變成2.0了。有了一些變化,總的來說還是 萬變不離其宗。本篇就來詳細接受下同步美團訂單的相關步奏。寫得不對地方,歡迎指正 :)
具體流程,下圖中寫得比較詳細。
申請
去年過年,因娃太小,沒能回家,閑在杭州,發現可以申請美團外賣相關接口,欣喜若狂,擼起袖子就動了起了,登錄申請網站地址《美團點評 | 聚寶盆餐飲開放平臺》,填寫相關信息。記得,當時是2月5號,再2天就過年了,想著如果能年前審核好...,當然,後來是想多了,過了一個月都沒有審核通過,也不能進行下一步。到時那個心呀,難過,沒有還好,現在是看得見,不讓用。經過漫長的煎熬,終於在一個不起眼的地方,發現一個郵箱,懷著死馬當活馬醫的想法,發過去了,想不到,還真給回復了,說是過年漏掉了申請。好嘛,審核通過了總是好的,過程是復雜了些。
這裏通過了,他們會加你QQ,確認相關信息,還會快遞一份文件,簽字蓋章,按說明快遞回去就OK了。
審核通過,開放平臺裏有相關信息了。關鍵的東西就是 developerId,與SignKey 。調用接口會用到
開入平臺文檔地址:《文檔中心》,也許你看了文檔,都不用看下面的:)。
回調接口設置
開始開發前,先要設置好回調,通知接口。美團外賣會根據在開放平臺設置的通知地址,發送相關信息,比如新訂單通知,商家確認訂單通知,及綁定,解綁商家通知等。這裏每個通知一個接口,這樣程序蠻方便的,可以一個通知,一個url。不用去判斷到底是什麽通知。
在下圖中設置
門店映射
所謂映射,就是把你系統的商家編號,與美團商家綁定起來,以後推送都是自己系統的商家編號推送過來。方便操作
對接第一步,還是綁定商家,並保存Token(後面的操作都會用到)。
綁定操作就是訪問連接 https://open-erp.meituan.com/storemap?developerId=100019&businessId=2&ePoiId=8859&signKey=8bl1g62omy2m5ywp&ePoiName=湘北人家&netStore=1
輸入商家賬號,密碼選擇商家授權即可完成映射
具體參數可以參考文檔, 其中 ePoiId 為自己系統的商家編號,像我就直接用自動編號,這個方便記錄,後臺綁定也方便,訂單通知過來也方便。比如,我們最後的效果就是在商家詳情中增加相關設置。
在回調接口設置中,設置了url後,會收到通知,處理通知的代碼如下。
Response.Clear(); Response.Write("{\"data\":\"success\"}"); Hangjing.AppLog.AppLog.Info("美團門店與ERP綁定接收token回調URL"); System.IO.Stream stream = Request.InputStream;//這是你獲得的流 if (stream != null && stream.Length > 10) { Hangjing.AppLog.AppLog.Info("stream.Length :" + stream.Length); string jsondata = ""; using (StreamReader reader = new StreamReader(stream)) { jsondata = reader.ReadToEnd(); ; } //保存 appAuthToken Hangjing.AppLog.AppLog.Info("回調URL信息:" + jsondata); }View Code
既然有映射商家,就是有解除綁定的操作,同樣,在回調接口設置中,設置了url後,會收到通知,處理通知的代碼如下。 這裏記錄,主要是為了方便後臺操作,知道當前商家是否綁定。
Response.Clear(); Response.Write("{\"data\":\"success\"}"); Hangjing.AppLog.AppLog.Info("美團門店與ERP解除綁定token回調URL"); System.IO.Stream stream = Request.InputStream;//這是你獲得的流 if (stream != null && stream.Length > 10) { Hangjing.AppLog.AppLog.Info("stream.Length :" + stream.Length); string jsondata = ""; using (StreamReader reader = new StreamReader(stream)) { jsondata = reader.ReadToEnd(); ; } Hangjing.AppLog.AppLog.Info("解除綁定回調URL信息:" + jsondata); }View Code
新訂單推送
要推送訂單,首先得要設置接收通知的url
要推送訂單,其次得有商家,所以美團為我們設置了測試商家。還可以添加多個。要特別註意的就是:測試門店為一個坐標位於南極洲、配送範圍為西藏昌都的線上測試門店,開發者可使用美團外賣APP定位到西藏昌都氣象局,根據測試門店名稱搜索到測試門店進行下單。
一定要App定位在西藏昌都氣象局方可下訂單。
因為推送的數據格式是json,所以我的做法是:先創建好訂單對應的體,收到通知後,轉成實體,再做邏輯處理。接收通知,所上面的類似。
Response.Clear(); string order = Server.UrlDecode(Request["order"]); Hangjing.AppLog.AppLog.Info("美團訂單來了.美團訂單內容:" + order); apiResultInfo rs = new apiResultInfo(); System.IO.Stream stream = Request.InputStream;//這是你獲得的流 if (stream != null && stream.Length > 10) { Hangjing.AppLog.AppLog.Info("stream.Length :" + stream.Length); string jsondata = ""; using (StreamReader reader = new StreamReader(stream)) { jsondata = reader.ReadToEnd(); ; } Hangjing.AppLog.AppLog.Info("美團訂單信息:" + jsondata); mtorderInfo model = JsonConvert.DeserializeObject<mtorderInfo>(order); if (model.ePoiId == "1015") { mthelper mt = new mthelper(Context); apiResultInfo retuls = mt.confirmOrder(model.orderId, Convert.ToInt32(model.ePoiId)); } } else { rs.state = 0; rs.msg = "參數錯誤"; } Response.Write("{\"data\":\"OK\"}"); Response.End();View Code
確認訂單
我們收到新訂單通知時,可以調用api直接確認訂單,也就是商戶接單。到這裏,我們才正式去調用api,前面都是美團來調用我們,要調用api,首先要做的就是實現簽名。這是我對接這麽多系統,簽名算法最簡單的。直接上代碼。
簽名:首先將GET
、POST
參數除去sign本身以及值為空的參數以及=號和&號,按參數自然排序,(例如a=&c=3&b=1,變為b1c3)然後按參數1值1參數2值2...參數n值n的方式拼接成新字符串,再跟字符串前面加上signKey,做sha1散列,最後將得出字符串轉成小寫即為sign。
簽名代碼
/// <summary> /// sha1簽名 /// </summary> /// <returns></returns> public string createSHA1Sign() { StringBuilder sb = new StringBuilder(); ArrayList akeys = new ArrayList(parameters.Keys); akeys.Sort(); foreach (string k in akeys) { string v = HttpUtility.UrlEncode((string)parameters[k], Encoding.UTF8); if (null != v && "".CompareTo(v) != 0 && "sign".CompareTo(k) != 0) { sb.Append(k+ v); } } string signstep2 = Constant.mt_SignKey + sb.ToString(); string sig = Utils.SHA1_Hash(signstep2).ToLower(); AppLog.AppLog.Info("美團簽名=" + "signstep1=" + sb.ToString() + "\r\nsignstep2=" + signstep2 + "\r\n => sign:" + sig); return sig; }View Code
錄入所有參數,得到簽名,初始化post參數,調用指定api,即可完成確認。大概代碼如下,代碼都比較文明,大家一看變懂了。
public apiResultInfo confirmOrder(string orderId, int shopid) { apiResultInfo rs = new apiResultInfo(); meituanbindlogInfo record = new meituanbindlog().GetList(1, 1, "ePoiId=" + shopid + " and mtype=1", "mid", 1).FirstOrDefault(); if (record == null) { OperationLog.Warn("商家:" + shopid + "未找到綁定token"); rs.msg = "商家:" + shopid + "未找到綁定token"; return rs; } parameters = new Hashtable(); parameters.Add("charset", "UTF-8"); parameters.Add("version", "1"); parameters.Add("timestamp", Utils.getTimestamp()); parameters.Add("appAuthToken", record.appAuthToken); parameters.Add("orderId", orderId.Replace("m", "")); createSHA1Sign(); HttpItem objHttpItem = new HttpItem() { Encoding = "utf-8", Method = "POST" }; string url = "http://api.open.cater.meituan.com/waimai/order/confirm"; string returnmsg = queryData(objHttpItem, url); mtresult result = Newtonsoft.Json.JsonConvert.DeserializeObject<mtresult>(returnmsg); if (result.data != null && result.data.ToLower() == "ok") { rs.state = 1; } else { rs.msg = "確認訂單失敗"; } return rs; } public string queryData(HttpItem objHttpItem, string url) { string sig = createSHA1Sign(); parameters.Add("sign", sig); serverurl = url; ArrayList akeys = new ArrayList(parameters.Keys); StringBuilder sb = new StringBuilder(); foreach (string k in akeys) { string v = context.Server.UrlEncode((string)parameters[k]); v = HttpUtility.UrlEncode(v, Encoding.UTF8); if (null != v && "".CompareTo(v) != 0) { if (sb.Length == 0) { sb.Append(k + "=" + v); } else { sb.Append("&" + k + "=" + v); } } } if (objHttpItem.Method.ToLower() == "get") { serverurl += "?" + sb.ToString(); } else { objHttpItem.Postdata = sb.ToString(); } HttpHelper objhttp = new HttpHelper(); objHttpItem.URL = serverurl; objhttp.isToLower = false; string returnmsg = objhttp.GetHtml(objHttpItem); Hangjing.Common.HJlog.toLog("returnmsg=" + returnmsg + "\r\n url=" + serverurl); // HJlog.toLog(this.getDebugInfo()); return returnmsg; }View Code
確認訂單後,我們設置的訂單確認通知接口,也有收到相應的通知,具體代碼與新訂單通知是一樣的,只是你可以根據自己業務處理,比如,商家確認訂單後,訂單直接進入系統,自動調度,或者人工派單。
設置商家營業狀態
這個接口也是經常用到的,因為測試賬號,不能登錄美團外賣商戶後臺,如果商家有一個訂單沒接,商家就會自動休息,影響我們測試。所以實現這個接口後,可方便修改商家狀態。
這個接口與確認訂單接口都是類似的,只是參數不同,url不同而已。由於調用api,我們都是封裝在方法:queryData了,我們只用設置好參數即可。代碼如下:
public apiResultInfo shopOnline(int shopid) { apiResultInfo rs = new apiResultInfo(); meituanbindlogInfo record = new meituanbindlog().GetList(1, 1, "ePoiId=" + shopid + " and mtype=1", "mid", 1).FirstOrDefault(); if (record == null) { OperationLog.Warn("商家:" + shopid + "未找到綁定token"); rs.msg = "商家:" + shopid + "未找到綁定token"; return rs; } parameters.Add("appAuthToken", record.appAuthToken); createSHA1Sign(); HttpItem objHttpItem = new HttpItem() { Encoding = "utf-8", Method = "POST" }; string url = "http://api.open.cater.meituan.com/waimai/poi/open"; string returnmsg = queryData(objHttpItem, url); mtresult result = Newtonsoft.Json.JsonConvert.DeserializeObject<mtresult>(returnmsg); if (result.data != null && result.data.ToLower() == "ok") { rs.state = 1; } else { rs.msg = "商家上線失敗"; } return rs; }設置商家上線
上線
其他還有很多接口可以按需對接,比如商口數據,評論數據。目前我們用不上,暫未對接。最後一步就上線操作了。
未上線之前,最多能接5個商家,上線後就沒有限制了。
目前上線要先寫一個《上線申請》,然後在開放平臺,裏點擊上線,會有美團人員聯系你,確認相關信息就OK了。
最後效果圖如下:
結語
對接美團外賣,除了提交審核時間不好,導致審核時間長了些外,其他還是蠻順利的,他們也蠻配合的,根據接口文檔幾乎可以完整大部分操作。
就代碼上而言,確定沒有太多可以說的,對接過程還是有些曲折的。希望這個文章能給那個正在對接的,想對接的人提供一些幫助,如果真有幫助了,有個贊最好了。
如果有同在做這個的,歡迎交流哈。
最後,呼應下開頭,7年半,真不是一個短時間,我們能寫多少個7年的代碼呢。也想借此,聽聽諸位的心聲。
成為一名優秀的程序員!
訂餐系統之同步美團商家訂單