using Api.Framework.Model;
using Api.Framework.Tools;
using CsharpHttpHelper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Api.Framework.Cps
{
///
/// 京东操作Api
///
public class JingdongApi : BaseCpsApi
{
#region 固定函数
///
/// 构造方法
///
/// fl_cps_member实例
public JingdongApi(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}");
}
}
#region
private static int AppKeysIndex = -1;
private static string[] AppKeys = null;
private static List WhiteApiList = new List() {
"jd.union.open.promotion.byunionid.get"/*转链*/,
"jd.union.open.position.query"/*推广位*/,
"jd.union.open.position.create"/*创建推广位*/,
"jd.union.open.goods.jingfen.query"/*京粉精选商品*/,
"jd.union.open.goods.promotiongoodsinfo.query"/*根据skuid查询商品信息*/ };
private static string[] KeyInfo = null;
private static DateTime UpdateKeyTime = DateTime.MinValue;
private string[] GetKeySecret()
{
if (UpdateKeyTime.AddDays(1) < DateTime.Now)
KeyInfo = null;
if (KeyInfo == null)
{
for (int i = 0; i < 3; i++)
{
try
{
var data = this.SendServer("find_wangzhi", "webTool.asmx", new { name = "京东APPKEY" }).message.ToString();
if (!string.IsNullOrWhiteSpace(data))
{
/*
appkey="4363c9848d8a43c8b7b9e957d3adcbcf";
"474ae90f6930495988c28701b6be1d9a";
*/
//data = "4363c9848d8a43c8b7b9e957d3adcbcf_474ae90f6930495988c28701b6be1d9a";
KeyInfo = data.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries);
break;
}
continue;
}
catch (Exception)
{
KeyInfo = null;
Thread.Sleep(500);
}
}
UpdateKeyTime = DateTime.Now;
}
return KeyInfo;
}
///
/// 发送京东报文
///
/// api接口
/// 参数
///
public Dictionary SendJingdong(string api, object data)
{
try
{
//执行次数
int num = 1;
Next:
string[] appKey = null;
if (AppKeysIndex == -1)
{
//appkey = "4363c9848d8a43c8b7b9e957d3adcbcf";
//secretkey = "474ae90f6930495988c28701b6be1d9a";
if (WhiteApiList.Contains(api))
//appKey = new string[] { "dd09c846450c044cf4977357e25ef2cb", "8a610e949a0d4657b310def702728059" };//自己的目前30W
appKey = GetKeySecret();//自己的目前30W
if (appKey == null)
appKey = new string[] { "4363c9848d8a43c8b7b9e957d3adcbcf", "474ae90f6930495988c28701b6be1d9a" };//别人的,无限制
}
//else
//{
// //第一次
// if (AppKeys == null || AppKeysIndex >= AppKeys.Length)
// {
// try
// {
// if (AppKeys != null && AppKeysIndex >= AppKeys.Length) AppKeysIndex = -1;
// else if (AppKeys == null && AppKeysIndex != -1) AppKeysIndex = -1;
// var result = base.SendServer("get_appkey", "");
// var msg = result.message.ToString();
// msg = ZipHelper.GZipDecompressString(msg);
// AppKeys = msg.Split(',');
// }
// catch (Exception ex)
// {
// throw new Exception("获取京东授权KEY失败!" + ex.Message);
// }
// }
// appKey = AppKeys[AppKeysIndex].Split('_');
//}
Dictionary param = new Dictionary();
param["access_token"] = "";
param["app_key"] = appKey[0];
param["format"] = "json";
param["method"] = api;
param["param_json"] = CsharpHttpHelper.HttpHelper.ObjectToJson(data);//param_json为空的时候需要写成 "{}"
param["sign_method"] = "md5";
param["timestamp"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
param["v"] = "1.0";
//计算签名
var sign = SignTopRequest(param, appKey[1]);
param["sign"] = sign;
if (param.ContainsKey("param_json"))
{
param["param_json"] = HttpHelper.URLEncode(param["param_json"]);
}
var _param = HttpHelper.URLDecode(HttpExtend.BuildQuery(param));
HttpHelper http = new HttpHelper();
HttpItem _item = new HttpItem()
{
URL = "https://router.jd.com/api?" + _param,
Method = "get",
Timeout = 10000,
ReadWriteTimeout = 10000,
IsToLower = false,
Cookie = "",
UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",
Accept = "text/html, application/xhtml+xml, */*",
ContentType = "application/x-www-form-urlencoded",
Referer = ""
};
Dictionary dic = null;
string html = string.Empty;
for (int i = 0; i < 4; i++)
{
html = http.GetHtml(_item).Html;
if (html.Contains("操作超时") || html.Contains("服务端异常"))
{
Thread.Sleep(200);
continue;
}
else
{
dic = HttpExtend.JsonToDictionary(html);
if (dic == null) continue;
}
break;
}
if (html.Contains("操作超时") || html.Contains("服务端异常")) return new Dictionary();
if (dic == null)
{
EventClient.OnEvent(this, $"【京东】 => 请求失败转换异常:{html}");
return new Dictionary();
}
var response = api.Replace(".", "_") + "_response";
if (dic.ContainsKey(response))
{
var result = dic[response] as Dictionary;
if (result.ContainsKey("result"))
{
dic = HttpExtend.JsonToDictionary(result["result"].ToString());
}
if (dic.ContainsKey("code"))
{
var code = dic["code"].ToString();
if (code != "200" && code != "1002016")
{
if (dic["message"].ToString().ToLower() == "授权key无权限或错误")
{
if (num < 3)
{
num++;
goto Next;
}
//if (code == "1002006") throw new Exception("京东key失效");
throw new Exception(@"授权key无权限或错误");
}
else
{
EventClient.OnEvent(this, $"京东接口异常:{this.Member.username}({this.Member.usernick})->{api}->{dic["message"]}");
throw new Exception(HttpHelper.ObjectToJson(dic["message"]));
}
}
}
return dic;
}
else if (dic.ContainsKey("errorResponse") || dic.ContainsKey("error_response"))//{"errorResponse":{"code":"3067","msg":"API GLOBAL LIMITER ACTIVE, REQUEST TIMES LIMITED"}}
{
if (dic.ContainsKey("errorResponse"))
{
var errorResponse = dic["errorResponse"] as Dictionary;
if (errorResponse.ContainsKey("code") && (errorResponse["code"].ToString() == "3066" || errorResponse["code"].ToString() == "67"))
{
AppKeysIndex++;
if (AppKeysIndex < AppKeys.Length)
{
goto Next;
}
else
throw new Exception($".京东调用量饱和,暂时无法为您发起请求!");
}
else
{
throw new Exception($".京东接口异常:({this.Member.usernick})->{api}->{HttpHelper.ObjectToJson(dic["errorResponse"])}");
}
}
else if (dic.ContainsKey("error_response"))
{
var errorResponse = dic["error_response"] as Dictionary;
//if (errorResponse.ContainsKey("code") && errorResponse["code"] == "2")
//{
if (errorResponse.ContainsKey("zh_desc") && errorResponse["zh_desc"].ToString().Contains("1天内访问接口"))
{
AppKeysIndex++;
if (AppKeysIndex < AppKeys.Length)
{
goto Next;
}
else
throw new Exception($".京东调用量饱和,暂时无法为您发起请求!");
}
//}
else
{
string code = string.Empty;
if (errorResponse.ContainsKey("code"))
code = errorResponse["code"].ToString();
throw new Exception($".京东接口异常:({this.Member.usernick})->{api}-> {code}.京东调用量饱和,暂时无法为您发起请求!");
}
}
}
return new Dictionary();
}
catch (Exception ex)
{
throw ex;
}
}
#endregion
#region 2021年1月25日 新接口
///
/// 京东下载订单
///
/// 开始时间
/// 结束时间
/// 第几页
/// 每页数量,上限500
/// 订单类型
///
internal Dictionary DownOrder(DateTime datetime, string key, int page_index, int page_size, int type = 3)
{
int i = 0;
Next:
try
{
var endTime = datetime.ToString("yyyy-MM-dd HH:mm:ss"); //每小时同步订单
var startTime = datetime.AddHours(-1).ToString("yyyy-MM-dd HH:mm:ss"); //每小时同步订单
var _rst = this.SendJingdong("jd.union.open.order.row.query", new
{
orderReq = new
{
key = key,
pageIndex = page_index,
pageSize = page_size,
type = type, //订单时间查询类型(1:下单时间,2:完成时间(购买用户确认收货时间),3:更新时间
startTime = startTime, //查询时间,建议使用分钟级查询,格式: yyyyMMddHH, yyyyMMddHHmm或yyyyMMddHHmmss,如201811031212的查询范围从12:12:00-12:12:59
endTime = endTime,
}
});
return _rst;
}
catch (Exception ex)
{
if (i <= 3 && ex.Message == "未将对象引用设置到对象的实例。") //调用接口是偶尔会出现为将对象实例化的错误.
{
i++;
Thread.Sleep(100);
goto Next;
}
else
throw ex;
EventClient.OnEvent(this, $"更新京东订单异常: {ex.Message} - {ex.StackTrace}");
return null;
}
}
#endregion
#endregion
#region Sign计算
private string SignTopRequest(Dictionary parameters, string appSecret)
{
StringBuilder sb = new StringBuilder(appSecret);
//按照规则拼成字符串
foreach (KeyValuePair entry in parameters)
{
string name = entry.Key;
string value = entry.Value;
//检测参数是否为空
if (areNotEmpty(new string[] { name, value }))
{
sb.Append(name).Append(value);
}
}
sb.Append(appSecret);
//MD5
return md5(sb.ToString());
}
private string md5(string source)
{
MD5 md5 = MD5.Create();
var result = md5.ComputeHash(Encoding.UTF8.GetBytes(source));
return byte2hex(result);
}
private string byte2hex(byte[] bytes)
{
//把二进制转化为大写的十六进制
StringBuilder result = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
result.Append(bytes[i].ToString("X2"));
}
return result.ToString();
}
private bool areNotEmpty(string[] values)
{
bool result = true;
if ((values == null) || (values.Length == 0))
result = false;
else
{
foreach (var value in values)
{
result &= !isEmpty(value);
}
}
return result;
}
private bool isEmpty(string value)
{
int strLen;
if ((value == null) || ((strLen = value.Length) == 0))
return true;
for (int i = 0; i < strLen; i++)
{
var ss = value[i];
if (!string.IsNullOrWhiteSpace(value[i].ToString()))
{
return false;
}
}
return true;
}
#endregion
}
}