예제 #1
0
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
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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