/// <summary> /// 判断当前已打开的IE中账号 与 当前任务账号 是否一致 /// </summary> /// <param name="info"></param> /// <returns></returns> private bool IsSameAccount(SBillTaskInfo info) { // 未登录,直接登录即可 if (!s_bIsLogining) { return(true); } try { var currUser = getCardInfo(); if (currUser.userName == info.username) { LOGGER.INFO($"当前在线用户[{FKBaseUtils.FKStringHelper.MaskString(info.username)}]和登录用户一致"); return(true); } } catch { LOGGER.INFO($"新登录用户[{FKBaseUtils.FKStringHelper.MaskString(info.username)}], 当前在线用户可能不是BCM用户"); return(false); } LOGGER.INFO($"新登录用户[{FKBaseUtils.FKStringHelper.MaskString(info.username)}], 当前在线用户可能不是BCM用户"); return(false); }
/// <summary> /// 从服务器进行注销 /// </summary> /// <returns></returns> private bool UnregsiterFromServer() { try { SUnregisteNode node = new SUnregisteNode(); node.id = GetCurCashierNodeID(); HttpSendResult result = RequestSender.SendRequestToServer(node); if (result.IsSendSuccessed() && result.ErrorStatus == 1) { LOGGER.INFO($"Node unregiste successed. NodeID = {node.id}"); return(true); } else { LOGGER.WARN($"Node unregiste failed. NodeID = {node.id}"); return(false); } } catch (Exception e) { LOGGER.ERROR($"Node unregiste error occured. Error = {e.ToString()}"); return(false); } }
/// <summary> /// 判断当前已打开的IE中账号 与 当前任务账号 是否一致 /// </summary> /// <param name="info"></param> /// <returns></returns> private bool IsSameAccount(SBillTaskInfo info) { // 未登录,直接登录即可 if (!s_bIsLogining) { return(true); } // 已登录,从页面获取account try { FKWebDriver.GetInstance.SwitchToFrameByID("contentFrame"); // 这是判断abc,如果不是abc,此项将为0,获取失败 string accountNumber = FKWebDriver.GetInstance.GetAttributeByXPath("//*[@id=\"debit\"]", "data-acctid"); if (String.IsNullOrEmpty(accountNumber)) { LOGGER.INFO($"当前登录用户为空,需要重新登录"); return(false); } if (String.Compare(info.accountNumber, accountNumber, true) != 0) { LOGGER.INFO($"新登录用户[{FKBaseUtils.FKStringHelper.MaskString(info.accountNumber)}], 当前在线用户[{FKBaseUtils.FKStringHelper.MaskString(accountNumber)}]"); return(false); } FKWebDriver.GetInstance.SwitchToParentFrame(); } catch { LOGGER.INFO($"新登录用户[{FKBaseUtils.FKStringHelper.MaskString(info.accountNumber)}], 当前在线用户可能不是ABC用户"); return(false); } LOGGER.INFO($"当前在线用户[{FKBaseUtils.FKStringHelper.MaskString(info.accountNumber)}]和登录用户一致"); return(true); }
/// <summary> /// 获取验证码字符串 /// </summary> /// <returns></returns> private string GetVerificationCodeString() { string tmpFile = System.IO.Path.GetTempFileName(); // 保存图片文件 if (!SaveVerificationCodeFile(tmpFile)) { return(""); } // 使用自定义方式解析出字符串 string CustomString = CustomGetStringByImage(tmpFile); // 使用OCR解析出字符串 string ORCString = "";// OCRGetStringByImage(tmpFile); CustomString = CustomString.Replace("*", ""); ORCString = ORCString.Replace("*", ""); LOGGER.INFO($"验证码:FK = {CustomString} OCR = {ORCString}"); // 删除图片文件 File.Delete(tmpFile); if (CustomString.Length != 4 && ORCString.Length == 4) { return(ORCString); } else if (CustomString.Length == 4 && ORCString.Length != 4) { return(CustomString); } else { return(CustomString); // 优先自定义 } }
/// <summary> /// 向服务器注册 /// </summary> private bool RegsiterToServer() { // 先尝试检查远程服务器是否可以ping通 bool bIsRomateCanPing = IsCanPingPass(); if (!bIsRomateCanPing) { LOGGER.ERROR("Can't pass server ip ping test, will not use registe node and heart-beat"); return(false); } // 开始注册 SRegisteNode node = new SRegisteNode(); node.bankCardNo = FKConfig.BankCardNo; node.ip = string.IsNullOrEmpty(FKConfig.LocalIP) ? FKBaseUtils.FKSystemEnviSettingHelper.GetLocalIPAddressByUri(FKConfig.ServerRegisteUrl) : FKConfig.LocalIP; node.publicKey = RSAKeyContainer.GetInstance.GetCSharpPublicKey(); LOGGER.INFO($"Begin to register to server. Bank card No = {node.bankCardNo}, Ip = {node.ip}"); HttpSendResult result = RequestSender.SendRequestToServer(node); if (result.IsSendSuccessed() && result.ErrorStatus == 1 && (!string.IsNullOrEmpty(result.publicKey))) { SetCurCashierNodeID(result.NodeID); RSAKeyContainer.GetInstance.SetJavaPublicKey(result.publicKey); LOGGER.INFO($"Register to server successed. Node id = {result.NodeID}"); return(true); } else { SetCurCashierNodeID(INVALID_NODE_ID); LOGGER.ERROR($"Register to server failed. but still use registe node and heart-beat. Node id = {GetCurCashierNodeID()}"); return(true); } }
/// <summary> /// 创建Web服务器 /// </summary> private void CreateWebServer() { try { if (FKConfig.IsUseHttpServer) { m_WebServer = new FKHttp.FKHttpServer(this, RequestReciver.Func_OnRequest, FKConfig.IsUseHttpsWebServer, FKConfig.WebServerListenUrl); } } catch (Exception e) { LOGGER.ERROR($"Create web server failed. Error = {e.ToString()}", 0); } if (m_WebServer == null || !m_WebServer.IsRunning()) { LOGGER.WARN("Web server is not running."); } else { if (m_WebServer.IsSupportingSSL()) { LOGGER.INFO("Create web server successed. Support HTTPS"); } else { LOGGER.INFO("Create web server successed. Only support HTTP"); } } }
/// <summary> /// 按下执行消息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button_DoCmd_Click(object sender, EventArgs e) { string strCmd = textBox_Cmd.Text; string[] strCmds = strCmd.Split(' '); if (strCmds.Length < 1) { button_Help_Click(null, null); return; } bool bSuccessed = false; string strRet = string.Empty; if (strCmds.Length == 1) { bSuccessed = DoCmd(strCmds[0], null, ref strRet); } else { bSuccessed = DoCmd(strCmds[0], strCmds.Skip(1).ToArray(), ref strRet); } if (bSuccessed) { LOGGER.INFO($"DoCmd {strCmds[0]} successed \n {strRet}"); } else { LOGGER.WARN($"DoCmd {strCmds[0]} failed. \n {strRet}"); } }
private bool IsSameAccount(SBillTaskInfo info) { // 未登录,直接登录即可 if (!s_bIsLogining) { return(true); } // 已登录,从页面获取account try { // 这是判断ccb,如果不是ccb,此项将为0,获取失败 string userName = FKWebDriver.GetInstance.GetAttributeByXPath("/html/body/div[6]/div[6]/div[1]/div[1]/p/b/span", "title"); if (String.IsNullOrEmpty(userName)) { return(false); } if (String.Compare(info.username, userName, true) != 0) { LOGGER.INFO($"新登录用户[{FKBaseUtils.FKStringHelper.MaskString(info.username)}], 当前在线用户[{FKBaseUtils.FKStringHelper.MaskString(userName)}]"); return(false); } } catch { LOGGER.INFO($"新登录用户[{FKBaseUtils.FKStringHelper.MaskString(info.username)}], 当前在线用户可能不是CCB用户"); return(false); } LOGGER.INFO($"当前在线用户[{FKBaseUtils.FKStringHelper.MaskString(info.username)}]和登录用户一致"); return(true); }
/// <summary> /// 逻辑线程 /// </summary> private void LogicThreadMain() { int nIdleTime = FKConfig.LoginThreadIdleTime; LOGGER.INFO($"Start Logic thread. Idle time = {nIdleTime} millseconds."); // 建议最早更新时间:若早于该时间则一定不会进行更新事件通知 DateTime SuggestEarlistUpdateTime = DateTime.Now; string strBankType = string.Empty; int nOprationType = 0; // 0: Unknown 1: GetBill 2: Out while (!m_bIsNeedCloseLogicThread) { if (m_BillTasksList.Count > 0) { try { nOprationType = 1; strBankType = m_BillTasksList.Peek().bankCode; HandleBillTask(); } catch (Exception e) { LOGGER.ERROR($"Handle bill task failed. Error = {e.ToString()}"); } } else if (m_OutTasksList.Count > 0) { try { nOprationType = 2; strBankType = m_OutTasksList.Peek().fromBankCode; HandleOutTask(); } catch (Exception e) { LOGGER.ERROR($"Handle out task failed. Error = {e.ToString()}"); } } { // 每次无论出入账与否,都尝试进行一次刷新 try { // 根据上一次执行的任务进行update更新 SuggestEarlistUpdateTime = HandleUpdateTask(SuggestEarlistUpdateTime, nOprationType, strBankType); } catch (Exception e) { LOGGER.ERROR($"Handle update task failed. Error = {e.ToString()}"); } // 逻辑线程休眠 Thread.Sleep(nIdleTime); } } LOGGER.INFO($"Logic thread exit"); }
/// <summary> /// 时间过滤器 /// </summary> /// <param name="info"></param> /// <param name="oneBill"></param> /// <returns> false表示被过滤掉 true表示需保留</returns> public static bool TimeFilter(SBillTaskInfo info, string billTime) { string startTime = info.startTime; string endTime = info.endTime; //一天以内数据不做过滤 if (startTime.Substring(0, 8) == endTime.Substring(0, 8)) { return(true); } DateTime dateTimeStart; bool ret = DateTime.TryParseExact(startTime, "yyyyMMdd HH:mm:ss", null, DateTimeStyles.None, out dateTimeStart); if (!ret) { LOGGER.INFO($"过滤开始时间格式错误:{startTime}"); return(true); } DateTime dateTimeEnd; ret = DateTime.TryParseExact(endTime, "yyyyMMdd HH:mm:ss", null, DateTimeStyles.None, out dateTimeEnd); if (!ret) { LOGGER.INFO($"过滤结束时间格式错误:{endTime}"); return(true); } if (dateTimeEnd.CompareTo(dateTimeStart) < 0) { //LOGGER.INFO($"过滤结束时间:{endTime}早于开始时间:{startTime}"); return(true); } DateTime dateTimeSumbmit; ret = DateTime.TryParseExact(billTime, "yyyy-MM-dd HH:mm:ss", null, DateTimeStyles.None, out dateTimeSumbmit); if (!ret) { LOGGER.INFO($"明细时间格式错误:{billTime}"); return(true); } if (dateTimeSumbmit.CompareTo(dateTimeStart) < 0) { //LOGGER.INFO($"删除项时间[{billTime}],过滤开始时间[{startTime}]"); return(false); } else if (dateTimeSumbmit.CompareTo(dateTimeEnd) > 0) { //LOGGER.INFO($"删除项时间[{billTime}],过滤结束时间[{endTime}]"); return(false); } return(true); }
public void Check() { var now = DateTime.Now; int leftSeconds = secondsForEachCall - (int)now.Subtract(lastCallTime).TotalSeconds; if (leftSeconds > 0) { LOGGER.INFO($"调用频率限制,睡眠:{leftSeconds}s"); Thread.Sleep(leftSeconds * 1000); } lastCallTime = DateTime.Now; }
/// <summary> /// 解析流水页面 /// </summary> /// <param name="html"></param> /// <param name="result"></param> /// <returns></returns> private bool ParseAutoBillHtmlPage(HtmlDocument html, ref SBillTaskResult result, SBillTaskInfo info) { try { var nodes = html.DocumentNode.SelectSingleNode("./table/tbody"); if (nodes == null) { LOGGER.INFO("未找到有效流水数据,可能已经查到最后一页"); return(false); } var items = nodes.SelectNodes("./tr"); if (items == null) { LOGGER.INFO("未找到有效流水数据,可能已经查到最后一页"); return(false); } if (items.Count == 0) { LOGGER.INFO("未找到有效流水数据,可能已经查到最后一页"); return(false); } foreach (var node in nodes.SelectNodes("./tr")) { SBillTaskResult.SBankBillInfo billItem = new SBillTaskResult.SBankBillInfo(); // 解析单一流水对象 if (ParseOneBillHtmlPage(node, ref billItem) == false) { continue; } // citic明细没有时间,一律不过滤 /*if (ResultFilter.TimeFilter(info, billItem.submitTime)) * { * result.billsList.Add(billItem); * }*/ result.billsList.Add(billItem); } result.status = (int)SBillTaskResult.ENUM_BillActionStatus.eBillActionStatus_Successed; } catch (Exception e) { result.msg = "CITIC解析返回html错误"; result.status = (int)SBillTaskResult.ENUM_BillActionStatus.eBillActionStatus_AutoProcessFailed; LOGGER.WARN($"CITIC解析返回html错误:{e.Message}"); return(false); } return(true); }
/// <summary> /// 处理流水查询任务 /// </summary> private void HandleBillTask() { try { SBillTaskInfo info = m_BillTasksList.Peek(); // 取出消息,不删除 LOGGER.INFO($"Handle a new bill task:\n {info.ToLogString()} \n, still left {m_BillTasksList.Count - 1} tasks in queue."); SBillTaskResult dealResult = new SBillTaskResult(); dealResult.taskID = info.taskID; dealResult.nodeID = GetCurCashierNodeID(); dealResult.bankId = info.bankId; // 记录当前在处理的任务ID SetCurTaskID(info.taskID); // 开始处理 AutomationBill(info, ref dealResult); LOGGER.WARN($"Auto get bill task is done. Now ready to send msg to server. TaskID = {info.taskID}.", info.taskID); // 发送回馈消息给服务器完毕 HttpSendResult SendResult = RequestSender.SendRequestToServer(dealResult); if (SendResult.IsSendSuccessed()) { SetLastTaskID(info.taskID); SetCurTaskID(INVALID_TASK_ID); LOGGER.INFO($"Send get bill result successed. TaskID = {info.taskID}. \n {SendResult.ToLogString()}"); } else { // result = null; 无论是否发送给服务器成功,只要执行成功,就不允许清除 SetLastTaskID(INVALID_TASK_ID); SetCurTaskID(INVALID_TASK_ID); LOGGER.ERROR($"Send get bill result failed. TaskID = {info.taskID}. \n {SendResult.ToLogString()}", info.taskID); } LOGGER.WARN($"Get bill task deal over. TaskID = {info.taskID}.", info.taskID); } catch (Exception e) { LOGGER.ERROR($"HandleBillTask exception.msg: {e.Message}."); } finally { SetCurTaskID(INVALID_TASK_ID); m_BillTasksList.Dequeue(); // 无论如何,该任务必须删除 } return; }
/// <summary> /// 关闭Web服务器 /// </summary> private void StopWebServer() { try { if (m_WebServer != null) { m_WebServer.Stop(); } } catch (Exception e) { LOGGER.ERROR($"Stop web server failed. Error = {e.ToString()}", 0); } LOGGER.INFO("Stop web server successed."); }
/// <summary> /// 释放 /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private void FKClose() { // 关闭心跳 StopHeartbeat(); // 申请从服务器注销 UnregsiterFromServer(); // 关闭Web服务器监听 StopWebServer(); // 关闭逻辑线程 StopLogicThread(); // 强杀IEDriver ForceShutdownIE(); LOGGER.INFO("Form close done."); }
/// <summary> /// 处理流水查询任务 /// </summary> private void HandleOutTask() { try { SOutTaskInfo info = m_OutTasksList.Peek(); // 取出消息,不删除 LOGGER.INFO($"Handle a new out task:\n {info.ToLogString()} \n, still left {m_OutTasksList.Count - 1} tasks in queue."); SOutTaskResult dealResult = new SOutTaskResult(); dealResult.taskID = info.taskID; dealResult.nodeID = GetCurCashierNodeID(); // 记录当前在处理的任务ID SetCurTaskID(info.taskID); // 开始处理 if (!AutomationOut(info, ref dealResult)) { } LOGGER.WARN($"Auto out task is done. Now ready to send msg to server. TaskID = {info.taskID}.", info.taskID); // 通知服务器处理结果 HttpSendResult sendResult = RequestSender.SendRequestToServer(dealResult); if (sendResult.IsSendSuccessed()) { SetLastTaskID(info.taskID); SetCurTaskID(INVALID_TASK_ID); LOGGER.INFO($"Send auto out task successed. TaskID = {info.taskID}. \n {sendResult.ToLogString()}"); } else { SetLastTaskID(INVALID_TASK_ID); SetCurTaskID(INVALID_TASK_ID); LOGGER.ERROR($"Send auto out task failed. TaskID = {info.taskID}. \n {sendResult.ToLogString()}", info.taskID); } LOGGER.WARN($"Out task deal over. TaskID = {info.taskID}.", info.taskID); } catch (Exception e) { LOGGER.ERROR($"Deal out task error occured. Error = {e.ToString()}"); } finally { SetCurTaskID(INVALID_TASK_ID); m_OutTasksList.Dequeue(); // 无论如何,该任务必须删除 } return; }
/// <summary> /// 安全释放App /// </summary> internal void SafeShutdown() { LOGGER.INFO($"Begin to safe shutdown. NodeID = {GetCurCashierNodeID()}"); try { // 计划下一部清除行为 FKClose(); // 清空所有的Key RSAKeyContainer.GetInstance.Clear(); } catch (Exception e) { LOGGER.WARN($"Safe shutdown failed, we will force close. Error = {e.ToString()}"); } }
/// <summary> /// Form 启动初始化函数 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void MainForm_Load(object sender, System.EventArgs e) { LOGGER.INFO("System init done, begin main form load."); // 设置标题 this.Text = GetAppDescption(); // 设置本线程名 Thread.CurrentThread.Name = "FKMainThread"; // 初次调用单例,创建RSA公私钥对 RSAKeyContainer.GetInstance.ToString(); m_InitTimer = new System.Windows.Forms.Timer(); m_InitTimer.Interval = 1000; m_InitTimer.Tick += new EventHandler(OnTimer_Init); m_InitTimer.Start(); }
/// <summary> /// 启动心跳 /// </summary> /// <returns></returns> private bool StartHeartbeat() { try { m_nHeartBeatTimer = new System.Timers.Timer(FKConfig.HeartbeatIdleTime); m_nHeartBeatTimer.Elapsed += (sender, e) => OnHeartbeatTimerEvent(sender, e, FKConfig.ServerHeartbeatUrl, this); m_nHeartBeatTimer.AutoReset = true; m_nHeartBeatTimer.Enabled = true; } catch (Exception e) { LOGGER.ERROR($"Create heart-beat timer failed. Error = {e.ToString()}"); return(false); } LOGGER.INFO($"Start heart-beat successed. TickTime = {FKConfig.HeartbeatIdleTime} ms."); return(true); }
/// <summary> /// 刷新事件 /// </summary> public static void Update() { if (!s_bIsLogining) // 未登录,不做任何刷新 { return; } try { int retryCount = 3; for (int i = 0; i < retryCount; i++) { if (FKWebAutomatic.FKWebDriver.GetInstance.ClickByXPath("//*[@class=\"index_page\"]")) { var element = FKWebDriver.GetInstance.WaitUntilVisibleByXPath("//*[@class=\"each_card\"]", 30000); if (element != null) { LOGGER.INFO("CITIC刷新主页成功"); return; } else { LOGGER.ERROR($"刷新等待主页元素超时,等待重试"); } } else { // 出现任何异常,立即关闭浏览器设置为未登录,等待下次登录 LOGGER.INFO($"CITIC刷新主页,失败[ClickByID返回false],等待重试"); Thread.Sleep(5000); } } } catch (Exception e) { LOGGER.ERROR($"Update CITIC bank error occured, IE driver will shutdown. Error = {e.ToString()}"); // 出现任何异常,立即关闭浏览器设置为未登录,等待下次登录 FKWebDriver.GetInstance.Close(); ForceShutdownIE(); s_bIsLogining = false; } LOGGER.INFO($"CITIC刷新主页失败,清理ie等待下次重新登录"); FKWebDriver.GetInstance.Close(); ForceShutdownIE(); s_bIsLogining = false; }
private bool IsSameAccount(SBillTaskInfo info) { // 未登录,直接登录即可 if (!s_bIsLogining) { return(true); } // 已登录,从页面获取account try { // 这是判断abc,如果不是abc,此项将为0,获取失败 string cardCode = FKWebDriver.GetInstance.GetAttributeByXPath("//*[@class=\"each_card\"]", "cardcode"); if (String.IsNullOrEmpty(cardCode)) { LOGGER.INFO($"当前登录用户为空,需要重新登录"); return(false); } string[] cardCodeArr = cardCode.Split('|'); if (cardCodeArr.Length < 2) { LOGGER.INFO($"当前登录用户未找到,需要重新登录"); return(false); } string accountNumber = cardCodeArr[1]; if (String.IsNullOrEmpty(accountNumber)) { LOGGER.INFO($"当前登录用户为空,需要重新登录"); return(false); } if (String.Compare(info.accountNumber, accountNumber, true) != 0) { LOGGER.INFO($"新登录用户[{FKBaseUtils.FKStringHelper.MaskString(info.accountNumber)}], 当前在线用户[{FKBaseUtils.FKStringHelper.MaskString(accountNumber)}]"); return(false); } } catch { LOGGER.INFO($"新登录用户[{FKBaseUtils.FKStringHelper.MaskString(info.accountNumber)}], 当前在线用户可能不是CITIC用户"); return(false); } LOGGER.INFO($"当前在线用户[{FKBaseUtils.FKStringHelper.MaskString(info.accountNumber)}]和登录用户一致"); return(true); }
/// <summary> /// 初始化 /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private void OnTimer_Init(object sender, EventArgs args) { // 计时器进行一次足够了 if (m_InitTimer != null) { m_InitTimer.Stop(); } // 创建Web服务器对象 CreateWebServer(); // 启动逻辑线程 StartLogicThread(); // 启动Web服务器监听 StartWebServer(); // 向服务器进行注册 if (RegsiterToServer()) { // 开始心跳 StartHeartbeat(); } LOGGER.INFO("Form init done."); }
/// <summary> /// 关闭心跳 /// </summary> /// <returns></returns> private bool StopHeartbeat() { try { if (m_nHeartBeatTimer != null) { m_nHeartBeatTimer.Stop(); m_nHeartBeatTimer.Close(); m_nHeartBeatTimer.Dispose(); LOGGER.INFO($"FKClose heart-beat successed."); } else { LOGGER.INFO($"We did't use heart-beat."); } } catch (Exception e) { LOGGER.ERROR($"FKClose heart-beat timer failed. Error = {e.ToString()}"); return(false); } return(true); }
/// <summary> /// 自动查询核心函数 /// </summary> /// <param name="nTaskID"></param> /// <param name="info"></param> /// <param name="result"></param> /// <returns></returns> public override bool AutoBill(int nTaskID, SBillTaskInfo info, ref SBillTaskResult result) { // 判断当前是否是同一个账号 if (!IsSameAccount(info)) { FKWebDriver.GetInstance.Close(); ForceShutdownIE(); s_bIsLogining = false; } // 先尝试进行登录 string logPrefix = $"银行代码[ABC]获取明细,TaskID[{info.taskID}],"; LOGGER.INFO($"{logPrefix}正在尝试登录 ..."); s_bIsLogining = TryLogin(info, ref result); if (!s_bIsLogining) { LOGGER.INFO($"{logPrefix}登录失败,失败原因[{result.msg}]"); FKWebDriver.GetInstance.Close(); ForceShutdownIE(); return(false); } LOGGER.INFO($"{logPrefix}登录成功,开始获取明细"); // 查询 bool ret = QueryAutoBill(info, ref result); if (!ret) { LOGGER.INFO($"{logPrefix}获取明细失败,失败原因[{result.msg}]"); } else { LOGGER.INFO($"{logPrefix}获取明细成功"); } return(ret); }
/// <summary> /// 刷新事件 /// </summary> public static void Update() { if (!s_bIsLogining) // 未登录,不做任何刷新 { return; } try { // 农行刷新时经常超时导致刷新失败,重试3次,有效减少超时导致的失败。 int retryCount = 3; for (int i = 0; i < retryCount; i++) { // 刷新首页按钮,保证登录状态 if (FKWebAutomatic.FKWebDriver.GetInstance.ClickByXPath("/html/body/div[5]/div/div[2]/ul/li[1]/span")) { LOGGER.INFO("ABC刷新主页成功"); return; } else { // 出现任何异常,立即关闭浏览器设置为未登录,等待下次登录 LOGGER.INFO($"ABC刷新主页,失败[ClickByID返回false],等待重试"); Thread.Sleep(5000); } } } catch (Exception e) { LOGGER.INFO($"ABC刷新主页,失败[{e.Message}]"); } LOGGER.INFO($"ABC刷新主页失败,清理ie等待下次重新登录"); // 重试后仍然失败 FKWebDriver.GetInstance.Close(); ForceShutdownIE(); s_bIsLogining = false; }
/// <summary> /// 获取验证码字符串 /// </summary> /// <returns></returns> private string GetVerificationCodeString() { string tmpFile = System.IO.Path.GetTempFileName(); // 保存图片文件 if (!SaveVerificationCodeFile(tmpFile)) { LOGGER.INFO($"保存文件失败"); return(""); } // 使用自定义方式解析出字符串 string CustomString = CustomGetStringByImage(tmpFile); // 使用OCR解析出字符串 string ORCString = OCRGetStringByImage(tmpFile); CustomString = CustomString.Replace("*", ""); ORCString = ORCString.Replace("*", ""); LOGGER.INFO($"验证码:FK = {CustomString} OCR = {ORCString}"); // 删除图片文件 File.Delete(tmpFile); int charCount = 5; if (CustomString.Length != charCount && ORCString.Length == charCount) { return(ORCString); } else if (CustomString.Length == charCount && ORCString.Length != charCount) { return(CustomString); } else { return(ORCString); // 自定义训练好之前优先tesser } }
/// <summary> /// 初始化函数 /// </summary> /// <returns></returns> public override bool Init() { s_FreqLimit.Check(); try { // 如果没有登录过,清除前面残留的ie if (s_bIsLogining == false) { var bankCode = "ABC"; LOGGER.INFO($"银行代码为[{bankCode}]的账号未在线,清理当前在线账号"); FKWebDriver.GetInstance.Close(); ForceShutdownIE(); Thread.Sleep(1000); } } catch (Exception e) { LOGGER.ERROR($"Init failed ... Error = {e.ToString()}"); FKWebDriver.GetInstance.Close(); ForceShutdownIE(); return(false); } return(true); }
private BCM_BankInfo getCardInfo() { string PSessionId = FKWebAutomatic.FKWebDriver.GetInstance.GetAttributeByXPath("//*[@name=\"PSessionId\"]", "value"); Dictionary <string, string> getHeader = new Dictionary <string, string>(); getHeader.Add("Cookie", FKWebAutomatic.FKWebDriver.GetInstance.GetAllCookies()); getHeader.Add("Accept", "text/javascript;charset=utf-8"); getHeader.Add("Referer", $"https://pbank.95559.com.cn/personbank/app/pebs.do?PSessionId={PSessionId}&x-channel=0&menuCode=&appId=&startMenu=&ibpsProtocolReq=&pebsUrl=&args=#1"); getHeader.Add("Accept-Language", "zh-CN"); getHeader.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"); getHeader.Add("Content-Type", "application/x-www-form-urlencoded"); getHeader.Add("Accept-Encoding", "gzip, deflate"); getHeader.Add("Host", "pbank.95559.com.cn"); string getUrl = $"https://pbank.95559.com.cn/personbank/system/syCardList.ajax?PSessionId={PSessionId}&x-channel=0&menuCode=P002000"; string jsonData = FKHttp.FKHttpClient.GET(getUrl, getHeader); LOGGER.INFO(FKHttp.FKHttpClient.GET(getUrl, getHeader)); BCM_BankInfo bcm_BankInfo = new BCM_BankInfo(); try { var o = JsonConvert.DeserializeObject <dynamic>(jsonData); bcm_BankInfo.userName = (string)o.RSP_BODY.accounts[0].alias; bcm_BankInfo.PSessionId = (string)o.RSP_BODY.PSessionId; bcm_BankInfo.safeValue = (string)o.RSP_BODY.safeValue; bcm_BankInfo.uuid = (string)o.RSP_BODY.accounts[0].uuid; bcm_BankInfo.cardNo = ((string)o.RSP_BODY.accounts[0].cardNo).Replace(" ", ""); } catch { } LOGGER.INFO($"bcm_BankInfo is {bcm_BankInfo.ToString()}"); return(bcm_BankInfo); }
/// <summary> /// 尝试登录 /// </summary> /// <param name="info"></param> /// <param name="result"></param> /// <returns></returns> private bool TryLogin(SBillTaskInfo info, ref SBillTaskResult result) { if (s_bIsLogining) { return(true); } bool isOCRPass = false; try { //FKWebDriver webDriver = FKWebDriver.GetInstance; string loginUrl = FKConfig.ABCLoginUrl; // 此部分代码根据现有网银官网的页面设计 // 如果个人银行网页改版,此处可能需要根据新页面做相应调整 FKWebAutomatic.FKWebDriver.GetInstance.OpenUrl(loginUrl); // 等待出现登录界面 var element = FKWebAutomatic.FKWebDriver.GetInstance.WaitUntilVisibleByXPath("//*[@id=\"username\"]", 30000); if (element == null) { result.status = (int)SBillTaskResult.ENUM_BillActionStatus.eBillActionStatus_WaitElementTimeout; result.msg = "等待登录账号元素超时,可能页面未正常打开"; return(false); } // 填充登录账号 FKWebAutomatic.FKWebDriver.GetInstance.SetTextByID("username", info.username); // 填充密码 LoginPassword(info.password); // 填充验证码,由于验证码可能识别失败,所以需要重试 int retryCount = 20; for (int i = 0; i < retryCount; i++) { string ocr = GetVerificationCodeString(); // 如果识别个数都不对 没必要输入了 重刷验证码再识别 if (ocr.Length == 4) { FKWebAutomatic.FKWebDriver.GetInstance.SetTextByID("code", ocr); //移走焦点 FKWebAutomatic.FKWebDriver.GetInstance.ClickByID("username"); // 填充完成后等待识别验证码打钩 Thread.Sleep(5000); // 第一次此元素为隐藏,等待出现 FKWebAutomatic.FKWebDriver.GetInstance.WaitUntilVisibleByXPath("//*[@id=\"imgError\"]", 10000); // 识别结果获取 string successString = FKWebAutomatic.FKWebDriver.GetInstance.GetAttributeByXPath("//*[@id=\"imgError\"]", "class"); if (successString == "v-code-error right") { // 点击登录 FKWebAutomatic.FKWebDriver.GetInstance.ClickByID("logo"); bool isInput = false; // 用户名提示为空 重新输入 if (FKWebAutomatic.FKWebDriver.GetInstance.IsElementVisiableByXPath("//*[@id=\"username-error\"]")) { LOGGER.INFO("用户名为空,重新输入"); FKWebAutomatic.FKWebDriver.GetInstance.SetTextByID("username", info.username); isInput = true; } // 密码提示为空 重新输入 if (FKWebAutomatic.FKWebDriver.GetInstance.IsElementVisiableByXPath("//*[@id=\"powerpass_ie_dyn_Msg\"]")) { LOGGER.INFO("密码为空或者不正确,重新输入"); LoginPassword(info.password, true); isInput = true; } // 多次输入验证码失败后 银行重新清空用户名密码,重填 if (FKWebAutomatic.FKWebDriver.GetInstance.IsElementVisiableByXPath("/html/body/div[2]/div[5]/div/div[1]/div[5]/form/div[5]")) { FKWebAutomatic.FKWebDriver.GetInstance.SetTextByID("username", info.username); LoginPassword(info.password, true); isInput = true; } if (isInput) { // 输入后需要重新点击登录 FKWebAutomatic.FKWebDriver.GetInstance.ClickByID("logo"); } isOCRPass = true; break; } Console.WriteLine($"successString = {successString}"); } // 失败 重新刷新验证码 FKWebAutomatic.FKWebDriver.GetInstance.ClickByID("vCode"); Thread.Sleep(1000); } if (!isOCRPass) { result.status = (int)SBillTaskResult.ENUM_BillActionStatus.eBillActionStatus_WaitElementTimeout; result.msg = "验证码超过重试次数"; return(false); } // 超时等待登陆成功 element = FKWebAutomatic.FKWebDriver.GetInstance.WaitUntilVisibleByXPath("//*[@id=\"intro4-1\"]", 30000); if (element != null) { LOGGER.INFO("成功获取登录element,登录成功"); return(true); } else { result.status = (int)SBillTaskResult.ENUM_BillActionStatus.eBillActionStatus_LoginFailed; result.msg = $"等待首页超时"; return(false); } } catch (Exception e) { result.status = (int)SBillTaskResult.ENUM_BillActionStatus.eBillActionStatus_LoginFailed; result.msg = $"TryLogin抛出异常[[{e.Message}]"; return(false); } }
/// <summary> /// 查询流水(在已登录成功后) /// </summary> /// <param name="info"></param> /// <param name="result"></param> /// <returns></returns> private bool QueryAutoBill(SBillTaskInfo info, ref SBillTaskResult result) { /** 完整的获取明细curl命令,此命令最终返回的是一个标准xls的文件,需要进一步解析文件才能提取出明细 * ---------------------------------------------------------------------------------- * curl 'https://perbank.abchina.com/EbankSite/AccountTradeDetailDownloadAct.do' * -H 'Accept: text/html, application/xhtml+xml, *\/*' * - H 'Referer: https://perbank.abchina.com/EbankSite/AccountTradeDetailQueryInitAct.do' * - H 'Accept-Language: zh-CN' * - H 'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko' * - H 'Content-Type: application/x-www-form-urlencoded' * - H 'Accept-Encoding: gzip, deflate' * - H 'Host: perbank.abchina.com' * - H 'Content-Length: 136' * - H 'Connection: Keep-Alive' * - H 'Cookie: WT_FPC=id=10.235.177.249-2296909152.30606638:lv=1500978056097:ss=1500977553848; ASP.NET_SessionId=elwlscn2t0puisyczziuwwdt; _ABCPerbankLogonCookie__=; BIGipServerpool_perbank_EbankSite=!Q5CBtVY5fUNWSa38cCqlIAZb8CxfUQboxPynXFLAUdu31cHrqqE7Bl6NuLXg8tH9gLUKWOZc2cVc9J8=' * --data 'acctId=6228482568556511677&acctOpenBankId=34905&acctType=401&provCode=12&acctCurCode=156&oofeFlg=0&trnStartDt=20160804&trnEndDt=20170727' * * ---------------------------------------------------------------------------------- * --data参数解释 * acctId 卡号 从传入参数中获取 * acctOpenBankId 开户行 需要从页面提取 * acctType 不懂 但是应该是账户相关 需要从页面提取 * provCode 省份code 页面提取 * acctCurCode 不懂 页面提取 * oofeFlg 不懂 传0 * trnStartDt 开始日期 * trnEndDt 结束日期 * **/ if (!s_bIsLogining) { // 未登录 return(false); } result.taskID = info.taskID; try { // 实际测试过程中发现这个链接是随着账号改变,需要在首页中获取 string postUrl = FKConfig.ABCBillUrl; if (string.IsNullOrEmpty(postUrl)) { result.status = (int)SBillTaskResult.ENUM_BillActionStatus.eBillActionStatus_AutoProcessFailed; result.msg = "ABC Post url获取失败"; return(false); } // 构造post content var postContentString = GetAutoBillPostContent(info); if (string.IsNullOrEmpty(postContentString)) { result.status = (int)SBillTaskResult.ENUM_BillActionStatus.eBillActionStatus_AutoProcessFailed; result.msg = "ABC Post content构造失败"; return(false); } // 构造post header var postHeader = GetAutoBillPostHeader(); // POST获取文件 string tmpFile = System.IO.Path.GetTempFileName(); string postResult = (string)FKHttp.FKHttpClient.POST(postUrl, postContentString, postHeader, 300000, tmpFile); if (File.Exists(tmpFile)) { bool bRet = parseXlsContent(tmpFile, ref result, info); int nBillCount = 0; if (result.billsList != null) { nBillCount = result.billsList.Count; } LOGGER.INFO($"XLS Tmp file = {tmpFile} InfoLen = {nBillCount}"); //delFile(tmpFile); // TODO: 前期测试不要删除,文件不太大的话,不会引发过多问题,之后版本删除 return(bRet); } else { result.status = (int)SBillTaskResult.ENUM_BillActionStatus.eBillActionStatus_AutoProcessFailed; LOGGER.INFO($"Can't find XLS Tmp file = {tmpFile}"); return(false); } } catch (Exception e) { result.msg = $"QueryAutoBill抛出异常[{e.Message}]"; return(false); } }