diff --git a/app/api/endpoints/mp.py b/app/api/endpoints/mp.py index 3936fb6..7e0981f 100644 --- a/app/api/endpoints/mp.py +++ b/app/api/endpoints/mp.py @@ -9,7 +9,7 @@ import hashlib import time from app.core.config import settings import logging - +from typing import Optional router = APIRouter() def check_signature(signature: str, timestamp: str, nonce: str) -> bool: @@ -81,4 +81,22 @@ async def handle_server(request: Request): except Exception as e: logging.exception("处理微信消息异常") # 返回空字符串表示接收成功 - return Response(content="", media_type="text/plain") \ No newline at end of file + return Response(content="", media_type="text/plain") + + + +# 发送模板消息接口,传入参数openid,template_id,data,url,miniprogram +@router.post("/template/send") +async def send_template_message( + openid: str, + template_id: str, + data: dict, + url: Optional[str] = None, + miniprogram: Optional[dict] = None +): + + # {"data":{"phrase2":"快递代取","character_string13":"123","time4":"2025-02-25 11:11:11","thing15":"天悦龙庭10栋","thing10":"周龙"}} + + """发送模板消息""" + await mp_client.send_template_message(openid, template_id, data, url, miniprogram) + return success_response(message="模板消息发送成功") \ No newline at end of file diff --git a/app/api/endpoints/order.py b/app/api/endpoints/order.py index a16b61e..9a4aadb 100644 --- a/app/api/endpoints/order.py +++ b/app/api/endpoints/order.py @@ -31,6 +31,7 @@ from app.models.point import PointRecordDB, PointRecordType from app.core.utils import CommonUtils import logging from sqlalchemy import func +from app.core.mpclient import mp_client router = APIRouter() @@ -237,6 +238,22 @@ async def create_order( packages = db.query(ShippingOrderPackageDB).filter( ShippingOrderPackageDB.orderid == orderid ).all() + + #发送订单创建成功的消息 + if current_user.mp_openid: + await mp_client.send_template_message( + openid=current_user.mp_openid, + template_id=settings.DELIVERY_ORDER_CREATED_TEMPLATE_ID, + data={ + "character_string13": db_order.orderid, + "time4": db_order.create_time, + "thing10": db_order.address_customer_name, + "thing15": f"{db_order.address_community_name} {db_order.address_community_building_name} {db_order.address_detail}", + "thing9": db_order.status.status_text + }, miniprogram={ + "appid": settings.WECHAT_APPID, + "path": f"/pages/order/detail/index?id={db_order.orderid}" + }) return success_response( message="订单创建成功", @@ -248,6 +265,7 @@ async def create_order( ) except Exception as e: db.rollback() + logging.exception(f"订单创建失败: {str(e)}") return error_response(code=500, message=f"订单创建失败: {str(e)}") @router.get("/{orderid}", response_model=ResponseModel) @@ -295,8 +313,8 @@ async def get_order_detail( ShippingOrderDB.status == OrderStatus.COMPLETED ).count() else: - deliveryman_user_name = None delivery_count = 0 + deliveryman_user_name = None deliveryman_user_avatar = None deliveryman_user_phone = None @@ -555,8 +573,20 @@ async def cancel_order( description=f"订单取消返还积分" ) db.add(point_record) - db.commit() + + # 发送模板消息 + if current_user.mp_openid: + await mp_client.send_template_message( + openid=current_user.mp_openid, + template_id=settings.DELIVERY_ORDER_CANCELLED_TEMPLATE_ID, + data={ + "character_string1": order.orderid, + "time19": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + "thing5": "用户主动取消订单" + } + ) + return success_response( message="订单取消成功", data=OrderInfo.model_validate(order) @@ -706,6 +736,22 @@ async def deliveryman_cancel_order( db.add(point_record) db.commit() + + # 发送模板消息 + if order.userid: + order_user = db.query(UserDB).filter( + UserDB.userid == order.userid + ).first() + if order_user.mp_openid: + await mp_client.send_template_message( + openid=order_user.mp_openid, + template_id=settings.DELIVERY_ORDER_CANCELLED_TEMPLATE_ID, + data={ + "character_string1": order.orderid, + "time19": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + "thing5": order.cancel_reason + } + ) return success_response( message="订单取消成功", data=OrderInfo.model_validate(order) @@ -763,6 +809,32 @@ async def complete_order( order.completed_time = datetime.now() db.commit() + + # 发送模板消息 + if order.userid: + order_user = db.query(UserDB).filter( + UserDB.userid == order.userid + ).first() + if order_user.mp_openid: + deliveryman_user = db.query(UserDB).filter( + UserDB.userid == order.deliveryman_user_id + ).first() + + await mp_client.send_template_message( + openid=order_user.mp_openid, + template_id=settings.DELIVERY_ORDER_COMPLETED_TEMPLATE_ID, + data={ + "character_string13": order.orderid, + "thing3": deliveryman_user.nickname, + "phone_number15": deliveryman_user.phone, + "time5" : datetime.now().strftime("%Y-%m-%d %H:%M:%S") + }, + miniprogram={ + "appid": settings.WECHAT_APPID, + "path": f"/pages/order/detail/index?id={order.orderid}" + } + ) + return success_response( message="订单已完成" if order.final_amount == 0 else "请继续支付", data=OrderInfo.model_validate(order) @@ -801,6 +873,31 @@ async def receive_order( order.received_time = datetime.now() db.commit() + + # 发送模板消息 + if order.userid: + order_user = db.query(UserDB).filter( + UserDB.userid == order.userid + ).first() + if order_user.mp_openid: + deliveryman_user = db.query(UserDB).filter( + UserDB.userid == order.deliveryman_user_id + ).first() + + await mp_client.send_template_message( + openid=order_user.mp_openid, + template_id=settings.DELIVERY_ORDER_RECEIVED_TEMPLATE_ID, + data={ + "character_string1": order.orderid, + "time2": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + "thing7": deliveryman_user.nickname, + "phone_number5" : deliveryman_user.phone + }, + miniprogram={ + "appid": settings.WECHAT_APPID, + "path": f"/pages/order/detail/index?id={order.orderid}" + } + ) return success_response( message="接单成功", data=OrderInfo.model_validate(order) @@ -835,6 +932,33 @@ async def pickup_order( order.pickup_time = datetime.now() db.commit() + + + # 发送模板消息 + if order.userid: + order_user = db.query(UserDB).filter( + UserDB.userid == order.userid + ).first() + if order_user.mp_openid: + order_deliveryman = db.query(UserDB).filter( + UserDB.userid == order.deliveryman_user_id + ).first() + + await mp_client.send_template_message( + openid=order_user.mp_openid, + template_id=settings.DELIVERY_ORDER_DELIVERING_TEMPLATE_ID, + data={ + "number1": order.orderid, + "thing3": order_deliveryman.nickname, + "phone_number8": order_deliveryman.phone, + "time5" : datetime.now().strftime("%Y-%m-%d %H:%M:%S") + }, + miniprogram={ + "appid": settings.WECHAT_APPID, + "path": f"/pages/order/detail/index?id={order.orderid}" + } + ) + return success_response( message="已标记为取货", data=OrderInfo.model_validate(order) diff --git a/app/core/config.py b/app/core/config.py index 213e0ea..cd891b7 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -76,13 +76,15 @@ class Settings(BaseSettings): # 微信模板消息ID #配送订单创建成功 - WECHAT_DELIVERY_ORDER_CREATED_TEMPLATE_ID: str = "-aFOuC2dv1E6Opn9auB39bSiU4p0DbKOrUtOFgS-AaA" + DELIVERY_ORDER_CREATED_TEMPLATE_ID: str = "N8sMeoBG6biUjWO1PbxBol6akEI6O9isSvCiB1MlVuY" #配送订单接单 - WECHAT_DELIVERY_ORDER_RECEIVED_TEMPLATE_ID: str = "zBdw3OQoZ4RQ9Yau-kpHJ-iGo6cjm7Q-dEh4Luzs2ww" + DELIVERY_ORDER_RECEIVED_TEMPLATE_ID: str = "-HJ-9uiSI8hyHD3zWEZ3Gh72LLf_qffrhJk9kTmgQU4" + #配送订单配送中 + DELIVERY_ORDER_DELIVERING_TEMPLATE_ID: str = "31KA432gVcnPUxIu6eKWWxMhacPS_v3svzqwN7uTI-w" #配送订单完成 - WECHAT_DELIVERY_ORDER_COMPLETED_TEMPLATE_ID: str = "Yr4BuHkwUw1LTWYfSz7MTEBWcqaqKGojqHlxt14moCU" + DELIVERY_ORDER_COMPLETED_TEMPLATE_ID: str = "eR7UlBRWRXEuQdVNNU6AByAOUqZd4fzxiVEYcRtXrLU" #配送订单取消 - WECHAT_DELIVERY_ORDER_CANCELLED_TEMPLATE_ID: str = "5sS4wKt7jyoFGYMKQHGweIDB6UHrikF_ith0swd8z5Y" + DELIVERY_ORDER_CANCELLED_TEMPLATE_ID: str = "iGR0rPtOFC_u8Xj5-R730zoDD_4Kbswkf_jSTnSSd6E" class Config: case_sensitive = True diff --git a/app/models/order.py b/app/models/order.py index e9aaf48..0f309ab 100644 --- a/app/models/order.py +++ b/app/models/order.py @@ -16,6 +16,19 @@ class OrderStatus(str, enum.Enum): UNPAID = "UNPAID" # 未支付 COMPLETED = "COMPLETED" # 已完成 + # 订单状态转化成中文 + @property + def status_text(self) -> str: + status_map = { + OrderStatus.CREATED: "待接单", + OrderStatus.CANCELLED: "已取消", + OrderStatus.RECEIVED: "已接单", + OrderStatus.DELIVERING: "配送中", + OrderStatus.UNPAID: "待支付", + OrderStatus.COMPLETED: "已完成" + } + return status_map.get(self, "未知状态") + class DeliveryMethod(str, enum.Enum): DELIVERY_AT_DOORSTEP = "DELIVERY_AT_DOORSTEP" # 放在门口 DELIVERY_TO_ROOM = "DELIVERY_TO_ROOM" # 投递到家 @@ -53,7 +66,10 @@ class ShippingOrderDB(Base): completed_time = Column(DateTime(timezone=True), nullable=True) # 完成时间 complete_images = Column(String(1000), nullable=True) # 完成订单的图片URL,多个URL用逗号分隔 create_time = Column(DateTime(timezone=True), server_default=func.now()) + + # 配送员信息 deliveryman_user_id = Column(Integer, ForeignKey("users.userid"), nullable=True) + cancel_user_id = Column(Integer, ForeignKey("users.userid"), nullable=True) pay_status = Column(Boolean, default=False) # 支付状态 prepay_id = Column(String(64)) # 微信支付预支付ID @@ -118,7 +134,9 @@ class OrderInfo(BaseModel): optimized_complete_images: Optional[List[str]] = None create_time: datetime delivery_method: DeliveryMethod + deliveryman_user_id: Optional[int] = None + cancel_reason: Optional[str] = None cancel_user_id: Optional[int] = None