Files
ycc-proxy-server/app/main/api/internal/logic/agent/offlinefeaturelogic.go
2026-06-20 15:13:58 +08:00

198 lines
5.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 agent
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"strings"
"ycc-server/app/main/model"
"ycc-server/common/ctxdata"
"ycc-server/common/xerr"
"ycc-server/pkg/lzkit/crypto"
"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"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
type OfflineFeatureLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewOfflineFeatureLogic(ctx context.Context, svcCtx *svc.ServiceContext) *OfflineFeatureLogic {
return &OfflineFeatureLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *OfflineFeatureLogic) OfflineFeature(req *types.OfflineFeatureReq) (resp *types.OfflineFeatureResp, err error) {
if err := l.validateRequest(req); err != nil {
return nil, err
}
userID, err := l.verifyAgent()
if err != nil {
return nil, err
}
queryModel, idCard, name, err := l.getQueryInfo(req.QueryId)
if err != nil {
return nil, err
}
mainApiId := extractMainApiId(req.FeatureApiId)
feature, err := l.svcCtx.FeatureModel.FindOneByApiId(l.ctx, mainApiId)
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)
}
needPay, amount, whitelistCreated, err := l.svcCtx.WhitelistService.ProcessOfflineFeature(
l.ctx,
nil,
idCard,
req.FeatureApiId,
userID,
req.QueryId,
)
if err != nil {
return nil, err
}
if needPay {
return &types.OfflineFeatureResp{
Success: false,
NeedPay: true,
Amount: amount,
}, nil
}
if whitelistCreated {
remark := fmt.Sprintf("代理下架自动同步 query_id=%s feature=%s", req.QueryId, feature.ApiId)
l.svcCtx.QueryWhitelistSyncService.TrySync(
l.ctx,
name,
idCard,
[]string{feature.ApiId},
remark,
)
if err := l.deleteQueryData(req.QueryId, req.FeatureApiId); err != nil {
logx.Errorf("下架模块后删除报告数据失败:查询记录 %s模块 %s错误%v", req.QueryId, req.FeatureApiId, err)
}
}
_ = queryModel
return &types.OfflineFeatureResp{
Success: whitelistCreated,
NeedPay: needPay,
Amount: amount,
}, nil
}
func (l *OfflineFeatureLogic) validateRequest(req *types.OfflineFeatureReq) error {
if req.QueryId == "" {
return errors.Wrapf(xerr.NewErrMsg("查询记录ID不能为空"), "")
}
if req.FeatureApiId == "" {
return errors.Wrapf(xerr.NewErrMsg("模块API标识不能为空"), "")
}
return nil
}
func (l *OfflineFeatureLogic) verifyAgent() (string, error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户信息失败, %v", err)
}
_, err = l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return "", errors.Wrapf(xerr.NewErrMsg("您不是代理"), "")
}
return "", errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败, %v", err)
}
return userID, nil
}
func (l *OfflineFeatureLogic) getQueryInfo(queryId string) (*model.Query, string, string, error) {
queryModel, err := l.svcCtx.QueryModel.FindOne(l.ctx, queryId)
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)
}
idCard, name, err := extractPersonInfoFromQueryParams(l.svcCtx, queryModel)
if err != nil {
return nil, "", "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取查询参数失败, %v", err)
}
if idCard == "" {
return nil, "", "", errors.Wrapf(xerr.NewErrMsg("查询参数中缺少身份证号"), "")
}
return queryModel, idCard, name, nil
}
func extractMainApiId(featureApiId string) string {
if idx := strings.Index(featureApiId, "_"); idx > 0 {
return featureApiId[:idx]
}
return featureApiId
}
func extractPersonInfoFromQueryParams(svcCtx *svc.ServiceContext, queryModel *model.Query) (idCard, name string, err error) {
if queryModel.QueryParams == "" {
return "", "", errors.New("查询参数为空")
}
secretKey := svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return "", "", errors.Wrap(decodeErr, "获取AES密钥失败")
}
decryptedParams, decryptErr := crypto.AesDecrypt(queryModel.QueryParams, key)
if decryptErr != nil {
return "", "", errors.Wrap(decryptErr, "解密查询参数失败")
}
var params map[string]interface{}
if unmarshalErr := json.Unmarshal(decryptedParams, &params); unmarshalErr != nil {
return "", "", errors.Wrap(unmarshalErr, "解析查询参数失败")
}
idCardValue, ok := params["id_card"].(string)
if !ok || idCardValue == "" {
return "", "", errors.New("查询参数中缺少 id_card 或 id_card 为空")
}
nameValue, _ := params["name"].(string)
if strings.TrimSpace(nameValue) == "" {
nameValue = "*"
}
return idCardValue, nameValue, nil
}
func (l *OfflineFeatureLogic) deleteQueryData(queryId, featureApiId string) error {
return l.svcCtx.QueryModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
return l.svcCtx.WhitelistService.DeleteFeatureFromQueryData(ctx, session, queryId, featureApiId)
})
}