old_flsystem/类库/Api.Framework/Cps/PinduoduoApi.cs

355 lines
15 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Api.Framework.Model;
using CsharpHttpHelper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
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="api">请求的api</param>
/// <param name="data">参数</param>
/// <returns></returns>
public JToken SendPinduoduoJToken(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时不需要写
};
var result = http.GetHtml(_item);
//if (html.Contains("access_token已过期")) Member.online = false;
//else if (api == "pdd.ddk.oauth.order.list.increment.get") Member.online = true;
if (result.StatusCode == HttpStatusCode.OK)
{
html = result.Html;
JObject jObj = null;
try
{
jObj = JObject.Parse(html);
}
catch (Exception e)
{
return null;
}
if (jObj?.First?.First != null)
{
var jData = jObj.First.First;
if (jData["error_code"] != null)
//throw new Exception(jObj.ToString());
throw new Exception(jData["error_msg"] + " 参数:" + JsonConvert.SerializeObject(data));
return jData;
}
}
return null;
}
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
/// <summary>
/// 生成授权地址
/// </summary>
/// <param name="pid"></param>
/// <returns></returns>
public string AuthorityUrl(string pid)
{
//授权的信息
var result = SendPinduoduoJToken("pdd.ddk.oauth.rp.prom.url.generate", new { generate_short_url = true, p_id_list = "[\"" + pid + "\"]", channel_type = 10 });
var urlList = result["url_list"]?.ToArray();
if (urlList == null || urlList.Length <= 0)
{
return string.Empty;
}
var mobileUrl = urlList[0]?["mobile_short_url"]?.ToString();
return mobileUrl;
}
/// <summary>
/// 用户是否授权
/// </summary>
/// <param name="adzoneAdzonePid"></param>
/// <returns></returns>
public bool IsAuthority(string adzoneAdzonePid)
{
var jToken = SendPinduoduoJToken("pdd.ddk.oauth.member.authority.query", new { pid = adzoneAdzonePid, custom_parameters = "" });
return jToken["bind"]?.Value<int>() == 1;
}
}
}