1. 程式人生 > >訂餐系統之同步美團商家訂單

訂餐系統之同步美團商家訂單

ken first ret 沒有 warn ons 回歸 http 選擇

引子   

  早上和往常一樣去工商大學打球,除了今天三分比較準外,一切都還是那樣的循規蹈矩。

   也許股子裏還有那麽一些不甘平庸,總想著能改變一下如此無趣的按部就班。

   轉過行政樓,一波一波的學生在談笑風生。哦,是了,又到拍畢業照片的時間了。

   又是一年過去了(也不知從何時起,開始以畢業來計年了),彈指一揮間,已經在這裏工作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,首先要做的就是實現簽名。這是我對接這麽多系統,簽名算法最簡單的。直接上代碼。

  簽名:首先將GETPOST參數除去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年的代碼呢。也想借此,聽聽諸位的心聲。

   成為一名優秀的程序員!

訂餐系統之同步美團商家訂單