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:
TradeMate Dev
2026-06-09 17:19:45 +08:00
parent f17a6ccbac
commit d2736d1ef6
28 changed files with 12368 additions and 267 deletions
+63 -2
View File
@@ -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()