```
feat(payment): 添加邀请奖励功能并重构订单支付处理逻辑 - 引入InviteReward模型用于记录邀请奖励 - 新增_process_success_order内部函数统一处理订单成功逻辑 - 实现邀请奖励机制:被邀请人前3次充值时,邀请人获得10%积分奖励 - 在支付回调、主动查询和异步通知中统一调用新的处理函数 - 改进代码结构,消除重复的订单处理逻辑 ```
This commit is contained in:
parent
0164140c39
commit
2ea495721c
@ -1,6 +1,6 @@
|
||||
from flask import Blueprint, request, redirect, url_for, session, jsonify, render_template
|
||||
from extensions import db, redis_client
|
||||
from models import Order, User, to_bj_time, get_bj_now
|
||||
from models import Order, User, InviteReward, to_bj_time, get_bj_now
|
||||
from services.alipay_service import AlipayService
|
||||
from services.logger import system_logger
|
||||
import uuid
|
||||
@ -16,6 +16,57 @@ POINTS_PACKAGES = {
|
||||
'5000': {'points': 5000, 'amount': 500.00},
|
||||
}
|
||||
|
||||
def _process_success_order(order, trade_no):
|
||||
"""内部处理订单成功逻辑 (需在锁内调用,不包含 commit)"""
|
||||
if order.status == 'PAID':
|
||||
return False
|
||||
|
||||
order.status = 'PAID'
|
||||
order.trade_no = trade_no
|
||||
order.paid_at = get_bj_now()
|
||||
|
||||
# 增加用户积分
|
||||
user = db.session.get(User, order.user_id)
|
||||
if user:
|
||||
user.points += order.points
|
||||
system_logger.info(f"订单支付成功", order_id=order.out_trade_no, points=order.points, user_id=user.id)
|
||||
|
||||
# ========== 邀请奖励逻辑 ==========
|
||||
if user.invited_by:
|
||||
# 统计该被邀请人之前已经完成多少次充值(不含本次)
|
||||
paid_count = Order.query.filter(
|
||||
Order.user_id == user.id,
|
||||
Order.status == 'PAID',
|
||||
Order.id != order.id
|
||||
).count()
|
||||
|
||||
# 只有前3次充值才有奖励
|
||||
if paid_count < 3:
|
||||
inviter = db.session.get(User, user.invited_by)
|
||||
if inviter:
|
||||
# 计算10%奖励积分(四舍五入)
|
||||
reward_points = round(order.points * 0.1)
|
||||
if reward_points > 0:
|
||||
inviter.points += reward_points
|
||||
|
||||
# 记录邀请奖励
|
||||
invite_reward = InviteReward(
|
||||
inviter_id=inviter.id,
|
||||
invitee_id=user.id,
|
||||
order_id=order.id,
|
||||
reward_points=reward_points,
|
||||
recharge_count=paid_count + 1
|
||||
)
|
||||
db.session.add(invite_reward)
|
||||
system_logger.info(
|
||||
f"邀请奖励发放成功",
|
||||
inviter_id=inviter.id,
|
||||
invitee_id=user.id,
|
||||
reward_points=reward_points,
|
||||
recharge_count=paid_count + 1
|
||||
)
|
||||
return True
|
||||
|
||||
@payment_bp.route('/create', methods=['POST'])
|
||||
def create_payment():
|
||||
if 'user_id' not in session:
|
||||
@ -88,17 +139,8 @@ def payment_return():
|
||||
order = Order.query.filter_by(out_trade_no=out_trade_no).with_for_update().first()
|
||||
|
||||
# 如果订单存在且状态为PENDING,则更新为PAID
|
||||
if order and order.status == 'PENDING':
|
||||
order.status = 'PAID'
|
||||
order.trade_no = trade_no
|
||||
order.paid_at = get_bj_now()
|
||||
|
||||
# 增加用户积分
|
||||
user = db.session.get(User, order.user_id)
|
||||
if user:
|
||||
user.points += order.points
|
||||
system_logger.info(f"同步回调-订单支付成功", order_id=out_trade_no, points=order.points, user_id=user.id)
|
||||
|
||||
if order:
|
||||
_process_success_order(order, trade_no)
|
||||
db.session.commit()
|
||||
elif order:
|
||||
# 订单已经是完成状态,不做处理
|
||||
@ -216,36 +258,28 @@ def api_sync_order():
|
||||
order_locked = Order.query.filter_by(out_trade_no=out_trade_no).with_for_update().first()
|
||||
|
||||
# 二次校验状态,防止异步回调/定时任务已经处理
|
||||
if order_locked and order_locked.status == 'PENDING':
|
||||
order_locked.status = 'PAID'
|
||||
order_locked.trade_no = alipay_result.get('trade_no')
|
||||
if not order_locked.paid_at:
|
||||
order_locked.paid_at = get_bj_now()
|
||||
|
||||
# 增加用户积分
|
||||
user = db.session.get(User, order_locked.user_id)
|
||||
if user:
|
||||
user.points += order_locked.points
|
||||
system_logger.info(f"主动查询-订单支付成功", order_id=out_trade_no, points=order_locked.points, user_id=user.id)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'msg': '订单已支付,积分已增加',
|
||||
'status': 'PAID',
|
||||
'points': order_locked.points,
|
||||
'paid_at': order_locked.paid_at_bj.strftime('%Y-%m-%d %H:%M:%S')
|
||||
})
|
||||
elif order_locked and order_locked.status == 'PAID':
|
||||
# 订单已经被处理,直接返回
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'msg': '订单已支付',
|
||||
'status': 'PAID',
|
||||
'points': order_locked.points,
|
||||
'paid_at': order_locked.paid_at_bj.strftime('%Y-%m-%d %H:%M:%S') if order_locked.paid_at else None
|
||||
})
|
||||
# 二次校验状态,防止异步回调/定时任务已经处理
|
||||
if order_locked:
|
||||
processed = _process_success_order(order_locked, alipay_result.get('trade_no'))
|
||||
if processed:
|
||||
db.session.commit()
|
||||
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'msg': '订单已支付,积分已增加',
|
||||
'status': 'PAID',
|
||||
'points': order_locked.points,
|
||||
'paid_at': order_locked.paid_at_bj.strftime('%Y-%m-%d %H:%M:%S')
|
||||
})
|
||||
else:
|
||||
# 订单已经是完成状态,不做处理
|
||||
return jsonify({
|
||||
'code': 200,
|
||||
'msg': '订单已支付',
|
||||
'status': 'PAID',
|
||||
'points': order_locked.points,
|
||||
'paid_at': order_locked.paid_at_bj.strftime('%Y-%m-%d %H:%M:%S') if order_locked.paid_at else None
|
||||
})
|
||||
except Exception as e:
|
||||
if "LockError" in str(e) or "BlockingIOError" in str(e):
|
||||
# 如果获取锁失败,可能是因为正在处理中,返回成功状态(前端会重试或刷新)
|
||||
@ -301,20 +335,10 @@ def payment_notify():
|
||||
lock_key = f"lock:order:{out_trade_no}"
|
||||
with redis_client.lock(lock_key, timeout=10, blocking_timeout=3):
|
||||
order = Order.query.filter_by(out_trade_no=out_trade_no).with_for_update().first()
|
||||
if order and order.status == 'PENDING':
|
||||
order.status = 'PAID'
|
||||
order.trade_no = trade_no
|
||||
order.paid_at = get_bj_now()
|
||||
|
||||
user = db.session.get(User, order.user_id)
|
||||
if user:
|
||||
user.points += order.points
|
||||
system_logger.info(f"订单支付成功", order_id=out_trade_no, points=order.points, user_id=user.id)
|
||||
|
||||
if order:
|
||||
_process_success_order(order, trade_no)
|
||||
db.session.commit()
|
||||
return "success"
|
||||
elif order:
|
||||
return "success"
|
||||
else:
|
||||
return "fail"
|
||||
except Exception as e:
|
||||
@ -327,59 +351,12 @@ def payment_notify():
|
||||
return "fail"
|
||||
raise e
|
||||
order = Order.query.filter_by(out_trade_no=out_trade_no).first()
|
||||
if order and order.status == 'PENDING':
|
||||
order.status = 'PAID'
|
||||
order.trade_no = trade_no
|
||||
order.paid_at = get_bj_now()
|
||||
|
||||
user = db.session.get(User, order.user_id)
|
||||
if user:
|
||||
user.points += order.points
|
||||
system_logger.info(f"订单支付成功", order_id=out_trade_no, points=order.points, user_id=user.id)
|
||||
|
||||
# ========== 邀请奖励逻辑 ==========
|
||||
if user.invited_by:
|
||||
from models import InviteReward
|
||||
# 统计该被邀请人之前已经完成多少次充值(不含本次)
|
||||
paid_count = Order.query.filter(
|
||||
Order.user_id == user.id,
|
||||
Order.status == 'PAID',
|
||||
Order.id != order.id # 排除本次订单
|
||||
).count()
|
||||
|
||||
# 只有前3次充值才有奖励(paid_count 是之前的次数,0/1/2 表示这是第1/2/3次)
|
||||
if paid_count < 3:
|
||||
inviter = db.session.get(User, user.invited_by)
|
||||
if inviter:
|
||||
# 计算10%奖励积分(四舍五入)
|
||||
reward_points = round(order.points * 0.1)
|
||||
if reward_points > 0:
|
||||
inviter.points += reward_points
|
||||
|
||||
# 记录邀请奖励
|
||||
invite_reward = InviteReward(
|
||||
inviter_id=inviter.id,
|
||||
invitee_id=user.id,
|
||||
order_id=order.id,
|
||||
reward_points=reward_points,
|
||||
recharge_count=paid_count + 1 # 第几次充值
|
||||
)
|
||||
db.session.add(invite_reward)
|
||||
system_logger.info(
|
||||
f"邀请奖励发放成功",
|
||||
inviter_id=inviter.id,
|
||||
invitee_id=user.id,
|
||||
reward_points=reward_points,
|
||||
recharge_count=paid_count + 1
|
||||
)
|
||||
# ========== 邀请奖励逻辑结束 ==========
|
||||
|
||||
db.session.commit()
|
||||
return "success"
|
||||
elif order:
|
||||
return "success"
|
||||
if order:
|
||||
_process_success_order(order, trade_no)
|
||||
db.session.commit()
|
||||
return "success"
|
||||
else:
|
||||
return "fail"
|
||||
return "fail"
|
||||
else:
|
||||
return "fail"
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user