From 2738538fb6aa8c366c718845b15c7272b6aa2123 Mon Sep 17 00:00:00 2001 From: Florent Date: Fri, 28 Mar 2014 14:15:45 +0100 Subject: [PATCH] Support transfer with browser2 --- modules/ing/backend.py | 28 ++++--- modules/ing/browser.py | 15 ++-- modules/ing/pages/transfer.py | 139 +++++++++++++++------------------- 3 files changed, 81 insertions(+), 101 deletions(-) diff --git a/modules/ing/backend.py b/modules/ing/backend.py index 8e7d6a23..48cb1bcc 100644 --- a/modules/ing/backend.py +++ b/modules/ing/backend.py @@ -80,23 +80,21 @@ class INGBackend(BaseBackend, ICapBank, ICapBill): yield history def iter_transfer_recipients(self, account): - with self.browser: - if not isinstance(account, Account): - account = self.get_account(account) - for recipient in self.browser.get_recipients(account): - yield recipient + if not isinstance(account, Account): + account = self.get_account(account) + for recipient in self.browser.get_recipients(account): + yield recipient def transfer(self, account, recipient, amount, reason): - with self.browser: - if not reason: - raise UserError('Reason is mandatory to do a transfer on ING website') - if not isinstance(account, Account): - account = self.get_account(account) - if not isinstance(recipient, Recipient): - # Remove weboob identifier prefix (LA-, CC-...) - if "-" in recipient: - recipient = recipient.split('-')[1] - return self.browser.transfer(account, recipient, amount, reason) + if not reason: + raise UserError('Reason is mandatory to do a transfer on ING website') + if not isinstance(account, Account): + account = self.get_account(account) + if not isinstance(recipient, Recipient): + # Remove weboob identifier prefix (LA-, CC-...) + if "-" in recipient: + recipient = recipient.split('-')[1] + return self.browser.transfer(account, recipient, amount, reason) def iter_investment(self, account): if not isinstance(account, Account): diff --git a/modules/ing/browser.py b/modules/ing/browser.py index 80f1b17c..7e4fb07f 100644 --- a/modules/ing/browser.py +++ b/modules/ing/browser.py @@ -145,16 +145,16 @@ class IngBrowser(LoginBrowser): } self.accountspage.go(data=data) + @need_login def get_recipients(self, account): - if not self.is_on_page(TransferPage): - self.location(self.transferpage) + self.transferpage.stay_or_go() if self.page.ischecked(account): return self.page.get_recipients() else: # It is hard to check the box and to get the real list. # We try an alternative way like normal users self.get_history(account.id).next() - self.location(self.dotransferpage) + self.transferpage.stay_or_go() return self.page.get_recipients() def transfer(self, account, recipient, amount, reason): @@ -168,15 +168,14 @@ class IngBrowser(LoginBrowser): recipient = destination break if found: - self.openurl(self.transferpage, - self.page.buildonclick(recipient, account)) + self.transferpage.open(data=self.page.buildonclick(recipient, account)) self.page.transfer(recipient, amount, reason) - self.location(self.valtransferpage) - if not self.is_on_page(TransferConfirmPage): + self.valtransferpage.go() + if not self.valtransferpage.is_here(): raise TransferError("Invalid transfer (no confirmation page)") else: self.page.confirm(self.password) - self.location(self.valtransferpage) + self.valtransferpage.go() return self.page.recap() else: raise TransferError('Recipient not found') diff --git a/modules/ing/pages/transfer.py b/modules/ing/pages/transfer.py index 20f672a1..e8420e5c 100644 --- a/modules/ing/pages/transfer.py +++ b/modules/ing/pages/transfer.py @@ -22,21 +22,18 @@ from decimal import Decimal from weboob.tools.capabilities.bank.transactions import FrenchTransaction from weboob.tools.captcha.virtkeyboard import VirtKeyboardError from weboob.capabilities.bank import Recipient, AccountNotFound, Transfer -from weboob.tools.browser import BasePage, BrokenPageError -from weboob.tools.mech import ClientForm +from weboob.tools.browser2.page import HTMLPage, LoggedPage +from weboob.tools.browser import BrokenPageError from .login import INGVirtKeyboard from logging import error __all__ = ['TransferPage'] -class TransferPage(BasePage): - def on_loaded(self): - pass - +class TransferPage(LoggedPage, HTMLPage): def get_recipients(self): # First, internals recipients - table = self.document.xpath('//table[@id="transfer_form:receiptAccount"]') + table = self.doc.xpath('//table[@id="transfer_form:receiptAccount"]') for tr in table[0].xpath('tbody/tr'): tds = tr.xpath('td') id = tds[0].xpath('input')[0].attrib['value'] @@ -50,7 +47,7 @@ class TransferPage(BasePage): yield recipient # Second, externals recipients - select = self.document.xpath('//select[@id="transfer_form:externalAccounts"]') + select = self.doc.xpath('//select[@id="transfer_form:externalAccounts"]') if len(select) > 0: recipients = select[0].xpath('option') recipients.pop(0) @@ -66,66 +63,55 @@ class TransferPage(BasePage): # remove prefix (CC-, LA-, ...) if "-" in id: id = id.split('-')[1] - option = self.document.xpath('//input[@value="%s"]' % id) + option = self.doc.xpath('//input[@value="%s"]' % id) if len(option) == 0: raise AccountNotFound() else: option = option[0] try: - if option.attrib["checked"] == "checked": - return True - else: - return False + return option.attrib["checked"] == "checked" except: return False def transfer(self, recipient, amount, reason): - self.browser.select_form("transfer_form") - self.browser.set_all_readonly(False) - for a in self.browser.controls[:]: - #for label in a.get_labels(): - if "transfer_form:_link_hidden_" in str(a) or "transfer_form:j_idcl" in str(a): - self.browser.controls.remove(a) - if "transfer_form:valide" in str(a): - self.browser.controls.remove(a) - self.browser.controls.append(ClientForm.TextControl('text', - 'AJAXREQUEST', {'value': "_viewRoot"})) - self.browser.controls.append(ClientForm.TextControl('text', - 'AJAX:EVENTS_COUNT', {'value': "1"})) - self.browser['transfer_form:transferMotive'] = reason.encode('ISO-8859-1') - self.browser.controls.append(ClientForm.TextControl('text', 'transfer_form:valide', {'value': "transfer_form:valide"})) - self.browser['transfer_form:validateDoTransfer'] = "needed" - self.browser['transfer_form:transferAmount'] = str(amount) + form = self.get_form(name="transfer_form") + form.pop('transfer_form:_link_hidden_') + form.pop('transfer_form:j_idcl') + form['AJAXREQUEST'] = "_viewRoot" + form['AJAX:EVENTS_COUNT'] = "1" + form['transfer_form:transferMotive'] = reason + form["transfer_form:valide"] = "transfer_form:valide" + form["transfer_form:validateDoTransfer"] = "needed" + form["transfer_form:transferAmount"] = str(amount) if recipient._type == "int": - self.browser['transfer_recipient_radio'] = [recipient.id] + form['transfer_recipient_radio'] = recipient.id else: - self.browser['transfer_form:externalAccounts'] = [recipient.id] - self.browser.submit() + form['transfer_form:externalAccounts'] = recipient.id + form.submit() def buildonclick(self, recipient, account): - javax = self.document.xpath('//input[@id="javax.faces.ViewState"]')[0].attrib['value'] + javax = self.doc.xpath('//input[@id="javax.faces.ViewState"]')[0].attrib['value'] if recipient._type == "ext": - select = self.document.xpath('//select[@id="transfer_form:externalAccounts"]')[0] + select = self.doc.xpath('//select[@id="transfer_form:externalAccounts"]')[0] onclick = select.attrib['onchange'] params = onclick.split(',')[3].split('{')[1] idparam = params.split("'")[1] param = params.split("'")[3] - request = self.browser.buildurl('', ("AJAXREQUEST", "transfer_form:transfer_radios_form"), - ("transfer_form:generalMessages", ""), - ("transfer_issuer_radio", account.id[3:]), - ("transfer_form:externalAccounts", recipient.id), - ("transfer_date", 0), - ("transfer_form:transferAmount", ""), - ("transfer_form:transferMotive", ""), - ("transfer_form:validateDoTransfer", "needed"), - ("transfer_form", "transfer_form"), - ("autoScrol", ""), - ("javax.faces.ViewState", javax), - (idparam, param)) - request = request[1:] # remove the "?" + request = {"AJAXREQUEST": "transfer_form:transfer_radios_form", + "transfer_form:generalMessages": "", + "transfer_issuer_radio": account.id[3:], + "transfer_form:externalAccounts": recipient.id, + "transfer_date": "0", + "transfer_form:transferAmount": "", + "transfer_form:transferMotive": "", + "transfer_form:validateDoTransfer": "needed", + "transfer_form": "transfer_form", + "autoScrol": "", + "javax.faces.ViewState": javax, + idparam: param} return request elif recipient._type == "int": - for input in self.document.xpath('//input[@value=%s]' % recipient.id): + for input in self.doc.xpath('//input[@value=%s]' % recipient.id): if input.attrib['name'] == "transfer_recipient_radio": onclick = input.attrib['onclick'] break @@ -133,23 +119,22 @@ class TransferPage(BasePage): params = onclick.split(',')[3].split('{')[1] idparam = params.split("'")[1] param = params.split("'")[3] - request = self.browser.buildurl('', ("AJAXREQUEST", "transfer_form:transfer_radios_form"), - ('transfer_issuer_radio', account.id[3:]), - ("transfer_recipient_radio", recipient.id), - ("transfer_form:externalAccounts", "na"), - ("transfer_date", 0), - ("transfer_form:transferAmount", ""), - ("transfer_form:transferMotive", ""), - ("transfer_form:validateDoTransfer", "needed"), - ("transfer_form", "transfer_form"), - ("autoScroll", ""), - ("javax.faces.ViewState", javax), - (idparam, param)) - request = request[1:] + request = {"AJAXREQUEST": "transfer_form:transfer_radios_form", + 'transfer_issuer_radio': account.id[3:], + "transfer_recipient_radio": recipient.id, + "transfer_form:externalAccounts": "na", + "transfer_date": 0, + "transfer_form:transferAmount": "", + "transfer_form:transferMotive": "", + "transfer_form:validateDoTransfer": "needed", + "transfer_form": "transfer_form", + "autoScroll": "", + "javax.faces.ViewState": javax, + idparam: param} return request -class TransferConfirmPage(BasePage): +class TransferConfirmPage(HTMLPage): def on_loaded(self): pass @@ -160,14 +145,14 @@ class TransferConfirmPage(BasePage): error("Error: %s" % err) return realpasswd = "" - span = self.document.find('//span[@id="digitpadtransfer"]') + span = self.doc.find('//span[@id="digitpadtransfer"]') i = 0 for font in span.getiterator('font'): if font.attrib.get('class') == "vide": realpasswd += password[i] i += 1 confirmform = None - divform = self.document.xpath('//div[@id="transfer_panel"]')[0] + divform = self.doc.xpath('//div[@id="transfer_panel"]')[0] for form in divform.xpath('./form'): try: if form.attrib['name'][0:4] == "j_id": @@ -179,26 +164,24 @@ class TransferConfirmPage(BasePage): raise BrokenPageError('Unable to find confirm form') formname = confirmform.attrib['name'] self.browser.logger.debug('We are looking for : ' + realpasswd) - self.browser.select_form(formname) - self.browser.set_all_readonly(False) - for a in self.browser.controls[:]: - if "_link_hidden_" in str(a) or "j_idcl" in str(a): - self.browser.controls.remove(a) + + form = self.get_form(name=formname) + for elem in form: + if "_link_hidden_" in elem or "j_idcl" in elem: + form.pop(elem) + coordinates = vk.get_string_code(realpasswd) self.browser.logger.debug("Coordonates: " + coordinates) - self.browser.controls.append(ClientForm.TextControl('text', - 'AJAXREQUEST', {'value': '_viewRoot'})) - self.browser.controls.append(ClientForm.TextControl( - 'text', '%s:mrgtransfer' % formname, - {'value': '%s:mrgtransfer' % formname})) - self.browser['%s:mrltransfer' % formname] = coordinates - self.browser.submit(nologin=True) + form['AJAXREQUEST'] = '_viewRoot' + form['%s:mrgtransfer' % formname] = '%s:mrgtransfer' % formname + form['%s:mrltransfer' % formname] = coordinates + form.submit() def recap(self): - if len(self.document.xpath('//p[@class="alert alert-success"]')) == 0: + if len(self.doc.xpath('//p[@class="alert alert-success"]')) == 0: raise BrokenPageError('Unable to find confirmation') - div = self.document.find( + div = self.doc.find( '//div[@class="encadre transfert-validation"]') transfer = Transfer(0) transfer.amount = Decimal(FrenchTransaction.clean_amount(