diff --git a/app/api/endpoints/wechat.py b/app/api/endpoints/wechat.py index 220246c..acf185d 100644 --- a/app/api/endpoints/wechat.py +++ b/app/api/endpoints/wechat.py @@ -128,7 +128,7 @@ async def create_payment( if not order: return error_response(code=404, message="订单不存在或状态不正确") amount = order.pay_amount - description = "商家商品订单" + description = "商家团购订单" elif request.order_type == OrderType.ONLINE_PAY: order = db.query(MerchantPayOrderDB).filter( @@ -140,6 +140,16 @@ async def create_payment( return error_response(code=404, message="订单不存在或状态不正确") amount = order.amount description = "商家在线买单" + elif request.order_type == OrderType.DELIVERY: + order = db.query(ShippingOrderDB).filter( + ShippingOrderDB.orderid == request.order_id, + ShippingOrderDB.userid == current_user.userid, + ShippingOrderDB.status == OrderStatus.UNPAID + ).first() + if not order: + return error_response(code=404, message="订单不存在或状态不正确") + amount = order.final_amount + description = "小区配送订单" else: return error_response(code=400, message="不支持的订单类型") @@ -167,7 +177,7 @@ async def create_payment( except Exception as e: return error_response(code=500, message=f"创建支付订单失败: {str(e)}") -@router.post("/payment-notify") +@router.post("/payment/notify") async def payment_notify( request: Request, db: Session = Depends(get_db) @@ -176,8 +186,7 @@ async def payment_notify( try: # 初始化微信支付客户端 wechat = WeChatClient() - - # 验证并解析回调数据 + data = await wechat.verify_payment_notify(request) if not data: print(f"回调数据验证失败: {data}") @@ -190,30 +199,63 @@ async def payment_notify( trade_state = data.get("trade_state") success_time = data.get("success_time") - if trade_state != "SUCCESS": - return error_response(code=400, message="支付未成功") + if not all([out_trade_no, transaction_id, trade_state]) or trade_state != "SUCCESS": + return error_response(code=400, message="缺少必要的订单信息或支付未成功") - # 更新订单状态 - if out_trade_no.startswith("M"): # 商家商品订单 + # 判断订单类型并处理 + if out_trade_no.startswith('D'): # 配送订单 + # 查询配送订单 + order = db.query(ShippingOrderDB).filter( + ShippingOrderDB.orderid == out_trade_no + ).first() + + if not order: + return error_response(code=404, message="订单不存在") + + if trade_state == "SUCCESS": + # 更新订单状态 + order.pay_status = True + order.status = OrderStatus.COMPLETED # 支付成功后状态为已完成 + order.transaction_id = transaction_id + order.pay_time = datetime.fromisoformat(success_time.replace('Z', '+00:00')) + + elif out_trade_no.startswith("M"): # 商家商品订单 + # 查询商户订单 order = db.query(MerchantOrderDB).filter( MerchantOrderDB.order_id == out_trade_no ).first() - if order: + + if not order: + return error_response(code=404, message="订单不存在") + + if trade_state == "SUCCESS": + # 更新订单状态 + order.pay_status = True order.status = MerchantOrderStatus.UNVERIFIED - order.pay_time = datetime.fromisoformat(success_time) order.transaction_id = transaction_id + order.pay_time = datetime.fromisoformat(success_time.replace('Z', '+00:00')) elif out_trade_no.startswith("P"): # 商家在线买单 order = db.query(MerchantPayOrderDB).filter( MerchantPayOrderDB.order_id == out_trade_no ).first() - if order: + + if not order: + return error_response(code=404, message="订单不存在") + + if trade_state == "SUCCESS": + # 更新订单状态 + order.pay_status = True order.status = MerchantPayOrderStatus.PAID - order.pay_time = datetime.fromisoformat(success_time) order.transaction_id = transaction_id + order.pay_time = datetime.fromisoformat(success_time.replace('Z', '+00:00')) + + else: + return error_response(code=400, message="未知的订单类型") db.commit() + # 返回成功 return success_response(message="支付成功") except Exception as e: diff --git a/app/core/wechat.py b/app/core/wechat.py index 5298ddb..1cf1ba3 100644 --- a/app/core/wechat.py +++ b/app/core/wechat.py @@ -185,7 +185,7 @@ class WeChatClient: "mchid": self.mch_id, "description": description, "out_trade_no": out_trade_no, - "notify_url": f"{settings.API_BASE_URL}/api/wechat/payment-notify", + "notify_url": f"{settings.API_BASE_URL}/api/wechat/payment/notify", "amount": { "total": total_amount, "currency": "CNY" @@ -286,14 +286,14 @@ class WeChatClient: aesgcm = AESGCM(key_bytes) - print("解密参数:") - print(f"密钥长度: {len(key_bytes)} bytes") - print(f"Nonce长度: {len(nonce_bytes)} bytes") - print(f"密文长度: {len(ciphertext_bytes)} bytes") - print(f"附加数据: {associated_data_bytes}") - print(f"使用的密钥: {self.api_v3_key}") # 仅用于调试,生产环境需要移除 - print(f"原始nonce: {nonce}") - print(f"原始associated_data: {associated_data}") + # print("解密参数:") + # print(f"密钥长度: {len(key_bytes)} bytes") + # print(f"Nonce长度: {len(nonce_bytes)} bytes") + # print(f"密文长度: {len(ciphertext_bytes)} bytes") + # print(f"附加数据: {associated_data_bytes}") + # print(f"使用的密钥: {self.api_v3_key}") # 仅用于调试,生产环境需要移除 + # print(f"原始nonce: {nonce}") + # print(f"原始associated_data: {associated_data}") # 解密数据 decrypted_data = aesgcm.decrypt( diff --git a/app/models/merchant_order.py b/app/models/merchant_order.py index 2fe96a8..8b00285 100644 --- a/app/models/merchant_order.py +++ b/app/models/merchant_order.py @@ -1,4 +1,4 @@ -from sqlalchemy import Column, String, Integer, DateTime, ForeignKey, Enum +from sqlalchemy import Column, String, Integer, DateTime, ForeignKey, Enum, Boolean from sqlalchemy.dialects.mysql import DECIMAL from sqlalchemy.sql import func from pydantic import BaseModel, Field @@ -26,11 +26,14 @@ class MerchantOrderDB(Base): order_amount = Column(DECIMAL(10,2), nullable=False) pay_amount = Column(DECIMAL(10,2), nullable=False, default=0) status = Column(Enum(MerchantOrderStatus), nullable=False, default=MerchantOrderStatus.CREATED) + pay_status = Column(Boolean, nullable=False, default=False) order_verify_code = Column(String(21), unique=True, nullable=False) verify_time = Column(DateTime(timezone=True), nullable=True) verify_user_id = Column(Integer, ForeignKey("users.userid"), nullable=True) create_time = Column(DateTime(timezone=True), server_default=func.now()) update_time = Column(DateTime(timezone=True), onupdate=func.now()) + transaction_id = Column(String(64)) # 微信支付交易号 + pay_time = Column(DateTime(timezone=True), nullable=True) class MerchantOrderCreate(BaseModel): merchant_product_id: int diff --git a/app/models/merchant_pay_order.py b/app/models/merchant_pay_order.py index c485f7c..ae30240 100644 --- a/app/models/merchant_pay_order.py +++ b/app/models/merchant_pay_order.py @@ -1,4 +1,4 @@ -from sqlalchemy import Column, String, Integer, DateTime, ForeignKey, Enum, DECIMAL +from sqlalchemy import Column, String, Integer, DateTime, ForeignKey, Enum, DECIMAL, Boolean from sqlalchemy.sql import func from pydantic import BaseModel, Field from typing import Optional @@ -10,6 +10,8 @@ import enum class MerchantPayOrderStatus(str, enum.Enum): UNPAID = "UNPAID" # 未支付 PAID = "PAID" # 已支付 + REFUNDING = "REFUNDING" # 退款中 + REFUNDED = "REFUNDED" # 已退款 class MerchantPayOrderDB(Base): __tablename__ = "merchant_pay_orders" @@ -21,9 +23,11 @@ class MerchantPayOrderDB(Base): amount = Column(DECIMAL(10,2), nullable=False) gift_points = Column(DECIMAL(10,1), nullable=False, default=0) status = Column(Enum(MerchantPayOrderStatus), nullable=False, default=MerchantPayOrderStatus.UNPAID) + pay_status = Column(Boolean, nullable=False, default=False) create_time = Column(DateTime(timezone=True), server_default=func.now()) update_time = Column(DateTime(timezone=True), onupdate=func.now()) pay_time = Column(DateTime(timezone=True), nullable=True) + transaction_id = Column(String(64)) # 微信支付交易号 class MerchantPayOrderCreate(BaseModel): merchant_id: int