zoukankan      html  css  js  c++  java
  • 9、ABPZero系列教程之拼多多卖家工具 拼团提醒类库封装

      本篇开始正式做功能,我在开发拼团提醒之前,拼多多并没有放出拼团人数不足就提醒卖家的功能。

    有这个想法主要来源于朋友的抱怨,我想这应该是大部分卖家的心声吧。

    经过分析,拿到了几个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

    通过以上连接可以查询拼多多商品信息,接着随便点入一个商品,点击“进店逛逛”,如下图所示:

    进来之后就可以看到地址栏就有店铺编号,如下图所示:

     其它几个方法测试类似,就不一一说明。

     返回总目录

  • 相关阅读:
    Tomcat 配置和springframework MVC配置简介
    Java监控工具、调优、调试辅助函数
    发布一个 Linux 下的 C++ 多线程库
    《程序中的日期与时间》第一章 日期计算
    《多线程服务器的适用场合》例释与答疑
    Muduo 网络编程示例之零:前言
    muduo 与 boost asio 吞吐量对比
    Muduo 网络编程示例之二:Boost.Asio 的聊天服务器
    计算机图书赠送
    muduo 与 libevent2 吞吐量对比
  • 原文地址:https://www.cnblogs.com/shensigzs/p/8302521.html
Copyright © 2011-2022 走看看