using Api.Framework.Model; using Api.Framework.Tools; using Api.Framework.Utils; using CsharpHttpHelper; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Net; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Api.Framework.EntityTmp.WeiPinHui; namespace Api.Framework.Cps { /// /// 唯品会操作Api /// public class WeipinhuiApi : BaseCpsApi { #region 固定函数 /// /// 构造方法 /// /// internal WeipinhuiApi(fl_cps_member member) : base(member) { } /// /// 刷新授权 /// public void RefreshStatus() { try { var result = SendServer("refresh_token", new { username = Member.username }); if (!result.ok) throw new Exception(result.message.ToString()); Member.online = true; } catch (Exception ex) { EventClient.OnEvent(this, $"ERROR:{this.GetType()}-{System.Reflection.MethodBase.GetCurrentMethod().Name}->{ex.Message}"); } } //private string AppKey = "0c85e6c0"; //private string AppSecret = "F921D8D3EFEAEA5B0387158512AEF909"; #region /// /// 发送唯品会报文 /// /// api接口 /// 参数 /// public T SendWeipinhui(string api, object data) { if (!Member.is_valid) return default(T); var isRefToken = false; var html = string.Empty; for (int i = 0; i < 3; i++) { try { var query = GetRequestData(api, data); var postData = JsonConvert.SerializeObject(data); var http = new HttpHelper(); var httpItem = new HttpItem() { URL = $"https://vop.vipapis.com/?{query}", Method = "POST", Timeout = 5000, ReadWriteTimeout = 5000, Accept = "text/html, application/xhtml+xml, */*", ContentType = "application/json;", Postdata = postData, }; var result = http.GetHtml(httpItem); if (result.StatusCode == HttpStatusCode.OK) { html = result.Html; if (!string.IsNullOrWhiteSpace(html)) { var jObj = JObject.Parse(html); var resultCode = jObj["returnCode"]?.ToString(); if (resultCode == "0") { T t = JsonConvert.DeserializeObject(html); return t; } else { //请求太快了 if (resultCode == "1008") { Thread.Sleep(5000); continue; } } } } throw new Exception(html); } catch (Exception ex) { LogHelper.GetSingleObj().Error("", $@"唯品会请求异常A.,{Member.usernick}({Member.username}),登录时间:{Member.logintime.ToString("yyyy-MM-dd HH:mm:ss")} {api} {html} {ex.Message} - {ex.StackTrace}"); //token失效的错误数据 //{"returnCode":"vipapis.oauth-invalidate-failure","returnMessage":"oauth-error-code[30111]description[access token invalid]"} if (ex.Message.Contains("invalid") || html.Contains("invalid") || html.Contains("token") || html.ToLower().Contains("does not exist")) { //没有刷新过token if (isRefToken == false) { isRefToken = true; if (RefToken()) continue; } EventClient.OnEvent(this, $@"【唯品会】 => 请求异常1:{this.Member.usernick}({this.Member.username}),注:请重新登录唯品会!!!"); Member.is_valid = false; return default(T); } Thread.Sleep(500); } } return default(T); } #endregion /// /// 唯品会下载订单 /// /// 开始时间 /// 结束时间 /// 第几页 /// 每页数量 /// internal OrderResponseResult DownOrder(DateTime _startTime, DateTime _endTime, int page_index, int page_size) { if (!Member.is_valid) { //Api.Framework.Utils.LogHelper.GetSingleObj().Error("唯品会订单下载异常.过期?", $"需要重新登录,{this.Member.usernick}({this.Member.username})"); throw new Exception("vipapis.oauth-invalidate-failure"); } var startTime = Util.GetTimeSpan(_startTime, true); //每小时同步订单 var endTime = Util.GetTimeSpan(_endTime, true); //每小时同步订单 //time = "2019042216"; //TODO 订单下载接口 var result = this.SendWeipinhui("com.vip.adp.api.open.service.UnionOrderService-1.0.0#orderListWithOauth", new { queryModel = new { //status = key,//订单状态:0-不合格,1-待定,2-已完结,该参数不设置默认代表全部状态 //orderTimeStart = page_index,//订单时间起始 时间戳 单位毫秒 //orderTimeEnd = page_size,//订单时间结束 时间戳 单位毫秒 page = page_index,//页码:从1开始 pageSize = page_size,//页面大小:默认20 requestId = Util.GetUUID(),//请求id:调用方自行定义,用于追踪请求,单次请求唯一,建议使用UUID updateTimeStart = startTime,//更新时间-起始 时间戳 单位毫秒 updateTimeEnd = endTime,//更新时间-结束 时间戳 单位毫秒 //orderSnList = ,//订单号列表:当传入订单号列表时,订单时间和更新时间区间可不传入 //vendorCode = ,//vendorCode,工具商方式下会传入 //chanTag = ,//渠道标识,即推广位PID } }); //if (_rst == null || _rst.result == null || _rst.returnCode == null || _rst.returnCode != "0") // throw new Exception(JsonConvert.SerializeObject(_rst)); return result; } #endregion #region Sign计算 /// /// 计算签名,返回请求阿里妈妈服务器的参数 /// /// api /// 参数 /// private string GetRequestData(string api, object data) { //try //{ var reg = Regex.Match(api, "(?.+?)-(?.+?)#(?.+)"); if (!reg.Success) throw new Exception($"无法识别“{api}”API请求!"); var param = new Dictionary(); if (Token == null) { throw new Exception("invalid .."); } param["accessToken"] = Token.access_token; param["appKey"] = "9f7a9b3d";//Token.appid; param["format"] = "JSON"; param["language"] = "zh"; param["method"] = reg.Groups["method"].Value; param["service"] = reg.Groups["service"].Value; param["version"] = reg.Groups["version"].Value; param["timestamp"] = Util.GetTimeSpan(DateTime.Now, false).ToString(); //计算签名 string sign = GetSign(param, "074B0E1FFB94334FDEC993913884EC7F"/*Token.appkey*/, data); param["sign"] = sign; return HttpExtend.BuildQuery(param); //} //catch (Exception ex) //{ //} return string.Empty; } /// /// 计算sign /// /// 计算的参数 /// appkey /// 请求的参数 /// private string GetSign(Dictionary parameters, string secret, object bizParam = null) { // 第一步:把字典按Key的字母顺序排序 IDictionary sortedParams = new SortedDictionary(parameters, StringComparer.Ordinal); //// 第二步:把所有参数名和参数值串在一起 StringBuilder query = new StringBuilder(); foreach (KeyValuePair kv in sortedParams) { if (!string.IsNullOrEmpty(kv.Key) && !string.IsNullOrEmpty(kv.Value)) query.Append(kv.Key).Append(kv.Value); } // 第三步:把请求主体拼接在参数后面 var boby = string.Empty; if (bizParam != null) boby = JsonConvert.SerializeObject(bizParam); if (!string.IsNullOrEmpty(boby)) { query.Append(boby); } var sss = query.ToString(); // 第四步: 使用HMAC加密 HMACMD5 hmac = new HMACMD5(Encoding.UTF8.GetBytes(secret)); var bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(query.ToString())); // 第五步:把二进制转化为大写的十六进制 StringBuilder result = new StringBuilder(); for (int i = 0; i < bytes.Length; i++) { result.Append(bytes[i].ToString("X2")); } return result.ToString(); } #endregion /// /// 获取唯品会推广位 /// /// WeipinhuiApi对象 /// 第几页 /// 每页的数量 /// public static QueryPid GetWphTgw(WeipinhuiApi api, int page = 1, int pageSize = 20) { var res = api.SendWeipinhui("com.vip.adp.api.open.service.UnionPidService-1.0.0#queryPidWithOauth", new { pidQueryRequest = new { requestId = Util.GetUUID(), page = page, pageSize = pageSize } }); if (res != null && res.returnCode == "0") { return res.result; } return null; } ///// ///// 获取唯品会推广位 ///// ///// WeipinhuiApi对象 ///// 第几页 ///// 每页的数量 ///// //public static ArrayList GetWphTgw(WeipinhuiApi api, out int total, int page = 1, int pageSize = 20) //{ // total = 0; // var res = api.SendWeipinhui("com.vip.adp.api.open.service.UnionPidService-1.0.0#queryPidWithOauth", new { pidQueryRequest = new { requestId = Util.GetUUID(), page = page, pageSize = pageSize } }); // if (res.ContainsKey("returnCode") && res["returnCode"].ToString() == "0") // { // res = res["result"] as Dictionary; // total = int.Parse(res["total"].ToString()); // return res["pidInfoList"] as ArrayList; // } // return null; //} /// /// 创建推广位 /// /// WeipinhuiApi对象 /// 要创建的推广位名称 public static void CreateWphTgw(WeipinhuiApi api, List pidList = null) { if (pidList == null) pidList = new List() { "WphDefault" }; api.SendWeipinhui("com.vip.adp.api.open.service.UnionPidService-1.0.0#genPidWithOauth", new { pidGenRequest = new { requestId = Util.GetUUID(), pidNameList = pidList } }); } } }