Ensure transaction id unicity, add logging to spplus
This commit is contained in:
parent
7b899eea74
commit
5af4679368
|
@ -5,6 +5,7 @@ from decimal import Decimal
|
|||
import logging
|
||||
import os
|
||||
import os.path
|
||||
import uuid
|
||||
|
||||
from common import PaymentCommon, HTML
|
||||
|
||||
|
@ -35,10 +36,21 @@ REQUEST_VALID_PARAMS = ['merchant_id', 'merchant_country', 'amount',
|
|||
'capture_day', 'capture_mode', 'bgcolor', 'block_align', 'block_order',
|
||||
'textcolor', 'receipt_complement', 'caddie', 'customer_id', 'customer_email',
|
||||
'customer_ip_address', 'data', 'return_context', 'target', 'order_id']
|
||||
|
||||
RESPONSE_PARAMS = [ 'code', 'error', 'merchant_id', 'merchant_country',
|
||||
'amount', 'transaction_id', 'payment_means', 'transmission_date',
|
||||
'payment_time', 'payment_date', 'response_code', 'payment_certificate',
|
||||
'authorisation_id', 'currency_code', 'card_number', 'cvv_flag',
|
||||
'cvv_response_code', 'bank_response_code', 'complementary_code',
|
||||
'complementary_info', 'return_context', 'caddie', 'receipt_complement',
|
||||
'merchant_language', 'language', 'customer_id', 'order_id', 'customer_email',
|
||||
'customer_ip_address', 'capture_day', 'capture_mode', 'data', ]
|
||||
|
||||
DATA = 'DATA'
|
||||
PARAMS = 'params'
|
||||
|
||||
TRANSACTION_ID = 'transaction_id'
|
||||
ORDER_ID = 'order_id'
|
||||
MERCHANT_ID = 'merchant_id'
|
||||
RESPONSE_CODE = 'response_code'
|
||||
|
||||
|
@ -75,6 +87,7 @@ class Payment(PaymentCommon):
|
|||
transaction_id = self.transaction_id(6, string.digits, 'sips',
|
||||
params[MERCHANT_ID])
|
||||
params[TRANSACTION_ID] = transaction_id
|
||||
params[ORDER_ID] = str(uuid.uuid4()).replace('-','')
|
||||
params['amount'] = str(Decimal(amount)*100)
|
||||
if email:
|
||||
params['customer_email'] = email
|
||||
|
@ -82,7 +95,7 @@ class Payment(PaymentCommon):
|
|||
params['normal_return_url'] = next_url
|
||||
code, error, form = self.execute('request', params)
|
||||
if int(code) == 0:
|
||||
return transaction_id, HTML, form
|
||||
return params[ORDER_ID], HTML, form
|
||||
else:
|
||||
raise RuntimeError('sips/request returned -1: %s' % error)
|
||||
|
||||
|
@ -90,6 +103,6 @@ class Payment(PaymentCommon):
|
|||
form = urlparse.parse_qs(query_string)
|
||||
params = {'message': form[DATA]}
|
||||
result = self.execute('response', params)
|
||||
d = dict([p.split('=',1) for p in result])
|
||||
d = dict(zip(RESPONSE_PARAMS, result))
|
||||
LOGGER.debug('response contains fields %s' % d)
|
||||
return result.get(RESPONSE_CODE) == '00', form.get(TRANSACTION_ID), d
|
||||
return result.get(RESPONSE_CODE) == '00', form.get(ORDER_ID), d, None
|
||||
|
|
|
@ -11,12 +11,15 @@ import logging
|
|||
import Crypto.Cipher.DES
|
||||
from common import PaymentCommon, URL
|
||||
|
||||
__all__ = ['Payment']
|
||||
|
||||
KEY_DES_KEY = '\x45\x1f\xba\x4f\x4c\x3f\xd4\x97'
|
||||
IV = '\x30\x78\x30\x62\x2c\x30\x78\x30'
|
||||
REFERENCE = 'reference'
|
||||
ETAT = 'etat'
|
||||
ETAT_PAIEMENT_ACCEPTE = '1'
|
||||
SPCHECKOK = 'spcheckok'
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
def decrypt_ntkey(ntkey):
|
||||
key = binascii.unhexlify(ntkey.replace(' ',''))
|
||||
|
@ -49,6 +52,7 @@ LOGGER = logging.getLogger(__name__)
|
|||
|
||||
class Payment(PaymentCommon):
|
||||
def __init__(self, options):
|
||||
LOGGER.debug('initializing spplus payment with %s' % options)
|
||||
self.cle = options['cle']
|
||||
self.siret = options['siret']
|
||||
self.devise = '978'
|
||||
|
@ -56,6 +60,8 @@ class Payment(PaymentCommon):
|
|||
self.taxe = options.get('taxe', '0.00')
|
||||
|
||||
def request(self, montant, email=None, next_url=None):
|
||||
LOGGER.debug('requesting spplus payment with montant %s email=%s and \
|
||||
next_url=%s' % (montant, email, next_url))
|
||||
reference = self.transaction_id(20, ALPHANUM, 'spplus', self.siret)
|
||||
validite = dt.date.today()+dt.timedelta(days=1)
|
||||
validite = validite.strftime('%d/%m/%Y')
|
||||
|
@ -75,9 +81,12 @@ class Payment(PaymentCommon):
|
|||
or '?' in next_url:
|
||||
raise ValueError('next_url must be an absolute URL without parameters')
|
||||
fields['urlretour'] = next_url
|
||||
LOGGER.debug('sending fields %s' % fields)
|
||||
query = urllib.urlencode(fields)
|
||||
return reference, URL, '%s?%s&hmac=%s' % (SERVICE_URL, query,
|
||||
sign_ntkey_query(self.cle, query))
|
||||
url = '%s?%s&hmac=%s' % (SERVICE_URL, query, sign_ntkey_query(self.cle,
|
||||
query))
|
||||
LOGGER.debug('full url %s' % url)
|
||||
return reference, URL, url
|
||||
|
||||
def response(self, query_string):
|
||||
form = urlparse.parse_qs(query_string)
|
||||
|
|
|
@ -15,6 +15,7 @@ __all__ = ['Payment']
|
|||
PAYMENT_URL = "https://systempay.cyberpluspaiement.com/vads-payment/"
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
SERVICE_URL = '???'
|
||||
VADS_TRANS_DATE = 'vads_trans_date'
|
||||
|
||||
def isonow():
|
||||
return dt.datetime.now() \
|
||||
|
@ -97,7 +98,7 @@ PARAMETERS = [
|
|||
Parameter('signature', 'an', None, length=40),
|
||||
Parameter('vads_site_id', 'n', 02, length=8, needed=True),
|
||||
Parameter('vads_theme_config', 'ans', 32, max_length=255),
|
||||
Parameter('vads_trans_date', 'n', 04, length=14, needed=True,
|
||||
Parameter(VADS_TRANS_DATE, 'n', 04, length=14, needed=True,
|
||||
default=isonow),
|
||||
Parameter('vads_trans_id', 'n', 03, length=6, needed=True),
|
||||
Parameter('vads_validation_mode', 'n', 5, max_length=1, choices=('', 0, 1),
|
||||
|
@ -205,8 +206,8 @@ class Payment(PaymentCommon):
|
|||
if next_url:
|
||||
kwargs['vads_url_return'] = next_url
|
||||
|
||||
transaction_id = self.transaction_id(6, string.digits,
|
||||
'systempay', self.options['vads_site_id'])
|
||||
transaction_id = self.transaction_id(6,
|
||||
string.digits, 'systempay', self.options['vads_site_id'])
|
||||
kwargs['vads_trans_id'] = transaction_id
|
||||
fields = kwargs
|
||||
for parameter in PARAMETERS:
|
||||
|
@ -232,6 +233,7 @@ parameters received: %s' % (name, kwargs))
|
|||
parameter.ptype))
|
||||
fields['signature'] = self.signature(fields)
|
||||
url = '%s?%s' % (SERVICE_URL, urllib.urlencode(fields))
|
||||
transaction_id = '%s_%s' % (fields[VADS_TRANS_DATE], transaction_id)
|
||||
return transaction_id, URL, fields
|
||||
|
||||
def response(self, query_string):
|
||||
|
@ -239,27 +241,32 @@ parameters received: %s' % (name, kwargs))
|
|||
copy = fields.copy()
|
||||
if 'vads_auth_result' in fields:
|
||||
v = copy['vads_auth_result']
|
||||
copy['vads_auth_result'] = '%s: %s' % (v, AUTH_RESULT_MAP.get(v, 'Code inconnu'))
|
||||
ctx = (v, AUTH_RESULT_MAP.get(v, 'Code inconnu'))
|
||||
copy['vads_auth_result'] = '%s: %s' % ctx
|
||||
if 'vads_result' in copy:
|
||||
v = copy['vads_result']
|
||||
copy['vads_result'] = '%s: %s' % (v, RESULT_MAP.get(v, 'Code inconnu'))
|
||||
ctx = (v, RESULT_MAP.get(v, 'Code inconnu'))
|
||||
copy['vads_result'] = '%s: %s' % ctx
|
||||
if v == '30':
|
||||
if 'vads_extra_result' in fields:
|
||||
v = fields['vads_extra_result']
|
||||
if v.isdigit():
|
||||
for parameter in PARAMETERS:
|
||||
if int(v) == parameter.code:
|
||||
fields['vads_extra_result'] = 'erreur dans le champ %s' % parameter.name
|
||||
s ='erreur dans le champ %s' % parameter.name
|
||||
fields['vads_extra_result'] = s
|
||||
elif v in ('05', '00'):
|
||||
v = fields['vads_extra_result']
|
||||
fields['vads_extra_result'] = '%s: %s' % (v, EXTRA_RESULT_MAP.get(v, 'Code inconnu'))
|
||||
fields['vads_extra_result'] = '%s: %s' % (v,
|
||||
EXTRA_RESULT_MAP.get(v, 'Code inconnu'))
|
||||
LOGGER.debug('checking systempay response on:')
|
||||
for key in sorted(fields.keys):
|
||||
LOGGER.debug(' %s: %s' % (key, copy[key]))
|
||||
signature = self.signature(fields)
|
||||
result = signature == fields['signature']
|
||||
LOGGER.debug('signature check result: %s' % result)
|
||||
return result
|
||||
transaction_id = '%s_%s' % (copy[VADS_TRANS_DATE], copy[VADS_TRANS_ID])
|
||||
return result, transaction_id, copy, None
|
||||
|
||||
def signature(self, fields):
|
||||
LOGGER.debug('got fields %s to sign' % fields )
|
||||
|
|
Loading…
Reference in New Issue