using AngleSharp; using AngleSharp.Dom; using AngleSharp.Html.Parser; using Hncore.Infrastructure.Common; using Hncore.Infrastructure.Extension; using Hncore.Infrastructure.Serializer; using Hncore.Infrastructure.WebApi; using Hncore.Pass.Vpn.Model; using Hncore.Pass.Vpn.Request.Product; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Http; using System.Security.Cryptography; using System.Threading.Tasks; namespace Hncore.Pass.Vpn.Service { public class AgentClient7Service : AgentClientBaseService { string apiId = "89"; string apiKey = "NFeK72yYXmPiGR86YeMCBRTWDxXkrQsd"; string LoginIndexUrl { get; set; } = "login"; string LoginUrl { get; set; } = "login"; string LoginCodeUrl { get; set; } = ""; string RefrushTokenUrl { get; set; } = "my"; string SingleAddUrl { get; set; } = "api/add"; string SingleReAddUrl { get; set; } = "v1/renewal"; string MuiltAddUrl { get; set; } = "agent/memberMuiltAdd.html"; string RefundUrl { get; set; } = "agent/memberRefundAct.html "; string UpdateUrl = "v1/edit"; string OnlineLoginUrl { get; set; } = "online"; string OnlineUrl { get; set; } = "v1/oln"; string KIllUrl { get; set; } = "agent/disConnect2/radacctid/{0}.html"; string searchAccountUrl = "v1/get"; string DeleteUrl { get; set; } = "v1/refund";//1160862.html"; string ExistUrl = "v1/verify"; IHttpClientFactory m_HttpClientFactory; public AgentClient7Service(IHttpClientFactory httpClientFactory) : base(httpClientFactory) { m_HttpClientFactory = httpClientFactory; } protected override HttpClient CreateHttpClient(bool autoCooke = true) { var client = m_HttpClientFactory.CreateClient("agentClient1.0"); client.BaseAddress = new System.Uri(this.BaseUrl); if (this.Token.Has() && autoCooke) { AddCookie(client, this.Token); } return client; } public override async Task RefrushStatus() { int status = 0; if (this.Token.Has()) { var client = CreateHttpClient(); if (this.RefrushTokenUrl.Has()) { // client.DefaultRequestHeaders.Add("Cookie", this.Token); var getResp = await client.GetAsync(this.RefrushTokenUrl); if (getResp.StatusCode == HttpStatusCode.OK) { status = 1; } else { var request = new AgentLoginRequest() { Account = this.Product.Account, Pwd = this.Product.Pwd }; var ret = await this.Login(request); if (ret.Code == ResultCode.C_SUCCESS) { this.Product.Token = ret.Data.ToString(); status = 1; } else { Debug.WriteLine("离线"); } } } } return status; } private async Task<(string, string)> GetHomeCookie() { var client = CreateHttpClient(false); client.BaseAddress = new Url("https://yoyoapi.yoyoip.com/"); var getResp = await client.GetAsync(this.LoginIndexUrl); var cookies = this.GetCookies(getResp); cookies = cookies.Replace("path=/;", "").Replace("httponly", "").Trim(); var content = await getResp.Content.ReadAsStringAsync(); var parser = new HtmlParser(); var document = await parser.ParseDocumentAsync(content); var csrf_tokenNode = document.QuerySelector("meta[name=csrf-token]");// var csrf_token = csrf_tokenNode.GetAttribute("content"); return (cookies, csrf_token); } public override async Task Login(AgentLoginRequest request) { var tokens = await this.GetHomeCookie(); var client = CreateHttpClient(false); client.BaseAddress = new Url("https://yoyoapi.yoyoip.com"); client.DefaultRequestHeaders.Add("Connection", "keep-alive"); client.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests", "1"); var map = new Dictionary(){ {"_csrf-daili",tokens.Item2}, {"LoginForm[username]",request.Account }, {"LoginForm[password]",request.Pwd }, }; LogHelper.Info("Login", map.ToJson()); var csrf = GetCookieValue(tokens.Item1, "_csrf-daili"); AddCookie(client, $"_csrf-daili={csrf}"); var resp = await client.PostAsForm(this.LoginUrl, map); var content = await resp.Content.ReadAsStringAsync(); if (resp.StatusCode != HttpStatusCode.OK || content.IndexOf("成功") == -1) { return new ApiResult(ResultCode.C_VISITOR_CHECKING, "登录失败"); } var frontend = this.GetCookie(resp, "advanced-frontend"); csrf = this.GetCookie(resp, "_csrf-daili"); request.Key = $"{frontend};{csrf}"; return new ApiResult(request.Key); } public override bool CheckAccount(int productId,List accounts) { return false; } private string Sign(SortedDictionary map) { map["apiid"] = this.apiId; map["sendtime"] = DateTime.Now.GetUnixTimeStamp().ToString(); var data = string.Join("&", map.Select(m => $"{m.Key}={m.Value}")); var signStr = Md5(data + apiKey); data = $"{data}&sign={signStr}"; return data; } //Md5摘要 private static string Md5(string text) { MD5 md5 = new MD5CryptoServiceProvider(); byte[] fromData = System.Text.Encoding.UTF8.GetBytes(text); byte[] targetData = md5.ComputeHash(fromData); string byte2String = null; for (int i = 0; i < targetData.Length; i++) { byte2String += targetData[i].ToString("x2"); } return byte2String; } /// /// 新开 /// /// /// /// /// public override async Task NewAccount(string packageKey, string account, string pwd, int connCount = 1, int accountType = 1, int payCount = 1) { var new_url = "v1/one"; var client = CreateHttpClient(); var package = "m"; var buyCount = "1"; if(packageKey =="test"){ new_url = "v1/test"; } else if(packageKey =="m3"){ package = "m"; buyCount = "3"; } else if(packageKey =="m12"){ package = "m"; buyCount = "12"; } else { package = packageKey; buyCount = payCount.ToString(); } var map = new SortedDictionary(){ {"name",account }, {"passwd",pwd }, {"num","1"}, {"max_conn",connCount.ToString() }, {"paytype",package }, {"paynum",buyCount }, {"product_id",accountType.ToString() }, {"mobile","13073735878" }, {"mark","api" }, }; var title = GetOpTitle("NewAccount", account); try { var resp = await client.GetAsync(new_url+"?"+ Sign(map)); var content = await resp.Content.ReadAsStringAsync(); JObject jo = (JObject)JsonConvert.DeserializeObject(content); var status = jo["status"].ToString(); if (status =="200") { var retAccount=jo["data"].ToArray().FirstOrDefault(); // var id = retAccount["name"].ToString(); return new ApiResult(ResultCode.C_SUCCESS); } else { var info = jo["info"].ToString(); LogHelper.Error(title, content); return new ApiResult(ResultCode.C_INVALID_ERROR, info); } } catch (Exception ex) { LogHelper.Error(title, ex.Message); return new ApiResult(ResultCode.C_INVALID_ERROR, "开户失败"); } } /// /// 续费 /// /// /// 原始的账号的id /// /// public override async Task NewReAccount(string packageKey, string id, int connCount, int payCount = 1) { var package = "m"; var buyCount = "1"; if(packageKey =="m3"){ package = "m"; buyCount = "3"; } else if(packageKey =="m12"){ package = "m"; buyCount = "12"; } else { package = packageKey; buyCount = payCount.ToString(); } var client = CreateHttpClient(); var map = new SortedDictionary(){ {"names",id }, //原始的账号的id {"paytype",package }, {"paynum",buyCount }, }; try { var resp = await client.GetAsync(this.SingleReAddUrl + "?" + Sign(map)); var content = await resp.Content.ReadAsStringAsync(); JObject jo = (JObject)JsonConvert.DeserializeObject(content); var status = jo["status"].ToString(); if (status =="200") { return new ApiResult(ResultCode.C_SUCCESS); } else { var info = jo["info"].ToString(); return new ApiResult(ResultCode.C_INVALID_ERROR, info); } } catch (Exception ex) { return new ApiResult(ResultCode.C_INVALID_ERROR, "续费失败"); } } /// /// 删除账号 /// /// /// /// public override async Task DeleteAccount(string account) { var client = CreateHttpClient(); var map = new SortedDictionary(){ {"name",account }, }; try { var resp = await client.GetAsync(this.DeleteUrl + "?" + Sign(map)); var content = await resp.Content.ReadAsStringAsync(); JObject jo = (JObject)JsonConvert.DeserializeObject(content); var status = jo["status"].ToString(); if (status=="200") { return true; } else { return false; } } catch (Exception ex) { return false; } } /// /// 得到账号信息 /// /// /// /// public override async Task> GetAccountInfo(string id, bool isTest=false) { var client = CreateHttpClient(); var map = new SortedDictionary(){ {"name",id }, }; try { var resp = await client.GetAsync(this.searchAccountUrl + "?" + Sign(map)); var content = await resp.Content.ReadAsStringAsync(); JObject jo = (JObject)JsonConvert.DeserializeObject(content); var status = jo["status"].ToString(); if (status == "200") { var data = jo["data"]; var trData = new OriginAccountModel { Id = data["name"].ToString(), Account = data["name"].ToString(), Pwd = data["passwd"].ToString(), AccountType = data["mark"].ToString(), Package = "", ConnectCount = data["max_conn"].ToString(), RegistTime = data["add_time"].ToString(), EndTime = data["end_time"].ToString(), RestTime = "", Amount = data["balance"].ToString(), Remark = data["mark"].ToString(), }; return new ApiResult(trData); } else { var info = jo["info"].ToString(); return new ApiResult(ResultCode.C_INVALID_ERROR, "没有查询到信息"); } } catch (Exception ex) { return new ApiResult(ResultCode.C_INVALID_ERROR, "查询失败"); } } /// /// 修改账号密码 /// /// /// /// /// public override async Task UpdateAccountPwd(string account, string pwd) { var client = CreateHttpClient(); var map = new SortedDictionary(){ {"name",account }, {"passwd",pwd }, }; try { var resp = await client.GetAsync(this.UpdateUrl + "?" + Sign(map)); var content = await resp.Content.ReadAsStringAsync(); JObject jo = (JObject)JsonConvert.DeserializeObject(content); var status = jo["status"].ToString(); if (status == "200") { return true; } else { LogHelper.Error(GetOpTitle("UpdateAccountPwd", account), content); } } catch (Exception ex) { LogHelper.Error(GetOpTitle("UpdateAccountPwd", account), ex); } return false; } /// /// 退款 /// /// /// /// public override async Task Refund(string id, string packageKey, int days) { var ret = await this.DeleteAccount(id); if (ret) { return new ApiResult(ResultCode.C_SUCCESS); } else { return new ApiResult(ResultCode.C_INVALID_ERROR, "退款失败"); } } /// /// 是否在线 /// /// /// /// public override async Task>> OnLine(string account) { var client = CreateHttpClient(); var map = new SortedDictionary(){ {"name",account }, }; var resp = await client.GetAsync(this.OnlineUrl + "?" + Sign(map)); var content = await resp.Content.ReadAsStringAsync(); JObject jo = (JObject)JsonConvert.DeserializeObject(content); var status = jo["status"].ToString(); var retData = new List(); if (status =="200") { if(jo["data"]["total"].ToInt()>0){ foreach (var tr in jo["data"]["items"]) { JObject jsondata = (JObject)JsonConvert.DeserializeObject(tr.ToJson()); var trData = new OriginAccountOnlineModel { Account = account, ServerIP = jsondata["ip"].ToString(), LoginTime = "", OnlineTime = "", LoginIP = jsondata["user_ip"].ToString(), UpStream = "", DownStream = "", Id= jsondata["id"].ToString(), }; retData.Add(trData); } } return new ApiResult>(retData); } else { return new ApiResult>(ResultCode.C_INVALID_ERROR, "查询失败"); } } /// /// 踢号 /// /// /// /// public override async Task KillOut( string id) { var client = CreateHttpClient(); var title = GetOpTitle("KillOut", id); var info = ""; var map = new SortedDictionary(){ {"id",id }, }; try { var resp = await client.GetAsync("v1/olnstop?" + Sign(map)); var content = await resp.Content.ReadAsStringAsync(); return true; } catch (Exception ex) { LogHelper.Error(title, ex.Message + "-->info:" + info); } return false; } /// /// 是否存在 /// /// /// public override async Task Exist(string account) { var client = CreateHttpClient(); var map = new SortedDictionary(){ {"user",account } }; var title = GetOpTitle("Exist", account); LogHelper.Info(title, account); try { var resp = await client.GetAsync(this.ExistUrl + "?" + Sign(map)); var content = await resp.Content.ReadAsStringAsync(); JObject jo = (JObject)JsonConvert.DeserializeObject(content); var status = jo["status"].ToString(); if (status != "200") { return true; } else { return false; } } catch (Exception ex) { LogHelper.Error(title, ex); } return false; } } }