初始提交
This commit is contained in:
537
Services/Hncore.Pass.Vpn/Service/AgentClient1Service.cs
Normal file
537
Services/Hncore.Pass.Vpn/Service/AgentClient1Service.cs
Normal file
@@ -0,0 +1,537 @@
|
||||
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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public class AgentClient1Service:AgentClientBaseService
|
||||
{
|
||||
string LoginUrl { get; set; } = "main/agentLogin.html";
|
||||
string LoginCodeUrl { get; set; } = "main/imgcode.html";
|
||||
string RefrushTokenUrl { get; set; } = "agent/index.html";
|
||||
string SingleAddUrl { get; set; } = "agent/memberSingleAdd.html";
|
||||
string SingleReAddUrl { get; set; } = "agent/memberRenew.html";
|
||||
string MuiltAddUrl { get; set; } = "agent/memberMuiltAdd.html";
|
||||
string RefundUrl { get; set; } = "agent/memberRefundAct.html ";
|
||||
string UpdateUrl = "agent/memberUpdate/id/";//agent/memberUpdate/id/1155709.html
|
||||
string OnlineUrl { get; set; } = "agent/radiusOnline.html?search=1&username=";
|
||||
string KIllUrl { get; set; } = "agent/disConnect2/radacctid/{0}.html";
|
||||
string searchAccountUrl = "agent/memberList/type/1.html?search=1&username=";
|
||||
string searchTestAccountUrl = "agent/memberList/type/0.html?search=1&username=";
|
||||
string DeleteUrl { get; set; } = "agent/memberDel/id/";//1160862.html";
|
||||
IHttpClientFactory m_HttpClientFactory;
|
||||
public AgentClient1Service(IHttpClientFactory httpClientFactory):base(httpClientFactory)
|
||||
{
|
||||
m_HttpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
public override async Task<int> 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);
|
||||
var content = await getResp.Content.ReadAsStringAsync();
|
||||
if (getResp.StatusCode == HttpStatusCode.OK && content.IndexOf("agentLogin.html") == -1)
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("离线");
|
||||
Debug.WriteLine(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
public override async Task<(byte[], string)> GetCode()
|
||||
{
|
||||
var client = CreateHttpClient(false);
|
||||
if (this.LoginUrl.NotHas()) return (null, "");
|
||||
var getResp = await client.GetAsync(this.LoginUrl);
|
||||
var cookie = this.GetCookie(getResp, "PHPSESSID");
|
||||
if (cookie.Has())
|
||||
{
|
||||
client.DefaultRequestHeaders.Add("Cookie", cookie);
|
||||
var ret = await client.GetByteArrayAsync(this.LoginCodeUrl + "?t=" + DateTime.Now.Millisecond);
|
||||
return (ret, cookie);
|
||||
}
|
||||
return (null, "");
|
||||
}
|
||||
public override async Task<ApiResult> Login(AgentLoginRequest request)
|
||||
{
|
||||
var client = CreateHttpClient(false);
|
||||
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"agentName",request.Account },
|
||||
{"password",request.Pwd },
|
||||
{"authnum",request.Code },
|
||||
};
|
||||
LogHelper.Info("Login", map.ToJson());
|
||||
AddCookie(client, request.Key);
|
||||
//client.DefaultRequestHeaders.Add("Cookie", request.Key);
|
||||
var resp = await client.PostAsForm(this.LoginUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.IndexOf("alert alert-danger") != -1)
|
||||
{
|
||||
return new ApiResult(ResultCode.C_VISITOR_CHECKING, "登录失败");
|
||||
}
|
||||
return new ApiResult(request.Key);
|
||||
}
|
||||
public override bool CheckAccount(int productId,List<string> accounts)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新开
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewAccount(string packageKey, string account, string pwd, int connCount = 1, int accountType = 1, int payCount = 1)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"taocanName",packageKey },
|
||||
{"username",account },
|
||||
{"password",pwd },
|
||||
{"maxonline",connCount.ToString()},
|
||||
{"type",accountType.ToString()}
|
||||
};
|
||||
var title = GetOpTitle("NewAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.SingleAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("{alert(\"成功\")") != -1)
|
||||
{
|
||||
return new ApiResult(ResultCode.C_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "开户失败");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新开
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewMuiltAccount(string packageKey, string account, string pwd, int connCount = 1, int accountType = 1,int startNum=0, int endNum=1 )
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"taocanName",packageKey },
|
||||
{"usernameTpl",account },
|
||||
{"password",pwd },
|
||||
{"maxonline",connCount.ToString()},
|
||||
{"startNum",startNum.ToString()},
|
||||
{"endNum",endNum.ToString()},
|
||||
{"mode",accountType.ToString()},
|
||||
};
|
||||
var title = GetOpTitle("NewMuiltAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.MuiltAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("<td>成功</td>") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "开户失败");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 续费
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewReAccount(string packageKey, string account, int connCount)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"taocanName",packageKey },
|
||||
{"username",account },
|
||||
{"iscz","3" },
|
||||
};
|
||||
var title = GetOpTitle("NewReAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.SingleReAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("alert(\"成功\")") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "续费失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除账号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> DeleteAccount(string account)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var infoRet = await this.GetAccountInfo(account, true);
|
||||
if (infoRet.Code != ResultCode.C_SUCCESS)
|
||||
return false;
|
||||
|
||||
var title = GetOpTitle("DeleteAccount", account);
|
||||
LogHelper.Info(title, account);
|
||||
try
|
||||
{
|
||||
var delete = this.DeleteUrl + infoRet.Data.Id + ".html";
|
||||
var resp = await client.GetAsync(delete);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("alert(\"删除成功\")") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Error(title, content);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 得到账号信息
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult<OriginAccountModel>> GetAccountInfo(string account,bool isTest=false)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("GetAccountInfo", account);
|
||||
|
||||
var info = "";
|
||||
try
|
||||
{
|
||||
var url = this.searchAccountUrl + account;
|
||||
if (isTest)
|
||||
{
|
||||
url = this.searchTestAccountUrl + account;
|
||||
}
|
||||
var resp = await client.GetAsync(url);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
|
||||
var parser = new HtmlParser();
|
||||
var document = await parser.ParseDocumentAsync(content);
|
||||
////table class="table table-bordered"
|
||||
var trs = document.QuerySelectorAll("table.table tr").ToList();
|
||||
// var trs= table.QuerySelectorAll("tr").ToList();
|
||||
var retData = new List<OriginAccountModel>();
|
||||
if (trs.Count() > 1)
|
||||
{
|
||||
foreach(var tr in trs.Skip(1))
|
||||
{
|
||||
var tds = tr.QuerySelectorAll("td").ToList();
|
||||
var tdAccount = tds[1].FirstChild.TextContent;
|
||||
if (tdAccount != account)
|
||||
continue;
|
||||
info = string.Join("", tds.Select(m => m.OuterHtml));
|
||||
//<td >会员账号</td><td >类型</td><td >套餐</td><td >注册日期</td><td >过期日期</td><td >连接数</td><td >余额</td><td >激活</td><td >备注</td>
|
||||
|
||||
var trData = new OriginAccountModel
|
||||
{
|
||||
Account = account,
|
||||
Pwd = tds[1].QuerySelector("font").TextContent,
|
||||
AccountType = tds[2].TextContent,
|
||||
Package = tds[3].TextContent,
|
||||
RegistTime = tds[4].TextContent,
|
||||
EndTime = tds[5].ChildNodes[0].TextContent.Replace("\n", "").Replace("\t", "").Trim(),
|
||||
RestTime = tds[5].ChildNodes[2].TextContent.Replace("\n", "").Replace("\t", ""),
|
||||
ConnectCount = tds[6].TextContent,
|
||||
Amount = tds[7].TextContent,
|
||||
IsActive = tds[8].TextContent,
|
||||
Remark = tds[9].TextContent,
|
||||
};
|
||||
trData.RealEndTime = DateTime.Parse(trData.EndTime);
|
||||
if (tds[5].TextContent.Contains("已过期"))
|
||||
{
|
||||
trData.RestTime = "已过期";
|
||||
}else
|
||||
{
|
||||
// "6.14:32"
|
||||
var timeStr = trData.RestTime.Replace("天", ".").Replace("时", ":").Replace("分", "").Trim();
|
||||
var restTime = TimeSpan.Parse(timeStr);
|
||||
trData.RealEndTime = DateTime.Now.Add(restTime);
|
||||
}
|
||||
var href = tr.LastElementChild.QuerySelector("a")?.Attributes["href"]?.Value;
|
||||
if (href.Has())
|
||||
{
|
||||
var start = href.LastIndexOf('/');
|
||||
var end = href.IndexOf(".html");
|
||||
if (start != -1 && end != -1)
|
||||
{
|
||||
trData.Id = href.Substring(start + 1, end - start).TrimEnd('.');
|
||||
}
|
||||
}
|
||||
return new ApiResult<OriginAccountModel>(trData);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message+"-->info:"+ info);
|
||||
return new ApiResult<OriginAccountModel>(ResultCode.C_INVALID_ERROR, "查询失败");
|
||||
}
|
||||
|
||||
return new ApiResult<OriginAccountModel>(ResultCode.C_INVALID_ERROR, "没有查询到信息");
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 修改账号密码
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> UpdateAccountPwd(string account, string pwd)
|
||||
{
|
||||
var ret = await this.GetAccountInfo(account);
|
||||
if (ret.Code != ResultCode.C_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var accountModel = ret.Data;
|
||||
if (accountModel == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"username",account },
|
||||
{"password",pwd },
|
||||
{"submit","提交" },
|
||||
};
|
||||
LogHelper.Info(GetOpTitle("UpdateAccountPwd", account), map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.UpdateUrl + accountModel.Id + ".html", map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("更新成功") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("UpdateAccountPwd", account), content);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("UpdateAccountPwd", account), ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 退款
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> Refund(string account, string packageKey, int days)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"refundUser",account },
|
||||
{"refundReason","hl" },
|
||||
};
|
||||
var title = GetOpTitle("Refund", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.RefundUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
content = System.Text.RegularExpressions.Regex.Unescape(content);
|
||||
if (content.Has() && content.IndexOf("退款成功") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "退款失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否在线
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult<List<OriginAccountOnlineModel>>> OnLine(string account)
|
||||
{
|
||||
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("OnLine", account);
|
||||
|
||||
var info = "";
|
||||
try
|
||||
{
|
||||
var url = this.OnlineUrl + account;
|
||||
var resp = await client.GetAsync(url);
|
||||
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<OriginAccountOnlineModel>();
|
||||
if (trs.Count() > 1)
|
||||
{
|
||||
foreach (var tr in trs.Skip(1))
|
||||
{
|
||||
var tds = tr.QuerySelectorAll("td").ToList();
|
||||
var tdAccount = tds[1].FirstChild.TextContent;
|
||||
if (tdAccount != account)
|
||||
continue;
|
||||
info = string.Join("", tds.Select(m => m.OuterHtml));
|
||||
//序号 会员账号 服务器IP 登录时间 在线时长 会员IP 上行流量 下行流量 操作
|
||||
|
||||
var trData = new OriginAccountOnlineModel
|
||||
{
|
||||
Account = account,
|
||||
ServerIP = tds[2].TextContent,
|
||||
LoginTime = tds[3].TextContent,
|
||||
OnlineTime = tds[4].TextContent,
|
||||
LoginIP = tds[5].TextContent,
|
||||
UpStream = tds[6].TextContent,
|
||||
DownStream = tds[7].TextContent,
|
||||
Id= account,
|
||||
};
|
||||
var href = tr.LastElementChild.QuerySelector("a")?.Attributes["href"]?.Value;
|
||||
if (href.Has())
|
||||
{
|
||||
var start = href.LastIndexOf('/');
|
||||
var end = href.IndexOf(".html");
|
||||
if (start != -1 && end != -1)
|
||||
{
|
||||
trData.Id = href.Substring(start + 1, end - start).TrimEnd('.');
|
||||
}
|
||||
}
|
||||
retData.Add(trData);
|
||||
}
|
||||
}
|
||||
return new ApiResult<List<OriginAccountOnlineModel>>(retData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message + "-->info:" + info);
|
||||
return new ApiResult<List<OriginAccountOnlineModel>>(ResultCode.C_INVALID_ERROR, "查询失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 踢号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> KillOut( string id)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("KillOut", id);
|
||||
var info = "";
|
||||
try
|
||||
{
|
||||
var url = string.Format(this.KIllUrl, id);
|
||||
var resp = await client.GetAsync(url);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if(content.Has()&&content.IndexOf("断开成功")!=-1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message + "-->info:" + info);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否存在
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> Exist(string account)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("Exist", account);
|
||||
LogHelper.Info(title, account);
|
||||
var testRet = await this.NewAccount("free", account, "1234", 1, 0);
|
||||
if (testRet.Code == ResultCode.C_SUCCESS)
|
||||
{
|
||||
await DeleteAccount(account);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
526
Services/Hncore.Pass.Vpn/Service/AgentClient2Service.cs
Normal file
526
Services/Hncore.Pass.Vpn/Service/AgentClient2Service.cs
Normal file
@@ -0,0 +1,526 @@
|
||||
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.Threading.Tasks;
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
//老鹰A组
|
||||
public class AgentClient2Service : AgentClientBaseService
|
||||
{
|
||||
string LoginUrl { get; set; } = "index.php/admin/index/login.html";
|
||||
string LoginCodeUrl { get; set; } = "main/imgcode.html";
|
||||
string RefrushTokenUrl { get; set; } = "index.php/admin/index/public_welcome.html";// "";
|
||||
string SingleAddUrl { get; set; } = "index.php/admin/users/useradd.html";
|
||||
string SingleReAddUrl { get; set; } = "index.php/admin/users/userrenew.html";
|
||||
string MuiltAddUrl { get; set; } = "index.php/admin/users/usersadd.html";
|
||||
string RefundUrl { get; set; } = "index.php/admin/users/userrefund.html";
|
||||
string OnlineUrl { get; set; } = "";
|
||||
string GetAccount { get; set; } = "index.php/admin/users/users/grid/datagrid.html";
|
||||
string KIllUrl { get; set; } = "index.php/admin/users/useroffline.html";
|
||||
string UpdateUrl { get; set; } = "index.php/admin/users/useredit.html";
|
||||
string DeleteAccountUrl { get; set; } = "index.php/admin/users/userdelete.html";
|
||||
string searchAccountUrl = "index.php/admin/users/users/grid/datagrid.html";
|
||||
string existCheckUrl = "index.php/admin/users/public_checkusername.html";
|
||||
string refrushCookie = "admin/Common/getCookie";
|
||||
string sessionlife = "index.php/admin/index/public_sessionlife.html";
|
||||
IHttpClientFactory m_HttpClientFactory;
|
||||
public AgentClient2Service(IHttpClientFactory httpClientFactory):base(httpClientFactory)
|
||||
{
|
||||
m_HttpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
public async Task<int> RefrushStatus1()
|
||||
{
|
||||
int status = 0;
|
||||
if (this.Token.Has())
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
if (this.RefrushTokenUrl.Has())
|
||||
{
|
||||
var getResp = await client.GetAsync(this.RefrushTokenUrl);
|
||||
var content = await getResp.Content.ReadAsStringAsync();
|
||||
if (getResp.StatusCode == HttpStatusCode.OK && content.IndexOf("正常登录") == -1)
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("离线");
|
||||
Debug.WriteLine(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
public override async Task<int> RefrushStatus()
|
||||
{
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"key","1" }
|
||||
};
|
||||
int status = 0;
|
||||
var client = CreateHttpClient();
|
||||
client.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest");
|
||||
var getResp = await client.PostAsForm(this.sessionlife, map);
|
||||
var content = await getResp.Content.ReadAsStringAsync();
|
||||
content= System.Text.RegularExpressions.Regex.Unescape(content);
|
||||
if (getResp.StatusCode == HttpStatusCode.OK && content.IndexOf("登录后台") == -1)
|
||||
{
|
||||
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("离线");
|
||||
// }
|
||||
//}
|
||||
client.DefaultRequestHeaders.Remove("X-Requested-With");
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
private async Task<string> GetHomeCookie()
|
||||
{
|
||||
var client = CreateHttpClient(false);
|
||||
if (this.LoginUrl.NotHas()) return "";
|
||||
var getResp = await client.GetAsync(this.LoginUrl);
|
||||
var cookies = this.GetCookies(getResp);
|
||||
cookies=cookies.Replace("path=/;", "").Replace("httponly", "").Trim();
|
||||
return cookies;
|
||||
}
|
||||
|
||||
public override async Task<ApiResult> Login(AgentLoginRequest request)
|
||||
{
|
||||
var client = CreateHttpClient(false);
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"managername",request.Account },
|
||||
{"password",request.Pwd },
|
||||
// {"authnum",request.Code },
|
||||
};
|
||||
LogHelper.Info("Login", map.ToJson());
|
||||
request.Key = await GetHomeCookie();
|
||||
AddCookie(client, request.Key);
|
||||
var resp = await client.PostAsForm(this.LoginUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.IndexOf("index.html") == -1)
|
||||
{
|
||||
return new ApiResult(ResultCode.C_VISITOR_CHECKING, "登录失败");
|
||||
}
|
||||
return new ApiResult(request.Key);
|
||||
}
|
||||
|
||||
public override bool CheckAccount(int productId,List<string> accounts)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新开
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewAccount(string packageKey, string account, string pwd, int connCount = 1, int accountType = 1, int payCount = 1)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"info[groupid]","2001" },
|
||||
{"info[srvid]","6" },
|
||||
{"info[username]",account },
|
||||
{"info[password]",pwd },
|
||||
{"info[cycle]",packageKey },
|
||||
{"info[simuse]",connCount.ToString() },
|
||||
{"info[usetime]","1" },
|
||||
{"info[tryuse]",accountType==1?"0":"1"},
|
||||
};
|
||||
var title = GetOpTitle("NewAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.SingleAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("开通成功") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "开户失败");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量新开
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewMuiltAccount(string packageKey, string account, string pwd, int connCount = 1, int accountType = 1,int startNum=0, int endNum=1 )
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"info[groupid]","2001" },
|
||||
{"info[srvid]","6" },
|
||||
{"info[username_header]",account },
|
||||
{"info[username_start]",startNum.ToString() },
|
||||
{"info[username_end]",endNum.ToString() },
|
||||
{"info[pwdtype]","0" },
|
||||
{"info[password]",pwd },
|
||||
{"info[repassword]",pwd },
|
||||
{"info[cycle]",packageKey },
|
||||
{"info[simuse]",connCount.ToString() },
|
||||
{"info[usetime]","1" },
|
||||
{"info[tryuse]","0" },
|
||||
};
|
||||
var title = GetOpTitle("NewMuiltAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.MuiltAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("开通成功") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "开户失败");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 续费
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewReAccount(string packageKey,string account, int connCount)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
Dictionary<string, int> priceMap = new Dictionary<string, int>()
|
||||
{
|
||||
{"daycardprice",3},
|
||||
{"weekcardprice",15},
|
||||
{"monthcardprice",60},
|
||||
};
|
||||
var price = priceMap[packageKey];
|
||||
var totalAmount = price * connCount;
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"info[username]",account },
|
||||
{"info[cycle]",packageKey },
|
||||
{"info[simuse]",connCount.ToString()},
|
||||
{"info[usetime]","1" },
|
||||
{"info[usemoney]",totalAmount.ToString() },
|
||||
};
|
||||
var title = GetOpTitle("NewReAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.SingleReAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("续费成功") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "续费失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除账号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> DeleteAccount(string account)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"usernames",account }
|
||||
};
|
||||
LogHelper.Info(GetOpTitle("DeleteAccount", account), map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.SingleAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("删除成功") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("DeleteAccount", account), content);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("DeleteAccount", account), ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 得到账号信息
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult<OriginAccountModel>> GetAccountInfo(string account,bool isTest)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"search[username]",account },
|
||||
{"page","1" },
|
||||
{"rows","25" },
|
||||
};
|
||||
var title = GetOpTitle("GetAccountInfo", account);
|
||||
try
|
||||
{
|
||||
var content = await client.PostAsFormGetString(this.searchAccountUrl, map);
|
||||
|
||||
JObject jo = (JObject)JsonConvert.DeserializeObject(content);
|
||||
var rows = jo["rows"].ToArray();
|
||||
var row = rows.FirstOrDefault();
|
||||
var trData = new OriginAccountModel
|
||||
{
|
||||
User = row["groupname"].ToString(),
|
||||
Account = row["username"].ToString(),
|
||||
AccountType = row["username"].ToString(),
|
||||
Package = row["cycle"].ToString(),
|
||||
RegistTime = row["createdon"].ToString(),
|
||||
EndTime = row["expiration"].ToString(),
|
||||
ConnectCount = row["simuse"].ToString(),
|
||||
Pwd=row["open_password"].ToString(),
|
||||
// Amount = row["cycle"].ToString(),
|
||||
RestTime = row["havetime"].ToString(),
|
||||
IsActive = row["status"].ToString(),
|
||||
Remark = row["comment"].ToString(),
|
||||
OnLine = row["status"].ToString().IndexOf("在线") == -1 ? 0 : 1,
|
||||
LoginTime= row["acctstarttime"].ToString(),
|
||||
LoginServer= row["nasipaddress"].ToString(),
|
||||
};
|
||||
trData.RealEndTime = DateTime.Parse(trData.EndTime);
|
||||
return new ApiResult<OriginAccountModel>(trData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message);
|
||||
return new ApiResult<OriginAccountModel>(ResultCode.C_INVALID_ERROR, "查询失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 修改账号密码
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> UpdateAccountPwd(string account,string pwd)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"info[groupid]","2001" },
|
||||
{"info[srvid]","6" },
|
||||
{"info[username]",account },
|
||||
{"info[password]",pwd },
|
||||
};
|
||||
|
||||
LogHelper.Info(GetOpTitle("UpdateAccountPwd", account), map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.UpdateUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("修改成功") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("UpdateAccountPwd", account), content);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("UpdateAccountPwd", account), ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 退款
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> Refund(string account, string packageKey, int days)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"info[username]",account },
|
||||
{"info[cycle]",packageKey },
|
||||
{"info[expiretime]",days.ToString() },
|
||||
};
|
||||
var title = GetOpTitle("Refund", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.RefundUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("退款成功") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "退款失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否在线
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult<List<OriginAccountOnlineModel>>> OnLine(string account)
|
||||
{
|
||||
var accountInfo =await this.GetAccountInfo(account, false);
|
||||
if (accountInfo.Code != ResultCode.C_SUCCESS) return await base.OnLine(account);
|
||||
|
||||
var list = new List<OriginAccountOnlineModel>();
|
||||
if (accountInfo.Data.OnLine == 1)
|
||||
{
|
||||
list.Add(new OriginAccountOnlineModel()
|
||||
{
|
||||
Account = account,
|
||||
OnLine = accountInfo.Data.OnLine,
|
||||
Id = account,
|
||||
LoginTime= accountInfo.Data.LoginTime,
|
||||
LoginIP= accountInfo.Data.LoginServer
|
||||
});
|
||||
}
|
||||
return new ApiResult<List<OriginAccountOnlineModel>>(list);
|
||||
}
|
||||
/// <summary>
|
||||
/// 踢号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account">账号</param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> KillOut( string account)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
client.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest");
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"usernames",account },
|
||||
};
|
||||
var title = GetOpTitle("KillOut", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.KIllUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("次踢人操作") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Error(title, content);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否存在
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> Exist(string account)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"username",account }
|
||||
};
|
||||
var title = GetOpTitle("Exist", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.existCheckUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("false") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
539
Services/Hncore.Pass.Vpn/Service/AgentClient3Service.cs
Normal file
539
Services/Hncore.Pass.Vpn/Service/AgentClient3Service.cs
Normal file
@@ -0,0 +1,539 @@
|
||||
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.Threading.Tasks;
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
//老鹰B组
|
||||
public class AgentClient3Service : AgentClientBaseService
|
||||
{
|
||||
string LoginUrl { get; set; } = "api/login";
|
||||
string LoginCodeUrl { get; set; } = "";
|
||||
string RefrushTokenUrl { get; set; } = "api/info?_=";
|
||||
string SingleAddUrl { get; set; } = "api/ppp/one";
|
||||
string ReAddUrl { get; set; } = "api/ppp/renewal";
|
||||
string MuiltAddUrl { get; set; } = "api/ppp/batch";
|
||||
string RefundUrl { get; set; } = "api/ppp/delete";
|
||||
string OnlineUrl { get; set; } = "api/ppp/oln?user={0}&_={1}";
|
||||
string GetAccount { get; set; } = "index.php/admin/users/users/grid/datagrid.html";
|
||||
string KIllUrl { get; set; } = "api/ppp/oln/stop";
|
||||
string UpdateUrl { get; set; } = "api/ppp/update";
|
||||
string DeleteAccountUrl { get; set; } = "api/ppp/delete?user=hl&_=1583126809671";
|
||||
string InfoUrl = "api/ppp?page=1&user=";
|
||||
string TestAddUrl { get; set; } = "api/ppp/test";
|
||||
IHttpClientFactory m_HttpClientFactory;
|
||||
public AgentClient3Service(IHttpClientFactory httpClientFactory):base(httpClientFactory)
|
||||
{
|
||||
m_HttpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
public override async Task<int> RefrushStatus()
|
||||
{
|
||||
int status = 0;
|
||||
if (this.Token.Has())
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
if (this.RefrushTokenUrl.Has())
|
||||
{
|
||||
var getResp = await client.GetAsync(this.RefrushTokenUrl+DateTime.Now.GetUnixTimeStamp());
|
||||
var content = await getResp.Content.ReadAsStringAsync();
|
||||
if (getResp.StatusCode == HttpStatusCode.OK && content.IndexOf("\"ret\":200") != -1)
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("离线");
|
||||
Debug.WriteLine(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
public override async Task<ApiResult> Login(AgentLoginRequest request)
|
||||
{
|
||||
var client = CreateHttpClient(false);
|
||||
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"username",request.Account },
|
||||
{"password",request.Pwd },
|
||||
{"autologon","false"},
|
||||
};
|
||||
LogHelper.Info("Login", map.ToJson());
|
||||
var resp = await client.PostAsForm(this.LoginUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.IndexOf("登陆成功")!= -1)
|
||||
{
|
||||
request.Key = this.GetCookie(resp, "_dailissid");
|
||||
return new ApiResult(request.Key);
|
||||
}
|
||||
return new ApiResult(ResultCode.C_VISITOR_CHECKING, "登录失败");
|
||||
}
|
||||
public override bool CheckAccount(int productId,List<string> accounts)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新开
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewAccount(string packageKey, string account, string pwd, int connCount = 1, int accountType = 1, int payCount = 1)
|
||||
{
|
||||
if (accountType == 0)//新开测试号
|
||||
{
|
||||
return await NewTestAccount(account, pwd);
|
||||
}
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"user",account },
|
||||
{"passwd",pwd },
|
||||
{"type",packageKey },
|
||||
{"conn_max",connCount.ToString() },
|
||||
{"paynum",payCount.ToString()},
|
||||
{"details","hl" },
|
||||
};
|
||||
var title = GetOpTitle("NewAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.SingleAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("开户成功") != -1)
|
||||
{
|
||||
return new ApiResult(ResultCode.C_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
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 async Task<ApiResult> NewTestAccount(string account, string pwd)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"user",account },
|
||||
{"passwd",pwd },
|
||||
};
|
||||
var title = GetOpTitle("NewTestAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.TestAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("开户成功") != -1)
|
||||
{
|
||||
return new ApiResult(ResultCode.C_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "开户失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 批量新开
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewMuiltAccount(string packageKey, string account, string pwd, int connCount = 1, int accountType = 1, int startNum = 0, int endNum = 1)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"user",account },
|
||||
{"passwd",pwd },
|
||||
{"form",startNum.ToString() },
|
||||
{"to",endNum.ToString() },
|
||||
{"type",packageKey },
|
||||
{"conn_max",connCount.ToString() },
|
||||
{"paynum","1" },
|
||||
{"details","hl" },
|
||||
};
|
||||
var title = GetOpTitle("NewMuiltAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.MuiltAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("开户成功") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "开户失败");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 续费
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewReAccount(string packageKey, string account, int connCount)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"user",account },
|
||||
{"type",packageKey },
|
||||
{"paynum","1"},
|
||||
};
|
||||
var title = GetOpTitle("NewReAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.ReAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("续费成功") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "续费失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除账号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> DeleteAccount(string account)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"usernames",account }
|
||||
};
|
||||
LogHelper.Info(GetOpTitle("DeleteAccount", account), map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.SingleAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("删除成功") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("DeleteAccount", account), content);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("DeleteAccount", account), ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 得到账号信息
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult<OriginAccountModel>> GetAccountInfo(string account,bool isTest)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("GetAccountInfo", account);
|
||||
var info = "";
|
||||
try
|
||||
{
|
||||
var resp = await client.GetAsync(this.InfoUrl+account);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
info = content;
|
||||
JObject jo = (JObject)JsonConvert.DeserializeObject(content);
|
||||
var datas = jo["data"]["data"];
|
||||
var row = datas?.FirstOrDefault();
|
||||
var trData = new OriginAccountModel
|
||||
{
|
||||
User = row["user"].ToString(),
|
||||
Account = row["user"].ToString(),
|
||||
AccountType = row["type"].ToString(),
|
||||
Package ="",
|
||||
RegistTime = Convert.ToInt64(row["add_time"]).LoadFromUnixTimeStamp().AddHours(8).ToString(),
|
||||
EndTime =Convert.ToInt64(row["end_time"]).LoadFromUnixTimeStamp().AddHours(8).ToString(),
|
||||
ConnectCount = row["conn_max"].ToString(),
|
||||
Pwd = row["passwd"].ToString(),
|
||||
};
|
||||
trData.RealEndTime = DateTime.Parse(trData.EndTime);
|
||||
|
||||
var restDay = (trData.RealEndTime - DateTime.Now).Days;
|
||||
restDay = restDay < 0 ? 0 : restDay;
|
||||
if (restDay <= 1) trData.Package = "天";
|
||||
else if(restDay <= 7) trData.Package = "周";
|
||||
else trData.Package = "月";
|
||||
return new ApiResult<OriginAccountModel>(trData);
|
||||
|
||||
//var parser = new HtmlParser();
|
||||
//var document = await parser.ParseDocumentAsync(content);
|
||||
//////table class="table table-bordered"
|
||||
//var trs = document.QuerySelectorAll("table[class='table table-bordered']>tr").ToList();
|
||||
//// var trs= table.QuerySelectorAll("tr").ToList();
|
||||
//if (trs.Count() > 1)
|
||||
//{
|
||||
// var tr = trs.Skip(1).FirstOrDefault();
|
||||
// var tdTexts = tr.QuerySelectorAll("td").Select(m => m.TextContent).ToList();
|
||||
// //<td >会员账号</td><td >类型</td><td >套餐</td><td >注册日期</td><td >过期日期</td><td >连接数</td><td >余额</td><td >激活</td><td >备注</td>
|
||||
// var trData = new OriginAccountModel
|
||||
// {
|
||||
// Account = tdTexts[0],
|
||||
// AccountType = tdTexts[1],
|
||||
// Package = tdTexts[2],
|
||||
// RegistTime = tdTexts[3],
|
||||
// EndTime = tdTexts[4],
|
||||
// ConnectCount = tdTexts[5],
|
||||
// Amount = tdTexts[6],
|
||||
// IsActive = tdTexts[7],
|
||||
// Remark = tdTexts[8],
|
||||
// };
|
||||
// var href = tr.LastElementChild.QuerySelector("a")?.Attributes["href"]?.Value;
|
||||
// if (href.Has())
|
||||
// {
|
||||
// var start = href.LastIndexOf('/');
|
||||
// var end = href.IndexOf(".html");
|
||||
// if (start != -1 && end != -1)
|
||||
// {
|
||||
// trData.Id = href.Substring(start, end - start);
|
||||
// }
|
||||
// }
|
||||
|
||||
// return new ApiResult<OriginAccountModel>(trData);
|
||||
//}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message+"-->info:"+ info);
|
||||
return new ApiResult<OriginAccountModel>(ResultCode.C_INVALID_ERROR, "查询失败");
|
||||
}
|
||||
|
||||
return new ApiResult<OriginAccountModel>(ResultCode.C_INVALID_ERROR, "没有查询到信息");
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 修改账号密码
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> UpdateAccountPwd(string account,string pwd)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"user",account },
|
||||
{"new_user",account},
|
||||
{"passwd",pwd },
|
||||
{"details","hl" },
|
||||
};
|
||||
|
||||
LogHelper.Info(GetOpTitle("UpdateAccountPwd", account), map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.UpdateUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("修改成功") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("UpdateAccountPwd", account), content);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("UpdateAccountPwd", account), ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 退款
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> Refund(string account, string packageKey, int days)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("Refund", account);
|
||||
try
|
||||
{
|
||||
var resp = await client.GetAsync(this.RefundUrl+$"?user={account}&_={DateTime.Now.GetUnixTimeStamp()} ");
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
content = System.Text.RegularExpressions.Regex.Unescape(content);
|
||||
if (content.Has() && content.IndexOf("删除成功") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "退款失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否在线
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult<List<OriginAccountOnlineModel>>> OnLine(string account)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("OnLine", account);
|
||||
var info = "";
|
||||
try
|
||||
{
|
||||
string url = string.Format(this.OnlineUrl, account, DateTime.Now.GetUnixTimeStamp());
|
||||
var resp = await client.GetAsync(url);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
info = content;
|
||||
|
||||
JObject jo = (JObject)JsonConvert.DeserializeObject(content);
|
||||
var datas = jo["data"]["data"];
|
||||
var rows = datas.Children();
|
||||
var retData = new List<OriginAccountOnlineModel>();
|
||||
if (datas!=null&& rows.Count() > 0)
|
||||
{
|
||||
foreach (var row in rows)
|
||||
{
|
||||
var trData = new OriginAccountOnlineModel()
|
||||
{
|
||||
Account = account,
|
||||
OnLine = 1,
|
||||
LoginIP = row["client_ip"].ToString(),
|
||||
ServerIP=row["nas_name"].ToString(),
|
||||
LoginTime=row["add_time"].ToString(),
|
||||
Id = row["id"].ToString()
|
||||
};
|
||||
trData.LoginTime = (DateTime.Now - trData.LoginTime.LoadFromUnixTimeStamp().Value).ToString("d\\.hh\\:mm\\:ss");
|
||||
retData.Add(trData);
|
||||
}
|
||||
}
|
||||
return new ApiResult<List<OriginAccountOnlineModel>>(retData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message + "-->info:" + info);
|
||||
return await base.OnLine(account);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 踢号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> KillOut( string id)
|
||||
{
|
||||
// formData id: d9bd8ac88e31d43b0507f5f66927c2ee
|
||||
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"id",id },
|
||||
};
|
||||
|
||||
LogHelper.Info(GetOpTitle("KillOut", id), map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.KIllUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("踢线成功") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("KillOut", id), content);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("KillOut", id), ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否存在
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> Exist(string account)
|
||||
{
|
||||
// return false;
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"groupname",account }
|
||||
};
|
||||
var title = GetOpTitle("Exist", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
|
||||
var ret = await this.NewAccount("w", account, "123");
|
||||
if (ret.Code == ResultCode.C_SUCCESS)
|
||||
{
|
||||
await this.Refund(account, "w", 1);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
591
Services/Hncore.Pass.Vpn/Service/AgentClient4Service.cs
Normal file
591
Services/Hncore.Pass.Vpn/Service/AgentClient4Service.cs
Normal file
@@ -0,0 +1,591 @@
|
||||
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 Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
//金桥
|
||||
public class AgentClient4Service: AgentClient1Service
|
||||
{
|
||||
string LoginUrl { get; set; } = "main/agentLogin.html";
|
||||
string LoginCodeUrl { get; set; } = "main/imgcode.html";
|
||||
string RefrushTokenUrl { get; set; } = "agent.html";
|
||||
string SingleAddUrl { get; set; } = "agent/memberSingleAdd.html";
|
||||
string SingleReAddUrl { get; set; } = "agent/memberRenew.html";
|
||||
string MuiltAddUrl { get; set; } = "agent/memberMuiltAdd.html";
|
||||
string RefundUrl { get; set; } = "agent/memberRefundAct.html ";
|
||||
string UpdateUrl = "agent/memberUpdate/id/";//agent/memberUpdate/id/1155709.html
|
||||
string OnlineUrl { get; set; } = "";
|
||||
string KIllUrl { get; set; } = "";
|
||||
string searchAccountUrl = "agent/memberList/type/1.html?search=1&username=";
|
||||
string searchTestAccountUrl = "agent/memberList/type/0.html?search=1&username=";
|
||||
string DeleteUrl { get; set; } = "agent/memberDel/id/";//1160862.html";
|
||||
string KillUrlClient = "/agent/disConnect/sessionid/{0}.html";
|
||||
string ClientOnlineUrl { get; set; } = "agent/clientOnline/page/{0}.html";
|
||||
IHttpClientFactory m_HttpClientFactory;
|
||||
public AgentClient4Service(IHttpClientFactory httpClientFactory):base(httpClientFactory)
|
||||
{
|
||||
m_HttpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
public override async Task<int> 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);
|
||||
var content = await getResp.Content.ReadAsStringAsync();
|
||||
if (getResp.StatusCode == HttpStatusCode.OK && content.IndexOf("agentLogin.html") == -1)
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("离线");
|
||||
Debug.WriteLine(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
public override async Task<(byte[], string)> GetCode()
|
||||
{
|
||||
var client = CreateHttpClient(false);
|
||||
if (this.LoginUrl.NotHas()) return (null, "");
|
||||
var getResp = await client.GetAsync(this.LoginUrl);
|
||||
var cookie = this.GetCookie(getResp, "PHPSESSID");
|
||||
if (cookie.Has())
|
||||
{
|
||||
client.DefaultRequestHeaders.Add("Cookie", cookie);
|
||||
var ret = await client.GetByteArrayAsync(this.LoginCodeUrl + "?t=" + DateTime.Now.Millisecond);
|
||||
return (ret, cookie);
|
||||
}
|
||||
return (null, "");
|
||||
}
|
||||
public override async Task<ApiResult> Login(AgentLoginRequest request)
|
||||
{
|
||||
var client = CreateHttpClient(false);
|
||||
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"agentName",request.Account },
|
||||
{"password",request.Pwd },
|
||||
{"authnum",request.Code },
|
||||
};
|
||||
LogHelper.Info("Login", map.ToJson());
|
||||
AddCookie(client, request.Key);
|
||||
//client.DefaultRequestHeaders.Add("Cookie", request.Key);
|
||||
var resp = await client.PostAsForm(this.LoginUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.IndexOf("alert alert-danger") != -1)
|
||||
{
|
||||
return new ApiResult(ResultCode.C_VISITOR_CHECKING, "登录失败");
|
||||
}
|
||||
return new ApiResult(request.Key);
|
||||
}
|
||||
public override bool CheckAccount(int productId,List<string> accounts)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新开
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewAccount(string packageKey, string account, string pwd, int connCount = 1, int accountType = 1, int payCount = 1)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"taocanName",packageKey },
|
||||
{"username",account },
|
||||
{"password",pwd },
|
||||
{"maxonline",connCount.ToString()},
|
||||
{"type",accountType.ToString()}
|
||||
};
|
||||
var title = GetOpTitle("NewAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.SingleAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("{alert(\"成功\")") != -1)
|
||||
{
|
||||
return new ApiResult(ResultCode.C_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "开户失败");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新开
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewMuiltAccount(string packageKey, string account, string pwd, int connCount = 1, int accountType = 1,int startNum=0, int endNum=1 )
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"taocanName",packageKey },
|
||||
{"usernameTpl",account },
|
||||
{"password",pwd },
|
||||
{"maxonline",connCount.ToString()},
|
||||
{"startNum",startNum.ToString()},
|
||||
{"endNum",endNum.ToString()},
|
||||
{"mode",accountType.ToString()},
|
||||
};
|
||||
var title = GetOpTitle("NewMuiltAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.MuiltAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("<td>成功</td>") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "开户失败");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 续费
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewReAccount(string packageKey, string account, int connCount)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"taocanName",packageKey },
|
||||
{"username",account },
|
||||
{"iscz","3" },
|
||||
};
|
||||
var title = GetOpTitle("NewReAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.SingleReAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("alert(\"成功\")") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "续费失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除账号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> DeleteAccount(string account)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var infoRet = await this.GetAccountInfo(account, true);
|
||||
if (infoRet.Code != ResultCode.C_SUCCESS)
|
||||
return false;
|
||||
|
||||
var title = GetOpTitle("DeleteAccount", account);
|
||||
LogHelper.Info(title, account);
|
||||
try
|
||||
{
|
||||
var delete = this.DeleteUrl + infoRet.Data.Id + ".html";
|
||||
var resp = await client.GetAsync(delete);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("alert(\"删除成功\")") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Error(title, content);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 得到账号信息
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult<OriginAccountModel>> GetAccountInfo(string account,bool isTest=false)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("GetAccountInfo", account);
|
||||
var info = "";
|
||||
try
|
||||
{
|
||||
var url = this.searchAccountUrl + account;
|
||||
if (isTest)
|
||||
{
|
||||
url = this.searchTestAccountUrl + account;
|
||||
}
|
||||
var resp = await client.GetAsync(url);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
|
||||
var parser = new HtmlParser();
|
||||
var document = await parser.ParseDocumentAsync(content);
|
||||
////table class="table table-bordered"
|
||||
var trs = document.QuerySelectorAll("table.table tr").ToList();
|
||||
// var trs= table.QuerySelectorAll("tr").ToList();
|
||||
var retData = new List<OriginAccountModel>();
|
||||
if (trs.Count() > 1)
|
||||
{
|
||||
//var tr = trs.Skip(1).FirstOrDefault();
|
||||
foreach(var tr in trs.Skip(1))
|
||||
{
|
||||
var tds = tr.QuerySelectorAll("td").ToList();
|
||||
var tdAccount = tds[1].FirstChild.TextContent;
|
||||
if (tdAccount != account)
|
||||
continue;
|
||||
info = string.Join("", tds.Select(m => m.OuterHtml));
|
||||
//<td >会员账号</td><td >类型</td><td >套餐</td><td >注册日期 过期日期</td><td>专线IP </td><td >连接数</td><td >余额</td><td >激活</td><td >备注</td>
|
||||
|
||||
var dateText = tds[4].InnerHtml;
|
||||
var endtext = dateText.Split("<br>")[1].Split('\n');
|
||||
var trData = new OriginAccountModel
|
||||
{
|
||||
Account = account,
|
||||
Pwd = tds[1].QuerySelector("font").TextContent,
|
||||
AccountType = tds[2].TextContent,
|
||||
Package = tds[3].TextContent,
|
||||
RegistTime = dateText.Split("<br>")[0],
|
||||
EndTime = endtext[0].Replace("\n", "").Replace("\t", ""),
|
||||
RestTime = endtext[1].Replace("\n", "").Replace("\t", ""),
|
||||
ConnectCount = tds[6].TextContent,
|
||||
Amount = tds[7].TextContent,
|
||||
IsActive = tds[8].TextContent,
|
||||
Remark = tds[9].TextContent,
|
||||
};
|
||||
|
||||
trData.RealEndTime = DateTime.Parse(trData.EndTime);
|
||||
if (trData.RestTime.Contains("已过期"))
|
||||
{
|
||||
trData.RestTime = "已过期";
|
||||
}else
|
||||
{
|
||||
// "6.14:32"
|
||||
var timeStr = trData.RestTime.Replace("天", ".").Replace("时", ":").Replace("分", "");
|
||||
var restTime = TimeSpan.Parse(timeStr);
|
||||
trData.RealEndTime = DateTime.Now.Add(restTime);
|
||||
}
|
||||
|
||||
var href = tr.LastElementChild.QuerySelector("a")?.Attributes["href"]?.Value;
|
||||
if (href.Has())
|
||||
{
|
||||
var start = href.LastIndexOf('/');
|
||||
var end = href.IndexOf(".html");
|
||||
if (start != -1 && end != -1)
|
||||
{
|
||||
trData.Id = href.Substring(start + 1, end - start).TrimEnd('.');
|
||||
}
|
||||
}
|
||||
return new ApiResult<OriginAccountModel>(trData);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message+"-->info:"+ info);
|
||||
return new ApiResult<OriginAccountModel>(ResultCode.C_INVALID_ERROR, "查询失败");
|
||||
}
|
||||
|
||||
return new ApiResult<OriginAccountModel>(ResultCode.C_INVALID_ERROR, "没有查询到信息");
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 修改账号密码
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> UpdateAccountPwd(string account, string pwd)
|
||||
{
|
||||
var ret = await this.GetAccountInfo(account);
|
||||
if (ret.Code != ResultCode.C_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var accountModel = ret.Data;
|
||||
if (accountModel == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"username",account },
|
||||
{"password",pwd },
|
||||
{"submit","提交" },
|
||||
};
|
||||
LogHelper.Info(GetOpTitle("UpdateAccountPwd", account), map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.UpdateUrl + accountModel.Id + ".html", map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("更新成功") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("UpdateAccountPwd", account), content);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("UpdateAccountPwd", account), ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 退款
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> Refund(string account, string packageKey, int days)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"refundUser",account },
|
||||
{"refundReason","hl" },
|
||||
};
|
||||
var title = GetOpTitle("Refund", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.RefundUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("alert(\"退款成功\")") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "退款失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否在线
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult<List<OriginAccountOnlineModel>>> OnLine(string account)
|
||||
{
|
||||
//虚拟在线
|
||||
var onlines = await base.OnLine(account);
|
||||
|
||||
if (onlines.Code == ResultCode.C_SUCCESS && onlines.Data.Count > 0)
|
||||
return onlines;
|
||||
var retData = new List<OriginAccountOnlineModel>();
|
||||
var client = CreateHttpClient();
|
||||
int page = 1;
|
||||
var url = string.Format(this.ClientOnlineUrl, page);
|
||||
var resp = await client.GetAsync(url);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
|
||||
var parser = new HtmlParser();
|
||||
var document = await parser.ParseDocumentAsync(content);
|
||||
var table = document.QuerySelectorAll("table");
|
||||
var pageP = table?.Next("p")?.FirstOrDefault();
|
||||
if (pageP != null)
|
||||
{
|
||||
var total = 0;
|
||||
if (pageP.TextContent.Has())
|
||||
{
|
||||
var start = pageP.TextContent.IndexOf('(');
|
||||
var end = pageP.TextContent.IndexOf("页)");
|
||||
var pageStr = pageP.TextContent.Substring(start + 2, end - start - 1);
|
||||
int.TryParse(pageStr, out total);
|
||||
}
|
||||
if (total > 1)
|
||||
{
|
||||
await Enumerable.Range(1, total).ForEachAsync(async (int i) =>
|
||||
{
|
||||
var ret = await ClientOnLine(account, i);
|
||||
retData.AddRange(ret);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
retData = await ClientOnLine(account, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
retData = await ClientOnLine(account, 1);
|
||||
}
|
||||
return new ApiResult<List<OriginAccountOnlineModel>>(retData);
|
||||
}
|
||||
|
||||
public async Task<List<OriginAccountOnlineModel>> ClientOnLine(string account,int page=1)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("ClientOnLine", account);
|
||||
var info = "";
|
||||
var retData = new List<OriginAccountOnlineModel>();
|
||||
try
|
||||
{
|
||||
var url =string.Format(this.ClientOnlineUrl,page);
|
||||
var resp = await client.GetAsync(url);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
var parser = new HtmlParser();
|
||||
var document = await parser.ParseDocumentAsync(content);
|
||||
var trs = document.QuerySelectorAll("table.table tr").ToList();
|
||||
|
||||
if (trs.Count() > 1)
|
||||
{
|
||||
foreach (var tr in trs.Skip(1))
|
||||
{
|
||||
var tds = tr.QuerySelectorAll("td").ToList();
|
||||
var tdAccount = tds[1].FirstChild.TextContent;
|
||||
if (tdAccount != account)
|
||||
continue;
|
||||
info = string.Join("", tds.Select(m => m.OuterHtml));
|
||||
//序号 会员账号 登录时间 在线时长 客户端IP地址 操作
|
||||
var trData = new OriginAccountOnlineModel
|
||||
{
|
||||
Account = account,
|
||||
LoginTime = tds[2].TextContent,
|
||||
OnlineTime = tds[3].TextContent,
|
||||
LoginIP = tds[4].TextContent,
|
||||
};
|
||||
var href = tr.LastElementChild.QuerySelector("a")?.Attributes["href"]?.Value;
|
||||
if (href.Has())
|
||||
{
|
||||
var start = href.LastIndexOf('/');
|
||||
var end = href.IndexOf(".html");
|
||||
if (start != -1 && end != -1)
|
||||
{
|
||||
trData.Id = href.Substring(start + 1, end - start).TrimEnd('.');
|
||||
}
|
||||
}
|
||||
retData.Add(trData);
|
||||
}
|
||||
}
|
||||
return retData;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message + "-->info:" + info);
|
||||
}
|
||||
return retData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 踢号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> KillOut( string id)
|
||||
{
|
||||
var flag = await base.KillOut(id);
|
||||
if (flag) return true;
|
||||
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("KillOut", id);
|
||||
var info = "";
|
||||
try
|
||||
{
|
||||
var url = string.Format(this.KillUrlClient, id);
|
||||
var resp = await client.GetAsync(url);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("已经向客户端发送断开消息") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message + "-->info:" + info);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否存在
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> Exist(string account)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("Exist", account);
|
||||
LogHelper.Info(title, account);
|
||||
var testRet = await this.NewAccount("free", account, "1234", 1, 0);
|
||||
if (testRet.Code == ResultCode.C_SUCCESS)
|
||||
{
|
||||
await DeleteAccount(account);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
319
Services/Hncore.Pass.Vpn/Service/AgentClient5Service.cs
Normal file
319
Services/Hncore.Pass.Vpn/Service/AgentClient5Service.cs
Normal file
@@ -0,0 +1,319 @@
|
||||
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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
//先锋
|
||||
public class AgentClient5Service : AgentClient1Service
|
||||
{
|
||||
string LoginUrl { get; set; } = "main/agentLogin.html";
|
||||
string LoginCodeUrl { get; set; } = "main/imgcode.html";
|
||||
string RefrushTokenUrl { get; set; } = "agent.html";
|
||||
string SingleAddUrl { get; set; } = "agent/memberSingleAdd.html";
|
||||
string SingleReAddUrl { get; set; } = "agent/memberRenew.html";
|
||||
string MuiltAddUrl { get; set; } = "agent/memberMuiltAdd.html";
|
||||
string RefundUrl { get; set; } = "agent/memberRefund/id/{0}.html";
|
||||
string UpdateUrl = "agent/memberUpdate/id/{0}.html";//agent/memberUpdate/id/1155709.html
|
||||
string OnlineUrl { get; set; } = "agent/radiusOnline.html?search=1&username=";
|
||||
string ClientOnlineUrl { get; set; } = "agent/clientOnline.html?search=1&username=";
|
||||
string KIllUrl { get; set; } = "";
|
||||
string KillUrlClient = "/agent/disConnect/sessionid/{0}.html";
|
||||
string KillUrl = "/agent/disConnect/radacctid/{0}.html";
|
||||
string searchAccountUrl = "agent/memberList/type/1.html?search=1&username=";
|
||||
string searchTestAccountUrl = "agent/memberList/type/0.html?search=1&username=";
|
||||
string DeleteUrl { get; set; } = "agent/multiDelMember.html ";
|
||||
IHttpClientFactory m_HttpClientFactory;
|
||||
public AgentClient5Service(IHttpClientFactory httpClientFactory):base(httpClientFactory)
|
||||
{
|
||||
m_HttpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新开
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewAccount(string packageKey, string account, string pwd, int connCount = 1, int accountType = 1, int payCount = 1)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"taocanName",packageKey },
|
||||
{"username",account },
|
||||
{"password",pwd },
|
||||
{"bingfa",connCount.ToString()},
|
||||
{"type",accountType.ToString()}
|
||||
};
|
||||
var title = GetOpTitle("NewAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.SingleAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("{alert(\"成功\")") != -1)
|
||||
{
|
||||
return new ApiResult(ResultCode.C_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "开户失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除账号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> DeleteAccount(string account)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var infoRet = await this.GetAccountInfo(account, true);
|
||||
if (infoRet.Code != ResultCode.C_SUCCESS)
|
||||
return false;
|
||||
var map = new Dictionary<string, string>(){
|
||||
{infoRet.Data.Id,infoRet.Data.Id },
|
||||
};
|
||||
var title = GetOpTitle("DeleteAccount", account);
|
||||
LogHelper.Info(title, account);
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.DeleteUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("删除成功") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Error(title, content);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修改账号密码
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> UpdateAccountPwd(string account, string pwd)
|
||||
{
|
||||
var ret = await this.GetAccountInfo(account);
|
||||
if (ret.Code != ResultCode.C_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var accountModel = ret.Data;
|
||||
if (accountModel == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"username",account },
|
||||
{"password",pwd },
|
||||
{"maxOnline",ret.Data.ConnectCount },
|
||||
};
|
||||
LogHelper.Info(GetOpTitle("UpdateAccountPwd", account), map.ToJson());
|
||||
try
|
||||
{
|
||||
var url = string.Format(this.UpdateUrl, accountModel.Id);
|
||||
var resp = await client.PostAsForm(url, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("更新成功") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("UpdateAccountPwd", account), content);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("UpdateAccountPwd", account), ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 退款
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> Refund(string account, string packageKey, int days)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("Refund", account);
|
||||
try
|
||||
{
|
||||
var accountInfo = await this.GetAccountInfo(account);
|
||||
if (accountInfo.Code != ResultCode.C_SUCCESS)
|
||||
{
|
||||
return new ApiResult(ResultCode.C_INVALID_ERROR, "退款失败");
|
||||
}
|
||||
var url = string.Format(this.RefundUrl, accountInfo.Data.Id);
|
||||
var resp = await client.GetAsync(url);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("退款成功!") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "退款失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否在线
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult<List<OriginAccountOnlineModel>>> OnLine(string account)
|
||||
{
|
||||
//虚拟在线
|
||||
var onlines= await base.OnLine(account);
|
||||
|
||||
if (onlines.Code == ResultCode.C_SUCCESS && onlines.Data.Count > 0)
|
||||
return onlines;
|
||||
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("OnLine", account);
|
||||
var info = "";
|
||||
try
|
||||
{
|
||||
var url = this.ClientOnlineUrl + account;
|
||||
var resp = await client.GetAsync(url);
|
||||
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<OriginAccountOnlineModel>();
|
||||
if (trs.Count() > 1)
|
||||
{
|
||||
foreach (var tr in trs.Skip(1))
|
||||
{
|
||||
var tds = tr.QuerySelectorAll("td").ToList();
|
||||
var tdAccount = tds[1].FirstChild.TextContent;
|
||||
if (tdAccount != account)
|
||||
continue;
|
||||
info = string.Join("", tds.Select(m => m.OuterHtml));
|
||||
//序号 会员账号 登录时间 在线时长 客户端IP地址 操作
|
||||
|
||||
var trData = new OriginAccountOnlineModel
|
||||
{
|
||||
Account = account,
|
||||
LoginTime = tds[2].TextContent,
|
||||
OnlineTime = tds[3].TextContent,
|
||||
LoginIP = tds[4].TextContent,
|
||||
};
|
||||
var href = tr.LastElementChild.QuerySelector("a")?.Attributes["href"]?.Value;
|
||||
if (href.Has())
|
||||
{
|
||||
var start = href.LastIndexOf('/');
|
||||
var end = href.IndexOf(".html");
|
||||
if (start != -1 && end != -1)
|
||||
{
|
||||
trData.Id = href.Substring(start + 1, end - start).TrimEnd('.');
|
||||
}
|
||||
}
|
||||
retData.Add(trData);
|
||||
}
|
||||
}
|
||||
return new ApiResult<List<OriginAccountOnlineModel>>(retData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message + "-->info:" + info);
|
||||
return new ApiResult<List<OriginAccountOnlineModel>>(ResultCode.C_INVALID_ERROR, "查询失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 踢号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> KillOut(string id)
|
||||
{
|
||||
var flag = await this.KillOutClient(id);
|
||||
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("KillOut", id);
|
||||
var info = "";
|
||||
try
|
||||
{
|
||||
var url = string.Format(this.KillUrl, id);
|
||||
var resp = await client.GetAsync(url);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("断开消息已发送") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message + "-->info:" + info);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task<bool> KillOutClient(string id)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("KillOutClient", id);
|
||||
var info = "";
|
||||
try
|
||||
{
|
||||
var url = string.Format(this.KillUrlClient, id);
|
||||
var resp = await client.GetAsync(url);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("已经向客户端发送断开消息") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message + "-->info:" + info);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
597
Services/Hncore.Pass.Vpn/Service/AgentClient6Service.cs
Normal file
597
Services/Hncore.Pass.Vpn/Service/AgentClient6Service.cs
Normal file
@@ -0,0 +1,597 @@
|
||||
using AngleSharp.Dom;
|
||||
using AngleSharp.Html.Parser;
|
||||
using Bogus.DataSets;
|
||||
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.Threading.Tasks;
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public class AgentClient6Service : AgentClientBaseService
|
||||
{
|
||||
string secretId = "20200716182518182489";
|
||||
string secretKey = "OFcEJAfzYjWT3e2s";
|
||||
string UserApiUrl = "userapi/";
|
||||
string LoginIndexUrl { get; set; } = "login/";
|
||||
string LoginUrl { get; set; } = "loginauth/";
|
||||
string LoginCodeUrl { get; set; } = "";
|
||||
string RefrushTokenUrl { get; set; } = "userInfo/";
|
||||
string SingleAddUrl { get; set; } = "userapi/";
|
||||
string SingleReAddUrl { get; set; } = "user_buy_server";
|
||||
string MuiltAddUrl { get; set; } = "agent/memberMuiltAdd.html";
|
||||
string RefundUrl { get; set; } = "agent/memberRefundAct.html ";
|
||||
string UpdateUrl = "setuser";
|
||||
string OnlineUrl { get; set; } = "active_log/?user=";
|
||||
string KIllUrl { get; set; } = "agent/disConnect2/radacctid/{0}.html";
|
||||
string searchAccountUrl = "userList/?sum=100&page=1&search_data=";
|
||||
string searchTestAccountUrl = "agent/memberList/type/0.html?search=1&username=";
|
||||
string DeleteUrl { get; set; } = "agent/memberDel/id/";//1160862.html";
|
||||
IHttpClientFactory m_HttpClientFactory;
|
||||
public AgentClient6Service(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;
|
||||
}
|
||||
|
||||
private string FormatRequest(Dictionary<string, string> map)
|
||||
{
|
||||
map["secretId"] = this.secretId;
|
||||
map["secretKey"] = this.secretKey;
|
||||
var data = string.Join("&", map.Select(m => $"{m.Key}={m.Value}"));
|
||||
return data;
|
||||
}
|
||||
|
||||
public override async Task<int> 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;
|
||||
}
|
||||
public override async Task<(byte[], string)> GetCode()
|
||||
{
|
||||
|
||||
return (null, "");
|
||||
}
|
||||
|
||||
private async Task<(string, string)> GetHomeCookie()
|
||||
{
|
||||
var client = CreateHttpClient(false);
|
||||
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("input[name=csrfmiddlewaretoken]");//<input type='hidden' name='csrfmiddlewaretoken' value='b8XKenjQ9GJUJF0xSZySXLsG5FGNHepk' />
|
||||
|
||||
var csrf_token = csrf_tokenNode.GetAttribute("value");
|
||||
return (cookies, csrf_token);
|
||||
}
|
||||
|
||||
public override async Task<ApiResult> Login(AgentLoginRequest request)
|
||||
{
|
||||
var tokens = await this.GetHomeCookie();
|
||||
var client = CreateHttpClient(false);
|
||||
client.DefaultRequestHeaders.Add("Connection", "keep-alive");
|
||||
client.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests", "1");
|
||||
|
||||
var csrftoken = this.GetCookieValue(tokens.Item1, "csrftoken");
|
||||
var key = this.GetCookieValue(tokens.Item1, "key");
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"csrfmiddlewaretoken",tokens.Item2},
|
||||
{"username",request.Account },
|
||||
{"password",request.Pwd },
|
||||
{"remember",key },
|
||||
};
|
||||
LogHelper.Info("Login", map.ToJson());
|
||||
|
||||
var loginToken = $"csrftoken={csrftoken};key={key}";
|
||||
AddCookie(client, loginToken);
|
||||
var resp = await client.PostAsForm(this.LoginUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (resp.StatusCode != HttpStatusCode.Found || resp.Headers.Location.ToString().IndexOf("http://user.webok.me/userInfo/")==-1)
|
||||
{
|
||||
return new ApiResult(ResultCode.C_VISITOR_CHECKING, "登录失败");
|
||||
}
|
||||
var sessionid = this.GetCookie(resp, "sessionid");
|
||||
var username_user = this.GetCookie(resp, "username_user");
|
||||
request.Key = $"{loginToken};{sessionid};{username_user}";
|
||||
return new ApiResult(request.Key);
|
||||
}
|
||||
public override bool CheckAccount(int productId,List<string> accounts)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新开
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewAccount(string packageKey, string account, string pwd, int connCount = 1, int accountType = 1, int payCount = 1)
|
||||
{
|
||||
if (packageKey == "test_pay")
|
||||
return await NewTestAccount(account, pwd);
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"type","adduser" },
|
||||
{"user",account },
|
||||
{"pass",pwd },
|
||||
{"logincount",connCount.ToString()},
|
||||
{"serverid",packageKey },
|
||||
};
|
||||
var title = GetOpTitle("NewAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.GetAsync(this.UserApiUrl + "?" + this.FormatRequest(map));
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
JObject jo = (JObject)JsonConvert.DeserializeObject(content);
|
||||
var status = jo["code"].ToString();
|
||||
if (status == "1")
|
||||
{
|
||||
return new ApiResult(ResultCode.C_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Error(title, content);
|
||||
return new ApiResult(ResultCode.C_INVALID_ERROR, "开户失败");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.GetInfo());
|
||||
return new ApiResult(ResultCode.C_INVALID_ERROR, "开户失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 新开测试账号
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<ApiResult> NewTestAccount(string account, string pwd)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"user",account},
|
||||
{"pass",pwd },
|
||||
{"type","newuser" },
|
||||
{"logincount","1"},
|
||||
{"serverid","test_pay" },
|
||||
{"username",this.Product.Account },
|
||||
{"otherserver","no" },
|
||||
};
|
||||
var title = GetOpTitle("NewTestAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm("userRegisterAdd/" , map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
JObject jo = (JObject)JsonConvert.DeserializeObject(content);
|
||||
var status = jo["code"].ToString();
|
||||
if (status == "1")
|
||||
{
|
||||
return new ApiResult(ResultCode.C_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "开户失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 新开
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewMuiltAccount(string packageKey, string account, string pwd, int connCount = 1, int accountType = 1,int startNum=0, int endNum=1 )
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"taocanName",packageKey },
|
||||
{"usernameTpl",account },
|
||||
{"password",pwd },
|
||||
{"maxonline",connCount.ToString()},
|
||||
{"startNum",startNum.ToString()},
|
||||
{"endNum",endNum.ToString()},
|
||||
{"mode",accountType.ToString()},
|
||||
};
|
||||
var title = GetOpTitle("NewMuiltAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.PostAsForm(this.MuiltAddUrl, map);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if (content.Has() && content.IndexOf("<td>成功</td>") != -1)
|
||||
{
|
||||
return new ApiResult(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "开户失败");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 续费
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewReAccount(string packageKey, string account, int connCount)
|
||||
{
|
||||
var ret = await this.GetAccountInfo(account);
|
||||
if (ret.Code != ResultCode.C_SUCCESS|| ret.Data==null)
|
||||
{
|
||||
return new ApiResult(ResultCode.C_INVALID_ERROR, "账户不存在,续费失败");
|
||||
}
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"user",account },
|
||||
{"serverid",packageKey },
|
||||
{"type","buy" },
|
||||
};
|
||||
var title = GetOpTitle("NewReAccount", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.GetAsync(this.UserApiUrl + "?" + this.FormatRequest(map));
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
JObject jo = (JObject)JsonConvert.DeserializeObject(content);
|
||||
var status = jo["code"].ToString();
|
||||
if (status == "1")
|
||||
{
|
||||
return new ApiResult(ResultCode.C_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
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, "续费失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除账号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> DeleteAccount(string account)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 得到账号信息
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult<OriginAccountModel>> GetAccountInfo(string account, bool isTest = false)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"user",account },
|
||||
{"type","getuserinfo" },
|
||||
};
|
||||
var title = GetOpTitle("GetAccountInfo", account);
|
||||
try
|
||||
{
|
||||
var searchUser = $"userList/?sum=100&page=1&search_data={account}";
|
||||
var resp = await client.GetAsync(searchUser);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
|
||||
var parser = new HtmlParser();
|
||||
var document = await parser.ParseDocumentAsync(content);
|
||||
////table class="table table-bordered"
|
||||
var trs = document.QuerySelectorAll("#datatable tr").ToList();
|
||||
// var trs= table.QuerySelectorAll("tr").ToList();
|
||||
var retData = new List<OriginAccountModel>();
|
||||
var info = "";
|
||||
if (trs.Count() > 1)
|
||||
{
|
||||
//var tr = trs.Skip(1).FirstOrDefault();
|
||||
foreach (var tr in trs.Skip(1))
|
||||
{
|
||||
var tds = tr.QuerySelectorAll("td").ToList();
|
||||
var tdAccount = tds[1].TextContent;
|
||||
if (tdAccount != account)
|
||||
continue;
|
||||
info = string.Join("", tds.Select(m => m.OuterHtml));
|
||||
var trData = new OriginAccountModel
|
||||
{
|
||||
Account = account,
|
||||
Pwd = tds[2].TextContent,
|
||||
AccountType = tds[3].TextContent,
|
||||
Package = tds[3].TextContent,
|
||||
RegistTime = tds[5].TextContent,
|
||||
EndTime = tds[6].TextContent,
|
||||
ConnectCount = tds[4].TextContent,
|
||||
IsActive = tds[7].TextContent,
|
||||
Remark = tds[8].TextContent,
|
||||
};
|
||||
|
||||
trData.RealEndTime = DateTime.Parse(trData.EndTime);
|
||||
if (trData.RealEndTime < DateTime.Now)
|
||||
{
|
||||
trData.RestTime = "已过期";
|
||||
}
|
||||
else
|
||||
{
|
||||
trData.RestTime = (trData.RealEndTime - DateTime.Now).ToString(@"dd\.hh\:mm\:ss");
|
||||
}
|
||||
|
||||
var button = tr.LastElementChild.QuerySelector("button")?.Attributes["onclick"]?.Value;
|
||||
if (button.Has())
|
||||
{
|
||||
var start = button.IndexOf('(');
|
||||
var end = button.IndexOf(")");
|
||||
if (start != -1 && end != -1)
|
||||
{
|
||||
trData.Id = button.Substring(start + 1, end - start);
|
||||
}
|
||||
}
|
||||
return new ApiResult<OriginAccountModel>(trData);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message);
|
||||
}
|
||||
return new ApiResult<OriginAccountModel>(ResultCode.C_INVALID_ERROR, "没有查询到信息");
|
||||
}
|
||||
/// <summary>
|
||||
/// 修改账号密码
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> UpdateAccountPwd(string account, string pwd)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new Dictionary<string, string>(){
|
||||
{"user",account },
|
||||
{"new_pwd",pwd },
|
||||
{"type","setuser" },
|
||||
};
|
||||
var title = GetOpTitle("UpdateAccountPwd", account);
|
||||
LogHelper.Info(title, map.ToJson());
|
||||
try
|
||||
{
|
||||
var resp = await client.GetAsync(this.UserApiUrl + "?" + this.FormatRequest(map));
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
JObject jo = (JObject)JsonConvert.DeserializeObject(content);
|
||||
var status = jo["code"].ToString();
|
||||
if (status == "1")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.Error(title, content);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(GetOpTitle("UpdateAccountPwd", account), ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 退款
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> Refund(string account, string packageKey, int days)
|
||||
{
|
||||
var title = GetOpTitle("Refund", account);
|
||||
LogHelper.Info(title, account);
|
||||
return new ApiResult(ResultCode.C_INVALID_ERROR, "退款失败-不支持退款");
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否在线
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult<List<OriginAccountOnlineModel>>> OnLine(string account)
|
||||
{
|
||||
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("OnLine", account);
|
||||
|
||||
var info = "";
|
||||
try
|
||||
{
|
||||
var url = this.OnlineUrl + account;
|
||||
var resp = await client.GetAsync(url);
|
||||
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<OriginAccountOnlineModel>();
|
||||
if (trs.Count() > 1)
|
||||
{
|
||||
foreach (var tr in trs.Skip(1))
|
||||
{
|
||||
var tds = tr.QuerySelectorAll("td").ToList();
|
||||
var tdAccount = tds[1].FirstChild.TextContent;
|
||||
if (tdAccount != account)
|
||||
continue;
|
||||
info = string.Join("", tds.Select(m => m.OuterHtml));
|
||||
//序号 会员账号 服务器IP 登录时间 在线时长 会员IP 上行流量 下行流量 操作
|
||||
|
||||
var trData = new OriginAccountOnlineModel
|
||||
{
|
||||
Account = account,
|
||||
ServerIP = tds[6].TextContent,
|
||||
LoginTime = tds[1].TextContent,
|
||||
OnlineTime = tds[3].TextContent,
|
||||
LoginIP = tds[5].TextContent,
|
||||
UpStream = tds[4].TextContent,
|
||||
DownStream = tds[4].TextContent,
|
||||
Id= account,
|
||||
};
|
||||
var href = tr.LastElementChild.QuerySelector("a")?.Attributes["href"]?.Value;
|
||||
if (href.Has())
|
||||
{
|
||||
var start = href.LastIndexOf('/');
|
||||
var end = href.IndexOf(".html");
|
||||
if (start != -1 && end != -1)
|
||||
{
|
||||
trData.Id = href.Substring(start + 1, end - start).TrimEnd('.');
|
||||
}
|
||||
}
|
||||
retData.Add(trData);
|
||||
}
|
||||
}
|
||||
return new ApiResult<List<OriginAccountOnlineModel>>(retData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message + "-->info:" + info);
|
||||
return new ApiResult<List<OriginAccountOnlineModel>>(ResultCode.C_INVALID_ERROR, "查询失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 踢号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> KillOut( string id)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("KillOut", id);
|
||||
var info = "";
|
||||
try
|
||||
{
|
||||
var url = string.Format(this.KIllUrl, id);
|
||||
var resp = await client.GetAsync(url);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if(content.Has()&&content.IndexOf("断开成功")!=-1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message + "-->info:" + info);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否存在
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> Exist(string account)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("Exist", account);
|
||||
LogHelper.Info(title, account);
|
||||
|
||||
|
||||
string url = $"userapi3/?secretId={secretId}&secretKey={secretKey}&type=getuserlenNum&user={account}";
|
||||
var resp = await client.GetAsync(url);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
JObject jo = (JObject)JsonConvert.DeserializeObject(content);
|
||||
var status = jo["code"].ToString();
|
||||
if (status == "1")
|
||||
{
|
||||
var count = jo["count"].ToInt();
|
||||
return count > 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
532
Services/Hncore.Pass.Vpn/Service/AgentClient7Service.cs
Normal file
532
Services/Hncore.Pass.Vpn/Service/AgentClient7Service.cs
Normal file
@@ -0,0 +1,532 @@
|
||||
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 = "131";
|
||||
string apiKey = "icJZ5ty7csDcmN4aZk25YCd5K5SCiRbf";
|
||||
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<int> 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]");//<meta name="csrf-token" content="WfjPwY-RY_A_3d09abknzQm-eRDaVnDeMNRxN-juDDEYzomD3cshgk-zk3M94FC9P8Yte6AjCvMCmz4BmYZvSw==">
|
||||
var csrf_token = csrf_tokenNode.GetAttribute("content");
|
||||
return (cookies, csrf_token);
|
||||
}
|
||||
|
||||
public override async Task<ApiResult> 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<string, string>(){
|
||||
{"_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<string> accounts)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private string Sign(SortedDictionary<string, string> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新开
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewAccount(string packageKey, string account, string pwd, int connCount = 1, int accountType = 1, int payCount = 1)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new SortedDictionary<string, string>(){
|
||||
{"user",account },
|
||||
{"passwd",pwd },
|
||||
{"num","1"},
|
||||
{"conn_max",connCount.ToString() },
|
||||
{"test",packageKey=="test"?"1":"0" },
|
||||
{"type",packageKey=="test"?"d":packageKey },
|
||||
{"paynum","1" },
|
||||
};
|
||||
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, "开户失败");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 续费
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account">原始的账号的id</param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> NewReAccount(string packageKey, string id, int connCount)
|
||||
{
|
||||
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<string, string>(){
|
||||
{"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, "续费失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除账号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> DeleteAccount(string id)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new SortedDictionary<string, string>(){
|
||||
{"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;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 得到账号信息
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult<OriginAccountModel>> GetAccountInfo(string id, bool isTest=false)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new SortedDictionary<string, string>(){
|
||||
{"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<OriginAccountModel>(trData);
|
||||
}
|
||||
else
|
||||
{
|
||||
var info = jo["info"].ToString();
|
||||
LogHelper.Error(title, content);
|
||||
return new ApiResult<OriginAccountModel>(ResultCode.C_INVALID_ERROR, "没有查询到信息");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message);
|
||||
return new ApiResult<OriginAccountModel>(ResultCode.C_INVALID_ERROR, "查询失败");
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 修改账号密码
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> UpdateAccountPwd(string account, string pwd)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var map = new SortedDictionary<string, string>(){
|
||||
{"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;
|
||||
}
|
||||
/// <summary>
|
||||
/// 退款
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult> 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, "退款失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否在线
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<ApiResult<List<OriginAccountOnlineModel>>> OnLine(string account)
|
||||
{
|
||||
var client = CreateHttpClient(false);
|
||||
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<OriginAccountOnlineModel>();
|
||||
if (trs.Count() > 1)
|
||||
{
|
||||
foreach (var tr in trs.Skip(1))
|
||||
{
|
||||
var tds = tr.QuerySelectorAll("td").ToList();
|
||||
var tdAccount = tds[1].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,
|
||||
Id= account,
|
||||
};
|
||||
var href = tr.LastElementChild.QuerySelector("a")?.Attributes["href"]?.Value;
|
||||
if (href.Has())
|
||||
{
|
||||
var start = href.LastIndexOf('/');
|
||||
var end = href.IndexOf(".html");
|
||||
if (start != -1 && end != -1)
|
||||
{
|
||||
trData.Id = href.Substring(start + 1, end - start).TrimEnd('.');
|
||||
}
|
||||
}
|
||||
retData.Add(trData);
|
||||
}
|
||||
}
|
||||
return new ApiResult<List<OriginAccountOnlineModel>>(retData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message + "-->info:" + info);
|
||||
return new ApiResult<List<OriginAccountOnlineModel>>(ResultCode.C_INVALID_ERROR, "查询失败");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 踢号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> KillOut( string id)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
var title = GetOpTitle("KillOut", id);
|
||||
var info = "";
|
||||
try
|
||||
{
|
||||
var url = string.Format(this.KIllUrl, id);
|
||||
var resp = await client.GetAsync(url);
|
||||
var content = await resp.Content.ReadAsStringAsync();
|
||||
if(content.Has()&&content.IndexOf("断开成功")!=-1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(title, ex.Message + "-->info:" + info);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否存在
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<bool> Exist(string account)
|
||||
{
|
||||
var client = CreateHttpClient();
|
||||
|
||||
var map = new SortedDictionary<string, string>(){
|
||||
{"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;
|
||||
}
|
||||
}
|
||||
}
|
||||
223
Services/Hncore.Pass.Vpn/Service/AgentClientBaseService.cs
Normal file
223
Services/Hncore.Pass.Vpn/Service/AgentClientBaseService.cs
Normal file
@@ -0,0 +1,223 @@
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Hncore.Pass.Vpn.Request.Product;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Hncore.Infrastructure.WebApi;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Hncore.Pass.Vpn.Model;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public abstract class AgentClientBaseService
|
||||
{
|
||||
protected string BaseUrl { get; set; }
|
||||
protected string Token { get; set; }
|
||||
string LoginUrl { get; set; }
|
||||
string LoginCodeUrl { get; set; }
|
||||
string RefrushTokenUrl { get; set; }
|
||||
string SingleAddUrl { get; set; }
|
||||
string SingleReAddUrl { get; set; }
|
||||
string MuiltAddUrl { get; set; }
|
||||
string RefundUrl { get; set; }
|
||||
string OnlineUrl { get; set; }
|
||||
string KIllUrl { get; set; }
|
||||
string UpdateUrl { get; set; }
|
||||
public string ClientName { get; set; }
|
||||
public string Raw { get; set; }
|
||||
|
||||
IHttpClientFactory m_HttpClientFactory;
|
||||
public AgentClientBaseService(IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
m_HttpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
public ProductEntity Product { get; set; }
|
||||
|
||||
public void Init(string BaseUrl,string Token)
|
||||
{
|
||||
this.BaseUrl = BaseUrl;
|
||||
this.Token = Token;
|
||||
}
|
||||
|
||||
public virtual string GetOpTitle(string op,string account)
|
||||
{
|
||||
return $"{this.ClientName}_{op}_{account}";
|
||||
}
|
||||
|
||||
protected virtual HttpClient CreateHttpClient(bool autoCooke = true)
|
||||
{
|
||||
var client = m_HttpClientFactory.CreateClient("agentClient");
|
||||
client.BaseAddress = new System.Uri(this.BaseUrl);
|
||||
|
||||
|
||||
|
||||
if (this.Token.Has()&& autoCooke)
|
||||
{
|
||||
AddCookie(client, this.Token);
|
||||
}
|
||||
return client;
|
||||
}
|
||||
protected virtual void AddCookie(HttpClient client, string cookie)
|
||||
{
|
||||
client.DefaultRequestHeaders.Remove("Cookie");
|
||||
client.DefaultRequestHeaders.Add("Cookie", cookie);
|
||||
}
|
||||
public string GetCookie(HttpResponseMessage resp, string name)
|
||||
{
|
||||
if (resp.Headers.TryGetValues("Set-Cookie", out IEnumerable<string> cookies))
|
||||
{
|
||||
foreach (var cookie in cookies)
|
||||
{
|
||||
var ret = cookie.Split(";").FirstOrDefault(m => m.IndexOf(name) != -1);
|
||||
if (ret.Has())
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
public string GetCookies(HttpResponseMessage resp)
|
||||
{
|
||||
if (resp.Headers.TryGetValues("Set-Cookie", out IEnumerable<string> cookies))
|
||||
{
|
||||
return string.Join(";", cookies);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
protected string GetCookieValue(string cookies, string name)
|
||||
{
|
||||
foreach (var item in cookies.Split(";"))
|
||||
{
|
||||
var token = item.Split("=");
|
||||
if (token.Length == 2 && token[0] == name)
|
||||
{
|
||||
return token[1];
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public virtual async Task<int> RefrushStatus()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
public virtual async Task<(byte[], string)> GetCode()
|
||||
{
|
||||
return (null, "");
|
||||
}
|
||||
public virtual async Task<ApiResult> Login(AgentLoginRequest request)
|
||||
{
|
||||
return new ApiResult();
|
||||
}
|
||||
public virtual bool CheckAccount(int productId,List<string> accounts)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新开
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<ApiResult> NewAccount(string packageKey, string account,string pwd,int connCount=1,int accountType=1, int payCount = 1)
|
||||
{
|
||||
return new ApiResult();
|
||||
}
|
||||
public virtual async Task<ApiResult> NewMuiltAccount(string packageKey, string account, string pwd, int connCount = 1, int accountType = 1, int startNum = 0, int endNum = 1)
|
||||
{
|
||||
return new ApiResult();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 续费
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<ApiResult> NewReAccount(string packageKey,string account,int connCount)
|
||||
{
|
||||
return new ApiResult();
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除账号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<bool> DeleteAccount(string account)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
/// 得到账号信息
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<ApiResult<OriginAccountModel>> GetAccountInfo(string account, bool isTest = false)
|
||||
{
|
||||
return new ApiResult<OriginAccountModel>();
|
||||
}
|
||||
/// <summary>
|
||||
/// 修改账号密码
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<bool> UpdateAccountPwd(string account,string pwd)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
/// 退款
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<ApiResult> Refund(string account, string packageKey, int days)
|
||||
{
|
||||
return new ApiResult();
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否在线
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<ApiResult<List<OriginAccountOnlineModel>>> OnLine(string account)
|
||||
{
|
||||
return new ApiResult<List<OriginAccountOnlineModel>>();
|
||||
}
|
||||
/// <summary>
|
||||
/// 踢号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<bool> KillOut(string account)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否存在
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<bool> Exist(string account)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
Services/Hncore.Pass.Vpn/Service/AgentClientLogHandler.cs
Normal file
21
Services/Hncore.Pass.Vpn/Service/AgentClientLogHandler.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public class AgentClientLogHandler : DelegatingHandler
|
||||
{
|
||||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
if (request.Headers.Contains("hl"))
|
||||
{
|
||||
Console.WriteLine(request.RequestUri.ToString());
|
||||
}
|
||||
return base.SendAsync(request, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
419
Services/Hncore.Pass.Vpn/Service/AgentService.cs
Normal file
419
Services/Hncore.Pass.Vpn/Service/AgentService.cs
Normal file
@@ -0,0 +1,419 @@
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Infrastructure.WebApi;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Hncore.Pass.Vpn.Model;
|
||||
using Hncore.Pass.Vpn.Request.Product;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public class AgentService:IFindService
|
||||
{
|
||||
CourseContext m_DbContext;
|
||||
IHttpClientFactory m_HttpClientFactory;
|
||||
protected ProductService m_ProductService;
|
||||
protected ProductPackageService m_ProductPackageService;
|
||||
protected ProductPackageUnitService m_ProductPackageUnitService;
|
||||
protected ProductEntity m_Product;
|
||||
protected ProductAccountChargeService m_AccountChargeService;
|
||||
protected Dictionary<string,AgentClientBaseService> m_MapAgentClient=new Dictionary<string, AgentClientBaseService>();
|
||||
public AgentService(ProductService _ProductService
|
||||
, ProductPackageService _ProductPackageService
|
||||
, ProductPackageUnitService _ProductPackageUnitService
|
||||
, ProductAccountChargeService _AccountChargeService
|
||||
, IHttpClientFactory httpClientFactory
|
||||
, CourseContext _DbContext)
|
||||
{
|
||||
m_HttpClientFactory = httpClientFactory;
|
||||
m_ProductService = _ProductService;
|
||||
m_ProductPackageService = _ProductPackageService;
|
||||
m_ProductPackageUnitService = _ProductPackageUnitService;
|
||||
m_AccountChargeService = _AccountChargeService;
|
||||
m_DbContext = _DbContext;
|
||||
}
|
||||
|
||||
protected AgentClientBaseService _AgentClient;
|
||||
private AgentClientBaseService GetAgent(ProductEntity product)
|
||||
{
|
||||
AgentClientBaseService agent=null;
|
||||
if (product.GroupNO == "g1")
|
||||
agent = new AgentClient1Service(m_HttpClientFactory) { ClientName=product.GroupNO};
|
||||
if (product.GroupNO == "g2")
|
||||
agent = new AgentClient2Service(m_HttpClientFactory) { ClientName = product.GroupNO };
|
||||
if (product.GroupNO == "g3")
|
||||
agent = new AgentClient3Service(m_HttpClientFactory) { ClientName = product.GroupNO };
|
||||
if (product.GroupNO == "g4")
|
||||
agent = new AgentClient4Service(m_HttpClientFactory) { ClientName = product.GroupNO };
|
||||
if (product.GroupNO == "g5")
|
||||
agent = new AgentClient5Service(m_HttpClientFactory) { ClientName = product.GroupNO };
|
||||
if (product.GroupNO == "g6")
|
||||
agent = new AgentClient6Service(m_HttpClientFactory) { ClientName = product.GroupNO };
|
||||
if (product.GroupNO == "g7")
|
||||
agent = new AgentClient7Service(m_HttpClientFactory) { ClientName = product.GroupNO };
|
||||
agent.Product = product;
|
||||
return agent;
|
||||
}
|
||||
public async Task RefrushAllStatus()
|
||||
{
|
||||
var products = await m_ProductService.Query(false).ToListAsync();
|
||||
|
||||
await products.ForEachAsync(async m =>
|
||||
{
|
||||
// if (m.GroupNO == "g6")
|
||||
await RefrushStatus(m);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public virtual async Task RefrushStatus(ProductEntity product)
|
||||
{
|
||||
var agent = GetAgent(product);
|
||||
agent.Init(product.BaseUrl, product.Token);
|
||||
int status = await agent.RefrushStatus();
|
||||
if (product.Status != status)
|
||||
{
|
||||
product.UpdateTime = DateTime.Now;
|
||||
product.Status = status;
|
||||
await m_ProductService.Update(product);
|
||||
}
|
||||
if (product.Status == 0)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine($"{product.Name}:离线");
|
||||
Console.ResetColor();
|
||||
}
|
||||
}
|
||||
public virtual async Task<(byte[], string)> GetCode(int productId)
|
||||
{
|
||||
var product = await m_ProductService.GetById(productId);
|
||||
var agent = GetAgent(product);
|
||||
agent.Init(product.BaseUrl, product.Token);
|
||||
return await agent.GetCode();
|
||||
}
|
||||
public virtual async Task<ApiResult> Login(AgentLoginRequest request)
|
||||
{
|
||||
var product = await m_ProductService.GetById(request.ProductId);
|
||||
product.Token = request.Key;
|
||||
var agent = GetAgent(product);
|
||||
agent.Init(product.BaseUrl, product.Token);
|
||||
request.Account = product.Account;
|
||||
request.Pwd = product.Pwd;
|
||||
var ret = await agent.Login(request);
|
||||
if (ret.Code == ResultCode.C_SUCCESS)
|
||||
{
|
||||
product.Status = 1;
|
||||
product.Token = ret.Data.ToString();
|
||||
await m_ProductService.Update(product);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
public virtual async Task<ApiResult<List<OriginAccountModel>>> GetOriginAccounts(List<ProductAccountEntity> accountList)
|
||||
{
|
||||
var retList = new List<OriginAccountModel>();
|
||||
foreach (var item in accountList)
|
||||
{
|
||||
var product = await m_ProductService.GetById(item.ProductId);
|
||||
var agent = GetAgent(product);
|
||||
agent.Init(product.BaseUrl, product.Token);
|
||||
var account = item.Account;
|
||||
if (product.GroupNO == "g7") account = item.Raw;
|
||||
var ret = await agent.GetAccountInfo(account);
|
||||
if (ret.Code == ResultCode.C_SUCCESS)
|
||||
retList.Add(ret.Data as OriginAccountModel);
|
||||
}
|
||||
return new ApiResult<List<OriginAccountModel>>(retList);
|
||||
}
|
||||
|
||||
public virtual async Task<ApiResult<OriginAccountModel>> GetOriginAccountInfo(int productId, string account, string pwd = "")
|
||||
{
|
||||
var product = await m_ProductService.GetById(productId);
|
||||
var agent = GetAgent(product);
|
||||
agent.Init(product.BaseUrl, product.Token);
|
||||
if (product.GroupNO == "g7")
|
||||
{
|
||||
var accountInfo = await GetProductAccount(productId, account);
|
||||
if (accountInfo != null && accountInfo.Raw.Has())
|
||||
account = accountInfo.Raw;
|
||||
}
|
||||
var ret = await agent.GetAccountInfo(account);
|
||||
if (ret.Code != ResultCode.C_SUCCESS) return new ApiResult<OriginAccountModel>(ResultCode.C_NOT_EXISTS_ERROR, "账号不存在");
|
||||
if (pwd.Has()&&ret.Data.Pwd != pwd)
|
||||
return new ApiResult<OriginAccountModel>(ResultCode.C_NOT_EXISTS_ERROR, "密码不正确");
|
||||
return ret;
|
||||
}
|
||||
|
||||
public virtual async Task<List<OriginAccountModel>> GetOriginAccountInfo(int productId, List<string> accounts)
|
||||
{
|
||||
var list = new List<OriginAccountModel>();
|
||||
var product = await m_ProductService.GetById(productId);
|
||||
var agent = GetAgent(product);
|
||||
agent.Init(product.BaseUrl, product.Token);
|
||||
foreach (var item in accounts)
|
||||
{
|
||||
var account = item;
|
||||
if (product.GroupNO == "g7")
|
||||
{
|
||||
var accountInfo = await GetProductAccount(productId, item);
|
||||
if (accountInfo != null && accountInfo.Raw.Has())
|
||||
account = accountInfo.Raw;
|
||||
}
|
||||
var ret = await agent.GetAccountInfo(account);
|
||||
if (ret.Code == ResultCode.C_SUCCESS)
|
||||
{
|
||||
list.Add(ret.Data);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新开
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<ApiResult> NewAccount(int orderId, int packageId, string account, string pwd, int connCount = 1, int accountType = 1)
|
||||
{
|
||||
ApiResult flagResult = new ApiResult(ResultCode.C_SUCCESS);
|
||||
var package = await m_ProductPackageService.GetById(packageId);
|
||||
var product = await m_ProductService.GetById(package.ProductId);
|
||||
var agent = GetAgent(product);
|
||||
agent.Init(product.BaseUrl, product.Token);
|
||||
|
||||
if (package.PackageType == PackageType.Base)
|
||||
{
|
||||
var ret = await agent.NewAccount(package.OriginKey, account, pwd, connCount, accountType);
|
||||
//var ret = new ApiResult(ResultCode.C_INVALID_ERROR);
|
||||
var status = ret.Code == ResultCode.C_SUCCESS ? ChargeStatus.Ok : ChargeStatus.Faild;
|
||||
await m_AccountChargeService.RecordNew(package, orderId, product.GroupNO, account, pwd, accountType, connCount, status);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
var basePackages = await m_ProductPackageService.GetBasePackages(packageId);
|
||||
var firstPackage = basePackages.FirstOrDefault();
|
||||
basePackages.Remove(firstPackage);
|
||||
if (firstPackage.Count > 1)
|
||||
{
|
||||
firstPackage.Count--;
|
||||
basePackages.Insert(0, firstPackage);
|
||||
}
|
||||
var ret = await agent.NewAccount(firstPackage.Package.OriginKey, account, pwd, connCount, accountType);
|
||||
//var ret = new ApiResult(ResultCode.C_INVALID_ERROR);
|
||||
var status = ret.Code == ResultCode.C_SUCCESS ? ChargeStatus.Ok : ChargeStatus.Faild;
|
||||
await m_AccountChargeService.RecordNew(firstPackage.Package, orderId, product.GroupNO, account, pwd, accountType, connCount, status);
|
||||
|
||||
if (ret.Code != ResultCode.C_SUCCESS)
|
||||
flagResult = ret;
|
||||
|
||||
foreach (var item in basePackages)
|
||||
{
|
||||
for (var j = 0; j < item.Count; j++)
|
||||
{
|
||||
ret = await agent.NewReAccount(item.Package.OriginKey, account, connCount);
|
||||
// ret = new ApiResult(ResultCode.C_INVALID_ERROR);
|
||||
status = ret.Code == ResultCode.C_SUCCESS ? ChargeStatus.Ok : ChargeStatus.Faild;
|
||||
await m_AccountChargeService.RecordReNew(item.Package, orderId, product.GroupNO, account, connCount, status);
|
||||
if (ret.Code != ResultCode.C_SUCCESS)
|
||||
flagResult = ret;
|
||||
}
|
||||
}
|
||||
return flagResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 续费
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<ApiResult> ReNewAccount(int orderId, int packageId, string account, int connCount)
|
||||
{
|
||||
var package = await m_ProductPackageService.GetById(packageId);
|
||||
var product = await m_ProductService.GetById(package.ProductId);
|
||||
if (product.GroupNO == "g7")
|
||||
{
|
||||
var accountInfo = await GetProductAccount(package.ProductId, account);
|
||||
if (accountInfo != null && accountInfo.Raw.Has())
|
||||
account = accountInfo.Raw;
|
||||
}
|
||||
var agent = GetAgent(product);
|
||||
agent.Init(product.BaseUrl, product.Token);
|
||||
ApiResult flagResult = new ApiResult(ResultCode.C_SUCCESS);
|
||||
if (package.PackageType == PackageType.Base)
|
||||
{
|
||||
var ret = await agent.NewReAccount(package.OriginKey, account, connCount);
|
||||
// var ret = new ApiResult(ResultCode.C_INVALID_ERROR);
|
||||
var status = ret.Code == ResultCode.C_SUCCESS ? ChargeStatus.Ok : ChargeStatus.Faild;
|
||||
await m_AccountChargeService.RecordReNew(package, orderId, product.GroupNO, account, connCount, status);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
var basePackages = await m_ProductPackageService.GetBasePackages(packageId);
|
||||
foreach (var basePackage in basePackages)
|
||||
{
|
||||
for (var j = 0; j < basePackage.Count; j++)
|
||||
{
|
||||
var ret = await agent.NewReAccount(basePackage.Package.OriginKey, account, connCount);
|
||||
//var ret = new ApiResult(ResultCode.C_INVALID_ERROR);
|
||||
var status = ret.Code == ResultCode.C_SUCCESS ? ChargeStatus.Ok : ChargeStatus.Faild;
|
||||
await m_AccountChargeService.RecordReNew(basePackage.Package, orderId, product.GroupNO, account, connCount, status);
|
||||
if (status == ChargeStatus.Faild) flagResult = ret;
|
||||
}
|
||||
}
|
||||
return flagResult;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除账号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public virtual bool DeleteAccount(int productId, string account)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
/// 修改账号密码
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<bool> UpdateAccountPwd(int productId, string account, string pwd)
|
||||
{
|
||||
var product = await m_ProductService.GetById(productId);
|
||||
var agent = GetAgent(product);
|
||||
agent.Init(product.BaseUrl, product.Token);
|
||||
if (product.GroupNO == "g7")
|
||||
{
|
||||
var accountInfo = await GetProductAccount(productId, account);
|
||||
if (accountInfo != null && accountInfo.Raw.Has())
|
||||
agent.Raw = accountInfo.Raw;
|
||||
}
|
||||
return await agent.UpdateAccountPwd(account, pwd);
|
||||
}
|
||||
/// <summary>
|
||||
/// 退款
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<ApiResult> Refund(ProductPackageEntity package, ProductAccountEntity accountInfo)
|
||||
{
|
||||
var product = await m_ProductService.GetById(package.ProductId);
|
||||
var agent = GetAgent(product);
|
||||
agent.Init(product.BaseUrl, product.Token);
|
||||
var account = accountInfo.Account;
|
||||
if (product.GroupNO == "g7")
|
||||
{
|
||||
if (accountInfo != null && accountInfo.Raw.Has())
|
||||
account = accountInfo.Raw;
|
||||
}
|
||||
var flag = await agent.Refund(account, package.OriginKey, accountInfo.RestDay);
|
||||
return flag;
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否在线
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<ApiResult<List<OriginAccountOnlineModel>>> OnLine(int productId, string account)
|
||||
{
|
||||
var product = await m_ProductService.GetById(productId);
|
||||
var agent = GetAgent(product);
|
||||
agent.Init(product.BaseUrl, product.Token);
|
||||
return await agent.OnLine(account);
|
||||
}
|
||||
/// <summary>
|
||||
/// 踢号
|
||||
/// </summary>
|
||||
/// <param name="productId"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<bool> KillOut(int productId, string id)
|
||||
{
|
||||
var product = await m_ProductService.GetById(productId);
|
||||
var agent = GetAgent(product);
|
||||
agent.Init(product.BaseUrl, product.Token);
|
||||
return await agent.KillOut(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否存在
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> Exist(int productId, string account)
|
||||
{
|
||||
if (productId == 5) productId = 12;
|
||||
var product = await m_ProductService.GetById(productId);
|
||||
var agent = GetAgent(product);
|
||||
agent.Init(product.BaseUrl, product.Token);
|
||||
return await agent.Exist(account);
|
||||
}
|
||||
|
||||
public async Task FaildTry()
|
||||
{
|
||||
var records = await m_AccountChargeService.GetFaildRecord();
|
||||
|
||||
foreach (var chargeEntity in records)
|
||||
{
|
||||
if (chargeEntity.Status != ChargeStatus.Faild)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (chargeEntity.TryTimes > 3)
|
||||
{
|
||||
chargeEntity.Status = ChargeStatus.Outtime;
|
||||
chargeEntity.UpdateTime = DateTime.Now;
|
||||
await m_AccountChargeService.Update(chargeEntity);
|
||||
continue;
|
||||
}
|
||||
var product = await m_ProductService.GetById(chargeEntity.ProductId);
|
||||
var agent = GetAgent(product);
|
||||
agent.Init(product.BaseUrl, product.Token);
|
||||
if (chargeEntity.OperationType == ChargeOperationType.New)
|
||||
{
|
||||
var ret = await agent.NewAccount(chargeEntity.PackageOriginKey, chargeEntity.Account, chargeEntity.Pwd, chargeEntity.ConnectCount, chargeEntity.AccountType);
|
||||
var status = ret.Code == ResultCode.C_SUCCESS ? ChargeStatus.Ok : ChargeStatus.Faild;
|
||||
|
||||
chargeEntity.Status = status;
|
||||
chargeEntity.TryTimes++;
|
||||
chargeEntity.UpdateTime = DateTime.Now;
|
||||
await m_AccountChargeService.Update(chargeEntity);
|
||||
}else if(chargeEntity.OperationType == ChargeOperationType.ReNew)
|
||||
{
|
||||
var ret = await agent.NewReAccount(chargeEntity.PackageOriginKey, chargeEntity.Account, chargeEntity.ConnectCount);
|
||||
// var ret = new ApiResult(ResultCode.C_INVALID_ERROR);
|
||||
var status = ret.Code == ResultCode.C_SUCCESS ? ChargeStatus.Ok : ChargeStatus.Faild;
|
||||
|
||||
chargeEntity.Status = status;
|
||||
chargeEntity.TryTimes++;
|
||||
chargeEntity.UpdateTime = DateTime.Now;
|
||||
await m_AccountChargeService.Update(chargeEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected async Task<ProductAccountEntity> GetProductAccount(int productId, string account)
|
||||
{
|
||||
return await m_DbContext.Set<ProductAccountEntity>().FirstOrDefaultAsync(m => m.ProductId == productId && m.Account == account);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Services/Hncore.Pass.Vpn/Service/ArticleService.cs
Normal file
25
Services/Hncore.Pass.Vpn/Service/ArticleService.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public partial class ArticleService : ServiceBase<ArticleEntity>, IFindService
|
||||
{
|
||||
CourseContext m_DbContext;
|
||||
public ArticleService(CourseContext dbContext, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
m_DbContext = dbContext;
|
||||
}
|
||||
|
||||
public async Task<List<ArticleEntity>> GetTop(int top, ArticleCatalog catalog)
|
||||
{
|
||||
return await this.Query(m => m.CatalogId == catalog).Take(top).ToListAsync();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public partial class ProductAccountChargeService : ServiceBase<ProductAccountChargeEntity>, IFindService
|
||||
{
|
||||
CourseContext m_DbContext;
|
||||
public ProductAccountChargeService(CourseContext dbContext
|
||||
, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
m_DbContext = dbContext;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录新开操作
|
||||
/// </summary>
|
||||
/// <param name="package"></param>
|
||||
/// <param name="orderId"></param>
|
||||
/// <param name="gid"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <param name="accountType"></param>
|
||||
/// <param name="connCount"></param>
|
||||
/// <param name="chargeStatus"></param>
|
||||
/// <returns></returns>
|
||||
public async Task RecordNew(ProductPackageEntity package, int orderId, string gid, string account, string pwd, int accountType, int connCount, ChargeStatus chargeStatus = ChargeStatus.Ok)
|
||||
{
|
||||
var chargeEntity = new ProductAccountChargeEntity()
|
||||
{
|
||||
Account = account,
|
||||
AccountType = accountType,
|
||||
ConnectCount = connCount,
|
||||
OperationType = ChargeOperationType.New,
|
||||
OrderId = orderId,
|
||||
PackageId = package.Id,
|
||||
PackageOriginKey = package.OriginKey,
|
||||
ProductGroup = gid,
|
||||
ProductId = package.ProductId,
|
||||
Pwd = pwd,
|
||||
Status = chargeStatus,
|
||||
TryTimes = 1,
|
||||
};
|
||||
await this.Add(chargeEntity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录续费操作
|
||||
/// </summary>
|
||||
/// <param name="package"></param>
|
||||
/// <param name="orderId"></param>
|
||||
/// <param name="gid"></param>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <param name="accountType"></param>
|
||||
/// <param name="connCount"></param>
|
||||
/// <param name="chargeStatus"></param>
|
||||
/// <returns></returns>
|
||||
public async Task RecordReNew(ProductPackageEntity package, int orderId, string gid, string account, int connCount, ChargeStatus chargeStatus = ChargeStatus.Ok)
|
||||
{
|
||||
var chargeEntity = new ProductAccountChargeEntity()
|
||||
{
|
||||
Account = account,
|
||||
AccountType =0,
|
||||
ConnectCount = connCount,
|
||||
OperationType = ChargeOperationType.ReNew,
|
||||
OrderId = orderId,
|
||||
PackageId = package.Id,
|
||||
PackageOriginKey = package.OriginKey,
|
||||
ProductGroup = gid,
|
||||
ProductId = package.ProductId,
|
||||
Pwd = "",
|
||||
Status = chargeStatus,
|
||||
TryTimes = 1,
|
||||
};
|
||||
await this.Add(chargeEntity);
|
||||
}
|
||||
|
||||
public async Task<List<ProductAccountChargeEntity>> GetFaildRecord(int maxTryTimes = 3, int maxTop = 100)
|
||||
{
|
||||
var query = this.Query(m => m.Status == ChargeStatus.Faild
|
||||
&& m.TryTimes <= maxTryTimes
|
||||
&& (DateTime.Now - m.CreateTime).Minutes <= 10);
|
||||
return await query.OrderBy(m => m.Id)
|
||||
.Take(maxTop)
|
||||
.ToListAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
150
Services/Hncore.Pass.Vpn/Service/ProductAccountService.cs
Normal file
150
Services/Hncore.Pass.Vpn/Service/ProductAccountService.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using HHncore.Pass.Vpn.Request.Product;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Infrastructure.WebApi;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.EntitiesExtension;
|
||||
using Hncore.Infrastructure.EF;
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public partial class ProductAccountService : ServiceBase<ProductAccountEntity>, IFindService
|
||||
{
|
||||
CourseContext m_DbContext;
|
||||
private IConfiguration m_Configuration;
|
||||
public AgentService m_AgentService;
|
||||
private UserService m_UserService;
|
||||
public ProductAccountService(CourseContext dbContext
|
||||
, AgentService _AgentService
|
||||
, UserService _UserService
|
||||
, IConfiguration _Configuration
|
||||
, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
m_DbContext = dbContext;
|
||||
m_AgentService = _AgentService;
|
||||
m_Configuration = _Configuration;
|
||||
m_UserService = _UserService;
|
||||
}
|
||||
|
||||
public async Task<bool> CheckAccountExist(int productId, List<string> accouts)
|
||||
{
|
||||
var flag = this.Exist(m => accouts.Contains(m.Account));
|
||||
if (flag)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
foreach (var item in accouts)
|
||||
{
|
||||
var ret = await m_AgentService.Exist(productId, item);
|
||||
await Task.Delay(50);
|
||||
if (ret == true)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
public bool CheckUserAccountExist(int product, List<string> accouts, int userId)
|
||||
{
|
||||
return this.Exist(m => accouts.Contains(m.Account) && m.UserId == userId);
|
||||
}
|
||||
|
||||
public async Task<ProductAccountEntity> GetAccountInfo(string accout, int userId)
|
||||
{
|
||||
return await this.Query(true).FirstOrDefaultAsync(m => m.Account == accout && m.UserId == userId);
|
||||
}
|
||||
|
||||
public async Task<List<ProductAccountEntity>> GetAccounts(string accouts,int userId=0)
|
||||
{
|
||||
var alist = accouts.Split(",");
|
||||
return await this.Query(m =>(userId==0||m.UserId== userId)&& alist.Contains(m.Account)).ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<ProductAccountEntity> GetAccountInfo(string accout)
|
||||
{
|
||||
return await this.Query(true).FirstOrDefaultAsync(m => m.Account == accout);
|
||||
}
|
||||
|
||||
public async Task<ProductAccountEntity> GetAccountInfo(int packageId,string accout)
|
||||
{
|
||||
return await this.Query(true).FirstOrDefaultAsync(m =>m.PackageId== packageId&& m.Account == accout);
|
||||
}
|
||||
|
||||
public async Task<ProductAccountEntity> GetProductAccountInfo(int productId, string accout)
|
||||
{
|
||||
return await this.Query(true).FirstOrDefaultAsync(m => m.ProductId == productId && m.Account == accout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// day 0:已过期,1天
|
||||
/// </summary>
|
||||
/// <param name="day"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<ProductAccountEntity>> GetExpireingAccounts_bak(int day)
|
||||
{
|
||||
Expression<Func<ProductAccountEntity, bool>> expr = m => 1 == 1;
|
||||
|
||||
if (day == 0)
|
||||
{
|
||||
expr = expr.And(m => m.EndTime.Value < DateTime.Now);
|
||||
}
|
||||
else
|
||||
{
|
||||
var startTime = DateTime.Now.Begin().AddDays(day);
|
||||
var EndTime = DateTime.Now.End().AddDays(day);
|
||||
expr = expr.And(m => m.EndTime >= startTime && m.EndTime <= EndTime);
|
||||
}
|
||||
return await this.Query(expr,true).ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<List<ProductAccountEntity>> GetExpireingAccounts(int day)
|
||||
{
|
||||
var sql = $"select * from product_account where DATEDIFF(EndTime,now())={day}";
|
||||
return this.m_DbContext.SqlQuery<ProductAccountEntity>(sql);
|
||||
}
|
||||
|
||||
public async Task<ApiResult> UpdateAccountPwd(UpdateAccountPwdRequest request)
|
||||
{
|
||||
var entity = await this.GetById(request.Id);
|
||||
if (entity == null)
|
||||
{
|
||||
return new ApiResult(ResultCode.C_INVALID_ERROR, "账号不存在");
|
||||
}
|
||||
if (request.Pwd.NotHas())
|
||||
{
|
||||
return new ApiResult(ResultCode.C_INVALID_ERROR, "密码不能为空");
|
||||
}
|
||||
var agentRet = await m_AgentService.UpdateAccountPwd(entity.ProductId.Value, entity.Account, request.Pwd);
|
||||
if (!agentRet)
|
||||
{
|
||||
return new ApiResult(ResultCode.C_INVALID_ERROR, "远程更新失败");
|
||||
}
|
||||
entity.Pwd = request.Pwd;
|
||||
await this.Update(entity);
|
||||
return new ApiResult(1);
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<ProductAccountEntity>> GetUserTestAccount(int userId)
|
||||
{
|
||||
return await this.Query(m => m.UserId == userId && m.AccountType == (int)AccountType.Test).ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<int> GetRestTestCount(int userId)
|
||||
{
|
||||
var userInfo = await m_UserService.GetById(userId);
|
||||
var restTimes = Convert.ToInt32(m_Configuration["TestCountLimit"]);
|
||||
if (userInfo.TestCountLimit > 0) restTimes = userInfo.TestCountLimit.Value;
|
||||
restTimes = restTimes - userInfo.UseTestCount.Value;
|
||||
restTimes = restTimes < 0 ? 0 : restTimes;
|
||||
return restTimes;
|
||||
}
|
||||
}
|
||||
}
|
||||
63
Services/Hncore.Pass.Vpn/Service/ProductOrderItemService.cs
Normal file
63
Services/Hncore.Pass.Vpn/Service/ProductOrderItemService.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Infrastructure.WebApi;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public partial class ProductOrderItemService : ServiceBase<ProductOrderItemEntity>, IFindService
|
||||
{
|
||||
CourseContext m_DbContext;
|
||||
public ProductOrderItemService(CourseContext dbContext
|
||||
, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
m_DbContext = dbContext;
|
||||
}
|
||||
public async Task<List<ProductOrderItemEntity>> CreateOrderItems(ProductOrderEntity orderEntity,string pwd)
|
||||
{
|
||||
List<ProductOrderItemEntity> items = new List<ProductOrderItemEntity>();
|
||||
var accounts = orderEntity.Accounts.Split(',').ToList();
|
||||
accounts.ForEach(m =>
|
||||
{
|
||||
var item = new ProductOrderItemEntity()
|
||||
{
|
||||
ConnectCount = orderEntity.ConnectCount,
|
||||
DayPrice = orderEntity.DayPrice.Value,
|
||||
DayCount=orderEntity.DayCount,
|
||||
OrderId = orderEntity.Id,
|
||||
OrderNo = orderEntity.OrderNo,
|
||||
OrderState = orderEntity.OrderState,
|
||||
OrderType = orderEntity.OrderType,
|
||||
PackageId = orderEntity.PackageId,
|
||||
PackageName = orderEntity.PackageName,
|
||||
PayState = orderEntity.PayState,
|
||||
PayType = orderEntity.PayType,
|
||||
Account = m,
|
||||
ProductId = orderEntity.ProductId,
|
||||
ProductName = orderEntity.ProductName,
|
||||
TenantId = orderEntity.TenantId,
|
||||
UserId = orderEntity.UserId,
|
||||
UserName = orderEntity.UserName,
|
||||
AccountPwd = pwd
|
||||
};
|
||||
items.Add(item);
|
||||
});
|
||||
await this.Adds(items);
|
||||
return items;
|
||||
}
|
||||
|
||||
|
||||
public async Task<ProductOrderItemEntity> GetLastByAccount(string account)
|
||||
{
|
||||
var orderItem = await this.Query(m => m.Account == account && m.OrderState == OrderStatus.Complete)
|
||||
.OrderByDescending(m => m.Id)
|
||||
.FirstOrDefaultAsync();
|
||||
return orderItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
1321
Services/Hncore.Pass.Vpn/Service/ProductOrderService.cs
Normal file
1321
Services/Hncore.Pass.Vpn/Service/ProductOrderService.cs
Normal file
File diff suppressed because it is too large
Load Diff
34
Services/Hncore.Pass.Vpn/Service/ProductPackageService.cs
Normal file
34
Services/Hncore.Pass.Vpn/Service/ProductPackageService.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Hncore.Pass.Vpn.Model;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public partial class ProductPackageService : ServiceBase<ProductPackageEntity>, IFindService
|
||||
{
|
||||
CourseContext m_DbContext;
|
||||
ProductPackageUnitService m_ProductPackageUnitService;
|
||||
public ProductPackageService(CourseContext dbContext
|
||||
, ProductPackageUnitService _ProductPackageUnitService
|
||||
, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
m_DbContext = dbContext;
|
||||
this.m_ProductPackageUnitService = _ProductPackageUnitService;
|
||||
}
|
||||
|
||||
public async Task<List<PackageUnitItemModel>> GetBasePackages(int packageId)
|
||||
{
|
||||
var packageUnits = m_ProductPackageUnitService.Query(m => m.PackageId == packageId);
|
||||
|
||||
var query = from packageUnit in packageUnits
|
||||
join package in this.Query(true) on packageUnit.BasePackageId equals package.Id
|
||||
select new PackageUnitItemModel { Count = packageUnit.Count, Package = package };
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public partial class ProductPackageUnitService : ServiceBase<ProductPackageUnitEntity>, IFindService
|
||||
{
|
||||
CourseContext m_DbContext;
|
||||
public ProductPackageUnitService(CourseContext dbContext, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
m_DbContext = dbContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Hncore.Pass.Vpn.Response.Product;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using System.Linq;
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public partial class ProductPriceDiscountService : ServiceBase<ProductPriceDiscountEntity>, IFindService
|
||||
{
|
||||
CourseContext m_DbContext;
|
||||
ProductService m_ProductService;
|
||||
ProductPackageService m_ProductPackageService;
|
||||
public ProductPriceDiscountService(CourseContext dbContext
|
||||
, ProductService _ProductService
|
||||
, ProductPackageService _ProductPackageService
|
||||
, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
m_DbContext = dbContext;
|
||||
m_ProductService = _ProductService;
|
||||
m_ProductPackageService = _ProductPackageService;
|
||||
}
|
||||
|
||||
public async Task<List<ProductWithPriceDiscountResponse>> GetPriceDiscount(int schemeId)
|
||||
{
|
||||
var products = await m_ProductService.Query(true).ToListAsync();
|
||||
|
||||
var packages = m_ProductPackageService.Query(true);
|
||||
var priceDiscount = this.Query(m => m.SchemeId == schemeId);
|
||||
var ret = from pakcage in packages
|
||||
join uDiscount in priceDiscount on pakcage.Id equals uDiscount.PackageId into temp
|
||||
from uDiscount in temp.DefaultIfEmpty()
|
||||
select new PackagePriceDiscount()
|
||||
{
|
||||
Package = pakcage,
|
||||
PriceDiscount = uDiscount ?? new ProductPriceDiscountEntity()
|
||||
};
|
||||
var packgesPrice = await ret.ToListAsync();
|
||||
|
||||
List<ProductWithPriceDiscountResponse> respList = new List<ProductWithPriceDiscountResponse>();
|
||||
products.ForEach(p =>
|
||||
{
|
||||
var resp = new ProductWithPriceDiscountResponse();
|
||||
resp.Product = p.MapTo<ProductResponse>();
|
||||
resp.PackageDiscounts = packgesPrice.Where(m => m.Package.ProductId == p.Id).ToList();
|
||||
respList.Add(resp);
|
||||
});
|
||||
return respList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public partial class ProductPriceSchemeService : ServiceBase<ProductPriceSchemeEntity>, IFindService
|
||||
{
|
||||
CourseContext m_DbContext;
|
||||
public ProductPriceSchemeService(CourseContext dbContext, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
m_DbContext = dbContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Services/Hncore.Pass.Vpn/Service/ProductRouteService.cs
Normal file
15
Services/Hncore.Pass.Vpn/Service/ProductRouteService.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public partial class ProductRouteService : ServiceBase<ProductRouteEntity>, IFindService
|
||||
{
|
||||
CourseContext m_DbContext;
|
||||
public ProductRouteService(CourseContext dbContext, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
m_DbContext = dbContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
78
Services/Hncore.Pass.Vpn/Service/ProductService.cs
Normal file
78
Services/Hncore.Pass.Vpn/Service/ProductService.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Hncore.Pass.Vpn.Response.Product;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public partial class ProductService : ServiceBase<ProductEntity>, IFindService
|
||||
{
|
||||
private static readonly string m_ProductCacheKey = "Product:{0}";
|
||||
CourseContext m_DbContext;
|
||||
ProductPackageService m_ProductPackageService;
|
||||
public ProductService(CourseContext dbContext, ProductPackageService _ProductPackageService, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
m_DbContext = dbContext;
|
||||
m_ProductPackageService = _ProductPackageService;
|
||||
}
|
||||
|
||||
|
||||
public async override Task<ProductEntity> GetById(object id)
|
||||
{
|
||||
return await base.GetById(id);
|
||||
string key = string.Format(m_ProductCacheKey, id);
|
||||
|
||||
var cacheData = await RedisHelper.GetAsync<ProductEntity>(key);
|
||||
if (cacheData == null)
|
||||
{
|
||||
cacheData = await base.GetById(id);
|
||||
if (cacheData != null)
|
||||
await RedisHelper.SetAsync(key, cacheData, 60 * 30);
|
||||
}
|
||||
|
||||
return cacheData;
|
||||
}
|
||||
|
||||
|
||||
public async override Task<bool> Update(ProductEntity entity, bool autoSave = true)
|
||||
{
|
||||
string key = string.Format(m_ProductCacheKey, entity.Id);
|
||||
await RedisHelper.SetAsync(key, entity, 60 * 30);
|
||||
return await base.Update(entity, autoSave);
|
||||
}
|
||||
|
||||
public async Task<List<ProductWithPackageResponse>> ProductWithPackage(int online=1)
|
||||
{
|
||||
var products = await this.Query(m => m.Sort != 1000).Where(m=>m.OnLine==online).ToListAsync();
|
||||
var packages = await m_ProductPackageService.Query(true).ToListAsync();
|
||||
|
||||
List<ProductWithPackageResponse> respList = new List<ProductWithPackageResponse>();
|
||||
products.ForEach(p =>
|
||||
{
|
||||
var resp = new ProductWithPackageResponse();
|
||||
resp.Product = p.MapTo<ProductResponse>();
|
||||
resp.Packages = packages.Where(m => m.ProductId == p.Id).ToList();
|
||||
respList.Add(resp);
|
||||
});
|
||||
return respList;
|
||||
}
|
||||
|
||||
public async Task<ProductWithPackageResponse> GetOneProductWithPackage(int productId)
|
||||
{
|
||||
var product = await this.GetById(productId);
|
||||
var packages = await m_ProductPackageService.Query(m => m.ProductId == productId).ToListAsync();
|
||||
|
||||
List<ProductWithPackageResponse> respList = new List<ProductWithPackageResponse>();
|
||||
var resp = new ProductWithPackageResponse();
|
||||
resp.Product = product.MapTo<ProductResponse>();
|
||||
resp.Packages = packages;
|
||||
return resp;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
68
Services/Hncore.Pass.Vpn/Service/ProductUserPriceService.cs
Normal file
68
Services/Hncore.Pass.Vpn/Service/ProductUserPriceService.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Hncore.Pass.Vpn.Response.Product;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public partial class ProductUserPriceService : ServiceBase<ProductUserPriceEntity>, IFindService
|
||||
{
|
||||
CourseContext m_DbContext;
|
||||
ProductService m_ProductService;
|
||||
ProductPackageService m_ProductPackageService;
|
||||
public ProductUserPriceService(ProductPackageService m_ProductPackageService
|
||||
, ProductService m_ProductService
|
||||
,CourseContext dbContext, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
m_DbContext = dbContext;
|
||||
this.m_ProductPackageService = m_ProductPackageService;
|
||||
this.m_ProductService = m_ProductService;
|
||||
}
|
||||
|
||||
public async Task<List<ProductWithPackageUserPriceResponse>> GetPackageUserPrice(int userId)
|
||||
{
|
||||
var products = await m_ProductService.Query(true).ToListAsync();
|
||||
|
||||
var packages = m_ProductPackageService.Query(true);
|
||||
var userPrice = this.Query(m => m.UserId == userId);
|
||||
var ret = from pakcage in packages
|
||||
join uPrice in userPrice on pakcage.Id equals uPrice.PackageId into temp
|
||||
from uPrice in temp.DefaultIfEmpty()
|
||||
select new PackageUserPriceResponse()
|
||||
{
|
||||
Package = pakcage,
|
||||
UserPrice = uPrice ?? new ProductUserPriceEntity() { RefundDayPrice= products.FirstOrDefault(m=>m.Id==pakcage.ProductId).RefundDayPrice, UserPrice=pakcage.Price }
|
||||
};
|
||||
var packgesPrice = await ret.ToListAsync();
|
||||
|
||||
List<ProductWithPackageUserPriceResponse> respList = new List<ProductWithPackageUserPriceResponse>();
|
||||
products.ForEach(p =>
|
||||
{
|
||||
var resp = new ProductWithPackageUserPriceResponse();
|
||||
resp.Product = p.MapTo<ProductResponse>();
|
||||
resp.PackageUserPrices = packgesPrice.Where(m => m.Package.ProductId == p.Id).ToList();
|
||||
respList.Add(resp);
|
||||
});
|
||||
return respList;
|
||||
}
|
||||
|
||||
public async Task<List<ProductUserPriceEntity>> GetProductUserPrice(int product,int userId)
|
||||
{
|
||||
return this.Query(m => m.ProductId == product && m.UserId == userId && m.Status == 1).ToList();
|
||||
}
|
||||
|
||||
public async Task<List<ProductUserPriceEntity>> GetProductUserPrice(int userId)
|
||||
{
|
||||
return this.Query(m => m.UserId == userId && m.Status == 1).ToList();
|
||||
}
|
||||
public async Task<ProductUserPriceEntity> GetPackageUserPrice(int packageId, int userId)
|
||||
{
|
||||
return this.Query(m => m.PackageId == packageId && m.UserId == userId&& m.Status==1).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Services/Hncore.Pass.Vpn/Service/UserService.cs
Normal file
30
Services/Hncore.Pass.Vpn/Service/UserService.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Infrastructure.WebApi;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Hncore.Pass.Vpn.Request.Product;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using System;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using System.Collections.Generic;
|
||||
using Hncore.Pass.BaseInfo.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public class UserService : ServiceBase<UserEntity>, IFindService
|
||||
{
|
||||
CourseContext m_DbContext;
|
||||
public UserService(CourseContext dbContext
|
||||
,IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
m_DbContext = dbContext;
|
||||
}
|
||||
|
||||
public async Task<List<UserEntity>> GetByIds(List<int> userids)
|
||||
{
|
||||
return await this.Query(m => userids.Contains(m.Id)).ToListAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
49
Services/Hncore.Pass.Vpn/Service/WxAppService.cs
Normal file
49
Services/Hncore.Pass.Vpn/Service/WxAppService.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Hncore.Wx.Open;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
|
||||
public partial class WxAppService : ServiceBase<WxAppEntity>
|
||||
{
|
||||
public WxAppService(CourseContext dbContext, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public async Task SaveAppInfo(GetAuthorizerInfoResponse info, int tenantId, int storeId)
|
||||
{
|
||||
var wxAppInfo = await this.Query(true).FirstOrDefaultAsync(m => m.TenantId == tenantId
|
||||
&& m.Appid == info.authorization_info.authorizer_appid
|
||||
&& m.DeleteTag == 0);
|
||||
|
||||
var wxAuthInfoNew = new WxAppEntity()
|
||||
{
|
||||
TenantId = tenantId,
|
||||
StoreId = storeId,
|
||||
Appid = info.authorization_info.authorizer_appid,
|
||||
HeadImg = info.authorizer_info.head_img,
|
||||
NickName = info.authorizer_info.nick_name,
|
||||
PrincipalName = info.authorizer_info.principal_name,
|
||||
UserName = info.authorizer_info.user_name,
|
||||
Bussinessinfo = info.authorizer_info.signature,
|
||||
AuthorizerState = 0,
|
||||
RefreshToken = info.authorization_info.authorizer_refresh_token,
|
||||
ExpiresIn = info.authorization_info.expires_in,
|
||||
};
|
||||
if (wxAppInfo == null)
|
||||
{
|
||||
await this.Add(wxAuthInfoNew);
|
||||
}
|
||||
else
|
||||
{
|
||||
wxAuthInfoNew.Id = wxAppInfo.Id;
|
||||
await this.Update(wxAuthInfoNew);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Services/Hncore.Pass.Vpn/Service/WxAppUserService.cs
Normal file
34
Services/Hncore.Pass.Vpn/Service/WxAppUserService.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Hncore.Infrastructure.Service;
|
||||
using Hncore.Pass.Vpn.Domain;
|
||||
using Hncore.Wx.Open;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Pass.Vpn.Service
|
||||
{
|
||||
public partial class WxAppUserService : ServiceBase<WxAppUserEntity>
|
||||
{
|
||||
WxAppService m_WxAppService;
|
||||
public WxAppUserService(WxAppService _WxAppService, CourseContext dbContext, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor)
|
||||
{
|
||||
m_WxAppService = _WxAppService;
|
||||
}
|
||||
public async Task<List<WxAppUserEntity>> GetWxUsers(List<int> UserId)
|
||||
{
|
||||
return await this.Query(m => UserId.Contains(m.UserId)).ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<WxAppUserEntity> GetWxUser(string appId, int userId)
|
||||
{
|
||||
return await this.Query(m => m.Appid == appId && m.UserId == userId).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<WxAppUserEntity> GetWxUser(string appId, string openId)
|
||||
{
|
||||
return await this.Query(m => m.Appid == appId && m.Openid == openId).FirstOrDefaultAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user