餓了麼訂單--快到碗裏來

引子   

     堅持了20天,終於仍是作了一個艱難的決定--把媳婦和娃送到了丈母孃家。html

   前些時間,老媽有事兒回了四川,給了我和媳婦獨自撫養娃的機會,我知道這將是一個巨大的挑戰。程序員

   由於一些知道的和不知道的緣由,娃的溼疹比較嚴重,晚上老睡不踏實,得整晚拍着,哄着,實在沒轍了,就得抱着睡,否則就不停的撓頭呀,肚子的。。算法

   白天除非抱着,根本睡不了一下子,醒了沒人看着,也是有事兒沒事兒撓本身。根本離不開人...看着娃身上的溼疹,以及來不及好的撓痕,內心真是奔潰的。sql

   還獲得處尋醫問診,泡中藥,塗藥膏,抹茶油...官方的,民間的... 都是3個字:然並卵。json

   又值搬新家,更是忙得不可開交,與媳婦在杭州奮鬥了6-7年,總算是有了本身的家,只是全然沒空喜悅一下,反倒時房貸的壓力總記在心上。api

   媳婦幾度落淚,這不是矯情,一則是爲本身孕期沒管牢嘴,滿月又吃了蝦而自責;二則吃很差,睡很差,身心都是承受巨大壓力,就是上個洗手間都得把娃哄睡了。微信

   話說回來,也是正是這短短的20天,方纔對「當家才知柴米貴,養兒方知父母恩」,有了切身的感覺,對父母的噓寒問暖再也不厭煩,而真正心懷感恩。這個認知與媳婦的意見終於空前的一致了 :)。app

   跨出了丈母孃家門,揮手告別妻兒時,心頭一緊,眼眶微酸,眼淚幾乎奪眶而出...是了,這就是離別。也終於理解了,母親每次送我出遠門時,老是忍不住的哭泣。ide

 

   —————————— 生活感悟,藉此叨叨,迴歸主題——————————post

 

背景

  以前寫過一篇關於同步餓了麼訂單的文章《訂餐系統之同步餓了麼商家訂單》,是介紹如何經過 餓了麼OpenAPI 同步餓了麼商家訂單。此版本最大的弊端即是每次要綁定商家都須要發郵件給他們,綁定商家是一個頻繁的操做,可是他們郵件處理的速度又較爲緩慢,有鑑於此對接人的幾乎都是望而卻步,像早期的淘點點,及新開美團外賣開放平臺,都是以商家登陸受權方式綁定,徹底是開發商與商家自助就能夠完成。前些天,餓了麼OpenAPI2.0 總算是千呼萬喚始出來了。趕忙註冊,認證。因而有了這篇文章。

申請

  先上開放平臺網址, https://open.shop.ele.me/openapi《餓了麼開放平臺》,  首先,你得註冊成爲開放者,這個過程不用截圖了吧。而後 開發者資質認證,這個按要求填寫相關信息,上傳相關資料等他們審覈了。

  

  幾個工做日審覈經過後,大家會看以下信息,就可開始進入下一步操做了。

  

  

建立應用

   對接了美團後,才知道能夠建立應用是多麼方便一個功能,否則來一個客戶,又得從新註冊帳號,走申請的流程,漫長而痛苦。餓了麼OpenAPI2.0 能夠建立多個應用,每一個應用獨立運行,減小了不少沒必要要的麻煩。

進入開發都中心,便可開始新建應用,輸入幾個基本信息,應用就建立好了。

  

 

  

 

  接下來能夠配置沙箱環境了,點擊查看應用,進入「沙箱環境」選項卡。設置好 回調地址URL(商家受權後回調通知地址),推送URL(新訂單,訂單狀態變化等通知地址),推送消息(選擇要接收的通知類型)。配置部分到如今就結束了,接下變是上代碼了。

  

 

商戶受權

  準備寫代碼以前,仍是習慣性的去找下SDK,有SDK確定會事半功倍的,只是不看不知道,一看真又感受被默默的鄙視了一下下。提供了5種語言,都沒有.net。好吧,別的咱不敢說,寫代碼仍是會的。

  

 

   初略看了文檔知道受權流程採用國際通用的OAuth2.0標準協議做爲商戶身份驗證與受權協議,以前對接QQ登陸,微信公從平臺,流程幾乎相似,輕車熟路,已經有代碼修改幾個配置與json對應的實體,分分鐘就完成了前面4個流程,流程圖以下,核心代碼也貼上來了

   

 

/// <summary>
        /// 受權
        /// </summary>
        /// <param name="callbackurl"></param>
        public ELEAuth(HttpContext _context)
        {
            context = _context;
            parameters = new Hashtable();
            singparameters = new Hashtable();
        }

        /// <summary>
        /// 返回受權url
        /// </summary>
        /// <param name="shopid"></param>
        /// <returns></returns>
        public string GetAuthURL(int shopid)
        {
            string callbackurl = appconfig.authcallbackURL;
            string OAuthurl = appconfig.authurl + "?response_type=code&client_id=" + Hangjing.EleAPIV2.appconfig.Key + "&redirect_uri=" + context.Server.UrlEncode(Hangjing.EleAPIV2.appconfig.authcallbackURL) + "&state=" + shopid + "&scope=all";
            return OAuthurl;
        }

        public access_tokenInfo getToken()
        {
            access_tokenInfo token = new access_tokenInfo();

            parameters.Add("grant_type", "authorization_code");
            parameters.Add("code", context.Request["code"]);
            parameters.Add("redirect_uri", appconfig.authcallbackURL);
            parameters.Add("client_id", appconfig.Key);

            string Authorization = appconfig.Key + ":" + appconfig.Secret;
            byte[] bytes = Encoding.UTF8.GetBytes(Authorization);

            HttpItem objHttpItem = new HttpItem()
            {
                Authorization = "Basic " + Convert.ToBase64String(bytes),
                URL = appconfig.tokenurl,
                Encoding = "utf-8",
                Method = "POST",
                Postdata = getPostDatan()
            };

            HttpHelper objhttp = new HttpHelper();
            objhttp.isToLower = false;


            Hangjing.AppLog.AppLog.Info("getToken:" + getPostDatan() + "\r\nurl=" + appconfig.tokenurl + "\r\nAuthorization=" + Convert.ToBase64String(bytes));

            string returnmsg = objhttp.GetHtml(objHttpItem);

            Hangjing.AppLog.AppLog.Info("getToken:" + getPostDatan() + "\r\nmsg=" + returnmsg + "\r\nAuthorization=" + Convert.ToBase64String(bytes));

            token = JsonConvert.DeserializeObject<access_tokenInfo>(returnmsg);
            if (token != null)
            {
                token.shopid = Convert.ToInt32(context.Request["state"]);
            }

            return token;
        }
商戶受權部分代碼

 

 

  回調地址URL指向的地方 只要以下調用就能夠了。

  ELEAuth auth = new EleAPIV2.ELEAuth(Context);
  access_tokenInfo token = auth.getToken();

  

  整個過程就一個地方要注意下:HTTP header中須要攜帶Authorization請求頭,Basic值的算法以下(+號表示字符串鏈接)  base64_encode(key + ":" + secret),具體的寫法在上面的代碼已經有了。大夥兒稍微留意下就過了。

  話說回來,爲何是前面4個流程分分鐘,獨少了第五個呢,是了,第5個裏面有一個計算簽名的過程,幾乎是第一次遇到這樣的簽名方式,過程較爲麻煩,容易出錯,以前也有幾個園友也問到簽名的事兒,因此這裏單獨拿出來。

 

簽名算法

   對接接口,簽名老是較爲麻煩的一點,相關文檔以下點這裏,若是想了解流程,能夠自行查看。流程很長,這裏就不寫了,幾個地方要注意的以下:

   1,簽名的參數,只包含 JSON對像,metas和params 的屬性。固然,params可能沒有屬性,忽略就能夠了。

   2,使用"key=json_encode(value)"方式進行字符串拼接,這就得要求 參數的類型 要與文檔裏匹配,long與string  json_encode後的值是有區別的。好比  json_encode(123) = 123,而 json_encode(「123」) =「 123」,這就直接致使用於加密的內容都不一樣了。

  其餘的什麼排序,action + token  + secret,md5等等按正常流程走就能夠了,沒有坑了。

  到這裏,就只剩代碼,簽名算法代碼以下:

  

//構建簽名參數,注意 timestamp 類型是 int64
singparameters.Add("app_key", appconfig.Key);
singparameters.Add("timestamp", Convert.ToInt64(Timestamp));


        /// <summary>
        /// 簽名
        /// </summary>
        /// <returns></returns>
        public string createMD5Sign(string action, string token)
        {
            StringBuilder sb = new StringBuilder();
            ArrayList akeys = new ArrayList();

            foreach (var item in singparameters.Keys)
            {
                akeys.Add(item + "=" + JsonConvert.SerializeObject(singparameters[item]) + "");
            }
            akeys.Sort();

            foreach (string k in akeys)
            {
                sb.Append(k);
            }

            string signstep = action + token + sb.ToString() + appconfig.Secret;

            Hangjing.AppLog.AppLog.Info("createMD5Sign:oldsignstep=" + signstep);

            signstep = Utils.MD5(signstep).ToUpper();

            Hangjing.AppLog.AppLog.Info("createMD5Sign:signstep=" + signstep);

            return signstep;
        }
簽名實體,調用代碼

 

  

  第5個流程的文檔在這裏,主要是獲取商戶信息,與系統商家對應好,我是經過state參數傳系統商家編號,由於state會原樣回傳回來。

  計算好籤名,這個流程就完成大半了,剩下注意以下:

  1, Content-Type = application/json;charset=utf-8,

  2, id 參數值爲 Guid.NewGuid().ToString()

  3,post的參數要是josn 格式。參數在系統裏是用 Hashtable 保存的,只要一句話就能夠轉成Json -- JsonConvert.SerializeObject(parameters); 

  作了以上操做,此流程80%的狀況就OK了。最後上幾個實際流程圖

  

  

   

接收訂單參數,查詢訂單信息

  設置好接收推送的url,根據通知類型和內容進行相應的邏輯操做,好比收到商家確認訂單通知,就把訂單加入系統,訂單取消通知就把系統中訂單相應取消。

  完成了簽名算法,其餘的接口對接就是水到渠成的事兒了,根據json生成實體,替換參數,很快就能夠完成其餘接口了。

  接收通知代碼以下,特別注意就是消息體是以流形式推送過來的。另外還有一個狀況可能你們都會遇到:建立應用後,會生成測試商家,商家的商品全是1毛的,你測試幾單後,餓了麼會認爲商家在刷單,之後提交訂單就直接取消了,沒法測試,後來諮詢的了客服,說是商品要大於1元纔不會自動取消,這樣就能夠測試新訂單推送,商家接單推送,而後再把訂單取消,支付的金額就自動退回來了,

  

 HJlog.toLog("\r\nele2.0推送");


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

            pushMessageInfo notice = JsonConvert.DeserializeObject<pushMessageInfo>(jsondata);

            switch (notice.type)
            {
                case 14:
                case 15:
                case 17:
                case 23:
                case 25:
                case 35:
                    ////訂單取消
                    {
                        ordermessageinfo pushorder = JsonConvert.DeserializeObject<ordermessageinfo>(notice.message);
                        string sys_orderid = "e" + pushorder.orderId;
                        new Custorder().AddOrderRecord("e" + sys_orderid, 5, "ele", "餓了麼取消了訂單");

                        string sql = "update Custorder set OrderStatus=5 where OrderID='" + sys_orderid + "';update shopeleCustorder set OrderStatus=5 where OrderID='" + sys_orderid + "'";
                        WebUtility.excutesql(sql);

                    }
                    break;
                case 12: //接收訂單

                    {
                        ordermessageinfo pushorder = JsonConvert.DeserializeObject<ordermessageinfo>(notice.message);
                        //獲取token
                        taobaoAPIAcountInfo token = new taobaoAPIAcount().GetList(1, 1, "linkurl='"+notice.shopId+"'", "id", 1).FirstOrDefault();
                        if (token == null)
                        {
                            Hangjing.AppLog.AppLog.Info("商家:" + notice.shopId + "未找到受權信息,orderid=" + pushorder.orderId);
                        }
                        else
                        {
                            ELEShopV2 eleshop = new ELEShopV2(Context);
                            OrderResult rs = eleshop.getOrder(pushorder.orderId,token.pic);



                        }

                    }

                    break;


                default:
                    break;
            }





        }
接收推送代碼

 

  

上線

  對接完成後,在 設置好 正式環境 的相關參數,提交審覈,至此對接就基本完成了。訂單同步進入系統後,就是咱們的調度系統派上用場了。經過自動調度規則,讓配送員本身搶單,幾乎都不用客服調度了,你們還搶的不亦樂乎。如下是某客戶實時效果圖。

  

  

  到此,終於實現了幾個平臺訂單同步,總算是了了一件心事兒,還少百度外賣?直接忽略了,聽商家說百度外賣半個月都不來個訂單,連業務員都聯繫不上了。

  對接流程就完結了,但願對那些想要對接的人能有些幫助,全部流程都是親測,絕對童叟無欺。

結語

  又到夏天了,猛然發現大學4年,天天6點起來練出來的腹肌早已緊密的團結在了一起,確實作咱們一行的,天天上班,加班加起的得坐10幾個小時,如疏於鍛鍊,不出3年,基本都得長肉肉的。因而,趁着媳婦回孃家,我開始了找回腹肌計劃,但願她回來時,看到一個不同的我。【她一直想看我有8塊腹肌的樣子 :)】

  一,早上6:30起牀,作好中午的飯,帶去公司(外賣太貴了,也不是特別好吃),順道在工商大學打30分鐘籃球。去上班恰好。

  二,晚上22:30-23:00之間 從公司跑回家,全程4千米,繞一下能夠有5-6千米。(再晚點,就只能騎車了)

  計劃之初,心裏也會抵觸,反卻是執行2個月後,一切都變得天然而然,成了生活的一部分了。順帶還學會炒菜,固然了,我一般只放油鹽,最多加點豆油,味道就那樣了 :)。

  到如今跑5千米基本不費多少力,有時還故意再繞一圈小區。惟一麻煩的就是要揹着早上帶的兩個飯盒,權當負重吧。下面是一張最近的跑步記錄,下一步就是挑戰10KM了,個人終極目前是全馬(哈哈)。另外,若是你也要想跑起來,必定注意跑前熱身,跑後拉伸。

  

  

  以前聽別人的小密圈挺火,也下載玩了下把,建立了一個同步餓麼訂單的圈子,設置了付費50元加入(付費圈子最低50),抱着玩玩的心態,分享給了以前諮詢餓了麼接口微信好友,萬萬沒想到,還真有幾我的加入了,說是「做爲支持你的分享」這也算是意外的驚喜吧,錢很少,背信任的感受滿好的。在此,也謝過幾位了哈。

  

  

 

   成爲一名優秀的程序員!

相關文章
相關標籤/搜索