From 5dfb2a6c6fc4688a9f0f067dc93d98f347e2ff20 Mon Sep 17 00:00:00 2001
From: Emmanuel Cazenave <ecazenave@entrouvert.com>
Date: Fri, 10 May 2019 17:03:03 +0200
Subject: [PATCH] expose transaction capabilities (#32969)

And implement the first one, manual validation for
systempayv2 and paybox.
---
 eopayment/__init__.py     |  3 +++
 eopayment/common.py       |  2 ++
 eopayment/paybox.py       | 16 +++++++++++++-
 eopayment/systempayv2.py  | 17 ++++++++++++++-
 tests/test_paybox.py      | 44 +++++++++++++++++++++++++++++++++++++++
 tests/test_systempayv2.py | 38 +++++++++++++++++++++++++++++++++
 6 files changed, 118 insertions(+), 2 deletions(-)

diff --git a/eopayment/__init__.py b/eopayment/__init__.py
index f2f1239..a412b17 100644
--- a/eopayment/__init__.py
+++ b/eopayment/__init__.py
@@ -192,3 +192,6 @@ class Payment(object):
            - bank_data -- the transaction dictionary received from the bank
         '''
         return self.backend.validate(amount, bank_data, **kwargs)
+
+    def get_capabilities(self):
+        return self.backend.capabilities
diff --git a/eopayment/common.py b/eopayment/common.py
index 258f856..aa0584d 100644
--- a/eopayment/common.py
+++ b/eopayment/common.py
@@ -120,6 +120,8 @@ class PaymentCommon(object):
     PATH = '/tmp'
     BANK_ID = '__bank_id'
 
+    capabilities = {}
+
     def __init__(self, options, logger=None):
         self.logger = logger or logging.getLogger(self.__class__.__module__)
         self.logger.debug('initializing with options %s', options)
diff --git a/eopayment/paybox.py b/eopayment/paybox.py
index 4c34731..66031b6 100644
--- a/eopayment/paybox.py
+++ b/eopayment/paybox.py
@@ -250,7 +250,19 @@ class Payment(PaymentCommon):
         ]
     }
 
-    def request(self, amount, email, name=None, orderid=None, **kwargs):
+    capabilities = {
+            'params':
+            [
+                {
+                    'name': 'manual_validation',
+                    'label': _('Validation manuelle'),
+                    'type': 'bool',
+                    'default': False
+                }
+            ]
+        }
+
+    def request(self, amount, email, name=None, orderid=None, manual_validation=None, **kwargs):
         d = OrderedDict()
         d['PBX_SITE'] = force_text(self.site)
         d['PBX_RANG'] = force_text(self.rang).strip()[-2:]
@@ -283,6 +295,8 @@ class Payment(PaymentCommon):
         if capture_day:
             d['PBX_DIFF'] = capture_day.zfill(2)
         d['PBX_AUTOSEULE'] = PAYMENT_MODES[self.capture_mode]
+        if manual_validation:
+            d['PBX_AUTOSEULE'] = PAYMENT_MODES['AUTHOR_CAPTURE']
         if automatic_return_url:
             d['PBX_REPONDRE_A'] = force_text(automatic_return_url)
         d = d.items()
diff --git a/eopayment/systempayv2.py b/eopayment/systempayv2.py
index 31731fd..9d70a24 100644
--- a/eopayment/systempayv2.py
+++ b/eopayment/systempayv2.py
@@ -262,14 +262,27 @@ class Payment(PaymentCommon):
              'max_length': parameter.max_length}
         description['parameters'].append(x)
 
+        capabilities = {
+            'params':
+            [
+                {
+                    'name': 'manual_validation',
+                    'label': _('Validation manuelle'),
+                    'type': 'bool',
+                    'default': False
+                }
+            ]
+        }
+
     def __init__(self, options, logger=None):
         super(Payment, self).__init__(options, logger=logger)
         options = add_vads(options)
         self.options = options
 
+
     def request(self, amount, name=None, first_name=None, last_name=None,
                 address=None, email=None, phone=None, orderid=None, info1=None,
-                info2=None, info3=None, next_url=None, **kwargs):
+                info2=None, info3=None, next_url=None, manual_validation=None, **kwargs):
         '''
            Create the URL string to send a request to SystemPay
         '''
@@ -338,6 +351,8 @@ class Payment(PaymentCommon):
         capture_day = fields.pop('capture_day')
         if capture_day:
             fields['vads_capture_delay'] = capture_day
+        if manual_validation:
+            fields['vads_validation_mode'] = '1'
         check_vads(fields)
         fields[SIGNATURE] = force_text(self.signature(fields))
         self.logger.debug('%s request contains fields: %s', __name__, fields)
diff --git a/tests/test_paybox.py b/tests/test_paybox.py
index 9f38090..4567c9a 100644
--- a/tests/test_paybox.py
+++ b/tests/test_paybox.py
@@ -253,3 +253,47 @@ ZdzrudBlevZXpr6iYwIDAQAB
 z0Dkz0NjxvU+5WzQZh9Uuxr/egRCwV4NMRWqu0zaVVioeBvl4/5CWm4f4/1L9+0m
 FBFKOZhgBJnkC+l6+XhT4aYWKaQ4ocmOMV92yjeXTE4='''
         self.assertTrue(paybox.verify(data, base64.b64decode(sig64), key=pkey))
+
+    def test_capabilities(self):
+        params = BACKEND_PARAMS.copy()
+
+        backend = eopayment.Payment('paybox', params)
+        capabilities = backend.get_capabilities()
+        params = capabilities['params']
+        assert len(params) == 1
+
+        param = params[0]
+        assert param['name'] == 'manual_validation'
+        assert param['label'] == 'Validation manuelle'
+        assert param['type'] == 'bool'
+        assert param['default'] is False
+
+    def test_request_manual_validation(self):
+        params = BACKEND_PARAMS.copy()
+        time = '2018-08-21T10:26:32+02:00'
+        email = 'user@entrouvert.com'
+        order_id = '20180821'
+        transaction = '1234'
+        amount = '42.99'
+
+        backend = eopayment.Payment('paybox', params)
+
+        transaction_id, kind, what = backend.request(
+                Decimal(amount), email=email, orderid=order_id,
+                transaction_id=transaction, time=time)
+        root = ET.fromstring(str(what))
+        form_params = dict((
+            (node.attrib['name'], node.attrib['value']) for node in root
+            if node.attrib['type'] == 'hidden'))
+        self.assertIn('PBX_AUTOSEULE', form_params)
+        self.assertEqual(form_params['PBX_AUTOSEULE'], 'N')
+
+        transaction_id, kind, what = backend.request(
+                Decimal(amount), email=email, orderid=order_id,
+                transaction_id=transaction, time=time, manual_validation=True)
+        root = ET.fromstring(str(what))
+        form_params = dict((
+            (node.attrib['name'], node.attrib['value']) for node in root
+            if node.attrib['type'] == 'hidden'))
+        self.assertIn('PBX_AUTOSEULE', form_params)
+        self.assertEqual(form_params['PBX_AUTOSEULE'], 'O')
diff --git a/tests/test_systempayv2.py b/tests/test_systempayv2.py
index 1df7282..7aaff59 100644
--- a/tests/test_systempayv2.py
+++ b/tests/test_systempayv2.py
@@ -98,3 +98,41 @@ def test_systempayv2_deferred_payment():
     data['capture_date'] = (datetime.now().date() + timedelta(days=4))
     transaction_id, f, form = p.request(**data)
     assert get_field(form, 'vads_capture_delay')['value'] == '4'
+
+
+def test_capabilities():
+    params = {
+        'secret_test': u'1122334455667788',
+        'vads_site_id': u'12345678',
+        'vads_ctx_mode': u'TEST',
+    }
+    backend = eopayment.Payment('systempayv2', params)
+    capabilities = backend.get_capabilities()
+    params = capabilities['params']
+    assert len(params) == 1
+
+    param = params[0]
+    assert param['name'] == 'manual_validation'
+    assert param['label'] == 'Validation manuelle'
+    assert param['type'] == 'bool'
+    assert param['default'] is False
+
+
+def test_manual_validation():
+    params = {
+        'secret_test': u'1122334455667788',
+        'vads_site_id': u'12345678',
+        'vads_ctx_mode': u'TEST',
+    }
+    data = {
+        'amount': 15.24, 'orderid': '654321', 'first_name': u'John',
+        'last_name': u'Doe'
+    }
+
+    backend = eopayment.Payment('systempayv2', params)
+    transaction_id, f, form = backend.request(**data.copy())
+    assert get_field(form, 'vads_validation_mode')['value'] == ''
+
+    data['manual_validation'] = True
+    transaction_id, f, form = backend.request(**data.copy())
+    assert get_field(form, 'vads_validation_mode')['value'] == '1'
-- 
2.20.1

