feat(jituan): 集团多俱乐部改造 — club 隔离、财务/提现/分红/展示配置
This commit is contained in:
@@ -43,6 +43,10 @@ class User(_UserBase):
|
||||
IP = models.CharField(max_length=50, db_column='IP', verbose_name='来访用户IP', null=True, blank=True)
|
||||
IsStaff = models.BooleanField(default=False, db_column='IsStaff', verbose_name='是否员工')
|
||||
IsSuperuser = models.BooleanField(default=False, db_column='IsSuperuser', verbose_name='是否超级用户')
|
||||
ClubID = models.CharField(
|
||||
max_length=16, default='xq', db_column='ClubID', verbose_name='所属俱乐部',
|
||||
null=True, blank=True,
|
||||
)
|
||||
|
||||
objects = UserManager()
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ def process_fadan_fenhong(fadan_id):
|
||||
return True, "罚款金额为0,无分红"
|
||||
|
||||
# 5. 确定分红利率
|
||||
rate = _get_fenhong_rate(shenqing_chufa, fenhong_shenfen, lilv_shenfen)
|
||||
rate = _get_fenhong_rate(shenqing_chufa, fenhong_shenfen, lilv_shenfen, club_id=fadan.ClubID)
|
||||
if rate is None:
|
||||
logger.warning(f"未找到身份 {src_shenfen} (映射后 fenhong_shenfen={fenhong_shenfen}, lilv_shenfen={lilv_shenfen}) 的分红利率,罚单 {fadan_id} 不进行分红")
|
||||
fadan.ApplicantBonusAmount = Decimal('0.00')
|
||||
@@ -79,6 +79,8 @@ def process_fadan_fenhong(fadan_id):
|
||||
fadan.save(update_fields=['ApplicantBonusAmount'])
|
||||
return True, "分红金额为0"
|
||||
|
||||
club_id = fadan.ClubID or 'xq'
|
||||
|
||||
# 7. 根据申请处罚者身份执行不同的分红逻辑
|
||||
# src_shenfen == 5 代表商家(源身份)
|
||||
if src_shenfen == 5:
|
||||
@@ -87,6 +89,7 @@ def process_fadan_fenhong(fadan_id):
|
||||
fenhong_record, created = PenaltyBonus.objects.get_or_create(
|
||||
BeneficiaryID=shenqing_chufa,
|
||||
Identity=fenhong_shenfen,
|
||||
ClubID=club_id,
|
||||
defaults={
|
||||
'TotalAmount': Decimal('0.00'),
|
||||
'WithdrawableAmount': Decimal('0.00'),
|
||||
@@ -120,6 +123,7 @@ def process_fadan_fenhong(fadan_id):
|
||||
fenhong_record, created = PenaltyBonus.objects.get_or_create(
|
||||
BeneficiaryID=shenqing_chufa,
|
||||
Identity=fenhong_shenfen,
|
||||
ClubID=club_id,
|
||||
defaults={
|
||||
'TotalAmount': Decimal('0.00'),
|
||||
'WithdrawableAmount': Decimal('0.00'),
|
||||
@@ -145,7 +149,7 @@ def process_fadan_fenhong(fadan_id):
|
||||
return False, f"分红处理异常: {str(e)}"
|
||||
|
||||
|
||||
def _get_fenhong_rate(fenhongzhe_id, fenhong_shenfen, lilv_shenfen):
|
||||
def _get_fenhong_rate(fenhongzhe_id, fenhong_shenfen, lilv_shenfen, club_id='xq'):
|
||||
"""
|
||||
获取分红利率(优先使用个人单独配置,否则使用全局身份配置)
|
||||
"""
|
||||
@@ -153,6 +157,7 @@ def _get_fenhong_rate(fenhongzhe_id, fenhong_shenfen, lilv_shenfen):
|
||||
individual = PenaltyBonus.objects.get(
|
||||
BeneficiaryID=fenhongzhe_id,
|
||||
Identity=fenhong_shenfen,
|
||||
ClubID=club_id,
|
||||
is_individual_rate=True
|
||||
)
|
||||
return individual.IndividualRate
|
||||
|
||||
20
users/migrations/0002_user_clubid.py
Normal file
20
users/migrations/0002_user_clubid.py
Normal file
@@ -0,0 +1,20 @@
|
||||
"""users: User.ClubID 字段"""
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('users', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='ClubID',
|
||||
field=models.CharField(
|
||||
blank=True, db_column='ClubID', default='xq',
|
||||
max_length=16, null=True, verbose_name='所属俱乐部',
|
||||
),
|
||||
),
|
||||
]
|
||||
30
users/migrations/0003_tixian_club_id.py
Normal file
30
users/migrations/0003_tixian_club_id.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('users', '0002_user_clubid'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='tixianautorecord',
|
||||
name='club_id',
|
||||
field=models.CharField(db_index=True, default='xq', max_length=16, verbose_name='俱乐部ID'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tixianjilu',
|
||||
name='club_id',
|
||||
field=models.CharField(db_index=True, default='xq', max_length=16, verbose_name='俱乐部ID'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tixianshenhejilu',
|
||||
name='club_id',
|
||||
field=models.CharField(db_index=True, default='xq', max_length=16, verbose_name='俱乐部ID'),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name='tixianjilu',
|
||||
index=models.Index(fields=['club_id', 'zhuangtai'], name='tixianjilu_club_status_idx'),
|
||||
),
|
||||
]
|
||||
@@ -340,6 +340,7 @@ class UserKefu(QModel):
|
||||
|
||||
class Tixianjilu(QModel):
|
||||
id = models.AutoField(primary_key=True, verbose_name='提现记录ID')
|
||||
club_id = models.CharField(max_length=16, default='xq', db_index=True, verbose_name='俱乐部ID')
|
||||
yonghuid = models.CharField(max_length=7, db_index=True, verbose_name='提现用户ID')
|
||||
avatar = models.CharField(max_length=500, null=True, blank=True, verbose_name='头像') # 用CharField
|
||||
phone = models.CharField(max_length=11, blank=True, null=True, verbose_name='手机号')
|
||||
@@ -370,6 +371,7 @@ class Tixianjilu(QModel):
|
||||
verbose_name = '提现记录表'
|
||||
verbose_name_plural = verbose_name
|
||||
indexes = [
|
||||
models.Index(fields=['club_id', 'zhuangtai']),
|
||||
models.Index(fields=['yonghuid']),
|
||||
models.Index(fields=['zhuangtai']),
|
||||
models.Index(fields=['shenheid']),
|
||||
@@ -393,6 +395,7 @@ class TixianShenheJilu(QModel):
|
||||
shenhe_danhao = models.CharField(
|
||||
max_length=32, unique=True, db_index=True, verbose_name='审核单号'
|
||||
)
|
||||
club_id = models.CharField(max_length=16, default='xq', db_index=True, verbose_name='俱乐部ID')
|
||||
yonghuid = models.CharField(max_length=7, db_index=True, verbose_name='用户ID')
|
||||
# 提现类型:1打手佣金 2管事分红 3组长分红 4考核官分佣 5打手押金 6商家余额
|
||||
leixing = models.PositiveSmallIntegerField(db_index=True, verbose_name='提现类型')
|
||||
@@ -454,6 +457,7 @@ class TixianAutoRecord(QModel):
|
||||
db_index=True,
|
||||
verbose_name='提现订单号(自定义)'
|
||||
)
|
||||
club_id = models.CharField(max_length=16, default='xq', db_index=True, verbose_name='俱乐部ID')
|
||||
yonghuid = models.CharField(max_length=7, db_index=True, verbose_name='用户ID')
|
||||
leixing = models.IntegerField(verbose_name='提现类型 1打手 2管事')
|
||||
jine = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='申请提现金额')
|
||||
|
||||
@@ -25,8 +25,15 @@ from django.conf import settings
|
||||
from django.db import transaction
|
||||
from django.utils import timezone
|
||||
|
||||
from orders.models import Order, MerchantOrderExt, Penalty, CommissionRate
|
||||
from config.models import Szjilu, TixianQuotaDefault
|
||||
from orders.models import Order, MerchantOrderExt, Penalty
|
||||
from jituan.services.wechat_pay import club_id_for_tixian_yonghuid
|
||||
from jituan.services.withdraw_config import (
|
||||
get_or_create_platform_daily_stat,
|
||||
get_personal_daily_quota,
|
||||
get_platform_daily_limit,
|
||||
get_platform_daily_total,
|
||||
get_tixian_feilv as _get_tixian_feilv_for_club,
|
||||
)
|
||||
|
||||
from utils.fadan_utils import check_fadan_qiangdan_eligible
|
||||
|
||||
@@ -67,6 +74,19 @@ LEIXING_RATE_KEY = {
|
||||
6: '10',
|
||||
}
|
||||
|
||||
def _club_id_for_user(user_main):
|
||||
return club_id_for_tixian_yonghuid(user_main.UserUID)
|
||||
|
||||
|
||||
def get_tixian_feilv(leixing, yonghuid=None, club_id=None):
|
||||
"""按用户所属俱乐部读取提现手续费率。"""
|
||||
if club_id is None:
|
||||
if not yonghuid:
|
||||
raise ValueError('缺少用户或俱乐部')
|
||||
club_id = club_id_for_tixian_yonghuid(yonghuid)
|
||||
return _get_tixian_feilv_for_club(club_id, leixing)
|
||||
|
||||
|
||||
DAKUAN_MODE_MANUAL = 1
|
||||
DAKUAN_MODE_AUTO = 2
|
||||
|
||||
@@ -149,16 +169,6 @@ def generate_shenhe_danhao():
|
||||
raise RuntimeError('生成审核单号失败,请重试')
|
||||
|
||||
|
||||
def get_tixian_feilv(leixing):
|
||||
rate_key = LEIXING_RATE_KEY.get(leixing)
|
||||
if not rate_key:
|
||||
raise ValueError('无效的提现类型')
|
||||
rate_obj = CommissionRate.query.filter(Platform=rate_key).first()
|
||||
if not rate_obj:
|
||||
raise ValueError(f'提现费率未配置(类型{leixing})')
|
||||
return decimal.Decimal(str(rate_obj.Rate))
|
||||
|
||||
|
||||
def calc_fee_amounts(jine, feilv):
|
||||
"""申请金额 jine;实际到账 = jine - 手续费"""
|
||||
shouxufei = (jine * feilv).quantize(decimal.Decimal('0.01'))
|
||||
@@ -410,25 +420,8 @@ def validate_collect_eligibility(user_main, leixing):
|
||||
return False, '无效的提现类型'
|
||||
|
||||
|
||||
def _get_personal_daily_quota(leixing, profile):
|
||||
"""打手/管事/组长个人每日限额:额外开启优先,否则默认配置"""
|
||||
if leixing == 1:
|
||||
if profile.kaioi_ewai_xiane and profile.ewai_xiane > 0:
|
||||
return profile.ewai_xiane
|
||||
return TixianQuotaDefault.query.get(UserType=1).default_quota
|
||||
if leixing == 2:
|
||||
if profile.kaioi_ewai_xiane and profile.ewai_xiane > 0:
|
||||
return profile.ewai_xiane
|
||||
return TixianQuotaDefault.query.get(UserType=2).default_quota
|
||||
if leixing == 3:
|
||||
try:
|
||||
default_quota = TixianQuotaDefault.query.get(UserType=3).default_quota
|
||||
except TixianQuotaDefault.DoesNotExist:
|
||||
default_quota = decimal.Decimal('0.00')
|
||||
if profile.kaioi_ewai_tixian and profile.ewai_tixian_xiane > 0:
|
||||
return profile.ewai_tixian_xiane
|
||||
return default_quota
|
||||
raise ValueError('无效的个人限额身份')
|
||||
def _get_personal_daily_quota(club_id, leixing, profile):
|
||||
return get_personal_daily_quota(club_id, leixing, profile)
|
||||
|
||||
|
||||
def _get_active_auto_record(shenhe_danhao):
|
||||
@@ -444,23 +437,12 @@ def _get_active_auto_record(shenhe_danhao):
|
||||
)
|
||||
|
||||
|
||||
def _get_platform_daily_total(leixing, today=None):
|
||||
"""平台今日已提现总额:只读 houtai.WithdrawalDailyStats(到账金额口径)"""
|
||||
if today is None:
|
||||
today = date.today()
|
||||
try:
|
||||
return WithdrawalDailyStats.query.get(Date=today, WithdrawalType=leixing).total_amount
|
||||
except WithdrawalDailyStats.DoesNotExist:
|
||||
return decimal.Decimal('0.00')
|
||||
def _get_platform_daily_total(club_id, leixing, today=None):
|
||||
return get_platform_daily_total(club_id, leixing, today)
|
||||
|
||||
|
||||
def _calc_platform_projected(leixing, shijidaozhang, shenhe_danhao=''):
|
||||
"""
|
||||
平台今日预占后总额(收款前只读预估)。
|
||||
本审核单若已有进行中打款记录,其金额尚未写入统计表,但不应重复加计。
|
||||
返回 (daily_used, projected_total, additional_amount)
|
||||
"""
|
||||
daily_used = _get_platform_daily_total(leixing)
|
||||
def _calc_platform_projected(club_id, leixing, shijidaozhang, shenhe_danhao=''):
|
||||
daily_used = _get_platform_daily_total(club_id, leixing)
|
||||
active_rec = _get_active_auto_record(shenhe_danhao)
|
||||
if active_rec:
|
||||
return daily_used, daily_used, decimal.Decimal('0.00')
|
||||
@@ -475,20 +457,14 @@ def _projected_personal_total(personal_today, jine, shenhe_danhao=''):
|
||||
return personal_today - already_counted + jine
|
||||
|
||||
|
||||
def _get_platform_daily_limit(leixing):
|
||||
"""
|
||||
平台每日总限额(peizhi.TixianQuotaDefault):
|
||||
提现身份1打手→配置4,2管事→5,3组长→6,4考核官→7,5押金→8,6商家→9
|
||||
"""
|
||||
quota_leixing = leixing + 3
|
||||
try:
|
||||
return TixianQuotaDefault.query.get(UserType=quota_leixing).default_quota
|
||||
except TixianQuotaDefault.DoesNotExist:
|
||||
def _get_platform_daily_limit(club_id, leixing):
|
||||
limit = get_platform_daily_limit(club_id, leixing)
|
||||
if limit <= 0:
|
||||
logger.warning(
|
||||
'平台每日总限额未配置 leixing=%s(读取quota_leixing=%s),按0处理禁止新增收款',
|
||||
leixing, quota_leixing,
|
||||
'平台每日总限额为0 club_id=%s leixing=%s',
|
||||
club_id, leixing,
|
||||
)
|
||||
return decimal.Decimal('0.00')
|
||||
return limit
|
||||
|
||||
|
||||
def _check_personal_quota_readonly(user_main, leixing, jine, shenhe_danhao=''):
|
||||
@@ -525,7 +501,7 @@ def _check_personal_quota_readonly(user_main, leixing, jine, shenhe_danhao=''):
|
||||
else:
|
||||
personal_today = decimal.Decimal('0.00')
|
||||
|
||||
personal_quota = _get_personal_daily_quota(leixing, profile)
|
||||
personal_quota = _get_personal_daily_quota(_club_id_for_user(user_main), leixing, profile)
|
||||
projected_personal = _projected_personal_total(personal_today, jine, shenhe_danhao)
|
||||
if projected_personal > personal_quota:
|
||||
return (
|
||||
@@ -536,22 +512,22 @@ def _check_personal_quota_readonly(user_main, leixing, jine, shenhe_danhao=''):
|
||||
return True, '', ''
|
||||
|
||||
|
||||
def _check_platform_quota_readonly(leixing, shijidaozhang, shenhe_danhao=''):
|
||||
def _check_platform_quota_readonly(club_id, leixing, shijidaozhang, shenhe_danhao=''):
|
||||
"""平台每日总限额只读校验:今日已用 + 本笔到账 > 总限额 则拒绝"""
|
||||
platform_limit = _get_platform_daily_limit(leixing)
|
||||
platform_limit = _get_platform_daily_limit(club_id, leixing)
|
||||
shijidaozhang = shijidaozhang or decimal.Decimal('0.00')
|
||||
|
||||
if platform_limit <= 0 and shijidaozhang > 0:
|
||||
return False, '今日该角色提现已关闭(总限额为0),暂无法收款', 'platform'
|
||||
|
||||
daily_used, projected, additional = _calc_platform_projected(
|
||||
leixing, shijidaozhang, shenhe_danhao,
|
||||
club_id, leixing, shijidaozhang, shenhe_danhao,
|
||||
)
|
||||
if projected > platform_limit:
|
||||
logger.warning(
|
||||
'平台总限额拦截 leixing=%s shenhe_danhao=%s daily_used=%s additional=%s '
|
||||
'平台总限额拦截 club_id=%s leixing=%s shenhe_danhao=%s daily_used=%s additional=%s '
|
||||
'projected=%s limit=%s',
|
||||
leixing, shenhe_danhao, daily_used, additional, projected, platform_limit,
|
||||
club_id, leixing, shenhe_danhao, daily_used, additional, projected, platform_limit,
|
||||
)
|
||||
return (
|
||||
False,
|
||||
@@ -570,7 +546,8 @@ def check_collect_quota_limits(user_main, leixing, jine, shijidaozhang, shenhe_d
|
||||
ok, msg, kind = _check_personal_quota_readonly(user_main, leixing, jine, shenhe_danhao)
|
||||
if not ok:
|
||||
return False, msg, kind
|
||||
return _check_platform_quota_readonly(leixing, shijidaozhang, shenhe_danhao)
|
||||
club_id = _club_id_for_user(user_main)
|
||||
return _check_platform_quota_readonly(club_id, leixing, shijidaozhang, shenhe_danhao)
|
||||
|
||||
|
||||
def reserve_collect_quota_limits(user_main, leixing, jine, shijidaozhang, shenhe_danhao=''):
|
||||
@@ -583,6 +560,7 @@ def reserve_collect_quota_limits(user_main, leixing, jine, shijidaozhang, shenhe
|
||||
|
||||
today = date.today()
|
||||
shijidaozhang = shijidaozhang or decimal.Decimal('0.00')
|
||||
club_id = _club_id_for_user(user_main)
|
||||
|
||||
if _get_active_auto_record(shenhe_danhao):
|
||||
return True, '', ''
|
||||
@@ -609,7 +587,7 @@ def reserve_collect_quota_limits(user_main, leixing, jine, shijidaozhang, shenhe
|
||||
personal_profile.jinri_tixian = decimal.Decimal('0.00')
|
||||
personal_today = personal_profile.jinri_tixian
|
||||
|
||||
personal_quota = _get_personal_daily_quota(leixing, personal_profile)
|
||||
personal_quota = _get_personal_daily_quota(club_id, leixing, personal_profile)
|
||||
if personal_today + jine > personal_quota:
|
||||
return (
|
||||
False,
|
||||
@@ -617,12 +595,8 @@ def reserve_collect_quota_limits(user_main, leixing, jine, shijidaozhang, shenhe
|
||||
'personal',
|
||||
)
|
||||
|
||||
platform_stat, _ = WithdrawalDailyStats.objects.select_for_update().get_or_create(
|
||||
Date=today,
|
||||
WithdrawalType=leixing,
|
||||
defaults={'total_amount': decimal.Decimal('0.00')},
|
||||
)
|
||||
platform_limit = _get_platform_daily_limit(leixing)
|
||||
platform_stat = get_or_create_platform_daily_stat(club_id, leixing, today)
|
||||
platform_limit = _get_platform_daily_limit(club_id, leixing)
|
||||
if platform_limit <= 0 and shijidaozhang > 0:
|
||||
return False, '今日该角色提现已关闭(总限额为0),暂无法收款', 'platform'
|
||||
if platform_stat.total_amount + shijidaozhang > platform_limit:
|
||||
@@ -659,6 +633,7 @@ def release_collect_quota_reservation(user_main, leixing, jine, shijidaozhang):
|
||||
"""微信打款明确失败/用户取消时回滚收款预占的限额"""
|
||||
today = date.today()
|
||||
shijidaozhang = shijidaozhang or decimal.Decimal('0.00')
|
||||
club_id = _club_id_for_user(user_main)
|
||||
try:
|
||||
with transaction.atomic():
|
||||
if leixing == 1:
|
||||
@@ -679,7 +654,7 @@ def release_collect_quota_reservation(user_main, leixing, jine, shijidaozhang):
|
||||
|
||||
try:
|
||||
stat = WithdrawalDailyStats.objects.select_for_update().get(
|
||||
Date=today, WithdrawalType=leixing,
|
||||
club_id=club_id, Date=today, WithdrawalType=leixing,
|
||||
)
|
||||
stat.total_amount = max(
|
||||
stat.total_amount - shijidaozhang,
|
||||
@@ -727,8 +702,10 @@ def _quota_already_reserved_for_record(auto_record):
|
||||
|
||||
today = date.today()
|
||||
shijidaozhang = auto_record.shijidaozhang or decimal.Decimal('0.00')
|
||||
stat_total = _get_platform_daily_total(auto_record.leixing, today)
|
||||
club_id = club_id_for_tixian_yonghuid(auto_record.yonghuid)
|
||||
stat_total = _get_platform_daily_total(club_id, auto_record.leixing, today)
|
||||
other_sum = TixianAutoRecord.query.filter(
|
||||
club_id=club_id,
|
||||
leixing=auto_record.leixing,
|
||||
zhuangtai__in=[0, 1],
|
||||
CreateTime__date=today,
|
||||
@@ -758,11 +735,8 @@ def apply_transfer_success_quota(auto_record):
|
||||
logger.error('打款成功累加限额失败:用户不存在 %s', auto_record.yonghuid)
|
||||
return
|
||||
|
||||
platform_stat, _ = WithdrawalDailyStats.objects.select_for_update().get_or_create(
|
||||
Date=today,
|
||||
WithdrawalType=leixing,
|
||||
defaults={'total_amount': decimal.Decimal('0.00')},
|
||||
)
|
||||
club_id = _club_id_for_user(user_main)
|
||||
platform_stat = get_or_create_platform_daily_stat(club_id, leixing, today)
|
||||
platform_stat.total_amount += shijidaozhang
|
||||
platform_stat.save(update_fields=['total_amount'])
|
||||
|
||||
@@ -981,19 +955,28 @@ def close_audit_over_limit_refund(audit, auto_record=None, fail_reason='单笔
|
||||
return True
|
||||
|
||||
|
||||
def query_wechat_transfer_bill(out_bill_no):
|
||||
def query_wechat_transfer_bill(out_bill_no, club_id=None):
|
||||
"""
|
||||
向微信查转账单状态
|
||||
GET /v3/fund-app/mch-transfer/transfer-bills/out-bill-no/{out_bill_no}
|
||||
返回 dict;网络/系统异常返回 None;微信无此单返回 {'_not_found': True}
|
||||
"""
|
||||
from jituan.services.wechat_pay import club_id_for_tixian_yonghuid
|
||||
|
||||
if not club_id:
|
||||
try:
|
||||
rec = TixianAutoRecord.query.filter(tixian_id=out_bill_no).first()
|
||||
if rec:
|
||||
club_id = club_id_for_tixian_yonghuid(rec.yonghuid)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
url = (
|
||||
'https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/'
|
||||
f'transfer-bills/out-bill-no/{out_bill_no}'
|
||||
)
|
||||
try:
|
||||
auth = build_authorization('GET', url, '')
|
||||
auth = build_authorization('GET', url, '', club_id=club_id)
|
||||
headers = {
|
||||
'Authorization': auth,
|
||||
'Accept': 'application/json',
|
||||
@@ -1030,21 +1013,11 @@ def _parse_package_info(raw):
|
||||
|
||||
def _apply_platform_accounting(auto_record):
|
||||
"""平台收支统计(幂等由 mark_transfer_success 外层保证只调一次)"""
|
||||
|
||||
update_daily_payout(auto_record.shijidaozhang)
|
||||
try:
|
||||
szjilu = Szjilu.objects.select_for_update().get(id=1)
|
||||
szjilu.TotalIncome -= auto_record.shijidaozhang
|
||||
szjilu.TotalExpense += auto_record.shijidaozhang
|
||||
szjilu.DailyExpense += auto_record.shijidaozhang
|
||||
szjilu.save()
|
||||
except Szjilu.DoesNotExist:
|
||||
Szjilu.query.create(
|
||||
id=1,
|
||||
TotalIncome=-auto_record.shijidaozhang,
|
||||
TotalExpense=auto_record.shijidaozhang,
|
||||
DailyExpense=auto_record.shijidaozhang,
|
||||
)
|
||||
from jituan.services.szjilu_accounting import apply_szjilu_expense
|
||||
from jituan.services.wechat_pay import club_id_for_tixian_yonghuid
|
||||
payout_club = club_id_for_tixian_yonghuid(auto_record.yonghuid)
|
||||
update_daily_payout(auto_record.shijidaozhang, payout_club)
|
||||
apply_szjilu_expense(auto_record.shijidaozhang, payout_club)
|
||||
|
||||
|
||||
def mark_transfer_success(auto_record, *, wechat_transfer_no=None, with_accounting=True):
|
||||
@@ -1210,7 +1183,7 @@ def reconcile_shenhe_wechat_bills(shenhe_danhao):
|
||||
if rec.zhuangtai == 1:
|
||||
return RECONCILE_COMPLETED, {'msg': '该提现已完成,请勿重复操作'}
|
||||
|
||||
wx_data = query_wechat_transfer_bill(rec.tixian_id)
|
||||
wx_data = query_wechat_transfer_bill(rec.tixian_id, club_id_for_tixian_yonghuid(rec.yonghuid))
|
||||
if wx_data is None:
|
||||
logger.error(
|
||||
'对账查单不可用 shenhe_danhao=%s bill=%s',
|
||||
@@ -1316,7 +1289,7 @@ def handle_post_transfer_failure(tixian_id, shenhe_danhao, err_code='', err_msg=
|
||||
except TixianAutoRecord.DoesNotExist:
|
||||
return RECONCILE_PENDING, '收款处理中,请稍后再试'
|
||||
|
||||
wx_data = query_wechat_transfer_bill(tixian_id)
|
||||
wx_data = query_wechat_transfer_bill(tixian_id, club_id_for_tixian_yonghuid(ar.yonghuid))
|
||||
if wx_data is None:
|
||||
logger.error(
|
||||
'发起转账失败且查单不可用 bill=%s code=%s msg=%s,保持待查单',
|
||||
@@ -1377,7 +1350,7 @@ def create_audit_application(user_main, leixing, jine):
|
||||
if not ok:
|
||||
raise ValueError(msg)
|
||||
|
||||
feilv = get_tixian_feilv(leixing)
|
||||
feilv = get_tixian_feilv(leixing, yonghuid=yonghuid)
|
||||
shouxufei, shijidaozhang = calc_fee_amounts(jine, feilv)
|
||||
if shijidaozhang <= 0:
|
||||
raise ValueError('提现金额过低,扣除手续费后无实际到账')
|
||||
@@ -1391,9 +1364,11 @@ def create_audit_application(user_main, leixing, jine):
|
||||
|
||||
with transaction.atomic():
|
||||
nicheng = deduct_balance(user_main, leixing, jine) or nicheng
|
||||
club_id = club_id_for_tixian_yonghuid(yonghuid)
|
||||
|
||||
audit_kwargs = {
|
||||
'shenhe_danhao': shenhe_danhao,
|
||||
'club_id': club_id,
|
||||
'yonghuid': yonghuid,
|
||||
'leixing': leixing,
|
||||
'zhuangtai': 1,
|
||||
@@ -1407,6 +1382,7 @@ def create_audit_application(user_main, leixing, jine):
|
||||
audit = TixianShenheJilu.query.create(**audit_kwargs)
|
||||
|
||||
tixian_record = Tixianjilu.query.create(
|
||||
club_id=club_id,
|
||||
yonghuid=yonghuid,
|
||||
avatar=user_main.Avatar or '',
|
||||
phone=user_main.Phone or '',
|
||||
|
||||
@@ -120,10 +120,10 @@ def _build_wx_transfer_body(wx_cfg, tixian_id, openid, yonghuid, leixing, shijid
|
||||
}
|
||||
|
||||
|
||||
def _call_wechat_transfer(body, wx_cfg):
|
||||
def _call_wechat_transfer(body, wx_cfg, club_id=None):
|
||||
url = 'https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills'
|
||||
body_json = json.dumps(body, separators=(',', ':'))
|
||||
auth = build_authorization('POST', url, body_json)
|
||||
auth = build_authorization('POST', url, body_json, club_id=club_id)
|
||||
headers = {
|
||||
'Authorization': auth,
|
||||
'Content-Type': 'application/json',
|
||||
@@ -203,9 +203,13 @@ def process_audit_collect(request):
|
||||
if not user_main.OpenID:
|
||||
return Response({'code': 10, 'msg': '用户未绑定微信,无法收款'})
|
||||
|
||||
wx_cfg = settings.WECHAT_PAY_V3_CONFIG
|
||||
from jituan.services.club_user import get_user_club_id
|
||||
from jituan.services.wechat_pay import get_wechat_v3_config
|
||||
|
||||
payout_club_id = get_user_club_id(user_main)
|
||||
wx_cfg = get_wechat_v3_config(payout_club_id)
|
||||
if not wx_cfg.get('APPID') or not wx_cfg.get('MCHID') or not wx_cfg.get('TRANSFER_SCENE_ID'):
|
||||
logger.error('微信打款配置不完整 APPID=%s MCHID=%s', wx_cfg.get('APPID'), wx_cfg.get('MCHID'))
|
||||
logger.error('微信打款配置不完整 club=%s APPID=%s MCHID=%s', payout_club_id, wx_cfg.get('APPID'), wx_cfg.get('MCHID'))
|
||||
return Response({'code': 11, 'msg': '系统配置异常,请联系客服'})
|
||||
|
||||
ctx, err = resolve_collect_context(
|
||||
@@ -295,8 +299,10 @@ def process_audit_collect(request):
|
||||
quota_reserved = True
|
||||
|
||||
tixian_id = generate_tixian_id()
|
||||
from jituan.services.club_user import get_user_club_id
|
||||
TixianAutoRecord.query.create(
|
||||
tixian_id=tixian_id,
|
||||
club_id=get_user_club_id(user_main),
|
||||
yonghuid=yonghuid,
|
||||
leixing=leixing,
|
||||
jine=jine,
|
||||
@@ -314,7 +320,7 @@ def process_audit_collect(request):
|
||||
)
|
||||
|
||||
try:
|
||||
resp, wx_result = _call_wechat_transfer(body, wx_cfg)
|
||||
resp, wx_result = _call_wechat_transfer(body, wx_cfg, payout_club_id)
|
||||
|
||||
if resp.status_code == 200 and wx_result.get('state') == 'WAIT_USER_CONFIRM':
|
||||
package_info = wx_result.get('package_info')
|
||||
|
||||
395
users/views.py
395
users/views.py
@@ -43,8 +43,6 @@ from gvsdsdk.fluent import db, func, FQ
|
||||
|
||||
from utils.oss_utils import validate_image, upload_to_oss, delete_from_oss
|
||||
from utils.fadan_utils import check_fadan_qiangdan_eligible
|
||||
from utils.wechat_v3 import verify_wechat_sign, decrypt_callback_ciphertext
|
||||
|
||||
from utils.invitationcode_utils import CreateInvitationCode, VerifyInvitationCode
|
||||
from users.fadan_fenhong_utils import process_fadan_fenhong
|
||||
|
||||
@@ -83,7 +81,7 @@ from orders.models import (
|
||||
from products.models import (
|
||||
ShangpinLeixing, Huiyuan, Huiyuangoumai, Gsfenhong, Czjilu
|
||||
)
|
||||
from config.models import Qunpeizhi, Szjilu
|
||||
from config.models import Qunpeizhi
|
||||
from backend.models import MerchantDailyStats
|
||||
from rank.models import (
|
||||
KaohePayTemp, Chenghao, ShenheJilu,
|
||||
@@ -1327,6 +1325,15 @@ class DashouZhuceView(APIView):
|
||||
'data': None
|
||||
}, status=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
from jituan.services.invite_guard import assert_invite_same_club
|
||||
ok, msg = assert_invite_same_club(request, guanshi_profile.user, current_user)
|
||||
if not ok:
|
||||
return Response({
|
||||
'code': 403,
|
||||
'message': msg,
|
||||
'data': None
|
||||
}, status=status.HTTP_403_FORBIDDEN)
|
||||
|
||||
# 4. 验证管事状态
|
||||
|
||||
# 5. 核心:在数据库事务中创建用户的所有身份
|
||||
@@ -1590,25 +1597,20 @@ class TixianXinxiHuoquView(APIView):
|
||||
# 从request.user获取当前用户
|
||||
user_main = request.user
|
||||
|
||||
# 🔥【修改开始 - 使用Decimal,字段名是Rate】
|
||||
# 查询打手提现费率 (Platform='5')
|
||||
dashou_rate_obj = CommissionRate.query.filter(Platform='5').first()
|
||||
dashou_rate = decimal.Decimal(str(dashou_rate_obj.Rate)) if dashou_rate_obj else decimal.Decimal('0.00')
|
||||
from jituan.services.club_user import get_user_club_id
|
||||
from jituan.services.withdraw_config import get_tixian_feilv
|
||||
|
||||
# 查询管事提现费率 (Platform='6')
|
||||
guanshi_rate_obj = CommissionRate.query.filter(Platform='6').first()
|
||||
guanshi_rate = decimal.Decimal(str(guanshi_rate_obj.Rate)) if guanshi_rate_obj else decimal.Decimal('0.00')
|
||||
# 🔥【修改结束】
|
||||
club_id = get_user_club_id(user_main)
|
||||
dashou_rate = get_tixian_feilv(club_id, 1)
|
||||
guanshi_rate = get_tixian_feilv(club_id, 2)
|
||||
|
||||
# 构建返回数据
|
||||
response_data = {
|
||||
'txdianhua': user_main.Phone if user_main.Phone else '',
|
||||
'txtupian': user_main.PaymentQRCode if user_main.PaymentQRCode else '',
|
||||
'txzh': user_main.PaymentAccount if user_main.PaymentAccount else '',
|
||||
# 🔥【修改开始】
|
||||
'dashou_rate': dashou_rate, # 打手提现费率
|
||||
'guanshi_rate': guanshi_rate, # 管事提现费率
|
||||
# 🔥【修改结束】
|
||||
'dashou_rate': dashou_rate,
|
||||
'guanshi_rate': guanshi_rate,
|
||||
}
|
||||
|
||||
# 返回成功响应
|
||||
@@ -1850,7 +1852,10 @@ class TixianShenqingView(APIView):
|
||||
return Response({'code': 5, 'msg': '无效的收款方式,只能是1(微信)或2(支付宝)'},
|
||||
status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
# 2. 获取对应费率及手续费
|
||||
from jituan.services.club_user import get_user_club_id
|
||||
from jituan.services.withdraw_config import get_tixian_feilv
|
||||
|
||||
club_id = get_user_club_id(user_main)
|
||||
current_rate = decimal.Decimal('0.00')
|
||||
rate_key = {
|
||||
1: '5', # 打手佣金
|
||||
@@ -1862,10 +1867,9 @@ class TixianShenqingView(APIView):
|
||||
}.get(leixing)
|
||||
|
||||
if rate_key:
|
||||
rate_obj = CommissionRate.query.filter(Platform=rate_key).first()
|
||||
if rate_obj:
|
||||
current_rate = decimal.Decimal(str(rate_obj.Rate))
|
||||
else:
|
||||
try:
|
||||
current_rate = get_tixian_feilv(club_id, leixing)
|
||||
except ValueError:
|
||||
return Response({'code': 41, 'msg': f'提现费率未配置(类型{leixing})'},
|
||||
status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
@@ -1956,7 +1960,9 @@ class TixianShenqingView(APIView):
|
||||
phone = user_main.Phone or ''
|
||||
zhifu = user_main.PaymentQRCode or ''
|
||||
skzhanghao = user_main.PaymentAccount or ''
|
||||
from jituan.services.club_user import get_user_club_id
|
||||
tixian_record = Tixianjilu.query.create(
|
||||
club_id=get_user_club_id(user_main),
|
||||
yonghuid=yonghuid,
|
||||
avatar=avatar,
|
||||
phone=phone,
|
||||
@@ -2482,43 +2488,10 @@ class AdminFinancialDataView(APIView):
|
||||
status=status.HTTP_401_UNAUTHORIZED
|
||||
)
|
||||
|
||||
# 6. 查询收支记录表(Szjilu)
|
||||
# 使用高效的ORM查询,获取最新的一条记录
|
||||
# 注意:根据你的业务需求,这里获取最新的一条记录
|
||||
# 如果需要汇总多条记录,可以使用aggregate进行聚合查询
|
||||
|
||||
# 方法1:获取最新的一条记录(假设表中只有一条汇总记录)
|
||||
shouzhijilu = Szjilu.query.order_by('-CreateTime').first()
|
||||
|
||||
# 方法2:如果表中可能有多条记录,需要汇总,可以使用以下方式:
|
||||
# from django.db.models Sum
|
||||
# zonghe = Szjilu.query.aggregate(
|
||||
# zongliushui=Sum('TotalFlow'),
|
||||
# zongshouyi=Sum('TotalIncome'),
|
||||
# zongzhichu=Sum('TotalExpense'),
|
||||
# DailyFlow=Sum('DailyFlow'),
|
||||
# DailyExpense=Sum('DailyExpense')
|
||||
# )
|
||||
|
||||
# 准备返回数据
|
||||
if shouzhijilu:
|
||||
# 有记录的情况
|
||||
huizongshuju = {
|
||||
'zongliushui': float(shouzhijilu.TotalFlow or 0),
|
||||
'zongshouyi': float(shouzhijilu.TotalIncome or 0),
|
||||
'zongzhichu': float(shouzhijilu.TotalExpense or 0),
|
||||
'jrls': float(shouzhijilu.DailyFlow or 0),
|
||||
'jrzc': float(shouzhijilu.DailyExpense or 0)
|
||||
}
|
||||
else:
|
||||
# 没有记录的情况,返回默认值
|
||||
huizongshuju = {
|
||||
'zongliushui': 0.00,
|
||||
'zongshouyi': 0.00,
|
||||
'zongzhichu': 0.00,
|
||||
'jrls': 0.00,
|
||||
'jrzc': 0.00
|
||||
}
|
||||
# 6. 查询收支记录表(按俱乐部 xq,旧管理员端默认)
|
||||
from jituan.constants import CLUB_ID_DEFAULT
|
||||
from jituan.services.szjilu_accounting import get_szjilu_snapshot
|
||||
huizongshuju = get_szjilu_snapshot(CLUB_ID_DEFAULT)
|
||||
|
||||
# 7. 返回成功响应
|
||||
return Response({
|
||||
@@ -4347,11 +4320,13 @@ class AdcjxgView(APIView):
|
||||
# 🔥 修改:新购买时只能增加天数
|
||||
if days > 0:
|
||||
daoqi_time = timezone.now() + timedelta(days=days)
|
||||
from jituan.services.club_user import get_user_club_id
|
||||
new_record = Huiyuangoumai.query.create(
|
||||
huiyuan_id=huiyuan_id,
|
||||
yonghu_id=uid,
|
||||
jieshao=huiyuan.jieshao,
|
||||
daoqi_time=daoqi_time
|
||||
daoqi_time=daoqi_time,
|
||||
club_id=get_user_club_id(User.query.filter(UserUID=uid).first()),
|
||||
)
|
||||
|
||||
# 记录会员购买
|
||||
@@ -4638,29 +4613,14 @@ class AdtixianqkView(APIView):
|
||||
# 🟢 新增:如果同意提现(result=2),更新收支记录表
|
||||
if result == 2:
|
||||
try:
|
||||
# 查询收支记录表,id=1的记录
|
||||
szjilu_record = Szjilu.query.get(id=1)
|
||||
|
||||
# 获取提现金额
|
||||
tixian_jine = withdrawal.jine # 假设提现记录模型中有jine字段
|
||||
|
||||
update_daily_payout(tixian_jine)
|
||||
|
||||
# 更新收支记录
|
||||
szjilu_record.TotalIncome -= tixian_jine # 总收益减去提现金额
|
||||
szjilu_record.TotalExpense += tixian_jine # 总支出加上提现金额
|
||||
szjilu_record.DailyExpense += tixian_jine # 今日支出加上提现金额
|
||||
szjilu_record.UpdateTime = timezone.now()
|
||||
szjilu_record.save()
|
||||
|
||||
except Szjilu.DoesNotExist:
|
||||
# 如果收支记录表不存在id=1的记录,创建一个
|
||||
szjilu_record = Szjilu.query.create(
|
||||
id=1,
|
||||
TotalIncome=-tixian_jine if result == 2 else 0,
|
||||
TotalExpense=tixian_jine if result == 2 else 0,
|
||||
DailyExpense=tixian_jine if result == 2 else 0
|
||||
from jituan.services.szjilu_accounting import apply_szjilu_expense
|
||||
tixian_jine = withdrawal.jine
|
||||
from jituan.services.club_user import get_user_club_id
|
||||
payout_club = get_user_club_id(
|
||||
User.query.filter(UserUID=withdrawal.yonghuid).first()
|
||||
)
|
||||
update_daily_payout(tixian_jine, payout_club)
|
||||
apply_szjilu_expense(tixian_jine, payout_club)
|
||||
except Exception as e:
|
||||
# 如果更新收支记录失败,抛出异常,事务会回滚
|
||||
raise Exception(f"更新收支记录失败: {str(e)}")
|
||||
@@ -5372,6 +5332,22 @@ class WechatLoginAndDashouRegisterView(APIView):
|
||||
# 这里我们继续执行,但只返回登录信息
|
||||
return self.fanhuiZhihouDengluXinxi(user_main, yaoqingma_wuxiao=True)
|
||||
|
||||
from jituan.services.invite_guard import assert_invite_same_club
|
||||
from jituan.services.club_user import ensure_user_club_id
|
||||
from jituan.services.club_context import resolve_club_id_from_request
|
||||
|
||||
ok, invite_msg = assert_invite_same_club(
|
||||
request, guanshi_profile.user, user_main,
|
||||
)
|
||||
if not ok:
|
||||
return Response({
|
||||
'code': 403,
|
||||
'msg': invite_msg,
|
||||
'data': None
|
||||
}, status=status.HTTP_403_FORBIDDEN)
|
||||
|
||||
ensure_user_club_id(user_main, resolve_club_id_from_request(request))
|
||||
|
||||
# 验证管事状态
|
||||
|
||||
# 4.3 检查用户是否已是打手
|
||||
@@ -7100,8 +7076,12 @@ class KefuGetOrderListView(APIView):
|
||||
if clkf:
|
||||
q_conditions &= Q(AssignedCS__icontains=clkf)
|
||||
|
||||
from jituan.services.club_context import orders_for_request
|
||||
|
||||
# ---------- 统计(仅按发单平台,非跨平台) ----------
|
||||
stats = Order.query.filter(Platform=1).aggregate(
|
||||
club_orders = orders_for_request(request)
|
||||
platform_orders = club_orders.filter(Platform=1)
|
||||
stats = platform_orders.aggregate(
|
||||
total_orders=Count('id'),
|
||||
completed_orders=Count('id', filter=Q(Status=3)),
|
||||
refund_orders=Count('id', filter=Q(Status=5)),
|
||||
@@ -7110,20 +7090,20 @@ class KefuGetOrderListView(APIView):
|
||||
|
||||
# ---------- 状态计数(所有状态都返回,非跨平台) ----------
|
||||
status_counts = {
|
||||
'all': Order.query.filter(Platform=1).count(),
|
||||
'1,7': Order.query.filter(Platform=1, Status__in=[1,7]).count(),
|
||||
'2': Order.query.filter(Platform=1, Status=2).count(),
|
||||
'8': Order.query.filter(Platform=1, Status=8).count(),
|
||||
'3': Order.query.filter(Platform=1, Status=3).count(),
|
||||
'4': Order.query.filter(Platform=1, Status=4).count(),
|
||||
'5': Order.query.filter(Platform=1, Status=5).count(),
|
||||
'6': Order.query.filter(Platform=1, Status=6).count(),
|
||||
'all': platform_orders.count(),
|
||||
'1,7': platform_orders.filter(Status__in=[1,7]).count(),
|
||||
'2': platform_orders.filter(Status=2).count(),
|
||||
'8': platform_orders.filter(Status=8).count(),
|
||||
'3': platform_orders.filter(Status=3).count(),
|
||||
'4': platform_orders.filter(Status=4).count(),
|
||||
'5': platform_orders.filter(Status=5).count(),
|
||||
'6': platform_orders.filter(Status=6).count(),
|
||||
}
|
||||
|
||||
# ---------- 分页查询 ----------
|
||||
total_count = Order.query.filter(q_conditions).count()
|
||||
total_count = club_orders.filter(q_conditions).count()
|
||||
|
||||
orders_qs = Order.query.filter(q_conditions).select_related(
|
||||
orders_qs = club_orders.filter(q_conditions).select_related(
|
||||
'pingtai_kuozhan'
|
||||
).only(
|
||||
'OrderID', 'Description', 'Status', 'ProductTypeID', 'Platform',
|
||||
@@ -7158,6 +7138,8 @@ class KefuGetOrderListView(APIView):
|
||||
'youxi_nicheng': youxi_nicheng
|
||||
})
|
||||
|
||||
from jituan.services.club_user_access import list_response_meta
|
||||
|
||||
response_data = {
|
||||
'stats': {
|
||||
'totalOrders': stats['total_orders'] or 0,
|
||||
@@ -7169,7 +7151,8 @@ class KefuGetOrderListView(APIView):
|
||||
'list': result_list,
|
||||
'total': total_count,
|
||||
'page': page,
|
||||
'pageSize': page_size
|
||||
'pageSize': page_size,
|
||||
**list_response_meta(request),
|
||||
}
|
||||
|
||||
logger.info(f"平台订单接口总耗时: {time.time()-start_total:.3f}s")
|
||||
@@ -7269,8 +7252,12 @@ class KefuGetShangjiaOrderListView(APIView):
|
||||
ShopProfile__nicheng__icontains=shangjia_nicheng
|
||||
).values_list('UserUID', flat=True))
|
||||
|
||||
from jituan.services.club_context import orders_for_request
|
||||
|
||||
# ---------- 统计(仅按发单平台,非跨平台) ----------
|
||||
stats = Order.query.filter(Platform=2).aggregate(
|
||||
club_orders = orders_for_request(request)
|
||||
merchant_orders = club_orders.filter(Platform=2)
|
||||
stats = merchant_orders.aggregate(
|
||||
total_orders=Count('id'),
|
||||
completed_orders=Count('id', filter=Q(Status=3)),
|
||||
refund_orders=Count('id', filter=Q(Status=5)),
|
||||
@@ -7279,20 +7266,20 @@ class KefuGetShangjiaOrderListView(APIView):
|
||||
|
||||
# ---------- 状态计数(所有状态都返回,非跨平台) ----------
|
||||
status_counts = {
|
||||
'all': Order.query.filter(Platform=2).count(),
|
||||
'1,7': Order.query.filter(Platform=2, Status__in=[1,7]).count(),
|
||||
'2': Order.query.filter(Platform=2, Status=2).count(),
|
||||
'8': Order.query.filter(Platform=2, Status=8).count(),
|
||||
'3': Order.query.filter(Platform=2, Status=3).count(),
|
||||
'4': Order.query.filter(Platform=2, Status=4).count(),
|
||||
'5': Order.query.filter(Platform=2, Status=5).count(),
|
||||
'6': Order.query.filter(Platform=2, Status=6).count(),
|
||||
'all': merchant_orders.count(),
|
||||
'1,7': merchant_orders.filter(Status__in=[1,7]).count(),
|
||||
'2': merchant_orders.filter(Status=2).count(),
|
||||
'8': merchant_orders.filter(Status=8).count(),
|
||||
'3': merchant_orders.filter(Status=3).count(),
|
||||
'4': merchant_orders.filter(Status=4).count(),
|
||||
'5': merchant_orders.filter(Status=5).count(),
|
||||
'6': merchant_orders.filter(Status=6).count(),
|
||||
}
|
||||
|
||||
# ---------- 分页查询 ----------
|
||||
total_count = Order.query.filter(q_conditions).count()
|
||||
total_count = club_orders.filter(q_conditions).count()
|
||||
|
||||
orders_qs = Order.query.filter(q_conditions).select_related(
|
||||
orders_qs = club_orders.filter(q_conditions).select_related(
|
||||
'shangjia_kuozhan'
|
||||
).only(
|
||||
'OrderID', 'Description', 'Status', 'ProductTypeID', 'Platform',
|
||||
@@ -7327,6 +7314,8 @@ class KefuGetShangjiaOrderListView(APIView):
|
||||
'youxi_nicheng': youxi_nicheng
|
||||
})
|
||||
|
||||
from jituan.services.club_user_access import list_response_meta
|
||||
|
||||
response_data = {
|
||||
'stats': {
|
||||
'totalOrders': stats['total_orders'] or 0,
|
||||
@@ -7338,7 +7327,8 @@ class KefuGetShangjiaOrderListView(APIView):
|
||||
'list': result_list,
|
||||
'total': total_count,
|
||||
'page': page,
|
||||
'pageSize': page_size
|
||||
'pageSize': page_size,
|
||||
**list_response_meta(request),
|
||||
}
|
||||
|
||||
logger.info(f"商家订单接口总耗时: {time.time()-start_total:.3f}s")
|
||||
@@ -7708,7 +7698,7 @@ class KefuPlatformRefundView(APIView):
|
||||
# 10. 更新退款记录表(假设存在 RefundRecord 模型,字段需根据实际调整)
|
||||
|
||||
#更新支出记录
|
||||
update_daily_payout(order.Amount)
|
||||
update_daily_payout(order.Amount, getattr(order, 'ClubID', None))
|
||||
|
||||
|
||||
try:
|
||||
@@ -9033,14 +9023,18 @@ class KefuPunishmentListView(APIView):
|
||||
return Response({'code': 403, 'msg': '您无权查看平台订单列表'})
|
||||
|
||||
# 3. 获取统计信息(不分页)
|
||||
from jituan.services.club_penalty import filter_penalty_record_qs
|
||||
from jituan.services.club_user_access import list_response_meta
|
||||
|
||||
base_qs = filter_penalty_record_qs(PenaltyRecord.query.all(), request)
|
||||
stats = {
|
||||
'zongshu': PenaltyRecord.query.count(),
|
||||
'daichuli': PenaltyRecord.query.filter(ApplyStatus__in=[0, 3]).count(),
|
||||
'yichuli': PenaltyRecord.query.filter(ApplyStatus__in=[1, 2]).count(),
|
||||
'zongshu': base_qs.count(),
|
||||
'daichuli': base_qs.filter(ApplyStatus__in=[0, 3]).count(),
|
||||
'yichuli': base_qs.filter(ApplyStatus__in=[1, 2]).count(),
|
||||
}
|
||||
|
||||
# 4. 构建查询条件
|
||||
queryset = PenaltyRecord.query.all()
|
||||
queryset = base_qs
|
||||
|
||||
if status_list and isinstance(status_list, list):
|
||||
queryset = queryset.filter(ApplyStatus__in=status_list)
|
||||
@@ -9075,7 +9069,8 @@ class KefuPunishmentListView(APIView):
|
||||
'data': {
|
||||
'list': list_data,
|
||||
'total': total,
|
||||
'stats': stats
|
||||
'stats': stats,
|
||||
**list_response_meta(request),
|
||||
}
|
||||
})
|
||||
|
||||
@@ -9696,12 +9691,14 @@ class KefuWithdrawListView(APIView):
|
||||
)
|
||||
return False
|
||||
|
||||
def _list_queryset(self, q, shenhe_field_ok):
|
||||
def _list_queryset(self, q, shenhe_field_ok, request):
|
||||
"""字段未迁移时 only 旧字段,避免 SELECT 不存在的列导致 500"""
|
||||
fields = _TIXIAN_LIST_BASE_FIELDS + (
|
||||
_TIXIAN_LIST_AUDIT_FIELDS if shenhe_field_ok else ()
|
||||
)
|
||||
return Tixianjilu.query.filter(q).only(*fields)
|
||||
from jituan.services.tixian_club import filter_tixianjilu_by_request
|
||||
qs = Tixianjilu.query.filter(q).only(*fields)
|
||||
return filter_tixianjilu_by_request(qs, request)
|
||||
|
||||
def _resolve_row_dakuan_mode(self, item, audit_mode_map, shenhe_field_ok):
|
||||
"""无关联审核或审核表未标记自动 → 默认手动(1)"""
|
||||
@@ -9747,7 +9744,7 @@ class KefuWithdrawListView(APIView):
|
||||
if kefu is None:
|
||||
return permissions
|
||||
if '005bb' not in permissions:
|
||||
return Response({'code': 403, 'msg': '您无权查看平台订单列表'})
|
||||
return Response({'code': 403, 'msg': '您无权查看提现审核列表'})
|
||||
|
||||
q = Q()
|
||||
|
||||
@@ -9824,11 +9821,11 @@ class KefuWithdrawListView(APIView):
|
||||
|
||||
processed_statuses = [2, 3, 4, 5, 6] if effective_dakuan == 2 else [2, 3]
|
||||
|
||||
base_qs = self._list_queryset(q, shenhe_field_ok)
|
||||
base_qs = self._list_queryset(q, shenhe_field_ok, request)
|
||||
total_count = base_qs.count()
|
||||
awaiting_count = self._list_queryset(q & Q(zhuangtai=1), shenhe_field_ok).count()
|
||||
awaiting_count = self._list_queryset(q & Q(zhuangtai=1), shenhe_field_ok, request).count()
|
||||
processed_count = self._list_queryset(
|
||||
q & Q(zhuangtai__in=processed_statuses), shenhe_field_ok,
|
||||
q & Q(zhuangtai__in=processed_statuses), shenhe_field_ok, request,
|
||||
).count()
|
||||
agg = base_qs.aggregate(total=Sum('jine'))
|
||||
total_amount = agg.get('total') or 0
|
||||
@@ -9888,12 +9885,15 @@ class KefuWithdrawListView(APIView):
|
||||
'UpdateTime': item.UpdateTime.strftime('%Y-%m-%d %H:%M:%S') if item.UpdateTime else '',
|
||||
})
|
||||
|
||||
from jituan.services.club_user_access import list_response_meta
|
||||
|
||||
return Response({
|
||||
'code': 0,
|
||||
'data': {
|
||||
'list': list_data,
|
||||
'total': total,
|
||||
'stats': stats,
|
||||
**list_response_meta(request),
|
||||
},
|
||||
})
|
||||
|
||||
@@ -9971,6 +9971,11 @@ class KefuWithdrawDetailView(APIView):
|
||||
except Tixianjilu.DoesNotExist:
|
||||
return Response({'code': 404, 'msg': '提现记录不存在'}, status=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
from jituan.services.tixian_club import forbid_if_tixian_out_of_scope
|
||||
deny = forbid_if_tixian_out_of_scope(request, record)
|
||||
if deny:
|
||||
return deny
|
||||
|
||||
# 查询用户主表
|
||||
try:
|
||||
user = User.query.get(UserUID=record.yonghuid)
|
||||
@@ -10113,7 +10118,7 @@ class KefuWithdrawActionView(APIView):
|
||||
return None, Response({'code': 400, 'msg': '参数格式错误'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
return [item], None
|
||||
|
||||
def _process_auto_item(self, item, action, reason, kefu_user):
|
||||
def _process_auto_item(self, request, item, action, reason, kefu_user):
|
||||
"""自动打款单条处理(须在 transaction.atomic 内调用)"""
|
||||
tixian_id = item['tixian_id']
|
||||
req_yonghuid = item['yonghuid']
|
||||
@@ -10127,6 +10132,11 @@ class KefuWithdrawActionView(APIView):
|
||||
except Tixianjilu.DoesNotExist:
|
||||
raise ValueError(f'提现记录{tixian_id}不存在')
|
||||
|
||||
from jituan.services.tixian_club import forbid_if_tixian_out_of_scope
|
||||
deny = forbid_if_tixian_out_of_scope(request, tixian)
|
||||
if deny:
|
||||
raise ValueError(deny.data.get('msg', '无权限处理该提现记录'))
|
||||
|
||||
if tixian.yonghuid != req_yonghuid:
|
||||
raise ValueError(f'提现记录{tixian_id}:用户ID不匹配')
|
||||
if tixian.leixing != req_leixing:
|
||||
@@ -10181,7 +10191,7 @@ class KefuWithdrawActionView(APIView):
|
||||
tixian.bhliyou = reason
|
||||
tixian.save(update_fields=['shenheid', 'bhliyou', 'UpdateTime'])
|
||||
|
||||
def _process_manual_item(self, item, action, reason, phone):
|
||||
def _process_manual_item(self, request, item, action, reason, phone):
|
||||
"""手动打款单条处理(原逻辑,须在 transaction.atomic 内调用)"""
|
||||
tixian_id = item['tixian_id']
|
||||
try:
|
||||
@@ -10189,6 +10199,11 @@ class KefuWithdrawActionView(APIView):
|
||||
except Tixianjilu.DoesNotExist:
|
||||
raise ValueError(f'提现记录{tixian_id}不存在')
|
||||
|
||||
from jituan.services.tixian_club import forbid_if_tixian_out_of_scope
|
||||
deny = forbid_if_tixian_out_of_scope(request, tixian)
|
||||
if deny:
|
||||
raise ValueError(deny.data.get('msg', '无权限处理该提现记录'))
|
||||
|
||||
req_yonghuid = item.get('yonghuid')
|
||||
req_leixing = item.get('leixing')
|
||||
if req_yonghuid and tixian.yonghuid != req_yonghuid:
|
||||
@@ -10206,16 +10221,14 @@ class KefuWithdrawActionView(APIView):
|
||||
except User.DoesNotExist:
|
||||
raise ValueError(f'用户{tixian.yonghuid}不存在')
|
||||
|
||||
from jituan.services.club_user import get_user_club_id
|
||||
|
||||
if action == 1:
|
||||
tixian.zhuangtai = 2
|
||||
try:
|
||||
update_daily_payout(tixian.jine)
|
||||
szjilu, _ = Szjilu.query.get_or_create(id=1)
|
||||
szjilu.TotalIncome -= tixian.jine
|
||||
szjilu.TotalExpense += tixian.jine
|
||||
szjilu.DailyExpense += tixian.jine
|
||||
szjilu.UpdateTime = timezone.now()
|
||||
szjilu.save()
|
||||
from jituan.services.szjilu_accounting import apply_szjilu_expense
|
||||
update_daily_payout(tixian.jine, get_user_club_id(user))
|
||||
apply_szjilu_expense(tixian.jine, get_user_club_id(user))
|
||||
except Exception as e:
|
||||
logger.error(f'更新收支记录失败: {e}')
|
||||
else:
|
||||
@@ -10265,15 +10278,20 @@ class KefuWithdrawActionView(APIView):
|
||||
except Tixianjilu.DoesNotExist:
|
||||
raise ValueError(f'提现记录{tixian_id}不存在')
|
||||
|
||||
from jituan.services.tixian_club import forbid_if_tixian_out_of_scope
|
||||
deny = forbid_if_tixian_out_of_scope(request, tixian_probe)
|
||||
if deny:
|
||||
raise ValueError(deny.data.get('msg', '无权限处理该提现记录'))
|
||||
|
||||
# 有关联审核记录(shenhe_jilu_id)即为 zddksh 自动打款,不依赖 dakuan_mode 字段
|
||||
is_auto = bool(getattr(tixian_probe, 'shenhe_jilu_id', None))
|
||||
|
||||
if is_auto:
|
||||
self._process_auto_item(item, action, reason, kefu_user)
|
||||
self._process_auto_item(request, item, action, reason, kefu_user)
|
||||
else:
|
||||
if is_batch:
|
||||
raise ValueError(f'提现记录{tixian_id}:批量操作仅支持自动打款记录')
|
||||
self._process_manual_item(item, action, reason, phone)
|
||||
self._process_manual_item(request, item, action, reason, phone)
|
||||
|
||||
except ValueError as e:
|
||||
return Response({'code': 400, 'msg': str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
||||
@@ -10943,6 +10961,12 @@ class GuanshiRegisterView(APIView):
|
||||
return Response({'code': 403, 'msg': '该邀请码对应的组长账号已被禁用', 'data': None},
|
||||
status=status.HTTP_403_FORBIDDEN)
|
||||
|
||||
from jituan.services.invite_guard import assert_invite_same_club
|
||||
ok, invite_msg = assert_invite_same_club(request, zuzhang.user, current_user)
|
||||
if not ok:
|
||||
return Response({'code': 403, 'msg': invite_msg, 'data': None},
|
||||
status=status.HTTP_403_FORBIDDEN)
|
||||
|
||||
zuzhang_yonghuid = zuzhang.user.UserUID
|
||||
|
||||
# 4. 事务内创建管事实体和打手(如果需要)
|
||||
@@ -11197,6 +11221,10 @@ class ZuzhangZhuceView(APIView):
|
||||
if invite_code != self.ACTIVATION_CODE:
|
||||
return Response({'code': 400, 'msg': '邀请码无效'}, status=400)
|
||||
|
||||
from jituan.services.club_user import ensure_user_club_id
|
||||
from jituan.services.club_context import resolve_club_id_from_request
|
||||
ensure_user_club_id(user, resolve_club_id_from_request(request))
|
||||
|
||||
# 生成唯一组长邀请码:时间戳 + 用户ID后6位 + 随机字符
|
||||
yaoqingma = self._generate_unique_yaoqingma(user.UserUID)
|
||||
|
||||
@@ -11707,13 +11735,15 @@ class FaKuanPayView(APIView):
|
||||
random_num = random.randint(0, 99)
|
||||
dingdanid = f"FK{timestamp_ms:011d}{timestamp_ns:06d}{random_num:02d}"
|
||||
|
||||
from jituan.services.club_write import resolve_club_id_for_write
|
||||
chongzhi_jilu = Czjilu.query.create(
|
||||
dingdan_id=dingdanid,
|
||||
zhuangtai=9,
|
||||
yonghuid=request.user.UserUID,
|
||||
jine=jine,
|
||||
leixing=4,
|
||||
shuoming=settings.FAKUAN_PAY_DESCRIPTION
|
||||
shuoming=settings.FAKUAN_PAY_DESCRIPTION,
|
||||
club_id=resolve_club_id_for_write(request, request.user),
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -11746,9 +11776,12 @@ class FaKuanPayView(APIView):
|
||||
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
def generate_wechat_pay_params(self, dingdanid, jine, openid, pay_type):
|
||||
APPID = settings.WEIXIN_APPID
|
||||
MCHID = settings.WEIXIN_MCHID
|
||||
KEY = settings.WEIXIN_SHANGHUMIYAO
|
||||
from jituan.services.club_write import resolve_club_id_for_write
|
||||
from jituan.services.wechat_pay import get_wechat_v2_config
|
||||
pay_cfg = get_wechat_v2_config(resolve_club_id_for_write(self.request, request.user))
|
||||
APPID = pay_cfg['appid']
|
||||
MCHID = pay_cfg['mch_id']
|
||||
KEY = pay_cfg['key']
|
||||
|
||||
if pay_type == 'fakuan':
|
||||
PAY_DESCRIPTION = settings.FAKUAN_PAY_DESCRIPTION
|
||||
@@ -11884,7 +11917,9 @@ class FaKuanHuitiaoView(View):
|
||||
return self.wechat_response('FAIL', '支付失败')
|
||||
|
||||
# 3. 验证签名(确保是微信发来的)
|
||||
if not self.verify_signature(request_body):
|
||||
from jituan.services.wechat_pay import club_id_from_czjilu, verify_wechat_v2_signature
|
||||
notify_club = club_id_from_czjilu(out_trade_no)
|
||||
if not verify_wechat_v2_signature(request_body, notify_club):
|
||||
logger.error(f"签名验证失败: {out_trade_no}")
|
||||
return self.wechat_response('FAIL', '签名验证失败')
|
||||
|
||||
@@ -11944,26 +11979,9 @@ class FaKuanHuitiaoView(View):
|
||||
# 获取订单金额(确保是Decimal类型)
|
||||
jine_decimal = Decimal(str(order.jine)) if not isinstance(order.jine, Decimal) else order.jine
|
||||
|
||||
update_daily_income(jine_decimal)
|
||||
|
||||
# 查询或创建ID=1的收支记录
|
||||
szjilu, created = Szjilu.query.get_or_create(
|
||||
id=1,
|
||||
defaults={
|
||||
'TotalIncome': Decimal('0.00'),
|
||||
'TotalFlow': Decimal('0.00'),
|
||||
'TotalExpense': Decimal('0.00'),
|
||||
'DailyExpense': Decimal('0.00'),
|
||||
'DailyFlow': Decimal('0.00')
|
||||
}
|
||||
)
|
||||
|
||||
# 更新三个字段
|
||||
szjilu.TotalIncome += jine_decimal # 总收益
|
||||
szjilu.TotalFlow += jine_decimal # 总流水
|
||||
szjilu.DailyFlow += jine_decimal # 今日流水
|
||||
|
||||
szjilu.save()
|
||||
update_daily_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
from jituan.services.szjilu_accounting import apply_szjilu_income
|
||||
apply_szjilu_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
|
||||
logger.info(f"收支记录更新成功: 订单{order.dingdan_id}, 金额{jine_decimal}元")
|
||||
|
||||
@@ -12181,13 +12199,15 @@ class KaohePayView(APIView):
|
||||
logger.info(f"生成订单ID: {dingdanid}")
|
||||
|
||||
# 8. 创建支付订单(Czjilu)
|
||||
from jituan.services.club_write import resolve_club_id_for_write
|
||||
order = Czjilu.query.create(
|
||||
dingdan_id=dingdanid,
|
||||
zhuangtai=9, # 未支付
|
||||
yonghuid=user.UserUID,
|
||||
jine=float(fee),
|
||||
leixing=5, # 5-考核支付
|
||||
shuoming=settings.KAOHE_PAY_DESCRIPTION
|
||||
shuoming=settings.KAOHE_PAY_DESCRIPTION,
|
||||
club_id=resolve_club_id_for_write(request, user),
|
||||
)
|
||||
logger.info(f"创建支付订单成功: {dingdanid}")
|
||||
|
||||
@@ -12249,9 +12269,12 @@ class KaohePayView(APIView):
|
||||
|
||||
def generate_wechat_pay_params(self, dingdanid, jine, openid, attach, pay_type):
|
||||
"""生成微信JSAPI支付参数"""
|
||||
APPID = settings.WEIXIN_APPID
|
||||
MCHID = settings.WEIXIN_MCHID
|
||||
KEY = settings.WEIXIN_SHANGHUMIYAO
|
||||
from jituan.services.club_write import resolve_club_id_for_write
|
||||
from jituan.services.wechat_pay import get_wechat_v2_config
|
||||
pay_cfg = get_wechat_v2_config(resolve_club_id_for_write(self.request, request.user))
|
||||
APPID = pay_cfg['appid']
|
||||
MCHID = pay_cfg['mch_id']
|
||||
KEY = pay_cfg['key']
|
||||
|
||||
if pay_type == 'kaohe':
|
||||
PAY_DESCRIPTION = settings.KAOHE_PAY_DESCRIPTION
|
||||
@@ -12441,7 +12464,9 @@ class KaohePayCallbackView(View):
|
||||
return self.wechat_response('FAIL', '支付失败')
|
||||
|
||||
# 验证签名
|
||||
if not self.verify_signature(request_body):
|
||||
from jituan.services.wechat_pay import club_id_from_czjilu, verify_wechat_v2_signature
|
||||
notify_club = club_id_from_czjilu(out_trade_no)
|
||||
if not verify_wechat_v2_signature(request_body, notify_club):
|
||||
logger.error(f"签名验证失败,订单号: {out_trade_no}")
|
||||
return self.wechat_response('FAIL', '签名验证失败')
|
||||
logger.info(f"签名验证成功,订单号: {out_trade_no}")
|
||||
@@ -12513,24 +12538,11 @@ class KaohePayCallbackView(View):
|
||||
# 更新收支记录
|
||||
try:
|
||||
jine_decimal = Decimal(str(order.jine))
|
||||
update_daily_income(jine_decimal)
|
||||
update_daily_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
logger.info(f"更新每日收入成功: {jine_decimal}元")
|
||||
|
||||
szjilu, created = Szjilu.query.get_or_create(
|
||||
id=1,
|
||||
defaults={
|
||||
'TotalIncome': Decimal('0.00'),
|
||||
'TotalFlow': Decimal('0.00'),
|
||||
'TotalExpense': Decimal('0.00'),
|
||||
'DailyExpense': Decimal('0.00'),
|
||||
'DailyFlow': Decimal('0.00'),
|
||||
}
|
||||
)
|
||||
szjilu.TotalIncome += jine_decimal
|
||||
szjilu.TotalFlow += jine_decimal
|
||||
szjilu.DailyFlow += jine_decimal
|
||||
szjilu.save()
|
||||
logger.info(f"更新收支记录成功: zongsy={szjilu.TotalIncome}")
|
||||
from jituan.services.szjilu_accounting import apply_szjilu_income
|
||||
apply_szjilu_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
logger.info(f"更新收支记录成功")
|
||||
except Exception as e:
|
||||
logger.error(f"更新收支记录失败: {str(e)}", exc_info=True)
|
||||
|
||||
@@ -12709,30 +12721,11 @@ class TixianAssetView(APIView):
|
||||
except ObjectDoesNotExist:
|
||||
pass
|
||||
|
||||
# ------------------- 费率查询(从 CommissionRate 获取) -------------------
|
||||
# 打手提现费率 (类型 '5')
|
||||
lilu_obj = CommissionRate.query.filter(Platform='5').first()
|
||||
data['dashou_rate'] = float(lilu_obj.Rate) if lilu_obj and lilu_obj.Rate is not None else 0.00
|
||||
from jituan.services.club_user import get_user_club_id
|
||||
from jituan.services.withdraw_config import build_tixian_asset_rates
|
||||
|
||||
# 打手保证金提现费率 (类型 '11')
|
||||
lilu_obj = CommissionRate.query.filter(Platform='11').first()
|
||||
data['dashou_yajin_rate'] = float(lilu_obj.Rate) if lilu_obj and lilu_obj.Rate is not None else 0.00
|
||||
|
||||
# 商家提现费率 (类型 '10')
|
||||
lilu_obj = CommissionRate.query.filter(Platform='10').first()
|
||||
data['shangjia_rate'] = float(lilu_obj.Rate) if lilu_obj and lilu_obj.Rate is not None else 0.00
|
||||
|
||||
# 管事提现费率 (类型 '6')
|
||||
lilu_obj = CommissionRate.query.filter(Platform='6').first()
|
||||
data['guanshi_rate'] = float(lilu_obj.Rate) if lilu_obj and lilu_obj.Rate is not None else 0.00
|
||||
|
||||
# 组长提现费率 (类型 '8')
|
||||
lilu_obj = CommissionRate.query.filter(Platform='8').first()
|
||||
data['zuzhang_rate'] = float(lilu_obj.Rate) if lilu_obj and lilu_obj.Rate is not None else 0.00
|
||||
|
||||
# 审核官(考核官)提现费率 (类型 '9')
|
||||
lilu_obj = CommissionRate.query.filter(Platform='9').first()
|
||||
data['kaoheguan_rate'] = float(lilu_obj.Rate) if lilu_obj and lilu_obj.Rate is not None else 0.00
|
||||
club_id = get_user_club_id(user)
|
||||
data.update(build_tixian_asset_rates(club_id))
|
||||
|
||||
return Response({
|
||||
'code': 200,
|
||||
@@ -12861,8 +12854,10 @@ class TixianCallbackV3View(APIView):
|
||||
headers = request.headers
|
||||
body = request.body.decode('utf-8')
|
||||
|
||||
# 1. 验证签名
|
||||
if not verify_wechat_sign(headers, body):
|
||||
# 1. 验证签名(多商户依次验签)
|
||||
from utils.wechat_v3 import resolve_callback_club_id, decrypt_callback_ciphertext
|
||||
callback_club_id = resolve_callback_club_id(headers, body)
|
||||
if not callback_club_id:
|
||||
return Response({'code': 'FAIL', 'message': '签名验证失败'}, status=status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
# 2. 解密数据
|
||||
@@ -12878,7 +12873,7 @@ class TixianCallbackV3View(APIView):
|
||||
if not nonce or not ciphertext:
|
||||
return Response({'code': 'FAIL', 'message': '解密字段缺失'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
plaintext = decrypt_callback_ciphertext(associated_data, nonce, ciphertext)
|
||||
plaintext = decrypt_callback_ciphertext(associated_data, nonce, ciphertext, club_id=callback_club_id)
|
||||
callback_data = json.loads(plaintext)
|
||||
except Exception as e:
|
||||
logger.error(f"回调解密失败: {str(e)}", exc_info=True)
|
||||
|
||||
Reference in New Issue
Block a user