小程序在9月27日发布了正式版

This commit is contained in:
qcloud
2025-10-01 08:29:09 +08:00
parent 8d90798647
commit c44e6715a0
15 changed files with 6679 additions and 25074 deletions

View File

@@ -8,6 +8,7 @@ import xml.etree.ElementTree as ET
import requests
import time
from datetime import datetime, timedelta, date
from dateutil.relativedelta import relativedelta
from decimal import Decimal
from uuid import UUID
import json
@@ -553,6 +554,7 @@ async def get_order_detial(
"msg": "success",
"data": result})
# 用户是否有权访问这个博物馆
@payment_router.post("/get_user_museum_subscriptions")
async def get_user_museum_subscriptions(
request: Request,
@@ -959,41 +961,6 @@ async def deliver_virtual_goods(order: dict) -> bool:
logger.exception(f"发货处理异常: {str(e)}")
return False
# 套餐激活函数
def activate_user_product(user_id: str, product_id: int, museum_id: int, order_id: str):
product = get_product_by_id(product_id)
if not product:
return
# 计算有效期
start_time = datetime.now()
end_time = calculate_expiry(start_time, product["validity_type"])
# 创建用户套餐记录
create_user_product({
"user_id": user_id,
"product_id": product_id,
"museum_id": museum_id,
"order_id": order_id,
"start_time": start_time,
"end_time": end_time,
"is_active": True
})
# 禁用同一博物馆的旧套餐
deactivate_previous_products(user_id, museum_id)
def calculate_expiry(start_time: datetime, validity_type: str) -> datetime:
if validity_type == "free":
return start_time + timedelta(days=7) # 免费套餐7天
elif validity_type == "1month":
return start_time + timedelta(days=30)
elif validity_type == "1year":
return start_time + timedelta(days=365)
else: # permanent
return datetime(2999, 12, 31)
async def generate_wx_prepay_params_v3(order_id: str, total_fee: int, openid: str, body: str):
"""微信支付v3统一下单"""
@@ -1194,6 +1161,128 @@ async def query_order_by_out_trade_no(out_trade_no: str):
except Exception as e:
logging.error(f"订单查询异常: {str(e)}", exc_info=True)
return None
"""
20250929 临时增加生成1个临时的收款二维码用于测试学校智能水表收费
"""
@payment_router.post("/create_temp_qrcode_simple")
async def create_temp_qrcode_simple(
request: Request
):
"""
生成临时收款二维码(简化版,不创建订单)
请求参数: {"amount": 金额(元), "description": "商品描述"}
返回: 二维码URL
"""
try:
data = await request.json()
amount = data.get("amount")
description = data.get("description", "临时收款")
if not amount or float(amount) <= 0:
raise HTTPException(status_code=400, detail="金额必须大于0")
# 生成临时订单ID仅用于支付不存储
order_id = f"SMART_WATER_{int(time.time())}{random.randint(1000, 9999)}"
amount_float = float(amount)
amount_in_cents = int(amount_float * 100) # 转换为分
# 生成Native支付二维码
try:
qr_code_url = await generate_simple_native_qrcode(
order_id=order_id,
total_fee=amount_in_cents,
body=description
)
except Exception as error:
logger.info(f"生成支付二维码失败{error}")
if not qr_code_url:
raise HTTPException(status_code=500, detail="生成支付二维码失败")
return JSONResponse({
"code": 0,
"msg": "success",
"data": {
"order_id": order_id, # 返回订单ID用于测试查询
"amount": amount_float,
"description": description,
"qr_code_url": qr_code_url,
"expire_time": (datetime.now() + timedelta(hours=4)).isoformat(),
"note": "此为测试二维码,支付成功后不会激活任何服务"
}
})
except ValueError:
raise HTTPException(status_code=400, detail="金额格式错误")
except Exception as e:
logger.error(f"生成临时收款二维码失败: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail=f"生成失败: {str(e)}")
async def generate_simple_native_qrcode(order_id: str, total_fee: int, body: str):
"""生成简化的Native支付二维码"""
try:
nonce_str = generate_nonce_str(32)
params = {
"appid": WX_APPID,
"mch_id": WX_MCH_ID,
"nonce_str": nonce_str,
"body": f"测试-{body}"[:128], # 添加测试前缀
"out_trade_no": order_id,
"total_fee": str(total_fee),
"spbill_create_ip": "127.0.0.1",
"notify_url": WX_PAY_NOTIFY_URL, # 使用相同的回调接口
"trade_type": "NATIVE",
"time_expire": (datetime.now() + timedelta(hours=4)).strftime('%Y%m%d%H%M%S') # 4小时过期
}
# 生成签名
params["sign"] = generate_sign_v2(params, WX_PAY_KEY)
# 转换为XML
xml_data = dict_to_xml(params)
try:
# 调用微信统一下单接口
response = requests.post(
"https://api.mch.weixin.qq.com/pay/unifiedorder",
data=xml_data.encode('utf-8'),
headers={"Content-Type": "application/xml"},
timeout=10
)
except Exception as error:
logging.info(f"调用生成支持二维码失败:{error}")
logging.info(f"res={response}")
if response.status_code != 200:
logger.error(f"Native支付接口错误: {response.status_code}")
return None
response_data = xml_to_dict(response.text)
if response_data.get("return_code") != "SUCCESS":
error_msg = response_data.get("return_msg", "未知错误")
logger.error(f"Native支付下单失败: {error_msg}")
return None
if response_data.get("result_code") != "SUCCESS":
error_code = response_data.get("err_code", "")
error_msg = response_data.get("err_code_des", "未知错误")
logger.error(f"Native支付业务失败: [{error_code}] {error_msg}")
return None
# 返回二维码链接
code_url = response_data.get("code_url")
if code_url:
logger.info(f"生成测试二维码成功: {order_id}, 金额: {total_fee}")
return code_url
else:
logger.error("Native支付返回缺少code_url")
return None
except Exception as e:
logger.error(f"生成测试二维码异常: {str(e)}", exc_info=True)
return None
"""
需要在 database.py 中实现以下函数: