优化一下自动提现接口就是user/tixian_shenhe_servers.py,tixian_shenhe_views.py,让文件以及对应的申请,回调,确认接口,让它更好用一点,允许用户多次提现审核,强化收款接口,及时更新数据库中的收款状态,其次,更新了客服提现审核接口,关于大于200元的提现,同意之后直接按驳回处理,微信官方不支持大于200元的提现申请

This commit is contained in:
XingQue
2026-06-15 22:24:32 +08:00
parent 653e127493
commit 143965da62
7 changed files with 277 additions and 114 deletions

View File

@@ -42,12 +42,12 @@ app.conf.beat_schedule = {
'options': {'queue': 'periodic_tasks', 'priority': 4},
},
# 补偿检查任务(每5分钟运行
'check_order_expire_task': {
'task': 'orders.tasks.check_order_expire_task',
'schedule': crontab(minute='*/5000'),
'options': {'queue': 'order_tasks', 'priority': 3},
},
# 补偿检查任务(订单自动结算已禁用
# 'check_order_expire_task': {
# 'task': 'orders.tasks.check_order_expire_task',
# 'schedule': crontab(minute='*/5000'),
# 'options': {'queue': 'order_tasks', 'priority': 3},
# },
# 1. 每日凌晨0点执行 - 清零任务
'daily_reset_task': {

View File

@@ -278,7 +278,7 @@ CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERY_ENABLE_UTC = True
CELERY_IMPORTS = ('dingdan.notice_tasks',)
CELERY_IMPORTS = ('orders.notice_tasks',)
CELERY_TASK_TIME_LIMIT = 300
CELERY_TASK_SOFT_TIME_LIMIT = 240
CELERY_WORKER_CONCURRENCY = 4

View File

@@ -56,36 +56,29 @@ def handle_order_status_8(sender, instance, **kwargs):
# 状态从 非8 变为 8
if old != 8 and instance.zhuangtai == 8:
#logger.info(f"📅 订单 {instance.dingdan_id} 状态变为8提交定时任务")
# 设置时间标记
# 订单自动结算已关闭:仅记录时间标记,不再提交 Celery 延时结算任务
instance.status_8_time = timezone.now()
instance.pending_dispatch = True
# 使用配置中的超时时间
expire_seconds = getattr(settings, 'ORDER_EXPIRE_SECONDS', 48 * 60 * 60)
# 提交Celery任务
try:
from orders.tasks import process_expired_order
task_result = process_expired_order.apply_async(
args=[instance.dingdan_id],
countdown=expire_seconds,
queue='order_tasks',
priority=9
)
#logger.info(f"✅ 任务提交成功,订单: {instance.dingdan_id}, 任务ID: {task_result.id}")
# 保存任务信息
instance.auto_task_id = task_result.id
instance.auto_expire_at = timezone.now() + timezone.timedelta(seconds=expire_seconds)
except Exception as e:
logger.error(f"❌ 任务提交失败: {e}")
instance.pending_dispatch = True
instance.auto_task_id = f"failed_{timezone.now().timestamp()}"
instance.pending_dispatch = False
instance.auto_task_id = ''
instance.auto_expire_at = None
logger.info(f"订单 {instance.dingdan_id} 状态变为8自动结算已禁用不提交结算任务")
# --- 原自动结算逻辑(已禁用,保留代码备查)---
# expire_seconds = getattr(settings, 'ORDER_EXPIRE_SECONDS', 48 * 60 * 60)
# try:
# from orders.tasks import process_expired_order
# task_result = process_expired_order.apply_async(
# args=[instance.dingdan_id],
# countdown=expire_seconds,
# queue='order_tasks',
# priority=9
# )
# instance.auto_task_id = task_result.id
# instance.auto_expire_at = timezone.now() + timezone.timedelta(seconds=expire_seconds)
# except Exception as e:
# logger.error(f"❌ 任务提交失败: {e}")
# instance.pending_dispatch = True
# instance.auto_task_id = f"failed_{timezone.now().timestamp()}"
# 状态从 8 变为 非8
elif old == 8 and instance.zhuangtai != 8:

View File

@@ -26,7 +26,12 @@ logger = logging.getLogger(__name__)
def process_expired_order(self, dingdan_id):
"""
处理单个超时订单(订单状态=8超过48小时未处理
【已禁用】保留任务定义避免 Celery 注册/引用报错,实际不执行结算逻辑
"""
logger.info(f"订单{dingdan_id}自动结算任务已禁用,跳过执行")
return f"订单{dingdan_id}自动结算已禁用,跳过"
# --- 以下原结算逻辑保留备查 ---
try:
# 使用select_for_update锁定记录防止并发修改
with transaction.atomic():
@@ -134,9 +139,12 @@ def process_expired_order(self, dingdan_id):
def check_order_expire_task():
"""
批量检查超时订单(补偿机制)
每5分钟执行一次作为信号处理的备用方案
查找状态为8且创建时间超过72小时的订单宽松时间防止误处理
【已禁用】保留任务定义避免 Beat/Worker 引用报错,实际不执行
"""
logger.info("订单自动结算补偿检查已禁用,跳过")
return {"success": True, "message": "自动结算已禁用", "count": 0}
# --- 以下原补偿逻辑保留备查 ---
try:
# 计算更宽松的时间点当前时间减去72小时48+24小时
# 这样避免误处理刚变为状态8的订单

View File

@@ -3,11 +3,11 @@
自动提现审核流程业务服务层(仅服务于 zddksh 申请接口 与 tixiansq 收款接口)
流程:
① zddksh 提交审核:资格校验 → 扣款(shenqing_jine) → 写审核表+提现记录表(状态=1)
(不在申请阶段校验/占用每日限额)
② 后台审核通过:状态变为 6待收款—— 由原有后台接口处理,此处不改动
③ tixiansq 收款:资格校验 → 只读预估 → 事务内原子预占限额 → 新建打款记录 → 调微信
微信明确失败/取消则回滚预占;待查单期间保留预占防并发超额
① zddksh 提交审核:完整资格校验 → 扣款 → 写审核表+提现记录表(状态=1)
允许多笔并行申请;单笔实际到账(shijidaozhang)不得超过200元
② 后台审核通过:校验到账≤200 → 状态 6待收款
③ tixiansq 收款:严格资格+限额 → 到账>200则关单退款(不退手续费),不调微信
微信官方 FAIL 关单不退款SUCCESS 落库;进行中禁止新建打款单
④ 打款成功tixianqr/回调/查单):若收款前已预占则不再累加;未预占的旧单/查单直成则补记
状态码(与前端 TX_STATUS 一致):
@@ -65,9 +65,6 @@ LEIXING_RATE_KEY = {
6: '10',
}
# 进行中的审核状态(不允许重复提交申请)
PENDING_AUDIT_STATUSES = [1, 4, 6]
DAKUAN_MODE_MANUAL = 1
DAKUAN_MODE_AUTO = 2
@@ -81,6 +78,10 @@ RECONCILE_COMPLETED = 'completed'
RECONCILE_WAIT_CONFIRM = 'wait_confirm'
RECONCILE_ALLOW_NEW = 'allow_new'
RECONCILE_PENDING = 'pending_query'
RECONCILE_AUDIT_CLOSED = 'audit_closed'
# 单笔实际到账上限(仅收款时校验)
MAX_SINGLE_COLLECT_AMOUNT = decimal.Decimal('200')
# 查单失败且本地 zhuangtai=0 超过该分钟数,才允许新建打款记录
PENDING_QUERY_GRACE_MINUTES = 10
@@ -182,7 +183,8 @@ def check_dashou_has_valid_huiyuan(yonghuid):
def validate_withdraw_eligibility(user_main, leixing, jine):
"""
提现资格校验(对齐手动提现 TixianShenqingView
提现申请资格校验(完整基本条件;仅放宽「不限制并行申请笔数」)。
与手动提现 TixianShenqingView 对齐。
"""
yonghuid = user_main.yonghuid
@@ -199,7 +201,6 @@ def validate_withdraw_eligibility(user_main, leixing, jine):
return False, '打手账号已被封禁,无法提现', {}
if dashou.zhuangtai != 1:
return False, '有订单进行中,请完成后提现', {}
# 与手动提现一致:积分必须正好 10 分
if dashou.jifen != 10:
return False, '积分不足10分请补充积分后提现', {}
huiyuan_ok, huiyuan_msg = check_dashou_has_valid_huiyuan(yonghuid)
@@ -293,11 +294,23 @@ def validate_withdraw_eligibility(user_main, leixing, jine):
return False, '无效的提现类型', {}
def check_shijidaozhang_within_limit(shijidaozhang):
"""校验单笔实际到账不超过上限(申请/审核/收款共用)"""
if shijidaozhang > MAX_SINGLE_COLLECT_AMOUNT:
return False, f'单笔实际到账不能超过{MAX_SINGLE_COLLECT_AMOUNT}元,请调整提现金额后重新申请'
return True, ''
def validate_collect_amount(audit):
"""收款时校验单笔实际到账上限(超限将关单退款)"""
return check_shijidaozhang_within_limit(audit.shijidaozhang)
def validate_collect_eligibility(user_main, leixing):
"""
收款前二次校验(申请时已扣款,不再校余额/金额)。
打手佣金/押金:罚单、封禁、接单中、积分、会员等;
其他身份:账号状态、罚单/订单等(不含金额)
收款前严格校验(申请时已扣款,不再校余额)。
打手佣金/押金:罚单、封禁、接单中、积分、会员、订单等;
其他身份:账号状态、罚单/订单等。
"""
yonghuid = user_main.yonghuid
@@ -354,24 +367,6 @@ def validate_collect_eligibility(user_main, leixing):
return False, '管事账号已被封禁,无法收款'
return True, ''
if leixing == 3:
try:
zuzhang = UserZuzhang.objects.get(user=user_main)
except UserZuzhang.DoesNotExist:
return False, '您不是组长身份,无法收款'
if zuzhang.zhuangtai != 1:
return False, '组长账号已被封禁,无法收款'
return True, ''
if leixing == 4:
try:
kaoheguan = UserShenheguan.objects.get(user=user_main)
except UserShenheguan.DoesNotExist:
return False, '您不是考核官身份,无法收款'
if kaoheguan.zhuangtai != 1:
return False, '考核官账号已被封禁,无法收款'
return True, ''
if leixing == 6:
try:
shangjia = UserShangjia.objects.get(user=user_main)
@@ -392,6 +387,24 @@ def validate_collect_eligibility(user_main, leixing):
return False, '您发起的处罚尚未处理完毕,无法收款'
return True, ''
if leixing == 3:
try:
zuzhang = UserZuzhang.objects.get(user=user_main)
except UserZuzhang.DoesNotExist:
return False, '您不是组长身份,无法收款'
if zuzhang.zhuangtai != 1:
return False, '组长账号已被封禁,无法收款'
return True, ''
if leixing == 4:
try:
kaoheguan = UserShenheguan.objects.get(user=user_main)
except UserShenheguan.DoesNotExist:
return False, '您不是考核官身份,无法收款'
if kaoheguan.zhuangtai != 1:
return False, '考核官账号已被封禁,无法收款'
return True, ''
return False, '无效的提现类型'
@@ -891,13 +904,6 @@ def get_balance_response_data(user_main, leixing):
return data
def has_pending_audit(yonghuid):
return TixianShenheJilu.objects.filter(
yonghuid=yonghuid,
zhuangtai__in=PENDING_AUDIT_STATUSES,
).exists()
def sync_audit_and_jilu_status(audit, new_status, **extra_fields):
audit.zhuangtai = new_status
for k, v in extra_fields.items():
@@ -910,6 +916,69 @@ def sync_audit_and_jilu_status(audit, new_status, **extra_fields):
Tixianjilu.objects.filter(id=audit.tixianjilu_id).update(**update_fields)
def _close_auto_record_failed(auto_record, fail_reason):
"""标记打款记录失败并释放收款预占限额"""
if auto_record is None or auto_record.zhuangtai == 1:
return
reason = (fail_reason or '打款失败')[:500]
auto_record.zhuangtai = 2
auto_record.fail_reason = reason
auto_record.save(update_fields=['zhuangtai', 'fail_reason', 'update_time'])
release_collect_quota_for_record(auto_record)
def close_audit_wechat_failed(audit, auto_record=None, fail_reason='微信转账失败'):
"""
微信官方终态 FAIL/CANCELLED审核单关闭(3),不退款(申请时已扣款,手续费不退)。
须在 transaction.atomic 内调用。
"""
_close_auto_record_failed(auto_record, fail_reason)
audit = TixianShenheJilu.objects.select_for_update().get(pk=audit.pk)
if audit.zhuangtai in (2, 3, 5):
return False
reason = (fail_reason or '微信转账失败')[:500]
sync_audit_and_jilu_status(
audit, 3,
bhliyou=reason,
fail_reason=reason,
tixian_auto_id=None,
)
logger.warning(
'微信失败关单(不退款) yonghuid=%s shenhe_danhao=%s reason=%s',
audit.yonghuid, audit.shenhe_danhao, reason,
)
return True
def close_audit_over_limit_refund(audit, auto_record=None, fail_reason='单笔实际到账超过限额'):
"""
到账超过200元等审核单关闭(3) + 退还可到账金额 shijidaozhang手续费不退
须在 transaction.atomic 内调用。
"""
reason = (fail_reason or '单笔实际到账超过限额')[:500]
_close_auto_record_failed(auto_record, reason)
audit = TixianShenheJilu.objects.select_for_update().get(pk=audit.pk)
if audit.zhuangtai in (2, 3, 5):
return False
user_main = UserMain.objects.select_for_update().get(yonghuid=audit.yonghuid)
refund_balance(user_main, audit.leixing, audit.shijidaozhang)
sync_audit_and_jilu_status(
audit, 3,
bhliyou=reason,
fail_reason=reason,
tixian_auto_id=None,
)
logger.warning(
'超限关单并退款 yonghuid=%s shenhe_danhao=%s reason=%s',
audit.yonghuid, audit.shenhe_danhao, reason,
)
return True
def query_wechat_transfer_bill(out_bill_no):
"""
向微信查转账单状态
@@ -1066,14 +1135,24 @@ def _sync_record_from_wx_query(auto_record, wx_data):
}
if state in WX_STATE_FAIL:
fail_reason = (
wx_data.get('fail_reason') or wx_data.get('close_reason') or state
)[:500]
if auto_record.zhuangtai != 1:
auto_record.zhuangtai = 2
auto_record.fail_reason = (
wx_data.get('fail_reason') or wx_data.get('close_reason') or state
)[:500]
auto_record.fail_reason = fail_reason
auto_record.save(update_fields=['zhuangtai', 'fail_reason', 'update_time'])
release_collect_quota_for_record(auto_record)
return RECONCILE_ALLOW_NEW, {}
if auto_record.shenhe_danhao:
try:
audit = TixianShenheJilu.objects.get(shenhe_danhao=auto_record.shenhe_danhao)
with transaction.atomic():
close_audit_wechat_failed(audit, None, fail_reason)
except TixianShenheJilu.DoesNotExist:
logger.warning('微信失败但审核记录不存在: %s', auto_record.shenhe_danhao)
return RECONCILE_AUDIT_CLOSED, {
'msg': '微信已确认转账失败,该笔提现已关闭,请联系客服处理',
}
if auto_record.zhuangtai == 0:
return RECONCILE_PENDING, {
@@ -1145,6 +1224,8 @@ def reconcile_shenhe_wechat_bills(shenhe_danhao):
return action, payload
if action == RECONCILE_WAIT_CONFIRM:
return action, payload
if action == RECONCILE_AUDIT_CLOSED:
return action, payload
if action == RECONCILE_PENDING:
if pending_hit is None:
pending_hit = (action, payload)
@@ -1286,12 +1367,10 @@ def create_audit_application(user_main, leixing, jine):
"""
提交审核申请:校验 → 扣款 → 写审核表 + 提现记录表
不创建打款记录表TixianAutoRecord 仅在收款时创建)
允许多笔并行申请(不阻塞待收款/审核中单)
"""
yonghuid = user_main.yonghuid
if has_pending_audit(yonghuid):
raise ValueError('账户余额不足或您有进行中的提现申请请等待处理完成或10分钟后后再提交')
ok, msg, extra = validate_withdraw_eligibility(user_main, leixing, jine)
if not ok:
raise ValueError(msg)
@@ -1301,6 +1380,10 @@ def create_audit_application(user_main, leixing, jine):
if shijidaozhang <= 0:
raise ValueError('提现金额过低,扣除手续费后无实际到账')
ok, limit_msg = check_shijidaozhang_within_limit(shijidaozhang)
if not ok:
raise ValueError(limit_msg)
shenhe_danhao = generate_shenhe_danhao()
nicheng = extra.get('nicheng', '')

View File

@@ -25,17 +25,21 @@ from utils.wechat_v3 import build_authorization
from .models import TixianAutoRecord
from .tixian_shenhe_services import (
RECONCILE_ALLOW_NEW,
RECONCILE_AUDIT_CLOSED,
RECONCILE_COMPLETED,
RECONCILE_PENDING,
RECONCILE_WAIT_CONFIRM,
check_collect_quota_limits,
create_audit_application,
close_audit_over_limit_refund,
close_audit_wechat_failed,
get_audit_for_collect,
handle_post_transfer_failure,
reconcile_shenhe_wechat_bills,
release_collect_quota_for_record,
reserve_collect_quota_limits,
resolve_collect_context,
validate_collect_amount,
validate_collect_eligibility,
)
@@ -217,7 +221,16 @@ def process_audit_collect(request):
tixianjilu_id_val = ctx['jilu'].id if ctx.get('jilu') else audit.tixianjilu_id
leixing = audit.leixing
# 二次资格校验:不通过仅返回错误,审核单保持待收款(6),不退款,用户补齐资质后可再点收款
amount_ok, amount_msg = validate_collect_amount(audit)
if not amount_ok:
with transaction.atomic():
close_audit_over_limit_refund(audit, None, amount_msg)
return Response({
'code': 400,
'msg': f'{amount_msg},可到账金额已退回余额(手续费不退),请重新申请',
})
# 收款前严格资格校验:不通过仅返回错误,审核单保持待收款(6),不退款
collect_ok, collect_msg = validate_collect_eligibility(user_main, leixing)
if not collect_ok:
logger.warning(
@@ -241,6 +254,11 @@ def process_audit_collect(request):
action, payload = reconcile_shenhe_wechat_bills(shenhe_danhao)
if action == RECONCILE_COMPLETED:
return Response({'code': 8, 'msg': payload.get('msg', '该提现已完成,请勿重复操作')})
if action == RECONCILE_AUDIT_CLOSED:
return Response({
'code': 400,
'msg': payload.get('msg', '该笔提现已关闭,请重新申请'),
})
if action == RECONCILE_WAIT_CONFIRM:
quota_resp = _verify_collect_quota_or_response(user_main, audit, shenhe_danhao)
if quota_resp:
@@ -344,6 +362,11 @@ def process_audit_collect(request):
return _build_collect_success_response(post_payload)
if post_action == RECONCILE_COMPLETED:
return Response({'code': 8, 'msg': '该提现已完成,请勿重复操作'})
if post_action == RECONCILE_AUDIT_CLOSED:
return Response({
'code': 400,
'msg': post_payload.get('msg', '该笔提现已关闭,请重新申请'),
})
if post_action == RECONCILE_PENDING:
pending_msg = (
post_payload.get('msg', post_payload)

View File

@@ -65,7 +65,10 @@ from .models import (
)
from .tixian_shenhe_services import (
load_audit_meta_map, refund_balance, sync_audit_and_jilu_status,
mark_transfer_success, release_collect_quota_for_record
mark_transfer_success, release_collect_quota_for_record,
close_audit_wechat_failed, query_wechat_transfer_bill,
check_shijidaozhang_within_limit,
WX_STATE_FAIL, WX_STATE_SUCCESS, WX_STATE_WAIT, WX_STATE_CANCELING,
)
from .tixian_shenhe_views import process_audit_collect
@@ -10046,6 +10049,18 @@ class KefuWithdrawActionView(APIView):
raise ValueError(f'用户{req_yonghuid}不存在')
if action == 1:
limit_ok, limit_msg = check_shijidaozhang_within_limit(audit.shijidaozhang)
if not limit_ok:
sync_audit_and_jilu_status(
audit, 5,
bhliyou=limit_msg,
bo_hui_ren_id=kefu_user.yonghuid,
)
refund_balance(user, audit.leixing, audit.shijidaozhang)
tixian.shenheid = kefu_user.yonghuid
tixian.bhliyou = limit_msg
tixian.save(update_fields=['shenheid', 'bhliyou', 'update_time'])
raise ValueError(f'提现记录{tixian_id}{limit_msg},已自动驳回并退款')
sync_audit_and_jilu_status(audit, 6, shenhe_ren_id=kefu_user.yonghuid)
tixian.shenheid = kefu_user.yonghuid
tixian.save(update_fields=['shenheid', 'update_time'])
@@ -12788,21 +12803,20 @@ class TixianCallbackV3View(APIView):
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:
# 申请时已扣款,回调失败不退余额,恢复待收款(6)可重试
try:
audit = TixianShenheJilu.objects.select_for_update().get(
shenhe_danhao=auto_record.shenhe_danhao
)
audit.tixian_auto_id = None
audit.fail_reason = auto_record.fail_reason
sync_audit_and_jilu_status(audit, 6, fail_reason=auto_record.fail_reason)
close_audit_wechat_failed(
audit, None, auto_record.fail_reason,
)
except TixianShenheJilu.DoesNotExist:
logger.warning(f'回调失败但审核记录不存在: {auto_record.shenhe_danhao}')
release_collect_quota_for_record(auto_record)
return Response({'code': 'SUCCESS', 'message': 'ok'})
@@ -12812,7 +12826,7 @@ class TixianQueRenAutoView(APIView):
"""
用户确认提现结果
POST /yonghu/tixianqr
新审核流程:打款记录带 shenhe_danhao 时,确认成功同步审核表+提现记录表为 2取消不退款申请已扣恢复待收款 6 可重试
以微信官方查单状态为准SUCCESS 落库成功FAIL/CANCELLED 关闭审核单+退款;进行中则提示等待
"""
permission_classes = [permissions.IsAuthenticated]
@@ -12847,37 +12861,79 @@ class TixianQueRenAutoView(APIView):
if auto_record.zhuangtai == 1:
return Response({'code': 0, 'msg': '提现成功', 'data': None})
if auto_record.zhuangtai != 0:
return Response({'code': 5, 'msg': '该提现已处理'})
wx_data = query_wechat_transfer_bill(tixian_id)
if wx_data is None:
return Response({'code': 12, 'msg': '系统正在核对微信状态,请稍后再试'})
mark_transfer_success(auto_record, with_accounting=True)
if wx_data.get('_not_found'):
return Response({'code': 12, 'msg': '收款处理中,请稍后再试'})
state = (wx_data.get('state') or '').upper()
if state in WX_STATE_SUCCESS:
mark_transfer_success(
auto_record,
wechat_transfer_no=wx_data.get('transfer_bill_no') or wx_data.get('transfer_no'),
with_accounting=True,
)
return Response({'code': 0, 'msg': '提现成功', 'data': None})
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': '微信已确认转账失败,该笔提现已关闭,请联系客服处理'})
if state in WX_STATE_WAIT or state in WX_STATE_CANCELING:
return Response({'code': 12, 'msg': '收款处理中,请在微信中完成或稍后再试'})
return Response({'code': 12, 'msg': '系统正在核对微信状态,请稍后再试'})
# 用户报告取消/失败:以微信查单为准,不本地盲目标记
if auto_record.zhuangtai == 2:
return Response({'code': 0, 'msg': '提现已取消', 'data': None})
if auto_record.zhuangtai == 1:
return Response({'code': 0, 'msg': '提现成功', 'data': None})
# 用户取消或失败
auto_record.zhuangtai = 2
auto_record.fail_reason = '用户取消收款'
auto_record.save(update_fields=['zhuangtai', 'fail_reason'])
wx_data = query_wechat_transfer_bill(tixian_id)
if wx_data is None:
return Response({'code': 12, 'msg': '系统正在核对微信状态,请稍后再试,切勿重复操作'})
if not auto_record.shenhe_danhao:
logger.error('确认取消但打款记录无审核单号 bill=%s', tixian_id)
return Response({'code': 5, 'msg': '该提现已处理'})
if wx_data.get('_not_found'):
return Response({'code': 12, 'msg': '收款处理中,请稍后再试'})
# 申请时已扣款,取消不退余额,审核单恢复 6 待收款,可再次点收款
try:
audit = TixianShenheJilu.objects.select_for_update().get(
shenhe_danhao=auto_record.shenhe_danhao,
state = (wx_data.get('state') or '').upper()
if state in WX_STATE_SUCCESS:
mark_transfer_success(
auto_record,
wechat_transfer_no=wx_data.get('transfer_bill_no') or wx_data.get('transfer_no'),
with_accounting=True,
)
audit.tixian_auto_id = None
sync_audit_and_jilu_status(
audit, 6,
fail_reason='用户取消收款,可重新发起',
)
except TixianShenheJilu.DoesNotExist:
logger.warning(f'确认取消但审核记录不存在: {auto_record.shenhe_danhao}')
release_collect_quota_for_record(auto_record)
return Response({'code': 0, 'msg': '提现成功', 'data': None})
return Response({'code': 0, 'msg': '提现已取消', 'data': None})
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': '提现已关闭,请联系客服处理'})
if state in WX_STATE_WAIT or state in WX_STATE_CANCELING:
return Response({'code': 12, 'msg': '收款仍在进行中,请在微信中操作或稍后再试'})
return Response({'code': 12, 'msg': '系统正在核对微信状态,请稍后再试'})
except Exception as e:
logger.error(f'提现确认异常: {str(e)}', exc_info=True)