Files
Django/jituan/services/pay_confirm.py
XingQue dacd55bb1e fix: 统一付呗/微信直连官方查单确认,轮询幂等入账
复查与充值轮询按通道查官方单:付呗单查付呗、直连查微信;履约仍幂等防多加,未完成返回业务码便于继续轮询。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 20:57:36 +08:00

89 lines
3.3 KiB
Python

"""统一远程支付确认:微信直连 / 付呗 / 支付宝,供复查与轮询调用。
返回:
{'ok': True, 'channel': 'fubei'|'wechat'|'alipay', 'transaction_id': str|None, 'amount': Decimal|None}
{'ok': False, 'pending': True, 'channel': ...} # 支付中,前端应继续轮询
{'ok': False, 'pending': False, 'channel': ..., 'msg': ...} # 明确失败(少见)
"""
from __future__ import annotations
import logging
from decimal import Decimal
from typing import Any, Dict, Optional
from django.core.cache import cache
logger = logging.getLogger(__name__)
def confirm_remote_payment(
out_trade_no: str,
club_id: Optional[str] = None,
*,
prefer_amount: Any = None,
) -> Dict[str, Any]:
"""按通道查官方支付状态(付呗优先于微信直连,互不串单)。"""
from jituan.services.fubei_query import fubei_success_payload
fb = fubei_success_payload(out_trade_no, club_id)
if fb is not None:
txn, total_fee = fb
if not txn and total_fee is None:
return {'ok': False, 'pending': True, 'channel': 'fubei'}
amount = total_fee if total_fee not in (None, '') else prefer_amount
return {
'ok': True,
'pending': False,
'channel': 'fubei',
'transaction_id': txn,
'amount': Decimal(str(amount)) if amount not in (None, '') else None,
}
is_alipay = cache.get(f'alipay_pay_url_{out_trade_no}') is not None
if is_alipay:
from jituan.services.alipay_pay import query_alipay_trade
trade_status = query_alipay_trade(out_trade_no, club_id)
if trade_status in ('TRADE_SUCCESS', 'TRADE_FINISHED'):
return {
'ok': True,
'pending': False,
'channel': 'alipay',
'transaction_id': None,
'amount': Decimal(str(prefer_amount)) if prefer_amount not in (None, '') else None,
}
return {'ok': False, 'pending': True, 'channel': 'alipay'}
from jituan.services.member_recharge import query_wechat_v2_trade_state
trade_state, transaction_id = query_wechat_v2_trade_state(out_trade_no, club_id)
if trade_state == 'SUCCESS':
return {
'ok': True,
'pending': False,
'channel': 'wechat',
'transaction_id': transaction_id,
'amount': Decimal(str(prefer_amount)) if prefer_amount not in (None, '') else None,
}
# cache 过期兜底:再试支付宝
from jituan.services.alipay_pay import query_alipay_trade
alipay_status = query_alipay_trade(out_trade_no, club_id)
if alipay_status in ('TRADE_SUCCESS', 'TRADE_FINISHED'):
logger.info('confirm_remote: cache 过期但支付宝查单成功 %s', out_trade_no)
return {
'ok': True,
'pending': False,
'channel': 'alipay',
'transaction_id': None,
'amount': Decimal(str(prefer_amount)) if prefer_amount not in (None, '') else None,
}
if trade_state in (None, 'NOTPAY', 'USERPAYING', ''):
return {'ok': False, 'pending': True, 'channel': 'wechat', 'trade_state': trade_state}
return {
'ok': False,
'pending': False,
'channel': 'wechat',
'trade_state': trade_state,
'msg': f'支付状态异常: {trade_state}',
}