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

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

经过分析,拿到了几个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(, , )); // 当地时区
DateTime dt = startTime.AddSeconds(unixTimeStamp);
var a = dt - DateTime.Now; return Math.Round(a.TotalHours, );
}
}

再类库下创建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 = ;// 总开团数量
var kaituan = GetKaiTuanInfo(goodId);
total = kaituan.total;
List<KaiTuan> groups = new List<KaiTuan>();
int maxNoKaituan = ;//获取拼团
int noKaituan = ;//获取拼团,返回的数据中没有新的拼团则+1
//获取开团信息存放集合里面
AddRange(groups, kaituan, mallId, goodId, ref noKaituan); //开团数量大于5就分页循环
if (kaituan.total > )
{
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 == )
{
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 == )
{
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 = ;
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 <= )
{
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; } = "";
[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

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

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

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

返回总目录

9、ABPZero系列教程之拼多多卖家工具 拼团提醒类库封装的更多相关文章

  1. 12、ABPZero系列教程之拼多多卖家工具 拼团提醒功能登录拼多多实现

    上篇文章已经完成了整个拼多多拼团提醒功能,本篇继续完成拼多多帐号登录,拼多多帐号登录的目的是为了获取拼团商品的SKU和订单号,便于商家备货. 以下是拼多多官方的后台登录,要实现的功能并不是直接在这里登 ...

  2. 10、ABPZero系列教程之拼多多卖家工具 拼团提醒逻辑功能实现

    上篇文章已经封装好了类库,现在继续实现功能,在ABPZero框架的基础上来实现一个完整的功能. Redis缓存 编写功能前先在本机安装好Redis,需要用到Redis做缓存,以下分享2个Windows ...

  3. 11、ABPZero系列教程之拼多多卖家工具 拼团提醒功能页面实现

    上一篇讲解了拼团提醒逻辑功能实现,现在继续实现页面功能. Core项目 打开AbpZeroTemplate-zh-CN.xml语言文件,在末尾添加如下代码: 文件路径:D:\abp version\a ...

  4. 1、ABPZero系列教程之拼多多卖家工具 前言

    此系列文章围绕着拼多多卖家工具来介绍ABPZero的使用,内容包括手机登录.手机注册.拼团提醒.微信公众号绑定帐号.有拼团发送消息到微信公众号(只要关注过微信公众号并已绑定系统帐号). 学习此系列必备 ...

  5. 2、ABPZero系列教程之拼多多卖家工具 更改数据库为Mysql

    因为要部署项目到云服务器,不想在服务器上装SqlServer,所以需要把项目改为Mysql. 项目初始化 1.下载项目压缩包,前面文章已经说到,可以加群到群文件里下载.解压缩下载的项目源码,使用VS2 ...

  6. 4、ABPZero系列教程之拼多多卖家工具 集成短信发送模块

    ABPZero并没有手机短信发送功能,现在我们来集成一个,为后面注册.登录作铺垫. 阿里云短信服务 首先需要在阿里云开通短信服务,连接地址 开通后,在签名管理中添加一个签名 在模板管理中添加一个模板, ...

  7. 7、ABPZero系列教程之拼多多卖家工具 修改注册功能

    本篇开始进入重头戏,之前的几篇文章都是为了现在的功能作准备.前面教程已经讲到修改User表结构,接下来就需要修改注册逻辑代码. 注册页面 修改Register.cshtml,备注如下代码: 文件路径: ...

  8. 13、ABPZero系列教程之拼多多卖家工具 微信公众号开发前的准备

    因为是开发阶段,我需要在本地调试,而微信开发需要配置域名,这样natapp.cn就有了用武之地,应该说natapp就是为此而生的. natapp.cn是什么 这是一个内网映射的网站,支持微信公众号.小 ...

  9. 3、ABPZero系列教程之拼多多卖家工具 项目修改及优化

    本篇内容杂而简单,不需要多租户.不需要多语言.使用MPA(多页面).页面加载速度提升…… 刚登录系统会看到如下界面,这不是最终想要的效果,以下就一一来修改. 不需要多租户 AbpZeroTemplat ...

随机推荐

  1. MPSOC之3——centos环境配置及petalinux安装及使用

    ubuntu虽然能正常安装,但是build时会出现闪退情况,闪退后一切归零,没啥错误提示,改用centos来安装petalinux. 0.环境 vmware pro 14,centos 7.3 pet ...

  2. angular过滤器基本用法

    1.过滤器主要用于数据的筛选,可以直接在模板使用 语法: {{expression | filter}} {{expression | filter | filter2}} {{expression ...

  3. Jmeter接口测试使用beanshell断言json返回

    一般情况下响应断言就能解决很多问题,但是返回复杂的json时就需要用到beanshell断言. 举个例子 免费的接口API www.sojson.com/api/beian/sojson.com ho ...

  4. 【CSS3】动画

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  5. 【CSS3】文本属性

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  6. iOS 蓝牙开发资料记录

    一.蓝牙基础认识:   1.iOS蓝牙开发:  iOS蓝牙开发:蓝牙连接和数据读写   iOS蓝牙后台运行  iOS关于app连接已配对设备的问题(ancs协议的锅)          iOS蓝牙空中 ...

  7. 云储存第三方--阿里云OSS VS 又拍云USS

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Helvetica Neue"; color: #454545 } p. ...

  8. [置顶] Xamarin android沉浸式状态栏

    虽然关于android "沉浸式"状态栏有很多博客介绍过,从小菜到大神无一例外.我第一次看到这种"沉浸"式的效果我也以为真的是这么叫,然而根本不是这么回事,完全 ...

  9. Android java.io.FileNotFoundException:*** (Permission denied)

    自从离开上海来到杭州之后,陆续接触了Android,Python,C++,OpenCV,最为一个新人来说,一路上遇到了很多坑,幸运的是 这互联网的强大(大傻子我还是蛮喜欢的哈),一路填填补补总算走了下 ...

  10. solr 的 field, copyfield ,dynamic field

    Field: Field就是一个字段,定义一个Field很简单: <field name="price" type="sfloat" indexed=&q ...