diff --git a/modules/bnporc/backend.py b/modules/bnporc/backend.py
index 6ecb398a..de2048c5 100644
--- a/modules/bnporc/backend.py
+++ b/modules/bnporc/backend.py
@@ -27,9 +27,10 @@ from datetime import datetime, timedelta
from weboob.capabilities.bank import ICapBank, AccountNotFound, Account, Recipient
from weboob.capabilities.messages import ICapMessages, Thread
from weboob.tools.backend import BaseBackend, BackendConfig
-from weboob.tools.value import ValueBackendPassword
+from weboob.tools.value import ValueBackendPassword, Value
from .browser import BNPorc
+from .enterprise.browser import BNPEnterprise
__all__ = ['BNPorcBackend']
@@ -42,12 +43,14 @@ class BNPorcBackend(BaseBackend, ICapBank, ICapMessages):
VERSION = '0.g'
LICENSE = 'AGPLv3+'
DESCRIPTION = 'BNP Paribas French bank website'
- CONFIG = BackendConfig(ValueBackendPassword('login', label='Account ID', masked=False),
- ValueBackendPassword('password', label='Password', regexp='^(\d{6}|)$'),
- ValueBackendPassword('rotating_password', default='',
- label='Password to set when the allowed uses are exhausted (6 digits)',
- regexp='^(\d{6}|)$'))
- BROWSER = BNPorc
+ CONFIG = BackendConfig(
+ ValueBackendPassword('login', label='Account ID', masked=False),
+ ValueBackendPassword('password', label='Password', regexp='^(\d{6}|)$'),
+ ValueBackendPassword('rotating_password', default='',
+ label='Password to set when the allowed uses are exhausted (6 digits)',
+ regexp='^(\d{6}|)$'),
+ Value('website', label='Website to use', default='pp',
+ choices={'pp': 'Particuliers/Profesionnels', 'ent': 'Entreprises'}))
STORAGE = {'seen': []}
# Store the messages *list* for this duration
@@ -59,14 +62,20 @@ class BNPorcBackend(BaseBackend, ICapBank, ICapMessages):
self._threads_age = datetime.utcnow()
def create_default_browser(self):
+ b = {'pp': BNPorc, 'ent': BNPEnterprise}
+ self.BROWSER = b[self.config['website'].get()]
if self.config['rotating_password'].get().isdigit() and len(self.config['rotating_password'].get()) == 6:
rotating_password = self.config['rotating_password'].get()
else:
rotating_password = None
- return self.create_browser(self.config['login'].get(),
- self.config['password'].get(),
- password_changed_cb=self._password_changed_cb,
- rotating_password=rotating_password)
+ if self.config['website'].get() != 'pp':
+ return self.create_browser(self.config['login'].get(),
+ self.config['password'].get())
+ else:
+ return self.create_browser(self.config['login'].get(),
+ self.config['password'].get(),
+ password_changed_cb=self._password_changed_cb,
+ rotating_password=rotating_password)
def _password_changed_cb(self, old, new):
self.config['password'].set(new)
@@ -92,10 +101,16 @@ class BNPorcBackend(BaseBackend, ICapBank, ICapMessages):
return self.browser.iter_history(account)
def iter_coming(self, account):
+ if self.config['website'].get() != 'pp':
+ raise NotImplementedError()
+
with self.browser:
return self.browser.iter_coming_operations(account)
def iter_transfer_recipients(self, ignored):
+ if self.config['website'].get() != 'pp':
+ raise NotImplementedError()
+
for account in self.browser.get_transfer_accounts().itervalues():
recipient = Recipient()
recipient.id = account.id
@@ -103,6 +118,9 @@ class BNPorcBackend(BaseBackend, ICapBank, ICapMessages):
yield recipient
def transfer(self, account, to, amount, reason=None):
+ if self.config['website'].get() != 'pp':
+ raise NotImplementedError()
+
if isinstance(account, Account):
account = account.id
@@ -141,6 +159,9 @@ class BNPorcBackend(BaseBackend, ICapBank, ICapMessages):
return self.get_thread(thread)
def get_thread(self, _id):
+ if self.config['website'].get() != 'pp':
+ raise NotImplementedError()
+
if isinstance(_id, Thread):
thread = _id
_id = thread.id
@@ -151,6 +172,9 @@ class BNPorcBackend(BaseBackend, ICapBank, ICapMessages):
return thread
def iter_unread_messages(self):
+ if self.config['website'].get() != 'pp':
+ raise NotImplementedError()
+
threads = list(self.iter_threads(cache=True))
for thread in threads:
if thread.root.flags & thread.root.IS_UNREAD:
diff --git a/modules/bnporc/enterprise/__init__.py b/modules/bnporc/enterprise/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/modules/bnporc/enterprise/browser.py b/modules/bnporc/enterprise/browser.py
new file mode 100644
index 00000000..b18f8e36
--- /dev/null
+++ b/modules/bnporc/enterprise/browser.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2013 Laurent Bachelier
+#
+# This file is part of weboob.
+#
+# weboob is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# weboob is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with weboob. If not, see .
+
+
+from weboob.tools.browser import BaseBrowser, BrowserIncorrectPassword
+
+from .pages import LoginPage, AccountsPage
+
+__all__ = ['BNPEnterprise']
+
+
+class BNPEnterprise(BaseBrowser):
+ DOMAIN = 'entreprisesplus.bnpparibas.net'
+ PROTOCOL = 'https'
+ CERTHASH = '423f68a8162d1328bacb48269675d8b8577ebcc9d222860de8421792c4d222c1'
+
+ PAGES = {'%s://%s/NSAccess.*' % (PROTOCOL, DOMAIN): LoginPage,
+ '%s://%s/UNE\?Action=DSP_VGLOBALE' % (PROTOCOL, DOMAIN): AccountsPage}
+
+ def home(self):
+ self.location('%s://%s/NSAccess' % (self.PROTOCOL, self.DOMAIN))
+
+ def is_logged(self):
+ if self.page:
+ if self.page.get_error() is not None:
+ return False
+ return not self.is_on_page(LoginPage)
+
+ def login(self):
+ assert isinstance(self.username, basestring)
+ assert isinstance(self.password, basestring)
+ assert self.password.isdigit()
+
+ if not self.is_on_page(LoginPage):
+ self.home()
+
+ self.page.login(self.username, self.password)
+ self.location('/UNE?Action=DSP_VGLOBALE', no_login=True)
+
+ if not self.is_logged():
+ raise BrowserIncorrectPassword()
diff --git a/modules/bnporc/enterprise/pages.py b/modules/bnporc/enterprise/pages.py
new file mode 100644
index 00000000..b9b3ae9f
--- /dev/null
+++ b/modules/bnporc/enterprise/pages.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+
+# Copyright(C) 2013 Laurent Bachelier
+#
+# This file is part of weboob.
+#
+# weboob is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# weboob is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with weboob. If not, see .
+
+from weboob.tools.browser import BasePage
+
+__all__ = ['LoginPage', 'AccountsPage']
+
+
+class BEPage(BasePage):
+ def get_error(self):
+ for title in self.document.xpath('/html/head/title'):
+ if 'erreur' in title.text or 'error' in title.text:
+ return self.parser.select(self.document.getroot(),
+ 'input[@name="titre_page"]', 1).value
+
+
+class LoginPage(BEPage):
+ def login(self, username, password):
+ raise NotImplementedError()
+
+
+class AccountsPage(BEPage):
+ pass