package exchange import ( "encoding/json" "fmt" "sort" "sync" "bet24.com/log" "bet24.com/servers/common" "bet24.com/servers/coreservice/bet" "bet24.com/servers/coreservice/client" "bet24.com/servers/coreservice/serviceconfig" "bet24.com/servers/coreservice/teacher" inventory "bet24.com/servers/micros/item_inventory/proto" item "bet24.com/servers/micros/item_inventory/proto" cash "bet24.com/servers/micros/money/proto" vip "bet24.com/servers/micros/userservices/proto" ) func newExchangeManager() *exchangemgr { em := new(exchangemgr) em.lock = &sync.RWMutex{} go em.loadInfo() log.Debug("exchange.Run") return em } type exchangemgr struct { exchangeList map[int]ExchangeInfo lock *sync.RWMutex } func (em *exchangemgr) loadInfo() { em.exchangeList = make(map[int]ExchangeInfo) // 去数据库读取可兑换列表 list := trans_loadExchangeList() for _, v := range list { em.exchangeList[v.Id] = v } } func (em *exchangemgr) getExchangeType() []ExchangeType { var ret []ExchangeType for _, v := range em.exchangeList { ret = append(ret, ExchangeType{ Id: v.Id, ExchangeType: v.ExchangeType, Price: v.Price, Memo: v.Memo, }) } sort.SliceStable(ret, func(i, j int) bool { return ret[i].Memo < ret[j].Memo }) sort.SliceStable(ret, func(i, j int) bool { return ret[i].Price < ret[j].Price }) return ret } func (em *exchangemgr) getExchangeList(userId int) []ExchangeInfo { var ret []ExchangeInfo // 这里用户ID待过滤 // 需要从数据库中查询兑换记录,去除已兑换过的选项 _, history := trans_getExchangeHistory(userId, 0, 1, 1000000) removeList := make(map[int]int) for _, v := range history { e := em.getExchange(v.ExchangeId) // 兑换数据不存在 if e.Id <= 0 { removeList[v.ExchangeId] = 1 continue } // 只兑换一次 if e.LimitOnce { removeList[v.ExchangeId] = 1 continue } } gameCount := 0 // 获取游戏局数 list := bet.GetGameCount(userId, 0) for _, v := range list { gameCount += v.TotalCount } // 判断vip userVip := vip.GetUserVipInfo(userId) vipLevel := 0 if userVip != nil && userVip.IsVip() { vipLevel = userVip.Level } for _, v := range em.exchangeList { if _, ok := removeList[v.Id]; ok { continue } if vipLevel < v.VipShow { continue } // 判断局数 if gameCount < v.GameCountShow { continue } ret = append(ret, v) } sort.SliceStable(ret, func(i, j int) bool { return ret[i].Id < ret[j].Id }) return ret } // 获取收益类型 (1=绑码 2=充值 3=兑换 4=提现) func (em *exchangemgr) getProfitType(exchangeType int) int { profitType := 0 switch exchangeType { case EXCHANGE_TYPE_FUKA: // 什么都不做 case EXCHANGE_TYPE_TEACHER_CASH: fallthrough case EXCHANGE_TYPE_TEACHER_TEL: profitType = 3 // 兑换 case EXCHANGE_TYPE_TEACHER_CHIP: profitType = 4 // 提现 } return profitType } func (em *exchangemgr) getExchange(exchangeId int) ExchangeInfo { em.lock.RLock() defer em.lock.RUnlock() e, ok := em.exchangeList[exchangeId] if !ok { return ExchangeInfo{} } return e } func (em *exchangemgr) userExchange(userId, exchangeId, num int, remark string) (int, string) { e := em.getExchange(exchangeId) if e.Id <= 0 { log.Debug("exchangemgr.userExchange %d not found", exchangeId) return -3, "" } //先判断vip userVip := vip.GetUserVipInfo(userId) vipLevel := 0 if userVip != nil && userVip.IsVip() { vipLevel = userVip.Level } if vipLevel < e.VipNeed { return -5, "Vip等级不够" } //限制购买1次 if e.LimitOnce { if _, history := trans_getExchangeHistory(userId, exchangeId, 1, 1000000); len(history) > 0 { return -6, "已经购买过" } } //剩余数量 if e.LeftCount <= 0 { return -7, "库存不足" } //道具无效 if len(e.Items) <= 0 { log.Error("exchangemgr.userExchange UserId=%d exchangeId=%d num=%d info=%+v", userId, exchangeId, num, e) return -3, "" } price := e.Price * num if price <= 0 { log.Error("exchangemgr.userExchange UserId=%d exchangeId=%d num=%d info=%+v", userId, exchangeId, num, e) return -3, "" } // 提现需要判断最低提现金额 if e.ExchangeType == EXCHANGE_TYPE_TEACHER_CASH && price < serviceconfig.Server.MinWithdraw { return -4, fmt.Sprintf("提取金额必须大于%d", serviceconfig.Server.MinWithdraw) } success, msg := false, "" //获取道具 tool := item.GetItem(e.Items[0].ItemId) if tool == nil { log.Error("exchangemgr.userExchange UserId=%d exchangeId=%d num=%d info=%+v", userId, exchangeId, num, e) return -1, "无效道具" } // 物品*数量 if num > 1 { for i := 0; i < len(e.Items); i++ { e.Items[i].Count = e.Items[i].Count * num } } switch e.ExchangeType { case EXCHANGE_TYPE_FUKA: // 扣减奖券 logType := 0 switch tool.Type { case item.Item_Gold: // 兑换金币 logType = common.LOGTYPE_EXCHANGE_TOGOLD case item.Item_Addminutes: // 兑换话费 logType = common.LOGTYPE_EXCHANGE_TOTEL case item.Item_Cash: // 兑换cash logType = common.LOGTYPE_EXCHANGE_TOCASH } success, msg = inventory.Consume(userId, 620100, logType, price, 0) if !success { log.Debug("exchangemgr.userExchange UserId=%d exchangeId=%d success=%v num=%d msg=%s info=%+v", userId, exchangeId, success, num, msg, e) return -1, "扣减福卡失败" } case EXCHANGE_TYPE_TEACHER_CHIP: // 代理收益兑元宝 fallthrough case EXCHANGE_TYPE_TEACHER_TEL: // 代理收益兑话费 fallthrough case EXCHANGE_TYPE_TEACHER_CASH: // 代理收益兑RP profitType := em.getProfitType(e.ExchangeType) if retCode := teacher.ReduceProfit(userId, price, profitType); retCode != 1 { log.Debug("exchangemgr.userExchange UserId=%d exchangeType=%d exchangeId=%d num=%d retCode=%v msg=%s info=%+v", userId, e.ExchangeType, exchangeId, num, retCode, msg, e) return retCode, "扣减收益失败" } case EXCHANGE_TYPE_GOLD: // 金币提现 // 判断提现金额足购 /*if !vip.TryWithdraw(userId, price, true) { log.Debug("exchangemgr.userExchange UserId=%d exchangeType=%d exchangeId=%d num=%d msg=%s info=%+v", userId, e.ExchangeType, exchangeId, num, msg, e) return -8, "不满足条件" }*/ if !cash.ReduceMoney(userId, price, common.LOGTYPE_GOLD_EXCHANGE, "金币提现", "金币提现", "") { log.Debug("exchangemgr.userExchange UserId=%d exchangeType=%d exchangeId=%d price=%d num=%d info=%+v", userId, e.ExchangeType, exchangeId, price, num, e) return -1, "扣减金币失败" } //vip.TryWithdraw(userId, price, false) case EXCHANGE_TYPE_CASH: // 现金卡提现 success, msg = inventory.Consume(userId, 14001, common.LOGTYPE_CASHCARD_TOCASH, price, 0) if !success { log.Debug("exchangemgr.userExchange UserId=%d exchangeId=%d success=%v num=%d msg=%s info=%+v", userId, exchangeId, success, num, msg, e) return -1, "扣减现金卡失败" } default: log.Error("exchange.userExchange UserId=%d exchangeId=%d exchangeType=%d num=%d info=%+v", userId, exchangeId, e.ExchangeType, num, e) return -3, "" } //剩余数量-1 if e.LeftCount != 999999999 { e.LeftCount-- em.lock.Lock() em.exchangeList[e.Id] = e em.lock.Unlock() //数据库更新数量 if retCode := trans_updateExchange(e.Id, e.LeftCount); retCode != 1 { return -1, "兑换失败,请重试" } } //待发货 status := 0 msg = "兑换成功,客服将于3个工作日之内处理发货,详情请查阅兑换记录" if tool.Type != item.Item_Addminutes && tool.Type != item.Item_Physical && tool.Type != item.Item_GiftCard && tool.Type != item.Item_Cash { //已发货 status = 1 msg = "兑换成功" } //物品 items, _ := json.Marshal(e.Items) //兑换 ret := trans_userExchange(userId, exchangeId, e.ExchangeType, price, status, string(items), remark) if !ret { return -2, "兑换失败,请联系客服" } //加道具 inventory.AddItems(userId, e.Items, fmt.Sprintf("兑换[%d]", exchangeId), common.LOGTYPE_EXCHANGE) return 1, msg } func (em *exchangemgr) getExchangeHistory(userId, pageIndex, pageSize int) (int, []client.ExchangeHistory) { return trans_getExchangeHistory(userId, 0, pageIndex, pageSize) }