exchangemgr.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. package exchange
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "sort"
  6. "sync"
  7. "bet24.com/log"
  8. "bet24.com/servers/common"
  9. "bet24.com/servers/coreservice/bet"
  10. "bet24.com/servers/coreservice/client"
  11. "bet24.com/servers/coreservice/serviceconfig"
  12. "bet24.com/servers/coreservice/teacher"
  13. inventory "bet24.com/servers/micros/item_inventory/proto"
  14. item "bet24.com/servers/micros/item_inventory/proto"
  15. cash "bet24.com/servers/micros/money/proto"
  16. vip "bet24.com/servers/micros/userservices/proto"
  17. )
  18. func newExchangeManager() *exchangemgr {
  19. em := new(exchangemgr)
  20. em.lock = &sync.RWMutex{}
  21. go em.loadInfo()
  22. log.Debug("exchange.Run")
  23. return em
  24. }
  25. type exchangemgr struct {
  26. exchangeList map[int]ExchangeInfo
  27. lock *sync.RWMutex
  28. }
  29. func (em *exchangemgr) loadInfo() {
  30. em.exchangeList = make(map[int]ExchangeInfo)
  31. // 去数据库读取可兑换列表
  32. list := trans_loadExchangeList()
  33. for _, v := range list {
  34. em.exchangeList[v.Id] = v
  35. }
  36. }
  37. func (em *exchangemgr) getExchangeType() []ExchangeType {
  38. var ret []ExchangeType
  39. for _, v := range em.exchangeList {
  40. ret = append(ret, ExchangeType{
  41. Id: v.Id,
  42. ExchangeType: v.ExchangeType,
  43. Price: v.Price,
  44. Memo: v.Memo,
  45. })
  46. }
  47. sort.SliceStable(ret, func(i, j int) bool {
  48. return ret[i].Memo < ret[j].Memo
  49. })
  50. sort.SliceStable(ret, func(i, j int) bool {
  51. return ret[i].Price < ret[j].Price
  52. })
  53. return ret
  54. }
  55. func (em *exchangemgr) getExchangeList(userId int) []ExchangeInfo {
  56. var ret []ExchangeInfo
  57. // 这里用户ID待过滤
  58. // 需要从数据库中查询兑换记录,去除已兑换过的选项
  59. _, history := trans_getExchangeHistory(userId, 0, 1, 1000000)
  60. removeList := make(map[int]int)
  61. for _, v := range history {
  62. e := em.getExchange(v.ExchangeId)
  63. // 兑换数据不存在
  64. if e.Id <= 0 {
  65. removeList[v.ExchangeId] = 1
  66. continue
  67. }
  68. // 只兑换一次
  69. if e.LimitOnce {
  70. removeList[v.ExchangeId] = 1
  71. continue
  72. }
  73. }
  74. gameCount := 0
  75. // 获取游戏局数
  76. list := bet.GetGameCount(userId, 0)
  77. for _, v := range list {
  78. gameCount += v.TotalCount
  79. }
  80. // 判断vip
  81. userVip := vip.GetUserVipInfo(userId)
  82. vipLevel := 0
  83. if userVip != nil && userVip.IsVip() {
  84. vipLevel = userVip.Level
  85. }
  86. for _, v := range em.exchangeList {
  87. if _, ok := removeList[v.Id]; ok {
  88. continue
  89. }
  90. if vipLevel < v.VipShow {
  91. continue
  92. }
  93. // 判断局数
  94. if gameCount < v.GameCountShow {
  95. continue
  96. }
  97. ret = append(ret, v)
  98. }
  99. sort.SliceStable(ret, func(i, j int) bool {
  100. return ret[i].Id < ret[j].Id
  101. })
  102. return ret
  103. }
  104. // 获取收益类型 (1=绑码 2=充值 3=兑换 4=提现)
  105. func (em *exchangemgr) getProfitType(exchangeType int) int {
  106. profitType := 0
  107. switch exchangeType {
  108. case EXCHANGE_TYPE_FUKA:
  109. // 什么都不做
  110. case EXCHANGE_TYPE_TEACHER_CASH:
  111. fallthrough
  112. case EXCHANGE_TYPE_TEACHER_TEL:
  113. profitType = 3 // 兑换
  114. case EXCHANGE_TYPE_TEACHER_CHIP:
  115. profitType = 4 // 提现
  116. }
  117. return profitType
  118. }
  119. func (em *exchangemgr) getExchange(exchangeId int) ExchangeInfo {
  120. em.lock.RLock()
  121. defer em.lock.RUnlock()
  122. e, ok := em.exchangeList[exchangeId]
  123. if !ok {
  124. return ExchangeInfo{}
  125. }
  126. return e
  127. }
  128. func (em *exchangemgr) userExchange(userId, exchangeId, num int, remark string) (int, string) {
  129. e := em.getExchange(exchangeId)
  130. if e.Id <= 0 {
  131. log.Debug("exchangemgr.userExchange %d not found", exchangeId)
  132. return -3, ""
  133. }
  134. //先判断vip
  135. userVip := vip.GetUserVipInfo(userId)
  136. vipLevel := 0
  137. if userVip != nil && userVip.IsVip() {
  138. vipLevel = userVip.Level
  139. }
  140. if vipLevel < e.VipNeed {
  141. return -5, "Vip等级不够"
  142. }
  143. //限制购买1次
  144. if e.LimitOnce {
  145. if _, history := trans_getExchangeHistory(userId, exchangeId, 1, 1000000); len(history) > 0 {
  146. return -6, "已经购买过"
  147. }
  148. }
  149. //剩余数量
  150. if e.LeftCount <= 0 {
  151. return -7, "库存不足"
  152. }
  153. //道具无效
  154. if len(e.Items) <= 0 {
  155. log.Error("exchangemgr.userExchange UserId=%d exchangeId=%d num=%d info=%+v",
  156. userId, exchangeId, num, e)
  157. return -3, ""
  158. }
  159. price := e.Price * num
  160. if price <= 0 {
  161. log.Error("exchangemgr.userExchange UserId=%d exchangeId=%d num=%d info=%+v",
  162. userId, exchangeId, num, e)
  163. return -3, ""
  164. }
  165. // 提现需要判断最低提现金额
  166. if e.ExchangeType == EXCHANGE_TYPE_TEACHER_CASH && price < serviceconfig.Server.MinWithdraw {
  167. return -4, fmt.Sprintf("提取金额必须大于%d", serviceconfig.Server.MinWithdraw)
  168. }
  169. success, msg := false, ""
  170. //获取道具
  171. tool := item.GetItem(e.Items[0].ItemId)
  172. if tool == nil {
  173. log.Error("exchangemgr.userExchange UserId=%d exchangeId=%d num=%d info=%+v",
  174. userId, exchangeId, num, e)
  175. return -1, "无效道具"
  176. }
  177. // 物品*数量
  178. if num > 1 {
  179. for i := 0; i < len(e.Items); i++ {
  180. e.Items[i].Count = e.Items[i].Count * num
  181. }
  182. }
  183. switch e.ExchangeType {
  184. case EXCHANGE_TYPE_FUKA: // 扣减奖券
  185. logType := 0
  186. switch tool.Type {
  187. case item.Item_Gold: // 兑换金币
  188. logType = common.LOGTYPE_EXCHANGE_TOGOLD
  189. case item.Item_Addminutes: // 兑换话费
  190. logType = common.LOGTYPE_EXCHANGE_TOTEL
  191. case item.Item_Cash: // 兑换cash
  192. logType = common.LOGTYPE_EXCHANGE_TOCASH
  193. }
  194. success, msg = inventory.Consume(userId, 620100, logType, price, 0)
  195. if !success {
  196. log.Debug("exchangemgr.userExchange UserId=%d exchangeId=%d success=%v num=%d msg=%s info=%+v",
  197. userId, exchangeId, success, num, msg, e)
  198. return -1, "扣减福卡失败"
  199. }
  200. case EXCHANGE_TYPE_TEACHER_CHIP: // 代理收益兑元宝
  201. fallthrough
  202. case EXCHANGE_TYPE_TEACHER_TEL: // 代理收益兑话费
  203. fallthrough
  204. case EXCHANGE_TYPE_TEACHER_CASH: // 代理收益兑RP
  205. profitType := em.getProfitType(e.ExchangeType)
  206. if retCode := teacher.ReduceProfit(userId, price, profitType); retCode != 1 {
  207. log.Debug("exchangemgr.userExchange UserId=%d exchangeType=%d exchangeId=%d num=%d retCode=%v msg=%s info=%+v",
  208. userId, e.ExchangeType, exchangeId, num, retCode, msg, e)
  209. return retCode, "扣减收益失败"
  210. }
  211. case EXCHANGE_TYPE_GOLD: // 金币提现
  212. // 判断提现金额足购
  213. /*if !vip.TryWithdraw(userId, price, true) {
  214. log.Debug("exchangemgr.userExchange UserId=%d exchangeType=%d exchangeId=%d num=%d msg=%s info=%+v",
  215. userId, e.ExchangeType, exchangeId, num, msg, e)
  216. return -8, "不满足条件"
  217. }*/
  218. if !cash.ReduceMoney(userId, price, common.LOGTYPE_GOLD_EXCHANGE, "金币提现", "金币提现", "") {
  219. log.Debug("exchangemgr.userExchange UserId=%d exchangeType=%d exchangeId=%d price=%d num=%d info=%+v",
  220. userId, e.ExchangeType, exchangeId, price, num, e)
  221. return -1, "扣减金币失败"
  222. }
  223. //vip.TryWithdraw(userId, price, false)
  224. case EXCHANGE_TYPE_CASH: // 现金卡提现
  225. success, msg = inventory.Consume(userId, 14001, common.LOGTYPE_CASHCARD_TOCASH, price, 0)
  226. if !success {
  227. log.Debug("exchangemgr.userExchange UserId=%d exchangeId=%d success=%v num=%d msg=%s info=%+v",
  228. userId, exchangeId, success, num, msg, e)
  229. return -1, "扣减现金卡失败"
  230. }
  231. default:
  232. log.Error("exchange.userExchange UserId=%d exchangeId=%d exchangeType=%d num=%d info=%+v",
  233. userId, exchangeId, e.ExchangeType, num, e)
  234. return -3, ""
  235. }
  236. //剩余数量-1
  237. if e.LeftCount != 999999999 {
  238. e.LeftCount--
  239. em.lock.Lock()
  240. em.exchangeList[e.Id] = e
  241. em.lock.Unlock()
  242. //数据库更新数量
  243. if retCode := trans_updateExchange(e.Id, e.LeftCount); retCode != 1 {
  244. return -1, "兑换失败,请重试"
  245. }
  246. }
  247. //待发货
  248. status := 0
  249. msg = "兑换成功,客服将于3个工作日之内处理发货,详情请查阅兑换记录"
  250. if tool.Type != item.Item_Addminutes && tool.Type != item.Item_Physical && tool.Type != item.Item_GiftCard &&
  251. tool.Type != item.Item_Cash {
  252. //已发货
  253. status = 1
  254. msg = "兑换成功"
  255. }
  256. //物品
  257. items, _ := json.Marshal(e.Items)
  258. //兑换
  259. ret := trans_userExchange(userId, exchangeId, e.ExchangeType, price, status, string(items), remark)
  260. if !ret {
  261. return -2, "兑换失败,请联系客服"
  262. }
  263. //加道具
  264. inventory.AddItems(userId, e.Items, fmt.Sprintf("兑换[%d]", exchangeId), common.LOGTYPE_EXCHANGE)
  265. return 1, msg
  266. }
  267. func (em *exchangemgr) getExchangeHistory(userId, pageIndex, pageSize int) (int, []client.ExchangeHistory) {
  268. return trans_getExchangeHistory(userId, 0, pageIndex, pageSize)
  269. }