本篇開始正式做功能,我在開發拼團提醒之前,拼多多並沒有放出拼團人數不足就提醒賣家的功能。 有這個想法主要來源於朋友的抱怨,我想這應該是大部分賣家的心聲吧。 經過分析,拿到了幾個api,不要問我api怎麼拿到的,這不是本系列的內容。 介面1:http://apiv4.yangkeduo.com/mal ...
本篇開始正式做功能,我在開發拼團提醒之前,拼多多並沒有放出拼團人數不足就提醒賣家的功能。
有這個想法主要來源於朋友的抱怨,我想這應該是大部分賣家的心聲吧。
經過分析,拿到了幾個api,不要問我api怎麼拿到的,這不是本系列的內容。
介面1:http://apiv4.yangkeduo.com/mall/{0}/info?pdduid=0(傳入店鋪編號,可以獲取店鋪資料)
介面2:http://apiv4.yangkeduo.com/v2/mall/{0}/goods?page=1&size=500&sort_type=PRIORITY&pdduid=0(傳入店鋪編號,可以拿到店鋪商品資料,拼多多限制最多獲取500個商品)
介面3:http://apiv2.yangkeduo.com/v2/goods/{0}/local_group(傳入商品id,可以獲取拼團信息)
有了這幾個api,拼團提醒功能就不在話下,接下來講解實現過程。
建立新項目
在解決方案下建立PddTool項目,目的是把拼多多相關業務邏輯以專門的一個類庫來實現。
在解決方案右鍵選擇“管理解決方案的 NuGet程式包”,搜索安裝如下NuGet包,註意版本號。
創建目錄,先創建好幾個目錄,如下圖所示:
在Response目錄下新建MallEntity類,代碼如下:
public class MallEntity { /// <summary> /// /// </summary> public int mall_id { get; set; } /// <summary> /// 木子緣 /// </summary> public string mall_name { get; set; } /// <summary> /// /// </summary> public string logo { get; set; } /// <summary> /// /// </summary> public int goods_num { get; set; } /// <summary> /// 小店主要經營時尚潮流女裝,品質女裝,質量有保障! /// </summary> public string mall_desc { get; set; } /// <summary> /// /// </summary> public string company_phone { get; set; } /// <summary> /// /// </summary> public string offline_note { get; set; } /// <summary> /// /// </summary> public int chat_enable { get; set; } /// <summary> /// 廣東廣州天河區沙太路牛利崗大街6巷28號 /// </summary> public string refund_address { get; set; } /// <summary> /// /// </summary> public int score_avg { get; set; } /// <summary> /// /// </summary> public int staple_id { get; set; } /// <summary> /// /// </summary> public int mall_sales { get; set; } /// <summary> /// /// </summary> public int region_emergent { get; set; } /// <summary> /// /// </summary> public int is_open { get; set; } /// <summary> /// /// </summary> public int status { get; set; } /// <summary> /// /// </summary> public int wms_id { get; set; } /// <summary> /// 店鋪優惠券,不需要 /// </summary> //public List<string> mall_coupons { get; set; } /// <summary> /// /// </summary> public int server_time { get; set; } }
這是請求api之後,根據返回json數據所生成的類,
http://www.bejson.com/convert/json2csharp/(通過這個工具,可以把json轉C#實體類)
再同目錄下新建ProductEntity類,代碼如下:
/// <summary> /// 拼團 /// </summary> public class Group { /// <summary> /// 拼團人數 /// </summary> public int customer_num { get; set; } /// <summary> /// 拼團價格÷100 /// </summary> public int price { get; set; } } public class Goods_listItem { /// <summary> /// 單買價÷100 /// </summary> public int normal_price { get; set; } /// <summary> /// 已拼數量 /// </summary> public int cnt { get; set; } /// <summary> /// 小圖連接 /// </summary> public string thumb_url { get; set; } /// <summary> /// /// </summary> public int event_type { get; set; } /// <summary> /// 市場價÷100 /// </summary> public int market_price { get; set; } /// <summary> /// 【木子緣】毛呢外套女中長款韓版2017新款寬鬆顯廋修身學生百搭大碼加厚外套bf過膝氣質呢子大衣 /// </summary> public string goods_name { get; set; } /// <summary> /// 商品id /// </summary> public int goods_id { get; set; } /// <summary> /// 【木子緣】毛呢外套女中長款韓版2017新款寬鬆顯廋修身學生百搭大碼加厚外套bf過膝氣質呢子大衣 /// </summary> public string short_name { get; set; } /// <summary> /// /// </summary> public Group group { get; set; } /// <summary> /// /// </summary> public string country { get; set; } /// <summary> /// 商品主圖 /// </summary> public string image_url { get; set; } /// <summary> /// 高清圖 /// </summary> public string hd_thumb_url { get; set; } /// <summary> /// /// </summary> public int is_app { get; set; } } public class ProductEntity { /// <summary> /// /// </summary> public List<string> recommend_subject { get; set; } /// <summary> /// /// </summary> public int server_time { get; set; } /// <summary> /// /// </summary> public List<Goods_listItem> goods_list { get; set; } /// <summary> /// /// </summary> public List<string> subject_list { get; set; } }
同目錄下再創建KaiTuanEntity類,代碼如下:
public class Local_groupItem { /// <summary> /// 拼團訂單id /// </summary> public string group_order_id { get; set; } /// <summary> /// 商品id /// </summary> public string goods_id { get; set; } /// <summary> /// 城市名稱 /// </summary> public string city_name { get; set; } /// <summary> /// 昵稱 /// </summary> public string nickname { get; set; } /// <summary> /// 頭像 /// </summary> public string avatar { get; set; } /// <summary> /// /// </summary> public string expire_time { get; set; } /// <summary> /// 用戶id /// </summary> public string uid { get; set; } } public class KaiTuanEntity { /// <summary> /// 正在拼團列表 /// </summary> public List<Local_groupItem> local_group { get; set; } /// <summary> /// /// </summary> public int server_time { get; set; } /// <summary> /// 正在拼團人數 /// </summary> public int total { get; set; } }
然後在Entities目錄下,創建KaiTuan類,代碼如下:
public class KaiTuan { /// <summary> /// 商品id /// </summary> public int Id { get; set; } /// <summary> /// 昵稱 /// </summary> public string NickName { get; set; } /// <summary> /// /// </summary> public string SKU { get; set; } /// <summary> /// 訂單號 /// </summary> public string OrderNum { get; set; } /// <summary> /// 剩餘時間 /// </summary> public double TimeLeft { get; set; } /// <summary> /// 開團單號 /// </summary> public string KaiTuanOrderNum { get; set; } }
繼續在Entities目錄下創建KaiTuanProduct類,代碼如下:
/// <summary> /// 開團商品 /// </summary> public class KaiTuanProduct { /// <summary> /// 商品id /// </summary> public int GoodId { get; set; } /// <summary> /// 商品名稱 /// </summary> public string Name { get; set; } /// <summary> /// 商品圖片 /// </summary> public string Img { get; set; } /// <summary> /// 開團人數 /// </summary> public int KaiTuanCount { get; set; } }
再類庫下創建DateTimeHelper類,代碼如下:
public class DateTimeHelper { /// <summary> /// 傳入unix時間戳,計算與當前時間之間的小時數 /// </summary> /// <param name="unixTimeStamp"></param> /// <returns></returns> public static double GetHours(long unixTimeStamp) { System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // 當地時區 DateTime dt = startTime.AddSeconds(unixTimeStamp); var a = dt - DateTime.Now; return Math.Round(a.TotalHours, 1); } }
再類庫下創建MallTool類,實現幾個方法,代碼如下:
public class MallTool { /// <summary> /// 按店鋪id獲取店鋪資料 /// </summary> /// <param name="mallId"></param> public static MallEntity GetInfo(string mallId) { string url = string.Format("http://apiv4.yangkeduo.com/mall/{0}/info?pdduid=0", mallId); var client = new RestClient(url); var request = new RestRequest(Method.GET); request.AddHeader("cache-control", "no-cache"); request.AddHeader("referer", url); IRestResponse response = client.Execute(request); if (string.IsNullOrWhiteSpace(response.Content) || response.Content.Contains("mall not exists")) { throw new Exception("店鋪編號錯誤!"); } var mall = JsonConvert.DeserializeObject<MallEntity>(response.Content); return mall; } /// <summary> /// 最多拿到500個商品 /// </summary> /// <param name="mallId"></param> /// <returns></returns> public static ProductEntity GetGoods(string mallId) { string url = string.Format( "http://apiv4.yangkeduo.com/v2/mall/{0}/goods?page=1&size=500&sort_type=PRIORITY&pdduid=0", mallId); var client = new RestClient(url); var request = new RestRequest(Method.GET); request.AddHeader("cache-control", "no-cache"); request.AddHeader("referer", url); IRestResponse response = client.Execute(request); var product = JsonConvert.DeserializeObject<ProductEntity>(response.Content); return product; } /// <summary> /// 根據商品id ,獲取開團信息 /// </summary> /// <param name="goodId"></param> /// <returns></returns> public static KaiTuanEntity GetKaiTuanInfo(int goodId) { string url = string.Format("http://apiv2.yangkeduo.com/v2/goods/{0}/local_group", goodId); var client = new RestClient(url); var request = new RestRequest(Method.GET); request.AddHeader("cache-control", "no-cache"); request.AddHeader("referer", url); IRestResponse response = client.Execute(request); var content = response.Content.Replace("\\\"", "\""); content = content.Replace("\\\\", "\\").Replace("\"{", "{").Replace("}\"", "}"); var kaiTuan = JsonConvert.DeserializeObject<KaiTuanEntity>(content); return kaiTuan; } /// <summary> /// 根據商品id,獲取此商品所有開團信息 /// </summary> /// <param name="goodId"></param> /// <returns></returns> public static List<KaiTuan> GetAllKaiTuanByGoodId(int mallId, int goodId) { int total = 0;// 總開團數量 var kaituan = GetKaiTuanInfo(goodId); total = kaituan.total; List<KaiTuan> groups = new List<KaiTuan>(); int maxNoKaituan = 20;//獲取拼團 int noKaituan = 0;//獲取拼團,返回的數據中沒有新的拼團則+1 //獲取開團信息存放集合裡面 AddRange(groups, kaituan, mallId, goodId, ref noKaituan); //開團數量大於5就分頁迴圈 if (kaituan.total > 5) { while (true) { //重試了maxNoKaituan次,還是沒有新數據就退出 if (noKaituan >= maxNoKaituan) { break; } kaituan = GetKaiTuanInfo(goodId); //已獲取到的開團數>=獲取回來的開團數 就退出 if (groups.Count >= kaituan.total) { break; } AddRange(groups, kaituan, mallId, goodId, ref noKaituan); } } return groups; } /// <summary> /// 根據店鋪id,獲取所有商品的開團人數 /// </summary> /// <param name="mallId"></param> /// <returns></returns> public static List<KaiTuanProduct> GetKaiTuanList(string mallId) { var goods = GetGoods(mallId); if (goods.goods_list.Count == 0) { throw new UserFriendlyException("此店鋪商品為 0"); } List<KaiTuanProduct> kaiTuanProducts = new List<KaiTuanProduct>(); foreach (var goodsListItem in goods.goods_list) { var kaituanProduct = GetKaiTuanCountByGoodId(goodsListItem.goods_id); if (kaituanProduct == null) { continue; } kaituanProduct.Name = goodsListItem.goods_name; kaituanProduct.GoodId = goodsListItem.goods_id; kaituanProduct.Img = goodsListItem.thumb_url; kaiTuanProducts.Add(kaituanProduct); } return kaiTuanProducts; } /// <summary> ///根據商品id, 獲取開團人數 /// </summary> /// <param name="goodId"></param> public static KaiTuanProduct GetKaiTuanCountByGoodId(int goodId) { var kaituanInfo = GetKaiTuanInfo(goodId); if (kaituanInfo.total == 0) { return null; } return new KaiTuanProduct() { KaiTuanCount = kaituanInfo.total }; } public static void AddRange(List<KaiTuan> groups, KaiTuanEntity kaiTuan, int mallId, int goodId, ref int noKaituan) { bool isExist = true; int count = 0; foreach (var localGroupItem in kaiTuan.local_group) { //過濾已經存在的拼團 if (groups.Any(a => a.KaiTuanOrderNum == localGroupItem.group_order_id)) { count++; isExist = false; continue; } //過濾時間小於0的拼團 var t = DateTimeHelper.GetHours(Convert.ToInt64(localGroupItem.expire_time)); if (t <= 0) { count++; isExist = false; continue; } var item = new KaiTuan() { Id = Convert.ToInt32(localGroupItem.goods_id), KaiTuanOrderNum = localGroupItem.group_order_id, NickName = localGroupItem.nickname, TimeLeft = DateTimeHelper.GetHours(Convert.ToInt64(localGroupItem.expire_time)), }; groups.Add(item); isExist = true; } if (isExist == false && count == kaiTuan.local_group.Count) { noKaituan++; } } }
可以看到UserFriendlyException報異常,這是abp的異常類,接著解決方案再打開”管理解決方案的 NuGet程式包”,搜索:“abp”安裝。
最後項目結構如下,拼團提醒功能就封裝好了。
創建單元測試
在解決方案Tests目錄下新建單元測試項目,如下圖所示:
新建MallTool_Test類,用來測試剛剛封裝的幾個方法,代碼如下:
[TestClass] public class MallTool_Test { public string mallId { get; set; } = "1277675"; [TestMethod] public void TestGetInfo() { MallEntity result=MallTool.GetInfo(mallId); Console.WriteLine(result.mall_name); } }
下圖為調試輸出結果:
以上代碼傳入店鋪編號,獲取店鋪資料,
店鋪編號哪裡來?
http://mobile.yangkeduo.com/search_result.html?search_key=%E6%89%93%E5%BA%95%E8%A1%AB%E5%A5%B3&search_src=history&search_met=history_sort&search_met_track=history&refer_page_name=search&refer_page_id=&page_id=&sp=0&item_index=1&is_back=1
通過以上連接可以查詢拼多多商品信息,接著隨便點入一個商品,點擊“進店逛逛”,如下圖所示:
進來之後就可以看到地址欄就有店鋪編號,如下圖所示:
其它幾個方法測試類似,就不一一說明。