Files
life-echo/api/payment/service.py
iammm0 e39fd97e06 feat: 新增后端支付模块,支持微信和支付宝
- 新增api/payment/支付服务(微信、支付宝)
- 新增api/routers/payment.py支付路由
- 更新database/models.py支付相关模型
- 新增数据库迁移文件(订单表、用户订阅字段)
- 更新main.py、requirements.txt、.env.production

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-10 14:23:29 +08:00

174 lines
5.1 KiB
Python

"""
统一支付服务门面
提供统一的支付接口,屏蔽微信/支付宝的底层差异
"""
import logging
from typing import Dict, Optional
from .config import PaymentConfig
from .wechat_pay import WeChatPayClient
from .alipay_pay import AlipayClient
from .schemas import PaymentResult, NotifyResult, PaymentStatus
from .exceptions import PaymentError, PaymentConfigError
logger = logging.getLogger(__name__)
# 支持的支付方式
PAYMENT_METHOD_WECHAT = "wechat"
PAYMENT_METHOD_ALIPAY = "alipay"
SUPPORTED_METHODS = {PAYMENT_METHOD_WECHAT, PAYMENT_METHOD_ALIPAY}
class PaymentService:
"""
统一支付服务
使用方式:
config = PaymentConfig.from_env()
payment_service = PaymentService(config)
# 创建支付订单
result = payment_service.create_payment("wechat", order_no, 9900, "高级版套餐")
# 处理回调
notify = payment_service.handle_wechat_notify(headers, body)
# 查询状态
status = payment_service.query_payment("wechat", order_no)
"""
def __init__(self, config: PaymentConfig):
self._config = config
self._wechat_client: Optional[WeChatPayClient] = None
self._alipay_client: Optional[AlipayClient] = None
@property
def wechat_client(self) -> WeChatPayClient:
"""获取微信支付客户端(懒加载)"""
if self._wechat_client is None:
self._wechat_client = WeChatPayClient(self._config.wechat)
return self._wechat_client
@property
def alipay_client(self) -> AlipayClient:
"""获取支付宝客户端(懒加载)"""
if self._alipay_client is None:
self._alipay_client = AlipayClient(self._config.alipay)
return self._alipay_client
def create_payment(
self,
method: str,
out_trade_no: str,
total_amount: int,
description: str,
) -> PaymentResult:
"""
创建支付订单
Args:
method: 支付方式 (wechat / alipay)
out_trade_no: 商户订单号
total_amount: 金额(单位:分)
description: 商品描述
Returns:
PaymentResult
"""
self._validate_method(method)
if method == PAYMENT_METHOD_WECHAT:
return self.wechat_client.create_app_order(
out_trade_no=out_trade_no,
total_amount=total_amount,
description=description,
)
else:
return self.alipay_client.create_app_order(
out_trade_no=out_trade_no,
total_amount=total_amount,
subject=description,
)
def handle_wechat_notify(
self, headers: Dict[str, str], body: str
) -> NotifyResult:
"""
处理微信支付异步回调通知
Args:
headers: 请求头
body: 请求体
Returns:
NotifyResult
"""
return self.wechat_client.verify_notify(headers=headers, body=body)
def handle_alipay_notify(self, params: Dict[str, str]) -> NotifyResult:
"""
处理支付宝异步回调通知
Args:
params: 回调参数
Returns:
NotifyResult
"""
return self.alipay_client.verify_notify(params=params)
def query_payment(self, method: str, out_trade_no: str) -> PaymentStatus:
"""
查询支付订单状态
Args:
method: 支付方式 (wechat / alipay)
out_trade_no: 商户订单号
Returns:
PaymentStatus
"""
self._validate_method(method)
if method == PAYMENT_METHOD_WECHAT:
return self.wechat_client.query_order(out_trade_no=out_trade_no)
else:
return self.alipay_client.query_order(out_trade_no=out_trade_no)
def close_payment(self, method: str, out_trade_no: str) -> bool:
"""
关闭支付订单
Args:
method: 支付方式 (wechat / alipay)
out_trade_no: 商户订单号
Returns:
是否关闭成功
"""
self._validate_method(method)
if method == PAYMENT_METHOD_WECHAT:
return self.wechat_client.close_order(out_trade_no=out_trade_no)
else:
return self.alipay_client.close_order(out_trade_no=out_trade_no)
def is_method_available(self, method: str) -> bool:
"""检查指定支付方式是否可用"""
if method == PAYMENT_METHOD_WECHAT:
return self._config.wechat.is_configured
elif method == PAYMENT_METHOD_ALIPAY:
if getattr(self._config, "alipay_under_development", True):
return False
return self._config.alipay.is_configured
return False
@staticmethod
def _validate_method(method: str):
"""验证支付方式"""
if method not in SUPPORTED_METHODS:
raise PaymentError(
f"不支持的支付方式: {method},支持的方式: {', '.join(SUPPORTED_METHODS)}",
code="UNSUPPORTED_METHOD",
)