fbef15ba7e
- 合并为单一初始全量迁移,覆盖 users/user_devices/user_points/point_batches/point_transactions/point_recharge_orders - 去掉所有 ForeignKey 约束(业务层软删除,不依赖数据库级联) - 去掉不必要的索引,仅保留 Unique 约束自带索引 - 修复 mjk_users.id 为 UUID 类型(非 String(36)) - 修复 user_device.last_active_at 时区类型一致性(添加 timezone=True)
148 lines
4.0 KiB
Python
148 lines
4.0 KiB
Python
"""
|
||
积分充值订单表
|
||
==============
|
||
|
||
记录微信支付充值订单,包含完整的支付链路信息用于排查。
|
||
|
||
排查场景:
|
||
1. 用户付了钱积分没到账 → 查 prepay_id / 回调记录 / 主动查询结果
|
||
2. 统一下单失败 → 查 request_params / error_code / error_msg
|
||
3. 回调没收到 → 查 notify_raw / notify_verified
|
||
4. 签名验证失败 → 查 notify_raw / error_msg
|
||
"""
|
||
|
||
import uuid
|
||
from datetime import datetime
|
||
|
||
from sqlalchemy import DateTime, String, Text
|
||
from sqlalchemy.dialects.postgresql import UUID
|
||
from sqlalchemy.orm import Mapped, mapped_column
|
||
|
||
from app.models.base import BaseModelBigInt
|
||
|
||
|
||
class PointRechargeOrder(BaseModelBigInt):
|
||
"""积分充值订单"""
|
||
|
||
__tablename__ = "mjk_point_recharge_orders"
|
||
|
||
user_id: Mapped[uuid.UUID] = mapped_column(
|
||
UUID(as_uuid=True),
|
||
nullable=False,
|
||
comment="用户 ID",
|
||
)
|
||
|
||
# ========== 商品信息 ==========
|
||
points: Mapped[int] = mapped_column(
|
||
default=0,
|
||
nullable=False,
|
||
comment="充值积分数",
|
||
)
|
||
|
||
amount_rmb: Mapped[int] = mapped_column(
|
||
default=0,
|
||
nullable=False,
|
||
comment="人民币金额(单位:分,如 500 = 5 元)",
|
||
)
|
||
|
||
# ========== 微信支付核心字段 ==========
|
||
out_trade_no: Mapped[str | None] = mapped_column(
|
||
String(64),
|
||
nullable=True,
|
||
unique=True,
|
||
comment="商户订单号(传给微信的 out_trade_no)",
|
||
)
|
||
|
||
prepay_id: Mapped[str | None] = mapped_column(
|
||
String(64),
|
||
nullable=True,
|
||
comment="微信预支付会话标识(统一下单返回)",
|
||
)
|
||
|
||
wx_order_no: Mapped[str | None] = mapped_column(
|
||
String(64),
|
||
nullable=True,
|
||
comment="微信支付订单号(微信侧唯一标识)",
|
||
)
|
||
|
||
openid: Mapped[str | None] = mapped_column(
|
||
String(64),
|
||
nullable=True,
|
||
comment="用户微信 OpenID(统一下单必需)",
|
||
)
|
||
|
||
client_ip: Mapped[str | None] = mapped_column(
|
||
String(45),
|
||
nullable=True,
|
||
comment="用户下单时的 IP 地址",
|
||
)
|
||
|
||
trade_type: Mapped[str | None] = mapped_column(
|
||
String(16),
|
||
nullable=True,
|
||
comment="交易类型:JSAPI / NATIVE / APP",
|
||
)
|
||
|
||
# ========== 订单状态 ==========
|
||
status: Mapped[str] = mapped_column(
|
||
String(20),
|
||
default="pending",
|
||
nullable=False,
|
||
comment="订单状态:pending / paid / failed / closed",
|
||
)
|
||
|
||
paid_at: Mapped[datetime | None] = mapped_column(
|
||
DateTime(timezone=True),
|
||
nullable=True,
|
||
comment="支付成功时间",
|
||
)
|
||
|
||
closed_at: Mapped[datetime | None] = mapped_column(
|
||
DateTime(timezone=True),
|
||
nullable=True,
|
||
comment="订单关闭时间(超时未支付)",
|
||
)
|
||
|
||
# ========== 排查字段(核心)==========
|
||
request_params: Mapped[str | None] = mapped_column(
|
||
Text,
|
||
nullable=True,
|
||
comment="统一下单请求参数(JSON 格式,用于排查请求侧问题)",
|
||
)
|
||
|
||
request_response: Mapped[str | None] = mapped_column(
|
||
Text,
|
||
nullable=True,
|
||
comment="统一下单响应内容(JSON 格式,用于排查微信返回)",
|
||
)
|
||
|
||
notify_raw: Mapped[str | None] = mapped_column(
|
||
Text,
|
||
nullable=True,
|
||
comment="微信回调原始内容(XML/JSON,用于排查回调问题)",
|
||
)
|
||
|
||
notify_verified: Mapped[bool] = mapped_column(
|
||
default=False,
|
||
nullable=False,
|
||
comment="回调签名是否验证通过",
|
||
)
|
||
|
||
query_result: Mapped[str | None] = mapped_column(
|
||
Text,
|
||
nullable=True,
|
||
comment="主动查询订单结果(JSON 格式,用于二次确认)",
|
||
)
|
||
|
||
error_code: Mapped[str | None] = mapped_column(
|
||
String(32),
|
||
nullable=True,
|
||
comment="错误码(微信返回或系统异常)",
|
||
)
|
||
|
||
error_msg: Mapped[str | None] = mapped_column(
|
||
Text,
|
||
nullable=True,
|
||
comment="错误描述(用于快速定位问题)",
|
||
)
|