fix: 付呗支付复查/轮询改查付呗单,避免一直显示支付中
下单已走付呗但复查仍查微信直连,导致付成功不入账;现按流水查付呗并履约,同时加强回调日志。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
91
jituan/services/fubei_query.py
Normal file
91
jituan/services/fubei_query.py
Normal file
@@ -0,0 +1,91 @@
|
||||
"""付呗支付结果确认:主动查单(轮询/复查兜底,不依赖回调)。"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Any, Dict, Optional, Tuple
|
||||
|
||||
from jituan.constants import PAY_CHANNEL_FUBEI_WX_MINI
|
||||
from jituan.services.club_payment_channel import get_fubei_config
|
||||
from jituan.services import fubei_client
|
||||
from jituan.services.mini_pay_router import get_pay_ledger
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def is_fubei_out_trade_no(out_trade_no: str) -> bool:
|
||||
ledger = get_pay_ledger(out_trade_no)
|
||||
return bool(ledger and ledger.channel == PAY_CHANNEL_FUBEI_WX_MINI)
|
||||
|
||||
|
||||
def query_fubei_trade(
|
||||
out_trade_no: str,
|
||||
club_id: Optional[str] = None,
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
查询付呗订单。
|
||||
非付呗单返回 None;付呗单返回 data 字典(含 trade_state 等)。
|
||||
"""
|
||||
ledger = get_pay_ledger(out_trade_no)
|
||||
if not ledger or ledger.channel != PAY_CHANNEL_FUBEI_WX_MINI:
|
||||
return None
|
||||
|
||||
cid = (club_id or ledger.club_id or '').strip()
|
||||
cfg = get_fubei_config(cid)
|
||||
if not cfg or not cfg.app_id or not cfg.api_key:
|
||||
logger.error('[FUBEI_QUERY] 配置缺失 club=%s out_trade_no=%s', cid, out_trade_no)
|
||||
raise Exception('付呗查单配置缺失')
|
||||
|
||||
data = fubei_client.query_order(
|
||||
gateway_url=cfg.gateway_url,
|
||||
app_id=cfg.app_id,
|
||||
app_secret=cfg.api_key,
|
||||
merchant_order_sn=out_trade_no,
|
||||
order_sn=ledger.provider_order_sn or '',
|
||||
)
|
||||
logger.info(
|
||||
'[FUBEI_QUERY] out_trade_no=%s trade_state=%s',
|
||||
out_trade_no, data.get('trade_state'),
|
||||
)
|
||||
return data
|
||||
|
||||
|
||||
def fubei_trade_is_success(data: Optional[Dict[str, Any]]) -> bool:
|
||||
if not data:
|
||||
return False
|
||||
state = str(data.get('trade_state') or '').upper()
|
||||
return state == 'SUCCESS'
|
||||
|
||||
|
||||
def fubei_success_payload(
|
||||
out_trade_no: str,
|
||||
club_id: Optional[str] = None,
|
||||
) -> Optional[Tuple[str, Any]]:
|
||||
"""
|
||||
若是付呗单且已支付成功,返回 (transaction_id, total_fee);
|
||||
若是付呗单但未成功,返回 ('', None) 且调用方可据此判断「支付中」;
|
||||
若不是付呗单,返回 None(继续走微信/支付宝查单)。
|
||||
"""
|
||||
try:
|
||||
data = query_fubei_trade(out_trade_no, club_id)
|
||||
except Exception as exc:
|
||||
# 明确是付呗单但查单失败:不要回落到微信直连(会永远查不到)
|
||||
ledger = get_pay_ledger(out_trade_no)
|
||||
if ledger and ledger.channel == PAY_CHANNEL_FUBEI_WX_MINI:
|
||||
logger.error('[FUBEI_QUERY] 付呗单查单异常 %s: %s', out_trade_no, exc, exc_info=True)
|
||||
return ('', None)
|
||||
return None
|
||||
|
||||
if data is None:
|
||||
return None
|
||||
if not fubei_trade_is_success(data):
|
||||
return ('', None)
|
||||
|
||||
txn = str(
|
||||
data.get('trade_no')
|
||||
or data.get('platform_order_no')
|
||||
or data.get('order_sn')
|
||||
or out_trade_no
|
||||
or 'FUBEI_PAID'
|
||||
)
|
||||
total_fee = data.get('total_fee') or data.get('cash_fee') or data.get('order_price')
|
||||
return (txn, total_fee)
|
||||
Reference in New Issue
Block a user