Spaces:
Running
Running
Download open_transaction.py from ZHIWEI666/ComfyUI-Ranking-API: direct link, hf CLI and curl.
- Browser
- Download file 4.95 kB
-
https://huggingface.co/spaces/ZHIWEI666/ComfyUI-Ranking-API/resolve/main/open_transaction.py
- Command line
-
hf download hf://spaces/ZHIWEI666/ComfyUI-Ranking-API/open_transaction.py
-
curl -L -o open_transaction.py https://huggingface.co/spaces/ZHIWEI666/ComfyUI-Ranking-API/resolve/main/open_transaction.py
4.95 kB
| """开放资金接口的实时插件授权与钱包写锁;事务由调用方提交/回滚。""" | |
| import hmac | |
| import hashlib | |
| import json | |
| import re | |
| from decimal import Decimal | |
| from fastapi import HTTPException | |
| from models_sql import RegisteredPlugin, OpenApiOperation, Transaction | |
| from plugin_permissions import parse_permissions | |
| from tip_transaction import lock_wallet_accounts | |
| def validate_live_plugin(row, key, permission): | |
| if row is None or not row.enabled: | |
| raise HTTPException(status_code=403, detail="插件已停用或不存在") | |
| if not isinstance(row.plugin_key, str) or not isinstance(key, str) or not hmac.compare_digest(row.plugin_key.encode('utf-8'), key.encode('utf-8')): | |
| raise HTTPException(status_code=403, detail="Plugin Key 已失效") | |
| try: | |
| permissions = parse_permissions(row.permissions) | |
| except Exception: | |
| raise HTTPException(status_code=503, detail="插件权限配置暂不可用") | |
| if permission not in permissions: | |
| raise HTTPException(status_code=403, detail="插件无权限调用该接口") | |
| return row | |
| def lock_open_wallet(session, account, plugin_id, key, permission): | |
| # 首项资金SQL取得SQLite写事务;其它方言先锁钱包再锁插件,所有开放资金路径同序。 | |
| wallet = lock_wallet_accounts(session, (account,))[account] | |
| row = session.query(RegisteredPlugin).filter(RegisteredPlugin.plugin_id == plugin_id).populate_existing().with_for_update().first() | |
| validate_live_plugin(row, key, permission) | |
| return wallet, row | |
| def positive_integer(value): | |
| if isinstance(value, bool) or not isinstance(value, int) or value <= 0: | |
| raise HTTPException(status_code=503, detail="插件额度配置暂不可用") | |
| return value | |
| def quota_total(value): | |
| """SQL聚合可返回整数或精确Decimal;拒绝浮点/字符串/非整数与坏统计。""" | |
| if isinstance(value, Decimal) and value.is_finite() and value >= 0 and value == value.to_integral_value(): | |
| return int(value) | |
| if isinstance(value, bool) or not isinstance(value, int) or value < 0: | |
| raise ValueError("invalid quota history") | |
| return value | |
| def open_operation_identity(request_id, account, plugin_id, kind, payload): | |
| if request_id is None: | |
| return None | |
| if not isinstance(request_id, str) or re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._:-]{7,127}", request_id) is None: | |
| raise HTTPException(status_code=422, detail="OPEN_REQUEST_ID_INVALID") | |
| encode = lambda value: json.dumps(value, ensure_ascii=False, separators=(',', ':'), allow_nan=False).encode('utf-8') | |
| key = hashlib.sha256(encode([plugin_id, account, kind, request_id])).hexdigest() | |
| fingerprint = hashlib.sha256(encode(payload)).hexdigest() | |
| return key, fingerprint | |
| def read_open_operation(db, identity, account, plugin_id, kind, amount, reference_id): | |
| if identity is None: | |
| return None | |
| key, fingerprint = identity | |
| row = db.get(OpenApiOperation, key) | |
| if row is None: | |
| if db.get(Transaction, f'{kind}_{key}') is not None: | |
| raise HTTPException(status_code=503, detail="OPEN_OPERATION_UNAVAILABLE") | |
| return None | |
| if row.request_hash != fingerprint: | |
| raise HTTPException(status_code=409, detail="OPEN_REQUEST_CONFLICT") | |
| try: | |
| response = json.loads(row.response_payload) | |
| transaction = db.get(Transaction, row.transaction_id) | |
| if (not isinstance(response, dict) or set(response) != {'success', 'remaining_balance', 'transaction_id'} | |
| or response['success'] is not True or type(response['remaining_balance']) is not int | |
| or response['transaction_id'] != row.transaction_id or row.transaction_id != f'{kind}_{key}' | |
| or transaction is None or transaction.account != account or transaction.tx_type != kind | |
| or transaction.source_plugin != plugin_id or transaction.related_account != plugin_id | |
| or type(transaction.amount) is not int or transaction.amount != amount | |
| or transaction.item_id != reference_id | |
| or not isinstance(transaction.prev_hash, str) | |
| or transaction.tx_hash != hashlib.sha256( | |
| f"{transaction.tx_id}{account}{kind}{amount}{transaction.prev_hash}".encode()).hexdigest()): | |
| raise ValueError('invalid open operation') | |
| except Exception: | |
| raise HTTPException(status_code=503, detail="OPEN_OPERATION_UNAVAILABLE") | |
| return response | |
| def save_open_operation(db, identity, response): | |
| if identity is not None: | |
| key, fingerprint = identity | |
| db.add(OpenApiOperation(request_key=key, request_hash=fingerprint, | |
| transaction_id=response['transaction_id'], | |
| response_payload=json.dumps(response, ensure_ascii=False, separators=(',', ':'), allow_nan=False))) | |