v2.0
This commit is contained in:
		@@ -2,17 +2,17 @@ package agent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
	"tydata-server/app/user/model"
 | 
			
		||||
	"tydata-server/common/ctxdata"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
	"tydata-server/pkg/lzkit/crypto"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/stores/sqlx"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
	"tydata-server/app/user/model"
 | 
			
		||||
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/logx"
 | 
			
		||||
)
 | 
			
		||||
@@ -30,27 +30,16 @@ func NewActivateAgentMembershipLogic(ctx context.Context, svcCtx *svc.ServiceCon
 | 
			
		||||
		svcCtx: svcCtx,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *ActivateAgentMembershipLogic) ActivateAgentMembership(req *types.AgentActivateMembershipReq) (resp *types.AgentActivateMembershipResp, err error) {
 | 
			
		||||
	//userID, err := ctxdata.GetUidFromCtx(l.ctx)
 | 
			
		||||
	//if err != nil {
 | 
			
		||||
	//	return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户ID失败: %v", err)
 | 
			
		||||
	//}
 | 
			
		||||
	secretKey := l.svcCtx.Config.Encrypt.SecretKey
 | 
			
		||||
	encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
 | 
			
		||||
	userID, err := ctxdata.GetUidFromCtx(l.ctx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "加密手机号失败: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	userModel, err := l.svcCtx.UserModel.FindOneByMobile(l.ctx, encryptedMobile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败: %v", err)
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户ID失败: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	// 查询用户代理信息
 | 
			
		||||
	agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userModel.Id)
 | 
			
		||||
	if err != nil && err != sql.ErrNoRows {
 | 
			
		||||
	agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 定义等级顺序映射
 | 
			
		||||
	levelOrder := map[string]int{
 | 
			
		||||
		"":                        1,
 | 
			
		||||
@@ -77,52 +66,20 @@ func (l *ActivateAgentMembershipLogic) ActivateAgentMembership(req *types.AgentA
 | 
			
		||||
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR),
 | 
			
		||||
				"禁止降级操作(当前等级:%s,请求等级:%s)", agentModel.LevelName, req.Type)
 | 
			
		||||
		}
 | 
			
		||||
		// 同等级视为续费,允许操作
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = l.svcCtx.AgentModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
 | 
			
		||||
		agentModel.LevelName = req.Type
 | 
			
		||||
		agentModel.MembershipExpiryTime = RenewMembership(agentModel.MembershipExpiryTime)
 | 
			
		||||
		transErr := l.svcCtx.AgentModel.UpdateWithVersion(transCtx, session, agentModel)
 | 
			
		||||
		if transErr != nil {
 | 
			
		||||
			return transErr
 | 
			
		||||
		}
 | 
			
		||||
		agentMembershipRechargeOrder := model.AgentMembershipRechargeOrder{
 | 
			
		||||
			AgentId:       agentModel.Id,
 | 
			
		||||
			UserId:        userModel.Id,
 | 
			
		||||
			LevelName:     req.Type,
 | 
			
		||||
			Amount:        req.Amount,
 | 
			
		||||
			PaymentMethod: req.PaymentMethod,
 | 
			
		||||
			TransactionId: req.TransactionId,
 | 
			
		||||
		}
 | 
			
		||||
		_, transErr = l.svcCtx.AgentMembershipRechargeOrderModel.Insert(transCtx, session, &agentMembershipRechargeOrder)
 | 
			
		||||
		if transErr != nil {
 | 
			
		||||
			return transErr
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	})
 | 
			
		||||
	outTradeNo := "A_" + l.svcCtx.AlipayService.GenerateOutTradeNo()
 | 
			
		||||
	redisKey := fmt.Sprintf(types.AgentVipCacheKey, userID, outTradeNo)
 | 
			
		||||
	agentVipCache := types.AgentVipCache{Type: req.Type}
 | 
			
		||||
	jsonData, err := json.Marshal(agentVipCache)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "升级代理等级失败: %s", req.Type)
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "序列化代理VIP缓存失败: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
 | 
			
		||||
	if cacheErr != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "设置缓存失败: %v", cacheErr)
 | 
			
		||||
	}
 | 
			
		||||
	return &types.AgentActivateMembershipResp{
 | 
			
		||||
		MembershipType: req.Type,
 | 
			
		||||
		ExpireTime:     agentModel.MembershipExpiryTime.Time.Format("2006-01-02 15:04:05"),
 | 
			
		||||
		Id: outTradeNo,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
func RenewMembership(expiry sql.NullTime) sql.NullTime {
 | 
			
		||||
	// 确定基准时间
 | 
			
		||||
	var baseTime time.Time
 | 
			
		||||
	if expiry.Valid {
 | 
			
		||||
		baseTime = expiry.Time
 | 
			
		||||
	} else {
 | 
			
		||||
		baseTime = time.Now()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 增加一年(自动处理闰年)
 | 
			
		||||
	newTime := baseTime.AddDate(1, 0, 0)
 | 
			
		||||
 | 
			
		||||
	// 返回始终有效的 NullTime
 | 
			
		||||
	return sql.NullTime{
 | 
			
		||||
		Time:  newTime,
 | 
			
		||||
		Valid: true,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -79,7 +79,7 @@ func (l *AgentWithdrawalLogic) AgentWithdrawal(req *types.WithdrawalReq) (*types
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// 生成交易号
 | 
			
		||||
		outBizNo = l.svcCtx.AlipayService.GenerateOutTradeNo()
 | 
			
		||||
		outBizNo = "W_" + l.svcCtx.AlipayService.GenerateOutTradeNo()
 | 
			
		||||
 | 
			
		||||
		// 创建提现记录(初始状态为处理中)
 | 
			
		||||
		if err = l.createWithdrawalRecord(session, agentModel.Id, req, outBizNo); err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ package agent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
	"tydata-server/app/user/model"
 | 
			
		||||
@@ -58,15 +59,15 @@ func (l *ApplyForAgentLogic) ApplyForAgent(req *types.AgentApplyReq) (resp *type
 | 
			
		||||
	var userID int64
 | 
			
		||||
	transErr := l.svcCtx.AgentAuditModel.Trans(l.ctx, func(transCtx context.Context, session sqlx.Session) error {
 | 
			
		||||
		// 两种情况,1. 已注册账号然后申请代理  2. 未注册账号申请代理
 | 
			
		||||
		user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, encryptedMobile)
 | 
			
		||||
		user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
 | 
			
		||||
		if findUserErr != nil && !errors.Is(findUserErr, model.ErrNotFound) {
 | 
			
		||||
			return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 读取数据库获取用户失败, mobile: %s, err: %+v", encryptedMobile, err)
 | 
			
		||||
		}
 | 
			
		||||
		if user == nil {
 | 
			
		||||
			user = &model.User{Mobile: encryptedMobile}
 | 
			
		||||
			if len(user.Nickname) == 0 {
 | 
			
		||||
				user.Nickname = encryptedMobile
 | 
			
		||||
			}
 | 
			
		||||
			user = &model.User{Mobile: sql.NullString{String: encryptedMobile, Valid: true}}
 | 
			
		||||
			// if len(user.Nickname) == 0 {
 | 
			
		||||
			// 	user.Nickname = encryptedMobile
 | 
			
		||||
			// }
 | 
			
		||||
			insertResult, userInsertErr := l.svcCtx.UserModel.Insert(transCtx, session, user)
 | 
			
		||||
			if userInsertErr != nil {
 | 
			
		||||
				return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 数据库插入新用户失败, mobile%s, err: %+v", encryptedMobile, err)
 | 
			
		||||
 
 | 
			
		||||
@@ -4,14 +4,15 @@ import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"github.com/Masterminds/squirrel"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"tydata-server/app/user/model"
 | 
			
		||||
	"tydata-server/common/ctxdata"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
	"tydata-server/pkg/lzkit/crypto"
 | 
			
		||||
 | 
			
		||||
	"github.com/Masterminds/squirrel"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,12 @@ package agent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"tydata-server/common/ctxdata"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"github.com/Masterminds/squirrel"
 | 
			
		||||
	"github.com/jinzhu/copier"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"tydata-server/common/ctxdata"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 
 | 
			
		||||
@@ -65,12 +65,13 @@ func (l *GetAgentInfoLogic) GetAgentInfo() (resp *types.AgentInfoResp, err error
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理信息, 解密手机号失败: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	return &types.AgentInfoResp{
 | 
			
		||||
		AgentID:  agent.Id,
 | 
			
		||||
		Level:    agent.LevelName,
 | 
			
		||||
		IsAgent:  true,
 | 
			
		||||
		Status:   1,
 | 
			
		||||
		Region:   agent.Region,
 | 
			
		||||
		Mobile:   agent.Mobile,
 | 
			
		||||
		WechatID: lzUtils.NullStringToString(agent.WechatId),
 | 
			
		||||
		AgentID:    agent.Id,
 | 
			
		||||
		Level:      agent.LevelName,
 | 
			
		||||
		IsAgent:    true,
 | 
			
		||||
		Status:     1,
 | 
			
		||||
		Region:     agent.Region,
 | 
			
		||||
		Mobile:     agent.Mobile,
 | 
			
		||||
		ExpiryTime: agent.MembershipExpiryTime.Time.Format("2006-01-02 15:04:05"),
 | 
			
		||||
		WechatID:   lzUtils.NullStringToString(agent.WechatId),
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,13 +2,14 @@ package agent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"github.com/jinzhu/copier"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"tydata-server/app/user/model"
 | 
			
		||||
	"tydata-server/common/ctxdata"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
	"tydata-server/pkg/lzkit/lzUtils"
 | 
			
		||||
 | 
			
		||||
	"github.com/jinzhu/copier"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,13 +2,14 @@ package agent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"github.com/Masterminds/squirrel"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"time"
 | 
			
		||||
	"tydata-server/app/user/model"
 | 
			
		||||
	"tydata-server/common/ctxdata"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"github.com/Masterminds/squirrel"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,12 @@ package agent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"tydata-server/common/ctxdata"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"github.com/Masterminds/squirrel"
 | 
			
		||||
	"github.com/jinzhu/copier"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"tydata-server/common/ctxdata"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,12 @@ package agent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"tydata-server/common/ctxdata"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"github.com/Masterminds/squirrel"
 | 
			
		||||
	"github.com/jinzhu/copier"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"tydata-server/common/ctxdata"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 
 | 
			
		||||
@@ -2,9 +2,10 @@ package agent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"github.com/jinzhu/copier"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,12 @@ package notification
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"github.com/jinzhu/copier"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"time"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"github.com/jinzhu/copier"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,16 +2,20 @@ package pay
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
	"tydata-server/pkg/lzkit/lzUtils"
 | 
			
		||||
 | 
			
		||||
	"github.com/smartwalle/alipay/v3"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/model"
 | 
			
		||||
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/logx"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/stores/sqlx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type AlipayCallbackLogic struct {
 | 
			
		||||
@@ -29,31 +33,46 @@ func NewAlipayCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Al
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *AlipayCallbackLogic) AlipayCallback(w http.ResponseWriter, r *http.Request) error {
 | 
			
		||||
	env := os.Getenv("ENV")
 | 
			
		||||
	if env == "development" {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	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, "A_") {
 | 
			
		||||
		// 代理会员订单处理
 | 
			
		||||
		return l.handleAgentVipOrderPayment(w, notification)
 | 
			
		||||
	} 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)
 | 
			
		||||
 | 
			
		||||
	amount := lzUtils.ToAlipayAmount(order.Amount)
 | 
			
		||||
	if user.Inside != 1 {
 | 
			
		||||
		// 确保订单金额和状态正确,防止重复更新
 | 
			
		||||
		if amount != notification.TotalAmount {
 | 
			
		||||
@@ -62,11 +81,6 @@ func (l *AlipayCallbackLogic) AlipayCallback(w http.ResponseWriter, r *http.Requ
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if order.Status != "pending" {
 | 
			
		||||
		w.WriteHeader(http.StatusOK)
 | 
			
		||||
		_, _ = w.Write([]byte("success")) // 确保只写入一次响应
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	switch notification.TradeStatus {
 | 
			
		||||
	case alipay.TradeStatusSuccess:
 | 
			
		||||
		order.Status = "paid"
 | 
			
		||||
@@ -74,17 +88,148 @@ func (l *AlipayCallbackLogic) AlipayCallback(w http.ResponseWriter, r *http.Requ
 | 
			
		||||
	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) 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)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// 设置会员等级
 | 
			
		||||
			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 = 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
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	alipay.ACKNotification(w)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
func RenewMembership(expiry sql.NullTime) sql.NullTime {
 | 
			
		||||
	// 确定基准时间
 | 
			
		||||
	var baseTime time.Time
 | 
			
		||||
	if expiry.Valid {
 | 
			
		||||
		baseTime = expiry.Time
 | 
			
		||||
	} else {
 | 
			
		||||
		baseTime = time.Now()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 增加一年(自动处理闰年)
 | 
			
		||||
	newTime := baseTime.AddDate(1, 0, 0)
 | 
			
		||||
 | 
			
		||||
	// 返回始终有效的 NullTime
 | 
			
		||||
	return sql.NullTime{
 | 
			
		||||
		Time:  newTime,
 | 
			
		||||
		Valid: true,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,13 +2,14 @@ package pay
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"time"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
	"tydata-server/pkg/lzkit/lzUtils"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/logx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										49
									
								
								app/user/cmd/api/internal/logic/pay/paymentchecklogic.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								app/user/cmd/api/internal/logic/pay/paymentchecklogic.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
package pay
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/logx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type PaymentCheckLogic struct {
 | 
			
		||||
	logx.Logger
 | 
			
		||||
	ctx    context.Context
 | 
			
		||||
	svcCtx *svc.ServiceContext
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewPaymentCheckLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PaymentCheckLogic {
 | 
			
		||||
	return &PaymentCheckLogic{
 | 
			
		||||
		Logger: logx.WithContext(ctx),
 | 
			
		||||
		ctx:    ctx,
 | 
			
		||||
		svcCtx: svcCtx,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *PaymentCheckLogic) PaymentCheck(req *types.PaymentCheckReq) (resp *types.PaymentCheckResp, err error) {
 | 
			
		||||
	if strings.HasPrefix(req.OrderNo, "A_") {
 | 
			
		||||
		order, err := l.svcCtx.AgentMembershipRechargeOrderModel.FindOneByOrderNo(l.ctx, req.OrderNo)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询订单失败: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		return &types.PaymentCheckResp{
 | 
			
		||||
			Type:   "agent_vip",
 | 
			
		||||
			Status: order.Status,
 | 
			
		||||
		}, nil
 | 
			
		||||
	} else {
 | 
			
		||||
		order, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, req.OrderNo)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询订单失败: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		return &types.PaymentCheckResp{
 | 
			
		||||
			Type:   "query",
 | 
			
		||||
			Status: order.Status,
 | 
			
		||||
		}, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -5,7 +5,6 @@ import (
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
	"tydata-server/app/user/model"
 | 
			
		||||
@@ -14,6 +13,7 @@ import (
 | 
			
		||||
	"tydata-server/pkg/lzkit/crypto"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/redis/go-redis/v9"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/logx"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/stores/sqlx"
 | 
			
		||||
)
 | 
			
		||||
@@ -23,6 +23,11 @@ type PaymentLogic struct {
 | 
			
		||||
	ctx    context.Context
 | 
			
		||||
	svcCtx *svc.ServiceContext
 | 
			
		||||
}
 | 
			
		||||
type PaymentTypeResp struct {
 | 
			
		||||
	amount      float64
 | 
			
		||||
	outTradeNo  string
 | 
			
		||||
	description string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewPaymentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PaymentLogic {
 | 
			
		||||
	return &PaymentLogic{
 | 
			
		||||
@@ -33,20 +38,61 @@ func NewPaymentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PaymentLo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp, err error) {
 | 
			
		||||
	var paymentTypeResp *PaymentTypeResp
 | 
			
		||||
	var prepayData interface{}
 | 
			
		||||
	l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
 | 
			
		||||
		switch req.PayType {
 | 
			
		||||
		case "agent_vip":
 | 
			
		||||
			paymentTypeResp, err = l.AgentVipOrderPayment(req, session)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case "query":
 | 
			
		||||
			paymentTypeResp, err = l.QueryOrderPayment(req, session)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var createOrderErr error
 | 
			
		||||
		if req.PayMethod == "wechat" {
 | 
			
		||||
			prepayData, createOrderErr = l.svcCtx.WechatPayService.CreateWechatOrder(l.ctx, paymentTypeResp.amount, paymentTypeResp.description, paymentTypeResp.outTradeNo)
 | 
			
		||||
		} else if req.PayMethod == "alipay" {
 | 
			
		||||
			prepayData, createOrderErr = l.svcCtx.AlipayService.CreateAlipayOrder(l.ctx, paymentTypeResp.amount, paymentTypeResp.description, paymentTypeResp.outTradeNo)
 | 
			
		||||
		} else if req.PayMethod == "appleiap" {
 | 
			
		||||
			prepayData = l.svcCtx.ApplePayService.GetIappayAppID(paymentTypeResp.outTradeNo)
 | 
			
		||||
		}
 | 
			
		||||
		if createOrderErr != nil {
 | 
			
		||||
			return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 创建支付订单失败: %+v", createOrderErr)
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	switch v := prepayData.(type) {
 | 
			
		||||
	case string:
 | 
			
		||||
		// 如果 prepayData 是字符串类型,直接返回
 | 
			
		||||
		return &types.PaymentResp{PrepayId: v, OrderNo: paymentTypeResp.outTradeNo}, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return &types.PaymentResp{PrepayData: prepayData, OrderNo: paymentTypeResp.outTradeNo}, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *PaymentLogic) QueryOrderPayment(req *types.PaymentReq, session sqlx.Session) (resp *PaymentTypeResp, err error) {
 | 
			
		||||
	userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
 | 
			
		||||
	if getUidErr != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取用户信息失败, %+v", getUidErr)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	brand, ok := l.ctx.Value("brand").(string)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取平台失败, %+v", getUidErr)
 | 
			
		||||
	}
 | 
			
		||||
	outTradeNo := req.Id
 | 
			
		||||
	redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
 | 
			
		||||
	redisKey := fmt.Sprintf(types.QueryCacheKey, userID, outTradeNo)
 | 
			
		||||
	cache, cacheErr := l.svcCtx.Redis.GetCtx(l.ctx, redisKey)
 | 
			
		||||
	if cacheErr != nil {
 | 
			
		||||
		return nil, cacheErr
 | 
			
		||||
		if cacheErr == redis.Nil {
 | 
			
		||||
			return nil, errors.Wrapf(xerr.NewErrMsg("订单已过期"), "生成订单, 缓存不存在, %+v", cacheErr)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取缓存失败, %+v", cacheErr)
 | 
			
		||||
	}
 | 
			
		||||
	var data types.QueryCacheLoad
 | 
			
		||||
	err = json.Unmarshal([]byte(cache), &data)
 | 
			
		||||
@@ -59,9 +105,7 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 查找产品错误: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var prepayData interface{}
 | 
			
		||||
	var amount float64
 | 
			
		||||
	var orderAmount float64
 | 
			
		||||
	user, err := l.svcCtx.UserModel.FindOne(l.ctx, userID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取用户信息失败: %v", err)
 | 
			
		||||
@@ -73,79 +117,95 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
 | 
			
		||||
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取代理订单失败: %+v", findAgentLinkErr)
 | 
			
		||||
		}
 | 
			
		||||
		amount = agentLinkModel.Price
 | 
			
		||||
		orderAmount = agentLinkModel.Price
 | 
			
		||||
	} else {
 | 
			
		||||
		amount = product.SellPrice
 | 
			
		||||
		orderAmount = product.SellPrice
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if user.Inside == 1 {
 | 
			
		||||
		amount = 0.01
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var createOrderErr error
 | 
			
		||||
	if req.PayMethod == "wechat" {
 | 
			
		||||
		prepayData, createOrderErr = l.svcCtx.WechatPayService.CreateWechatOrder(l.ctx, amount, product.ProductName, outTradeNo)
 | 
			
		||||
	} else if req.PayMethod == "alipay" {
 | 
			
		||||
		prepayData, createOrderErr = l.svcCtx.AlipayService.CreateAlipayOrder(l.ctx, amount, product.ProductName, outTradeNo, brand)
 | 
			
		||||
	} else if req.PayMethod == "appleiap" {
 | 
			
		||||
		prepayData = l.svcCtx.ApplePayService.GetIappayAppID(product.ProductEn)
 | 
			
		||||
	}
 | 
			
		||||
	if createOrderErr != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 创建支付订单失败: %+v", createOrderErr)
 | 
			
		||||
	}
 | 
			
		||||
	var orderID int64
 | 
			
		||||
	transErr := l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
 | 
			
		||||
		order := model.Order{
 | 
			
		||||
			OrderNo:         outTradeNo,
 | 
			
		||||
			UserId:          userID,
 | 
			
		||||
			ProductId:       product.Id,
 | 
			
		||||
			PaymentPlatform: req.PayMethod,
 | 
			
		||||
			PaymentScene:    "app",
 | 
			
		||||
			Amount:          orderAmount,
 | 
			
		||||
			Status:          "pending",
 | 
			
		||||
		}
 | 
			
		||||
		orderInsertResult, insertOrderErr := l.svcCtx.OrderModel.Insert(ctx, session, &order)
 | 
			
		||||
		if insertOrderErr != nil {
 | 
			
		||||
			return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存订单失败: %+v", insertOrderErr)
 | 
			
		||||
		}
 | 
			
		||||
		insertedOrderID, lastInsertIdErr := orderInsertResult.LastInsertId()
 | 
			
		||||
		if lastInsertIdErr != nil {
 | 
			
		||||
			return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取保存订单ID失败: %+v", lastInsertIdErr)
 | 
			
		||||
		}
 | 
			
		||||
		orderID = insertedOrderID
 | 
			
		||||
	order := model.Order{
 | 
			
		||||
		OrderNo:         outTradeNo,
 | 
			
		||||
		UserId:          userID,
 | 
			
		||||
		ProductId:       product.Id,
 | 
			
		||||
		PaymentPlatform: req.PayMethod,
 | 
			
		||||
		PaymentScene:    "app",
 | 
			
		||||
		Amount:          amount,
 | 
			
		||||
		Status:          "pending",
 | 
			
		||||
	}
 | 
			
		||||
	orderInsertResult, insertOrderErr := l.svcCtx.OrderModel.Insert(l.ctx, session, &order)
 | 
			
		||||
	if insertOrderErr != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存订单失败: %+v", insertOrderErr)
 | 
			
		||||
	}
 | 
			
		||||
	insertedOrderID, lastInsertIdErr := orderInsertResult.LastInsertId()
 | 
			
		||||
	if lastInsertIdErr != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取保存订单ID失败: %+v", lastInsertIdErr)
 | 
			
		||||
	}
 | 
			
		||||
	orderID = insertedOrderID
 | 
			
		||||
 | 
			
		||||
		if data.AgentIdentifier != "" {
 | 
			
		||||
			agent, parsingErr := l.agentParsing(data.AgentIdentifier)
 | 
			
		||||
			if parsingErr != nil {
 | 
			
		||||
				return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 解析代理标识符失败: %+v", parsingErr)
 | 
			
		||||
			}
 | 
			
		||||
			var agentOrder model.AgentOrder
 | 
			
		||||
			agentOrder.OrderId = orderID
 | 
			
		||||
			agentOrder.AgentId = agent.AgentID
 | 
			
		||||
			_, agentOrderInsert := l.svcCtx.AgentOrderModel.Insert(ctx, session, &agentOrder)
 | 
			
		||||
			if agentOrderInsert != nil {
 | 
			
		||||
				return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存代理订单失败: %+v", agentOrderInsert)
 | 
			
		||||
			}
 | 
			
		||||
	if data.AgentIdentifier != "" {
 | 
			
		||||
		agent, parsingErr := l.agentParsing(data.AgentIdentifier)
 | 
			
		||||
		if parsingErr != nil {
 | 
			
		||||
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 解析代理标识符失败: %+v", parsingErr)
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	})
 | 
			
		||||
	if transErr != nil {
 | 
			
		||||
		return nil, transErr
 | 
			
		||||
	}
 | 
			
		||||
	env := os.Getenv("ENV")
 | 
			
		||||
	if env == "development" {
 | 
			
		||||
		if asyncErr := l.svcCtx.AsynqService.SendQueryTask(orderID); asyncErr != nil {
 | 
			
		||||
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 异步订单调用失败: %+v", asyncErr)
 | 
			
		||||
		var agentOrder model.AgentOrder
 | 
			
		||||
		agentOrder.OrderId = orderID
 | 
			
		||||
		agentOrder.AgentId = agent.AgentID
 | 
			
		||||
		_, agentOrderInsert := l.svcCtx.AgentOrderModel.Insert(l.ctx, session, &agentOrder)
 | 
			
		||||
		if agentOrderInsert != nil {
 | 
			
		||||
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存代理订单失败: %+v", agentOrderInsert)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	switch v := prepayData.(type) {
 | 
			
		||||
	case string:
 | 
			
		||||
		// 如果 prepayData 是字符串类型,直接返回
 | 
			
		||||
		return &types.PaymentResp{PrepayId: v, OrderID: orderID}, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return &types.PaymentResp{PrepayData: prepayData, OrderID: orderID}, nil
 | 
			
		||||
	return &PaymentTypeResp{amount: amount, outTradeNo: outTradeNo, description: product.ProductName}, nil
 | 
			
		||||
}
 | 
			
		||||
func (l *PaymentLogic) AgentVipOrderPayment(req *types.PaymentReq, session sqlx.Session) (resp *PaymentTypeResp, err error) {
 | 
			
		||||
	userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
 | 
			
		||||
	if getUidErr != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取用户信息失败, %+v", getUidErr)
 | 
			
		||||
	}
 | 
			
		||||
	user, err := l.svcCtx.UserModel.FindOne(l.ctx, userID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取用户信息失败: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	// 查询用户代理信息
 | 
			
		||||
	agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	redisKey := fmt.Sprintf(types.AgentVipCacheKey, userID, req.Id)
 | 
			
		||||
	cache, cacheErr := l.svcCtx.Redis.GetCtx(l.ctx, redisKey)
 | 
			
		||||
	if cacheErr != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取缓存失败, %+v", cacheErr)
 | 
			
		||||
	}
 | 
			
		||||
	var agentVipCache types.AgentVipCache
 | 
			
		||||
	err = json.Unmarshal([]byte(cache), &agentVipCache)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 解析缓存内容失败, %+v", err)
 | 
			
		||||
	}
 | 
			
		||||
	agentMembershipConfig, err := l.svcCtx.AgentMembershipConfigModel.FindOneByLevelName(l.ctx, agentVipCache.Type)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取代理会员配置失败, %+v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	amount := agentMembershipConfig.Price.Float64
 | 
			
		||||
	if user.Inside == 1 {
 | 
			
		||||
		amount = 0.01
 | 
			
		||||
	}
 | 
			
		||||
	agentMembershipRechargeOrder := model.AgentMembershipRechargeOrder{
 | 
			
		||||
		OrderNo:       req.Id,
 | 
			
		||||
		UserId:        userID,
 | 
			
		||||
		AgentId:       agentModel.Id,
 | 
			
		||||
		Amount:        amount,
 | 
			
		||||
		PaymentMethod: req.PayMethod,
 | 
			
		||||
		LevelName:     agentVipCache.Type,
 | 
			
		||||
		Status:        "pending",
 | 
			
		||||
	}
 | 
			
		||||
	_, err = l.svcCtx.AgentMembershipRechargeOrderModel.Insert(l.ctx, session, &agentMembershipRechargeOrder)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存代理会员充值订单失败: %+v", err)
 | 
			
		||||
	}
 | 
			
		||||
	return &PaymentTypeResp{amount: amount, outTradeNo: req.Id, description: fmt.Sprintf("%s代理会员充值", agentMembershipConfig.LevelName)}, nil
 | 
			
		||||
}
 | 
			
		||||
func (l *PaymentLogic) agentParsing(agentIdentifier string) (*types.AgentIdentifier, error) {
 | 
			
		||||
	key, decodeErr := hex.DecodeString("8e3e7a2f60edb49221e953b9c029ed10")
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,9 @@ import (
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/service"
 | 
			
		||||
	"tydata-server/pkg/lzkit/lzUtils"
 | 
			
		||||
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/logx"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/logx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type WechatPayCallbackLogic struct {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,10 +2,11 @@ package pay
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/logx"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
 | 
			
		||||
	"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/logx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type WechatPayRefundCallbackLogic struct {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,12 +2,13 @@ package product
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"tydata-server/app/user/model"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"github.com/Masterminds/squirrel"
 | 
			
		||||
	"github.com/jinzhu/copier"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/mr"
 | 
			
		||||
	"tydata-server/app/user/model"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 
 | 
			
		||||
@@ -2,12 +2,13 @@ package product
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"tydata-server/app/user/model"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"github.com/Masterminds/squirrel"
 | 
			
		||||
	"github.com/jinzhu/copier"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/mr"
 | 
			
		||||
	"tydata-server/app/user/model"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 
 | 
			
		||||
@@ -52,10 +52,15 @@ func (l *QueryDetailByOrderIdLogic) QueryDetailByOrderId(req *types.QueryDetailB
 | 
			
		||||
		}
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 安全验证:确保订单属于当前用户
 | 
			
		||||
	if order.UserId != userId {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.LOGIC_QUERY_NOT_FOUND), "无权查看此订单报告")
 | 
			
		||||
	user, err := l.svcCtx.UserModel.FindOne(l.ctx, userId)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找用户错误: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	if user.Inside != 1 {
 | 
			
		||||
		// 安全验证:确保订单属于当前用户
 | 
			
		||||
		if order.UserId != userId {
 | 
			
		||||
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.LOGIC_QUERY_NOT_FOUND), "无权查看此订单报告")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 创建渐进式延迟策略实例
 | 
			
		||||
@@ -232,7 +237,6 @@ func (l *QueryDetailByOrderIdLogic) UpdateFeatureAndProductFeature(productID int
 | 
			
		||||
			if pf.FeatureId == feature.Id { // 确保和 Feature 关联
 | 
			
		||||
				sort = int(pf.Sort)
 | 
			
		||||
				break // 找到第一个符合条件的就退出循环
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		featureData = map[string]interface{}{
 | 
			
		||||
 
 | 
			
		||||
@@ -195,7 +195,6 @@ func (l *QueryDetailByOrderNoLogic) UpdateFeatureAndProductFeature(productID int
 | 
			
		||||
			if pf.FeatureId == feature.Id { // 确保和 Feature 关联
 | 
			
		||||
				sort = int(pf.Sort)
 | 
			
		||||
				break // 找到第一个符合条件的就退出循环
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		featureData = map[string]interface{}{
 | 
			
		||||
 
 | 
			
		||||
@@ -4,12 +4,13 @@ import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"github.com/jinzhu/copier"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
	"tydata-server/pkg/lzkit/crypto"
 | 
			
		||||
	"tydata-server/pkg/lzkit/lzUtils"
 | 
			
		||||
 | 
			
		||||
	"github.com/jinzhu/copier"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										152
									
								
								app/user/cmd/api/internal/logic/query/queryexamplelogic copy.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								app/user/cmd/api/internal/logic/query/queryexamplelogic copy.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,152 @@
 | 
			
		||||
package query
 | 
			
		||||
 | 
			
		||||
// import (
 | 
			
		||||
// 	"context"
 | 
			
		||||
// 	"encoding/hex"
 | 
			
		||||
// 	"fmt"
 | 
			
		||||
// 	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
// 	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
// 	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
// 	"github.com/jinzhu/copier"
 | 
			
		||||
// 	"github.com/pkg/errors"
 | 
			
		||||
 | 
			
		||||
// 	"github.com/zeromicro/go-zero/core/logx"
 | 
			
		||||
// )
 | 
			
		||||
 | 
			
		||||
// type QueryExampleLogic struct {
 | 
			
		||||
// 	logx.Logger
 | 
			
		||||
// 	ctx    context.Context
 | 
			
		||||
// 	svcCtx *svc.ServiceContext
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
// func NewQueryExampleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryExampleLogic {
 | 
			
		||||
// 	return &QueryExampleLogic{
 | 
			
		||||
// 		Logger: logx.WithContext(ctx),
 | 
			
		||||
// 		ctx:    ctx,
 | 
			
		||||
// 		svcCtx: svcCtx,
 | 
			
		||||
// 	}
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
// func (l *QueryExampleLogic) QueryExample(req *types.QueryExampleReq) (resp *types.QueryExampleResp, err error) {
 | 
			
		||||
// 	var exampleID int64
 | 
			
		||||
// 	switch req.Feature {
 | 
			
		||||
// 	case "backgroundcheck":
 | 
			
		||||
// 		exampleID = 508
 | 
			
		||||
// 	case "companyinfo":
 | 
			
		||||
// 		exampleID = 506
 | 
			
		||||
// 	case "homeservice":
 | 
			
		||||
// 		exampleID = 504
 | 
			
		||||
// 	case "marriage":
 | 
			
		||||
// 		exampleID = 501
 | 
			
		||||
// 	case "preloanbackgroundcheck":
 | 
			
		||||
// 		exampleID = 509
 | 
			
		||||
// 	case "rentalinfo":
 | 
			
		||||
// 		exampleID = 505
 | 
			
		||||
// 	case "riskassessment":
 | 
			
		||||
// 		exampleID = 503
 | 
			
		||||
 | 
			
		||||
// 	default:
 | 
			
		||||
// 		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "示例报告, 获取示例报告失败: %v", err)
 | 
			
		||||
// 	}
 | 
			
		||||
// 	queryModel, err := l.svcCtx.QueryModel.FindOne(l.ctx, exampleID)
 | 
			
		||||
// 	if err != nil {
 | 
			
		||||
// 		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "示例报告, 获取示例报告失败: %v", err)
 | 
			
		||||
// 	}
 | 
			
		||||
// 	var query types.Query
 | 
			
		||||
// 	query.CreateTime = queryModel.CreateTime.Format("2006-01-02 15:04:05")
 | 
			
		||||
// 	query.UpdateTime = queryModel.UpdateTime.Format("2006-01-02 15:04:05")
 | 
			
		||||
 | 
			
		||||
// 	// 解密查询数据
 | 
			
		||||
// 	secretKey := l.svcCtx.Config.Encrypt.SecretKey
 | 
			
		||||
// 	key, decodeErr := hex.DecodeString(secretKey)
 | 
			
		||||
// 	if decodeErr != nil {
 | 
			
		||||
// 		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 获取AES解密解药失败, %v", err)
 | 
			
		||||
// 	}
 | 
			
		||||
// 	processParamsErr := ProcessQueryParams(queryModel.QueryParams, &query.QueryParams, key)
 | 
			
		||||
// 	if processParamsErr != nil {
 | 
			
		||||
// 		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 报告参数处理失败: %v", processParamsErr)
 | 
			
		||||
// 	}
 | 
			
		||||
// 	processErr := ProcessQueryData(queryModel.QueryData, &query.QueryData, key)
 | 
			
		||||
// 	if processErr != nil {
 | 
			
		||||
// 		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 报告结果处理失败: %v", processErr)
 | 
			
		||||
// 	}
 | 
			
		||||
// 	updateFeatureAndProductFeatureErr := l.UpdateFeatureAndProductFeature(queryModel.ProductId, &query.QueryData)
 | 
			
		||||
// 	if updateFeatureAndProductFeatureErr != nil {
 | 
			
		||||
// 		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结果处理失败: %v", updateFeatureAndProductFeatureErr)
 | 
			
		||||
// 	}
 | 
			
		||||
// 	// 复制报告数据
 | 
			
		||||
// 	err = copier.Copy(&query, queryModel)
 | 
			
		||||
// 	if err != nil {
 | 
			
		||||
// 		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 报告结构体复制失败, %v", err)
 | 
			
		||||
// 	}
 | 
			
		||||
// 	product, err := l.svcCtx.ProductModel.FindOne(l.ctx, queryModel.ProductId)
 | 
			
		||||
// 	if err != nil {
 | 
			
		||||
// 		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 获取商品信息失败, %v", err)
 | 
			
		||||
// 	}
 | 
			
		||||
// 	query.ProductName = product.ProductName
 | 
			
		||||
// 	return &types.QueryExampleResp{
 | 
			
		||||
// 		Query: query,
 | 
			
		||||
// 	}, nil
 | 
			
		||||
// }
 | 
			
		||||
// func (l *QueryExampleLogic) UpdateFeatureAndProductFeature(productID int64, target *[]types.QueryItem) error {
 | 
			
		||||
// 	// 遍历 target 数组,使用倒序遍历,以便删除元素时不影响索引
 | 
			
		||||
// 	for i := len(*target) - 1; i >= 0; i-- {
 | 
			
		||||
// 		queryItem := &(*target)[i]
 | 
			
		||||
 | 
			
		||||
// 		// 确保 Data 为 map 类型
 | 
			
		||||
// 		data, ok := queryItem.Data.(map[string]interface{})
 | 
			
		||||
// 		if !ok {
 | 
			
		||||
// 			return fmt.Errorf("queryItem.Data 必须是 map[string]interface{} 类型")
 | 
			
		||||
// 		}
 | 
			
		||||
 | 
			
		||||
// 		// 从 Data 中获取 apiID
 | 
			
		||||
// 		apiID, ok := data["apiID"].(string)
 | 
			
		||||
// 		if !ok {
 | 
			
		||||
// 			return fmt.Errorf("queryItem.Data 中的 apiID 必须是字符串类型")
 | 
			
		||||
// 		}
 | 
			
		||||
 | 
			
		||||
// 		// 查询 Feature
 | 
			
		||||
// 		feature, err := l.svcCtx.FeatureModel.FindOneByApiId(l.ctx, apiID)
 | 
			
		||||
// 		if err != nil {
 | 
			
		||||
// 			// 如果 Feature 查不到,也要删除当前 QueryItem
 | 
			
		||||
// 			*target = append((*target)[:i], (*target)[i+1:]...)
 | 
			
		||||
// 			continue
 | 
			
		||||
// 		}
 | 
			
		||||
 | 
			
		||||
// 		// 查询 ProductFeatureModel
 | 
			
		||||
// 		builder := l.svcCtx.ProductFeatureModel.SelectBuilder().Where("product_id = ?", productID)
 | 
			
		||||
// 		productFeatures, err := l.svcCtx.ProductFeatureModel.FindAll(l.ctx, builder, "")
 | 
			
		||||
// 		if err != nil {
 | 
			
		||||
// 			return fmt.Errorf("查询 ProductFeatureModel 错误: %v", err)
 | 
			
		||||
// 		}
 | 
			
		||||
 | 
			
		||||
// 		// 遍历 productFeatures,找到与 feature.ID 关联且 enable == 1 的项
 | 
			
		||||
// 		var featureData map[string]interface{}
 | 
			
		||||
// 		foundFeature := false
 | 
			
		||||
 | 
			
		||||
// 		for _, pf := range productFeatures {
 | 
			
		||||
// 			if pf.FeatureId == feature.Id { // 确保和 Feature 关联
 | 
			
		||||
// 				foundFeature = true
 | 
			
		||||
// 				if pf.Enable == 1 {
 | 
			
		||||
// 					featureData = map[string]interface{}{
 | 
			
		||||
// 						"featureName": feature.Name,
 | 
			
		||||
// 						"sort":        pf.Sort,
 | 
			
		||||
// 					}
 | 
			
		||||
// 					break // 找到第一个符合条件的就退出循环
 | 
			
		||||
// 				}
 | 
			
		||||
// 			}
 | 
			
		||||
// 		}
 | 
			
		||||
 | 
			
		||||
// 		// 如果没有符合条件的 feature 或者 featureData 为空,则删除当前 queryItem
 | 
			
		||||
// 		if !foundFeature || featureData == nil {
 | 
			
		||||
// 			*target = append((*target)[:i], (*target)[i+1:]...)
 | 
			
		||||
// 			continue
 | 
			
		||||
// 		}
 | 
			
		||||
 | 
			
		||||
// 		// 更新 queryItem 的 Feature 字段(不是数组)
 | 
			
		||||
// 		queryItem.Feature = featureData
 | 
			
		||||
// 	}
 | 
			
		||||
 | 
			
		||||
// 	return nil
 | 
			
		||||
// }
 | 
			
		||||
@@ -4,13 +4,14 @@ import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/jinzhu/copier"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
	"tydata-server/common/ctxdata"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"github.com/jinzhu/copier"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/logx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,9 +2,10 @@ package query
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ package query
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
@@ -1380,8 +1381,8 @@ func (l *QueryServiceLogic) CacheData(params map[string]interface{}, Product str
 | 
			
		||||
	if marshalErr != nil {
 | 
			
		||||
		return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 序列化参数失败: %+v", marshalErr)
 | 
			
		||||
	}
 | 
			
		||||
	outTradeNo := l.svcCtx.AlipayService.GenerateOutTradeNo()
 | 
			
		||||
	redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
 | 
			
		||||
	outTradeNo := "Q_" + l.svcCtx.AlipayService.GenerateOutTradeNo()
 | 
			
		||||
	redisKey := fmt.Sprintf(types.QueryCacheKey, userID, outTradeNo)
 | 
			
		||||
	cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
 | 
			
		||||
	if cacheErr != nil {
 | 
			
		||||
		return "", cacheErr
 | 
			
		||||
@@ -1401,16 +1402,16 @@ func (l *QueryServiceLogic) GetOrCreateUser(mobile string) (int64, error) {
 | 
			
		||||
		return userID, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	userModel, err := l.svcCtx.UserModel.FindOneByMobile(l.ctx, mobile)
 | 
			
		||||
	userModel, err := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: mobile, Valid: true})
 | 
			
		||||
	if err != nil && !errors.Is(err, model.ErrNotFound) {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	// 没有则创建账号
 | 
			
		||||
	if userModel == nil {
 | 
			
		||||
		userModel = &model.User{Mobile: mobile}
 | 
			
		||||
		if len(userModel.Nickname) == 0 {
 | 
			
		||||
			userModel.Nickname = mobile
 | 
			
		||||
		}
 | 
			
		||||
		userModel = &model.User{Mobile: sql.NullString{String: mobile, Valid: true}}
 | 
			
		||||
		// if len(userModel.Nickname) == 0 {
 | 
			
		||||
		// 	userModel.Nickname = mobile
 | 
			
		||||
		// }
 | 
			
		||||
		if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
 | 
			
		||||
			insertResult, userInsertErr := l.svcCtx.UserModel.Insert(ctx, session, userModel)
 | 
			
		||||
			if userInsertErr != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,9 +3,10 @@ package query
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ package user
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
@@ -51,15 +52,15 @@ func (l *AgentMobileCodeLoginLogic) AgentMobileCodeLogin(req *types.MobileCodeLo
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "手机登录, 验证码不正确")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, encryptedMobile)
 | 
			
		||||
	user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
 | 
			
		||||
	if findUserErr != nil && findUserErr != model.ErrNotFound {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取数据库获取用户失败, mobile: %s, err: %+v", encryptedMobile, err)
 | 
			
		||||
	}
 | 
			
		||||
	if user == nil {
 | 
			
		||||
		user = &model.User{Mobile: encryptedMobile}
 | 
			
		||||
		if len(user.Nickname) == 0 {
 | 
			
		||||
			user.Nickname = ""
 | 
			
		||||
		}
 | 
			
		||||
		user = &model.User{Mobile: sql.NullString{String: encryptedMobile, Valid: true}}
 | 
			
		||||
		// if len(user.Nickname) == 0 {
 | 
			
		||||
		// 	user.Nickname = ""
 | 
			
		||||
		// }
 | 
			
		||||
		if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
 | 
			
		||||
			insertResult, userInsertErr := l.svcCtx.UserModel.Insert(ctx, session, user)
 | 
			
		||||
			if userInsertErr != nil {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										104
									
								
								app/user/cmd/api/internal/logic/user/bindmobilelogic.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								app/user/cmd/api/internal/logic/user/bindmobilelogic.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,104 @@
 | 
			
		||||
package user
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
	"tydata-server/app/user/model"
 | 
			
		||||
	"tydata-server/common/ctxdata"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
	"tydata-server/pkg/lzkit/crypto"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/logx"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/stores/redis"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/stores/sqlx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type BindMobileLogic struct {
 | 
			
		||||
	logx.Logger
 | 
			
		||||
	ctx    context.Context
 | 
			
		||||
	svcCtx *svc.ServiceContext
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewBindMobileLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BindMobileLogic {
 | 
			
		||||
	return &BindMobileLogic{
 | 
			
		||||
		Logger: logx.WithContext(ctx),
 | 
			
		||||
		ctx:    ctx,
 | 
			
		||||
		svcCtx: svcCtx,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *BindMobileLogic) BindMobile(req *types.BindMobileReq) (resp *types.BindMobileResp, err error) {
 | 
			
		||||
	userID, getUserIdErr := ctxdata.GetUidFromCtx(l.ctx)
 | 
			
		||||
	if getUserIdErr != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "绑定手机号, %v", getUserIdErr)
 | 
			
		||||
	}
 | 
			
		||||
	secretKey := l.svcCtx.Config.Encrypt.SecretKey
 | 
			
		||||
	encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "绑定手机号, 加密手机号失败: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	user, err := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
 | 
			
		||||
	if err != nil && !errors.Is(err, model.ErrNotFound) {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "绑定手机号, %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	if user != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrMsg("该手机号已绑定"), "绑定手机号, %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	// 检查手机号是否在一分钟内已发送过验证码
 | 
			
		||||
	redisKey := fmt.Sprintf("%s:%s", "bindMobile", encryptedMobile)
 | 
			
		||||
	cacheCode, err := l.svcCtx.Redis.Get(redisKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, redis.Nil) {
 | 
			
		||||
			return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "手机登录, 验证码过期: %s", encryptedMobile)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取验证码redis缓存失败, mobile: %s, err: %+v", encryptedMobile, err)
 | 
			
		||||
	}
 | 
			
		||||
	if cacheCode != req.Code {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "手机登录, 验证码不正确: %s", encryptedMobile)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	userModel, err := l.svcCtx.UserModel.FindOne(l.ctx, userID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "绑定手机号, %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	if userModel.Mobile.Valid && userModel.Mobile.String != "" {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrMsg("账号已绑定手机号,无法再次绑定"), "绑定手机号, %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	userAuthModel, err := l.svcCtx.UserAuthModel.FindOneByUserIdAuthType(l.ctx, userID, model.UserAuthTypeH5Mobile)
 | 
			
		||||
	if err != nil && !errors.Is(err, model.ErrNotFound) {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "绑定手机号, %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	if userAuthModel != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrMsg("账号已绑定手机号,无法再次绑定"), "绑定手机号, %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var userAuth model.UserAuth
 | 
			
		||||
	userAuth.UserId = userID
 | 
			
		||||
	userAuth.AuthType = model.UserAuthTypeH5Mobile
 | 
			
		||||
	userAuth.AuthKey = encryptedMobile
 | 
			
		||||
	transErr := l.svcCtx.UserAuthModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
 | 
			
		||||
		_, err = l.svcCtx.UserAuthModel.Insert(ctx, session, &userAuth)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "绑定手机号, %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		userModel.Mobile = sql.NullString{
 | 
			
		||||
			String: encryptedMobile,
 | 
			
		||||
			Valid:  true,
 | 
			
		||||
		}
 | 
			
		||||
		_, err = l.svcCtx.UserModel.Update(l.ctx, session, userModel)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "绑定手机号, %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	})
 | 
			
		||||
	if transErr != nil {
 | 
			
		||||
		return nil, transErr
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &types.BindMobileResp{}, nil
 | 
			
		||||
}
 | 
			
		||||
@@ -46,9 +46,11 @@ func (l *DetailLogic) Detail() (resp *types.UserInfoResp, err error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, 用户信息结构体复制失败, %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	userInfo.Mobile, err = crypto.DecryptMobile(userInfo.Mobile, l.svcCtx.Config.Encrypt.SecretKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, 解密手机号失败, %v", err)
 | 
			
		||||
	if user.Mobile.Valid {
 | 
			
		||||
		userInfo.Mobile, err = crypto.DecryptMobile(user.Mobile.String, l.svcCtx.Config.Encrypt.SecretKey)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, 解密手机号失败, %v", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return &types.UserInfoResp{
 | 
			
		||||
		UserInfo: userInfo,
 | 
			
		||||
 
 | 
			
		||||
@@ -2,12 +2,13 @@ package user
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"time"
 | 
			
		||||
	"tydata-server/common/ctxdata"
 | 
			
		||||
	jwtx "tydata-server/common/jwt"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ package user
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
@@ -53,15 +54,15 @@ func (l *MobileCodeLoginLogic) MobileCodeLogin(req *types.MobileCodeLoginReq) (r
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, encryptedMobile)
 | 
			
		||||
	user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
 | 
			
		||||
	if findUserErr != nil && findUserErr != model.ErrNotFound {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取数据库获取用户失败, mobile: %s, err: %+v", encryptedMobile, err)
 | 
			
		||||
	}
 | 
			
		||||
	if user == nil {
 | 
			
		||||
		user = &model.User{Mobile: encryptedMobile}
 | 
			
		||||
		if len(user.Nickname) == 0 {
 | 
			
		||||
			user.Nickname = encryptedMobile
 | 
			
		||||
		}
 | 
			
		||||
		user = &model.User{Mobile: sql.NullString{String: encryptedMobile, Valid: true}}
 | 
			
		||||
		// if len(user.Nickname) == 0 {
 | 
			
		||||
		// 	user.Nickname = encryptedMobile
 | 
			
		||||
		// }
 | 
			
		||||
		if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
 | 
			
		||||
			insertResult, userInsertErr := l.svcCtx.UserModel.Insert(ctx, session, user)
 | 
			
		||||
			if userInsertErr != nil {
 | 
			
		||||
@@ -99,8 +100,5 @@ func (l *MobileCodeLoginLogic) MobileCodeLogin(req *types.MobileCodeLoginReq) (r
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
func (l *MobileCodeLoginLogic) MobileCodeLoginInside(req *types.MobileCodeLoginReq) (pass bool) {
 | 
			
		||||
	if req.Mobile == "17776203797" && req.Code == "688629" {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
	return req.Code == "182761"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ package user
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"time"
 | 
			
		||||
	"tydata-server/app/user/model"
 | 
			
		||||
	jwtx "tydata-server/common/jwt"
 | 
			
		||||
@@ -38,7 +39,7 @@ func (l *MobileLoginLogic) MobileLogin(req *types.MobileLoginReq) (resp *types.M
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 加密手机号失败: %+v", err)
 | 
			
		||||
	}
 | 
			
		||||
	user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, encryptedMobile)
 | 
			
		||||
	user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
 | 
			
		||||
	if findUserErr != nil && findUserErr != model.ErrNotFound {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取数据库获取用户失败, mobile%s, err: %+v", encryptedMobile, err)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ package user
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
@@ -52,7 +53,7 @@ func (l *RegisterLogic) Register(req *types.RegisterReq) (resp *types.RegisterRe
 | 
			
		||||
	if cacheCode != req.Code {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "手机注册, 验证码不正确: %s", encryptedMobile)
 | 
			
		||||
	}
 | 
			
		||||
	hasUser, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, encryptedMobile)
 | 
			
		||||
	hasUser, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
 | 
			
		||||
	if findUserErr != nil && findUserErr != model.ErrNotFound {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 读取数据库获取用户失败, mobile%s, err: %+v", encryptedMobile, err)
 | 
			
		||||
	}
 | 
			
		||||
@@ -62,10 +63,10 @@ func (l *RegisterLogic) Register(req *types.RegisterReq) (resp *types.RegisterRe
 | 
			
		||||
	var userId int64
 | 
			
		||||
	if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
 | 
			
		||||
		user := new(model.User)
 | 
			
		||||
		user.Mobile = encryptedMobile
 | 
			
		||||
		if len(user.Nickname) == 0 {
 | 
			
		||||
			user.Nickname = encryptedMobile
 | 
			
		||||
		}
 | 
			
		||||
		user.Mobile = sql.NullString{String: encryptedMobile, Valid: true}
 | 
			
		||||
		// if len(user.Nickname) == 0 {
 | 
			
		||||
		// 	user.Nickname = encryptedMobile
 | 
			
		||||
		// }
 | 
			
		||||
		if len(req.Password) > 0 {
 | 
			
		||||
			user.Password = lzUtils.StringToNullString(tool.Md5ByString(req.Password))
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,6 @@ import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/stores/sqlx"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"time"
 | 
			
		||||
@@ -13,6 +11,9 @@ import (
 | 
			
		||||
	jwtx "tydata-server/common/jwt"
 | 
			
		||||
	"tydata-server/common/xerr"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/zeromicro/go-zero/core/stores/sqlx"
 | 
			
		||||
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/svc"
 | 
			
		||||
	"tydata-server/app/user/cmd/api/internal/types"
 | 
			
		||||
 | 
			
		||||
@@ -39,7 +40,9 @@ func (l *WxH5AuthLogic) WxH5Auth(req *types.WXH5AuthReq) (resp *types.WXH5AuthRe
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取access_token失败: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if accessTokenResp.AccessToken == "" || accessTokenResp.Openid == "" {
 | 
			
		||||
		return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取access_token失败: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	// Step 2: 查找用户授权信息
 | 
			
		||||
	userAuth, findErr := l.svcCtx.UserAuthModel.FindOneByAuthTypeAuthKey(l.ctx, model.UserAuthTypeWxh5, accessTokenResp.Openid)
 | 
			
		||||
	if findErr != nil && !errors.Is(findErr, model.ErrNotFound) {
 | 
			
		||||
@@ -58,7 +61,6 @@ func (l *WxH5AuthLogic) WxH5Auth(req *types.WXH5AuthReq) (resp *types.WXH5AuthRe
 | 
			
		||||
	} else {
 | 
			
		||||
		// 授权信息不存在,创建新用户
 | 
			
		||||
		user = &model.User{}
 | 
			
		||||
		user.Mobile = accessTokenResp.Openid
 | 
			
		||||
		if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(context context.Context, session sqlx.Session) error {
 | 
			
		||||
			// 插入数据库
 | 
			
		||||
			insertResult, insertErr := l.svcCtx.UserModel.Insert(l.ctx, session, user)
 | 
			
		||||
@@ -107,8 +109,8 @@ type AccessTokenResp struct {
 | 
			
		||||
 | 
			
		||||
// GetAccessToken 通过code获取access_token
 | 
			
		||||
func GetAccessToken(code string) (*AccessTokenResp, error) {
 | 
			
		||||
	appID := "wxa581992dc74d860e"
 | 
			
		||||
	appSecret := "cfca484cf8cebcccb1f16fbaf1d9fe2c"
 | 
			
		||||
	appID := "wx442ee1ac1ee75917"
 | 
			
		||||
	appSecret := "c80474909db42f63913b7a307b3bee17"
 | 
			
		||||
 | 
			
		||||
	url := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", appID, appSecret, code)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user