1+ #!/usr/bin/env python3
2+
3+ import urllib .parse
4+ import hashlib
5+ from urllib .request import urlopen
6+ import json
7+ import re
8+ import copy
9+ from flask import request
10+
11+
12+ class UnitPay (object ):
13+ secretKey = ''
14+ supportedUnitpayMethods = ['initPayment' , 'getPayment' ]
15+ requiredUnitpayMethodsParams = {'initPayment' : ['desc' , 'account' , 'sum' ], 'getPayment' : ['paymentId' ]}
16+ supportedPartnerMethods = ['check' , 'pay' , 'error' ]
17+ supportedUnitpayIp = [
18+ '31.186.100.49' ,
19+ '178.132.203.105' ,
20+ '52.29.152.23' ,
21+ '52.19.56.234' ,
22+ '127.0.0.1' # for debug
23+ ]
24+
25+ def __init__ (self , secret_key ):
26+ self .formUrl = 'https://unitpay.ru/pay/'
27+ self .apiUrl = 'https://unitpay.ru/api/'
28+ self .secretKey = secret_key
29+
30+ def form (self , public_key , summ , account , desc , currency = 'RUB' , locale = 'ru' , customer_email = None ):
31+ params = {'account' : account , 'currency' : currency , 'desc' : desc , 'sum' : summ , 'customerEmail' : customer_email }
32+ params ['signature' ] = self .get_signature (params )
33+ params ['locale' ] = locale
34+ print (self .generate_signature (account , currency , desc , summ , self .secretKey ))
35+ return self .formUrl + public_key + '?' + urllib .parse .urlencode (params )
36+
37+ @staticmethod
38+ def generate_signature (account : str , currency : str , desc : str , sum : str , secret_key : str ):
39+ signature = account + '{up}' + currency + '{up}' + desc + '{up}' + sum + '{up}' + secret_key
40+ signature = signature .encode ('utf-8' )
41+ return hashlib .sha256 (signature ).hexdigest ()
42+
43+ @staticmethod
44+ def generate_signature_output (account : str , currency : str , desc : str , sum : str , secret_key : str ):
45+ signature = account + '{up}' + currency + '{up}' + desc + '{up}' + sum + '{up}' + secret_key
46+ signature = signature .encode ('utf-8' )
47+ return hashlib .sha256 (signature ).hexdigest ()
48+
49+ def get_signature (self , params ):
50+ paramss = copy .copy (params )
51+
52+ if 'params[signature]' in paramss :
53+ paramss .pop ('params[signature]' )
54+ if 'params[sign]' in paramss :
55+ paramss .pop ('params[sign]' )
56+
57+ if 'customerEmail' in paramss :
58+ paramss .pop ('customerEmail' )
59+
60+ paramss = ksort (paramss )
61+ paramss .append ([0 , self .secretKey ])
62+
63+ # list of dict to str
64+ res_p = []
65+ for p in paramss :
66+ res_p .append (str (p [1 ]))
67+ strr = '{up}' .join (res_p )
68+ strr = strr .encode ('utf-8' )
69+ h = hashlib .sha256 (strr ).hexdigest ()
70+ return h
71+
72+ def check_handler_request (self ):
73+ ip = self .get_ip ()
74+
75+ params = {}
76+ for v in request .args .lists ():
77+ params [str (v [0 ])] = request .args .get (v [0 ])
78+
79+ if not 'method' in params :
80+ raise Exception ('Method is null' )
81+
82+ if not params :
83+ raise Exception ('Params is null' )
84+
85+ if not params ['method' ] in self .supportedPartnerMethods :
86+ raise Exception ('Method is not supported' )
87+
88+ if not 'params[signature]' in params :
89+ raise Exception ('signature params is null' )
90+
91+ if params ['params[signature]' ] != self .get_signature (params ):
92+ raise Exception ('Wrong signature' )
93+
94+ if not ip in self .supportedUnitpayIp :
95+ raise Exception ('IP address error' )
96+
97+ return True
98+
99+ @staticmethod
100+ def get_ip ():
101+ if not request .headers .getlist ("X-Forwarded-For" ):
102+ ip = request .remote_addr
103+ else :
104+ ips = request .headers .getlist ("X-Forwarded-For" )[0 ].split ("," )
105+ if ips [0 ] is not None :
106+ ip = ips [0 ]
107+ else :
108+ ip = request .headers .getlist ("X-Forwarded-For" )[0 ]
109+ return ip
110+
111+ @staticmethod
112+ def get_error_handler_response (message ):
113+ return json .dumps ({'error' : {'message' : message }})
114+
115+ @staticmethod
116+ def get_success_handler_response (message ):
117+ return json .dumps ({'result' : {'message' : message }})
118+
119+ def api (self , method , params = None ):
120+ if params is None :
121+ params = {}
122+ if not (method in self .supportedUnitpayMethods ):
123+ raise Exception ('Method is not supported' )
124+ for rParam in self .requiredUnitpayMethodsParams [method ]:
125+ if not rParam in params :
126+ raise Exception ('Param ' + rParam + ' is null' )
127+ params ['secretKey' ] = self .secretKey
128+ request_url = self .apiUrl + '?method=' + method + '&' + self .insert_url_encode ('params' , params )
129+ response = urlopen (request_url )
130+ data = response .read ().decode ('utf-8' )
131+ jsons = json .loads (data )
132+ return jsons
133+
134+ @staticmethod
135+ def insert_url_encode (inserted , params ):
136+ result = ''
137+ first = True
138+ for p in params :
139+ if first :
140+ first = False
141+ else :
142+ result += '&'
143+ result += inserted + '[' + p + ']=' + str (params [p ])
144+ return result
145+
146+
147+ def parse_params (s ):
148+ params = {}
149+ for v in s :
150+ if re .search ('params' , v ):
151+ p = v [len ('params[' ):- 1 ]
152+ params [p ] = s [v ][0 ]
153+ return params
154+
155+
156+ def ksort (d ):
157+ return [[k , d [k ]] for k in sorted (d .keys ())]
0 commit comments