159 lines
4.8 KiB
Go
159 lines
4.8 KiB
Go
package agent
|
|
|
|
import (
|
|
"context"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"strconv"
|
|
"ycc-server/app/main/model"
|
|
"ycc-server/common/ctxdata"
|
|
"ycc-server/common/globalkey"
|
|
"ycc-server/common/xerr"
|
|
"ycc-server/pkg/lzkit/crypto"
|
|
|
|
"github.com/Masterminds/squirrel"
|
|
"github.com/pkg/errors"
|
|
|
|
"ycc-server/app/main/api/internal/svc"
|
|
"ycc-server/app/main/api/internal/types"
|
|
|
|
"github.com/zeromicro/go-zero/core/logx"
|
|
)
|
|
|
|
type GeneratingLinkLogic struct {
|
|
logx.Logger
|
|
ctx context.Context
|
|
svcCtx *svc.ServiceContext
|
|
}
|
|
|
|
func NewGeneratingLinkLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GeneratingLinkLogic {
|
|
return &GeneratingLinkLogic{
|
|
Logger: logx.WithContext(ctx),
|
|
ctx: ctx,
|
|
svcCtx: svcCtx,
|
|
}
|
|
}
|
|
|
|
func (l *GeneratingLinkLogic) GeneratingLink(req *types.AgentGeneratingLinkReq) (resp *types.AgentGeneratingLinkResp, err error) {
|
|
userID, err := ctxdata.GetUidFromCtx(l.ctx)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成推广链接失败, %v", err)
|
|
}
|
|
|
|
// 1. 获取代理信息
|
|
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
|
|
if err != nil {
|
|
if errors.Is(err, model.ErrNotFound) {
|
|
return nil, errors.Wrapf(xerr.NewErrMsg("您不是代理"), "")
|
|
}
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败, %v", err)
|
|
}
|
|
|
|
// 2. 获取系统配置
|
|
basePrice, err := l.getConfigFloat("base_price")
|
|
if err != nil {
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取基础底价配置失败, %v", err)
|
|
}
|
|
systemMaxPrice, err := l.getConfigFloat("system_max_price")
|
|
if err != nil {
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取系统价格上限配置失败, %v", err)
|
|
}
|
|
|
|
// 4. 计算实际底价(基础底价 + 等级加成)
|
|
levelBonus := l.getLevelBonus(agentModel.Level)
|
|
actualBasePrice := basePrice + float64(levelBonus)
|
|
|
|
// 5. 验证设定价格范围
|
|
if req.SetPrice < actualBasePrice || req.SetPrice > systemMaxPrice {
|
|
return nil, errors.Wrapf(xerr.NewErrMsg("设定价格必须在 %.2f 到 %.2f 之间"), "设定价格必须在 %.2f 到 %.2f 之间", actualBasePrice, systemMaxPrice)
|
|
}
|
|
|
|
// 6. 检查是否已存在相同的链接(同一代理、同一产品、同一价格)
|
|
builder := l.svcCtx.AgentLinkModel.SelectBuilder().Where(squirrel.And{
|
|
squirrel.Eq{"agent_id": agentModel.Id},
|
|
squirrel.Eq{"product_id": req.ProductId},
|
|
squirrel.Eq{"set_price": req.SetPrice},
|
|
squirrel.Eq{"del_state": globalkey.DelStateNo},
|
|
})
|
|
|
|
existingLinks, err := l.svcCtx.AgentLinkModel.FindAll(l.ctx, builder, "")
|
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询推广链接失败, %v", err)
|
|
}
|
|
|
|
if len(existingLinks) > 0 {
|
|
// 已存在,直接返回
|
|
return &types.AgentGeneratingLinkResp{
|
|
LinkIdentifier: existingLinks[0].LinkIdentifier,
|
|
}, nil
|
|
}
|
|
|
|
// 7. 生成推广链接标识
|
|
var agentIdentifier types.AgentIdentifier
|
|
agentIdentifier.AgentID = agentModel.Id
|
|
agentIdentifier.ProductID = req.ProductId
|
|
agentIdentifier.SetPrice = req.SetPrice
|
|
agentIdentifierByte, err := json.Marshal(agentIdentifier)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "序列化标识失败, %v", err)
|
|
}
|
|
|
|
// 8. 加密链接标识
|
|
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", decodeErr)
|
|
}
|
|
|
|
encrypted, err := crypto.AesEncryptURL(agentIdentifierByte, key)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "加密链接标识失败, %v", err)
|
|
}
|
|
|
|
// 9. 保存推广链接
|
|
agentLink := &model.AgentLink{
|
|
AgentId: agentModel.Id,
|
|
UserId: userID,
|
|
ProductId: req.ProductId,
|
|
LinkIdentifier: encrypted,
|
|
SetPrice: req.SetPrice,
|
|
ActualBasePrice: actualBasePrice,
|
|
}
|
|
|
|
_, err = l.svcCtx.AgentLinkModel.Insert(l.ctx, nil, agentLink)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "保存推广链接失败, %v", err)
|
|
}
|
|
|
|
return &types.AgentGeneratingLinkResp{
|
|
LinkIdentifier: encrypted,
|
|
}, nil
|
|
}
|
|
|
|
// getLevelBonus 获取等级加成
|
|
func (l *GeneratingLinkLogic) getLevelBonus(level int64) int64 {
|
|
switch level {
|
|
case 1: // 普通
|
|
return 6
|
|
case 2: // 黄金
|
|
return 3
|
|
case 3: // 钻石
|
|
return 0
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
// getConfigFloat 获取配置值(浮点数)
|
|
func (l *GeneratingLinkLogic) getConfigFloat(configKey string) (float64, error) {
|
|
config, err := l.svcCtx.AgentConfigModel.FindOneByConfigKey(l.ctx, configKey)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
value, err := strconv.ParseFloat(config.ConfigValue, 64)
|
|
if err != nil {
|
|
return 0, errors.Wrapf(err, "解析配置值失败, key: %s, value: %s", configKey, config.ConfigValue)
|
|
}
|
|
return value, nil
|
|
}
|