public string AddGoods(Shop shop, PopGoods popGoods, float buyInPrice) { if (shop.AppEnabled == false) { throw new Exception("店铺订单发货接口已禁用,无法调用相应接口操作"); } return(GetPop(shop.PopType).AddGoods(shop, popGoods, buyInPrice)); }
public DataCollectionResponse <string> AddGoods(Shop shop, PopGoods popGoods, float buyInPrice) { Dictionary <string, object> para = new Dictionary <string, object>(); para["shop"] = shop; para["popGoods"] = popGoods; para["buyInPrice"] = buyInPrice; return(DoPost <DataCollectionResponse <string> >(para)); }
public DataCollectionResponse <string> AddGoods(Shop shop, PopGoods popGoods, float buyInPrice) { try { return(new DataCollectionResponse <string>((new PopService().AddGoods(shop, popGoods, buyInPrice)))); } catch (Exception e) { throw new WebFaultException <ResponseBase>(new ResponseBase(e.Message), HttpStatusCode.OK); } }
public abstract string AddGoods(Shop shop, PopGoods popGoods, float buyInPrice);
public PopGoodsInfoViewModel(PopGoods popGoodsInfo) { this.PopGoodsInfo = popGoodsInfo; }
private List <PopGoods> QueryHtmlGoodsPage(Shop shop, int pageIndex, PopGoodsState state) { Uri goodsListPageUri = new Uri(shop.PopType == PopType.TMALL ? "https://item.manager.tmall.com/tmall/manager/table.htm" : "https://item.publish.taobao.com/taobao/manager/table.htm"); string goodsEditPageDomain = shop.PopType == PopType.TMALL ? "item.upload.tmall.com" : "item.publish.taobao.com"; string goodsEditPageUrlBase = shop.PopType == PopType.TMALL ? "https://item.upload.tmall.com/tmall/publish.htm?id=" : "https://item.publish.taobao.com/sell/publish.htm?itemId="; var goodsListPageXsrfCookieValue = CefCookieVisitor.GetCookieValues(goodsListPageUri.Host, "XSRF-TOKEN"); if (string.IsNullOrWhiteSpace(goodsListPageXsrfCookieValue)) { throw new Exception("没有找到相应XSRF-TOKEN,刷新页面重新登录"); } var goodsListPageDomainCookie = CefCookieVisitor.GetCookieValues(goodsListPageUri.Host, null); if (string.IsNullOrWhiteSpace(goodsListPageDomainCookie)) { throw new Exception("未找到域:" + goodsListPageUri.Host + " 的任何COOKIE ,刷新页面重新登录"); } var goodsEditPageCookie = CefCookieVisitor.GetCookieValues(goodsEditPageDomain, null); string goodsState = state == PopGoodsState.NONE ? "all" : (state == PopGoodsState.ONSALE ? "on_sale" : "in_stock"); var xhrdata = "jsonBody=" + MsHttpRestful.UrlEncode("{\"filter\":{},\"pagination\":{\"current\":" + pageIndex + ",\"pageSize\":20},\"table\":{\"sort\":{}},\"tab\":\"" + goodsState + "\"}", Encoding.UTF8); var header = new Dictionary <string, string>(); header.Add("X-XSRF-TOKEN", goodsListPageXsrfCookieValue.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries)[1]); var content = MsHttpRestful.SendTbData(System.Net.Http.HttpMethod.Post, goodsListPageUri, header, goodsListPageDomainCookie, xhrdata); var resp = Newtonsoft.Json.JsonConvert.DeserializeObject <TaobaoQueryGoodsListResponse>(content); List <PopGoods> goods = new List <PopGoods>(); if (resp == null || resp.success == false) { throw new Exception("返回数据错误,请点击页面分页进行验证后重新开始"); } if (resp.data.table.dataSource == null) { return(goods); } foreach (var g in resp.data.table.dataSource) { if (this.WaitGoOn() == false) { break; } //每个商品获取的时候,都有可能,登录超时或者其它问题,需要循环 PopGoods pg = null; string goodsEditPageUrl = goodsEditPageUrlBase + g.itemId; for (int i = 0; i < 5; i++) { if (this.WaitGoOn() == false) { break; } Debug.WriteLine("开始抓取商品:" + g.itemId); this.OnDownload("暂停", true, "第:" + (i + 1) + " 次下载,第:" + pageIndex + "/" + ((resp.data.pagination.total / resp.data.pagination.pageSize) + 1) + "页,第" + (goods.Count + 1) + "条商品详情", false); bool ret = QueryHtmlGoods(g, goodsEditPageUrl, goodsEditPageCookie, ref pg); if (ret == true) { goods.Add(pg); break; } } if (this.isStop == false && pg == null) { throw new Exception("抓取商品5次都为成功:" + g.itemId); } if (this.WaitGoOn() == false) { break; } //每次等待3秒,太快淘宝会返回错误 Thread.Sleep(3000); } return(goods); }
private bool QueryHtmlGoods(TaobaoQueryGoodsListResponseDataTableDataSource g, string url, string cookie, ref PopGoods popGoods) { string htmlContent = MsHttpRestful.SendTbData(System.Net.Http.HttpMethod.Get, new Uri(url), null, cookie, null); if (string.IsNullOrWhiteSpace(htmlContent)) { throw new Exception("读取商品详情返回为空:" + g.itemId); } try { if (htmlContent[0] == '{' && htmlContent.Last() == '}') { var error = Newtonsoft.Json.JsonConvert.DeserializeObject <TaobaoQueryGoodsDetailErrorResponse>(htmlContent); if (error.success == false) { if ("SYS_REQUEST_TOO_FAST".Equals(error.code, StringComparison.OrdinalIgnoreCase)) { int wait = error.data == null ? 70 : error.data.wait + 10; this.Pause(false, "程序读取商品详情过快,等待:" + wait + "秒", wait); return(false); } else { Log.Logger.Log("获取淘宝详情失败,错误信息:" + htmlContent); throw new Exception("获取淘宝详情失败,错误信息:" + error.code + "," + error.msg); } } } } catch (Newtonsoft.Json.JsonException) { } if (htmlContent.Contains("客官别急") && htmlContent.Contains("交通拥堵")) { Debug.WriteLine(DateTime.Now + "检测到返回网页操作过快"); this.Pause(false, "程序读取商品详情过快,等待:70 秒", 70); return(false); } //第一步找JS JSON 起始符 int startIndex = htmlContent.IndexOf("window.Json ="); if (startIndex < 0) { Debug.WriteLine("商品详情:" + g.itemId + ":" + htmlContent); throw new Exception("分析商品编辑页失败,未找到window.Json =:" + g.itemId); } //第二步,找JSON开始符 startIndex = htmlContent.IndexOf("{\"", startIndex); if (startIndex < 0) { Debug.WriteLine("商品详情:" + g.itemId + ":" + htmlContent); throw new Exception("分析商品编辑页失败,未找到window.Json =:之后的{\"" + g.itemId); } startIndex = htmlContent.IndexOf("{\"", startIndex); //第三步找JSON结尾字符串 int end = htmlContent.IndexOf("}}};", startIndex); if (end <= 0) { Debug.WriteLine("商品详情:" + g.itemId + ":" + htmlContent); throw new Exception("分析商品编辑页失败,未找到JSON结束符}}};" + g.itemId); } string json = htmlContent.Substring(startIndex, end + 3 - startIndex); var goodsDetail = Newtonsoft.Json.JsonConvert.DeserializeObject <TaobaoQueryGoodsDetailResponse>(json); var pg = new PopGoods { AddTime = "", CatId = g.catId, Code = goodsDetail.models.formValues.outerId, Id = g.itemId, Images = goodsDetail.models.formValues.images.Select(obj => obj.url.StartsWith("http") ? obj.url : "https:" + obj.url).ToArray(), SaleNum = g.soldQuantity_m, UpdateTime = g.upShelfDate_m.value }; //状态 pg.State = g.upShelfDate_m.status.text == "出售中" ? PopGoodsState.ONSALE : PopGoodsState.NOTSALE; pg.Title = g.itemDesc.desc.FirstOrDefault(obj => string.IsNullOrWhiteSpace(obj.href) == false).text.Trim(); //SKU foreach (var vSku in goodsDetail.models.formValues.sku) { var pSku = new PopGoodsSku { Code = vSku.skuOuterId ?? "", Id = vSku.skuId ?? "", Stock = vSku.skuStock.ToString(), Price = vSku.skuPrice.ToString("F2"), Status = PopGoodsState.ONSALE, Color = vSku.props[0].text.Trim(), Size = vSku.props[1].text.Trim(), }; if (vSku.skuImage != null && vSku.skuImage.Length > 0) { pSku.Image = vSku.skuImage[0].url; } else { pSku.Image = goodsDetail.models.formValues.saleProp.Colors.FirstOrDefault(obj => obj.text == pSku.Color).img; } if (string.IsNullOrWhiteSpace(pSku.Image)) { throw new Exception("商品SKU图片为空:" + pg.Id); } if (pSku.Image.StartsWith("http") == false) { pSku.Image = "https:" + pSku.Image; } pg.Skus.Add(pSku); } //属性 天猫 //基本属性 if (goodsDetail.models.formValues.bindProp != null) { foreach (var v in goodsDetail.models.formValues.bindProp) { string key = goodsDetail.models.bindProp.dataSource.First(obj => obj.name == v.name).label; string values = string.Join("@#@", v.values.Select(obj => obj.text)); pg.Properties.Add(new KeyValuePairClass <string, string>(key, values)); } } if (goodsDetail.models.formValues.itemProp != null) { foreach (var v in goodsDetail.models.formValues.itemProp) { string key = goodsDetail.models.itemProp.dataSource.First(obj => obj.name == v.name).label; string values = string.Join("@#@", v.values.Select(obj => obj.text)); pg.Properties.Add(new KeyValuePairClass <string, string>(key, values)); } } if (goodsDetail.models.formValues.catProp != null) { foreach (var v in goodsDetail.models.formValues.catProp) { string key = goodsDetail.models.catProp.dataSource.First(obj => obj.name == v.name).label; string values = string.Join("@#@", v.values.Select(obj => obj.text)); pg.Properties.Add(new KeyValuePairClass <string, string>(key, values)); } } pg.PopType = shop.PopType; pg.Type = goodsDetail.models.catpath.value.Split(new string[] { ">>", "》" }, StringSplitOptions.RemoveEmptyEntries)[1]; pg.ShippingCity = goodsDetail.models.formValues.location != null ? goodsDetail.models.formValues.location.value.text : goodsDetail.models.global.location.city; if (shop.PopType == PopType.TMALL && (goodsDetail.models.formValues.modularDesc == null || goodsDetail.models.formValues.modularDesc.Length < 1)) { throw new Exception("商品:" + g.itemId + " 电脑端描述为空"); } if (shop.PopType == PopType.TAOBAO && string.IsNullOrWhiteSpace(goodsDetail.models.formValues.desc)) { throw new Exception("商品:" + g.itemId + " 电脑端描述为空"); } //详情图片 pg.DescImages = ParseImages(shop.PopType == PopType.TMALL ? goodsDetail.models.formValues.modularDesc.First().content : goodsDetail.models.formValues.desc); popGoods = pg; return(true); }
public override string AddGoods(Shop shop, PopGoods popGoods, float buyInPrice) { Dictionary <string, PddRspCatTemplateProperty[]> catTemplatesCaches = new Dictionary <string, PddRspCatTemplateProperty[]>(); Dictionary <string, string> catIdCaches = new Dictionary <string, string>(); Dictionary <string, PddRspGoodsSpecItem> specColorCaches = new Dictionary <string, PddRspGoodsSpecItem>(); Dictionary <string, PddRspGoodsSpecItem> specSizeCaches = new Dictionary <string, PddRspGoodsSpecItem>(); SortedDictionary <string, string> para = new SortedDictionary <string, string>(); string id = ""; //获取对应的运费模板 var addressNode = Invoke <PddRspAddress>(shop, "pdd.logistics.address.get", para); para.Clear(); para["page_size"] = "20"; var lotemplates = Invoke <PddRspTemplate>(shop, "pdd.goods.logistics.template.get", para); if (lotemplates.logistics_template_list == null || lotemplates.logistics_template_list.Length < 1) { throw new Exception("拼多多店铺内没有运费模板"); } para.Clear(); var an = addressNode.logistics_address_list.FirstOrDefault(obj => obj.region_type == 2 && obj.region_name.Contains(popGoods.ShippingCity)); if (an == null) { throw new Exception("拼多多地址区库没有找到对应的发货地区"); } PddRspTemplateItem t = null; var tt = lotemplates.logistics_template_list.Where(obj => obj.city_id == an.id.ToString()).ToArray(); if (tt.Length < 2) { t = tt.First(); } else { t = tt.FirstOrDefault(obj => obj.template_name == "默认运费模板"); } if (t == null) { throw new Exception("拼多多店铺内没有找到对发货地区的运费模板"); } //获取商品目录 para.Clear(); para["parent_cat_id"] = "0"; var cats = Invoke <PddRspGoodsCat>(shop, "pdd.goods.cats.get", para); var nvxieRootCat = cats.goods_cats_list != null?cats.goods_cats_list.FirstOrDefault(obj => obj.cat_name == "女鞋") : null; if (nvxieRootCat == null) { throw new Exception("拼多多上没有找到 女鞋 类目"); } if (catIdCaches.ContainsKey(popGoods.Type) == false) { //获取第二级目录 para.Clear(); para["parent_cat_id"] = nvxieRootCat.cat_id; cats = Invoke <PddRspGoodsCat>(shop, "pdd.goods.cats.get", para); var typeCat = cats.goods_cats_list != null?cats.goods_cats_list.FirstOrDefault(obj => obj.cat_name == popGoods.Type) : null; if (typeCat == null) { throw new Exception("拼多多上没有找到 " + popGoods.Type + " 类目"); } //获取第三级目录 para.Clear(); para["parent_cat_id"] = typeCat.cat_id; cats = Invoke <PddRspGoodsCat>(shop, "pdd.goods.cats.get", para); var leve3Cat = cats.goods_cats_list != null?cats.goods_cats_list.FirstOrDefault() : null; if (leve3Cat == null) { throw new Exception("拼多多上没有找到第三级目录 " + popGoods.Type + " 类目"); } catIdCaches[popGoods.Type] = leve3Cat.cat_id; } string level3CatId = catIdCaches[popGoods.Type]; //获取颜色,尺码规格 if (specColorCaches.ContainsKey(popGoods.Type) == false) { para.Clear(); para["cat_id"] = level3CatId; var specs = Invoke <PddRspGoodsSpec>(shop, "pdd.goods.spec.get", para); var specColor = specs.goods_spec_list != null?specs.goods_spec_list.FirstOrDefault(obj => obj.parent_spec_name == "颜色") : null; var specSize = specs.goods_spec_list != null?specs.goods_spec_list.FirstOrDefault(obj => obj.parent_spec_name == "尺码") : null; if (specColor == null || specSize == null) { throw new Exception("拼多多上获取颜色,尺码规格失败"); } specColorCaches[popGoods.Type] = specColor; specSizeCaches[popGoods.Type] = specSize; } if (catTemplatesCaches.ContainsKey(level3CatId) == false) { //获取商品属性 para.Clear(); para["cat_id"] = level3CatId; var ct = Invoke <PddRspCatTemplate>(shop, "pdd.goods.cat.template.get", para); catTemplatesCaches[level3CatId] = ct.properties.Where(obj => string.IsNullOrWhiteSpace(obj.name) == false).ToArray(); } //生成商品属性 List <PddReqGoodsProperty> properties = new List <PddReqGoodsProperty>(); foreach (var ctp in catTemplatesCaches[level3CatId]) { //根据淘宝天猫的属性名称,找到对应拼多多名称 string taobaoName = PddGoodsPropertyMap.GetMapPropertyNameByKey(popGoods.PopType, popGoods.Type, ctp.name_alias); if (string.IsNullOrWhiteSpace(taobaoName)) { id += ctp.name_alias + " 未找到对应的淘宝属性,"; continue; } if (ctp.name_alias == "品牌" && ctp.required) { if (shop.PopShopName.Contains("旗舰店")) { properties.Add(new PddReqGoodsProperty { template_pid = ctp.id, vid = 128029, value = shop.PopShopName.Replace("旗舰店", "") }); } continue; } var taobaoProperty = popGoods.Properties.FirstOrDefault(obj => obj.Key == taobaoName); if (taobaoProperty == null) { if (ctp.required) { throw new Exception("拼多多属性:" + ctp.name_alias + " 是必须项,但没有在淘宝找到对应属性"); } else { id += "属性:" + ctp.name_alias + " 未匹配"; } continue; } string[] values = taobaoProperty.Value.Split(new string[] { "@#@" }, StringSplitOptions.RemoveEmptyEntries); foreach (var vv in values) { var v = ctp.values.FirstOrDefault(obj => MatchValue(obj.value, vv)); if (v != null) { properties.Add(new PddReqGoodsProperty { template_pid = ctp.id, vid = long.Parse(v.vid), value = v.value }); if (ctp.choose_max_num <= 1) { break; } } else { id += "属性值:" + ctp.name_alias + " 的值:" + vv + " 未匹配"; } if (properties.Count(obj => obj.template_pid == ctp.id) >= ctp.choose_max_num) { break; } } } //上传图片,拼多多不传白底图 popGoods.Images = popGoods.Images.Where(obj => obj.EndsWith(".png", StringComparison.OrdinalIgnoreCase) == false).ToArray(); string[] skuSourceImages = popGoods.Skus.Select(obj => obj.Image).Distinct().ToArray(); string[] images = UploadImage(shop, popGoods.Images); string[] descImages = UploadImage(shop, popGoods.DescImages); string[] skuImages = UploadImage(shop, skuSourceImages); //拼多多图片张数达到8张,商品分值会高些 if (images.Length < 8) { var im = new string[8]; Array.Copy(images, im, images.Length); Array.Copy(images, 0, im, images.Length, 8 - images.Length); images = im; } //生成颜色尺码规格 string[] sColors = popGoods.Skus.Select(obj => obj.Color.Trim()).Distinct().ToArray(); string[] sSize = popGoods.Skus.Select(obj => obj.Size.Trim()).Distinct().ToArray(); PddRspGoodsSpecId[] colors = new PddRspGoodsSpecId[sColors.Length]; PddRspGoodsSpecId[] sizes = new PddRspGoodsSpecId[sSize.Length]; for (int j = 0; j < sColors.Length; j++) { para.Clear(); para["parent_spec_id"] = specColorCaches[popGoods.Type].parent_spec_id; para["spec_name"] = sColors[j]; colors[j] = Invoke <PddRspGoodsSpecId>(shop, "pdd.goods.spec.id.get", para); } for (int j = 0; j < sizes.Length; j++) { para.Clear(); para["parent_spec_id"] = specSizeCaches[popGoods.Type].parent_spec_id; para["spec_name"] = sSize[j]; sizes[j] = Invoke <PddRspGoodsSpecId>(shop, "pdd.goods.spec.id.get", para); } //SKU List <PddReqSku> skus = new List <PddReqSku>(); for (int j = 0; j < popGoods.Skus.Count; j++) { var sku = new PddReqSku(); //价格 sku.multi_price = (long)(100 * (float.Parse(popGoods.Skus[j].Price) > (buyInPrice * 2) ? (float.Parse(popGoods.Skus[j].Price) / 2) : float.Parse(popGoods.Skus[j].Price))); sku.price = sku.multi_price + 100; sku.out_sku_sn = popGoods.Skus[j].Code; sku.thumb_url = skuImages[Array.IndexOf(skuSourceImages, popGoods.Skus[j].Image)]; sku.spec_id_list = string.Format("[{0},{1}]", colors[Array.FindIndex(colors, 0, o => o.spec_name == popGoods.Skus[j].Color)].spec_id, sizes[Array.FindIndex(sizes, 0, o => popGoods.Skus[j].Size.Trim() == o.spec_name)].spec_id); skus.Add(sku); } //拼装参数 para.Clear(); para["goods_properties"] = Newtonsoft.Json.JsonConvert.SerializeObject(properties); para["goods_name"] = popGoods.Title.Trim(); para["goods_type"] = "1"; para["goods_desc"] = "商品跟高,面料,尺码情况请往下滑动查看详情页面"; para["cat_id"] = level3CatId; para["country_id"] = "0"; para["market_price"] = (((int)(buyInPrice * 3)) * 100).ToString(); para["is_pre_sale"] = "false"; para["shipment_limit_second"] = (48 * 60 * 60).ToString(); para["cost_template_id"] = t.template_id.ToString(); para["customer_num"] = "2"; para["is_refundable"] = "true"; para["second_hand"] = "false"; para["is_folt"] = "true"; para["out_goods_id"] = popGoods.Code.Trim(); para["carousel_gallery"] = Newtonsoft.Json.JsonConvert.SerializeObject(images); para["detail_gallery"] = Newtonsoft.Json.JsonConvert.SerializeObject(descImages); para["sku_list"] = Newtonsoft.Json.JsonConvert.SerializeObject(skus); //第三步上传信息 var ret = Invoke <PddRspGoodsAdd>(shop, "pdd.goods.add", para); id += ret.goods_id; return(id); }
public override List <PopGoods> SearchPopGoods(Domain.Shop shop, PopGoodsState state, int pageIndex, int pageSize) { SortedDictionary <string, string> param = new SortedDictionary <string, string>(); param["page_size"] = pageSize.ToString(); param["page"] = (pageIndex + 1).ToString(); if (state != PopGoodsState.NONE) { param["is_onsale"] = state == PopGoodsState.ONSALE ? "1" : "0"; } var ret = this.Invoke <PddRspGoods>(shop, "pdd.goods.list.get", param); List <PopGoods> goods = new List <PopGoods>(); if (ret.goods_list == null || ret.goods_list == null) { return(goods); } foreach (var g in ret.goods_list) { var pg = new PopGoods { Id = g.goods_id, Title = g.goods_name, AddTime = "", UpdateTime = "", SaleNum = 0, Images = new string[] { g.thumb_url }, CatId = "", Code = "", State = g.is_onsale == "1" ? PopGoodsState.ONSALE : PopGoodsState.NOTSALE, Type = "所有", }; if (g.sku_list == null || g.sku_list.Length < 1) { continue; } foreach (var sku in g.sku_list) { if (sku.is_sku_onsale == 0) { continue; } pg.Code = sku.outer_goods_id; var psku = new PopGoodsSku { Id = sku.sku_id, Code = sku.outer_id, Stock = sku.sku_quantity.ToString(), Status = PopGoodsState.ONSALE, Price = "0", }; string[] ss = sku.spec.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); psku.Color = ss[0]; psku.Size = ss[1]; pg.Skus.Add(psku); } goods.Add(pg); } return(goods); }
public override string AddGoods(Shop shop, PopGoods popGoods, float buyInPrice) { throw new NotImplementedException(); }