qnc-server-tob/app/main/api/internal/logic/pay/wechatpaycallbacklogic.go
liangzai 89bade9232 1、新增后台面板
2、查询页改三要素
3、佣金冻结
2025-06-09 12:30:13 +08:00

238 lines
7.4 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"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"qnc-server/app/user/cmd/api/internal/service"
"qnc-server/app/user/cmd/api/internal/types"
"qnc-server/app/user/model"
"qnc-server/pkg/lzkit/crypto"
"qnc-server/pkg/lzkit/lzUtils"
"strings"
"time"
"qnc-server/app/user/cmd/api/internal/svc"
"github.com/wechatpay-apiv3/wechatpay-go/services/payments"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
type WechatPayCallbackLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewWechatPayCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WechatPayCallbackLogic {
return &WechatPayCallbackLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *WechatPayCallbackLogic) WechatPayCallback(w http.ResponseWriter, r *http.Request) error {
notification, err := l.svcCtx.WechatPayService.HandleWechatPayNotification(l.ctx, 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, "A_") {
// 代理会员订单处理
return l.handleAgentVipOrderPayment(w, notification)
} else {
// 兼容旧订单,假设没有前缀的是查询订单
return l.handleQueryOrderPayment(w, notification)
}
}
// 处理查询订单支付
func (l *WechatPayCallbackLogic) handleQueryOrderPayment(w http.ResponseWriter, notification *payments.Transaction) error {
order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, *notification.OutTradeNo)
if findOrderErr != nil {
logx.Errorf("微信支付回调,查找订单信息失败: %+v", findOrderErr)
return nil
}
amount := lzUtils.ToWechatAmount(order.Amount)
if amount != *notification.Amount.Total {
logx.Errorf("微信支付回调,金额不一致")
return nil
}
if order.Status != "pending" {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("success"))
return nil
}
switch *notification.TradeState {
case service.TradeStateSuccess:
order.Status = "paid"
order.PayTime = lzUtils.TimeToNullTime(time.Now())
case service.TradeStateClosed:
order.Status = "closed"
order.CloseTime = lzUtils.TimeToNullTime(time.Now())
case service.TradeStateRevoked:
order.Status = "failed"
default:
return nil
}
order.PlatformOrderId = lzUtils.StringToNullString(*notification.TransactionId)
if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil {
logx.Errorf("微信支付回调,更新订单失败%+v", updateErr)
return nil
}
if order.Status == "paid" {
redisKey := fmt.Sprintf(types.QueryCacheKey, order.UserId, order.OrderNo)
cache, cacheErr := l.svcCtx.Redis.Get(redisKey)
if cacheErr != nil {
return fmt.Errorf("获取缓存内容失败: %+v", cacheErr)
}
var data types.QueryCacheLoad
err := json.Unmarshal([]byte(cache), &data)
if err != nil {
return fmt.Errorf("解析缓存内容失败: %+v", err)
}
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return fmt.Errorf("获取AES密钥失败: %+v", decodeErr)
}
decryptData, aesdecryptErr := crypto.AesDecrypt(data.Params, key)
if aesdecryptErr != nil {
return fmt.Errorf("解密参数失败: %+v", aesdecryptErr)
}
var paramsMap map[string]string
if err := json.Unmarshal([]byte(decryptData), &paramsMap); err != nil {
return fmt.Errorf("解析参数失败: %+v", err)
}
encryptName, err := crypto.AesEncrypt([]byte(paramsMap["name"]), key)
if err != nil {
return fmt.Errorf("生成订单, 加密姓名失败: %+v", err)
}
encryptIdcard, err := crypto.AesEncrypt([]byte(paramsMap["id_card"]), key)
if err != nil {
return fmt.Errorf("生成订单, 加密身份证号失败: %+v", err)
}
_, err = l.svcCtx.AuthorizationModel.Insert(l.ctx, nil, &model.Authorization{
OrderId: order.Id,
UserId: order.UserId,
TargetName: encryptName,
TargetIdcard: encryptIdcard,
Status: model.AuthorizationStatusPending,
})
if err != nil {
logx.Errorf("微信支付回调,插入授权信息失败: %+v", err)
return fmt.Errorf("插入授权信息失败: %+v", err)
}
}
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("success"))
return nil
}
// 处理代理会员订单支付
func (l *WechatPayCallbackLogic) handleAgentVipOrderPayment(w http.ResponseWriter, notification *payments.Transaction) error {
agentOrder, findAgentOrderErr := l.svcCtx.AgentMembershipRechargeOrderModel.FindOneByOrderNo(l.ctx, *notification.OutTradeNo)
if findAgentOrderErr != nil {
logx.Errorf("微信支付回调,查找代理会员订单失败: %+v", findAgentOrderErr)
return nil
}
if agentOrder.Status != "pending" {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("success"))
return nil
}
user, err := l.svcCtx.UserModel.FindOne(l.ctx, agentOrder.UserId)
if err != nil {
logx.Errorf("微信支付回调,查找用户失败: %+v", err)
return nil
}
amount := lzUtils.ToWechatAmount(agentOrder.Amount)
if user.Inside != 1 {
if amount != *notification.Amount.Total {
logx.Errorf("微信支付回调,金额不一致")
return nil
}
}
switch *notification.TradeState {
case service.TradeStateSuccess:
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.TransactionId)
if updateErr := l.svcCtx.AgentMembershipRechargeOrderModel.UpdateWithVersion(l.ctx, nil, agentOrder); updateErr != nil {
return fmt.Errorf("修改代理会员订单信息失败: %+v", updateErr)
}
// 设置会员等级
agentModel.LevelName = agentOrder.LevelName
// 延长会员时间
isRenewal := agentModel.LevelName == agentOrder.LevelName && agentModel.MembershipExpiryTime.Valid
if isRenewal {
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)
}
return nil
})
if err != nil {
logx.Errorf("微信支付回调,处理代理会员订单失败: %+v", err)
refundErr := l.handleRefund(agentOrder)
if refundErr != nil {
logx.Errorf("微信支付回调,退款失败: %+v", refundErr)
}
return nil
}
}
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("success"))
return nil
}
func (l *WechatPayCallbackLogic) 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
}
}
return nil
}