329 lines
13 KiB
C#
329 lines
13 KiB
C#
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
|
||
{
|
||
/// <summary>
|
||
/// 唯品会操作Api
|
||
/// </summary>
|
||
public class WeipinhuiApi : BaseCpsApi
|
||
{
|
||
#region 固定函数
|
||
/// <summary>
|
||
/// 构造方法
|
||
/// </summary>
|
||
/// <param name="member"></param>
|
||
internal WeipinhuiApi(fl_cps_member member) : base(member) { }
|
||
|
||
/// <summary>
|
||
/// 刷新授权
|
||
/// </summary>
|
||
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
|
||
|
||
/// <summary>
|
||
/// 发送唯品会报文
|
||
/// </summary>
|
||
/// <param name="api">api接口</param>
|
||
/// <param name="data">参数</param>
|
||
/// <returns></returns>
|
||
public T SendWeipinhui<T>(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<T>(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
|
||
|
||
/// <summary>
|
||
/// 唯品会下载订单
|
||
/// </summary>
|
||
/// <param name="_startTime">开始时间</param>
|
||
/// <param name="_endTime">结束时间</param>
|
||
/// <param name="page_index">第几页</param>
|
||
/// <param name="page_size">每页数量</param>
|
||
/// <returns></returns>
|
||
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<OrderResponseResult>("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计算
|
||
|
||
/// <summary>
|
||
/// 计算签名,返回请求阿里妈妈服务器的参数
|
||
/// </summary>
|
||
/// <param name="api">api</param>
|
||
/// <param name="data">参数</param>
|
||
/// <returns></returns>
|
||
private string GetRequestData(string api, object data)
|
||
{
|
||
//try
|
||
//{
|
||
var reg = Regex.Match(api, "(?<service>.+?)-(?<version>.+?)#(?<method>.+)");
|
||
if (!reg.Success) throw new Exception($"无法识别“{api}”API请求!");
|
||
|
||
var param = new Dictionary<string, string>();
|
||
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;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 计算sign
|
||
/// </summary>
|
||
/// <param name="parameters">计算的参数</param>
|
||
/// <param name="secret">appkey</param>
|
||
/// <param name="bizParam">请求的参数</param>
|
||
/// <returns></returns>
|
||
private string GetSign(Dictionary<string, string> parameters, string secret, object bizParam = null)
|
||
{
|
||
// 第一步:把字典按Key的字母顺序排序
|
||
IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters, StringComparer.Ordinal);
|
||
|
||
//// 第二步:把所有参数名和参数值串在一起
|
||
StringBuilder query = new StringBuilder();
|
||
foreach (KeyValuePair<string, string> 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
|
||
|
||
/// <summary>
|
||
/// 获取唯品会推广位
|
||
/// </summary>
|
||
/// <param name="api">WeipinhuiApi对象</param>
|
||
/// <param name="page">第几页</param>
|
||
/// <param name="pageSize">每页的数量</param>
|
||
/// <returns></returns>
|
||
public static QueryPid GetWphTgw(WeipinhuiApi api, int page = 1, int pageSize = 20)
|
||
{
|
||
var res = api.SendWeipinhui<QueryPids>("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;
|
||
}
|
||
|
||
///// <summary>
|
||
///// 获取唯品会推广位
|
||
///// </summary>
|
||
///// <param name="api">WeipinhuiApi对象</param>
|
||
///// <param name="page">第几页</param>
|
||
///// <param name="pageSize">每页的数量</param>
|
||
///// <returns></returns>
|
||
//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<string, object>;
|
||
// total = int.Parse(res["total"].ToString());
|
||
// return res["pidInfoList"] as ArrayList;
|
||
// }
|
||
// return null;
|
||
//}
|
||
|
||
/// <summary>
|
||
/// 创建推广位
|
||
/// </summary>
|
||
/// <param name="api">WeipinhuiApi对象</param>
|
||
/// <param name="pidList">要创建的推广位名称</param>
|
||
public static void CreateWphTgw(WeipinhuiApi api, List<string> pidList = null)
|
||
{
|
||
if (pidList == null)
|
||
pidList = new List<string>() { "WphDefault" };
|
||
api.SendWeipinhui<object>("com.vip.adp.api.open.service.UnionPidService-1.0.0#genPidWithOauth", new { pidGenRequest = new { requestId = Util.GetUUID(), pidNameList = pidList } });
|
||
}
|
||
|
||
}
|
||
}
|