214 lines
8.9 KiB
C#
214 lines
8.9 KiB
C#
using Api.Framework.Model;
|
||
using CsharpHttpHelper;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Security.Cryptography;
|
||
using System.Text;
|
||
using System.Threading;
|
||
|
||
namespace Api.Framework.Cps
|
||
{
|
||
/// <summary>
|
||
/// 拼多多操作Api
|
||
/// </summary>
|
||
public class PinduoduoApi : BaseCpsApi
|
||
{
|
||
#region 静态
|
||
/// <summary>
|
||
/// 拼多多接口请求地址
|
||
/// </summary>
|
||
private const string app_host = "http://gw-api.pinduoduo.com/api/router";
|
||
|
||
/// <summary>
|
||
/// 计算sign
|
||
/// </summary>
|
||
/// <param name="parameters">参数</param>
|
||
/// <param name="appkey">appkey</param>
|
||
/// <returns></returns>
|
||
private string SignTopRequest(Dictionary<string, string> parameters, string appkey)
|
||
{
|
||
// 第一步:把字典按Key的字母顺序排序
|
||
IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters, StringComparer.Ordinal);
|
||
|
||
// 第二步:把所有参数名和参数值串在一起
|
||
StringBuilder query = new StringBuilder();
|
||
query.Append(appkey);
|
||
foreach (KeyValuePair<string, string> kv in sortedParams)
|
||
{
|
||
if (!string.IsNullOrEmpty(kv.Key) && !string.IsNullOrEmpty(kv.Value))
|
||
{
|
||
query.Append(kv.Key).Append(kv.Value);
|
||
}
|
||
}
|
||
|
||
// 第四步
|
||
byte[] bytes;
|
||
query.Append(appkey);
|
||
MD5 md5 = MD5.Create();
|
||
bytes = md5.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
|
||
|
||
#region 实际操作
|
||
/// <summary>
|
||
/// 构造方法
|
||
/// </summary>
|
||
/// <param name="member"></param>
|
||
internal PinduoduoApi(fl_cps_member member) : base(member) { }
|
||
|
||
/// <summary>
|
||
/// 刷新授权
|
||
/// </summary>
|
||
internal void RefreshStatus()
|
||
{
|
||
for (int i = 0; i < 3; i++)
|
||
{
|
||
try
|
||
{
|
||
//if (Member.cpstype == Enums.CpsType.多多进宝)
|
||
// Console.WriteLine();
|
||
//UpdateCookies();
|
||
var result = SendServer("refresh_token", new { username = Member.username });
|
||
if (!result.ok) throw new Exception(result.message.ToString());
|
||
Member.online = true;
|
||
RefToken();
|
||
break;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
if (i < 2)
|
||
{
|
||
Thread.Sleep(10000);
|
||
continue;
|
||
}
|
||
else
|
||
EventClient.OnEvent(this, $"ERROR:{this.GetType()}@{System.Reflection.MethodBase.GetCurrentMethod().Name}->{ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送拼多多报文
|
||
/// </summary>
|
||
/// <param name="api">请求的api</param>
|
||
/// <param name="data">参数</param>
|
||
/// <returns></returns>
|
||
public Dictionary<string, object> SendPinduoduo(string api, object data)
|
||
{
|
||
int number = 0;
|
||
string html = string.Empty;
|
||
Next:
|
||
try
|
||
{
|
||
number++;
|
||
|
||
//throw new Exception("{\"error_msg\":\"公共参数错误: access_token\",\"sub_msg\":\"公共参数错误: access_token\",\"sub_code\":\"10019\",\"error_code\":10019,\"request_id\":\"16249438515389810\"}");
|
||
|
||
Dictionary<string, string> param = new Dictionary<string, string>();
|
||
var type = data.GetType().GetProperties();
|
||
foreach (var item in type)
|
||
{
|
||
var _value = item.GetValue(data).ToString();
|
||
param[item.Name] = _value;
|
||
}
|
||
//if (api != "pdd.ddk.oauth.order.list.increment.get" && api != "pdd.ddk.oauth.goods.search")
|
||
if (api.Contains("oauth"))
|
||
param["access_token"] = Token.access_token;
|
||
param["type"] = api;
|
||
param["client_id"] = Token.appid;
|
||
//param["timestamp"] = ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000).ToString();//HttpExtend.GetTimeStamp(DateTime.Now).ToString();
|
||
param["timestamp"] = HttpExtend.GetTimeStamp();
|
||
param["data_type"] = "JSON";
|
||
var sign = SignTopRequest(param, Token.appkey);
|
||
param["sign"] = sign;
|
||
|
||
HttpHelper http = new HttpHelper();
|
||
HttpItem _item = new HttpItem()
|
||
{
|
||
URL = app_host,
|
||
Method = "Post",//URL 可选项 默认为Get
|
||
Timeout = 10000,//连接超时时间 可选项默认为100000
|
||
ReadWriteTimeout = 10000,//写入Post数据超时时间 可选项默认为30000
|
||
IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写
|
||
Cookie = "",//字符串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 = "",//来源URL 可选项
|
||
Postdata = HttpExtend.BuildQuery(param),//Post数据 可选项GET时不需要写
|
||
};
|
||
html = http.GetHtml(_item).Html;
|
||
|
||
//if (html.Contains("access_token已过期")) Member.online = false;
|
||
//else if (api == "pdd.ddk.oauth.order.list.increment.get") Member.online = true;
|
||
var dic = HttpExtend.JsonToDictionary(html);
|
||
if (dic.ContainsKey("error_response"))
|
||
{
|
||
//EventClient.OnEvent(this, $"拼多多接口异常:{this.Member.username}({this.Member.usernick})->{api}->{html}");
|
||
throw new Exception(HttpHelper.ObjectToJson(dic["error_response"]));
|
||
}
|
||
return dic;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
if (ex.Message.Contains("access_token") && ((ex.Message.Contains("10019") || ex.Message.Contains("20033") || ex.Message.Contains("20032"))))
|
||
{
|
||
Thread.Sleep(1000);
|
||
if (this.Member != null && RefToken() && this.Member.is_valid && number < 3) goto Next;
|
||
else
|
||
{
|
||
//Member.online = false;
|
||
//ApiClient.GetSession().SaveOrUpdate(Member);
|
||
Member.is_valid = false;
|
||
ApiClient.GetSession().SaveOrUpdate(Member);
|
||
EventClient.OnEvent(this, $@"拼多多异常:{this.Member.username}({this.Member.usernick}),{ex.Message} - {ex.StackTrace}
|
||
,注:请重新登录拼多多,{api}");
|
||
throw new Exception($"{this.Member.username}({this.Member.usernick}),{ex.Message},注:请重新登录拼多多");
|
||
}
|
||
}
|
||
else if (html.Contains("超时"))
|
||
{
|
||
goto Next;
|
||
}
|
||
throw ex;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 拼多多下载订单
|
||
/// </summary>
|
||
/// <param name="start_time">开始时间</param>
|
||
/// <param name="end_time">结束时间</param>
|
||
/// <param name="page_index">每页数量默认50安全</param>
|
||
/// <param name="page_size">第几页</param>
|
||
/// <returns></returns>
|
||
internal Dictionary<string, object> DownOrder(DateTime start_time, DateTime end_time, int page_index, int page_size)
|
||
{
|
||
if (!Member.is_valid)
|
||
throw new Exception("需要重新登录");
|
||
|
||
var _rst = this.SendPinduoduo("pdd.ddk.oauth.order.list.increment.get", new
|
||
{
|
||
start_update_time = HttpExtend.GetTimeStamp(start_time),
|
||
end_update_time = HttpExtend.GetTimeStamp(end_time),
|
||
page_size = page_size,
|
||
page = page_index
|
||
});
|
||
if (_rst.ContainsKey("order_list_get_response"))
|
||
{
|
||
return _rst["order_list_get_response"] as Dictionary<string, object>;
|
||
}
|
||
return null;
|
||
}
|
||
#endregion
|
||
|
||
}
|
||
}
|