payment.py 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  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. amount: int
  37. currency: str
  38. random_offset: int
  39. exchange_rate: float # 注意:仅用于展示,DB 里是 DECIMAL
  40. external_refund_no: Optional[str]
  41. refund_reason: Optional[str]
  42. refunded_at: Optional[datetime]
  43. created_at: datetime
  44. updated_at: datetime
  45. model_config = {
  46. "from_attributes": True
  47. }