2016-10-13 16:59:10 +02:00
# -*- coding: utf-8 -*-
2018-03-26 09:56:16 +02:00
import codecs
2015-07-16 11:50:12 +02:00
from unittest import TestCase
from decimal import Decimal
import base64
2018-10-09 16:43:41 +02:00
import mock
2018-03-26 09:56:16 +02:00
from six . moves . urllib import parse as urllib
2018-08-21 10:56:49 +02:00
from xml . etree import ElementTree as ET
2015-07-16 11:50:12 +02:00
import eopayment . paybox as paybox
import eopayment
2016-02-08 18:40:45 +01:00
BACKEND_PARAMS = {
2016-10-13 16:59:10 +02:00
' platform ' : u ' test ' ,
' site ' : u ' 12345678 ' ,
' rang ' : u ' 001 ' ,
' identifiant ' : u ' 12345678 ' ,
' shared_secret ' : u ' 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF ' ,
' callback ' : u ' http://example.com/callback ' ,
2016-02-08 18:40:45 +01:00
}
2015-07-16 11:50:12 +02:00
class PayboxTests ( TestCase ) :
def test_sign ( self ) :
2018-03-26 09:56:16 +02:00
key = b ' 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF '
key = codecs . decode ( key , ' hex ' )
2015-07-16 11:50:12 +02:00
d = dict ( paybox . sign ( [
2016-10-13 16:59:10 +02:00
[ ' PBX_SITE ' , u ' 12345678 ' ] ,
[ ' PBX_RANG ' , u ' 32 ' ] ,
[ ' PBX_IDENTIFIANT ' , u ' 12345678 ' ] ,
[ ' PBX_TOTAL ' , u ' 999 ' ] ,
[ ' PBX_DEVISE ' , u ' 978 ' ] ,
[ ' PBX_CMD ' , u ' appel à Paybox ' ] ,
[ ' PBX_PORTEUR ' , u ' test@paybox.com ' ] ,
[ ' PBX_RETOUR ' , u ' Mt:M;Ref:R;Auto:A;Erreur:E ' ] ,
[ ' PBX_HASH ' , u ' SHA512 ' ] ,
[ ' PBX_TIME ' , u ' 2015-06-08T16:21:16+02:00 ' ] ,
2015-07-16 11:50:12 +02:00
] ,
key ) )
2016-10-13 16:59:10 +02:00
result = ' 7E74D8E9A0DBB65AAE51C5C50C2668FD98FC99AEDF18244BB1935F602B6C2E953B61FD84364F34FDB88B049901C0A07F6040AF446BBF5589113F48A733D551D4 '
2015-07-16 11:50:12 +02:00
self . assertIn ( ' PBX_HMAC ' , d )
self . assertEqual ( d [ ' PBX_HMAC ' ] , result )
def test_request ( self ) :
2016-02-08 18:40:45 +01:00
backend = eopayment . Payment ( ' paybox ' , BACKEND_PARAMS )
2015-07-16 11:50:12 +02:00
time = ' 2015-07-15T18:26:32+02:00 '
email = ' bdauvergne@entrouvert.com '
2016-02-08 18:40:45 +01:00
order_id = ' 20160216 '
transaction = ' 1234 '
amount = ' 19.99 '
2015-07-16 11:50:12 +02:00
transaction_id , kind , what = backend . request (
2016-02-08 18:40:45 +01:00
Decimal ( amount ) , email = email , orderid = order_id ,
transaction_id = transaction , time = time )
2015-07-16 11:50:12 +02:00
self . assertEqual ( kind , eopayment . FORM )
self . assertEqual ( transaction_id , ' 1234 ' )
root = ET . fromstring ( str ( what ) )
self . assertEqual ( root . tag , ' form ' )
self . assertEqual ( root . attrib [ ' method ' ] , ' POST ' )
self . assertEqual ( root . attrib [ ' action ' ] , paybox . URLS [ ' test ' ] )
2018-08-21 10:56:49 +02:00
expected_form_values = {
' PBX_RANG ' : ' 01 ' ,
' PBX_SITE ' : ' 12345678 ' ,
' PBX_IDENTIFIANT ' : ' 12345678 ' ,
2018-10-03 11:00:40 +02:00
' PBX_RETOUR ' : ' montant:M;reference:R;code_autorisation:A;erreur:E;numero_appel:T;numero_transaction:S;signature:K ' ,
2018-08-21 10:56:49 +02:00
' PBX_TIME ' : time ,
' PBX_PORTEUR ' : email ,
' PBX_CMD ' : order_id + eopayment . common . ORDERID_TRANSACTION_SEPARATOR + transaction ,
' PBX_TOTAL ' : amount . replace ( ' . ' , ' ' ) ,
' PBX_DEVISE ' : ' 978 ' ,
' PBX_HASH ' : ' SHA512 ' ,
2018-08-20 15:55:02 +02:00
' PBX_HMAC ' : ' 6C70F35F9C6F6C9AB16D1E766EF981D241CB527C2E547205622DFFAF5B1B6C0F47E1DE2D3A1CE579F97AD19F87C3AE63E89B22F4B6D1E118685F5DD977891668 ' ,
2018-08-21 10:56:49 +02:00
' PBX_ARCHIVAGE ' : ' 1234 ' ,
' PBX_REPONDRE_A ' : ' http://example.com/callback ' ,
2018-08-20 15:55:02 +02:00
' PBX_AUTOSEULE ' : ' N '
2018-08-21 10:56:49 +02:00
}
form_params = { }
2015-07-16 11:50:12 +02:00
for node in root :
self . assertIn ( node . attrib [ ' type ' ] , ( ' hidden ' , ' submit ' ) )
if node . attrib [ ' type ' ] == ' submit ' :
self . assertEqual ( set ( node . attrib . keys ( ) ) , set ( [ ' type ' , ' value ' ] ) )
if node . attrib [ ' type ' ] == ' hidden ' :
self . assertEqual ( set ( node . attrib . keys ( ) ) , set ( [ ' type ' , ' name ' , ' value ' ] ) )
name = node . attrib [ ' name ' ]
2018-08-21 10:56:49 +02:00
form_params [ name ] = node . attrib [ ' value ' ]
self . assertEqual ( form_params , expected_form_values )
def test_request_with_capture_day ( 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 '
for capture_day in ( ' 7 ' , ' 07 ' ) :
params [ ' capture_day ' ] = capture_day
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_DIFF ' , form_params )
self . assertEqual ( form_params [ ' PBX_DIFF ' ] , ' 07 ' )
2015-07-16 11:50:12 +02:00
2018-10-12 15:35:23 +02:00
# capture_day can be used as a request argument
params = BACKEND_PARAMS . copy ( )
backend = eopayment . Payment ( ' paybox ' , params )
transaction_id , kind , what = backend . request (
Decimal ( amount ) , email = email , orderid = order_id ,
transaction_id = transaction , time = time , capture_day = 2 )
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_DIFF ' , form_params )
self . assertEqual ( form_params [ ' PBX_DIFF ' ] , ' 02 ' )
# capture_day passed as a request argument
# overrides capture_day from backend params
params = BACKEND_PARAMS . copy ( )
params [ ' capture_day ' ] = ' 7 '
backend = eopayment . Payment ( ' paybox ' , params )
transaction_id , kind , what = backend . request (
Decimal ( amount ) , email = email , orderid = order_id ,
transaction_id = transaction , time = time , capture_day = 2 )
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_DIFF ' , form_params )
self . assertEqual ( form_params [ ' PBX_DIFF ' ] , ' 02 ' )
2018-08-20 15:55:02 +02:00
def test_request_with_authorization_only ( 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 '
params [ ' capture_mode ' ] = ' AUTHOR_CAPTURE '
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 . assertEqual ( form_params [ ' PBX_AUTOSEULE ' ] , ' O ' )
2016-02-08 18:40:45 +01:00
def test_response ( self ) :
backend = eopayment . Payment ( ' paybox ' , BACKEND_PARAMS )
order_id = ' 20160216 '
transaction = ' 1234 '
reference = order_id + eopayment . common . ORDERID_TRANSACTION_SEPARATOR + transaction
data = { ' montant ' : ' 4242 ' , ' reference ' : reference ,
' code_autorisation ' : ' A ' , ' erreur ' : ' 00000 ' }
response = backend . response ( urllib . urlencode ( data ) )
self . assertEqual ( response . order_id , order_id )
2018-08-22 23:14:53 +02:00
with self . assertRaisesRegexp ( eopayment . ResponseError , ' missing erreur or reference ' ) :
backend . response ( ' foo=bar ' )
2018-10-09 16:43:41 +02:00
def test_perform_operations ( self ) :
2018-10-24 10:36:51 +02:00
operations = { ' validate ' : ' 00002 ' , ' cancel ' : ' 00055 ' }
2018-10-09 16:43:41 +02:00
for operation_name , operation_code in operations . items ( ) :
params = BACKEND_PARAMS . copy ( )
params [ ' cle ' ] = ' cancelling_key '
backend = eopayment . Payment ( ' paybox ' , params )
bank_data = { ' numero_transaction ' : [ ' 13957441 ' ] ,
' numero_appel ' : [ ' 30310733 ' ] ,
' reference ' : [ ' 830657461681 ' ]
}
2019-10-29 15:30:38 +01:00
backend_raw_response = u """ NUMTRANS=0013989865&NUMAPPEL=0030378572&NUMQUESTION=0013989862&SITE=1999888&RANG=32&AUTORISATION=XXXXXX&CODEREPONSE=00000&COMMENTAIRE=Demande traitée avec succès&REFABONNE=&PORTEUR= """
2018-10-09 16:43:41 +02:00
backend_expected_response = { " CODEREPONSE " : " 00000 " ,
" RANG " : " 32 " ,
" AUTORISATION " : " XXXXXX " ,
" NUMTRANS " : " 0013989865 " ,
" PORTEUR " : " " ,
2018-10-23 20:30:34 +02:00
" COMMENTAIRE " : u " Demande traitée avec succès " ,
2018-10-09 16:43:41 +02:00
" SITE " : " 1999888 " ,
" NUMAPPEL " : " 0030378572 " ,
" REFABONNE " : " " ,
" NUMQUESTION " : " 0013989862 " }
with mock . patch ( ' eopayment.paybox.requests.post ' ) as requests_post :
2019-10-29 15:30:38 +01:00
response = mock . Mock ( status_code = 200 , text = backend_raw_response )
2018-10-09 16:43:41 +02:00
requests_post . return_value = response
backend_response = getattr ( backend , operation_name ) ( Decimal ( ' 10 ' ) , bank_data )
self . assertEqual ( requests_post . call_args [ 0 ] [ 0 ] , ' https://preprod-ppps.paybox.com/PPPS.php ' )
params_sent = requests_post . call_args [ 0 ] [ 1 ]
# make sure the date parameter is present
assert ' DATEQ ' in params_sent
# don't care about its value
params_sent . pop ( ' DATEQ ' )
expected_params = { ' CLE ' : ' cancelling_key ' ,
2018-10-24 10:36:51 +02:00
' VERSION ' : ' 00103 ' ,
2018-10-09 16:43:41 +02:00
' TYPE ' : operation_code ,
' MONTANT ' : Decimal ( ' 1000 ' ) ,
' NUMAPPEL ' : ' 30310733 ' ,
' NUMTRANS ' : ' 13957441 ' ,
' NUMQUESTION ' : ' 0013957441 ' ,
' REFERENCE ' : ' 830657461681 ' ,
' RANG ' : backend . backend . rang ,
' SITE ' : backend . backend . site ,
' DEVISE ' : backend . backend . devise
}
self . assertEqual ( params_sent , expected_params )
self . assertEqual ( backend_response , backend_expected_response )
params [ ' platform ' ] = ' prod '
backend = eopayment . Payment ( ' paybox ' , params )
with mock . patch ( ' eopayment.paybox.requests.post ' ) as requests_post :
2019-10-29 15:30:38 +01:00
response = mock . Mock ( status_code = 200 , text = backend_raw_response )
2018-10-09 16:43:41 +02:00
requests_post . return_value = response
getattr ( backend , operation_name ) ( Decimal ( ' 10 ' ) , bank_data )
self . assertEqual ( requests_post . call_args [ 0 ] [ 0 ] , ' https://ppps.paybox.com/PPPS.php ' )
with mock . patch ( ' eopayment.paybox.requests.post ' ) as requests_post :
2019-10-29 15:30:38 +01:00
error_response = u """ CODEREPONSE=00015&COMMENTAIRE=PAYBOX : Transaction non trouvée """
response = mock . Mock ( status_code = 200 , text = error_response )
2018-10-09 16:43:41 +02:00
requests_post . return_value = response
self . assertRaisesRegexp ( eopayment . ResponseError , ' Transaction non trouvée ' , getattr ( backend , operation_name ) ,
Decimal ( ' 10 ' ) , bank_data )
def test_validate_payment ( self ) :
params = BACKEND_PARAMS . copy ( )
params [ ' cle ' ] = ' cancelling_key '
backend = eopayment . Payment ( ' paybox ' , params )
bank_data = { ' numero_transaction ' : [ ' 13957441 ' ] ,
' numero_appel ' : [ ' 30310733 ' ] ,
' reference ' : [ ' 830657461681 ' ]
}
2019-10-29 15:30:38 +01:00
backend_raw_response = u """ NUMTRANS=0013989865&NUMAPPEL=0030378572&NUMQUESTION=0013989862&SITE=1999888&RANG=32&AUTORISATION=XXXXXX&CODEREPONSE=00000&COMMENTAIRE=Demande traitée avec succès&REFABONNE=&PORTEUR= """
with mock . patch ( ' eopayment.paybox.requests.post ' ) as requests_post :
response = mock . Mock ( status_code = 200 , text = backend_raw_response )
requests_post . return_value = response
backend . validate ( Decimal ( 13 ) , bank_data )
2018-10-09 16:43:41 +02:00
2015-07-16 11:50:12 +02:00
def test_rsa_signature_validation ( self ) :
pkey = ''' -----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUgYufHuheMztK1LhQSG6xsOzb
UX4D2A / QcMvkEcRVXFx5tQqcE9 / JnMqE41TF / ebn7jC / MBxxtPFkUN7 + EZoeMN7x
OWzAMDm / xsCWRvvel4GGixgm3aQRUPyTrlm4Ksy32Ya0rNnEDMAvB3dxOn7cp8GR
ZdzrudBlevZXpr6iYwIDAQAB
- - - - - END PUBLIC KEY - - - - - '''
2019-10-25 09:15:47 +02:00
data = ' coin \n '
2015-07-16 11:50:12 +02:00
sig64 = ''' VCt3sgT0ecacmDEWWNVXJ+jGmIPBMApK42tBJV0FlDjpllOGPy8MsAmLW4/QjTtx
z0Dkz0NjxvU + 5 WzQZh9Uuxr / egRCwV4NMRWqu0zaVVioeBvl4 / 5 CWm4f4 / 1 L9 + 0 m
FBFKOZhgBJnkC + l6 + XhT4aYWKaQ4ocmOMV92yjeXTE4 = '''
self . assertTrue ( paybox . verify ( data , base64 . b64decode ( sig64 ) , key = pkey ) )
2019-05-10 17:03:03 +02:00
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 ' )