小程序在9月27日发布了正式版
This commit is contained in:
@@ -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 中实现以下函数:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user