初始提交: Qihu-AIFlow v2.0.1 完整项目
- 前端 React+TypeScript (源码+构建产物) - 后端 Python FastAPI - 数据库迁移 001-015 - Docker部署配置 - 微信ClawBot API频道绑定 - 项目文档 README.md
This commit is contained in:
commit
78ff261b5a
199 files changed
+69126
No files matched your search
@@ -0,0 +1,226 @@
|
||||
"""
|
||||
支付渠道配置 API(管理员)
|
||||
"""
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from fastapi.responses import StreamingResponse
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy import func
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
from ...database import get_db, SessionLocal
|
||||
from ...models import PaymentConfig, Order
|
||||
from ...auth import get_current_admin
|
||||
from ...middleware.log_service import LogService
|
||||
import uuid
|
||||
import csv
|
||||
import io
|
||||
from datetime import datetime
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class PaymentConfigUpdate(BaseModel):
|
||||
app_id: Optional[str] = None
|
||||
merchant_id: Optional[str] = None
|
||||
api_key: Optional[str] = None
|
||||
api_v3_key: Optional[str] = None
|
||||
cert_path: Optional[str] = None
|
||||
cert_serial_no: Optional[str] = None
|
||||
alipay_public_key: Optional[str] = None
|
||||
app_private_key: Optional[str] = None
|
||||
gateway_url: Optional[str] = None
|
||||
notify_url: Optional[str] = None
|
||||
return_url: Optional[str] = None
|
||||
status: Optional[str] = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 支付配置管理
|
||||
# ============================================================
|
||||
|
||||
@router.get("/configs")
|
||||
async def get_payment_configs(
|
||||
admin_user=Depends(get_current_admin),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""获取支付配置列表"""
|
||||
configs = db.query(PaymentConfig).order_by(
|
||||
PaymentConfig.created_at.desc()
|
||||
).all()
|
||||
return [
|
||||
{
|
||||
"id": c.id,
|
||||
"type": c.type,
|
||||
"app_id": c.app_id,
|
||||
"merchant_id": c.merchant_id,
|
||||
"api_key": c.api_key,
|
||||
"api_v3_key": c.api_v3_key,
|
||||
"cert_path": c.cert_path,
|
||||
"cert_serial_no": c.cert_serial_no,
|
||||
"alipay_public_key": c.alipay_public_key,
|
||||
"app_private_key": c.app_private_key,
|
||||
"gateway_url": c.gateway_url,
|
||||
"notify_url": c.notify_url,
|
||||
"return_url": c.return_url,
|
||||
"status": c.status,
|
||||
"created_at": c.created_at.isoformat() if c.created_at else None,
|
||||
"updated_at": c.updated_at.isoformat() if c.updated_at else None,
|
||||
}
|
||||
for c in configs
|
||||
]
|
||||
|
||||
|
||||
@router.put("/configs/{id}")
|
||||
async def update_payment_config(
|
||||
id: str,
|
||||
data: PaymentConfigUpdate,
|
||||
admin_user=Depends(get_current_admin),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""更新支付配置"""
|
||||
config = db.query(PaymentConfig).filter(PaymentConfig.id == id).first()
|
||||
if not config:
|
||||
raise HTTPException(status_code=404, detail="支付配置不存在")
|
||||
|
||||
update_data = data.model_dump(exclude_unset=True)
|
||||
for key, value in update_data.items():
|
||||
if hasattr(config, key):
|
||||
setattr(config, key, value)
|
||||
config.updated_at = datetime.now()
|
||||
db.commit()
|
||||
|
||||
LogService.log_audit(
|
||||
admin_id=admin_user.id,
|
||||
admin_name=admin_user.username,
|
||||
action="update_payment_config",
|
||||
target_type="payment_config",
|
||||
target_id=id,
|
||||
detail=f"更新支付配置 [{config.type}]",
|
||||
)
|
||||
|
||||
return {"code": 0, "message": "支付配置已更新"}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 订单管理
|
||||
# ============================================================
|
||||
|
||||
@router.get("/orders")
|
||||
async def get_orders(
|
||||
status: str = Query(None, description="订单状态筛选: pending/paid/refunded/cancelled"),
|
||||
order_type: str = Query(None, description="订单类型筛选: membership/service/app"),
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(20, ge=1, le=100),
|
||||
admin_user=Depends(get_current_admin),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""获取所有订单列表"""
|
||||
query = db.query(Order)
|
||||
|
||||
if status:
|
||||
query = query.filter(Order.status == status)
|
||||
if order_type:
|
||||
query = query.filter(Order.order_type == order_type)
|
||||
|
||||
total = query.count()
|
||||
orders = query.order_by(Order.created_at.desc()).offset(
|
||||
(page - 1) * page_size
|
||||
).limit(page_size).all()
|
||||
|
||||
return {
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size,
|
||||
"items": [
|
||||
{
|
||||
"id": o.id,
|
||||
"user_id": o.user_id,
|
||||
"order_type": o.order_type,
|
||||
"item_id": o.item_id,
|
||||
"item_name": o.item_name,
|
||||
"amount": float(o.amount) if o.amount else 0,
|
||||
"coupon_id": o.coupon_id,
|
||||
"discount_amount": float(o.discount_amount) if o.discount_amount else 0,
|
||||
"payment_method": o.payment_method,
|
||||
"payment_id": o.payment_id,
|
||||
"status": o.status,
|
||||
"created_at": o.created_at.isoformat() if o.created_at else None,
|
||||
"updated_at": o.updated_at.isoformat() if o.updated_at else None,
|
||||
}
|
||||
for o in orders
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@router.put("/orders/{id}/refund")
|
||||
async def refund_order(
|
||||
id: str,
|
||||
admin_user=Depends(get_current_admin),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""退款操作"""
|
||||
order = db.query(Order).filter(Order.id == id).first()
|
||||
if not order:
|
||||
raise HTTPException(status_code=404, detail="订单不存在")
|
||||
if order.status != "paid":
|
||||
raise HTTPException(status_code=400, detail="只能对已支付的订单进行退款")
|
||||
if order.status == "refunded":
|
||||
raise HTTPException(status_code=400, detail="订单已退款")
|
||||
|
||||
order.status = "refunded"
|
||||
order.updated_at = datetime.now()
|
||||
db.commit()
|
||||
|
||||
LogService.log_audit(
|
||||
admin_id=admin_user.id,
|
||||
admin_name=admin_user.username,
|
||||
action="refund_order",
|
||||
target_type="order",
|
||||
target_id=id,
|
||||
detail=f"退款订单 {order.id}, 金额 {float(order.amount)}",
|
||||
)
|
||||
|
||||
return {"message": "退款成功"}
|
||||
|
||||
|
||||
@router.get("/orders/export")
|
||||
async def export_orders(
|
||||
status: str = Query(None, description="订单状态筛选"),
|
||||
admin_user=Depends(get_current_admin),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""导出订单(CSV格式)"""
|
||||
query = db.query(Order)
|
||||
if status:
|
||||
query = query.filter(Order.status == status)
|
||||
|
||||
orders = query.order_by(Order.created_at.desc()).all()
|
||||
|
||||
output = io.StringIO()
|
||||
writer = csv.writer(output)
|
||||
writer.writerow([
|
||||
"订单ID", "用户ID", "订单类型", "商品ID", "商品名称",
|
||||
"金额", "优惠券ID", "折扣金额", "支付方式", "支付ID",
|
||||
"状态", "创建时间", "更新时间"
|
||||
])
|
||||
|
||||
for o in orders:
|
||||
writer.writerow([
|
||||
o.id, o.user_id, o.order_type, o.item_id, o.item_name,
|
||||
float(o.amount) if o.amount else 0,
|
||||
o.coupon_id,
|
||||
float(o.discount_amount) if o.discount_amount else 0,
|
||||
o.payment_method, o.payment_id,
|
||||
o.status,
|
||||
o.created_at.isoformat() if o.created_at else "",
|
||||
o.updated_at.isoformat() if o.updated_at else "",
|
||||
])
|
||||
|
||||
output.seek(0)
|
||||
return StreamingResponse(
|
||||
iter([output.getvalue()]),
|
||||
media_type="text/csv",
|
||||
headers={
|
||||
"Content-Disposition": f"attachment; filename=orders_export_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
|
||||
},
|
||||
)
|
||||
Reference in new issue
Block a user