feat: 更新支付模块 (Stripe/PayPal/PingPong) 和 uni-app 配置

This commit is contained in:
TradeMate Dev
2026-06-16 13:32:50 +08:00
parent e5b1e7d588
commit 15d172e825
17 changed files with 1254 additions and 12 deletions
+57
View File
@@ -1,3 +1,4 @@
import json
from fastapi import APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel
from typing import Optional
@@ -15,6 +16,13 @@ class PurchaseRequest(BaseModel):
pay_type: str = "alipay"
class StripePurchaseRequest(BaseModel):
package_id: str
gateway: str = "stripe"
success_url: str = "https://trade.yuzhiran.com/workspace/credits?pay=success"
cancel_url: str = "https://trade.yuzhiran.com/workspace/credits?pay=cancel"
class SubscribeRequest(BaseModel):
plan_id: str
pay_type: str = "alipay"
@@ -103,6 +111,55 @@ async def subscribe_plan(
return order
@router.post("/stripe-purchase")
async def stripe_purchase(
req: StripePurchaseRequest,
user_id: str = Depends(get_current_user_id),
db: AsyncSession = Depends(get_db),
):
svc = CreditService(db)
packages = await svc.get_packages()
pkg = next((p for p in packages if p["id"] == req.package_id), None)
if not pkg:
raise HTTPException(status_code=404, detail="次数包不存在")
from app.services.payment import get_gateway, gen_order_no
price_usd = pkg.get("price_usd") or round(pkg["price"] / 7, 2)
amount_cents = int(price_usd * 100)
order_no = gen_order_no(user_id)
gw = get_gateway(req.gateway)
sep = '&' if '?' in req.success_url else '?'
success_url = f"{req.success_url}{sep}order_id={order_no}"
gw_result = await gw.create_order(
order_no, amount_cents, f"{pkg['name_en']} ({pkg['credits']} credits)",
pay_type=req.gateway,
success_url=success_url,
cancel_url=req.cancel_url,
)
from app.models.payment_transaction import PaymentTransaction
txn = PaymentTransaction(
user_id=user_id, order_no=order_no, plan="credit_purchase",
amount=price_usd, gateway=req.gateway, pay_type=req.gateway,
status="pending", description=json.dumps({"credits": pkg["credits"]}),
gateway_order_no=gw_result.get("session_id", ""),
)
db.add(txn)
await db.flush()
return {
"status": "pending",
"order_id": order_no,
"session_url": gw_result.get("session_url"),
"session_id": gw_result.get("session_id"),
"amount": price_usd,
"currency": "USD",
"gateway": req.gateway,
}
@router.post("/cancel-subscription")
async def cancel_subscription(
user_id: str = Depends(get_current_user_id),