訂餐系統之同步口碑外賣商家菜單與點點送訂單

  2015年餓了麼、百度外賣、美團外賣、口碑外賣幾家幾乎分完了外賣這碗羹,讓其他外賣網站幾乎舉步維艱,也讓那些蠢蠢欲動想進入外賣領域的人猶豫不決了(這估計是要砸我飯碗的節奏啊,ヾ(@⌒ー⌒@)ノ)。當然了,喝了外賣這碗羹,肯定得有“產物”,不然,還不被撐破了肚皮麼。對,這個"產物"就是外賣訂單,是大量的外賣訂單,商戶的配送員能力非常有限,於是第三方的配送公司如雨後春筍般的冒了出來,當然了,市場大,競爭也非常殘酷,有些剛冒出頭,就被"扼殺"在襁褓裏了;估計還有不少的沒找好“土壤”,壓根就沒冒出來;肯定還有好些隔岸觀火,躍躍欲試的主兒....反正是你方唱罷我登場,你有張良計我有過牆梯,好不熱鬧呢!!

  熱鬧落盡,平淡歸真,不少配送公司才發現:指望某一個平臺,訂單有限,壯大何其難?再則,大部分用戶估計也和我一樣,沒有忠誠度,哪家優惠大,就去哪家。於是,一方面開始發展自己的業務(開發一個自己的app),其次接口多家平臺(每個平臺一個app)..... 就這樣,活下來的配送公司業務穩定了,訂單也穩定了,但是問題來了:調度人員得幾個平臺來回切換,操作還不一樣,配送員也得在幾個app中切換,你要知道每個配送員身上的訂單,還得費不小勁....於是,整合各家訂單,統一調度,集中配送,讓客服與配送員從其他平臺解放出來,重複單一動作,效率自然就高了!但是願望是美好的,現實是殘酷的:除了口碑有完整的對配送商的接口外(之前申請還非常麻煩,不知道現在好些了沒),美團外賣只對品牌商家開放了接口外,壓根沒有對配送商的接口;餓了麼找半天也沒找着相關接口....雖然現在沒有,但是我估計着,不久的將來這幾個肯定會有針對配送商的接口。既然現在只有口碑有相關接口,那這一系列文章就以口碑外賣接口爲準。以後,如果其他平臺有了相關接口,我再給大家分享下。說得不好的地方,也請大家海涵、指出哈!

  之前的文章訂餐系統之自動確認淘點點訂單已經介紹過相關應用的申請,及獲取授權賬號下的訂單,在這裏就贅述了,有興趣的可以瞭解下。

 

批量上傳與下載口碑商家菜單

   在口碑商家後臺添加過菜單的人都知道,商品只能一個個添加,如果只有1、2個商家還好,但是配送商要生存,就得不停的開店,開了店就得上傳商品,一個店少說也得有百八十個商品,如此激烈的競爭不開個三、五百家商家生存都難啊....於是,我們會看到這一幕:他們在不停的尋找店鋪,到口碑上開設店鋪,再一個個添加商品....然後再重複着,重複着,重複着...於是想起了我。下圖爲批量上傳菜單的過程,同時也可以同步口碑商家已經有菜單到本地。這裏面有一個注意的地方就是:先上傳圖片到口碑,返回圖片地址,再上傳菜單。如果是先上傳菜單,再上傳圖片,特別麻煩。另外,就是接口中有些限制比如:原價不能小於現價,商品介紹不能少於5個字等等之類的,瞭解就可以了。

   

 

  代碼方面都是調用TopSdk.dll封裝的方法,自己在簡單的封裝下,方便使用和複用。我的代碼結構如下圖:

       baseTopAPI.cs  主要是初始化 appkey,appsecret,top_session幾個必要的參數,方便子類調用接口。

       TopSysFoodSort.cs  主要是處理分類相關的接口。

       FoodTopAPI.cs  主要是處理商品相關接口的。

       FoodSortSync.cs  客戶端調用,同步分類

       FoodSync.cs   客戶端調用,同步商品

      

       詳情代碼如下,寫得不好,有需要的可以看下:

    

using Hangjing.Model;
using Hangjing.SQLServerDAL;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using Top.Api;

/// <summary>
/// 淘點點調用接口基類
/// </summary>
public class baseTopAPI
{
    public SortedList<string, string> parameters = null;

    public string appkey { get; set; }
    public string appsecret { get; set; }
    public string top_session { get; set; }

    /// <summary>
    /// 系統商家編號
    /// </summary>
    public int shopid { get; set; }

    /// <summary>
    /// 淘寶商家編號
    /// </summary>
    public long TaoBaoId { get; set; }

    /// <summary>
    /// 接口地址
    /// </summary>
    public string serverurl = "http://gw.api.taobao.com/router/rest?";

    public baseTopAPI(int shopid)
    {
        parameters = new SortedList<string, string>();
        IList<taobaoAPIAcountInfo> apis = SectionProxyData.GettaobaoAPIAcountList();

        TogoInfo shop = new Togo().GetModelByDataId(shopid);
        if (shop.shoptype != 0 && shop.ReveVar1 != "")
        {
            foreach (var key in apis)
            {
                if (shop.shoptype == key.ID)
                {
                    this.appkey = key.classname;
                    this.appsecret = key.pic;
                    this.top_session = key.hovepic;
                    break;
                }
            }
        }
        TaoBaoId = Convert.ToInt64(shop.ReveVar1);
        this.shopid = shopid;
    }


    /// <summary>
    /// 用任意一個api即可
    /// </summary>
    public baseTopAPI()
    {
        parameters = new SortedList<string, string>();
        taobaoAPIAcountInfo apiconfig = SectionProxyData.GettaobaoAPIAcountList().First();

        this.appkey = apiconfig.classname;
        this.appsecret = apiconfig.pic;
        this.top_session = apiconfig.hovepic;

    }

}
baseTopAPI

 

using Hangjing.Common;
using Hangjing.Model;
using Hangjing.SQLServerDAL;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Top.Api;
using Top.Api.Request;
using Top.Api.Response;

/// <summary>
/// 商品分類
/// </summary>
public class FoodSortTopAPI : baseTopAPI
{
    public FoodSortTopAPI(int shopid)
        : base(shopid)
    {
        
    }

    public apiResultInfo CallServer(int operate, string data)
    {
        apiResultInfo rs = new apiResultInfo();
        if (TaoBaoId == 0)
        {
            rs.error_info = "top_session,或者淘寶商家編號未設置未設置";
            rs.error_no = "1";
            return rs;
        }

        ITopClient client = new DefaultTopClient(serverurl, appkey, appsecret, "json");
        WaimaiCategoryOperateRequest req = new WaimaiCategoryOperateRequest();
        req.ShopId = TaoBaoId;
        req.Operate = operate;
        if (operate > 0)
        {
            req.Data = data;
        }

        WaimaiCategoryOperateResponse response = client.Execute(req, top_session);


        if (response != null && response.Result != null)
        {
            rs.error_info = "";
            rs.error_no = "0";
            rs.data = response.Result;
        }
        else
        {
            rs.error_info = "接口出錯:" + response.ErrMsg;
            rs.error_no = "1";
        }

        return rs;
    }

    public TopFoodSort QueryFoodSort()
    {
        TopFoodSort model = new TopFoodSort();
        apiResultInfo rs = CallServer(0, "");
        if (rs.error_no == "0")
        {
            model = JsonConvert.DeserializeObject<TopFoodSort>(rs.data.ToString());
            if (model == null)
            {
                model = new TopFoodSort();
                model.cates = new List<CatesItem>();
            }
            model.msg = "";
        }
        else
        {
            model.msg = rs.error_info;
        }

        return model;
    }

    /// <summary>
    /// 刪除分類
    /// </summary>
    /// <param name="shopid"></param>
    /// <param name="Top_sort_cids">多個用逗號分開</param>
    /// <returns></returns>
    public apiResultInfo DelFoodSort(string Top_sort_cids)
    {
        TopFoodSort add = new TopFoodSort();
        add.cates = new List<CatesItem>();
        foreach (var sortid in Top_sort_cids.Split(','))
        {
            CatesItem item = new CatesItem();
            item.cid = sortid;
            add.cates.Add(item);
        }

        string data = JsonConvert.SerializeObject(add);
        apiResultInfo rs = CallServer(3, data);

        return rs;
    }


    /// <summary>
    /// 添加一個分類
    /// </summary>
    /// <param name="shopid"></param>
    /// <param name="addsort"></param>
    /// <returns></returns>
    public apiResultInfo CreateOneFoodSort(EFoodSortInfo addsort)
    {
        IList<EFoodSortInfo> addsorts = new List<EFoodSortInfo>();
        addsorts.Add(addsort);

        return CreateFoodSortS(addsorts);
    }

    /// <summary>
    /// 添加一個分類
    /// </summary>
    /// <param name="shopid"></param>
    /// <param name="addsort"></param>
    /// <returns></returns>
    public apiResultInfo CreateFoodSortS(IList<EFoodSortInfo> addsorts)
    {
        TopFoodSort add = new TopFoodSort();
        add.cates = new List<CatesItem>();

        foreach (var addsort in addsorts)
        {
            CatesItem item = new CatesItem();
            item.name = addsort.SortName;
            item.order = 100000 - addsort.Jorder; //這裏用10000-排序得到新的排序,是因爲系統裏是從降序,淘點點是升序
            add.cates.Add(item);
        }


        string data = JsonConvert.SerializeObject(add);
        apiResultInfo rs = CallServer(1, data);

        return rs;
    }

}
FoodSortTopAPI

 

using Hangjing.Common;
using Hangjing.Model;
using Hangjing.SQLServerDAL;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Top.Api;
using Top.Api.Request;
using Top.Api.Response;

/// <summary>
/// 淘寶商品接口
/// </summary>
public class FoodTopAPI : baseTopAPI
{
    public FoodTopAPI(int shopid)
        : base(shopid)
    {

    }


    public apiResultInfo AddFood(EFoodInfo food, long syssortid, string shopsortid)
    {
        apiResultInfo rs = new apiResultInfo();
        if (TaoBaoId == 0)
        {
            rs.error_info = "top_session,或者淘寶商家編號未設置未設置";
            rs.error_no = "1";
            return rs;
        }

        ITopClient client = new DefaultTopClient(serverurl, appkey, appsecret);
        WaimaiItemAddRequest req = new WaimaiItemAddRequest();
        req.Title = food.Name;
        req.Price = food.Price.ToString();
        req.Oriprice = food.Price.ToString();
        req.Quantity = 9999L;
        req.Picurl = food.Picture.Length == 0 ? SectionProxyData.GetSetValue(39):food.Picture;
        req.Goodsno = "";
        req.Auctionstatus = 0L;
        req.Limitbuy = 0L;
        req.Categoryid = syssortid;
        req.Auctiondesc = food.Introduce;
        req.Shopids = TaoBaoId.ToString();
        req.Categoryids = shopsortid;

        WaimaiItemAddResponse response = client.Execute(req, top_session);
        if (response != null && response.Result != null)
        {
            rs.error_info = "";
            rs.error_no = "0";
            rs.data = response.Result;
            rs.topFoodID = response.Result.ResultData;

        }
        else
        {
            rs.error_info = "接口出錯:" + response.ErrMsg + "(" + response.ErrCode + ")";
            rs.error_no = "1";

            HJlog.toLog("AddFood錯誤:" + rs.error_info);
        }

        return rs;
    }

    public apiResultInfo AddFood(int foodid, long syssortid, string shopsortid)
    {
        EFoodInfo addfood = new EFood().GetModel(foodid);
        return AddFood(addfood, syssortid, shopsortid);
    }


    /// <summary>
    /// 操作商品
    /// </summary>
    /// <param name="ids">待操作寶貝id,多個以英文逗號分隔</param>
    /// <param name="operate">操作類型(1上架2下架3刪除)</param>
    /// <returns></returns>
    public void operateFood(string ids, int operate)
    {
        int maxsize = 20;//淘點點一次能刪除20個商品

        string reqids = "";
        string[] foodids = ids.Split(',');
        if (foodids.Length > maxsize)
        {    
            for (int i = 0; i < foodids.Length; i++)
            {
                reqids += foodids[i] + ",";
                if (i % (maxsize -1) == 0 && i > 0)
                {
                    operateFoodCallServer(WebUtility.dellast(reqids),operate);
                    reqids = "";
                }
            }
        }
        if (reqids != "")
        {
            operateFoodCallServer(WebUtility.dellast(reqids), operate);
        }




    }

    /// <summary>
    /// 操作商品
    /// </summary>
    /// <param name="ids">待操作寶貝id,多個以英文逗號分隔</param>
    /// <param name="operate">操作類型(1上架2下架3刪除)</param>
    /// <returns></returns>
    public apiResultInfo operateFoodCallServer(string ids, int operate)
    {
        apiResultInfo rs = new apiResultInfo();
        ITopClient client = new DefaultTopClient(serverurl, appkey, appsecret);
        WaimaiItemOperateRequest req = new WaimaiItemOperateRequest();

        req.Ids = ids;
        req.O = operate;
        WaimaiItemOperateResponse response = client.Execute(req, top_session);

        if (response != null && response.BatchOperateResult != null)
        {
            rs.error_info = "";
            rs.error_no = "0";
            rs.data = response.BatchOperateResult;
        }
        else
        {
            rs.error_info = "接口出錯:" + response.ErrMsg + "(" + response.ErrCode + ")";
            rs.error_no = "1";

            HJlog.toLog("operateFood錯誤:" + rs.error_info);
        }


        return rs;
    }

    /// <summary>
    /// 查詢商品,如果keyword爲空,就不加此參數
    /// </summary>
    /// <param name="keyword"></param>
    /// <returns></returns>
    public List<Top.Api.Domain.TopAuction> queryFood(string keyword)
    {
        ITopClient client = new DefaultTopClient(serverurl, appkey, appsecret);
        WaimaiItemlistGetRequest req = new WaimaiItemlistGetRequest();
        req.Shopid = TaoBaoId;
        req.SalesStatus = 0L;
        if (keyword != "")
        {
            req.Keyword = keyword;
        }

        req.PageNo = 1L;
        req.PageSize = 200L;
        req.Fields = "itemid,title,price,oriprice,goods_no,auction_desc,pic_url,category_id";
        WaimaiItemlistGetResponse response = client.Execute(req, top_session);

        if (response != null)
        {
            long total_results = response.TotalResults;
            return response.DataList;
        }
        return null;
    }
}
FoodTopAPI

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using Hangjing.Model;
using Hangjing.SQLServerDAL;
using Hangjing.DBUtility;
using System.Data;
using Hangjing.Common;

/// <summary>
/// 商品分類同步
/// </summary>
public class FoodSortSync
{
    FoodSortTopAPI sortapid = null;
    public FoodSortSync(int shopid)
    {
        sortapid = new FoodSortTopAPI(shopid);
    }

    /// <summary>
    /// 從淘點點同步到系統
    /// </summary>
    /// <returns></returns>
    public apiResultInfo SyncFromTop()
    {
        TopFoodSort Topsorts = sortapid.QueryFoodSort();
        string sql = " DELETE dbo.EFoodSort WHERE TogoNUm =  "+sortapid.shopid;
        WebUtility.excutesql(sql);

        IList<DBEFoodSortInfo> websorts = new List<DBEFoodSortInfo>();

        foreach (var topsort in Topsorts.cates)
        {
            DBEFoodSortInfo websort = new DBEFoodSortInfo();
            websort.SortName = topsort.name;
            websort.JOrder = 10000 - topsort.order;
            websort.TogoNUm = sortapid.shopid;
            websort.topsortid = topsort.cid;
            websorts.Add(websort);

        }

        DataTable dt = CollectionHelper.ConvertTo(websorts, "EFoodSort");

        SQLHelper.SqlBulkCopyData(dt);  


        return null;
    }

    /// <summary>
    /// 上傳菜單到口碑
    /// </summary>
    /// <returns></returns>
    public apiResultInfo Upload()
    {
        TopFoodSort Topsorts = sortapid.QueryFoodSort();
        IList<EFoodSortInfo> Sysorts = new EFoodSort().GetListByTogoNum(sortapid.shopid);

        //1,刪除系統中沒有,而淘寶中有的分類
        string notinsyssortids = "";
        foreach (var topsort in Topsorts.cates)
        {
            if (Sysorts.Where(a => a.SortName == topsort.name).ToList().Count == 0)
            {
                notinsyssortids += topsort.cid + ",";
            }
        }
        notinsyssortids = WebUtility.dellast(notinsyssortids);
        if (notinsyssortids != "")
        {
            sortapid.DelFoodSort(notinsyssortids);
        }

        //添加系統中有,而淘寶中沒有的
        IList<EFoodSortInfo> notintopsorts = new List<EFoodSortInfo>();
        foreach (var syssort in Sysorts)
        {
            if (Topsorts.cates.Where(a => a.name == syssort.SortName).ToList().Count == 0)
            {
                notintopsorts.Add(syssort);
            }
        }

        if (notintopsorts.Count > 0)
        {
            sortapid.CreateFoodSortS(notintopsorts);
        }

        return null;
    }
}
FoodSortSync

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using Hangjing.Model;
using Hangjing.SQLServerDAL;
using System.Data;
using Hangjing.DBUtility;
using Hangjing.Common;

/// <summary>
/// 商品同步
/// </summary>
public class FoodSync
{
    FoodTopAPI api = null;
    public FoodSync(int shopid)
    {
        api = new FoodTopAPI(shopid);
    }

    /// <summary>
    /// 從淘點點同步菜單
    /// </summary>
    /// <returns></returns>
    public apiResultInfo SyncFromTop()
    {
        List<Top.Api.Domain.TopAuction> Topfoods = api.queryFood("");

        IList<EFoodSortInfo> websorts = new EFoodSort().GetListByTogoNum(api.shopid);

        string sql = "  DELETE dbo.EFood WHERE TogoNum = " + api.shopid;
        WebUtility.excutesql(sql);

        IList<DBEFoodInfo> webfoods = new List<DBEFoodInfo>();

        foreach (var topfood in Topfoods)
        {
            DBEFoodInfo food = new DBEFoodInfo();
            food.FoodID = 0;
            food.Name = topfood.Title;
            food.Picture = topfood.PicUrl;
            food.FoodType = 0;
            foreach (var websort in websorts)
            {
                if (topfood.CategoryId.ToString() == websort.topsortid)
                {
                    food.FoodType = websort.SortID;
                    break;
                }
            }

            food.Price = Convert.ToDecimal(topfood.Price);
            food.Introduce = topfood.AuctionDesc;
            food.Discount = 10;
            food.TogoNum = api.shopid;
            food.Total = 0;
            food.IsDelete = 0;
            food.WeekDay = "";
            food.istuan = 0;
            food.nprice = food.Price;
            food.allnum = 0;
            food.joinnum = 0;
            food.salecount = 0;
            food.PackageFree = 0;
            food.IstuanInve = 0;

            webfoods.Add(food);
        }

        DataTable dt = CollectionHelper.ConvertTo(webfoods, "EFood");

        SQLHelper.SqlBulkCopyData(dt);

        return null;
    }

    /// <summary>
    /// 上傳菜單 
    /// </summary>
    /// <returns></returns>
    public apiResultInfo Upload()
    {
        List<Top.Api.Domain.TopAuction> Topfoods = api.queryFood("");
        IList<EFoodInfo> Sysorts = new EFood().GetList(1000, 1, " IsDelete = 0 and TogoNum=" + api.shopid, "Total", 1);

        //1,刪除系統中沒有,而淘寶中有的分類
        string notinsyids = "";
        foreach (var topsort in Topfoods)
        {
            if (Sysorts.Where(a => a.Name == topsort.Title).ToList().Count == 0)
            {
                notinsyids += topsort.ItemId + ",";
            }
        }
        notinsyids = WebUtility.dellast(notinsyids);
        if (notinsyids != "")
        {
            api.operateFood(notinsyids, 3);
        }

        FoodSortTopAPI sortapi = new FoodSortTopAPI(api.shopid);
        TopFoodSort Topsorts = sortapi.QueryFoodSort();

        //添加系統中有,而淘寶中沒有的
        foreach (var syssort in Sysorts)
        {
            if (Topfoods.Where(a => a.Title == syssort.Name).ToList().Count == 0)
            {
                foreach (var tsort in Topsorts.cates)
                {
                    if (tsort.name == syssort.SortName)
                    {
                        apiResultInfo rs = api.AddFood(syssort, Convert.ToInt64(syssort.Weekday), tsort.cid);
                        if (rs.error_no == "0")
                        {
                            WebUtility.excutesql("UPDATE dbo.EFood SET topFoodID = '"+rs.topFoodID+"' WHERE FoodID = "+ syssort.FoodID);
                        }
                        break;
                    }
                }
            }
        }

        return null;
    }
}
FoodSync

 

 

批量營業與歇業口碑商家

   口碑的商家有這樣的一個算是要求吧:如果商家在營業中,一天內多次拒單,或者超時不接單,會讓你停業整改一天;再則,口碑的商家後臺沒有批量營業與歇業店鋪的功能(想不通是爲什麼....)天氣晴朗,配送高效,訂單自然是多多益善,少數實在不能配送的,與用戶友好協商,讓他取消,多數還是非常理解的;但遇到打雷、颳風、下雨....等惡劣天氣時,訂單肯定是一增再增,配送效率一降再降,這時,不能配送的訂單可能佔了很大的比重,再一個個去溝通,這個成本就非常高了,關掉部分店鋪是唯一有效的方法,但等你一個個去口碑商家後臺關店時,訂單已經堆積成山了,投訴也一個接一個的....不生在其中 不知其中苦,還是看代碼吧,主要就是調用接口,沒有太多可說的!

    

 /// <summary>
    /// 商戶營業 返回:成功:0,失敗:1
    /// </summary>
    public string shopOpen(string shopid, string sessionkey)
    {
        string appkey = "";
        string appsecret = "";
        string top_session = "";
        IList<taobaoAPIAcountInfo> apis = SectionProxyData.GettaobaoAPIAcountList();
        foreach (var item in apis)
        {
            if (item.hovepic == sessionkey)
            {
                top_session = item.hovepic;
                appsecret = item.pic;
                appkey = item.classname;
                break;
            }
        }

        //3.生成url
        string url = "http://gw.api.taobao.com/router/rest?";//線上環境: http://gw.api.taobao.com/router/rest  測試環境: http://gw.sandbox.taobao.com/router/rest


        ITopClient client = new DefaultTopClient(url, appkey, appsecret, "json");
        WaimaiShopOpenRequest req = new WaimaiShopOpenRequest();
        req.Shopid = Convert.ToInt64(shopid);
        WaimaiShopOpenResponse response = client.Execute(req, top_session);

        string rs = "1";

        if (response != null)
        {
            rs = response.RetCode; ;
        }

        return rs;
    }
shopOpen

 

 客戶端調用如下,使用 BackgroundWorker 響應操作是否完成。

/// <summary>
    /// 歇業
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void offline_Click(object sender, EventArgs e)
    {
      
        BackgroundWorker bgw;
        bgw = new BackgroundWorker();
        bgw.WorkerSupportsCancellation = true;
        bgw.WorkerReportsProgress = true;

        bgw.DoWork += new DoWorkEventHandler(offline);
        bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);

        bgw.RunWorkerAsync();

    }

    /// <summary>
    /// 歇業
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void offline(object sender, DoWorkEventArgs e)
    {
        try
        {
            string IdList = this.hidDels.Value;
            IList<shopserverInfo> shops = dal.GetList(100, 1, "id in (" + IdList + ")", "id", 0);
            foreach (var item in shops)
            {
                if (new TaoBaoAPI().shopClose(item.Status.ToString(), item.Parentid) == "0")
                {
                    string sql = "UPDATE dbo.shopserver SET Depth = 0 WHERE id = "+ item.ID;
                    WebUtility.excutesql(sql);
                }
            }

        }
        catch (Exception ee)
        {
            HJlog.toLog(ee.ToString());
        }

    }
客戶端調用

 

 

接收點點送推送訂單

   點點送,其實是口碑官方配送的名稱,後臺也是對接多個配送商,商家選擇某個配送商配送後,訂單就自動通知到相應配送商,也就配送家的管理系統,可以看訂單,管理人員,及相關報表,和配送員app。如果直接用他們提供的,也就沒有下文了,具體原因前文已有說明,這裏就不多說了。

  對接主要有發下幾個步驟:

      1,申請應用

      2,申請點點送權限包

  3,訂閱相關消息

  4,消息授權接口調用

      5,代碼實現接收消息

      6,訂單操作相關接口調用

      具體可參考如下網址 http://open.taobao.com/doc2/detail.htm?articleId=101663&docType=1&treeId=2

     

      代碼方面,也是簡單的封裝了下,接收消息程序以windows service爲宿主,隨服務啓動。

      MainService.cs 創建,啓動服務, 監聽訂單消息,

    

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.ServiceProcess;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Threading;
using System.ServiceModel;
using Hangjing.Commond;

namespace Hangjing.JobServer
{
    partial class MainService : ServiceBase
    {
        MessageListener Listener = new MessageListener();

        public MainService()
        {
            InitializeComponent();
           
        }

        protected override void OnStart(string[] args)
        {
            try
            {
                Listener.Listen();
            }
            catch (Exception ex)
            {
                Hangjing.AppLog.AppLog.Info("啓動失敗:" + ex);
                throw;
            }

            Hangjing.AppLog.AppLog.Info("啓動成功");
        }

        protected override void OnStop()
        {
            base.OnStop();
        }

        protected override void OnShutdown()
        {
            base.OnShutdown();
        }

    }


}
MainService.cs

 

      MessageListener.cs 監聽訂單消息

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Top.Tmc;

namespace Hangjing.Commond
{
    /// <summary>
    /// 淘寶消息監聽器
    /// </summary>
    public class MessageListener
    {
        public MessageListener()
        {

        }

        public void Listen()
        {
            TmcClient client = new TmcClient(CacheHelper.appkey, CacheHelper.secret, "default");
            client.OnMessage += (s, e) =>
            {
                try
                {
                    Hangjing.AppLog.AppLog.Info("msg:\r\n" + e.Message.Content + "\r\n" + e.Message.Topic);

                    MessageHandler hanlder = new MessageHandler(e.Message.Topic, e.Message.Content);

                }
                catch (Exception exp)
                {
                    Hangjing.AppLog.AppLog.Info("error:\r\n" + exp);
                    e.Fail(); // 消息處理失敗回滾,服務端需要重發  
                }
            };
            client.Connect("ws://mc.api.taobao.com/");
        }
    }
}
MessageListener.cs

 

      MessageHandler.cs 反射機制處理消息報文。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

using Newtonsoft.Json;
using System.Text.RegularExpressions;
using Hangjing.SQLServerDAL;
using Hangjing.Model;
using Hangjing.Common;
using Top.Tmc;
using Top.Api;
using Top.Api.Response;
using Top.Api.Request;

namespace Hangjing.Commond
{
    /// <summary>
    /// 消息處理類
    /// </summary>
    public class MessageHandler
    {
        /// <summary>
        /// 消息名稱
        /// </summary>
        public string Topic
        {
            set;
            get;
        }

        /// <summary>
        /// 消息內容
        /// </summary>
        public string Content
        {
            set;
            get;
        }

        /// <summary>
        /// 返回信息
        /// </summary>
        public string replaymsg
        {
            set;
            get;
        }


        public MessageHandler(string _Topic, string _Content)
        {
            Topic = _Topic;
            Content = _Content;

            DynamicMethod();
        }

        /// <summary>
        /// 動態調用方法
        /// </summary>
        private void DynamicMethod()
        {
            if (CacheHelper.goodTopics.Contains(Topic))
            {
                //獲取方法的實例  非靜態 需要Public訪問權限 忽略大小寫
                MethodInfo methodInfo = this.GetType().GetMethod(Topic, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
                if (methodInfo != null)
                {
                    //調用方法
                    methodInfo.Invoke(this, null);
                }
                else
                {
                    Hangjing.AppLog.AppLog.Error(string.Format("沒有找到方法{0}", Topic));
                }
            }
            else
            {
                Hangjing.AppLog.AppLog.Error("未處理的消息:" + Topic);
            }
        }

        /// <summary>
        /// 庫存變化
        /// </summary>
        public void taobao_item_ItemStockChanged()
        {

        }

        /// <summary>
        /// 點點送訂單通知消息
        /// </summary>
        public void taobao_waimai_OrderDispatch()
        {
           
               。。。

            }
        }


        /// <summary>
        /// 買家取消訂單
        /// </summary>
        public void taobao_waimai_OrderClose()
        {
            。。。
        }
        /// <summary>
        /// 解析返回的座標信息 [0]經度,[1]緯度
        /// 座標信息: LngLatAlt{longitude=120.02165, latitude=30.27919, altitude=NaN}
        /// </summary>
        /// <param name="LngLatAlt"></param>
        /// <returns></returns>
        public string[] ParseLatLng(string LngLatAlt)
        {
            string regexstr = @"[a-zA-Z={}]";   //最後的結果:120.02165, 30.27919, 
            string content = Regex.Replace(LngLatAlt, regexstr, string.Empty, RegexOptions.IgnoreCase);

            return content.Split(',');
        }

    }
}
MessageHandler.cs

 

   另外,關於訂單操作,如指定配送員取件、妥投、上傳座標等,按文檔,調用接口就完成了,基本沒什麼可說的。

 

結語

   關於口碑相關接口的介紹就到這裏了,基本都是調用封裝好的方法,技術上沒有太多可說的,他們有很多接口,調用方法基本是一致的,如果應用的好,還是會有不少好處的,這個誰用誰知道!寫得不好的地方,或者有誤的地方,非常熱情的歡迎大家指出,也希望能對大家有所幫助。當然了,寫個文章還有一個美好的願望:希望美團,餓了麼可以推出關於團隊訂單的相關接口(也有可能有接口,只是不給我們申請....)訂單還是您們的訂單,只是多了一個地方顯示,當然,這裏多了數據泄露的風險,但是總是有辦法降低風險的。還是那句話:大家好,纔是真的好!

 

       成爲一名優秀的程序員!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章