developing
This commit is contained in:
parent
c31591484c
commit
30be8c72df
|
|
@ -0,0 +1,8 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PublishConfigData" remoteFilesAllowedToDisappearOnAutoupload="false">
|
||||
<serverData>
|
||||
<paths name="root@192.168.16.207:22 password">
|
||||
<serverdata>
|
||||
<mappings>
|
||||
<mapping local="$PROJECT_DIR$" web="/" />
|
||||
</mappings>
|
||||
</serverdata>
|
||||
</paths>
|
||||
</serverData>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.11" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4">
|
||||
<component name="Flask">
|
||||
<option name="enabled" value="true" />
|
||||
</component>
|
||||
<component name="PyDocumentationSettings">
|
||||
<option name="format" value="PLAIN" />
|
||||
<option name="myDocStringFormat" value="Plain" />
|
||||
</component>
|
||||
<component name="TemplatesService">
|
||||
<option name="TEMPLATE_CONFIGURATION" value="Jinja2" />
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/payment_headend" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
7
app.py
7
app.py
|
|
@ -1,7 +0,0 @@
|
|||
from flask import Flask
|
||||
|
||||
from config import get_config
|
||||
|
||||
config = get_config()
|
||||
|
||||
app = Flask(__name__)
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
from flask import Flask, request, jsonify
|
||||
|
||||
from config import get_config
|
||||
from services.order import OrderService
|
||||
|
||||
config = get_config()
|
||||
|
||||
app = Flask(__name__)
|
||||
order_service = OrderService() # 获取单例实例
|
||||
|
||||
@app.route('/createOrder', methods=['POST'])
|
||||
def create_order():
|
||||
data = request.get_json()
|
||||
phone = data.get('phone', None)
|
||||
email = data.get('email', None)
|
||||
address = data.get('address', None)
|
||||
try:
|
||||
payment_method = data['paymentMethod']
|
||||
except KeyError:
|
||||
return jsonify({
|
||||
"message": "Unsupported payment method. Currently, only USDT payments are supported."
|
||||
}), 400
|
||||
|
||||
addresses = order_service.get_user_addresses(phone, email, address, payment_method)
|
||||
|
||||
if not addresses:
|
||||
return jsonify({
|
||||
"message": "No payment address associated with you was found. Please provide a payment address."
|
||||
}), 400
|
||||
|
||||
if len(addresses) == 1:
|
||||
order_id = order_service.create_order(addresses[0])
|
||||
return jsonify({"order_id": order_id}), 200
|
||||
|
||||
# 多个地址的情况
|
||||
return jsonify({
|
||||
"message": "请选择一个地址进行下单。",
|
||||
"addresses": addresses
|
||||
}), 200
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True)
|
||||
|
|
@ -10,3 +10,4 @@ password: 'your_mysql_password'
|
|||
host: 'localhost'
|
||||
database: 'your_database_name'
|
||||
autocommit: false
|
||||
allow_multi_statements: True
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
from utils.database import pack_params
|
||||
|
||||
|
||||
class User:
|
||||
def __init__(self, id_=None, name=None, phone=None, email=None, address=None, payment_method=None):
|
||||
self.id = id_
|
||||
self.name = name
|
||||
self.phone = phone
|
||||
self.email = email
|
||||
self.address = address
|
||||
self.payment_method = payment_method
|
||||
|
||||
def insert_sql(self, params_format="list"):
|
||||
params_sql, params = pack_params(params_format=params_format, param_sql="{param}", join_str=",",
|
||||
name=self.name, phone=self.phone, email=self.email, address=self.address,
|
||||
payment_method=self.payment_method)
|
||||
return f"INSERT INTO user ({params_sql}) VALUES ({','.join('%s' for _ in params)})", params
|
||||
|
||||
def select_sql(self, condition="AND", params_format="list"):
|
||||
params_sql, params = pack_params(params_format=params_format, param_sql="{param}=%s", join_str=f" {condition} ",
|
||||
name=self.name, phone=self.phone, email=self.email, address=self.address,
|
||||
payment_method=self.payment_method)
|
||||
return f"SELECT id, name, phone, email, address, payment_method FROM user WHERE {params_sql}", params
|
||||
|
||||
def exists_sql(self, condition="AND", params_format="list"):
|
||||
params_sql, params = pack_params(params_format=params_format, param_sql="{param}=%s", join_str=f" {condition} ",
|
||||
name=self.name, phone=self.phone, email=self.email, address=self.address,
|
||||
payment_method=self.payment_method)
|
||||
return f"SELECT id FROM user WHERE {params_sql} LIMIT 1", params
|
||||
|
||||
def params(self, format="dict"):
|
||||
if format == "list":
|
||||
params = []
|
||||
elif format == "dict":
|
||||
params = {}
|
||||
else:
|
||||
raise ValueError("format must be list or dict")
|
||||
if self.uid:
|
||||
if format == "list":
|
||||
params.append(self.uid)
|
||||
elif format == "dict":
|
||||
params["uid"] = self.uid
|
||||
if self.name:
|
||||
if format == "list":
|
||||
params.append(self.name)
|
||||
elif format == "dict":
|
||||
params["name"] = self.name
|
||||
if self.phone:
|
||||
if format == "list":
|
||||
params.append(self.phone)
|
||||
elif format == "dict":
|
||||
params["phone"] = self.phone
|
||||
if self.email:
|
||||
if format == "list":
|
||||
params.append(self.email)
|
||||
elif format == "dict":
|
||||
params["email"] = self.email
|
||||
if self.address:
|
||||
if format == "list":
|
||||
params.append(self.address)
|
||||
elif format == "dict":
|
||||
params["address"] = self.address
|
||||
if self.payment_method:
|
||||
if format == "list":
|
||||
params.append(self.payment_method)
|
||||
elif format == "dict":
|
||||
params["payment_method"] = self.payment_method
|
||||
return params
|
||||
|
||||
def get_difference(self, other_user):
|
||||
different_attrs = {}
|
||||
if self.uid != other_user.uid:
|
||||
different_attrs["uid"] = (self.uid, other_user.uid)
|
||||
if self.name != other_user.name:
|
||||
different_attrs["name"] = (self.name, other_user.name)
|
||||
if self.phone != other_user.phone:
|
||||
different_attrs["phone"] = (self.phone, other_user.phone)
|
||||
if self.email != other_user.email:
|
||||
different_attrs["email"] = (self.email, other_user.email)
|
||||
if self.address != other_user.address:
|
||||
different_attrs["address"] = (self.address, other_user.address)
|
||||
if self.payment_method != other_user.payment_method:
|
||||
different_attrs["payment_method"] = (self.payment_method, other_user.payment_method)
|
||||
return different_attrs
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, User):
|
||||
return ((self.name, self.phone, self.email, self.address, self.payment_method)
|
||||
== (other.name, other.phone, other.email, other.address, other.payment_method))
|
||||
return False
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.name, self.phone, self.email, self.address, self.payment_method))
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
import itertools
|
||||
|
||||
from custom_decorators import singleton
|
||||
from database import Database
|
||||
from models import User
|
||||
|
||||
|
||||
@singleton
|
||||
class UserRepository:
|
||||
def __init__(self, config):
|
||||
self.db = Database(config['MYSQL'])
|
||||
|
||||
def get_or_create(self, user):
|
||||
users = []
|
||||
cursor = self.db.execute_query(*user.select_sql(condition="OR"))
|
||||
same_users = cursor.fetchall()
|
||||
new_user = not len(same_users)
|
||||
# 对用户已存在的属性判断是否有新属性
|
||||
update_user = set()
|
||||
update_sqls = []
|
||||
update_params_list = []
|
||||
delete_params = []
|
||||
exist_conflicting_attr = False
|
||||
for same_user in same_users:
|
||||
exist_conflicting_attr = False
|
||||
different_attrs = user.get_difference(same_user)
|
||||
# 用于判断是否有新属性
|
||||
update_sql_params = []
|
||||
update_params = []
|
||||
for k, v in different_attrs.items():
|
||||
new_attr, exist_attr = v
|
||||
if exist_attr is None:
|
||||
setattr(same_user, k, new_attr)
|
||||
update_sql_params.append(f"{k}=%s")
|
||||
update_params.append(new_attr)
|
||||
else:
|
||||
# 出现冲突的属性,考虑新增一行记录
|
||||
exist_conflicting_attr = True
|
||||
break
|
||||
|
||||
if same_user in update_user:
|
||||
delete_params.append((same_user.id,))
|
||||
else:
|
||||
users.append(same_user)
|
||||
exist_new_attr = bool(update_params)
|
||||
if exist_new_attr:
|
||||
update_user.add(same_user)
|
||||
update_sqls.append(f'UPDATE user SET {",".join(update_sql_params)} WHERE id=%s;')
|
||||
update_params.append(same_user.id)
|
||||
update_params_list.append(update_params)
|
||||
sql_flag = False
|
||||
try:
|
||||
if delete_params:
|
||||
sql_flag = True
|
||||
self.db.get_connection().cursor().executemany("DELETE FROM user WHERE id=%s", delete_params)
|
||||
if update_user:
|
||||
sql_flag = True
|
||||
self.db.get_connection().cursor().execute("".join(update_sqls),
|
||||
list(itertools.chain.from_iterable(update_params_list)),
|
||||
multi=True)
|
||||
if sql_flag:
|
||||
self.db.commit()
|
||||
except Exception:
|
||||
self.db.rollback()
|
||||
raise
|
||||
if new_user or exist_conflicting_attr:
|
||||
try:
|
||||
self.db.execute_query(*user.insert_sql())
|
||||
self.db.commit()
|
||||
except Exception:
|
||||
self.db.rollback()
|
||||
raise
|
||||
users.append(user)
|
||||
return users
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
import uuid
|
||||
|
||||
from custom_decorators import singleton
|
||||
from models import User
|
||||
from repositories.order import OrderRepository
|
||||
from repositories.user import UserRepository
|
||||
from services.payment import PaymentService
|
||||
from utils.datetime import current, current_timestamp, is_time_difference_greater_than
|
||||
|
||||
|
|
@ -9,14 +11,27 @@ from utils.datetime import current, current_timestamp, is_time_difference_greate
|
|||
@singleton
|
||||
class OrderService:
|
||||
def __init__(self, config):
|
||||
self.order_repo = OrderRepository(config)
|
||||
self.config = config
|
||||
self.payment_service = PaymentService()
|
||||
self.order_repo = OrderRepository(config)
|
||||
self.user_repo = UserRepository(config)
|
||||
|
||||
def create_order(self, from_address, to_address):
|
||||
def get_user_addresses(self, phone=None, email=None, address=None, payment_method=None):
|
||||
if address is None:
|
||||
if phone or email:
|
||||
users = self.user_repo.get_or_create(User(phone=phone, email=email))
|
||||
addresses = set(user.address for user in users if address)
|
||||
return list(addresses)
|
||||
raise ValueError('A phone number, email, or address is required.')
|
||||
return [address]
|
||||
|
||||
def create_order(self, address=None):
|
||||
date_str = current().strftime('%Y%m%d%H%M%S')
|
||||
unique_id = str(uuid.uuid4()).split('-')[0]
|
||||
order_id = f"{date_str}-{unique_id}"
|
||||
self.order_repo.create(order_id, from_address, to_address)
|
||||
|
||||
self.order_repo.create(order_id, address,
|
||||
self.config['PaymentAddresses'])
|
||||
return order_id
|
||||
|
||||
def finish_order(self, order_id):
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
def pack_params(params_format="list", param_sql="{param}=%s", join_str=" AND ", **kwargs):
|
||||
if params_format == "list":
|
||||
params = []
|
||||
elif params_format == "dict":
|
||||
params = {}
|
||||
else:
|
||||
raise ValueError("Unknown params format")
|
||||
param_sqls = []
|
||||
for k, v in kwargs.items():
|
||||
if v is not None:
|
||||
if params_format == "list":
|
||||
params.append(v)
|
||||
elif params_format == "dict":
|
||||
params[k] = v
|
||||
param_sqls.append(param_sql.format(param=k))
|
||||
return join_str.join(param_sqls), params
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
from custom_decorators import singleton
|
||||
from database import Database
|
||||
from utils.database import pack_params
|
||||
|
||||
|
||||
@singleton
|
||||
class UserRepository:
|
||||
def __init__(self, config):
|
||||
self.db = Database(config['MYSQL'])
|
||||
|
||||
def get_user(self, phone=None, email=None, address=None):
|
||||
params_sql, params = pack_params(phone=phone, email=email, address=address)
|
||||
sql = f"SELECT name, phone, email, address FROM user WHERE {params_sql}"
|
||||
cursor = self.db.execute_query(sql, params)
|
||||
users = cursor.fetchall()
|
||||
return users
|
||||
|
||||
def create_user(self, phone=None, email=None, address=None):
|
||||
_, params = pack_params(phone=phone, email=email, address=address)
|
||||
sql = f"INSERT INTO user (phone, email, address) VALUES (%s, %s, %s)"
|
||||
self.db.execute_query(sql, params)
|
||||
self.db.commit()
|
||||
|
||||
def record_exists(self, phone=None, email=None, address=None):
|
||||
params_sql, params = pack_params(phone=phone, email=email, address=address)
|
||||
sql = f"SELECT EXISTS(SELECT 1 FROM user WHERE {params_sql} LIMIT 1)"
|
||||
cursor = self.db.execute_query(sql, params)
|
||||
result = cursor.fetchone()
|
||||
return bool(result[0])
|
||||
|
||||
def create_if_not_exists(self, phone=None, email=None, address=None):
|
||||
if not self.record_exists(phone=phone, email=email, address=address):
|
||||
self.create_user(phone=phone, email=email, address=address)
|
||||
|
||||
def get_and_create_if_not_exists(self, phone=None, email=None, address=None):
|
||||
users = self.get_user(phone=phone, email=email, address=address)
|
||||
if len(users) == 0:
|
||||
self.create_user(phone=phone, email=email, address=address)
|
||||
else:
|
||||
return users
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
def pack_params(**kwargs):
|
||||
params = []
|
||||
param_sqls = []
|
||||
flag = False
|
||||
for k, v in kwargs.items():
|
||||
flag = True
|
||||
params.append(v)
|
||||
param_sqls.append(f"{k}=%s")
|
||||
if flag:
|
||||
return " AND ".join(param_sqls), params
|
||||
Loading…
Reference in New Issue