payment.py 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. import json
  2. from pydantic import BaseModel, field_validator
  3. from typing import Optional, Dict, Any, Literal, List
  4. from datetime import datetime
  5. class VasPaymentBase(BaseModel):
  6. status: Optional[Literal['pending', 'succeeded', 'failed', 'expired', 'late_paid', 'refunded']] = None
  7. qr_id: Optional[int] = None
  8. payment_url: Optional[str] = None
  9. expire_at: Optional[datetime] = None
  10. provider_payload: Optional[Dict[str, Any]] = None
  11. @field_validator("provider_payload", mode="before")
  12. def normalize_json_field(cls, v):
  13. if v is None:
  14. return None
  15. if isinstance(v, str):
  16. try:
  17. return json.loads(v)
  18. except Exception:
  19. return {}
  20. return v
  21. class VasPaymentCreate(BaseModel):
  22. order_id: str
  23. provider: Literal['stripe', 'wechat', 'alipay']
  24. class AdminUpdateStatusPayload(BaseModel):
  25. remark: Optional[str] = None
  26. status: Literal['succeeded', 'failed']
  27. class VasPaymentOut(VasPaymentBase):
  28. id: int
  29. order_id: str
  30. provider: str
  31. channel: str
  32. payment_intent_id: Optional[str]
  33. external_trade_no: Optional[str]
  34. base_amount: int
  35. base_currency: str
  36. adjustment_delta: int
  37. final_amount: int
  38. amount: int
  39. currency: str
  40. random_offset: int
  41. exchange_rate: float # 注意:仅用于展示,DB 里是 DECIMAL
  42. external_refund_no: Optional[str]
  43. refund_reason: Optional[str]
  44. refunded_at: Optional[datetime]
  45. created_at: datetime
  46. updated_at: datetime
  47. model_config = {
  48. "from_attributes": True
  49. }