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'
|
host: 'localhost'
|
||||||
database: 'your_database_name'
|
database: 'your_database_name'
|
||||||
autocommit: false
|
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
|
import uuid
|
||||||
|
|
||||||
from custom_decorators import singleton
|
from custom_decorators import singleton
|
||||||
|
from models import User
|
||||||
from repositories.order import OrderRepository
|
from repositories.order import OrderRepository
|
||||||
|
from repositories.user import UserRepository
|
||||||
from services.payment import PaymentService
|
from services.payment import PaymentService
|
||||||
from utils.datetime import current, current_timestamp, is_time_difference_greater_than
|
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
|
@singleton
|
||||||
class OrderService:
|
class OrderService:
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
self.order_repo = OrderRepository(config)
|
self.config = config
|
||||||
self.payment_service = PaymentService()
|
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')
|
date_str = current().strftime('%Y%m%d%H%M%S')
|
||||||
unique_id = str(uuid.uuid4()).split('-')[0]
|
unique_id = str(uuid.uuid4()).split('-')[0]
|
||||||
order_id = f"{date_str}-{unique_id}"
|
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
|
return order_id
|
||||||
|
|
||||||
def finish_order(self, 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