This commit is contained in:
2026-06-20 15:13:58 +08:00
parent 6c4029e645
commit 8ccd20f69e
24 changed files with 526 additions and 888 deletions

View File

@@ -4,6 +4,8 @@ import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"strings"
"ycc-server/app/main/model"
"ycc-server/common/ctxdata"
"ycc-server/common/xerr"
@@ -33,28 +35,32 @@ func NewOfflineFeatureLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Of
}
func (l *OfflineFeatureLogic) OfflineFeature(req *types.OfflineFeatureReq) (resp *types.OfflineFeatureResp, err error) {
// 1. 验证参数
if err := l.validateRequest(req); err != nil {
return nil, err
}
// 2. 获取用户ID并验证代理权限任意等级代理均可下架
userID, err := l.verifyAgent()
if err != nil {
return nil, err
}
// 3. 获取查询记录和身份证号
queryModel, idCard, err := l.getQueryInfo(req.QueryId)
queryModel, idCard, name, err := l.getQueryInfo(req.QueryId)
if err != nil {
return nil, err
}
_ = queryModel // 避免未使用变量警告
// 4. 调用 WhitelistService 统一下架处理
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, // 不使用事务,因为可能只是检查
nil,
idCard,
req.FeatureApiId,
userID,
@@ -64,14 +70,31 @@ func (l *OfflineFeatureLogic) OfflineFeature(req *types.OfflineFeatureReq) (resp
return nil, err
}
// 5. 如果已创建白名单,需要删除报告数据
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,
@@ -79,7 +102,6 @@ func (l *OfflineFeatureLogic) OfflineFeature(req *types.OfflineFeatureReq) (resp
}, nil
}
// validateRequest 验证请求参数
func (l *OfflineFeatureLogic) validateRequest(req *types.OfflineFeatureReq) error {
if req.QueryId == "" {
return errors.Wrapf(xerr.NewErrMsg("查询记录ID不能为空"), "")
@@ -90,7 +112,6 @@ func (l *OfflineFeatureLogic) validateRequest(req *types.OfflineFeatureReq) erro
return nil
}
// verifyAgent 验证是否为代理并返回用户ID任意等级代理均可下架
func (l *OfflineFeatureLogic) verifyAgent() (string, error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil {
@@ -108,61 +129,67 @@ func (l *OfflineFeatureLogic) verifyAgent() (string, error) {
return userID, nil
}
// getQueryInfo 获取查询记录和身份证号
func (l *OfflineFeatureLogic) getQueryInfo(queryId string) (*model.Query, string, error) {
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.NewErrMsg("查询记录不存在"), "")
}
return nil, "", errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询报告记录失败, %v", err)
return nil, "", "", errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询报告记录失败, %v", err)
}
// 解密 QueryParams 获取 idCard
idCard, err := l.extractIdCardFromQueryParams(queryModel)
idCard, name, err := extractPersonInfoFromQueryParams(l.svcCtx, queryModel)
if err != nil {
return nil, "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取身份证号失败, %v", err)
return nil, "", "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取查询参数失败, %v", err)
}
if idCard == "" {
return nil, "", errors.Wrapf(xerr.NewErrMsg("查询参数中缺少身份证号"), "")
return nil, "", "", errors.Wrapf(xerr.NewErrMsg("查询参数中缺少身份证号"), "")
}
return queryModel, idCard, nil
return queryModel, idCard, name, nil
}
// extractIdCardFromQueryParams 从 QueryParams 中提取身份证号
func (l *OfflineFeatureLogic) extractIdCardFromQueryParams(queryModel *model.Query) (string, error) {
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("查询参数为空")
return "", "", errors.New("查询参数为空")
}
secretKey := l.svcCtx.Config.Encrypt.SecretKey
secretKey := svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return "", errors.Wrap(decodeErr, "获取AES密钥失败")
return "", "", errors.Wrap(decodeErr, "获取AES密钥失败")
}
decryptedParams, decryptErr := crypto.AesDecrypt(queryModel.QueryParams, key)
if decryptErr != nil {
return "", errors.Wrap(decryptErr, "解密查询参数失败")
return "", "", errors.Wrap(decryptErr, "解密查询参数失败")
}
var params map[string]interface{}
unmarshalErr := json.Unmarshal(decryptedParams, &params)
if unmarshalErr != nil {
return "", errors.Wrap(unmarshalErr, "解析查询参数失败")
if unmarshalErr := json.Unmarshal(decryptedParams, &params); unmarshalErr != nil {
return "", "", errors.Wrap(unmarshalErr, "解析查询参数失败")
}
idCard, ok := params["id_card"].(string)
if !ok || idCard == "" {
return "", errors.New("查询参数中缺少 id_card 或 id_card 为空")
idCardValue, ok := params["id_card"].(string)
if !ok || idCardValue == "" {
return "", "", errors.New("查询参数中缺少 id_card 或 id_card 为空")
}
return idCard, nil
nameValue, _ := params["name"].(string)
if strings.TrimSpace(nameValue) == "" {
nameValue = "*"
}
return idCardValue, nameValue, nil
}
// deleteQueryData 删除报告数据
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)