This repository has been archived by the owner on Feb 10, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathpayu.py
147 lines (122 loc) · 4.79 KB
/
payu.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
from hashlib import md5
from functools import partialmethod
import requests
from payu.helpers import clean_cc_number
class ImproperlyConfigured(Exception):
pass
class PayU:
defaults = {
'PAYMENT_URL': "https://stg.api.payulatam.com/payments-api/4.0/service.cgi",
'QUERY_URL': 'https://stg.api.payulatam.com/reports-api/4.0/service.cgi',
"API_KEY": None,
"API_LOGIN": None,
'ACCOUNT_ID': None,
'MERCHANT_ID': None,
'TEST': False,
'LANG': 'es',
"VERIFY_SSL": True,
}
def __init__(self, **conf):
self.configure(**conf)
def configure(self, **conf):
self.config = {}
self.config.update(self.defaults)
for key, value in conf.items():
self.config[key.upper()] = value
def get_headers(self):
return {'Accept': 'application/json'}
def build_request_base(self, cmd):
request = {}
request['test'] = self.config['TEST']
request['language'] = self.config['LANG']
request['command'] = cmd
request['merchant'] = {
"apiLogin": self.config['API_LOGIN'],
"apiKey": self.config['API_KEY']
}
return request
def build_signature(self, order, sep='~', algorithm='md5'):
self.validate_signature(order)
ref = order.get('referenceCode')
value = str(order.get('value'))
currency = order.get('currency')
msg = sep.join([self.config['API_KEY'],
self.config['MERCHANT_ID'],
ref,
value,
currency]).encode('ascii')
return md5(msg).hexdigest()
def post(self, request_data, url='PAYMENT_URL'):
headers = self.get_headers()
resp = requests.post(self.config.get(url),
json=request_data,
verify=self.config['VERIFY_SSL'],
headers=headers)
return resp
def tokenize(self, cc_data):
self.validate_cc(cc_data)
cc_data['number'] = clean_cc_number(cc_data['number'])
cmd = 'CREATE_TOKEN'
request_data = self.build_request_base(cmd)
request_data['creditCardToken'] = cc_data
return self.post(request_data)
def build_order(self, order):
order['accountId'] = self.config['ACCOUNT_ID']
order['signature'] = self.build_signature(order)
value = order.pop('value', None)
currency = order.pop('currency', None)
if 'language' not in order:
order['language'] = self.config['LANG']
if 'additionalValues' not in order:
order['additionalValues'] = {
'TX_VALUE': {
'value': value,
'currency': currency
}
}
return order
def build_transaction(self, order, payment_method, payment_country, **kwargs):
t = {}
t['paymentMethod'] = payment_method
t['paymentCountry'] = payment_country
if 'credit_card' in kwargs:
cc = kwargs.get('credit_card')
self.validate_cc(cc)
t['creditCard'] = cc
elif 'credit_card_token' in kwargs:
t['creditCardTokenId'] = kwargs.pop('credit_card_token')
if 'type' not in 'kwargs':
t['type'] = 'AUTHORIZATION_AND_CAPTURE'
# TODO: Support multiple orders in one transaction
t['order'] = order
t.update(kwargs.get('additional_data'))
return t
def submit_transaction(self, transaction):
cmd = 'SUBMIT_TRANSACTION'
request_data = self.build_request_base(cmd)
request_data['transaction'] = transaction
return self.post(request_data)
def query_transaction(self, reference_code):
cmd = 'ORDER_DETAIL_BY_REFERENCE_CODE'
request_data = self.build_request_base(cmd)
request_data['details'] = {
'referenceCode': reference_code
}
return self.post(request_data, url='QUERY_URL')
def validate(self, data, fields=[]):
errors = []
for field in fields:
if field not in data:
errors.append(field)
if errors:
raise ImproperlyConfigured('Missing attributes: %s' % ', '.join(errors))
validate_cc = partialmethod(validate,
fields=['payerId',
'name',
'paymentMethod',
'number',
'expirationDate'])
validate_signature = partialmethod(validate,
fields=['referenceCode',
'value',
'currency'])