def web_automation(driver, merchant, amount): driver.get('http://payments.xfinity.com/') logged_in = utils.is_logged_in(driver, timeout=90, logged_out_element=(By.ID, 'user'), logged_in_element=(By.ID, 'customAmount')) if not logged_in: driver.find_element_by_id('user').send_keys(merchant.usr) driver.find_element_by_id('passwd').send_keys(merchant.psw) driver.find_element_by_id('sign_in').click() try: # first time run captcha WebDriverWait(driver, 5).until( expected_conditions.element_to_be_clickable( (By.ID, 'nucaptcha-answer'))) LOGGER.info('captcha detected') input(''' Detected first time run captcha. Please follow these one-time steps. Future runs won't need this. 1. Open the Firefox window that debbit created. 2. Enter your user, pass, and the moving characters manually. 3. Click the "Sign In" button. 4. Click on this terminal window and hit "Enter" to continue running debbit. ''') except TimeoutException: pass WebDriverWait(driver, 90).until( expected_conditions.element_to_be_clickable( (By.ID, 'customAmount'))) if driver.find_elements_by_id('no'): # survey pop-up driver.find_element_by_id('no').click() cur_balance = driver.find_element_by_xpath( "//span[contains(text(), '$')]").text if utils.str_to_cents(cur_balance) == 0: LOGGER.error('xfinity balance is zero, will try again later.') return Result.skipped elif utils.str_to_cents(cur_balance) < amount: amount = utils.str_to_cents(cur_balance) driver.find_element_by_id('customAmount').send_keys( utils.cents_to_str(amount)) driver.find_element_by_xpath("//span[contains(text(),'nding in " + merchant.card[-4:] + "')]").click() driver.find_element_by_xpath("//span[contains(text(),'nding in " + merchant.card[-4:] + "')]").click() driver.find_element_by_xpath( "//button[contains(text(),'Continue')]").click() driver.find_element_by_xpath( "//button[contains(text(),'Submit Payment')]").click() try: WebDriverWait(driver, 90).until( expected_conditions.presence_of_element_located( (By.XPATH, "//*[contains(text(),'Your payment was successful')]"))) except TimeoutException: return Result.unverified return Result.success
def web_automation(driver, merchant, amount): driver.get( 'https://jakehilborn.github.io/debbit/example-merchant/login.html') logged_in = utils.is_logged_in(driver, timeout=90, logged_out_element=(By.ID, 'password'), logged_in_element=(By.ID, 'submit-payment')) if not logged_in: time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants try: # some websites will have the username auto-filled in due to a previous login driver.find_element_by_id('username').send_keys(merchant.usr) except ElementNotInteractableException: pass time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants driver.find_element_by_id('password').send_keys(merchant.usr) time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants driver.find_element_by_id('login').click() WebDriverWait(driver, 30).until( expected_conditions.element_to_be_clickable( (By.ID, 'submit-payment'))) cur_balance = driver.find_element_by_xpath( "//span[contains(text(), '$')]").text if utils.str_to_cents(cur_balance) == 0: LOGGER.error('example_merchant balance is zero, will try again later.') return Result.skipped elif utils.str_to_cents(cur_balance) < amount: amount = utils.str_to_cents(cur_balance) time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants driver.find_element_by_xpath("//*[contains(text(), 'card ending in " + merchant.card + "')]").click() time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants driver.find_element_by_id('amount').send_keys(utils.cents_to_str(amount)) time.sleep( 2 ) # pause to let user watch what's happening - not necessary for real merchants driver.find_element_by_id('submit-payment').click() try: WebDriverWait(driver, 30).until( expected_conditions.presence_of_element_located( (By.XPATH, "//*[contains(text(),'Thank you!')]"))) except TimeoutException: return Result.unverified # Purchase command was executed, yet we are unable to verify that it was successfully executed. # since debbit may have spent money but isn't sure, we log the error and stop any further payments for this merchant until the user intervenes time.sleep( 5) # sleep for a bit to show user that payment screen is reached return Result.success
def web_automation(driver, merchant, amount): driver.get('https://www.optimum.net/pay-bill/payment-options/') WebDriverWait(driver, 90).until( expected_conditions.element_to_be_clickable( (By.ID, 'loginPageUsername'))) driver.find_element_by_id('loginPageUsername').send_keys(merchant.usr) driver.find_element_by_id('loginPagePassword').send_keys(merchant.psw) driver.find_element_by_xpath( "//button[contains(text(),'Sign in to Optimum.net')]").click() WebDriverWait(driver, 90).until( expected_conditions.element_to_be_clickable( (By.ID, 'otherAmountInput'))) cur_balance = driver.find_element_by_xpath( "//span[@class='payment--radio--bold ng-binding']").text LOGGER.info('Current Optimum balance is ' + cur_balance) if str_to_cents(cur_balance) < 100: LOGGER.error( 'Optimum account balance is less than minimum $1 payment, will try again later.' ) return Result.skipped elif str_to_cents(cur_balance) < amount: LOGGER.info('Adjusting spend to ' + str_to_cents(cur_balance) + ' cents since current balance is less than ' + amount + ' cents') amount = str_to_cents(cur_balance) driver.find_element_by_id('otherAmountInput').send_keys( cents_to_str(amount)) # Enter the amount driver.find_element_by_xpath( "//span[contains(text(),'Other amount')]/preceding-sibling::div" ).click() # Select the radio button driver.find_element_by_xpath( "//div[contains(text(),'Payment Method')]/following-sibling::div" ).click() # Open the selector dropdown box try: driver.find_element_by_xpath( "//span[contains(text(),'" + merchant.card + "')]").click() # Select the payment method except common.exceptions.NoSuchElementException: LOGGER.error('Failed to find payment method with name ' + merchant.card) return Result.failed button_str = driver.find_element_by_id('otpSubmit').get_attribute('value') expect_str = "Pay $" + cents_to_str(amount) + " now with " + merchant.card if button_str == expect_str: driver.find_element_by_id('otpSubmit').click() LOGGER.info('Submitting purchase: ' + button_str) else: LOGGER.error('Failed to find valid pay button.') LOGGER.info('Detected: ' + button_str) LOGGER.info('Expected: ' + expect_str) return Result.failed # Check if the payment succeeded. try: WebDriverWait(driver, 90).until( expected_conditions.presence_of_element_located( (By.XPATH, "//*[contains(text(),'Confirmation Number:')]"))) LOGGER.info("Successful payment: " + driver.find_element_by_xpath( "//*[contains(text(),'Confirmation Number:')]").text) return Result.success except TimeoutException: # Check if there was an error, if so log the error. try: WebDriverWait(driver, 5).until( expected_conditions.presence_of_element_located( (By.XPATH, "//*[contains(text(),'unable')]"))) LOGGER.error("Failed payment: " + driver.find_element_by_xpath( "//*[contains(text(),'unable')]").text) except TimeoutException: return Result.unverified return Result.unverified
def web_automation(driver, merchant, amount): driver.get('https://www.att.com/my/#/passthrough/overview') # Wait until login screen, promotion pop-up, or account dashboard shows. WebDriverWait(driver, 120).until( utils.AnyExpectedCondition( expected_conditions.element_to_be_clickable( (By.NAME, "password")), # logged out expected_conditions.element_to_be_clickable( (By.XPATH, "//*[contains(@id,'ancel')]" )), # mfa flow identified by cancel button expected_conditions.element_to_be_clickable( (By.XPATH, "//img[contains(@src,'btnNoThanks')]")), # logged in expected_conditions.element_to_be_clickable( (By.XPATH, "//button[contains(text(),'Make a payment')]")) # logged in )) handle_mfa_code_flow(driver) time.sleep( 1 + random.random() * 2 ) # AT&T is using bot detection software, slow down the automation a bit to help avoid detection if driver.find_elements_by_name( 'password'): # password field found, need to log in try: driver.find_element_by_id('userID').send_keys(merchant.usr) time.sleep(1 + random.random() * 2) except common.exceptions.NoSuchElementException: pass driver.find_element_by_name('password').send_keys(merchant.psw) time.sleep(1 + random.random() * 2) driver.find_element_by_xpath( "//button[contains(text(),'Sign in')]").click() try: # Wait for potential promotions screen, regular account overview, or OTP flow WebDriverWait(driver, 120).until( utils.AnyExpectedCondition( expected_conditions.element_to_be_clickable( (By.XPATH, "//img[contains(@src,'btnNoThanks')]")), expected_conditions.element_to_be_clickable( (By.XPATH, "//button[contains(text(),'Make a payment')]")), expected_conditions.element_to_be_clickable( (By.XPATH, "//*[contains(@id,'ancel')]" )) # mfa flow identified by cancel button )) except TimeoutException: pass # Try continuing to the makePayment page just in case log in worked, but timeout failed time.sleep(1 + random.random() * 2) handle_mfa_code_flow(driver) driver.get("https://www.att.com/my/#/makePayment") WebDriverWait(driver, 20).until( expected_conditions.element_to_be_clickable( (By.ID, "MAP_Amount_TextField"))) time.sleep(1 + random.random() * 2) cur_balance_html_text = driver.find_element_by_xpath( "//span[contains(text(), 'Balance due')]").text cur_balance = cur_balance_html_text.split('$')[1] if utils.str_to_cents(cur_balance) == 0: LOGGER.warning('AT&T balance is zero, will try again later.') return Result.skipped elif utils.str_to_cents(cur_balance) < amount: amount = utils.str_to_cents(cur_balance) elem = driver.find_element_by_id('MAP_Amount_TextField') elem.clear() time.sleep(1 + random.random() * 2) elem.send_keys(utils.cents_to_str(amount)) time.sleep(1 + random.random() * 2) if driver.find_elements_by_xpath( "//*[contains(text(),'Debit or credit card')]"): driver.find_element_by_xpath( "//*[contains(text(),'Debit or credit card')]").click() time.sleep(1 + random.random() * 2) driver.find_element_by_xpath("//input[@value='" + merchant.card + "']").click() time.sleep(1 + random.random() * 2) driver.find_element_by_xpath("//*[contains(text(),'Pay $" + utils.cents_to_str(amount) + "')]").click() time.sleep(1 + random.random() * 2) try: WebDriverWait(driver, 120).until( utils.AnyExpectedCondition( expected_conditions.presence_of_element_located( (By.XPATH, "//*[contains(text(),'We got your $" + utils.cents_to_str(amount) + " payment')]")), expected_conditions.presence_of_element_located(( By.XPATH, "//*[contains(text(),'multiple payments for the same amount')]" )))) if driver.find_elements_by_xpath( "//*[contains(text(),'multiple payments for the same amount')]" ): LOGGER.info( "Duplicate payment amount not accepted within 24 hours. Trying again later. Please use a larger range between amount_min and amount_max in config.txt for att_bill_pay to avoid duplicate payment amount scenarios." ) return Result.skipped elif driver.find_elements_by_xpath("//*[text()='We got your $ + " + utils.cents_to_str(amount) + " payment']"): return Result.success else: return Result.unverified except (KeyboardInterrupt, SystemExit): raise except Exception: return Result.unverified # Purchase command was executed, yet we are unable to verify that it was successfully executed. # since debbit may have spent money but isn't sure, we log the error and stop any further payments for this merchant until the user intervenes return Result.success