Commit b704fff5 authored by Sylvie Ye's avatar Sylvie Ye Committed by Romain Bignon

[societegenerale] update and reorganize new recipient code

Put navigation on and page scraping on
Handle result of add new recipient with security pass
parent 2900c921
......@@ -25,10 +25,11 @@ from dateutil.relativedelta import relativedelta
from weboob.browser import LoginBrowser, URL, need_login, StatesMixin
from weboob.exceptions import BrowserIncorrectPassword, ActionNeeded, BrowserUnavailable
from import Account, TransferBankError
from import Account, TransferBankError, AddRecipientStep
from weboob.capabilities.base import find_object, NotAvailable
from weboob.browser.exceptions import BrowserHTTPNotFound, ClientError
from weboob.capabilities.profile import ProfileMissing
from import Value, ValueBool
from .pages.accounts_list import (
AccountsMainPage, AccountDetailsPage, AccountsPage, LoansPage, HistoryPage,
......@@ -37,7 +38,7 @@ from .pages.accounts_list import (
MarketPage, LifeInsurance, LifeInsuranceHistory, LifeInsuranceInvest, LifeInsuranceInvest2,
from .pages.transfer import AddRecipientPage, RecipientJson, TransferJson, SignTransferPage
from .pages.transfer import AddRecipientPage, SignRecipientPage, TransferJson, SignTransferPage
from .pages.login import MainPage, LoginPage, BadLoginPage, ReinitPasswordPage, ActionNeededPage, ErrorPage
from .pages.subscription import BankStatementPage
......@@ -67,7 +68,7 @@ class SocieteGenerale(LoginBrowser, StatesMixin):
json_recipient = URL(r'/sec/getsigninfo.json',
r'/sec/oob_polling.json', RecipientJson)
r'/sec/oob_polling.json', SignRecipientPage)
# Transfer
json_transfer = URL(r'/icd/vupri/data/vupri-liste-comptes.json\?an200_isBack=false',
......@@ -114,6 +115,9 @@ class SocieteGenerale(LoginBrowser, StatesMixin):
__states__ = ('context', 'dup', 'id_transaction')
def locate_browser(self, state):
def load_state(self, state):
if state.get('dup') is not None and state.get('context') is not None:
super(SocieteGenerale, self).load_state(state)
......@@ -327,17 +331,26 @@ class SocieteGenerale(LoginBrowser, StatesMixin):
return transfer
def end_sms_recipient(self, recipient, **params):
data = [('context', self.context), ('context', self.context), ('dup', self.dup), ('code', params['code']), ('csa_op', 'sign')]
self.add_recipient.go(data=data, headers={'Referer': self.absurl('/lgn/url.html')})
"""End adding recipient with OTP SMS authentication"""
data = [
('context', [self.context, self.context]),
('dup', self.dup),
('code', params['code']),
('csa_op', 'sign')
# needed to confirm recipient validation
add_recipient_url = self.absurl('/lgn/url.html', base=True)
self.location(add_recipient_url, data=data, headers={'Referer': add_recipient_url})
def end_oob_recipient(self, recipient, **params):
r ='/sec/oob_polling.json'), data={'n10_id_transaction': self.id_transaction})
assert['donnees']['transaction_status'] in ('available', 'in_progress'), \
'transaction_status is %s' %['donnees']['transaction_status']
if['donnees']['transaction_status'] == 'in_progress':
raise ActionNeeded('Veuillez valider le bénéficiaire sur votre application bancaire.')
"""End adding recipient with 'pass sécurité' authentication"""
r =
data={'n10_id_transaction': self.id_transaction}
assert self.id_transaction, "Transaction id is missing, can't sign new recipient."
data = [
('context', self.context),
......@@ -346,24 +359,51 @@ class SocieteGenerale(LoginBrowser, StatesMixin):
('n10_id_transaction', self.id_transaction),
('oob_op', 'sign')
# needed to confirm recipient validation
add_recipient_url = self.absurl('/lgn/url.html', base=True)
headers={'Referer': add_recipient_url}
self.location(add_recipient_url, data=data, headers={'Referer': add_recipient_url})
def send_sms_to_user(self, recipient):
"""Add recipient with OTP SMS authentication"""
data = {}
data['csa_op'] = 'sign'
data['context'] = self.context'/sec/csa/send.json'), data=data)
raise AddRecipientStep(recipient, Value('code', label='Cette opération doit être validée par un Code Sécurité.'))
def send_notif_to_user(self, recipient):
"""Add recipient with 'pass sécurité' authentication"""
data = {}
data['b64_jeton_transaction'] = self.context
r ='/sec/oob_sendoob.json'), data=data)
self.id_transaction =
raise AddRecipientStep(recipient, ValueBool('pass', label='Valider cette opération sur votre applicaton société générale'))
def new_recipient(self, recipient, **params):
if 'code' in params:
return self.end_sms_recipient(recipient, **params)
if 'pass' in params:
return self.end_oob_recipient(recipient, **params)
recipient =, get_info=True)
data =
r ='/sec/getsigninfo.json'), data=data)
sign_method =
# WARNING: this send validation request to user
if sign_method == 'CSA':
return self.send_sms_to_user(recipient)
elif sign_method == 'OOB':
return self.send_notif_to_user(recipient)
assert False, 'Sign process unknown: %s' % sign_method
def get_advisor(self):
......@@ -100,7 +100,7 @@ class SocieteGeneraleModule(Module, CapBankWealth, CapBankTransferAddRecipient,
return self.browser.iter_recipients(origin_account)
def new_recipient(self, recipient, **params):
if self.config['website'].get() not in ('pro', ):
if self.config['website'].get() not in ('par', 'pro'):
raise NotImplementedError()
recipient.label = ' '.join(w for w in re.sub('[^0-9a-zA-Z:\/\-\?\(\)\.,\'\+ ]+', '', recipient.label).split())
return self.browser.new_recipient(recipient, **params)
......@@ -23,7 +23,7 @@ import re
from weboob.browser.pages import LoggedPage, JsonPage, FormNotFound
from weboob.browser.elements import method, ItemElement, DictElement
from import (
Recipient, Transfer, TransferBankError, AddRecipientBankError, AddRecipientStep,
Recipient, Transfer, TransferBankError, AddRecipientBankError, AddRecipientTimeout,
from import is_iban_valid
from weboob.capabilities.base import NotAvailable
......@@ -32,9 +32,8 @@ from weboob.browser.filters.standard import (
from weboob.browser.filters.html import Link
from weboob.browser.filters.json import Dict
from import Value, ValueBool
from import json
from weboob.exceptions import BrowserUnavailable
from weboob.exceptions import BrowserUnavailable, ActionNeeded
from .base import BasePage
from .login import MainPage
......@@ -167,8 +166,29 @@ class SignTransferPage(LoggedPage, MainPage):
class RecipientJson(LoggedPage, JsonPage):
class SignRecipientPage(LoggedPage, JsonPage):
def on_load(self):
assert Dict('commun/statut')(self.doc).upper() == 'OK', \
'Something went wrong on sign recipient page: %s' % Dict('commun/raison')(self.doc)
def get_sign_method(self):
return Dict('donnees/sign_proc')(self.doc).upper()
def check_recipient_status(self):
transaction_status = Dict('donnees/transaction_status')(self.doc)
# check add new recipient status
assert transaction_status in ('available', 'in_progress', 'aborted', 'rejected'), \
'transaction_status is %s' % transaction_status
if transaction_status == 'aborted':
raise AddRecipientTimeout()
elif transaction_status == 'rejected':
raise ActionNeeded("La demande d'ajout de bénéficiaire a été annulée.")
elif transaction_status == 'in_progress':
raise ActionNeeded('Veuillez valider le bénéficiaire sur votre application bancaire.')
def get_transaction_id(self):
return Dict('donnees/id-transaction')(self.doc)
class AddRecipientPage(LoggedPage, BasePage):
......@@ -201,40 +221,26 @@ class AddRecipientPage(LoggedPage, BasePage):
if 'actionLevel' in CleanText('.')(script):
return"'actionLevel': (\d{3}),", script.text).group(1)
def double_auth(self, recipient):
def get_signinfo_data_form(self):
form = self.get_form(id='formCache')
except FormNotFound:
assert False, 'Double auth form not found'
assert False, 'Transfer auth form not found'
return form
def update_browser_recipient_state(self):
form = self.get_signinfo_data_form()
# set browser variable used to continue new recipient
self.browser.context = form['context']
self.browser.dup = form['dup']
self.browser.logged = 1
getsigninfo_data = {}
getsigninfo_data['b64_jeton_transaction'] = form['context']
getsigninfo_data['action_level'] = self.get_action_level()
r ='', data=getsigninfo_data)
assert['commun']['statut'] == 'ok'
recipient = self.get_recipient_object(recipient, get_info=True) = None
if['donnees']['sign_proc'] == 'csa':
send_data = {}
send_data['csa_op'] = 'sign'
send_data['context'] = form['context']
r ='', data=send_data)
assert['commun']['statut'] == 'ok'
raise AddRecipientStep(recipient, Value('code', label=u'Cette opération doit être validée par un Code Sécurité.'))
elif['donnees']['sign_proc'] == 'OOB':
oob_data = {}
oob_data['b64_jeton_transaction'] = form['context']
r ='', data=oob_data)
assert['commun']['statut'] == 'ok'
self.browser.id_transaction =['donnees']['id-transaction']
raise AddRecipientStep(recipient, ValueBool('pass', label=u'Valider cette opération sur votre applicaton société générale'))
assert False, 'Sign process unknown: %s' %['donnees']['sign_proc']
def get_signinfo_data(self):
form = self.get_signinfo_data_form()
signinfo_data = {}
signinfo_data['b64_jeton_transaction'] = form['context']
signinfo_data['action_level'] = self.get_action_level()
return signinfo_data
def get_recipient_object(self, recipient, get_info=False):
r = Recipient()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment