fix: 自动提现收款不再因查单失败卡死,失败可重试且防双笔

- 查单失败时优先用本地 package 直接调起微信确认收款
- 单次打款失败不关审核单(保持待收款6),允许同一审核单再次收款
- 跳过已失败打款记录;缩短 grace 至 2 分钟;去掉「核对状态」类死锁提示

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-10 21:48:00 +08:00
parent 49ad57bbb2
commit e1a3c07cef
3 changed files with 120 additions and 83 deletions

View File

@@ -70,6 +70,7 @@ from ..tixian_shenhe_services import (
load_audit_meta_map, refund_balance, sync_audit_and_jilu_status,
mark_transfer_success, release_collect_quota_for_record,
close_audit_wechat_failed, query_wechat_transfer_bill,
_mark_transfer_attempt_failed, club_id_for_tixian_yonghuid,
check_shijidaozhang_within_limit,
check_dashou_has_formal_huiyuan_for_withdraw,
check_dashou_trial_blocks_commission_withdraw,
@@ -1274,23 +1275,11 @@ class TixianCallbackV3View(APIView):
)
else: # transfer_status == 'FAIL'
auto_record.zhuangtai = 2
auto_record.fail_reason = fail_reason or '微信转账失败'
auto_record.save(update_fields=['zhuangtai', 'fail_reason'])
release_collect_quota_for_record(auto_record)
if not auto_record.shenhe_danhao:
logger.error('回调失败但打款记录无审核单号 bill=%s', out_bill_no)
else:
try:
audit = TixianShenheJilu.objects.select_for_update().get(
shenhe_danhao=auto_record.shenhe_danhao
)
close_audit_wechat_failed(
audit, None, auto_record.fail_reason,
)
except TixianShenheJilu.DoesNotExist:
logger.warning(f'回调失败但审核记录不存在: {auto_record.shenhe_danhao}')
_mark_transfer_attempt_failed(
auto_record,
fail_reason or '微信转账失败',
close_audit=False,
)
return Response({'code': 'SUCCESS', 'message': 'ok'})
@@ -1334,11 +1323,18 @@ class TixianQueRenAutoView(APIView):
if auto_record.zhuangtai == 1:
return Response({'code': 0, 'msg': '提现成功', 'data': None})
wx_data = query_wechat_transfer_bill(tixian_id)
payout_club = club_id_for_tixian_yonghuid(auto_record.yonghuid)
wx_data = query_wechat_transfer_bill(tixian_id, payout_club)
if wx_data is None:
return Response({'code': 12, 'msg': '系统正在核对微信状态,请稍后再试'})
return Response({'code': 0, 'msg': '收款确认已提交,请稍后刷新查看结果'})
if wx_data.get('_not_found'):
age = timezone.now() - auto_record.CreateTime
if auto_record.zhuangtai == 0 and age >= timedelta(minutes=2):
_mark_transfer_attempt_failed(
auto_record, '微信未找到该打款单', close_audit=False,
)
return Response({'code': 0, 'msg': '请再次点击收款重试'})
return Response({'code': 12, 'msg': '收款处理中,请稍后再试'})
state = (wx_data.get('state') or '').upper()
@@ -1352,21 +1348,15 @@ class TixianQueRenAutoView(APIView):
if state in WX_STATE_FAIL:
fail_reason = wx_data.get('fail_reason') or wx_data.get('close_reason') or state
auto_record.zhuangtai = 2
auto_record.fail_reason = str(fail_reason)[:500]
auto_record.save(update_fields=['zhuangtai', 'fail_reason'])
release_collect_quota_for_record(auto_record)
if auto_record.shenhe_danhao:
audit = TixianShenheJilu.objects.select_for_update().get(
shenhe_danhao=auto_record.shenhe_danhao,
)
close_audit_wechat_failed(audit, None, auto_record.fail_reason)
return Response({'code': 400, 'msg': '微信已确认转账失败,该笔提现已关闭,请联系客服处理'})
_mark_transfer_attempt_failed(
auto_record, str(fail_reason)[:500], close_audit=False,
)
return Response({'code': 0, 'msg': '本次收款未成功,可再次点击收款重试'})
if state in WX_STATE_WAIT or state in WX_STATE_CANCELING:
return Response({'code': 12, 'msg': '收款处理中,请在微信中完成或稍后再试'})
return Response({'code': 12, 'msg': '请在微信中完成收款确认'})
return Response({'code': 12, 'msg': '系统正在核对微信状态,请稍后再试'})
return Response({'code': 0, 'msg': '收款确认已提交,请稍后刷新查看结果'})
# 用户报告取消/失败:以微信查单为准,不本地盲目标记
if auto_record.zhuangtai == 2:
@@ -1374,12 +1364,15 @@ class TixianQueRenAutoView(APIView):
if auto_record.zhuangtai == 1:
return Response({'code': 0, 'msg': '提现成功', 'data': None})
wx_data = query_wechat_transfer_bill(tixian_id)
wx_data = query_wechat_transfer_bill(
tixian_id, club_id_for_tixian_yonghuid(auto_record.yonghuid),
)
if wx_data is None:
return Response({'code': 12, 'msg': '系统正在核对微信状态,请稍后再试,切勿重复操作'})
return Response({'code': 0, 'msg': '提现已取消,可再次点击收款重试'})
if wx_data.get('_not_found'):
return Response({'code': 12, 'msg': '收款处理中,请稍后再试'})
_mark_transfer_attempt_failed(auto_record, '用户取消收款', close_audit=False)
return Response({'code': 0, 'msg': '提现已取消,可再次点击收款重试'})
state = (wx_data.get('state') or '').upper()
if state in WX_STATE_SUCCESS:
@@ -1392,21 +1385,15 @@ class TixianQueRenAutoView(APIView):
if state in WX_STATE_FAIL:
fail_reason = wx_data.get('fail_reason') or wx_data.get('close_reason') or '用户取消收款'
auto_record.zhuangtai = 2
auto_record.fail_reason = str(fail_reason)[:500]
auto_record.save(update_fields=['zhuangtai', 'fail_reason'])
release_collect_quota_for_record(auto_record)
if auto_record.shenhe_danhao:
audit = TixianShenheJilu.objects.select_for_update().get(
shenhe_danhao=auto_record.shenhe_danhao,
)
close_audit_wechat_failed(audit, None, auto_record.fail_reason)
return Response({'code': 0, 'msg': '提现已关闭,请联系客服处理'})
_mark_transfer_attempt_failed(
auto_record, str(fail_reason)[:500], close_audit=False,
)
return Response({'code': 0, 'msg': '提现已取消,可再次点击收款重试'})
if state in WX_STATE_WAIT or state in WX_STATE_CANCELING:
return Response({'code': 12, 'msg': '收款仍在进行中,请在微信中操作或稍后再试'})
return Response({'code': 12, 'msg': '系统正在核对微信状态,请稍后再'})
return Response({'code': 0, 'msg': '提现已取消,可再次点击收款重'})
except Exception as e:
logger.error(f'提现确认异常: {str(e)}', exc_info=True)