First step on ING with Browser2

Login and listing of accounts work
This commit is contained in:
Florent 2014-03-27 23:48:16 +01:00
commit 15ca64f3d9
4 changed files with 105 additions and 111 deletions

View file

@ -26,7 +26,7 @@ from weboob.capabilities.base import UserError
from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import ValueBackendPassword
from .browser import Ing
from .browser import IngBrowser
__all__ = ['INGBackend']
@ -49,7 +49,7 @@ class INGBackend(BaseBackend, ICapBank, ICapBill):
regexp='^(\d{8}|)$',
masked=False)
)
BROWSER = Ing
BROWSER = IngBrowser
def create_default_browser(self):
return self.create_browser(self.config['login'].get(),

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2009-2011 Romain Bignon, Florent Fourcot
# Copyright(C) 2009-2014 Florent Fourcot
#
# This file is part of weboob.
#
@ -19,74 +19,67 @@
import urllib
import hashlib
from weboob.tools.browser import BaseBrowser, BrowserIncorrectPassword
from weboob.tools.browser2 import LoginBrowser, URL, need_login
from weboob.tools.browser import BrowserIncorrectPassword
from weboob.capabilities.bank import Account, TransferError
from .pages import AccountsList, LoginPage, \
TransferPage, TransferConfirmPage, \
BillsPage, StopPage, TitrePage, \
TitreHistory
__all__ = ['Ing']
__all__ = ['IngBrowser']
class Ing(BaseBrowser):
DOMAIN = 'secure.ingdirect.fr'
PROTOCOL = 'https'
DEBUG_HTTP = False
#DEBUG_HTTP = True
ENCODING = None
PAGES = {'.*pages/index.jsf.*': AccountsList,
'.*displayLogin.jsf.*': LoginPage,
'.*transferManagement.jsf': TransferPage,
'.*onHoldTransferManagement.jsf': TransferPage,
'.*DisplayDoTransferCommand.*': TransferPage,
'.*transferCreateValidation.jsf': TransferConfirmPage,
'.*eStatement.jsf': BillsPage,
'.*displayCoordonneesCommand.*': StopPage,
'.*portefeuille-TR.*': (TitrePage, 'raw'),
'.*compteTempsReelCK.php.*': (TitrePage, 'raw'),
'.*compte.php\?ong=3': TitreHistory,
}
CERTHASH = "257100e5f69b3c24b27eaaa82951ca5539e9ca264dee433b7c8d4779e778a0b4"
class IngBrowser(LoginBrowser):
BASEURL = 'https://secure.ingdirect.fr'
# '.*onHoldTransferManagement.jsf': TransferPage,
# '.*displayCoordonneesCommand.*': StopPage,
# '.*compteTempsReelCK.php.*': (TitrePage, 'raw'),
# '.*compte.php\?ong=3': TitreHistory,
# Login and error
loginpage = URL('/public/displayLogin.jsf.*', LoginPage)
errorpage = URL('.*displayCoordonneesCommand.*', StopPage)
# CapBank
accountspage = URL('/protected/pages/index.jsf', AccountsList)
transferpage = URL('/protected/pages/cc/transfer/transferManagement.jsf', TransferPage)
dotransferpage = URL('/general?command=DisplayDoTransferCommand', TransferPage)
valtransferpage = URL('/protected/pages/cc/transfer/create/transferCreateValidation.jsf', TransferConfirmPage)
#transferonhold = URL('
titrepage = URL('https://bourse.ingdirect.fr/priv/portefeuille-TR.php', TitrePage)
titrehistory = URL('https://bourse.ingdirect.fr/priv/compte.php?ong=3', TitreHistory)
# CapBill
billpage = URL('/protected/pages/common/estatement/eStatement.jsf', BillsPage)
loginpage = '/public/displayLogin.jsf'
accountspage = '/protected/pages/index.jsf'
transferpage = '/protected/pages/cc/transfer/transferManagement.jsf'
dotransferpage = '/general?command=DisplayDoTransferCommand'
valtransferpage = '/protected/pages/cc/transfer/create/transferCreateValidation.jsf'
billpage = '/protected/pages/common/estatement/eStatement.jsf'
titrepage = 'https://bourse.ingdirect.fr/priv/portefeuille-TR.php'
where = None
def __init__(self, *args, **kwargs):
self.birthday = kwargs.pop('birthday', None)
BaseBrowser.__init__(self, *args, **kwargs)
LoginBrowser.__init__(self, *args, **kwargs)
def home(self):
self.location(self.loginpage)
def is_logged(self):
return not self.is_on_page(LoginPage)
def login(self):
def do_login(self):
assert isinstance(self.username, basestring)
assert isinstance(self.password, basestring)
assert isinstance(self.birthday, basestring)
assert self.password.isdigit()
assert self.birthday.isdigit()
if not self.is_on_page(LoginPage):
self.location(self.loginpage)
self.loginpage.stay_or_go()
self.page.prelogin(self.username, self.birthday)
self.page.login(self.password)
if self.page.error():
raise BrowserIncorrectPassword()
@need_login
def get_accounts_list(self):
if not self.is_on_page(AccountsList) or self.where != "start":
self.location(self.accountspage)
self.accountspage.go()
self.where = "start"
return self.page.get_list()

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2009-2011 Romain Bignon, Florent Fourcot
# Copyright(C) 2009-2014 Florent Fourcot, Romain Bignon
#
# This file is part of weboob.
#
@ -25,7 +25,8 @@ import hashlib
from weboob.capabilities.bank import Account
from weboob.capabilities.base import NotAvailable
from weboob.tools.browser import BasePage
from weboob.tools.browser2.page import HTMLPage, method, ListElement, ItemElement
from weboob.tools.browser2.filters import Attr, CleanText, CleanDecimal, Filter, Field, MultiFilter
from weboob.tools.capabilities.bank.transactions import FrenchTransaction
@ -42,9 +43,31 @@ class Transaction(FrenchTransaction):
]
class AccountsList(BasePage):
def on_loaded(self):
pass
class AddPref(MultiFilter):
prefixes = {u'Courant': u'CC-', u'Livret A': 'LA-', u'Orange': 'LEO-',
u'Durable': u'LDD-', u"Titres": 'TITRE-', u'PEA': u'PEA-'}
def filter(self, values):
el, label = values
for key, pref in self.prefixes.items():
if key in label:
return pref + el
return el
class AddType(Filter):
types = {u'Courant': Account.TYPE_CHECKING, u'Livret A': Account.TYPE_SAVINGS,
u'Orange': Account.TYPE_SAVINGS, u'Durable': Account.TYPE_SAVINGS,
u'Titres': Account.TYPE_MARKET, u'PEA': Account.TYPE_MARKET}
def filter(self, label):
for key, acc_type in self.types.items():
if key in label:
return acc_type
return Account.TYPE_UNKNOWN
class AccountsList(HTMLPage):
monthvalue = {u'janv.': '01', u'févr.': '02', u'mars': '03', u'avr.': '04',
u'mai': '05', u'juin': '06', u'juil.': '07', u'août': '08',
@ -55,38 +78,22 @@ class AccountsList(BasePage):
u'cb_ach': u'Carte achat', u'chq': u'Chèque',
u'frais': u'Frais bancaire', u'sepaplvt': u'Prélèvement'}
def get_list(self):
# TODO: no idea abount how proxy account are displayed
for a in self.document.xpath('//a[@class="mainclic"]'):
account = Account()
account.currency = u'EUR'
account.id = unicode(a.find('span[@class="account-number"]').text)
account._id = account.id
account.label = unicode(a.find('span[@class="title"]').text)
balance = a.find('span[@class="solde"]/label').text
account.balance = Decimal(FrenchTransaction.clean_amount(balance))
account.coming = NotAvailable
if "Courant" in account.label:
account.id = "CC-" + account.id
account.type = Account.TYPE_CHECKING
elif "Livret A" in account.label:
account.id = "LA-" + account.id
account.type = Account.TYPE_SAVINGS
elif "Orange" in account.label:
account.id = "LEO-" + account.id
account.type = Account.TYPE_SAVINGS
elif "Durable" in account.label:
account.id = "LDD-" + account.id
account.type = Account.TYPE_SAVINGS
elif "Titres" in account.label:
account.id = "TITRE-" + account.id
account.type = Account.TYPE_MARKET
elif "PEA" in account.label:
account.id = "PEA-" + account.id
account.type = Account.TYPE_MARKET
jid = self.document.find('//input[@name="javax.faces.ViewState"]')
account._jid = jid.attrib['value']
yield account
@method
class get_list(ListElement):
item_xpath = '//a[@class="mainclic"]'
class item(ItemElement):
klass = Account
obj_currency = u'EUR'
obj__id = CleanText('span[@class="account-number"]')
obj_label = CleanText('span[@class="title"]')
obj_id = AddPref(Field('_id'), Field('label'))
obj_type = AddType(Field('label'))
obj_balance = CleanDecimal('span[@class="solde"]/label')
obj_coming = NotAvailable
obj__jid = Attr('//input[@name="javax.faces.ViewState"]', 'value')
def get_transactions(self, index):
i = 0

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright(C) 2009-2011 Romain Bignon, Florent Fourcot
# Copyright(C) 2009-2014 Florent Fourcot, Romain Bignon
#
# This file is part of weboob.
#
@ -17,13 +17,13 @@
# You should have received a copy of the GNU Affero General Public License
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
from StringIO import StringIO
from weboob.tools.mech import ClientForm
from logging import error
from weboob.tools.browser import BasePage, BrowserIncorrectPassword
from weboob.tools.captcha.virtkeyboard import VirtKeyboard, VirtKeyboardError
from weboob.tools.browser2.page import HTMLPage
__all__ = ['LoginPage', 'INGVirtKeyboard', 'StopPage']
@ -43,9 +43,9 @@ class INGVirtKeyboard(VirtKeyboard):
color = 64
def __init__(self, basepage):
divkeyboard = basepage.document.find("//div[@id='clavierdisplayLogin']")
divkeyboard = basepage.doc.find("//div[@id='clavierdisplayLogin']")
if divkeyboard is None:
divkeyboard = basepage.document.find("//div[@id='claviertransfer']")
divkeyboard = basepage.doc.find("//div[@id='claviertransfer']")
try:
img = divkeyboard.xpath("img")[1]
except:
@ -63,7 +63,7 @@ class INGVirtKeyboard(VirtKeyboard):
coords["42"] = (125, 45, 153, 73)
coords["52"] = (165, 45, 193, 73)
VirtKeyboard.__init__(self, basepage.browser.openurl(url), coords, self.color)
VirtKeyboard.__init__(self, StringIO(basepage.browser.open(url).content), coords, self.color)
self.check_symbols(self.symbols, basepage.browser.responses_dirname)
@ -84,23 +84,19 @@ class INGVirtKeyboard(VirtKeyboard):
return code
class LoginPage(BasePage):
def on_loaded(self):
pass
class LoginPage(HTMLPage):
def prelogin(self, login, birthday):
# First step : login and birthday
self.browser.select_form('zone1Form')
self.browser.set_all_readonly(False)
self.browser['zone1Form:numClient'] = str(login)
self.browser['zone1Form:dateDay'] = str(birthday[0:2])
self.browser['zone1Form:dateMonth'] = str(birthday[2:4])
self.browser['zone1Form:dateYear'] = str(birthday[4:9])
self.browser['zone1Form:idRememberMyCifCheck'] = False
self.browser.submit(nologin=True)
form = self.get_form(name='zone1Form')
form['zone1Form:numClient'] = login
form['zone1Form:dateDay'] = birthday[0:2]
form['zone1Form:dateMonth'] = birthday[2:4]
form['zone1Form:dateYear'] = birthday[4:9]
form['zone1Form:idRememberMyCifCheck'] = False
form.submit()
def error(self):
err = self.document.find('//span[@class="error"]')
err = self.doc.find('//span[@class="error"]')
return err is not None
def login(self, password):
@ -111,22 +107,20 @@ class LoginPage(BasePage):
error("Error: %s" % err)
return False
realpasswd = ""
span = self.document.find('//span[@id="digitpaddisplayLogin"]')
span = self.doc.find('//span[@id="digitpaddisplayLogin"]')
i = 0
for font in span.getiterator('font'):
if font.attrib.get('class') == "vide":
realpasswd += password[i]
i += 1
self.browser.logger.debug('We are looking for : ' + realpasswd)
self.browser.select_form('mrc')
self.browser.set_all_readonly(False)
self.browser.logger.debug("Coordonates: " + vk.get_string_code(realpasswd))
self.browser.controls.append(ClientForm.TextControl('text', 'mrc:mrg', {'value': ''}))
self.browser.controls.append(ClientForm.TextControl('text', 'AJAXREQUEST', {'value': ''}))
self.browser['AJAXREQUEST'] = '_viewRoot'
self.browser['mrc:mrldisplayLogin'] = vk.get_string_code(realpasswd)
self.browser['mrc:mrg'] = 'mrc:mrg'
self.browser.submit(nologin=True)
form = self.get_form(name='mrc')
form['mrc:mrg'] = 'mrc:mrg'
form['AJAXREQUEST'] = '_viewRoot'
form['mrc:mrldisplayLogin'] = vk.get_string_code(realpasswd)
form.submit()
class StopPage(BasePage):