ZHIWEI666 commited on
Commit
cd53308
·
verified ·
1 Parent(s): 79604c9

Upload 8 files

Browse files
Files changed (3) hide show
  1. router_posts.py +5 -3
  2. router_prompts.py +9 -5
  3. router_wallet.py +20 -10
router_posts.py CHANGED
@@ -13,13 +13,13 @@ import 数据库连接 as db
13
  from comment_store import COMMENT_MAX_LENGTH, append_comment, increment_comment_count, attach_comment_counts, read_comment_view
14
  from 安全认证 import require_auth
15
  from db_utils import read_public_source, record_view, sort_cache
16
- from database_sql import get_db
17
  from models_sql import Wallet, Transaction
18
  from notifications import add_notification
19
  from tip_transaction import lock_tip_wallets
20
  from tip_store import run_tip_effect
21
  import time
22
- from owned_thread import OwnedThreadGroup, owned_sync_endpoint
23
  from post_store import publish_post, edit_post, delete_post as remove_post, PostStoreError
24
  import uuid
25
  import hashlib
@@ -36,6 +36,7 @@ start_posts_io = _posts_io.start
36
  stop_posts_io = _posts_io.stop
37
  close_posts_io = _posts_io.close
38
  _posts_endpoint = owned_sync_endpoint(_posts_io)
 
39
 
40
  router = APIRouter()
41
 
@@ -426,7 +427,8 @@ def calculate_tx_hash(tx_id, account, tx_type, amount, prev_hash):
426
 
427
  @router.post("/api/posts/{post_id}/tip")
428
  @shared_limit(10)
429
- async def tip_post(request: Request, post_id: str, amount: int, is_anon: bool = False, current_user: str = Depends(require_auth), db_session: Session = Depends(get_db)):
 
430
  """
431
  打赏帖子(原子操作,并发安全)- 使用 SQL Wallet 系统
432
  """
 
13
  from comment_store import COMMENT_MAX_LENGTH, append_comment, increment_comment_count, attach_comment_counts, read_comment_view
14
  from 安全认证 import require_auth
15
  from db_utils import read_public_source, record_view, sort_cache
16
+ from database_sql import get_db, SessionLocal
17
  from models_sql import Wallet, Transaction
18
  from notifications import add_notification
19
  from tip_transaction import lock_tip_wallets
20
  from tip_store import run_tip_effect
21
  import time
22
+ from owned_thread import OwnedThreadGroup, owned_sync_endpoint, owned_session_endpoint
23
  from post_store import publish_post, edit_post, delete_post as remove_post, PostStoreError
24
  import uuid
25
  import hashlib
 
36
  stop_posts_io = _posts_io.stop
37
  close_posts_io = _posts_io.close
38
  _posts_endpoint = owned_sync_endpoint(_posts_io)
39
+ _posts_session_endpoint = owned_session_endpoint(_posts_io, lambda: SessionLocal(), 'db_session')
40
 
41
  router = APIRouter()
42
 
 
427
 
428
  @router.post("/api/posts/{post_id}/tip")
429
  @shared_limit(10)
430
+ @_posts_session_endpoint
431
+ def tip_post(request: Request, post_id: str, amount: int, is_anon: bool = False, current_user: str = Depends(require_auth), db_session: Session = Depends(get_db)):
432
  """
433
  打赏帖子(原子操作,并发安全)- 使用 SQL Wallet 系统
434
  """
router_prompts.py CHANGED
@@ -21,14 +21,14 @@ import 数据库连接 as db
21
  from comment_store import COMMENT_MAX_LENGTH, append_comment, increment_comment_count, attach_comment_counts, read_comment_view
22
  from 安全认证 import require_auth, optional_auth, is_admin
23
  from db_utils import read_public_source, record_view, sort_cache
24
- from database_sql import get_db
25
  from models_sql import Wallet, Transaction, Ownership
26
  from notifications import add_notification
27
  from tip_transaction import lock_tip_wallets
28
  from purchase_transaction import effective_resource_price, lock_resource_purchase_wallets
29
  from tip_store import run_tip_effect
30
  import time
31
- from owned_thread import OwnedThreadGroup, owned_sync_endpoint
32
  from prompt_store import (PromptStoreError, publish_prompt, edit_prompt,
33
  delete_prompt as remove_prompt, project_price, load_categories, modify_category, read_prompts)
34
  import uuid
@@ -46,6 +46,7 @@ start_prompts_io = _prompts_io.start
46
  stop_prompts_io = _prompts_io.stop
47
  close_prompts_io = _prompts_io.close
48
  _prompts_endpoint = owned_sync_endpoint(_prompts_io)
 
49
 
50
  router = APIRouter()
51
 
@@ -340,7 +341,8 @@ def get_my_prompts(current_user: str = Depends(require_auth)):
340
 
341
 
342
  @router.get("/api/prompts/{prompt_id}")
343
- async def get_prompt_detail(prompt_id: str, current_user: str = Depends(optional_auth),
 
344
  db_session: Session = Depends(get_db)):
345
  """
346
  获取提示词详情
@@ -657,7 +659,8 @@ def toggle_favorite(request: Request, prompt_id: str, current_user: str = Depend
657
 
658
  @router.post("/api/prompts/{prompt_id}/tip")
659
  @shared_limit(10)
660
- async def tip_prompt(request: Request, prompt_id: str, amount: int, is_anon: bool = False,
 
661
  current_user: str = Depends(require_auth), db_session: Session = Depends(get_db)):
662
  """
663
  打赏提示词(原子操作,并发安全)- 使用 SQL Wallet 系统
@@ -823,7 +826,8 @@ async def tip_prompt(request: Request, prompt_id: str, amount: int, is_anon: boo
823
 
824
  @router.post("/api/prompts/{prompt_id}/purchase")
825
  @shared_limit(10) # 🔒 P0安全优化:购买每分钟最多10次
826
- async def purchase_prompt(request: Request, prompt_id: str,
 
827
  purchase: Optional[PromptPurchaseRequest] = None,
828
  current_user: str = Depends(require_auth), db_session: Session = Depends(get_db)):
829
  """资金与所有权原子提交;通知失败不改变已提交的购买结果。"""
 
21
  from comment_store import COMMENT_MAX_LENGTH, append_comment, increment_comment_count, attach_comment_counts, read_comment_view
22
  from 安全认证 import require_auth, optional_auth, is_admin
23
  from db_utils import read_public_source, record_view, sort_cache
24
+ from database_sql import get_db, SessionLocal
25
  from models_sql import Wallet, Transaction, Ownership
26
  from notifications import add_notification
27
  from tip_transaction import lock_tip_wallets
28
  from purchase_transaction import effective_resource_price, lock_resource_purchase_wallets
29
  from tip_store import run_tip_effect
30
  import time
31
+ from owned_thread import OwnedThreadGroup, owned_sync_endpoint, owned_session_endpoint
32
  from prompt_store import (PromptStoreError, publish_prompt, edit_prompt,
33
  delete_prompt as remove_prompt, project_price, load_categories, modify_category, read_prompts)
34
  import uuid
 
46
  stop_prompts_io = _prompts_io.stop
47
  close_prompts_io = _prompts_io.close
48
  _prompts_endpoint = owned_sync_endpoint(_prompts_io)
49
+ _prompts_session_endpoint = owned_session_endpoint(_prompts_io, lambda: SessionLocal(), 'db_session')
50
 
51
  router = APIRouter()
52
 
 
341
 
342
 
343
  @router.get("/api/prompts/{prompt_id}")
344
+ @_prompts_session_endpoint
345
+ def get_prompt_detail(prompt_id: str, current_user: str = Depends(optional_auth),
346
  db_session: Session = Depends(get_db)):
347
  """
348
  获取提示词详情
 
659
 
660
  @router.post("/api/prompts/{prompt_id}/tip")
661
  @shared_limit(10)
662
+ @_prompts_session_endpoint
663
+ def tip_prompt(request: Request, prompt_id: str, amount: int, is_anon: bool = False,
664
  current_user: str = Depends(require_auth), db_session: Session = Depends(get_db)):
665
  """
666
  打赏提示词(原子操作,并发安全)- 使用 SQL Wallet 系统
 
826
 
827
  @router.post("/api/prompts/{prompt_id}/purchase")
828
  @shared_limit(10) # 🔒 P0安全优化:购买每分钟最多10次
829
+ @_prompts_session_endpoint
830
+ def purchase_prompt(request: Request, prompt_id: str,
831
  purchase: Optional[PromptPurchaseRequest] = None,
832
  current_user: str = Depends(require_auth), db_session: Session = Depends(get_db)):
833
  """资金与所有权原子提交;通知失败不改变已提交的购买结果。"""
router_wallet.py CHANGED
@@ -16,7 +16,6 @@ from fastapi.responses import Response
16
  from sqlalchemy.orm import Session
17
  from pydantic import BaseModel, Field
18
  import time
19
- import asyncio
20
  import uuid
21
  import hashlib
22
  import os
@@ -137,7 +136,8 @@ def calculate_tx_hash(tx_id, account, tx_type, amount, prev_hash):
137
 
138
  @router.post("/api/wallet/create_recharge_order")
139
  @shared_limit(10)
140
- async def create_recharge_order(request: Request, req: RechargeRequest, current_user: str = Depends(require_auth), db: Session = Depends(get_db)):
 
141
  if not alipay:
142
  raise HTTPException(status_code=500, detail="支付网关配置错误,请联系管理员")
143
  if type(req.amount) is not int or not 1 <= req.amount <= 10000:
@@ -146,7 +146,7 @@ async def create_recharge_order(request: Request, req: RechargeRequest, current_
146
  try:
147
  # 先持久化;失败时不能生成可付款订单。
148
  persist_order(db, order_id, current_user, req.amount)
149
- result = await asyncio.to_thread(alipay.api_alipay_trade_precreate,
150
  out_trade_no=order_id, total_amount=str(req.amount),
151
  subject=f"ComfyUI Community Points - {current_user}")
152
  if not isinstance(result, dict) or result.get("code") != "10000" or not isinstance(result.get("qr_code"), str) or not result["qr_code"]:
@@ -157,11 +157,9 @@ async def create_recharge_order(request: Request, req: RechargeRequest, current_
157
  raise HTTPException(status_code=503, detail="创建支付订单失败,请稍后查询确认")
158
 
159
 
160
- @router.post("/api/wallet/alipay_notify")
161
- async def alipay_notify(request: Request, db: Session = Depends(get_db)):
162
  try:
163
- form = await request.form()
164
- pairs = list(form.multi_items())
165
  if len({key for key, _ in pairs}) != len(pairs):
166
  raise ValueError("duplicate payment fields")
167
  data = dict(pairs)
@@ -169,7 +167,7 @@ async def alipay_notify(request: Request, db: Session = Depends(get_db)):
169
  sign_type = data.pop("sign_type", None)
170
  if not alipay or not isinstance(signature, str) or not signature or sign_type != "RSA2":
171
  raise ValueError("invalid signature fields")
172
- if not await asyncio.to_thread(alipay.verify, data, signature):
173
  raise ValueError("invalid signature")
174
  app_id = os.environ.get("ALIPAY_APPID", "").strip()
175
  seller_id = os.environ.get("ALIPAY_SELLER_ID", "").strip()
@@ -191,8 +189,20 @@ async def alipay_notify(request: Request, db: Session = Depends(get_db)):
191
  return Response(content="fail", media_type="text/plain")
192
 
193
 
 
 
 
 
 
 
 
 
 
 
 
194
  @router.get("/api/wallet/check_order/{order_id}")
195
- async def check_order(order_id: str, current_user: str = Depends(require_auth), db: Session = Depends(get_db)):
 
196
  try:
197
  info = read_order(db, order_id)
198
  if info is None or info["account"] != current_user:
@@ -201,7 +211,7 @@ async def check_order(order_id: str, current_user: str = Depends(require_auth),
201
  return {"status": "SUCCESS"}
202
  if not alipay:
203
  return {"status": "PENDING"}
204
- result = await asyncio.to_thread(alipay.api_alipay_trade_query, out_trade_no=order_id)
205
  if not isinstance(result, dict) or result.get("code") != "10000":
206
  return {"status": "PENDING"}
207
  if result.get("out_trade_no") != order_id:
 
16
  from sqlalchemy.orm import Session
17
  from pydantic import BaseModel, Field
18
  import time
 
19
  import uuid
20
  import hashlib
21
  import os
 
136
 
137
  @router.post("/api/wallet/create_recharge_order")
138
  @shared_limit(10)
139
+ @_wallet_endpoint
140
+ def create_recharge_order(request: Request, req: RechargeRequest, current_user: str = Depends(require_auth), db: Session = Depends(get_db)):
141
  if not alipay:
142
  raise HTTPException(status_code=500, detail="支付网关配置错误,请联系管理员")
143
  if type(req.amount) is not int or not 1 <= req.amount <= 10000:
 
146
  try:
147
  # 先持久化;失败时不能生成可付款订单。
148
  persist_order(db, order_id, current_user, req.amount)
149
+ result = alipay.api_alipay_trade_precreate(
150
  out_trade_no=order_id, total_amount=str(req.amount),
151
  subject=f"ComfyUI Community Points - {current_user}")
152
  if not isinstance(result, dict) or result.get("code") != "10000" or not isinstance(result.get("qr_code"), str) or not result["qr_code"]:
 
157
  raise HTTPException(status_code=503, detail="创建支付订单失败,请稍后查询确认")
158
 
159
 
160
+ @_wallet_endpoint
161
+ def _process_alipay_notification(pairs, db: Session = Depends(get_db)):
162
  try:
 
 
163
  if len({key for key, _ in pairs}) != len(pairs):
164
  raise ValueError("duplicate payment fields")
165
  data = dict(pairs)
 
167
  sign_type = data.pop("sign_type", None)
168
  if not alipay or not isinstance(signature, str) or not signature or sign_type != "RSA2":
169
  raise ValueError("invalid signature fields")
170
+ if not alipay.verify(data, signature):
171
  raise ValueError("invalid signature")
172
  app_id = os.environ.get("ALIPAY_APPID", "").strip()
173
  seller_id = os.environ.get("ALIPAY_SELLER_ID", "").strip()
 
189
  return Response(content="fail", media_type="text/plain")
190
 
191
 
192
+ @router.post("/api/wallet/alipay_notify")
193
+ async def alipay_notify(request: Request):
194
+ try:
195
+ form = await request.form()
196
+ pairs = list(form.multi_items())
197
+ except Exception as error:
198
+ run_tip_effect(lambda: logger.error(f"RECHARGE_ERROR | error_type={type(error).__name__}"))
199
+ return Response(content="fail", media_type="text/plain")
200
+ return await _process_alipay_notification(pairs)
201
+
202
+
203
  @router.get("/api/wallet/check_order/{order_id}")
204
+ @_wallet_endpoint
205
+ def check_order(order_id: str, current_user: str = Depends(require_auth), db: Session = Depends(get_db)):
206
  try:
207
  info = read_order(db, order_id)
208
  if info is None or info["account"] != current_user:
 
211
  return {"status": "SUCCESS"}
212
  if not alipay:
213
  return {"status": "PENDING"}
214
+ result = alipay.api_alipay_trade_query(out_trade_no=order_id)
215
  if not isinstance(result, dict) or result.get("code") != "10000":
216
  return {"status": "PENDING"}
217
  if result.get("out_trade_no") != order_id: