Projet

Général

Profil

0001-paybox-add-support-for-payment-cancelling-26960.patch

Serghei Mihai (congés, retour 15/05), 11 octobre 2018 19:20

Télécharger (6,96 ko)

Voir les différences:

Subject: [PATCH] paybox: add support for payment cancelling (#26960)

 eopayment/paybox.py  | 37 +++++++++++++++++++++++++++
 tests/test_paybox.py | 61 ++++++++++++++++++++++++++++++++++++++++++++
 tox.ini              |  1 +
 3 files changed, 99 insertions(+)
eopayment/paybox.py
6 6
import logging
7 7
import hashlib
8 8
import hmac
9
import requests
9 10
from decimal import Decimal, ROUND_DOWN
10 11
from Crypto.Signature import PKCS1_v1_5
11 12
from Crypto.PublicKey import RSA
......
99 100
        'https://tpeweb1.paybox.com/cgi/MYchoix_pagepaiement.cgi',
100 101
}
101 102

  
103
DIRECT_URLS = {
104
    'test': 'https://preprod-ppps.paybox.com/PPPS.php',
105
    'prod': 'https://ppps.paybox.com/PPPS.php',
106
    'backup': 'https://ppps1.paybox.com/PPPS.php'
107
}
108

  
102 109

  
103 110
def sign(data, key):
104 111
    '''Take a list of tuple key, value and sign it by building a string to
......
174 181
                'validation': lambda x: isinstance(x, basestring) and
175 182
                x.isdigit() and len(x) == 7,
176 183
            },
184
            {
185
                'name': 'cle',
186
                'caption': _('Site key'),
187
                'required': False,
188
                'validation': lambda x: isinstance(x, basestring),
189
            },
177 190
            {
178 191
                'name': 'rang',
179 192
                'caption': _('Numéro de rang'),
......
311 324
            bank_data=d,
312 325
            result=result,
313 326
            bank_status=bank_status)
327

  
328
    def cancel(self, amount, bank_data, **kwargs):
329
        logger = logging.getLogger(__name__)
330
        url = DIRECT_URLS[self.platform]
331
        params = {'VERSION': '00104', # protocol version
332
                  'TYPE': '00005', # cancelling operation code
333
                  'SITE': force_text(self.site),
334
                  'RANG': self.rang.strip(),
335
                  'CLE': force_text(self.cle),
336
                  'NUMQUESTION': bank_data['numero_transaction'][0].zfill(10),
337
                  'MONTANT': (amount * Decimal(100)).to_integral_value(ROUND_DOWN),
338
                  'DEVISE': force_text(self.devise),
339
                  'NUMTRANS': bank_data['numero_transaction'][0], # paybox transaction number
340
                  'NUMAPPEL': bank_data['numero_appel'][0],
341
                  'REFERENCE': bank_data['reference'][0],
342
                  'DATEQ': datetime.datetime.now().strftime('%d%m%Y%H%M%S'),
343
        }
344
        response = requests.post(url, params)
345
        response.raise_for_status()
346
        logger.debug('received %r', response.content)
347
        data = dict(urlparse.parse_qsl(response.content, True, True))
348
        if data.get('CODEREPONSE') != '00000':
349
            raise ResponseError(data.get('COMMENTAIRE'))
350
        return data
tests/test_paybox.py
4 4
from unittest import TestCase
5 5
from decimal import Decimal
6 6
import base64
7
import mock
7 8
from six.moves.urllib import parse as urllib
8 9
from xml.etree import ElementTree as ET
9 10

  
......
116 117
        with self.assertRaisesRegexp(eopayment.ResponseError, 'missing erreur or reference'):
117 118
            backend.response('foo=bar')
118 119

  
120
    def test_cancel_payment(self):
121
        params = BACKEND_PARAMS.copy()
122
        params['cle'] = 'cancelling_key'
123
        backend = eopayment.Payment('paybox', params)
124
        bank_data = {'numero_transaction': ['13957441'],
125
                     'numero_appel': ['30310733'],
126
                     'reference': ['830657461681']
127
        }
128
        backend_raw_response = """NUMTRANS=0013989865&NUMAPPEL=0030378572&NUMQUESTION=0013989862&SITE=1999888&RANG=32&AUTORISATION=XXXXXX&CODEREPONSE=00000&COMMENTAIRE=Demande traitée avec succès&REFABONNE=&PORTEUR="""
129
        backend_expected_response = {"CODEREPONSE": "00000",
130
                    "RANG": "32",
131
                    "AUTORISATION": "XXXXXX",
132
                    "NUMTRANS": "0013989865",
133
                    "PORTEUR": "",
134
                    "COMMENTAIRE": "Demande traitée avec succès",
135
                    "SITE": "1999888",
136
                    "NUMAPPEL": "0030378572",
137
                    "REFABONNE": "",
138
                    "NUMQUESTION": "0013989862"}
139

  
140
        with mock.patch('eopayment.paybox.requests.post') as requests_post:
141
            response = mock.Mock(status_code=200, content=backend_raw_response)
142
            requests_post.return_value = response
143
            backend_response = backend.cancel(Decimal('10'), bank_data)
144
            self.assertEqual(requests_post.call_args[0][0], 'https://preprod-ppps.paybox.com/PPPS.php')
145
            params_sent = requests_post.call_args[0][1]
146
            # make sure the date parameter is present
147
            assert 'DATEQ' in params_sent
148
            # don't care about its value
149
            params_sent.pop('DATEQ')
150
            expected_params = {'CLE': 'cancelling_key',
151
                'VERSION': '00104',
152
                'TYPE': '00005',
153
                'MONTANT': Decimal('1000'),
154
                'NUMAPPEL': '30310733',
155
                'NUMTRANS': '13957441',
156
                'NUMQUESTION': '0013957441',
157
                'REFERENCE': '830657461681',
158
                'RANG': backend.backend.rang,
159
                'SITE': backend.backend.site,
160
                'DEVISE': backend.backend.devise
161
            }
162
            self.assertEqual(params_sent, expected_params)
163
            self.assertEqual(backend_response, backend_expected_response)
164

  
165
        params['platform'] = 'prod'
166
        backend = eopayment.Payment('paybox', params)
167
        with mock.patch('eopayment.paybox.requests.post') as requests_post:
168
            response = mock.Mock(status_code=200, content=backend_raw_response)
169
            requests_post.return_value = response
170
            backend.cancel(Decimal('10'), bank_data)
171
            self.assertEqual(requests_post.call_args[0][0], 'https://ppps.paybox.com/PPPS.php')
172

  
173
        with mock.patch('eopayment.paybox.requests.post') as requests_post:
174
            error_response = """CODEREPONSE=00015&COMMENTAIRE=PAYBOX : Transaction non trouvée"""
175
            response = mock.Mock(status_code=200, content=error_response)
176
            requests_post.return_value = response
177
            self.assertRaisesRegexp(eopayment.ResponseError, 'Transaction non trouvée', backend.cancel, Decimal('10'), bank_data)
178

  
179

  
119 180
    def test_rsa_signature_validation(self):
120 181
        pkey = '''-----BEGIN PUBLIC KEY-----
121 182
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUgYufHuheMztK1LhQSG6xsOzb
tox.ini
15 15
deps = coverage
16 16
  pytest
17 17
  pytest-cov
18
  mock
18
-