Files
ycc-proxy-server/app/main/api/internal/logic/query/query_common.go
2026-02-01 19:15:52 +08:00

179 lines
6.0 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 query
import (
"context"
"database/sql"
"encoding/hex"
"encoding/json"
"fmt"
"ycc-server/common/xerr"
"ycc-server/pkg/lzkit/crypto"
"ycc-server/pkg/lzkit/lzUtils"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"ycc-server/app/main/api/internal/svc"
"ycc-server/app/main/api/internal/types"
"ycc-server/app/main/model"
)
func ProcessQueryData(queryData sql.NullString, target *[]types.QueryItem, key []byte) error {
queryDataStr := lzUtils.NullStringToString(queryData)
if queryDataStr == "" {
return nil
}
decryptedData, decryptErr := crypto.AesDecrypt(queryDataStr, key)
if decryptErr != nil {
return decryptErr
}
var decryptedArray []map[string]interface{}
unmarshalErr := json.Unmarshal(decryptedData, &decryptedArray)
if unmarshalErr != nil {
return unmarshalErr
}
if len(*target) == 0 {
*target = make([]types.QueryItem, len(decryptedArray))
}
for i := 0; i < len(decryptedArray); i++ {
(*target)[i].Data = decryptedArray[i]
}
return nil
}
func ProcessQueryParams(QueryParams string, target *map[string]interface{}, key []byte) error {
decryptedData, decryptErr := crypto.AesDecrypt(QueryParams, key)
if decryptErr != nil {
return decryptErr
}
unmarshalErr := json.Unmarshal(decryptedData, target)
if unmarshalErr != nil {
return unmarshalErr
}
return nil
}
// ensureQueryParamsIDCard 确保 target 中 id_card 非空,缺则用 fallbackId 填充(同一次报告多次进入分数一致)
func ensureQueryParamsIDCard(target *map[string]interface{}, fallbackId string) {
if target == nil {
return
}
if *target == nil {
*target = make(map[string]interface{})
}
v, ok := (*target)["id_card"]
if !ok {
(*target)["id_card"] = fallbackId
return
}
s, _ := v.(string)
if s == "" {
(*target)["id_card"] = fallbackId
}
}
func UpdateFeatureAndProductFeature(ctx context.Context, svcCtx *svc.ServiceContext, productID string, target *[]types.QueryItem) error {
for i := len(*target) - 1; i >= 0; i-- {
queryItem := &(*target)[i]
data, ok := queryItem.Data.(map[string]interface{})
if !ok {
return fmt.Errorf("queryItem.Data 必须是 map[string]interface{} 类型")
}
apiID, ok := data["apiID"].(string)
if !ok {
return fmt.Errorf("queryItem.Data 中的 apiID 必须是字符串类型")
}
feature, err := svcCtx.FeatureModel.FindOneByApiId(ctx, apiID)
if err != nil {
*target = append((*target)[:i], (*target)[i+1:]...)
continue
}
builder := svcCtx.ProductFeatureModel.SelectBuilder().Where("product_id = ?", productID)
productFeatures, err := svcCtx.ProductFeatureModel.FindAll(ctx, builder, "")
if err != nil {
return fmt.Errorf("查询 ProductFeatureModel 错误: %v", err)
}
sort := 0
for _, pf := range productFeatures {
if pf.FeatureId == feature.Id {
sort = int(pf.Sort)
break
}
}
featureData := map[string]interface{}{
"featureName": feature.Name,
"sort": sort,
}
queryItem.Feature = featureData
}
return nil
}
func BuildEncryptedQuery(ctx context.Context, svcCtx *svc.ServiceContext, queryModel *model.Query) (string, error) {
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 := svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取AES解密解药失败, %v", decodeErr)
}
processParamsErr := ProcessQueryParams(queryModel.QueryParams, &query.QueryParams, key)
if processParamsErr != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告参数处理失败: %v", processParamsErr)
}
// 保证 query_params 中始终有 id_card供前端评分 ±10 等逻辑使用(代理/自己查看报告等模式)
ensureQueryParamsIDCard(&query.QueryParams, "fallback_"+queryModel.Id)
processErr := ProcessQueryData(queryModel.QueryData, &query.QueryData, key)
if processErr != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结果处理失败: %v", processErr)
}
updateErr := UpdateFeatureAndProductFeature(ctx, svcCtx, queryModel.ProductId, &query.QueryData)
if updateErr != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结果处理失败: %v", updateErr)
}
err := copier.Copy(&query, queryModel)
if err != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结构体复制失败, %v", err)
}
product, err := svcCtx.ProductModel.FindOne(ctx, queryModel.ProductId)
if err != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取商品信息失败, %v", err)
}
query.Product = product.ProductEn
query.ProductName = product.ProductName
queryBytes, marshalErr := json.Marshal(query)
if marshalErr != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 序列化查询结果失败: %v", marshalErr)
}
encryptedQuery, encryptErr := crypto.AesEncrypt(queryBytes, key)
if encryptErr != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 加密查询结果失败: %v", encryptErr)
}
return encryptedQuery, nil
}
func IsOrderAgent(ctx context.Context, svcCtx *svc.ServiceContext, userId string, orderId string) (bool, error) {
agent, err := svcCtx.AgentModel.FindOneByUserId(ctx, userId)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return false, nil
}
return false, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理信息失败, %v", err)
}
if agent == nil {
return false, nil
}
agentOrder, err := svcCtx.AgentOrderModel.FindOneByOrderId(ctx, orderId)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return false, nil
}
return false, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询代理订单失败, %v", err)
}
if agentOrder == nil {
return false, nil
}
return agentOrder.AgentId == agent.Id, nil
}