def check_result(self, xml): start_time = time.time() while time.time() - start_time < 60: cur_activity = self.driver.get_cur_activity() xml = self.driver.get_xml() if self.__handle_random_page(cur_activity, xml): start_time = time.time() continue elif cur_activity == 'com.ccb.framework.security.base.successpage.CcbSuccessPageAct': check_result_btn = re.findall(self.__pattern_check_result_btn, xml) if len(check_result_btn) == 1: self.__click(check_result_btn[0]) elif '转账提交成功' in xml or re.search( r'转账成功(.+?)" resource-id="com.chinamworld.main:id/tv_dlg_content"', xml): ret = '转账成功' logger.info(ret) return True, ret elif re.search( r'具体原因:(.+?)" resource-id="com.chinamworld.main:id/tv_dlg_content"', xml): ret = re.findall( r'具体原因:(.+?)" resource-id="com.chinamworld.main:id/tv_dlg_content"', xml)[0] logger.info(ret) raise UserError(ret) else: logger.warning('未知 activity %s' % cur_activity) raise MyError('查询转账结果超时')
def check_result(self, xml): start_time = time.time() while time.time() - start_time < 180: cur_activity = self.driver.get_cur_activity() xml = self.driver.get_xml() if self.__handle_random_page(cur_activity, xml): logger.info() start_time = time.time() continue elif '转账已受理' in xml or '转账成功' in xml: self.send_status(self.taskid, 0) ret = '转账成功' logger.info(ret) self.__click(re.findall(self.__pattern_complish, xml)[0]) return True, ret elif '账号户名不符' in xml: self.send_status(self.taskid, 0) ret = '账号户名不符' logger.info(ret) self.__click(re.findall(self.__pattern_back, xml)[0]) return False, ret elif '通讯中断啦' in xml: self.send_status(self.taskid, 0) raise UserError(f'用户未点击k宝的ok键') else: logger.warning('未知 activity %s' % cur_activity) raise MyError('查询转账结果超时')
def __transfer(self, xml, name, card, money, bank_name, only4remainds=False): start_time = time.time() self._remainds = '' while time.time() - start_time < 80: cur_activity = self.driver.get_cur_activity() xml = self.driver.get_xml() if self.__handle_random_page(cur_activity, xml): start_time = time.time() continue elif cur_activity == 'com.ccb.transfer.smarttransfer.view.SmartTransferMainAct': if re.search(self.__pattern_continue, xml): ret = re.findall(self.__pattern_continue, xml)[0] logger.info('点击继续') self.__click(ret) continue if re.search(self.__pattern_check_result_sure_btn, xml): ret = re.findall(self.__pattern_continue, xml)[0] logger.info('点击确定') self.__click(ret) continue ''' ret_remainds = xml.find('活期储蓄') if ret_remainds == -1: xml = self.driver.get_xml() ret_remainds = xml.find('活期储蓄') if ret_remainds == -1: logger.error(f'未找到余额, {cur_activity}, {xml}') continue ret_remainds = xml[ret_remainds + len('活期储蓄') : ] ret_remainds = [float(ret_remainds[: ret_remainds.find('"')])] ''' # 正则表达式不稳定 ret_remainds = re.findall(self.__pattern_remainds, xml) if len(ret_remainds) != 1: logger.error(f'未找到余额, {ret_remainds}') continue if only4remainds: logger.info(f'余额:{ret_remainds[0]}') return re.sub(r',', '', ret_remainds[0]), xml ret_reciver = re.findall(self.__pattern_reciver, xml) if len(ret_reciver) != 1: logger.error('未找到收款人控件') continue ret_card = re.findall(self.__pattern_card, xml) if len(ret_card) != 1: logger.error('未找到卡号控件') continue ret_money = re.findall(self.__pattern_money, xml) if len(ret_money) != 1: logger.error('未找到转账金额控件') continue ret_next = re.findall(self.__pattern_next, xml) if len(ret_next) != 1: logger.error('未找到下一步控件') continue self._remainds = re.sub(r',', '', ret_remainds[0]) logger.info(f'余额:{self._remainds}') if float(self._remainds) < float(money): raise NomoneyError(f'余额不足{money}元,当前余额{self._remainds}元') logger.info('输入收款人 %s' % name) self.__click(ret_reciver[0]) self.driver.input_text(name) logger.info('输入卡号 %s' % card) self.__click(ret_card[0]) for c in card: x = int(self.code_key_board[c][0] * self.driver.width()) y = int(self.code_key_board[c][1] * self.driver.height()) self.driver.click(x, y) self.driver.back() time.sleep(2) temp_start = time.time() while time.time() - temp_start < 30: ret_money = re.findall(self.__pattern_money, self.driver.get_xml()) if len(ret_money) != 1: time.sleep(2) continue logger.info('输入金额 %s' % money) self.__click(ret_money[0]) for c in money: x = int(self.code_key_board[c][0] * self.driver.width()) y = int(self.code_key_board[c][1] * self.driver.height()) self.driver.click(x, y) self.driver.back() time.sleep(0.5) xml = self.driver.get_xml() if re.search(self.__pattern_bank_name, xml): raise UserError(f'未选择银行') self.driver.swip(0.5, 0.7, 0.5, 0.3) logger.info('点击下一步') self.__click(ret_next[0]) start_time = time.time() break else: raise MyError(f'可能网络状况不佳,导致一直找不到输入金额的控件') elif cur_activity == 'com.ccb.framework.security.transecurityverify.TransSecurityVerifyDialogAct': logger.info('已进入付款页面') return self._remainds, xml else: logger.warning('未知 activity %s' % cur_activity) raise MyError('转账页面操作超时')
def __handle_random_page(self, activity, xml='', back=False): xml = self.driver.get_xml() if xml == '' else xml if activity == '': if len(re.findall(self.__pattern_udpate_text, xml)) == 1: ret = re.findall(self.__pattern_udpate_text, xml) logger.info('点击取消更新按钮') self.__click(ret[0]) return True elif not back and len(re.findall(self.__pattern_continue, xml)) == 1: ret = re.findall(self.__pattern_continue, xml) logger.info('点击继续按钮') self.__click(ret[0]) return True elif activity == 'com.ccb.start.view.startdialog.StartDialogActivity' or activity == 'com.ccb.transfer.transfer_home.view.TransferHomeAct': if re.search(self.__pattern_close, xml): logger.info('点击叉叉') self.__click(re.findall(self.__pattern_close, xml)[0]) return True elif re.search(self.__pattern_udpate_text, xml): logger.info('取消更新按钮') self.__click(re.findall(self.__pattern_udpate_text, xml)[0]) return True elif back is True and activity == 'com.ccb.transfer.smarttransfer.view.SmartTransferMainAct': if len(re.findall(self.__pattern_check_result_cancle_btn, xml)) == 1: ret = re.findall(self.__pattern_check_result_cancle_btn, xml) logger.info(f'点击转账页面的取消按钮') self.__click(ret[0]) return True if len(re.findall(self.__pattern_check_result_sure_btn, xml)) == 1: ret = re.findall(self.__pattern_check_result_sure_btn, xml) logger.info('点击转账页面的确定按钮') self.__click(ret[0]) return True elif back and activity == 'com.ccb.framework.security.base.successpage.CcbSuccessPageAct': if len(re.findall(self.__pattern_check_result_sure_btn, xml)) == 1: ret = re.findall(self.__pattern_check_result_sure_btn, xml) logger.info('点击转账结果页面的确定按钮') self.__click(ret[0]) return True elif len(re.findall(self.__pattern_check_result_cancle_btn, xml)) == 1: ret = re.findall(self.__pattern_check_result_cancle_btn, xml) logger.info('点击转账结果页面的取消按钮') self.__click(ret[0]) return True elif activity == 'com.ccb.start.MainActivity': if len(re.findall(self.__pattern_udpate_text, xml)) == 1: ret = re.findall(self.__pattern_udpate_text, xml) logger.info('点击取消更新按钮') self.__click(ret[0]) return True elif activity == 'com.ccb.framework.security.login.internal.view.LoginActivity': if re.search(self.__pattern_close, xml): logger.info('点击叉叉') self.__click(re.findall(self.__pattern_close, xml)[0]) return True elif re.search(self.__pattern_udpate_text, xml): logger.info('取消更新按钮') self.__click(re.findall(self.__pattern_udpate_text, xml)[0]) return True logger.info('进入登录页面') ret = re.findall(self.__pattern_pw_edit, xml) if len(ret) != 1: logger.warning('未找到密码编辑框') return False logger.info('点击密码编辑框') self.__click(ret[0]) time.sleep(0.5) # 等待键盘弹出来 # 匹配登录按钮 ret = re.findall(self.__pattern_login, xml) if len(ret) != 1: logger.warning('未找到登录按钮') return False logger.info('输入密码中') for c in self.login_passwd: x = int(self.login_key_board[c][0] * self.driver.width()) y = int(self.login_key_board[c][1] * self.driver.height()) logger.info(f'{c}, {x}, {y}') self.driver.click(x, y) logger.info('点击登录按钮') self.__click(ret[0]) time.sleep(2.5) return True elif re.search(self.__pattern_exception, xml): ret = re.findall(self.__pattern_exception, xml)[0] self.__click(ret) logger.info('点击关闭按钮') return True else: for error_text in ['收款方姓名与账户户名不一致', '交易金额低于总行允许的最低单笔限额']: if error_text in xml: if back: self.__click( re.findall(self.__pattern_check_result_sure_btn, xml)[0]) else: raise UserError(error_text) return True else: logger.info(f'未知,activity: {activity}') return False
def __transfer(self, xml, name, card, money, bank_name, only4remainds=False): start_time = time.time() self._remainds = '' while time.time() - start_time < 100: cur_activity = self.driver.get_cur_activity() xml = self.driver.get_xml() if self.__handle_random_page(cur_activity, xml): start_time = time.time() continue elif '提交了一笔转相同' in xml and re.search(self.__pattern_sure, xml): self.__click(re.findall(self.__pattern_sure, xml)[0]) elif cur_activity == 'com.android.bankabc.MainActivity' and '请输入转账金额' in xml: # 正则表达式不稳定 ret_remainds = re.findall(self.__pattern_remainds, xml) if len(ret_remainds) != 1: logger.error(f'未找到余额, {ret_remainds}') continue if only4remainds: logger.info(f'余额:{ret_remainds[0]}') return re.sub(r',', '', ret_remainds[0]), xml ret_reciver = re.findall(self.__pattern_reciver, xml) if len(ret_reciver) != 1: logger.error('未找到收款人控件') continue ret_card = re.findall(self.__pattern_card, xml) if len(ret_card) != 1: logger.error('未找到卡号控件') continue ret_money = re.findall(self.__pattern_money, xml) if len(ret_money) != 1: logger.error('未找到转账金额控件') continue self._remainds = re.sub(r',', '', ret_remainds[0]) logger.info(f'余额:{self._remainds}') if float(self._remainds) < float(money): raise NomoneyError(f'余额不足{money}元,当前余额{self._remainds}元') logger.info('输入收款人 %s' % name) self.__click(ret_reciver[0], cnt=2) time.sleep(0.2) self.driver.input_text(name) time.sleep(0.2) logger.info('输入卡号 %s' % card) self.__click(ret_card[0], cnt=2) self.driver.input_text_by_adb(card) self.__click(ret_money[0], cnt=2) time.sleep(1) logger.info('输入金额 %s' % money) self.__click(ret_money[0], cnt=2) time.sleep(0.2) self.driver.input_text_by_adb(money) xml = self.driver.get_xml() if re.search(self.__pattern_bank_name, xml): logger.info(f'未找到银行{bank_name},搜索去找') self.__click(re.findall(self.__pattern_bank_name, xml)[0], cnt=1) search_time = time.time() while time.time() - search_time < 10: xml = self.driver.get_xml() if not re.search(self.__pattern_search, xml): continue self.__click(re.findall(self.__pattern_search, xml)[0], cnt=1) logger.info(f'输入银行{bank_name}') self.driver.input_text(bank_name) search_time = time.time() pattern = f'text="\s*{bank_name}\s*" resource-id="com.android.bankabc:id/tv_title" class="android.widget.TextView".+?bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"' logger.info(f'用正则查找银行 {pattern}') while time.time() - search_time < 10: xml = self.driver.get_xml() if not re.search(pattern, xml): continue self.__click(re.findall(pattern, xml)[0]) time.sleep(1) break else: raise UserError(f'卡号{card}对应的银行{bank_name}不存在') break else: raise MyError(f'进入银行选择界面超时') self.driver.swip(0.5, 0.7, 0.5, 0.3) xml = self.driver.get_xml() logger.info('点击下一步') ret_next = re.findall(self.__pattern_next, xml) if len(ret_next) == 0: raise MyError("未能找到'下一步'按钮") self.__click(ret_next[0]) # 发http请求通知打开k宝 self.send_status(self.taskid, 1) start_time = time.time() elif '未搜索到您的K宝' in xml: self.send_status(self.taskid, 0) raise UserError('用户未打开k宝') elif '请输入K宝密码' in xml: logger.info('已进入付款页面') return self._remainds, xml else: logger.warning('未知 activity %s' % cur_activity) raise MyError('转账页面操作超时')
def __handle_random_page(self, activity, xml='', back=False): xml = self.driver.get_xml() if xml == '' else xml if re.search(self.__pattern_sure, xml) and '会话超时' in xml: logger.info(f'会话超时,点击确定按钮') self.__click(re.findall(self.__pattern_sure, xml)[0]) raise RePlayError('') elif re.search(self.__pattern_cancle, xml) and ('确定' not in xml or back): logger.info('点击取消') self.__click(re.findall(self.__pattern_cancle, xml)[0]) return True elif re.search(self.__pattern_sure, xml): if back or '确定转账' in xml: if back and '确定转账' in xml: return False if re.search(self.__pattern_sure, xml): self.__click(re.findall(self.__pattern_sure, xml)[0]) elif re.search(self.__pattern_next_pay, xml): self.__click(re.findall(self.__pattern_next_pay, xml)[0]) return True elif '请输入收款账户' in xml: raise UserError(f"用户未提供收款账户") elif '请输入收款方' in xml: raise UserError(f'用户未提供收款账户') elif '请选择或输入转账金额' in xml: raise UserError(f'用户未提供转账金额') elif '未搜索到您的k宝' in xml: raise UserError(f'未打开k宝') elif '蓝牙k宝连接顿开' in xml: raise UserError(f'蓝牙k宝连接顿开') else: return False elif back is True and '继续转账' in xml and re.search( self.__pattern_complish, xml): logger.info(f'点击完成 ') self.__click(re.findall(self.__pattern_complish, xml)[0]) return True elif (back is True or '会话超时,请重新登录' in xml) and re.search( self.__pattern_back, xml): logger.info(f'点击返回 ') self.__click(re.findall(self.__pattern_back, xml)[0]) return True elif activity == 'com.android.bankabc.MainActivity' and re.search( self.__pattern_login, xml): if back is True: # 在登录界面处于返回状态,则按返回图标, 返回键在此界面没有用 if re.search(self.__pattern_back_edit, xml): self.__click(re.findall(self.__pattern_back_edit, xml)[0]) return True else: return False else: logger.info(f'进入登录页面') self.__click(re.findall(self.__pattern_pw_edit, xml)[0]) time.sleep(1) cur = DIGITAL keyboard = KeyBoardOcr.Ocr( self.driver.screencap(), self.login_digit_keyboard_templateSign) login_keyboard = self.login_digit_keyboard for c in self.login_passwd: if c.isdigit() and cur == CHARACTER: # 切换数字键盘 logger.info(f'切换数字键盘 {c.isdigit()} {cur}') self.driver.click( self.login_char2digit[0] * self.driver.width(), self.login_char2digit[1] * self.driver.height()) keyboard = KeyBoardOcr.Ocr( self.driver.screencap(), self.login_digit_keyboard_templateSign) login_keyboard = self.login_digit_keyboard cur = DIGITAL elif c.isalpha() and cur == DIGITAL: # 切换字母键盘 logger.info(f'切换字母键盘 {c.isalpha()} {cur}') self.driver.click( self.login_digit2char[0] * self.driver.width(), self.login_digit2char[1] * self.driver.height()) keyboard = KeyBoardOcr.Ocr( self.driver.screencap(), self.login_char_keyboard_templateSign) login_keyboard = self.login_char_keyboard cur = CHARACTER for i in range(3): if c in keyboard: pos = login_keyboard[keyboard[c]] pos = (int(pos[0] * self.driver.width()), int(pos[1] * self.driver.height())) self.driver.click(pos[0], pos[1]) logger.info(f'{c}{pos}') break templateSign = self.login_char_keyboard_templateSign if c.isalpha( ) else self.login_digit_keyboard_templateSign keyboard = KeyBoardOcr.Ocr(self.driver.screencap(), templateSign) else: xml = self.driver.get_xml() if re.search(self.__pattern_login, xml): raise MyError('无法在登录%s键盘识别字母%s, %s' % ('数字' if cur == DIGITAL else '字母', c, keyboard)) elif '请输入或选择收款方' in xml: # 此时进入了转账页面 logger.info(f'走出登录页面') return True self.driver.click(self.login_btn[0] * self.driver.width(), self.login_btn[1] * self.driver.height()) time.sleep(1) return True return False
def __pay(self, code): start_time = time.time() while time.time() - start_time < 70: # 更新页面 cur_activity = self.driver.get_cur_activity() xml = self.driver.get_xml() if self.__handle_random_page(cur_activity, xml): start_time = time.time() continue elif cur_activity == 'com.pingan.core.base.PocketWebViewActivity': if '"收不到验证码"' in xml and re.search(self.__pattern_sms_prompt, xml): logger.info(f'取消收不到短信提醒框') self.__click(re.findall(self.__pattern_sms_prompt, xml)[0]) elif '的取款密码' in xml: logger.info(f'输入取款密码') for c in code: x = int(self.login_key_board_digital[c][0] * self.driver.width()) y = int(self.login_key_board_digital[c][1] * self.driver.height()) self.driver.click(x, y) msg_start_time = time.time() self.driver.click(self.finish[0] * self.driver.width(), self.finish[1] * self.driver.height()) time.sleep(1) elif '验证码' in xml and '手机号' in xml and '查收' in xml: logger.info('进入验证码输入界面') temp_start = time.time() while time.time() - temp_start < 120: msg_list = MsgManger.getMsg('95511', int(msg_start_time)) if len(msg_list) == 0: time.sleep(1) continue msg = msg_list[0] pattern = f'动态码(\d+),收款人' ret = re.findall(pattern, msg) if len(ret) != 1: logger.error(f'未能在短信{msg}中匹配到 {pattern}') time.sleep(0.5) continue logger.info('双击验证码编辑框') self.__click([107, 837, 658, 1002], True) logger.info(f'输入验证码{ret[0]}') for c in ret[0]: x = int(self.login_key_board_digital[c][0] * self.driver.width()) y = int(self.login_key_board_digital[c][1] * self.driver.height()) self.driver.click(x, y) start_time = msg_start_time = time.time() break else: raise MyError('120秒内未能收到短信验证码') elif '转账' in xml and '完成' in xml: logger.info('进入转账查询结果界面') if '转账提交成功' in xml: ''' logger.info(f'转账成功,等待支付结果短信') temp_start = time.time() while time.time() - temp_start < 40: msg_list = MsgManger.getMsg('106927995511', int(msg_start_time)) if len(msg_list) == 0: time.sleep(0.3) continue ret = msg_list[0] logger.info(ret) return True, ret ''' return True, '' elif re.search( r'content-desc="转账失败"[\s\S]+?<node index="2".+?content-desc="(.+?)"', xml): ret = re.findall( r'content-desc="转账失败"[\s\S]+?<node index="2".+?content-desc="(.+?)"', xml)[0] logger.info(ret) raise UserError(ret) else: logger.warning('未知 activity %s' % cur_activity) raise MyError('支付超时')
def __enter_transfer(self, name, card, money, only4remainds=False): start_time = time.time() self._remainds = '' while time.time() - start_time < 70: cur_activity = self.driver.get_cur_activity() xml = self.driver.get_xml() logger.info(f'---{cur_activity}') if self.__handle_random_page(cur_activity, xml): start_time = time.time() continue elif '取款密码' in xml: logger.info('进入支付页面') return elif re.search(self.__pattern_sure, xml): logger.info('点击确定') self.__click(re.findall(self.__pattern_sure, xml)[0]) start_time = time.time() elif re.search(self.__pattern_continue, xml): logger.info('点击继续转账') ret = re.findall(self.__pattern_continue, xml)[0] self.__click(ret) start_time = time.time() elif '可用余额' in xml: logger.info('进入正式转账页面') ret_remainds = re.findall(self.__pattern_remainds, xml) if len(ret_remainds) != 1: logger.error(f'未找到余额') continue if only4remainds: logger.info(f'余额:{ret_remainds[0]}') return re.sub(',', '', ret_remainds[0]) ret_reciver = re.findall(self.__pattern_reciver, xml) if len(ret_reciver) != 1: logger.error('未找到收款人控件') continue ret_card = re.findall(self.__pattern_card, xml) if len(ret_card) != 1: logger.error('未找到卡号控件') continue ret_next = re.findall(self.__pattern_next, xml) if len(ret_next) != 1: logger.error('未找到下一步控件') continue self._remainds = re.sub(',', '', ret_remainds[0]) logger.info(f'余额:{self._remainds}') if float(self._remainds) < float(money): raise NomoneyError(f'余额不足{money}元,当前余额{self._remainds}元') logger.info('输入卡号 %s' % card) self.__click(ret_card[0]) self.driver.input_text(card) xml = self.driver.get_xml() if '请选择' in xml: raise UserError(f'卡号不存在') logger.info('输入收款人 %s' % name) ret_reciver = re.findall(self.__pattern_reciver, xml) self.__click(ret_reciver[0]) self.driver.input_text(name) xml = self.driver.get_xml() ret_money = re.findall(self.__pattern_money, xml) if len(ret_money) != 1: logger.error('未找到转账金额控件') raise MyError('未找到转账金额控件') logger.info('输入金额 %s' % money) self.__click(ret_money[0]) time.sleep(1) for c in money: x = int(self.login_key_board_digital[c][0] * self.driver.width()) y = int(self.login_key_board_digital[c][1] * self.driver.height()) self.driver.click(x, y) self.driver.click(self.finish[0] * self.driver.width(), self.finish[1] * self.driver.height()) time.sleep(2) xml = self.driver.get_xml() if re.search(self.__pattern_cancel_contact, xml): logger.info(f'点击取消联系人按钮') self.__click( re.findall(self.__pattern_cancel_contact, xml)[0]) time.sleep(0.5) self.driver.swip(0.5, 0.7, 0.5, 0.3) ret_next = re.findall(self.__pattern_next, self.driver.get_xml()) if len(ret_next) != 1: logger.error('未找到下一步控件') raise MyError('未找到下一步控件') logger.info('点击下一步') self.__click(ret_next[0]) start_time = time.time() elif cur_activity == 'com.pingan.core.base.PocketWebViewActivity': ret = re.findall(self.__pattern_tansfer, xml) if len(ret) == 1: logger.info('点击待转账页面的转账按钮') self.__click(ret[0]) else: logger.warning(f'未知 activity {cur_activity}') raise MyError('从待转账页面进入转账页面超时')