's'
This commit is contained in:
12
.gitignore
vendored
Normal file
12
.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# 日志文件(不产生,避免 git 本地/线上不一致)
|
||||||
|
*.log
|
||||||
|
payment_notify.log
|
||||||
|
xorpay_notify.log
|
||||||
|
|
||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
venv/
|
||||||
|
.venv/
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
@@ -51,14 +51,11 @@ async def global_exception_handler(request: Request, exc: Exception):
|
|||||||
logging.error(f"未处理异常: {request.url.path} - {exc}", exc_info=True)
|
logging.error(f"未处理异常: {request.url.path} - {exc}", exc_info=True)
|
||||||
return JSONResponse(status_code=500, content={"detail": str(exc)})
|
return JSONResponse(status_code=500, content={"detail": str(exc)})
|
||||||
|
|
||||||
# 日志
|
# 日志(仅控制台,不写文件,避免 git 本地/线上不一致)
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
level=logging.INFO,
|
level=logging.INFO,
|
||||||
format="%(asctime)s - %(message)s",
|
format="%(asctime)s - %(message)s",
|
||||||
handlers=[
|
handlers=[logging.StreamHandler()],
|
||||||
logging.FileHandler("payment_notify.log"),
|
|
||||||
logging.StreamHandler(),
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 挂载路由
|
# 挂载路由
|
||||||
|
|||||||
Binary file not shown.
@@ -167,3 +167,24 @@ class ZPayProvider(PaymentProvider):
|
|||||||
|
|
||||||
def success_response(self) -> str:
|
def success_response(self) -> str:
|
||||||
return "success"
|
return "success"
|
||||||
|
|
||||||
|
def query_order_status(self, out_trade_no: str, timeout: int = 15) -> Dict[str, Any]:
|
||||||
|
"""查询 ZPAY 订单支付状态(供 nomadvip/digital/cnomadcna/nomadlms 共用)"""
|
||||||
|
url = f"https://zpayz.cn/api.php?act=order&pid={self.pid}&key={self.key}&out_trade_no={out_trade_no}"
|
||||||
|
try:
|
||||||
|
resp = requests.get(url, timeout=timeout)
|
||||||
|
result = resp.json() if resp.ok else {}
|
||||||
|
except Exception as e:
|
||||||
|
return {"paid": False, "error": str(e)}
|
||||||
|
try:
|
||||||
|
code = result.get("code", 0)
|
||||||
|
code = int(code) if isinstance(code, (int, float)) or str(code).isdigit() else 0
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
code = 0
|
||||||
|
if code != 1:
|
||||||
|
return {"paid": False, "msg": result.get("msg", "查询失败")}
|
||||||
|
try:
|
||||||
|
status = int(result.get("status", 0))
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
status = 0
|
||||||
|
return {"paid": status == 1, "status": status}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -7,10 +7,9 @@ import random
|
|||||||
import string
|
import string
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import requests
|
|
||||||
from fastapi import APIRouter, Request, HTTPException
|
from fastapi import APIRouter, Request, HTTPException
|
||||||
|
|
||||||
from ..config import BASE_URL, ZPAY_PID, ZPAY_KEY
|
from ..config import BASE_URL
|
||||||
from ..payment import get_payment_provider
|
from ..payment import get_payment_provider
|
||||||
from ..payment.zpay import ZPayProvider
|
from ..payment.zpay import ZPayProvider
|
||||||
from ..services import handle_payment_success, processed_orders
|
from ..services import handle_payment_success, processed_orders
|
||||||
@@ -142,27 +141,12 @@ def create_digital_router(prefix: str, project_name: str) -> APIRouter:
|
|||||||
async def zpay_order_status(out_trade_no: str):
|
async def zpay_order_status(out_trade_no: str):
|
||||||
"""查询 ZPAY 订单支付状态"""
|
"""查询 ZPAY 订单支付状态"""
|
||||||
provider = get_payment_provider()
|
provider = get_payment_provider()
|
||||||
if provider.name != "zpay":
|
if not isinstance(provider, ZPayProvider):
|
||||||
raise HTTPException(status_code=400, detail="仅 zpay 渠道支持")
|
raise HTTPException(status_code=400, detail="仅 zpay 渠道支持")
|
||||||
url = f"https://zpayz.cn/api.php?act=order&pid={ZPAY_PID}&key={ZPAY_KEY}&out_trade_no={out_trade_no}"
|
result = provider.query_order_status(out_trade_no, timeout=15)
|
||||||
try:
|
if result.get("error"):
|
||||||
resp = requests.get(url, timeout=10)
|
logging.warning(f"{project_name} ZPAY 订单查询失败: {result.get('error')}")
|
||||||
result = resp.json() if resp.ok else {}
|
return result
|
||||||
except Exception as e:
|
|
||||||
logging.warning(f"ZPAY 订单查询失败: {e}")
|
|
||||||
return {"paid": False, "error": str(e)}
|
|
||||||
try:
|
|
||||||
code = result.get("code", 0)
|
|
||||||
code = int(code) if isinstance(code, (int, float)) or str(code).isdigit() else 0
|
|
||||||
except (ValueError, TypeError):
|
|
||||||
code = 0
|
|
||||||
if code != 1:
|
|
||||||
return {"paid": False, "msg": result.get("msg", "查询失败")}
|
|
||||||
try:
|
|
||||||
status = int(result.get("status", 0))
|
|
||||||
except (ValueError, TypeError):
|
|
||||||
status = 0
|
|
||||||
return {"paid": status == 1, "status": status}
|
|
||||||
|
|
||||||
@router.post("/xorpay_notify")
|
@router.post("/xorpay_notify")
|
||||||
async def xorpay_notify(request: Request):
|
async def xorpay_notify(request: Request):
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import time
|
|||||||
from fastapi import APIRouter, Request, HTTPException
|
from fastapi import APIRouter, Request, HTTPException
|
||||||
from fastapi.responses import RedirectResponse, JSONResponse
|
from fastapi.responses import RedirectResponse, JSONResponse
|
||||||
|
|
||||||
import requests
|
|
||||||
|
|
||||||
from ..config import BASE_URL, ZPAY_PID, ZPAY_KEY
|
from ..config import BASE_URL, ZPAY_PID, ZPAY_KEY
|
||||||
from ..payment.zpay import ZPayProvider
|
from ..payment.zpay import ZPayProvider
|
||||||
from ..services import handle_payment_success, processed_orders
|
from ..services import handle_payment_success, processed_orders
|
||||||
@@ -118,25 +116,10 @@ async def nomadvip_payh5_redirect(item: dict, request: Request):
|
|||||||
@router.get("/zpay_order_status")
|
@router.get("/zpay_order_status")
|
||||||
async def nomadvip_zpay_order_status(out_trade_no: str):
|
async def nomadvip_zpay_order_status(out_trade_no: str):
|
||||||
"""nomadvip 专用:查询 ZPAY 订单支付状态"""
|
"""nomadvip 专用:查询 ZPAY 订单支付状态"""
|
||||||
url = f"https://zpayz.cn/api.php?act=order&pid={ZPAY_PID}&key={ZPAY_KEY}&out_trade_no={out_trade_no}"
|
result = _nomadvip_zpay.query_order_status(out_trade_no, timeout=15)
|
||||||
try:
|
if result.get("error"):
|
||||||
resp = requests.get(url, timeout=10)
|
logging.warning(f"nomadvip ZPAY 订单查询失败: {result.get('error')}")
|
||||||
result = resp.json() if resp.ok else {}
|
return result
|
||||||
except Exception as e:
|
|
||||||
logging.warning(f"nomadvip ZPAY 订单查询失败: {e}")
|
|
||||||
return {"paid": False, "error": str(e)}
|
|
||||||
try:
|
|
||||||
code = result.get("code", 0)
|
|
||||||
code = int(code) if isinstance(code, (int, float)) or str(code).isdigit() else 0
|
|
||||||
except (ValueError, TypeError):
|
|
||||||
code = 0
|
|
||||||
if code != 1:
|
|
||||||
return {"paid": False, "msg": result.get("msg", "查询失败")}
|
|
||||||
try:
|
|
||||||
status = int(result.get("status", 0))
|
|
||||||
except (ValueError, TypeError):
|
|
||||||
status = 0
|
|
||||||
return {"paid": status == 1, "status": status}
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/zpay_notify")
|
@router.get("/zpay_notify")
|
||||||
|
|||||||
@@ -4,3 +4,14 @@
|
|||||||
2026-03-08 06:31:18,405 - ZPAY 땐데꿴璂呵겨: HTTPSConnectionPool(host='zpayz.cn', port=443): Read timed out. (read timeout=10)
|
2026-03-08 06:31:18,405 - ZPAY 땐데꿴璂呵겨: HTTPSConnectionPool(host='zpayz.cn', port=443): Read timed out. (read timeout=10)
|
||||||
2026-03-08 06:39:41,805 - ZPAY 땐데꿴璂呵겨: HTTPSConnectionPool(host='zpayz.cn', port=443): Read timed out. (read timeout=10)
|
2026-03-08 06:39:41,805 - ZPAY 땐데꿴璂呵겨: HTTPSConnectionPool(host='zpayz.cn', port=443): Read timed out. (read timeout=10)
|
||||||
2026-03-08 06:40:22,362 - ZPAY 땐데꿴璂呵겨: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
|
2026-03-08 06:40:22,362 - ZPAY 땐데꿴璂呵겨: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
|
||||||
|
2026-03-10 05:01:08,564 - nomadvip payh5/redirect 헝헹: item={'user_id': 'user1773135567826', 'total_fee': 18800, 'type': 'vip', 'channel': 'wxpay', 'return_url': 'http://192.168.41.222:3000/paid', 'device': 'pc', 'client_ip': '192.168.41.222'}
|
||||||
|
2026-03-10 05:02:23,523 - nomadvip ZPAY 땐데꿴璂呵겨: HTTPSConnectionPool(host='zpayz.cn', port=443): Read timed out. (read timeout=10)
|
||||||
|
2026-03-10 05:02:46,901 - nomadvip payh5/redirect 헝헹: item={'user_id': 'user1773136912337', 'total_fee': 18800, 'type': 'vip', 'channel': 'wxpay', 'return_url': 'http://192.168.41.222:3000/paid', 'device': 'wechat', 'client_ip': '192.168.41.34'}
|
||||||
|
2026-03-10 05:03:26,325 - nomadvip payh5/redirect 헝헹: item={'user_id': 'user1773136912337', 'total_fee': 18800, 'type': 'vip', 'channel': 'wxpay', 'return_url': 'http://192.168.41.222:3000/paid', 'device': 'wechat', 'client_ip': '192.168.41.34'}
|
||||||
|
2026-03-10 05:04:54,606 - nomadvip ZPAY 땐데꿴璂呵겨: ('Connection aborted.', ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None))
|
||||||
|
2026-03-10 05:06:39,639 - nomadvip payh5/redirect 헝헹: item={'user_id': 'user1773136912337', 'total_fee': 18800, 'type': 'vip', 'channel': 'wxpay', 'return_url': 'http://192.168.41.222:3000/paid', 'device': 'wechat', 'client_ip': '192.168.41.34'}
|
||||||
|
2026-03-10 05:07:03,035 - nomadvip payh5/redirect 헝헹: item={'user_id': 'user1773136912337', 'total_fee': 18800, 'type': 'vip', 'channel': 'wxpay', 'return_url': 'http://192.168.41.222:3000/paid', 'device': 'wechat', 'client_ip': '192.168.41.34'}
|
||||||
|
2026-03-10 05:07:37,981 - nomadvip ZPAY 땐데꿴璂呵겨: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
|
||||||
|
2026-03-10 05:08:31,484 - nomadvip payh5/redirect 헝헹: item={'user_id': 'user1773136912337', 'total_fee': 18800, 'type': 'vip', 'channel': 'wxpay', 'return_url': 'http://192.168.41.222:3000/paid', 'device': 'wechat', 'client_ip': '192.168.41.34'}
|
||||||
|
2026-03-10 05:15:55,977 - nomadvip payh5/redirect 헝헹: item={'user_id': 'user1773136912337', 'total_fee': 18800, 'type': 'vip', 'channel': 'wxpay', 'return_url': 'http://192.168.41.222:3000/paid', 'device': 'wechat', 'client_ip': '192.168.41.34'}
|
||||||
|
2026-03-10 05:22:16,735 - nomadvip payh5/redirect 헝헹: item={'user_id': 'user1773131395284', 'total_fee': 18800, 'type': 'vip', 'channel': 'wxpay', 'return_url': 'http://localhost:3000/paid', 'device': 'pc', 'client_ip': '127.0.0.1'}
|
||||||
|
|||||||
Reference in New Issue
Block a user