Skip to content

Commit 4214e6e

Browse files
committed
v.1.0.0
1 parent eb4a2fd commit 4214e6e

6 files changed

Lines changed: 250 additions & 0 deletions

File tree

cgi-bin/UnitPay.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/usr/bin/env python3
2+
3+
import urllib.parse
4+
import hashlib
5+
import os
6+
from urllib.request import urlopen
7+
import json
8+
import re
9+
import copy
10+
from unitpay_lib import *
11+
12+
class UnitPay:
13+
formUrl = 'https://unitpay.ru/pay/'
14+
apiUrl = 'https://unitpay.ru/api';
15+
secretKey = ''
16+
supportedUnitpayMethods = ['initPayment', 'getPayment']
17+
requiredUnitpayMethodsParams = {'initPayment' : ['desc', 'account', 'sum'],'getPayment' : ['paymentId']}
18+
supportedPartnerMethods = ['check', 'pay', 'error'];
19+
supportedUnitpayIp = [
20+
'31.186.100.49',
21+
'178.132.203.105',
22+
'52.29.152.23',
23+
'52.19.56.234',
24+
'127.0.0.1' # for debug
25+
];
26+
def __init__(self, secretKey):
27+
self.secretKey = secretKey
28+
def form( self, publicKey, summ, account, desc, currency='RUB', locale='ru'):
29+
params = {
30+
'account' : account,
31+
'currency' : currency,
32+
'desc' : desc,
33+
'sum' : summ
34+
}
35+
params['signature'] = self.getSignature(params)
36+
params['locale'] = locale
37+
38+
return self.formUrl + publicKey + '?' + urllib.parse.urlencode(params)
39+
40+
def getSignature( self, params, method = None ):
41+
paramss = copy.copy(params)
42+
if 'signature' in paramss:
43+
del paramss['signature']
44+
if 'sign' in paramss:
45+
del paramss['sign']
46+
paramss = ksort(paramss)
47+
paramss.append([0,self.secretKey])
48+
if method:
49+
paramss.insert(0,['method',method])
50+
51+
#list of dict to str
52+
res_p = []
53+
for p in paramss:
54+
res_p.append(str(p[1]))
55+
strr = '{up}'.join(res_p)
56+
strr = strr.encode('utf-8')
57+
h = hashlib.sha256(strr).hexdigest()
58+
return h
59+
def checkHandlerRequest(self):
60+
ip = os.environ.get('REMOTE_ADDR', '')
61+
qs = os.environ.get('QUERY_STRING', '')
62+
val = urllib.parse.parse_qs(qs)
63+
params = parseParams(val);
64+
method = val['method'][0]
65+
if not 'method' in val:
66+
raise Exception('Method is null')
67+
if not params:
68+
raise Exception('Params is null')
69+
if not method in self.supportedPartnerMethods:
70+
raise Exception('Method is not supported')
71+
signature = self.getSignature(params, method);
72+
if not 'signature' in params:
73+
raise Exception('signature params is null')
74+
if params['signature'] != signature:
75+
raise Exception('Wrong signature')
76+
if not ip in self.supportedUnitpayIp:
77+
raise Exception ('IP address error')
78+
return True
79+
def getErrorHandlerResponse(self, message):
80+
return json.dumps({'error': {'message': message}})
81+
def getSuccessHandlerResponse(self, message):
82+
return json.dumps({'result': {'message': message}})
83+
def api(self, method, params = {}):
84+
if (not(method in self.supportedUnitpayMethods)):
85+
raise Exception('Method is not supported')
86+
for rParam in self.requiredUnitpayMethodsParams[method]:
87+
if (not rParam in params):
88+
raise Exception('Param ' + rParam + ' is null')
89+
params['secretKey'] = self.secretKey
90+
requestUrl = self.apiUrl + '?method=' + method + '&' + self.insertUrlEncode('params', params)
91+
response = urlopen(requestUrl)
92+
data = response.read().decode('utf-8')
93+
jsons = json.loads(data)
94+
return jsons
95+
def insertUrlEncode(self, inserted, params):
96+
result = ''
97+
first = True
98+
for p in params:
99+
if first:
100+
first = False
101+
else:
102+
result += '&'
103+
result += inserted + '[' + p + ']=' + str(params[p])
104+
return result

cgi-bin/sample/handler.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/env python3
2+
3+
from orderInfo import *
4+
5+
import os, sys, inspect
6+
sys.path.append(os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"../"))))
7+
8+
from unitpay_lib import *
9+
from UnitPay import *
10+
11+
#print ('Content-Type: text/html')
12+
print ('Content-Type: application/json')
13+
print()
14+
15+
unitpay = UnitPay( secretKey )
16+
try:
17+
18+
unitpay.checkHandlerRequest()
19+
20+
qs = os.environ.get('QUERY_STRING', '')
21+
val = urllib.parse.parse_qs(qs)
22+
params = parseParams(val);
23+
method = val['method'][0]
24+
25+
if (float(params['orderSum']) != float(orderSum) or
26+
params['orderCurrency'] != orderCurrency or
27+
params['account'] != orderId or
28+
params['projectId'].strip() != str(projectId)):
29+
raise Exception('Order validation Error')
30+
31+
if (method == 'check'):
32+
print(unitpay.getSuccessHandlerResponse('Check Success. Ready to pay.'));
33+
elif (method == 'pay'):
34+
print (unitpay.getSuccessHandlerResponse('Pay Success'));
35+
elif (method == 'error'):
36+
print (unitpay.getSuccessHandlerResponse('Error logged'));
37+
elif (method == 'refund'):
38+
print (unitpay.getSuccessHandlerResponse('Order canceled'));
39+
except Exception as e:
40+
s = str(e)
41+
print (unitpay.getErrorHandlerResponse(s))
42+

cgi-bin/sample/initPaymentApi.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env python3
2+
3+
import os, sys, inspect
4+
sys.path.append(os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"../"))))
5+
6+
from orderInfo import *
7+
from UnitPay import *
8+
9+
unitPay = UnitPay( secretKey )
10+
11+
try:
12+
response = unitPay.api('initPayment', {
13+
'account' : orderId,
14+
'desc' : orderDesc,
15+
'sum' : orderSum,
16+
'paymentType' : 'yandex',
17+
'currency' : orderCurrency,
18+
'projectId' : projectId,
19+
});
20+
if ('result' in response) and ('type' in response['result']):
21+
if (response['result']['type'] == 'redirect'):
22+
redirectUrl = response['result']['redirectUrl']
23+
paymentId = response['result']['paymentId']
24+
redirect(redirectUrl)
25+
elif (response['result']['type'] == 'invoice'):
26+
receiptUrl = response['result']['receiptUrl']
27+
paymentId = response['result']['paymentId']
28+
invoiceId = response['result']['invoiceId']
29+
redirect(receiptUrl)
30+
elif ('error' in response) and ('message' in response['error']):
31+
error = response['error']['message']
32+
print ('Content-Type: text/html; charset=UTF-8')
33+
print()
34+
print ('error: ' + error)
35+
36+
except Exception as e:
37+
s = str(e)
38+
print ('Content-Type: text/html; charset=UTF-8')
39+
print()
40+
print (s)
41+
42+
def redirect(redirectUrl):
43+
print ('Content-Type: text/html')
44+
print ('Location: ' + redirectUrl)
45+
print ('')# HTTP says you have to have a blank line between headers and content
46+
print ('<html>')
47+
print (' <head>')
48+
print (' <meta http-equiv="refresh" content="0;url=' + redirectUrl + '" />')
49+
print (' <title>You are going to be redirected</title>')
50+
print (' </head>' )
51+
print (' <body>')
52+
print (' Redirecting... <a href="' + redirectUrl + '">Click here if you are not redirected</a>')
53+
print (' </body>')
54+
print ('</html>')

cgi-bin/sample/initPaymentForm.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env python3
2+
3+
import os, sys, inspect
4+
sys.path.append(os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"../"))))
5+
6+
from orderInfo import *
7+
from UnitPay import *
8+
9+
unitpay = UnitPay( secretKey )
10+
redirectUrl = unitpay.form( publicId, orderSum, orderId, orderDesc, orderCurrency )
11+
12+
print ('Content-Type: text/html')
13+
print ('Location: ' + redirectUrl)
14+
print ('')# HTTP says you have to have a blank line between headers and content
15+
print ('<html>')
16+
print (' <head>')
17+
print (' <meta http-equiv="refresh" content="0;url=' + redirectUrl + '" />')
18+
print (' <title>You are going to be redirected</title>')
19+
print (' </head>' )
20+
print (' <body>')
21+
print (' Redirecting... <a href="' + redirectUrl + '">Click here if you are not redirected</a>')
22+
print (' </body>')
23+
print ('</html>')

cgi-bin/sample/orderInfo.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
# Project Data
3+
projectId = 9922
4+
secretKey = 'b444b19ef5395455ebbr2ee60576d3fc'
5+
publicId = '9922-2bfc2'
6+
7+
# My item Info
8+
itemName = 'Iphone 6 Skin Cover'
9+
10+
# My Order Data
11+
orderId = 'a183f94-1434-1e44'
12+
orderSum = 10
13+
orderDesc = 'Payment for item "' + itemName + '"'
14+
orderCurrency = 'RUB'

cgi-bin/unitpay_lib.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import re
2+
3+
#parse "params" in request
4+
def parseParams( s ):
5+
params = {}
6+
for v in s:
7+
if re.search('params', v):
8+
p = v[len('params['):-1]
9+
params[p] = s[v][0]
10+
return params
11+
#sorted by key
12+
def ksort(d):
13+
return [[k,d[k]] for k in sorted(d.keys())]

0 commit comments

Comments
 (0)