From 0ab9da2fc6d285d3a175b32c0598d4ae274367cd Mon Sep 17 00:00:00 2001 From: Romain Bignon Date: Sun, 28 Jul 2013 20:45:12 +0200 Subject: [PATCH] sgpe: support credit cards --- modules/societegenerale/sgpe/browser.py | 66 ++++++++++++----- modules/societegenerale/sgpe/pages.py | 95 ++++++++++++++++++++++++- 2 files changed, 142 insertions(+), 19 deletions(-) diff --git a/modules/societegenerale/sgpe/browser.py b/modules/societegenerale/sgpe/browser.py index c1ca4966..1325e70d 100644 --- a/modules/societegenerale/sgpe/browser.py +++ b/modules/societegenerale/sgpe/browser.py @@ -21,7 +21,7 @@ from weboob.tools.browser import BaseBrowser, BrowserIncorrectPassword from weboob.tools.ordereddict import OrderedDict -from .pages import LoginPage, ErrorPage, AccountsPage, HistoryPage +from .pages import LoginPage, ErrorPage, AccountsPage, CardsPage, HistoryPage, CardHistoryPage __all__ = ['SGProfessionalBrowser', 'SGEnterpriseBrowser'] @@ -34,7 +34,9 @@ class SGPEBrowser(BaseBrowser): def __init__(self, *args, **kwargs): self.PAGES = OrderedDict(( ('%s://%s/Pgn/.+PageID=SoldeV3&.+' % (self.PROTOCOL, self.DOMAIN), AccountsPage), + ('%s://%s/Pgn/.+PageID=Cartes&.+' % (self.PROTOCOL, self.DOMAIN), CardsPage), ('%s://%s/Pgn/.+PageID=ReleveCompteV3&.+' % (self.PROTOCOL, self.DOMAIN), HistoryPage), + ('%s://%s/Pgn/.+PageID=ReleveCarte&.+' % (self.PROTOCOL, self.DOMAIN), CardHistoryPage), ('%s://%s/authent\.html' % (self.PROTOCOL, self.DOMAIN), ErrorPage), ('%s://%s/' % (self.PROTOCOL, self.DOMAIN), LoginPage), )) @@ -67,20 +69,36 @@ class SGPEBrowser(BaseBrowser): raise BrowserIncorrectPassword() def accounts(self, no_login=False): - self.location('/Pgn/NavigationServlet?PageID=SoldeV3&MenuID=%s&Classeur=1&NumeroPage=1' % self.MENUID, no_login=no_login) + self.location('/Pgn/NavigationServlet?PageID=SoldeV3&MenuID=%sCPT&Classeur=1&NumeroPage=1' % self.MENUID, no_login=no_login) + + def cards(self): + doc = self.get_document(self.openurl('/Pgn/NavigationServlet?PageID=CartesFutures&MenuID=%sOPF&Classeur=1&NumeroPage=1&PageDetail=1' % self.MENUID)) + url = doc.xpath('//iframe[@name="cartes"]')[0].attrib['src'] + self.location(url) def history(self, _id, page=1): if page > 1: pgadd = '&page_numero_page_courante=%s' % page else: pgadd = '' - self.location('/Pgn/NavigationServlet?PageID=ReleveCompteV3&MenuID=%s&Classeur=1&Rib=%s&NumeroPage=1%s' % (self.MENUID, _id, pgadd)) + self.location('/Pgn/NavigationServlet?PageID=ReleveCompteV3&MenuID=%sCPT&Classeur=1&Rib=%s&NumeroPage=1%s' % (self.MENUID, _id, pgadd)) + + def card_history(self, rib, _id, date, currency, page=1): + self.location('/Pgn/NavigationServlet?PageID=ReleveCarte&MenuID=%sOPF&Classeur=1&Rib=%s&Carte=%s&Date=%s&PageDetail=%s&Devise=%s' % (self.MENUID, rib, _id, date, page, currency)) def get_accounts_list(self): if not self.is_on_page(AccountsPage): self.accounts() + assert self.is_on_page(AccountsPage) - return self.page.get_list() + for acc in self.page.get_list(): + yield acc + + self.cards() + + assert self.is_on_page(CardsPage) + for acc in self.page.get_list(): + yield acc def get_account(self, _id): for a in self.get_accounts_list(): @@ -88,29 +106,41 @@ class SGPEBrowser(BaseBrowser): yield a def iter_history(self, account): - page = 1 - basecount = 0 - while page: - self.history(account.id, page) - assert self.is_on_page(HistoryPage) - for transaction in self.page.iter_transactions(account, basecount): - basecount = int(transaction.id) + 1 - yield transaction - if self.page.has_next(): - page += 1 - else: - page = False + if account._is_card: + page = 1 + while page: + self.card_history(account._link_rib, account.id, account._link_date, account._link_currency, page) + assert self.is_on_page(CardHistoryPage) + for tr in self.page.iter_transactions(): + yield tr + if self.page.has_next(): + page += 1 + else: + page = False + else: + page = 1 + basecount = 0 + while page: + self.history(account.id, page) + assert self.is_on_page(HistoryPage) + for transaction in self.page.iter_transactions(account, basecount): + basecount = int(transaction.id) + 1 + yield transaction + if self.page.has_next(): + page += 1 + else: + page = False class SGProfessionalBrowser(SGPEBrowser): DOMAIN = 'professionnels.secure.societegenerale.fr' LOGIN_FORM = 'auth_reco' - MENUID = 'SBORELCPT' + MENUID = 'SBOREL' CERTHASH = 'd369315d357ba0018c2bd4d3394645669d99106c797d7390fded516b098a933e' class SGEnterpriseBrowser(SGPEBrowser): DOMAIN = 'entreprises.secure.societegenerale.fr' LOGIN_FORM = 'auth' - MENUID = 'BANRELCPT' + MENUID = 'BANREL' CERTHASH = 'd5c21d47c7d5a300b40856be49d0b36b42eaae409c8891184652b888d16a05f5' diff --git a/modules/societegenerale/sgpe/pages.py b/modules/societegenerale/sgpe/pages.py index d84c3170..8f1738ad 100644 --- a/modules/societegenerale/sgpe/pages.py +++ b/modules/societegenerale/sgpe/pages.py @@ -33,7 +33,7 @@ from weboob.tools.capabilities.bank.transactions import FrenchTransaction from ..captcha import Captcha, TileError -__all__ = ['LoginPage', 'AccountsPage'] +__all__ = ['LoginPage', 'AccountsPage', 'CardsPage', 'HistoryPage', 'CardHistoryPage'] class Transaction(FrenchTransaction): @@ -107,10 +107,64 @@ class AccountsPage(SGPEPage): account.label = to_unicode(tdname) account.id = to_unicode(tdid.replace(u'\xa0', '').replace(' ', '')) account._agency = to_unicode(tdagency) + account._is_card = False account.balance = Decimal(Transaction.clean_amount(tdbalance)) account.currency = account.get_currency(tdbalance) yield account +class CardsPage(SGPEPage): + COL_ID = 0 + COL_LABEL = 1 + COL_BALANCE = 2 + + def get_list(self): + rib = None + currency = None + for script in self.document.xpath('//script'): + if script.text is None: + continue + + m = re.search('var rib = "(\d+)"', script.text) + if m: + rib = m.group(1) + m = re.search("var devise='(\w+)'", script.text) + if m: + currency = m.group(1) + + if all((rib, currency)): + break + + if not all((rib, currency)): + self.logger.error('Unable to find rib or currency') + + for tr in self.document.xpath('//table[@id="tab-corps"]//tr'): + tds = tr.findall('td') + + if len(tds) != 3: + continue + + account = Account() + account.label = self.parser.tocleanstring(tds[self.COL_LABEL]) + if len(account.label) == 0: + continue + + link = tds[self.COL_ID].xpath('.//a')[0] + m = re.match(r"changeCarte\('(\d+)','(\d+)','([\d/]+)'\);.*", link.attrib['onclick']) + if not m: + self.logger.error('Unable to parse link %r' % link.attrib['onclick']) + continue + account.id = m.group(2) + account._link_num = m.group(1) #useless + account._link_date = m.group(3) + account._link_rib = rib + account._link_currency = currency + account._is_card = True + tdbalance = self.parser.tocleanstring(tds[self.COL_BALANCE]) + account.balance = - Decimal(Transaction.clean_amount(tdbalance)) + account.currency = account.get_currency(tdbalance) + yield account + + class HistoryPage(SGPEPage): def iter_transactions(self, account, basecount): @@ -144,3 +198,42 @@ class HistoryPage(SGPEPage): for end in self.parser.select(n, '.contenu3-lien'): return int(end.text.replace('/', '')) > cur return False + +class CardHistoryPage(SGPEPage): + COL_DATE = 0 + COL_LABEL = 1 + COL_AMOUNT = -1 + + def iter_transactions(self): + table = self.parser.select(self.document.getroot(), '#tab-corps', 1) + for i, tr in enumerate(self.parser.select(table, 'tr', 'many')): + + tds = tr.findall('td') + + date = self.parser.tocleanstring(tds[self.COL_DATE]) + raw = self.parser.tocleanstring(tds[self.COL_LABEL]) + amount = self.parser.tocleanstring(tds[self.COL_AMOUNT]) + + t = Transaction(i) + t.parse(date, raw) + t.set_amount(amount) + yield t + + def has_next(self): + current = None + total = None + for script in self.document.xpath('//script'): + if script.text is None: + continue + + m = re.search('var pageActive\s+= (\d+)', script.text) + if m: + current = int(m.group(1)) + m = re.search("var nombrePage\s+= (\d+)", script.text) + if m: + total = int(m.group(1)) + + if all((current, total)) and current < total: + return True + + return False