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 = "135"; string apiKey = "7dayCFfY6zcwJa6QHtHbGQBRckjJbrbS"; 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; } = "api/renewal"; string MuiltAddUrl { get; set; } = "agent/memberMuiltAdd.html"; string RefundUrl { get; set; } = "agent/memberRefundAct.html "; string UpdateUrl = "api/edit"; string OnlineLoginUrl { get; set; } = "online"; string OnlineUrl { get; set; } = "ppp/oln?"; string KIllUrl { get; set; } = "agent/disConnect2/radacctid/{0}.html"; string searchAccountUrl = "api/get"; string DeleteUrl { get; set; } = "api/del";//1160862.html"; string ExistUrl = "api/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("http://dl.91ip.vip/"); 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("http://dl.91ip.vip/"); 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 client = CreateHttpClient(); var map = new SortedDictionary(){ {"user",account }, {"passwd",pwd }, {"num","1"}, {"conn_max",connCount.ToString() }, {"test",packageKey=="test"?"1":"0" }, {"type",packageKey=="test"?"d":packageKey }, {"paynum",payCount.ToString() }, {"mobile","17719092232" }, }; var title = GetOpTitle("NewAccount", account); LogHelper.Info(title, map.ToJson()); try { var resp = await client.GetAsync(this.SingleAddUrl+"?"+ 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["id"].ToString(); return new ApiResult(ResultCode.C_SUCCESS) { Data=id}; } 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 ret = await this.GetAccountInfo(id); if (ret.Code != ResultCode.C_SUCCESS|| ret.Data==null) { return new ApiResult(ResultCode.C_INVALID_ERROR, "账户不存在,续费失败"); } var client = CreateHttpClient(); var map = new SortedDictionary(){ {"id",id }, //原始的账号的id {"type",packageKey }, {"paynum","1" }, }; var title = GetOpTitle("NewReAccount", id); LogHelper.Info(title, map.ToJson()); 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(); 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, "续费失败"); } } /// /// 删除账号 /// /// /// /// public override async Task DeleteAccount(string id) { var client = CreateHttpClient(); var map = new SortedDictionary(){ {"id",id }, }; var title = GetOpTitle("DeleteAccount", id); LogHelper.Info(title, id); 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 { LogHelper.Error(title, content); return false; } } catch (Exception ex) { LogHelper.Error(title, ex.Message); return false; } } /// /// 得到账号信息 /// /// /// /// public override async Task> GetAccountInfo(string id, bool isTest=false) { var client = CreateHttpClient(); var map = new SortedDictionary(){ {"id",id }, }; var title = GetOpTitle("GetAccountInfo", 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["id"].ToString(), Account = data["user"].ToString(), Pwd = data["passwd"].ToString(), AccountType = data["type"].ToString(), Package = "", ConnectCount = data["conn_max"].ToString(), RegistTime = data["add_time"].ToString(), EndTime = data["end_time"].ToString(), RestTime = "", Amount = data["money"].ToString(), Remark = data["details"].ToString(), }; return new ApiResult(trData); } else { var info = jo["info"].ToString(); LogHelper.Error(title, content); return new ApiResult(ResultCode.C_INVALID_ERROR, "没有查询到信息"); } } catch (Exception ex) { LogHelper.Error(title, ex.Message); return new ApiResult(ResultCode.C_INVALID_ERROR, "查询失败"); } } /// /// 修改账号密码 /// /// /// /// /// public override async Task UpdateAccountPwd(string account, string pwd) { var client = CreateHttpClient(); var map = new SortedDictionary(){ {"id",Raw }, {"user",account }, {"passwd",pwd }, }; LogHelper.Info(GetOpTitle("UpdateAccountPwd", account), map.ToJson()); 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(); // client.BaseAddress = new Url("http://dl.91ip.vip/"); var title = GetOpTitle("OnLine", account); var info = ""; try { var resp = await client.GetAsync(this.OnlineUrl+ "user="+account); var content = await resp.Content.ReadAsStringAsync(); var parser = new HtmlParser(); var document = await parser.ParseDocumentAsync(content); var trs = document.QuerySelectorAll("table.table tr").ToList(); var retData = new List(); if (trs.Count() > 1) { foreach (var tr in trs.Skip(1)) { var tds = tr.QuerySelectorAll("td").ToList(); var tdAccount = tds[0].FirstChild.TextContent; if (tdAccount != account) continue; info = string.Join("", tds.Select(m => m.OuterHtml)); var trData = new OriginAccountOnlineModel { Account = account, ServerIP = tds[1].TextContent, OnlineTime = tds[2].TextContent, }; var href = tr.LastElementChild.QuerySelector("a")?.Attributes["href"]?.Value; trData.Id = href; retData.Add(trData); } } return new ApiResult>(retData); } catch (Exception ex) { LogHelper.Error(title, ex.Message + "-->info:" + info); return new ApiResult>(ResultCode.C_INVALID_ERROR, "查询失败"); } } /// /// 踢号 /// /// /// /// public override async Task KillOut( string id) { var client = CreateHttpClient(); var title = GetOpTitle("KillOut", id); var info = ""; try { var resp = await client.GetAsync(id); 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; } } }