Files
server-core/app/pay/models.py
T

123 lines
8.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""支付子应用 ORM:算力充值订单 + 活动报名订单 + OPC 收款绑定 + 分账流水。
(落平台主库,alembic 统一迁移;新表由 create_all 幂等创建。)
"""
from __future__ import annotations
from sqlalchemy import Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from ..infrastructure.db import Base
class ComputeRechargeOrder(Base):
"""算力充值订单(微信支付 V3)。
状态机:pending → paid(支付成功,本地终态)→ credited(引擎到账完成);
pending 超时未支付 → closed;到账异常 → failed(待人工/对账补单)。
"""
__tablename__ = "compute_recharge_orders"
id: Mapped[str] = mapped_column(String, primary_key=True) # cr_<hex>
order_no: Mapped[str] = mapped_column(String, unique=True, index=True) # CR_<ts>_<hex8>,微信 out_trade_no
user_id: Mapped[str] = mapped_column(String, default="", index=True) # 平台 users.id
username: Mapped[str] = mapped_column(String, default="", index=True) # 平台/引擎用户名(充值归集键)
engine_user_id: Mapped[int] = mapped_column(Integer, default=0) # 引擎用户 id(下单时解析缓存,0=待解析)
package_id: Mapped[str] = mapped_column(String, default="") # 套餐 id;空 = 自由金额
amount_fen: Mapped[int] = mapped_column(Integer, default=0) # 实付金额(分,微信口径)
quota_micro: Mapped[int] = mapped_column(Integer, default=0) # 到账微元 = amount_fen//100 * 1_000_000
bonus_quota_micro: Mapped[int] = mapped_column(Integer, default=0) # 套餐赠送微元
client_type: Mapped[str] = mapped_column(String, default="native") # native(扫码) | jsapi(小程序)
appid: Mapped[str] = mapped_column(String, default="") # 下单所用 appid(对账依据)
status: Mapped[str] = mapped_column(String, default="pending", index=True) # pending|paid|credited|closed|failed
prepay_id: Mapped[str] = mapped_column(String, default="") # 微信预支付单号(jsapi
transaction_id: Mapped[str] = mapped_column(String, default="", index=True) # 微信支付单号
code_url: Mapped[str] = mapped_column(String, default="") # Native 二维码内容
expires_at: Mapped[str] = mapped_column(String, default="") # 过期时刻(ISO,超时未付 → closed)
paid_at: Mapped[str] = mapped_column(String, default="")
credited_at: Mapped[str] = mapped_column(String, default="") # 引擎到账完成时刻
notify_payload: Mapped[str] = mapped_column(Text, default="") # 回调/查单原始报文(JSON 串,排查用)
created_at: Mapped[str] = mapped_column(String, default="", index=True)
updated_at: Mapped[str] = mapped_column(String, default="")
class EventOrder(Base):
"""活动报名订单(微信支付 V3,课程/沙龙定价)。
状态机与充值订单一致:pending → paid(支付成功)→ credited(报名确认完成);
pending 超时未支付 → closed;确认异常 → failed(对账补单)。
"""
__tablename__ = "event_orders"
id: Mapped[str] = mapped_column(String, primary_key=True) # ev_<hex>
order_no: Mapped[str] = mapped_column(String, unique=True, index=True) # EV_<ts>_<hex8>,微信 out_trade_no
booking_id: Mapped[str] = mapped_column(String, default="", index=True) # bookings.id
event_id: Mapped[str] = mapped_column(String, default="", index=True) # events.id
event_title: Mapped[str] = mapped_column(String, default="")
user_id: Mapped[str] = mapped_column(String, default="", index=True) # 平台 users.id
username: Mapped[str] = mapped_column(String, default="", index=True)
openid: Mapped[str] = mapped_column(String, default="") # JSAPI 支付 openid(下单人)
amount_fen: Mapped[int] = mapped_column(Integer, default=0) # 实付金额(分)
client_type: Mapped[str] = mapped_column(String, default="jsapi")
appid: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="pending", index=True) # pending|paid|credited|closed|failed
prepay_id: Mapped[str] = mapped_column(String, default="")
transaction_id: Mapped[str] = mapped_column(String, default="", index=True)
expires_at: Mapped[str] = mapped_column(String, default="")
paid_at: Mapped[str] = mapped_column(String, default="")
credited_at: Mapped[str] = mapped_column(String, default="")
notify_payload: Mapped[str] = mapped_column(Text, default="")
created_at: Mapped[str] = mapped_column(String, default="", index=True)
updated_at: Mapped[str] = mapped_column(String, default="")
class PaymentBinding(Base):
"""OPC 收款绑定(微信服务商分账接收方)。
bind_type
- personal:个人绑定 → PERSONAL_OPENID 分账到 OPC 微信零钱
- merchant:商户绑定 → 特约商户进件生成子商户号 sub_mchid → MERCHANT_ID 接收方
状态机:applying(商户进件中)→ active(可接收分账)→ disabled / rejected。
"""
__tablename__ = "payment_bindings"
id: Mapped[str] = mapped_column(String, primary_key=True) # pb_<hex>
user_id: Mapped[str] = mapped_column(String, default="", index=True) # 平台 users.idOPC 主体)
bind_type: Mapped[str] = mapped_column(String, default="personal") # personal | merchant
openid: Mapped[str] = mapped_column(String, default="") # personal:小程序 openid
real_name: Mapped[str] = mapped_column(String, default="") # personal:实名(微信校验)
sub_mchid: Mapped[str] = mapped_column(String, default="", index=True) # merchant:子商户号
applyment_id: Mapped[str] = mapped_column(String, default="") # merchant:进件申请单号
status: Mapped[str] = mapped_column(String, default="applying", index=True) # applying|active|disabled|rejected
detail: Mapped[str] = mapped_column(String, default="") # 进件驳回原因/接收方状态提示
# ── 进件生命周期(applyment4sub 查询回填,前端据此展示签约/验证引导)──
applyment_state: Mapped[str] = mapped_column(String, default="") # 微信 applyment_state 枚举
sign_url: Mapped[str] = mapped_column(String, default="") # 超管签约链接(扫码完成验证+授权)
account_validation_json: Mapped[str] = mapped_column(Text, default="{}") # 账户验证信息(打款/法人)
audit_detail_json: Mapped[str] = mapped_column(Text, default="{}") # 驳回原因/状态说明
# ── 分账授权(查询 /v3/profitsharing/merchant-configs 回填)──
split_allowed: Mapped[str] = mapped_column(String, default="") # OPEN|CLOSED|WAIT_CONFIRM
split_max_ratio: Mapped[int] = mapped_column(Integer, default=0) # 允许服务商分账的最大比例(%)
created_at: Mapped[str] = mapped_column(String, default="", index=True)
updated_at: Mapped[str] = mapped_column(String, default="")
class SettlementLog(Base):
"""分账流水镜像(业务侧对账用,真金在微信侧)。"""
__tablename__ = "settlement_logs"
id: Mapped[str] = mapped_column(String, primary_key=True) # sl_<hex>
escrow_id: Mapped[str] = mapped_column(String, default="", index=True) # escrows.id
task_id: Mapped[str] = mapped_column(String, default="", index=True)
share_order_no: Mapped[str] = mapped_column(String, default="", index=True) # 分账单号(幂等键)
channel: Mapped[str] = mapped_column(String, default="wx_split") # wx_split | manual | ...
amount: Mapped[int] = mapped_column(Integer, default=0) # 分账总额(分)
commission: Mapped[int] = mapped_column(Integer, default=0) # 平台佣金(分)
receivers_json: Mapped[str] = mapped_column(Text, default="[]") # 接收方+金额快照
status: Mapped[str] = mapped_column(String, default="initiated", index=True) # initiated|shared|failed|returned
detail: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="", index=True)
updated_at: Mapped[str] = mapped_column(String, default="")