初步增加, 扫码登录成功
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
"""应用宝充值任务服务。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ..models import YybRechargeTask
|
||||
from .yyb_worker_client import YybWorkerClient
|
||||
|
||||
|
||||
def _utcnow():
|
||||
return datetime.now(timezone.utc)
|
||||
|
||||
|
||||
def cleanup_orphan_yyb_tasks(db: Session, message: str) -> int:
|
||||
rows = db.query(YybRechargeTask).filter(YybRechargeTask.status.in_(["created", "waiting_login", "running", "ready"])).all()
|
||||
for task in rows:
|
||||
task.status = "failed"
|
||||
task.message = message
|
||||
task.finished_at = _utcnow()
|
||||
if rows:
|
||||
db.commit()
|
||||
return len(rows)
|
||||
|
||||
|
||||
def sync_task(db: Session, task: YybRechargeTask, worker: YybWorkerClient) -> YybRechargeTask:
|
||||
data = worker.get_job(task.worker_job_id)
|
||||
task.status = str(data.get("status", task.status))
|
||||
task.phase = str(data.get("phase", task.phase))
|
||||
task.message = str(data.get("message", task.message))
|
||||
if data.get("provider"):
|
||||
task.provider = str(data["provider"])
|
||||
if data.get("qr_data"):
|
||||
task.login_qr_data = str(data["qr_data"])
|
||||
task.result = {**(task.result or {}), "login_qr_mime_type": data.get("qr_mime_type", "image/jpeg")}
|
||||
if data.get("payment_qr_data"):
|
||||
task.payment_qr_data = str(data["payment_qr_data"])
|
||||
task.result = {**(task.result or {}), "payment_qr_mime_type": data.get("payment_qr_mime_type", "image/png")}
|
||||
task.result = {
|
||||
**(task.result or {}),
|
||||
"logs": data.get("logs", []),
|
||||
"payment_status": data.get("payment_status"),
|
||||
}
|
||||
if task.status in {"success", "failed"} and task.finished_at is None:
|
||||
task.finished_at = _utcnow()
|
||||
db.commit()
|
||||
db.refresh(task)
|
||||
return task
|
||||
|
||||
|
||||
def public_task(task: YybRechargeTask, include_qr: bool = True,
|
||||
include_payment_qr: bool | None = None) -> dict[str, Any]:
|
||||
result: dict[str, Any] = {
|
||||
"id": task.id, "task_id": task.task_id,
|
||||
"provider": task.provider, "platform": task.platform, "points": task.points,
|
||||
"product_id": task.product_id, "zone_id": task.zone_id, "zone_name": task.zone_name,
|
||||
"role_id": task.role_id, "role_name": task.role_name, "status": task.status,
|
||||
"phase": task.phase, "message": task.message, "result": task.result,
|
||||
"created_by": task.created_by, "created_at": task.created_at,
|
||||
"finished_at": task.finished_at,
|
||||
}
|
||||
if task.result:
|
||||
result["login_qr_mime_type"] = task.result.get("login_qr_mime_type", "image/jpeg")
|
||||
result["payment_qr_mime_type"] = task.result.get("payment_qr_mime_type", "image/png")
|
||||
if include_payment_qr is None:
|
||||
include_payment_qr = include_qr
|
||||
if include_qr:
|
||||
result["login_qr_data"] = task.login_qr_data or ""
|
||||
if include_payment_qr:
|
||||
result["payment_qr_data"] = task.payment_qr_data or ""
|
||||
return result
|
||||
@@ -0,0 +1,57 @@
|
||||
"""应用宝 Worker HTTP 客户端。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
class YybWorkerError(RuntimeError):
|
||||
"""Worker 返回业务错误。"""
|
||||
|
||||
|
||||
class YybWorkerClient:
|
||||
def __init__(self) -> None:
|
||||
self.base_url = os.getenv("YYB_WORKER_URL", "http://127.0.0.1:8810").rstrip("/")
|
||||
self.key = os.getenv("YYB_WORKER_KEY", "")
|
||||
self.timeout = float(os.getenv("YYB_WORKER_TIMEOUT", "30"))
|
||||
|
||||
def _request(self, method: str, path: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
||||
headers = {"Accept": "application/json"}
|
||||
if self.key:
|
||||
headers["Authorization"] = f"Bearer {self.key}"
|
||||
try:
|
||||
response = requests.request(method, self.base_url + path, json=payload,
|
||||
headers=headers, timeout=self.timeout)
|
||||
data = response.json()
|
||||
except (requests.RequestException, ValueError) as exc:
|
||||
raise YybWorkerError(f"应用宝 Worker 不可用: {exc}") from exc
|
||||
if response.status_code >= 400:
|
||||
raise YybWorkerError(str(data.get("detail", "Worker 请求失败")))
|
||||
return data
|
||||
|
||||
def create_job(self) -> dict[str, Any]:
|
||||
return self._request("POST", "/v1/jobs")
|
||||
|
||||
def login(self, worker_job_id: str, provider: str, timeout: int = 600) -> dict[str, Any]:
|
||||
return self._request("POST", f"/v1/jobs/{worker_job_id}/login",
|
||||
{"provider": provider, "timeout": timeout})
|
||||
|
||||
def get_job(self, worker_job_id: str) -> dict[str, Any]:
|
||||
return self._request("GET", f"/v1/jobs/{worker_job_id}")
|
||||
|
||||
def selection_options(self, worker_job_id: str, platform: str,
|
||||
points: int | None = None, zone_id: str | None = None) -> dict[str, Any]:
|
||||
return self._request("POST", f"/v1/jobs/{worker_job_id}/selection-options",
|
||||
{"platform": platform, "points": points, "zone_id": zone_id})
|
||||
|
||||
def selection(self, worker_job_id: str, selection: dict[str, Any]) -> dict[str, Any]:
|
||||
return self._request("POST", f"/v1/jobs/{worker_job_id}/selection", selection)
|
||||
|
||||
def payment(self, worker_job_id: str) -> dict[str, Any]:
|
||||
return self._request("POST", f"/v1/jobs/{worker_job_id}/payment")
|
||||
|
||||
def stop(self, worker_job_id: str) -> dict[str, Any]:
|
||||
return self._request("POST", f"/v1/jobs/{worker_job_id}/stop")
|
||||
Reference in New Issue
Block a user