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