Files
ycc-proxy-server/app/main/api/internal/logic/pay/alipaycallbacklogic.go
2025-12-09 18:55:28 +08:00

339 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package pay
import (
"context"
"net/http"
"strings"
"time"
"ycc-server/pkg/lzkit/lzUtils"
"github.com/pkg/errors"
"github.com/smartwalle/alipay/v3"
"ycc-server/app/main/api/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
type AlipayCallbackLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAlipayCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AlipayCallbackLogic {
return &AlipayCallbackLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AlipayCallbackLogic) AlipayCallback(w http.ResponseWriter, r *http.Request) error {
notification, err := l.svcCtx.AlipayService.HandleAliPaymentNotification(r)
if err != nil {
logx.Errorf("支付宝支付回调,%v", err)
return nil
}
// 根据订单号前缀判断订单类型
orderNo := notification.OutTradeNo
if strings.HasPrefix(orderNo, "Q_") {
// 查询订单处理
return l.handleQueryOrderPayment(w, notification)
} else if strings.HasPrefix(orderNo, "U_") {
// 代理升级订单处理
return l.handleAgentUpgradeOrderPayment(w, notification)
} else if strings.HasPrefix(orderNo, "A_") {
// 旧系统会员充值订单(已废弃,新系统使用升级功能)
// return l.handleAgentVipOrderPayment(w, notification)
// 直接返回成功,避免旧订单影响
alipay.ACKNotification(w)
return nil
} else {
// 兼容旧订单,假设没有前缀的是查询订单
return l.handleQueryOrderPayment(w, notification)
}
}
// 处理查询订单支付
func (l *AlipayCallbackLogic) handleQueryOrderPayment(w http.ResponseWriter, notification *alipay.Notification) error {
order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, notification.OutTradeNo)
if findOrderErr != nil {
logx.Errorf("支付宝支付回调,查找订单失败: %+v", findOrderErr)
return nil
}
if order.Status != "pending" {
alipay.ACKNotification(w)
return nil
}
user, err := l.svcCtx.UserModel.FindOne(l.ctx, order.UserId)
if err != nil {
logx.Errorf("支付宝支付回调,查找用户失败: %+v", err)
return nil
}
amount := lzUtils.ToAlipayAmount(order.Amount)
if user.Inside != 1 {
// 确保订单金额和状态正确,防止重复更新
if amount != notification.TotalAmount {
logx.Errorf("支付宝支付回调,金额不一致")
return nil
}
}
switch notification.TradeStatus {
case alipay.TradeStatusSuccess:
order.Status = "paid"
order.PayTime = lzUtils.TimeToNullTime(time.Now())
default:
return nil
}
order.PlatformOrderId = lzUtils.StringToNullString(notification.TradeNo)
if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil {
logx.Errorf("支付宝支付回调,修改订单信息失败: %+v", updateErr)
return nil
}
if order.Status == "paid" {
if asyncErr := l.svcCtx.AsynqService.SendQueryTask(order.Id); asyncErr != nil {
logx.Errorf("异步任务调度失败: %v", asyncErr)
return asyncErr
}
}
alipay.ACKNotification(w)
return nil
}
// 处理代理升级订单支付
func (l *AlipayCallbackLogic) handleAgentUpgradeOrderPayment(w http.ResponseWriter, notification *alipay.Notification) error {
orderNo := notification.OutTradeNo
// 1. 查找订单
order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, orderNo)
if findOrderErr != nil {
logx.Errorf("支付宝支付回调,查找升级订单失败: %+v", findOrderErr)
alipay.ACKNotification(w)
return nil
}
// 2. 验证金额
amount := lzUtils.ToAlipayAmount(order.Amount)
user, err := l.svcCtx.UserModel.FindOne(l.ctx, order.UserId)
if err == nil && user.Inside != 1 {
if amount != notification.TotalAmount {
logx.Errorf("支付宝支付回调,升级订单金额不一致,订单号: %s", orderNo)
alipay.ACKNotification(w)
return nil
}
}
// 3. 检查订单状态
if order.Status != "pending" {
alipay.ACKNotification(w)
return nil
}
// 4. 查找升级记录
upgradeRecords, findUpgradeErr := l.svcCtx.AgentUpgradeModel.FindAll(l.ctx, l.svcCtx.AgentUpgradeModel.SelectBuilder().
Where("order_no = ?", orderNo).
Limit(1), "")
if findUpgradeErr != nil || len(upgradeRecords) == 0 {
logx.Errorf("支付宝支付回调,查找升级记录失败,订单号: %s, 错误: %+v", orderNo, findUpgradeErr)
alipay.ACKNotification(w)
return nil
}
upgradeRecord := upgradeRecords[0]
// 5. 检查升级记录状态
if upgradeRecord.Status != 1 {
// 升级记录状态不是待支付,直接返回成功
alipay.ACKNotification(w)
return nil
}
// 6. 处理支付状态
switch notification.TradeStatus {
case alipay.TradeStatusSuccess:
order.Status = "paid"
order.PayTime = lzUtils.TimeToNullTime(time.Now())
order.PlatformOrderId = lzUtils.StringToNullString(notification.TradeNo)
case alipay.TradeStatusClosed:
order.Status = "closed"
order.CloseTime = lzUtils.TimeToNullTime(time.Now())
default:
alipay.ACKNotification(w)
return nil
}
// 7. 更新订单状态
if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil {
logx.Errorf("支付宝支付回调,更新升级订单状态失败: %+v", updateErr)
alipay.ACKNotification(w)
return nil
}
// 8. 如果支付成功,执行升级操作
if order.Status == "paid" {
err := l.svcCtx.AgentWalletModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
// 8.1 执行升级操作
if err := l.svcCtx.AgentService.ProcessUpgrade(transCtx, upgradeRecord.AgentId, upgradeRecord.ToLevel, upgradeRecord.UpgradeType, upgradeRecord.UpgradeFee, upgradeRecord.RebateAmount, orderNo, ""); err != nil {
return errors.Wrapf(err, "执行升级操作失败")
}
// 8.2 更新升级记录状态为已完成
upgradeRecord.Status = 2 // 已完成status: 1=待处理2=已完成3=已失败)
upgradeRecord.Remark = lzUtils.StringToNullString("支付成功,升级完成")
if updateErr := l.svcCtx.AgentUpgradeModel.UpdateWithVersion(transCtx, session, upgradeRecord); updateErr != nil {
return errors.Wrapf(updateErr, "更新升级记录状态失败")
}
return nil
})
if err != nil {
logx.Errorf("支付宝支付回调,处理升级订单失败,订单号: %s, 错误: %+v", orderNo, err)
// 即使升级失败,也返回成功给支付宝,避免重复回调
} else {
logx.Infof("支付宝支付回调,代理升级成功,订单号: %s, 代理ID: %d, 从等级 %d 升级到等级 %d", orderNo, upgradeRecord.AgentId, upgradeRecord.FromLevel, upgradeRecord.ToLevel)
}
}
alipay.ACKNotification(w)
return nil
}
// 处理代理会员订单支付(已废弃,新系统使用升级功能)
/*
func (l *AlipayCallbackLogic) handleAgentVipOrderPayment(w http.ResponseWriter, notification *alipay.Notification) error {
agentOrder, findAgentOrderErr := l.svcCtx.AgentMembershipRechargeOrderModel.FindOneByOrderNo(l.ctx, notification.OutTradeNo)
if findAgentOrderErr != nil {
logx.Errorf("支付宝支付回调,查找代理会员订单失败: %+v", findAgentOrderErr)
return nil
}
if agentOrder.Status != "pending" {
alipay.ACKNotification(w)
return nil
}
user, err := l.svcCtx.UserModel.FindOne(l.ctx, agentOrder.UserId)
if err != nil {
logx.Errorf("支付宝支付回调,查找用户失败: %+v", err)
return nil
}
amount := lzUtils.ToAlipayAmount(agentOrder.Amount)
if user.Inside != 1 {
// 确保订单金额和状态正确,防止重复更新
if amount != notification.TotalAmount {
logx.Errorf("支付宝支付回调,金额不一致")
return nil
}
}
switch notification.TradeStatus {
case alipay.TradeStatusSuccess:
agentOrder.Status = "paid"
default:
return nil
}
if agentOrder.Status == "paid" {
err = l.svcCtx.AgentModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
agentModel, err := l.svcCtx.AgentModel.FindOne(transCtx, agentOrder.AgentId)
if err != nil {
return fmt.Errorf("查找代理信息失败: %+v", err)
}
agentOrder.PlatformOrderId = lzUtils.StringToNullString(notification.TradeNo)
if updateErr := l.svcCtx.AgentMembershipRechargeOrderModel.UpdateWithVersion(l.ctx, nil, agentOrder); updateErr != nil {
return fmt.Errorf("修改代理会员订单信息失败: %+v", updateErr)
}
// 记录旧等级,用于判断是否为升级
oldLevel := agentModel.LevelName
// 设置会员等级
agentModel.LevelName = agentOrder.LevelName
// 延长会员时间
// 检查是否是有效期内续费(不发放奖励)还是重新激活(发放奖励)
isValidRenewal := oldLevel == agentOrder.LevelName && agentModel.MembershipExpiryTime.Valid && agentModel.MembershipExpiryTime.Time.After(time.Now())
if isValidRenewal {
logx.Infof("代理会员有效期内续费成功会员ID%d等级%s", agentModel.Id, agentModel.LevelName)
} else {
logx.Infof("代理会员新购、升级或重新激活成功会员ID%d等级%s", agentModel.Id, agentModel.LevelName)
}
agentModel.MembershipExpiryTime = lzUtils.RenewMembership(agentModel.MembershipExpiryTime)
if updateErr := l.svcCtx.AgentModel.UpdateWithVersion(l.ctx, nil, agentModel); updateErr != nil {
return fmt.Errorf("修改代理信息失败: %+v", updateErr)
}
// 如果不是有效期内续费,给上级代理发放升级奖励
if !isValidRenewal && (agentOrder.LevelName == model.AgentLeveNameVIP || agentOrder.LevelName == model.AgentLeveNameSVIP) {
// 验证升级路径的有效性
if oldLevel != agentOrder.LevelName {
upgradeRewardErr := l.svcCtx.AgentService.GiveUpgradeReward(transCtx, agentModel.Id, oldLevel, agentOrder.LevelName, session)
if upgradeRewardErr != nil {
logx.Errorf("发放升级奖励失败代理ID%d旧等级%s新等级%s错误%+v", agentModel.Id, oldLevel, agentOrder.LevelName, upgradeRewardErr)
// 升级奖励失败不影响主流程,只记录日志
} else {
logx.Infof("发放升级奖励成功代理ID%d旧等级%s新等级%s", agentModel.Id, oldLevel, agentOrder.LevelName)
}
}
}
return nil
})
if err != nil {
logx.Errorf("支付宝支付回调,处理代理会员订单失败: %+v", err)
refundErr := l.handleRefund(agentOrder)
if refundErr != nil {
logx.Errorf("支付宝支付回调,退款失败: %+v", refundErr)
}
return nil
}
}
alipay.ACKNotification(w)
return nil
} */
/* func (l *AlipayCallbackLogic) handleRefund(order *model.AgentMembershipRechargeOrder) error {
ctx := context.Background()
// 退款
if order.PaymentMethod == "wechat" {
refundErr := l.svcCtx.WechatPayService.WeChatRefund(ctx, order.OrderNo, order.Amount, order.Amount)
if refundErr != nil {
return refundErr
}
} else {
refund, refundErr := l.svcCtx.AlipayService.AliRefund(ctx, order.OrderNo, order.Amount)
if refundErr != nil {
return refundErr
}
if refund.IsSuccess() {
logx.Errorf("支付宝退款成功, orderID: %d", order.Id)
// 更新订单状态为退款
order.Status = "refunded"
updateOrderErr := l.svcCtx.AgentMembershipRechargeOrderModel.UpdateWithVersion(ctx, nil, order)
if updateOrderErr != nil {
logx.Errorf("更新订单状态失败订单ID: %d, 错误: %v", order.Id, updateOrderErr)
return fmt.Errorf("更新订单状态失败: %v", updateOrderErr)
}
return nil
} else {
logx.Errorf("支付宝退款失败:%v", refundErr)
return refundErr
}
// 直接成功
}
return nil
} */