Skip to content

Commit 9b09986

Browse files
author
WeRn
committed
inital import
1 parent fabe762 commit 9b09986

File tree

4 files changed

+300
-0
lines changed

4 files changed

+300
-0
lines changed

api.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
from flask import Flask
2+
import locale
3+
from flask_sqlalchemy import SQLAlchemy
4+
from config import Config
5+
6+
app = Flask(__name__)
7+
app.config.from_object(Config)
8+
locale.setlocale(locale.LC_ALL, '')
9+
db = SQLAlchemy(app)
10+
11+
12+
@app.route('/')
13+
def index():
14+
return 'UnitPay API'
15+
16+
17+
from models import UnitpayPayments, AccountData
18+
from unitpay import UnitPay
19+
from flask import request
20+
from sqlalchemy import exc
21+
from datetime import datetime
22+
import decimal
23+
24+
25+
@app.route('/api/v1.0/unitpay/payment/', methods=['GET'])
26+
def unitpay_processor():
27+
unitpay = UnitPay('SECRET_KEY') # ВВести ключ от UnitPay
28+
if unitpay.check_handler_request():
29+
try:
30+
sum_count = decimal.Decimal(request.args.get('params[profit]'))
31+
account = db.session.query(AccountData).filter(AccountData.name == request.args.get('params[account]')).first()
32+
if request.args.get('method') == 'pay':
33+
if account:
34+
pay = UnitpayPayments(unitpay_id=request.args.get('params[unitpayId]'),
35+
account=request.args.get('params[account]'),
36+
sum=request.args.get('params[payerSum]'),
37+
payment_type=request.args.get('params[paymentType]'),
38+
payer_currency=request.args.get('params[payerCurrency]'),
39+
signature=request.args.get('params[signature]'),
40+
profit=request.args.get('params[profit]'))
41+
db.session.add(pay)
42+
db.session.commit()
43+
44+
update_count = sum_count
45+
46+
db.session.query(AccountData).filter(AccountData.name == request.args.get('params[account]')).update({
47+
'balance': account.balance + update_count
48+
})
49+
db.session.query(UnitpayPayments).filter(UnitpayPayments.unitpay_id == request.args.get('params[unitpayId]')).update({
50+
'date_complete': datetime.now(),
51+
'status': 1
52+
})
53+
db.session.commit()
54+
app.logger.info('The request was successfully processed by the system.')
55+
return unitpay.get_success_handler_response("The request was successfully processed by the system.")
56+
else:
57+
app.logger.info('Account with this email does not exist.')
58+
return unitpay.get_error_handler_response("Account with this email does not exist.")
59+
else:
60+
app.logger.info('The request was successfully processed by the system without writing to the database because of.')
61+
return unitpay.get_success_handler_response("The request was successfully processed by the system without writing to the database because of.")
62+
except exc.SQLAlchemyError as e:
63+
print(e)
64+
app.logger.error(e)
65+
db.session.rollback()
66+
return unitpay.get_error_handler_response("The request has been processed by the system.")
67+
else:
68+
return unitpay.get_error_handler_response("The request has been processed by the system.")
69+
70+
71+
if __name__ == '__main__':
72+
app.run(host='127.0.0.1', port=8080)

config.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import os
2+
3+
basedir = os.path.abspath(os.path.dirname(__file__))
4+
5+
6+
class Config(object):
7+
8+
TEST = False
9+
DEBUG = False
10+
11+
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:[email protected]:3306/aion?charset=utf8mb4'
12+
SQLALCHEMY_TRACK_MODIFICATIONS = False
13+
SQLALCHEMY_ECHO = False
14+
15+
SECRET_KEY = str(os.urandom(48))[2:-1].replace('\\x', '')

models.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from api import db
2+
from datetime import datetime
3+
4+
5+
class UnitpayPayments(db.Model):
6+
__tablename__ = 'unitpay_payments'
7+
8+
id = db.Column(db.Integer(), primary_key=True, autoincrement=True, nullable=False)
9+
unitpay_id = db.Column(db.VARCHAR(255), nullable=False)
10+
account = db.Column(db.VARCHAR(255), nullable=False)
11+
sum = db.Column(db.REAL(), nullable=False)
12+
payment_type = db.Column(db.VARCHAR(255), nullable=False)
13+
payer_currency = db.Column(db.VARCHAR(255), nullable=False)
14+
signature = db.Column(db.VARCHAR(100), nullable=False)
15+
date_create = db.Column(db.DateTime(), nullable=False, default=datetime.now())
16+
date_complete = db.Column(db.DateTime(), nullable=True, default=None)
17+
status = db.Column(db.Integer(), nullable=False, default=0)
18+
profit = db.Column(db.VARCHAR(255), nullable=True)
19+
20+
def __init__(self, unitpay_id, account, sum, payment_type, payer_currency, signature, profit):
21+
self.unitpay_id = unitpay_id
22+
self.account = account
23+
self.sum = sum
24+
self.payment_type = payment_type
25+
self.payer_currency = payer_currency
26+
self.signature = signature
27+
self.profit = profit
28+
29+
30+
class AccountData(db.Model):
31+
__tablename__ = 'account_data'
32+
33+
id = db.Column(db.Integer(), primary_key=True, autoincrement=True, nullable=False)
34+
name = db.Column(db.VARCHAR(30), nullable=False)
35+
password = db.Column(db.VARCHAR(100), nullable=False)
36+
activated = db.Column(db.Integer(), nullable=False, default=0)
37+
access_level = db.Column(db.Integer(), nullable=False, default=0)
38+
last_server = db.Column(db.Integer(), nullable=False, default=-1)
39+
last_ip = db.Column(db.VARCHAR(20), nullable=False, default='xxx.xxx.xxx.xxx')
40+
last_mac = db.Column(db.VARCHAR(20), nullable=False, default='xx-xx-xx-xx-xx-xx')
41+
last_hdd = db.Column(db.VARCHAR(100), nullable=False, default='xxxxxxxxxxxxx')
42+
allowed_ip = db.Column(db.VARCHAR(20), nullable=True)
43+
allowed_mac = db.Column(db.VARCHAR(20), nullable=True)
44+
allowed_hdd = db.Column(db.VARCHAR(100), nullable=True)
45+
session_id = db.Column(db.VARCHAR(100), nullable=True)
46+
create_date = db.Column(db.TIMESTAMP(), nullable=False, default=datetime.now())
47+
edit_date = db.Column(db.TIMESTAMP(), nullable=False, default=datetime.now())
48+
password_edit_date = db.Column(db.TIMESTAMP(), nullable=False, default=datetime.now())
49+
security_ip = db.Column(db.VARCHAR(20), nullable=False, default='127.0.0.1')
50+
balance = db.Column(db.Integer(), nullable=False, default=0)
51+
is_banned = db.Column(db.Integer(), nullable=False, default=0)
52+
two_factor = db.Column(db.Integer(), nullable=False, default=0)
53+
54+
def __init__(self, name, password):
55+
self.name = name
56+
self.password = password

unitpay.py

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
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

Comments
 (0)