Merge branch 'master' of git://github.com/strycore/eopayment
Conflicts: eopayment/systempayv2.py
This commit is contained in:
commit
a4b47d91f4
|
@ -5,8 +5,8 @@ import os.path
|
|||
|
||||
from common import URL, HTML
|
||||
|
||||
__all__ = [ 'Payment', 'URL', 'HTML', '__version__', 'SIPS', 'SYSTEMPAY',
|
||||
'SPPLUS', 'DUMMY', 'get_backend' ]
|
||||
__all__ = ['Payment', 'URL', 'HTML', '__version__', 'SIPS', 'SYSTEMPAY',
|
||||
'SPPLUS', 'DUMMY', 'get_backend']
|
||||
|
||||
__version__ = "0.0.19"
|
||||
|
||||
|
@ -17,11 +17,13 @@ SYSTEMPAY = 'systempayv2'
|
|||
SPPLUS = 'spplus'
|
||||
DUMMY = 'dummy'
|
||||
|
||||
|
||||
def get_backend(kind):
|
||||
'''Resolve a backend name into a module object'''
|
||||
module = __import__(kind, globals(), locals(), [])
|
||||
return module.Payment
|
||||
|
||||
|
||||
class Payment(object):
|
||||
'''
|
||||
Interface to credit card online payment servers of French banks. The
|
||||
|
@ -84,7 +86,7 @@ class Payment(object):
|
|||
- the first gives a string value to later match the payment with
|
||||
the invoice,
|
||||
- kind gives the type of the third value, payment.URL or
|
||||
payment.HTML,
|
||||
payment.HTML,
|
||||
- the third is the URL or the HTML form to contact the payment
|
||||
server, which must be sent to the customer browser.
|
||||
|
||||
|
@ -120,7 +122,7 @@ class Payment(object):
|
|||
query_string -- the URL encoded form-data from a GET or a POST
|
||||
|
||||
It returns a quadruplet of values:
|
||||
|
||||
|
||||
(result, transaction_id, bank_data, return_content)
|
||||
|
||||
- result is a boolean stating whether the transaction worked, use it
|
||||
|
@ -141,7 +143,7 @@ if __name__ == '__main__':
|
|||
logging.basicConfig(level=logging.DEBUG)
|
||||
spplus_options = {
|
||||
'cle': '58 6d fc 9c 34 91 9b 86 3f fd 64 \
|
||||
63 c9 13 4a 26 ba 29 74 1e c7 e9 80 79',
|
||||
63 c9 13 4a 26 ba 29 74 1e c7 e9 80 79',
|
||||
'siret': '00000000000001-01',
|
||||
}
|
||||
p = Payment(kind=SPPLUS, options=spplus_options)
|
||||
|
@ -149,7 +151,7 @@ if __name__ == '__main__':
|
|||
next_url='https://my-site.com')
|
||||
systempay_options = {
|
||||
'secrets': {
|
||||
'TEST': '1234567890123456',
|
||||
'TEST': '1234567890123456',
|
||||
'PRODUCTION': 'yyy'
|
||||
},
|
||||
'site_id': '00001234',
|
||||
|
@ -160,7 +162,7 @@ if __name__ == '__main__':
|
|||
print p.request('10.00', email='bob@example.com',
|
||||
next_url='https://my-site.com')
|
||||
|
||||
sips_options = { 'filepath': '/', 'binpath': os.path.dirname(__file__) }
|
||||
sips_options = {'filepath': '/', 'binpath': os.path.dirname(__file__)}
|
||||
p = Payment(kind=SIPS, options=sips_options)
|
||||
print p.request('10.00', email='bob@example.com',
|
||||
next_url='https://my-site.com')
|
||||
|
|
|
@ -4,8 +4,8 @@ import random
|
|||
import logging
|
||||
from datetime import date
|
||||
|
||||
__all__ = [ 'PaymentCommon', 'URL', 'HTML', 'RANDOM', 'RECEIVED', 'ACCEPTED',
|
||||
'PAID', 'ERROR' ]
|
||||
__all__ = ['PaymentCommon', 'URL', 'HTML', 'RANDOM', 'RECEIVED', 'ACCEPTED',
|
||||
'PAID', 'ERROR']
|
||||
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
@ -21,6 +21,7 @@ DENIED = 4
|
|||
CANCELED = 5
|
||||
ERROR = 99
|
||||
|
||||
|
||||
class PaymentResponse(object):
|
||||
'''Holds a generic view on the result of payment transaction response.
|
||||
|
||||
|
@ -85,9 +86,11 @@ class PaymentCommon(object):
|
|||
while True:
|
||||
parts = [RANDOM.choice(choices) for x in range(length)]
|
||||
id = ''.join(parts)
|
||||
name = '%s_%s_%s' % (str(date.today()), '-'.join(prefixes), str(id))
|
||||
name = '%s_%s_%s' % (str(date.today()),
|
||||
'-'.join(prefixes), str(id))
|
||||
try:
|
||||
fd=os.open(os.path.join(self.PATH, name), os.O_CREAT|os.O_EXCL)
|
||||
fd = os.open(os.path.join(self.PATH, name),
|
||||
os.O_CREAT | os.O_EXCL)
|
||||
except:
|
||||
raise
|
||||
else:
|
||||
|
|
|
@ -7,7 +7,6 @@ import logging
|
|||
import os
|
||||
import os.path
|
||||
import uuid
|
||||
import logging
|
||||
|
||||
from common import PaymentCommon, HTML, PaymentResponse
|
||||
from cb import CB_RESPONSE_CODES
|
||||
|
@ -29,26 +28,28 @@ contained in the middleware distribution file.
|
|||
|
||||
'''
|
||||
|
||||
__all__ = [ 'Payment' ]
|
||||
__all__ = ['Payment']
|
||||
|
||||
BINPATH = 'binpath'
|
||||
BINPATH = 'binpath'
|
||||
PATHFILE = 'pathfile'
|
||||
AUTHORISATION_ID = 'authorisation_id'
|
||||
REQUEST_VALID_PARAMS = ['merchant_id', 'merchant_country', 'amount',
|
||||
'currency_code', 'pathfile', 'normal_return_url', 'cancel_return_url',
|
||||
'automatic_response_url', 'language', 'payment_means', 'header_flag',
|
||||
'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']
|
||||
'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',
|
||||
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', ]
|
||||
'merchant_language', 'language', 'customer_id', 'order_id',
|
||||
'customer_email', 'customer_ip_address', 'capture_day', 'capture_mode',
|
||||
'data', ]
|
||||
|
||||
DATA = 'DATA'
|
||||
PARAMS = 'params'
|
||||
|
@ -58,9 +59,9 @@ ORDER_ID = 'order_id'
|
|||
MERCHANT_ID = 'merchant_id'
|
||||
RESPONSE_CODE = 'response_code'
|
||||
|
||||
DEFAULT_PARAMS = { 'merchant_id': '014213245611111',
|
||||
'merchant_country': 'fr',
|
||||
'currency_code': '978' }
|
||||
DEFAULT_PARAMS = {'merchant_id': '014213245611111',
|
||||
'merchant_country': 'fr',
|
||||
'currency_code': '978'}
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -80,40 +81,47 @@ FINAREF_BANK_RESPONSE_CODE = {
|
|||
'05': 'Compte / Porteur avec statut bloqué ou invalide',
|
||||
'11': 'Compte / porteur inconnu',
|
||||
'16': 'Provision insuffisante',
|
||||
'20': 'Commerçant invalide - Code monnaie incorrect - Opération commerciale inconnue - Opération commerciale invalide',
|
||||
'20': 'Commerçant invalide - Code monnaie incorrect - ' + \
|
||||
'Opération commerciale inconnue - Opération commerciale invalide',
|
||||
'80': 'Transaction approuvée avec dépassement',
|
||||
'81': 'Transaction approuvée avec augmentation capital',
|
||||
'82': 'Transaction approuvée NPAI',
|
||||
'83': 'Compte / porteur invalide',
|
||||
}
|
||||
|
||||
|
||||
class Payment(PaymentCommon):
|
||||
description = {
|
||||
'caption': 'SIPS',
|
||||
'parameters': [{
|
||||
'name': 'merchand_id',
|
||||
},
|
||||
{ 'name': 'merchant_country', },
|
||||
{ 'name': 'currency_code', }
|
||||
{'name': 'merchant_country', },
|
||||
{'name': 'currency_code', }
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
def __init__(self, options, logger=LOGGER):
|
||||
self.options = options
|
||||
self.logger = logger
|
||||
logger.debug('initializing sips payment class with %s' % options)
|
||||
self.logger.debug('initializing sips payment class with %s' % options)
|
||||
|
||||
def execute(self, executable, params):
|
||||
if PATHFILE in self.options:
|
||||
params[PATHFILE] = self.options[PATHFILE]
|
||||
executable = os.path.join(self.options[BINPATH], executable)
|
||||
args = [executable] + [ "%s=%s" % p for p in params.iteritems() ]
|
||||
executable = os.path.join(self.options.pop(BINPATH), executable)
|
||||
args = [executable] + ["%s=%s" % p for p in params.iteritems()]
|
||||
self.logger.debug('executing %s' % args)
|
||||
result, _ = subprocess.Popen(args, executable=executable,
|
||||
result,_ = subprocess.Popen(' '.join(args),
|
||||
stdout=subprocess.PIPE, shell=True).communicate()
|
||||
try:
|
||||
if result[0] == '!':
|
||||
result = result[1:]
|
||||
if result[-1] == '!':
|
||||
result = result[:-1]
|
||||
except IndexError:
|
||||
raise ValueError("Invalid response", result)
|
||||
return False
|
||||
result = result.split('!')
|
||||
self.logger.debug('got response %s' % result)
|
||||
return result
|
||||
|
@ -129,12 +137,13 @@ 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)
|
||||
params[ORDER_ID] = str(uuid.uuid4()).replace('-', '')
|
||||
params['amount'] = str(int(Decimal(amount) * 100))
|
||||
if email:
|
||||
params['customer_email'] = email
|
||||
if next_url:
|
||||
params['normal_return_url'] = next_url
|
||||
params.pop('binpath')
|
||||
code, error, form = self.execute('request', params)
|
||||
if int(code) == 0:
|
||||
return params[ORDER_ID], HTML, form
|
||||
|
@ -143,7 +152,7 @@ class Payment(PaymentCommon):
|
|||
|
||||
def response(self, query_string):
|
||||
form = urlparse.parse_qs(query_string)
|
||||
params = {'message': form[DATA]}
|
||||
params = {'message': form[DATA][0]}
|
||||
result = self.execute('response', params)
|
||||
d = dict(zip(RESPONSE_PARAMS, result))
|
||||
# The reference identifier for the payment is the authorisation_id
|
||||
|
@ -153,7 +162,7 @@ class Payment(PaymentCommon):
|
|||
response_code_msg = CB_BANK_RESPONSE_CODES.get(d.get(RESPONSE_CODE))
|
||||
response = PaymentResponse(
|
||||
result=response_result,
|
||||
signed_result=response_result,
|
||||
signed=response_result,
|
||||
bank_data=d,
|
||||
order_id=d.get(ORDER_ID),
|
||||
transaction_id=d.get(AUTHORISATION_ID),
|
||||
|
|
|
@ -33,12 +33,14 @@ VADS_TRANS_ID = 'vads_trans_id'
|
|||
SIGNATURE = 'signature'
|
||||
VADS_TRANS_ID = 'vads_trans_id'
|
||||
|
||||
|
||||
def isonow():
|
||||
return dt.datetime.utcnow() \
|
||||
.isoformat('T') \
|
||||
.replace('-','') \
|
||||
.replace('T','') \
|
||||
.replace(':','')[:14]
|
||||
.replace('-', '') \
|
||||
.replace('T', '') \
|
||||
.replace(':', '')[:14]
|
||||
|
||||
|
||||
class Parameter:
|
||||
def __init__(self, name, ptype, code, max_length=None, length=None,
|
||||
|
@ -64,27 +66,29 @@ class Parameter:
|
|||
return False
|
||||
if value == '':
|
||||
return True
|
||||
value = str(value).replace('.','')
|
||||
value = str(value).replace('.', '')
|
||||
if self.ptype == 'n':
|
||||
return value.isdigit()
|
||||
elif self.ptype == 'an':
|
||||
return value.isalnum()
|
||||
elif self.ptype == 'an-':
|
||||
return value.replace('-','').isalnum()
|
||||
return value.replace('-', '').isalnum()
|
||||
elif self.ptype == 'an;':
|
||||
return value.replace(';','').isalnum()
|
||||
return value.replace(';', '').isalnum()
|
||||
return True
|
||||
|
||||
|
||||
PARAMETERS = [
|
||||
# amount as euro cents
|
||||
Parameter('vads_action_mode', None, 47, needed=True,
|
||||
default='INTERACTIVE', choices=('SILENT','INTERACTIVE')),
|
||||
default='INTERACTIVE', choices=('SILENT', 'INTERACTIVE')),
|
||||
Parameter('vads_amount', 'n', 9, max_length=12, needed=True),
|
||||
Parameter('vads_capture_delay', 'n', 6, max_length=3, default=''),
|
||||
Parameter('vads_contrib', 'ans', 31, max_length=255, default='eopayment'),
|
||||
Parameter('vads_contrib', 'ans', 31, max_length=255,
|
||||
default='eopayment'),
|
||||
# defaut currency = EURO, norme ISO4217
|
||||
Parameter('vads_currency', 'n', 10, length=3, default=978, needed=True),
|
||||
Parameter('vads_currency', 'n', 10, length=3, default=978,
|
||||
needed=True),
|
||||
Parameter('vads_cust_address', 'an', 19, max_length=255),
|
||||
# code ISO 3166
|
||||
Parameter('vads_cust_country', 'a', 22, length=2, default='FR'),
|
||||
|
@ -116,9 +120,9 @@ PARAMETERS = [
|
|||
'PAYPAL_SB, PAYSAFECARD, VISA')),
|
||||
# must be SINGLE or MULTI with parameters
|
||||
Parameter('vads_payment_config', '', 07, default='SINGLE',
|
||||
choices=('SINGLE','MULTI'), needed=True),
|
||||
choices=('SINGLE', 'MULTI'), needed=True),
|
||||
Parameter('vads_return_mode', None, 48, default='GET',
|
||||
choices=('','NONE','POST','GET')),
|
||||
choices=('', 'NONE', 'POST', 'GET')),
|
||||
Parameter('signature', 'an', None, length=40),
|
||||
Parameter('vads_site_id', 'n', 02, length=8, needed=True,
|
||||
description=_(u'Identifiant de la boutique')),
|
||||
|
@ -126,8 +130,8 @@ PARAMETERS = [
|
|||
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),
|
||||
default=''),
|
||||
Parameter('vads_validation_mode', 'n', 5, max_length=1,
|
||||
choices=('', 0, 1), default=''),
|
||||
Parameter('vads_version', 'an', 01, default='V2', needed=True,
|
||||
choices=('V2',)),
|
||||
Parameter('vads_url_success', 'ans', 24, max_length=127),
|
||||
|
@ -139,7 +143,8 @@ PARAMETERS = [
|
|||
Parameter('vads_user_info', 'ans', 61, max_length=255),
|
||||
Parameter('vads_contracts', 'ans', 62, max_length=255),
|
||||
]
|
||||
PARAMETER_MAP = dict(((parameter.name, parameter) for parameter in PARAMETERS ))
|
||||
PARAMETER_MAP = dict(((parameter.name,
|
||||
parameter) for parameter in PARAMETERS))
|
||||
|
||||
AUTH_RESULT_MAP = CB_RESPONSE_CODES
|
||||
|
||||
|
@ -165,15 +170,17 @@ liste blanche du commerçant",
|
|||
d'un des contrôles locaux",
|
||||
}
|
||||
|
||||
|
||||
def add_vads(kwargs):
|
||||
new_vargs={}
|
||||
new_vargs = {}
|
||||
for k, v in kwargs.iteritems():
|
||||
if k.startswith('vads_'):
|
||||
new_vargs[k] = v
|
||||
else:
|
||||
new_vargs['vads_'+k] = v
|
||||
new_vargs['vads_' + k] = v
|
||||
return new_vargs
|
||||
|
||||
|
||||
def check_vads(kwargs, exclude=[]):
|
||||
for parameter in PARAMETERS:
|
||||
name = parameter.name
|
||||
|
@ -184,13 +191,14 @@ def check_vads(kwargs, exclude=[]):
|
|||
name, kwargs[name],
|
||||
parameter.ptype))
|
||||
|
||||
|
||||
class Payment(PaymentCommon):
|
||||
'''
|
||||
'''
|
||||
Produce request for and verify response from the SystemPay payment
|
||||
gateway.
|
||||
|
||||
>>> gw =Payment(dict(secret_test='xxx', secret_production='yyyy' site_id=123,
|
||||
ctx_mode='PRODUCTION')
|
||||
>>> gw =Payment(dict(secret_test='xxx', secret_production='yyyy',
|
||||
site_id=123, ctx_mode='PRODUCTION'))
|
||||
>>> print gw.request(100)
|
||||
('20120525093304_188620',
|
||||
'https://paiement.systempay.fr/vads-payment/?vads_url_return=http%3A%2F%2Furl.de.retour%2Fretour.php&vads_cust_country=FR&vads_site_id=&vads_payment_config=SINGLE&vads_trans_id=188620&vads_action_mode=INTERACTIVE&vads_contrib=eopayment&vads_page_action=PAYMENT&vads_trans_date=20120525093304&vads_ctx_mode=TEST&vads_validation_mode=&vads_version=V2&vads_payment_cards=&signature=5d412498ab523627ec5730a09118f75afa602af5&vads_language=fr&vads_capture_delay=&vads_currency=978&vads_amount=100&vads_return_mode=NONE',
|
||||
|
@ -207,41 +215,37 @@ class Payment(PaymentCommon):
|
|||
|
||||
'''
|
||||
description = {
|
||||
'caption': 'SystemPay, système de paiment du groupe BPCE',
|
||||
'parameters': [
|
||||
{ 'name': 'service_url',
|
||||
'default': SERVICE_URL,
|
||||
'caption': _(u'URL du service de paiment'),
|
||||
'help_text': _(u'ne pas modifier si vous ne savez pas'),
|
||||
'validation': lambda x: x.startswith('http'),
|
||||
'required': True,
|
||||
},
|
||||
{ 'name': 'secret_test',
|
||||
'caption': _(u'Secret pour la configuration de TEST'),
|
||||
'validation': str.isdigit,
|
||||
'required': True,
|
||||
},
|
||||
{ 'name': 'secret_production',
|
||||
'caption': _(u'Secret pour la configuration de PRODUCTION'),
|
||||
'validation': str.isdigit,
|
||||
},
|
||||
]
|
||||
'caption': 'SystemPay, système de paiment du groupe BPCE',
|
||||
'parameters': [
|
||||
{'name': 'service_url',
|
||||
'default': SERVICE_URL,
|
||||
'caption': _(u'URL du service de paiment'),
|
||||
'help_text': _(u'ne pas modifier si vous ne savez pas'),
|
||||
'validation': lambda x: x.startswith('http'),
|
||||
'required': True, },
|
||||
{'name': 'secret_test',
|
||||
'caption': _(u'Secret pour la configuration de TEST'),
|
||||
'validation': str.isdigit,
|
||||
'required': True, },
|
||||
{'name': 'secret_production',
|
||||
'caption': _(u'Secret pour la configuration de PRODUCTION'),
|
||||
'validation': str.isdigit, },
|
||||
]
|
||||
}
|
||||
|
||||
for name in ('vads_ctx_mode', VADS_SITE_ID, 'vads_order_info', 'vads_order_info2',
|
||||
'vads_order_info3', 'vads_payment_cards', 'vads_payment_config'):
|
||||
for name in ('vads_ctx_mode', VADS_SITE_ID, 'vads_order_info',
|
||||
'vads_order_info2', 'vads_order_info3',
|
||||
'vads_payment_cards', 'vads_payment_config'):
|
||||
parameter = PARAMETER_MAP[name]
|
||||
x = { 'name': name,
|
||||
'caption': parameter.description or name,
|
||||
'validation': parameter.check_value,
|
||||
'default': parameter.default,
|
||||
'required': parameter.needed,
|
||||
'help_text': parameter.help_text,
|
||||
'max_length': parameter.max_length
|
||||
}
|
||||
x = {'name': name,
|
||||
'caption': parameter.description or name,
|
||||
'validation': parameter.check_value,
|
||||
'default': parameter.default,
|
||||
'required': parameter.needed,
|
||||
'help_text': parameter.help_text,
|
||||
'max_length': parameter.max_length}
|
||||
description['parameters'].append(x)
|
||||
|
||||
|
||||
def __init__(self, options, logger=LOGGER):
|
||||
self.service_url = options.pop('service_url', SERVICE_URL)
|
||||
self.secret_test = options.pop('secret_test')
|
||||
|
@ -326,7 +330,7 @@ class Payment(PaymentCommon):
|
|||
if v.isdigit():
|
||||
for parameter in PARAMETERS:
|
||||
if int(v) == parameter.code:
|
||||
s ='erreur dans le champ %s' % parameter.name
|
||||
s = 'erreur dans le champ %s' % parameter.name
|
||||
copy[VADS_EXTRA_RESULT] = s
|
||||
bank_status.append(copy[VADS_EXTRA_RESULT])
|
||||
elif v in ('05', '00'):
|
||||
|
@ -362,10 +366,10 @@ class Payment(PaymentCommon):
|
|||
return response
|
||||
|
||||
def signature(self, fields):
|
||||
self.logger.debug('got fields %s to sign' % fields )
|
||||
ordered_keys = sorted([ key for key in fields.keys() if key.startswith('vads_') ])
|
||||
self.logger.debug('got fields %s to sign' % fields)
|
||||
ordered_keys = sorted([key for key in fields.keys() if key.startswith('vads_')])
|
||||
self.logger.debug('ordered keys %s' % ordered_keys)
|
||||
ordered_fields = [ str(fields[key]) for key in ordered_keys]
|
||||
ordered_fields = [str(fields[key]) for key in ordered_keys]
|
||||
secret = getattr(self, 'secret_%s' % fields['vads_ctx_mode'].lower())
|
||||
signed_data = '+'.join(ordered_fields)
|
||||
signed_data = '%s+%s' % (signed_data, secret)
|
||||
|
@ -377,7 +381,7 @@ class Payment(PaymentCommon):
|
|||
if __name__ == '__main__':
|
||||
p = Payment(dict(
|
||||
secret_test='',
|
||||
site_id='',
|
||||
site_id='',
|
||||
ctx_mode='TEST'))
|
||||
print p.request(100, vads_url_return='http://url.de.retour/retour.php')
|
||||
qs = 'vads_amount=100&vads_auth_mode=FULL&vads_auth_number=767712&vads_auth_result=00&vads_capture_delay=0&vads_card_brand=CB&vads_card_number=497010XXXXXX0000&vads_payment_certificate=9da32cc109882089e1b3fb80888ebbef072f70b7&vads_ctx_mode=TEST&vads_currency=978&vads_effective_amount=100&vads_site_id=&vads_trans_date=20120529132547&vads_trans_id=620594&vads_validation_mode=0&vads_version=V2&vads_warranty_result=NO&vads_payment_src=&vads_order_id=---&vads_cust_country=FR&vads_contrib=eopayment&vads_contract_used=2334233&vads_expiry_month=6&vads_expiry_year=2013&vads_pays_ip=FR&vads_identifier=&vads_subscription=&vads_threeds_enrolled=&vads_threeds_cavv=&vads_threeds_eci=&vads_threeds_xid=&vads_threeds_cavvAlgorithm=&vads_threeds_status=&vads_threeds_sign_valid=&vads_threeds_error_code=&vads_threeds_exit_status=&vads_result=00&vads_extra_result=&vads_card_country=FR&vads_language=fr&vads_action_mode=INTERACTIVE&vads_page_action=PAYMENT&vads_payment_config=SINGLE&signature=9c4f2bf905bb06b008b07090905adf36638d8ece&'
|
||||
|
|
Loading…
Reference in New Issue