feat: AI routing DB-driven, payment gateway full integration, WeChat mini-program CI/CD
- AI routing rules now stored in system_configs DB table instead of hardcoded config - Multi-model support via name|model composite key for same-provider routing - UnifiedPayService with HMAC-SHA256 gateway integration (alipay/wechat) - Admin payment panel: list, stats, search, filter, refund - WeChat mini-program CI/CD via miniprogram-ci (v1.0.9) - Translation quota extended to LLM provider tier - SearchService with DB-driven provider config (bing/google_cse/searxng) - Footer cleanup across admin/workspace/uni-app - Private key excluded from git tracking
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import json
|
||||
import logging
|
||||
import hashlib
|
||||
from typing import Optional, Dict, Any, List
|
||||
@@ -109,9 +110,11 @@ class PaymentService:
|
||||
order_no = gen_order_no(user_id)
|
||||
description = PLAN_DESCRIPTIONS.get(plan, f"TradeMate {plan}")
|
||||
|
||||
remark = json.dumps({"uid": user_id, "oid": order_no}, ensure_ascii=False, separators=(",", ":"))
|
||||
|
||||
gw = get_gateway(pay_type)
|
||||
gw_result = await gw.create_order(order_no, int(plan_info["price"] * 100),
|
||||
description, pay_type=pay_type)
|
||||
description, pay_type=pay_type, remark=remark)
|
||||
|
||||
sub = Subscription(
|
||||
user_id=user_id, plan=plan, status="pending",
|
||||
@@ -208,6 +211,45 @@ class PaymentService:
|
||||
"created_at": txn.created_at.isoformat(),
|
||||
}
|
||||
|
||||
async def close_order(self, user_id: str, order_no: str) -> Dict[str, Any]:
|
||||
result = await self.db.execute(
|
||||
select(PaymentTransaction).where(
|
||||
PaymentTransaction.order_no == order_no,
|
||||
PaymentTransaction.user_id == user_id,
|
||||
)
|
||||
)
|
||||
txn = result.scalar_one_or_none()
|
||||
if not txn:
|
||||
raise ValueError("订单不存在")
|
||||
if txn.status != "pending":
|
||||
raise ValueError("只有待支付订单可关闭")
|
||||
gw = get_gateway(txn.pay_type)
|
||||
await gw.close_order(order_no)
|
||||
txn.status = "closed"
|
||||
await self.db.flush()
|
||||
return {"status": "ok", "order_no": order_no}
|
||||
|
||||
async def query_refund(self, order_no: str, user_id: str = "") -> Dict[str, Any]:
|
||||
query = select(PaymentTransaction).where(PaymentTransaction.order_no == order_no)
|
||||
if user_id:
|
||||
query = query.where(PaymentTransaction.user_id == user_id)
|
||||
result = await self.db.execute(query)
|
||||
txn = result.scalar_one_or_none()
|
||||
if not txn:
|
||||
raise ValueError("订单不存在")
|
||||
if txn.status != "refunded":
|
||||
raise ValueError("该订单未退款")
|
||||
gw = get_gateway(txn.pay_type)
|
||||
gw_result = await gw.query_refund(order_no)
|
||||
return {
|
||||
"order_no": order_no,
|
||||
"status": txn.status,
|
||||
"refund_amount": txn.refund_amount,
|
||||
"refund_reason": txn.refund_reason,
|
||||
"refunded_at": txn.refunded_at.isoformat() if txn.refunded_at else None,
|
||||
"gateway": gw_result,
|
||||
}
|
||||
|
||||
async def list_transactions(self, user_id: str,
|
||||
page: int = 1, size: int = 20) -> Dict[str, Any]:
|
||||
query = select(PaymentTransaction).where(
|
||||
@@ -277,7 +319,8 @@ class PaymentService:
|
||||
|
||||
async def admin_list_payments(self, page: int = 1, size: int = 20,
|
||||
gateway: str = "", status: str = "",
|
||||
user_id: str = "") -> Dict[str, Any]:
|
||||
user_id: str = "",
|
||||
pay_type: str = "") -> Dict[str, Any]:
|
||||
query = select(PaymentTransaction).order_by(desc(PaymentTransaction.created_at))
|
||||
count_query = select(PaymentTransaction.id)
|
||||
if gateway:
|
||||
@@ -289,6 +332,9 @@ class PaymentService:
|
||||
if user_id:
|
||||
query = query.where(PaymentTransaction.user_id == user_id)
|
||||
count_query = count_query.where(PaymentTransaction.user_id == user_id)
|
||||
if pay_type:
|
||||
query = query.where(PaymentTransaction.pay_type == pay_type)
|
||||
count_query = count_query.where(PaymentTransaction.pay_type == pay_type)
|
||||
|
||||
total_result = await self.db.execute(count_query)
|
||||
total = len(total_result.scalars().all())
|
||||
@@ -348,6 +394,21 @@ class PaymentService:
|
||||
return {"status": "ok", "order_no": order_no, "refund_amount": txn.amount,
|
||||
"user_id": str(txn.user_id)}
|
||||
|
||||
async def admin_close_order(self, order_no: str) -> Dict[str, Any]:
|
||||
result = await self.db.execute(
|
||||
select(PaymentTransaction).where(PaymentTransaction.order_no == order_no)
|
||||
)
|
||||
txn = result.scalar_one_or_none()
|
||||
if not txn:
|
||||
raise ValueError("订单不存在")
|
||||
if txn.status != "pending":
|
||||
raise ValueError("只有待支付订单可关闭")
|
||||
gw = get_gateway(txn.pay_type)
|
||||
await gw.close_order(order_no)
|
||||
txn.status = "closed"
|
||||
await self.db.flush()
|
||||
return {"status": "ok", "order_no": order_no}
|
||||
|
||||
async def admin_payment_stats(self) -> Dict[str, Any]:
|
||||
all_txns = await self.db.execute(select(PaymentTransaction))
|
||||
rows = all_txns.scalars().all()
|
||||
|
||||
Reference in New Issue
Block a user