pull/1/head
mofangmin 1 year ago
commit 4403d9284c
  1. 27
      .gitignore
  2. 3
      bin/conf/andarbahar/conf.toml
  3. 29
      bin/conf/andarbahar/module.json
  4. 10
      bin/conf/backend/conf.toml
  5. 38
      bin/conf/backend/gm/gm.html
  6. 29
      bin/conf/backend/module.json
  7. 59
      bin/conf/baseConf.toml
  8. 2
      bin/conf/blackred/conf.toml
  9. 29
      bin/conf/blackred/module.json
  10. 3
      bin/conf/blockpay/conf.toml
  11. 29
      bin/conf/blockpay/module.json
  12. 2
      bin/conf/car/conf.toml
  13. 29
      bin/conf/car/module.json
  14. 2
      bin/conf/common/conf.toml
  15. 18
      bin/conf/common/module.json
  16. 4
      bin/conf/customer/conf.toml
  17. 29
      bin/conf/customer/module.json
  18. 3
      bin/conf/dragon/conf.toml
  19. 29
      bin/conf/dragon/module.json
  20. 2
      bin/conf/fruit/conf.toml
  21. 29
      bin/conf/fruit/module.json
  22. 8
      bin/conf/gate/conf.toml
  23. 18
      bin/conf/gate/module.json
  24. 8
      bin/conf/hall/conf.toml
  25. 29
      bin/conf/hall/module.json
  26. 3
      bin/conf/horse/conf.toml
  27. 29
      bin/conf/horse/module.json
  28. BIN
      bin/conf/ip2region.db
  29. 3
      bin/conf/jm/conf.toml
  30. 29
      bin/conf/jm/module.json
  31. 1
      bin/conf/matching/conf.toml
  32. 18
      bin/conf/matching/module.json
  33. 31
      bin/conf/pay/conf.toml
  34. 29
      bin/conf/pay/module.json
  35. 4
      bin/conf/rocket/conf.toml
  36. 29
      bin/conf/rocket/module.json
  37. 3
      bin/conf/seven/conf.toml
  38. 29
      bin/conf/seven/module.json
  39. 3
      bin/conf/slot/conf.toml
  40. 29
      bin/conf/slot/module.json
  41. 3
      bin/conf/slotastrologer/conf.toml
  42. 29
      bin/conf/slotastrologer/module.json
  43. 3
      bin/conf/slotcashmania/conf.toml
  44. 29
      bin/conf/slotcashmania/module.json
  45. 3
      bin/conf/slotchristmas/conf.toml
  46. 29
      bin/conf/slotchristmas/module.json
  47. 3
      bin/conf/slotmaya/conf.toml
  48. 29
      bin/conf/slotmaya/module.json
  49. 3
      bin/conf/slotminer/conf.toml
  50. 29
      bin/conf/slotminer/module.json
  51. 3
      bin/conf/slotmonster/conf.toml
  52. 29
      bin/conf/slotmonster/module.json
  53. 3
      bin/conf/slotquick/conf.toml
  54. 29
      bin/conf/slotquick/module.json
  55. 3
      bin/conf/slotsurya/conf.toml
  56. 29
      bin/conf/slotsurya/module.json
  57. 3
      bin/conf/slotvegas777/conf.toml
  58. 29
      bin/conf/slotvegas777/module.json
  59. 39
      bin/conf/web/conf.toml
  60. 108
      bin/conf/web/gm/gm.html
  61. 29
      bin/conf/web/module.json
  62. 103
      bin/start.sh
  63. 46
      bin/stop.sh
  64. 9
      build.sh
  65. 22
      call/Snowflake.go
  66. 328
      call/activity.go
  67. 1448
      call/config.go
  68. 388
      call/currency.go
  69. 46
      call/game.go
  70. 40
      call/item.go
  71. 65
      call/mail.go
  72. 70
      call/module.go
  73. 813
      call/pay.go
  74. 38
      call/protocol.go
  75. 47
      call/queue.go
  76. 203
      call/realMail.go
  77. 53
      call/redpoint.go
  78. 442
      call/reload.go
  79. 155
      call/session.go
  80. 156
      call/share.go
  81. 573
      call/statistics.go
  82. 183
      call/sys.go
  83. 16
      call/timer.go
  84. 664
      call/user.go
  85. 1058
      call/warn.go
  86. 479
      common/activity.go
  87. 539
      common/config.go
  88. 239
      common/currency.go
  89. 89
      common/email.go
  90. 331
      common/es.go
  91. 79
      common/game.go
  92. 20
      common/lang.go
  93. 373
      common/platform.go
  94. 309
      common/player.go
  95. 67
      common/provider.go
  96. 235
      common/recharge.go
  97. 191
      common/redis_keys.go
  98. 9
      common/routers.go
  99. 109
      common/share.go
  100. 66
      common/task.go
  101. Some files were not shown because too many files have changed in this diff Show More

27
.gitignore vendored

@ -0,0 +1,27 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
*.log
.vs/
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
.idea
*test*
/pb/*.pb.go
/docs/backend/swagger.json
/docs/web/swagger.json
gameserver*

@ -0,0 +1,3 @@
WorkID=5000
MaxPlayerCount=10000
[Andarbahar]

@ -0,0 +1,29 @@
{
"Module":{
"game5000":[
{
"Id":"game5000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,10 @@
[Backend]
Addr=":7616"
Release=false
DB="root:d47a98e748ccaf1f@tcp(172.105.117.6:3306)/backend"
[Web.ZYPay]
ZYPayURL="https://in.zyhws.com/tablegames/singleton/orderPay"
ZYWithdrawURL="https://in.zyhws.com/tablegames/singleton/orderdraw"
PayNotifyURL="http://192.168.1.141:7615/balance/recharge/ZYPayCallback"
WithdrawNotifyURL="http://192.168.1.141:7615/balance/withdraw/ZYWithdrawCallback"
WhiteIPs = ["47.241.254.165","8.214.46.27"]

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>GM</title>
</head>
<body>
<form action="/gm/upload" method="post" enctype="multipart/form-data">
<label for="file">上传excel配置文件:</label>
<input type="file" name="config" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
<input type="submit" value="上传">
</form>
<form action="/gm/addcoin1" method="post" enctype="multipart/form-data">
金额(分): <input type="text" name="value" >
用户ID: <input type="text" name="uid" >
<input type="submit" value="添加">
</form>
<form action="/gm/resetSign" method="post" enctype="multipart/form-data">
用户ID: <input type="text" name="uid" >
类型:<input id="type" type="text" list="list" placeholder="选择重置类型" name="type">
<datalist id="list">
  <option>今日</option>
  <option>全部</option>
</datalist>
<input type="submit" value="重置签到">
</form>
<form action="/gm/recharge" method="post" enctype="multipart/form-data">
用户ID: <input type="text" name="uid" >
充值商品id: <input type="text" name="pid" >
<input type="submit" value="模拟充值">
</form>
</body>
</html>

@ -0,0 +1,29 @@
{
"Module":{
"backend":[
{
"Id":"backend001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,59 @@
[net]
registry="127.0.0.1:8500" # consul 地址
nats="nats://127.0.0.1:4222" # nats地址
[redis]
addr="127.0.0.1:6379"
name=""
passwd=""
tls=false
db=0
cluster=false
[es]
#urls=["http://127.0.0.1:9200"]
urls=["http://elastic:joyyu7XRwlpJtXFEIw80@47.112.119.250:9400"]
sniff=false
[mysql]
#dsn="xh_rwuser:!Xhwlkj2018@tcp(127.0.0.1:3306)/game"
dsn="root:d9JaXnG5QuuZLIrY@tcp(47.112.119.250:3306)/slotsgame"
debug=true
[facebook]
prefix="fb"
appKey=""
appSecret=""
authURL="https://graph.facebook.com"
[google]
prefix="gp"
authURL="oauth2.googleapis.com/tokeninfo?id_token="
[common]
savePicPath=""
avatarURL=""
[server]
IsExamine=true
ExamineURL="172.105.117.6:7615"
GameURL="172.105.117.6:7615"
[warn]
URL = "http://smsapi.5taogame.com/sms/httpSmsInterface2"
ID = "xlk168888"
Account = "xlk168888"
Password = "xlk168888"
Sign = "【章鱼游戏】"
Action = "sendhy"
[mails]
Accounts = ["lila48w4@gmail.com"]
Pass = ["eqqpmbabzihirygu"]
[newPacks]
PIDs = [117,116,102,157,121,141,162]
[ad]
FBAPIURL = "https://graph.facebook.com/v18.0/"
KwaiAPIURL = "http://www.adsnebula.com/log/common/api"

@ -0,0 +1,2 @@
WorkID=9000
MaxPlayerCount=10000

@ -0,0 +1,29 @@
{
"Module":{
"game9000":[
{
"Id":"game9000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,3 @@
[BlockPay]
[BlockPay.Tron]
Addrs = []

@ -0,0 +1,29 @@
{
"Module":{
"blockpay":[
{
"Id":"blockpay001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,2 @@
WorkID=16000
MaxPlayerCount=10000

@ -0,0 +1,29 @@
{
"Module":{
"game16000":[
{
"Id":"game16000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,2 @@
WorkID=1
Release=true

@ -0,0 +1,18 @@
{
"Module":{
"common":[
{
"Id":"common001",
"ProcessID":"development"
}
]
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,4 @@
[Customer]
Addr=":9616"
Release=false
DB="root:d9JaXnG5QuuZLIrY@tcp(47.112.119.250:3306)/customer"

@ -0,0 +1,29 @@
{
"Module":{
"customer":[
{
"Id":"customer001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,3 @@
WorkID=8000
MaxPlayerCount=10000
[Dragon]

@ -0,0 +1,29 @@
{
"Module":{
"game8000":[
{
"Id":"game8000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,2 @@
WorkID=15000
MaxPlayerCount=10000

@ -0,0 +1,29 @@
{
"Module":{
"game15000":[
{
"Id":"game15000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,8 @@
[Gate]
WSAddr="172.105.117.6"
WSPort=":6615"
HeartBeat=20
BufSize=4096
TLS=false
cert_file=""
key_file=""

@ -0,0 +1,18 @@
{
"Module":{
"gate":[
{
"Id":"gate001",
"ProcessID":"development"
}
]
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,8 @@
[Hall]
AvatarURL=""
SavePath=""
[Hall.FacebookParams]
Prefix=""
AppKey=""
AppScrect=""
AuthURL=""

@ -0,0 +1,29 @@
{
"Module":{
"hall":[
{
"Id":"hall001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,3 @@
WorkID=10000
MaxPlayerCount=10000
[Andarbahar]

@ -0,0 +1,29 @@
{
"Module":{
"game10000":[
{
"Id":"game10000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

Binary file not shown.

@ -0,0 +1,3 @@
WorkID=11000
MaxPlayerCount=10000
[JhandiMunda]

@ -0,0 +1,29 @@
{
"Module":{
"game11000":[
{
"Id":"game11000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,18 @@
{
"Module":{
"matching":[
{
"Id":"matching001",
"ProcessID":"development"
}
]
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,31 @@
[Pay]
Addr=":8615"
Release=true
TLS=false
CertFile=""
KeyFile=""
CallbackURL = "http://47.112.119.250"
CheckLimit = 20
RootChannel = [12,14]
SelectPayWay = true
PayCheckTime = 2
PayFailWeight = 20
PaySuccessWeight = 50
BaseSuccess = 10
WithdrawScanTime = 10
[Pay.IGeek]
APIURL = "http://api.test.igeekpay.com/gateway"
APPID = "H4RIKR"
MID = "RSRV686X"
Key = "2YHPVB8DZKTALVVI"
[Web.Adjust]
URL = "https://s2s.adjust.com/event"
APIURL = "https://api.adjust.com/device_service/api/v1/inspect_device"
APIToken = "_2ZGYezfdZ7yD2he-zWx"
[Pay.BestPay]
APIURL = "https://very.goodrummy.co.in"
[Pay.GrePay]
Key = ""
WithdrawAccount = ""
MIDAmount = 3000
BigChannel = "0452"

@ -0,0 +1,29 @@
{
"Module":{
"pay":[
{
"Id":"pay001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,4 @@
WorkID=22000
MaxPlayerCount=10000
[Rummy]
SettleTime=3

@ -0,0 +1,29 @@
{
"Module":{
"game22000":[
{
"Id":"game22000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,3 @@
WorkID=6000
MaxPlayerCount=10000
[Seven]

@ -0,0 +1,29 @@
{
"Module":{
"game6000":[
{
"Id":"game6000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,3 @@
WorkID=18000
MaxPlayerCount=10000
[TeenpattiWar]

@ -0,0 +1,29 @@
{
"Module":{
"game18000":[
{
"Id":"game18000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,3 @@
WorkID=58000
MaxPlayerCount=10000
[TeenpattiWar]

@ -0,0 +1,29 @@
{
"Module":{
"game58000":[
{
"Id":"game58000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,3 @@
WorkID=53000
MaxPlayerCount=10000
[TeenpattiWar]

@ -0,0 +1,29 @@
{
"Module":{
"game53000":[
{
"Id":"game53000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,3 @@
WorkID=50000
MaxPlayerCount=10000
[TeenpattiWar]

@ -0,0 +1,29 @@
{
"Module":{
"game50000":[
{
"Id":"game50000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,3 @@
WorkID=55000
MaxPlayerCount=10000
[TeenpattiWar]

@ -0,0 +1,29 @@
{
"Module":{
"game55000":[
{
"Id":"game55000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,3 @@
WorkID=52000
MaxPlayerCount=10000
[TeenpattiWar]

@ -0,0 +1,29 @@
{
"Module":{
"game52000":[
{
"Id":"game52000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,3 @@
WorkID=56000
MaxPlayerCount=10000
[TeenpattiWar]

@ -0,0 +1,29 @@
{
"Module":{
"game56000":[
{
"Id":"game56000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,3 @@
WorkID=57000
MaxPlayerCount=10000
[TeenpattiWar]

@ -0,0 +1,29 @@
{
"Module":{
"game57000":[
{
"Id":"game57000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,3 @@
WorkID=51000
MaxPlayerCount=10000
[TeenpattiWar]

@ -0,0 +1,29 @@
{
"Module":{
"game51000":[
{
"Id":"game51000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,3 @@
WorkID=54000
MaxPlayerCount=10000
[TeenpattiWar]

@ -0,0 +1,29 @@
{
"Module":{
"game54000":[
{
"Id":"game54000001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,39 @@
[Web]
Addr=":7615"
Release=true
TLS=false
CertFile=""
KeyFile=""
MaxPlayerAccountIP=2
MaxBankCardCount=1
PassRegion=["阿萨姆","奥里萨","锡金","那加兰","特伦甘纳","泰米尔纳德"]
BlackRegion=["马哈拉施特拉"]
IFSCURL="https://ifsc.razorpay.com"
TestWithdraw=-1
TestPay=3
FetchTime = 60
OldChannels = []
FreeSpinFirst = 500000000
TotalWithdrawPer = 50
BreakLimit = 100000000
SelectID = 2
[Web.OTP]
AntgstSmsReqURL="https://api.antgst.com/sms/txt/3/send/json"
AntgstAccessKey="5ac944dc65924f3dbfa1da2556a0f91b"
AntgstAccessSecret="f35a5d8b324d43a9be629a1f0dc62604"
AntgstModel="[TERFTE] Your OTP is {%v}. Valid for only 10 minutes."
AliSmsReqURL="http://smsapi.5taogame.com/sms/httpSmsInterface?action=sendhy"
AliSmsAccount="zygj6688"
AliSmsPass="zygj6688"
AliSmsModel="【Rummy Gold Mango】Your Verification code is %v.The verification code is valid within %v minutes.Don't share it to other people."
BukaUrl = "https://api.onbuka.com/v3/sendSms"
BukaAppID = "7g8gVTyL"
BukaAPIKey = "KFN1IKOd"
BukaAPISecret = "hX80mNh2"
BukaModel="Your Verification code is %v."
[Web.Adjust]
URL = "https://s2s.adjust.com/event"
APIURL = "https://api.adjust.com/device_service/api/v1/inspect_device"
APIToken = "_2ZGYezfdZ7yD2he-zWx"
[Web.FB]
APIURL = "https://graph.facebook.com/v18.0/"

@ -0,0 +1,108 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>GM</title>
</head>
<body>
<form action="/gm/upload" method="post" enctype="multipart/form-data">
<label for="file">上传excel配置文件:</label>
<input type="file" name="config" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
<input type="submit" value="上传">
</form>
<form action="/gm/uploaderrcode" method="post" enctype="multipart/form-data">
<label for="file">上传toml错误消息配置文件:</label>
<input type="file" name="config" accept=".toml">
<input type="submit" value="上传">
</form>
<form action="/gm/addcoin" method="post" enctype="multipart/form-data">
金额(分): <input type="text" name="value" >
用户ID: <input type="text" name="uid" >
类型:<input id="type" type="text" list="currencylist" placeholder="选择货币类型" name="type">
<datalist id="currencylist">
  <option>门票</option>
  <option>现金</option>
  <option>钻石</option>
  <option>奖券1</option>
  <option>奖券2</option>
  <option>奖券3</option>
  <option>奖券4</option>
</datalist>
<input type="submit" value="添加">
</form>
<form action="/gm/forceover" method="post" enctype="multipart/form-data">
选择模块:<input id="type" type="text" list="modules" placeholder="选择模块" name="module">
<datalist id="modules">
<option value="all">所有</option>
  <option value="solitaire">纸牌</option>
  <option value="blitz21">21点</option>
</datalist>
<input type="submit" value="结束比赛">
</form>
<form action="/gm/marquee" method="post" enctype="multipart/form-data">
内容:<input type="text" value="跑马灯。。。" name="content" size = 160>
优先级:<input type="text" name="priority" value="1" size=2>
次数:<input type="text" name="number" value="1" size=2>
<input type="submit" value="添加跑马灯">
</form>
<p>
玩家匹配分
</p>
<form action="/gm/queryMatchInfo" method="post" enctype="multipart/form-data">
uid:<input type="text" value="输入用户uid" name="uid" size = 40>
游戏:<input type="text" value="输入游戏名" name="name" size = 40>
参赛类型:<input id="type" type="text" list="currencylist" placeholder="选择门票类型" name="type">
<datalist id="currencylist">
  <option>门票</option>
  <option>现金</option>
</datalist>
<input type="submit" value="查询匹配分">
</form>
<form action="/gm/editMatchInfo" method="post" enctype="multipart/form-data">
uid:<input type="text" value="输入用户uid" name="uid" size = 40>
游戏:<input type="text" value="输入游戏名" name="name" size = 40>
参赛类型:<input id="type" type="text" list="currencylist" placeholder="选择门票类型" name="type">
<datalist id="currencylist">
  <option>门票</option>
  <option>现金</option>
</datalist>
匹配分:<input type="text" value="输入目标匹配分" name="score" size = 40>
难度:<input type="text" value="输入目标难度" name="difficult" size = 40>
<input type="submit" value="修改匹配数据">
</form>
<form action="/gm/queryDifficult" method="post" enctype="multipart/form-data">
<input type="submit" value="查询难度等级情况">
</form>
<p>
</p>
<form action="/gm/editPrizePool" method="post" enctype="multipart/form-data">
奖池:<input type="text" value="输入奖池数额" name="prize" size = 40>
<input type="submit" value="修改奖池">
</form>
</body>
</html>

@ -0,0 +1,29 @@
{
"Module":{
"web":[
{
"Id":"web001",
"ProcessID":"development"
}
]
},
"Mqtt":{
"WirteLoopChanNum": 10,
"ReadPackLoop": 1,
"ReadTimeout": 60,
"WriteTimeout": 60
},
"Rpc":{
"MaxCoroutine":10000,
"RpcExpired": 1,
"LogSuccess":false
},
"Log": {
"file":{
"daily":true,
"level":7,
"maxsize":1024000000,
"maxlines":10000000
}
}
}

@ -0,0 +1,103 @@
#!/bin/bash
#nohup ./gameserver-blitz21 -module=conf/modules.json -log=logs/ -conf=conf/config.json -rule=conf/rule.toml >/dev/null 2>&1 &
#nohup ./gameserver -module=conf/blitz21/modules.json -log=logs/blitz21 -conf=conf/blitz21/config.json -rule=conf/blitz21/rule.toml >/dev/null 2>&1 &
#source ./stop.sh
echo "start gameserver..."
if [[ $# -gt 0 ]]
then
echo "stop $1..."
for f in `ls conf/$1`
do
if [[ $f =~ ^gameserver ]]
then
array=(`echo $f | tr '.' ' '` )
echo "stop $array"
tmp=$(ps -ef | grep $array | grep -v "grep" | awk '{print $2}')
#echo $tmp
if [ "$tmp" = "" ];then
echo "$array not running"
else
kill $tmp
fi
break
fi
done
#source ./stop.sh $1
cp gameserver gameserver-$1
mv gameserver-$1 conf/$1
echo "start $1..."
tmp="-log=../../logs/$1 -baseConf=../baseConf.toml -debug=true"
for c in `ls conf/$1`
do
if [[ $c =~ ^gameserver ]]
then continue
fi
array=(`echo $c | tr '.' ' '` )
#echo $array
if [[ ${#array[@]} -ne 2 ]] || [[ $c =~ ^ip ]]
then continue
fi
tmp="$tmp -$array=$c"
#echo $tmp
done
echo $tmp
cd conf/$1
nohup ./gameserver-$1 $tmp >/dev/null 2>&1 &
exit 0
fi
source ./stop.sh
#cd conf/
for f in `ls conf`
do
#echo "start $f..."
if [[ $f =~ ^_ ]] || [[ $f = *.toml ]] || [[ -f $f ]] || [[ $f = *.db ]]
then
echo "pass $f..."
continue
fi
echo "start $f..."
cp gameserver gameserver-$f
mv gameserver-$f conf/$f
tmp="-log=../../logs/$f -baseConf=../baseConf.toml -debug=true"
for c in `ls conf/$f`
do
if [[ $c =~ ^gameserver|bi ]]
then continue
fi
array=(`echo $c | tr '.' ' '` )
#echo $array
if [[ ${#array[@]} -ne 2 ]] || [[ $c =~ ^ip ]]
then continue
fi
tmp="$tmp -$array=$c"
#echo $tmp
done
#echo $tmp
#tmp="-module=conf/$f/modules.json -log=logs/$f -conf=conf/$f/config.json -rule=conf/$f/rule.toml"
#mv gameserver gameserver1
#nohup ./gameserver -module=conf/$f/modules.json -log=logs/$f -conf=conf/$f/config.json -rule=conf/$f/rule.toml >/dev/null 2>&1 &
cd conf/$f
nohup ./gameserver-$f $tmp >/dev/null 2>&1 &
cd ../../
done
#for f in `ls`
#do
# if [[ $f =~ ^arena.*(.exe)?$ && -x $f ]]
# then
# echo "start $f"
# nohup ./$f -module=conf/modules.json -log=logs/ -conf=conf/config.json -rule=conf/rule.toml >/dev/null 2>&1 &
# fi
#done
echo 'finish ...'

@ -0,0 +1,46 @@
#!/bin/bash
echo 'stop server...'
if [[ $# -gt 0 ]]
then
echo "stop $1..."
for f in `ls conf/$1`
do
if [[ $f =~ ^gameserver ]]
then
array=(`echo $f | tr '.' ' '` )
#echo $array
echo "stop $array"
tmp=$(ps -ef | grep $array | grep -v "grep" | awk '{print $2}')
#echo $tmp
if [ "$tmp" = "" ];then
echo "$array not running"
else
kill $tmp
fi
break
fi
done
exit 0
fi
for f in `ls`
do
if [[ $f =~ ^.*robot(.exe)?|gameserver.*(.exe)?$ && -x $f ]]
then
array=(`echo $f | tr '.' ' '` )
echo "stop $array"
tmp=$(ps -ef | grep $array | grep -v "grep" | awk '{print $2}')
#echo $tmp
if [ "$tmp" = "" ];then
echo "$array not running"
else
kill $tmp
fi
fi
done
#ps -ef | grep "gateway_server\ -port" | grep -v "grep" | awk '{print $2}' | xargs kill -9
echo 'stop ok'

@ -0,0 +1,9 @@
#!/bin/bash
set -e
cd pb/proto
./gener.sh
# cd ../../
# cd tools
# go generate
cd ../..
go build main.go

@ -0,0 +1,22 @@
package call
import (
"github.com/bwmarrin/snowflake"
)
var (
snowNode *snowflake.Node
)
func NewSnowflake(id int64) {
id = id % 1023
var err error
snowNode, err = snowflake.NewNode(id)
if err != nil {
panic(err)
}
}
func SnowNode() *snowflake.Node {
return snowNode
}

@ -0,0 +1,328 @@
package call
import (
"fmt"
"server/common"
"server/config"
"server/db"
"server/pb"
"server/util"
"time"
"github.com/liangdas/mqant/log"
"github.com/olivere/elastic/v7"
"gorm.io/gorm"
)
func IsActivityValid(actID int) bool {
act := GetConfigActivityByID(actID)
if act == nil {
return false
}
return act.IsValid()
}
// NotifyActivityItem 通知客户端获得活动物品
func NotifyActivityItem(uid, activityID int, items []*pb.ActivityItem) {
activityNotify := &pb.ActivityResp{
ActivityID: int64(activityID),
ActivityItems: items,
}
SendNR(uid, int(pb.ServerCommonResp_CommonActivityItemResp), activityNotify, "common")
}
func GetAcitivityPddData(uid int) *common.PddData {
pddData := &common.PddData{UID: uid}
db.Mysql().Get(pddData)
con := GetConfigActivityPdd()
if con == nil {
return nil
}
now := time.Now().Unix()
if now-pddData.Time < con.Expire*60 {
// 每天有一次免费旋转
if !util.IsSameDayTimeStamp(now, pddData.FreeSpinTime) {
pddData.Spin++
}
return pddData
}
resetSpinCount := 1
if !config.GetBase().Release {
resetSpinCount = 100
}
if pddData.ID == 0 {
pddData.Time = now
pddData.Spin = resetSpinCount
db.Mysql().Create(pddData)
} else {
db.Mysql().Update(&common.PddData{UID: pddData.UID, Time: pddData.Time},
map[string]interface{}{"amount": 0, "time": now, "Spin": resetSpinCount, "free_spin_time": 0, "new_record_time": 0})
pddData.Amount = 0
pddData.Time = now
pddData.Spin = resetSpinCount
pddData.FreeSpinTime = 0
pddData.NewRecordTime = 0
}
return pddData
}
// 是否有新邀请
func HasNewAcitivityPddShare(uid int) bool {
if !IsActivityValid(common.ActivityIDPDD) {
return false
}
pddData := GetAcitivityPddData(uid)
if pddData.NewRecordTime <= 0 {
return false
}
q := elastic.NewBoolQuery()
q.Filter(elastic.NewTermQuery("Referer", uid))
q.Filter(elastic.NewRangeQuery("Time").Gte(pddData.NewRecordTime))
return db.ES().Count(common.ESIndexBackPddRecord, q) > 0
}
func GetUserFreeSpinData(uid int) *common.ActivityFreeSpinData {
data := &common.ActivityFreeSpinData{UID: uid}
db.Mysql().Get(data)
return data
}
func GetUserFirstRechargeBackData(uid int) *common.ActivityFirstRechargeBackData {
data := &common.ActivityFirstRechargeBackData{UID: uid}
db.Mysql().Get(data)
return data
}
func ShouldShowActivityFirstRechargeBack(uid int) bool {
if !IsActivityValid(common.ActivityIDFirstRechargeBack) {
return false
}
if uid == 0 {
return true
}
now := time.Now().Unix()
data := GetUserFirstRechargeBackData(uid)
if data.RechargeTime == 0 {
return true
}
if now-data.RechargeTime > 2*common.ActivityFirstRechargeBackTime {
return false
}
if now-data.RechargeTime > common.ActivityFirstRechargeBackTime && data.Lost == 0 {
return false
}
return true
}
func UploadActivityData(uid, activityID, t int, amount int64) {
db.ES().InsertToESGO(common.ESIndexBackActivity, &common.ESActivity{
ActivityID: activityID,
UID: uid,
Time: time.Now().Unix(),
Type: t,
Amount: amount,
})
}
func ShouldShowActivitySign(uid int) bool {
if !IsActivityValid(common.ActivityIDSign) {
return false
}
if uid == 0 {
return true
}
p, _ := GetUserXInfo(uid, "birth")
now := util.GetZeroTime(time.Now()).Unix()
birth := util.GetZeroTime(time.Unix(p.Birth, 0)).Unix()
return now-birth <= 6*common.OneDay
}
func GetUserWeekCard(uid, level int) *common.ActivityWeekCardData {
data := &common.ActivityWeekCardData{UID: uid, Level: level}
db.Mysql().Get(data)
return data
}
func GetUserWeekCards(uid int) []*common.ActivityWeekCardData {
list := []*common.ActivityWeekCardData{}
db.Mysql().QueryAll(fmt.Sprintf("uid = %d", uid), "", &common.ActivityWeekCardData{}, &list)
return list
}
func ShouldShowActivityWeekCard(uid int) bool {
if !IsActivityValid(common.ActivityIDWeekCard) {
return false
}
if uid == 0 {
return true
}
cards := GetUserWeekCards(uid)
for _, v := range cards {
if v.Day > 0 {
return false
}
}
return true
}
func GetUserActivitySlotsData(uid int) *common.ActivitySlotsData {
data := &common.ActivitySlotsData{UID: uid}
db.Mysql().Get(data)
now := time.Now().Unix()
isSingle := IsActivitySingleDay(common.ActivityIDSlots)
t := data.Time2
if isSingle {
t = data.Time1
}
if !util.IsSameDayTimeStamp(now, t) {
data.Spin = 0
}
if data.ID == 0 {
if isSingle {
data.Time1 = now
} else {
data.Time2 = now
}
p, _ := GetUserXInfo(uid, "mobile", "avatar")
data.Avatar = p.Avatar
data.Nick = p.Nick
db.Mysql().Create(data)
}
return data
}
func UpdateUserActivitySlotsData(uid int, count int) {
data := &common.ActivitySlotsData{UID: uid}
db.Mysql().Get(data)
now := time.Now().Unix()
isSingle := IsActivitySingleDay(common.ActivityIDSlots)
if data.ID == 0 {
if isSingle {
data.Time1 = now
} else {
data.Time2 = now
}
data.Spin = count
db.Mysql().Create(data)
return
}
update := map[string]interface{}{}
t := data.Time2
str := "time2"
if isSingle {
t = data.Time1
str = "time1"
}
if !util.IsSameDayTimeStamp(now, t) {
update["spin"] = count
update[str] = now
} else {
update["spin"] = gorm.Expr("spin + ?", count)
}
log.Debug("UpdateUserActivitySlotsData uid:%v,count:%v,isSingle:%v,update:%v", uid, count, isSingle, update)
db.Mysql().Update(&common.ActivitySlotsData{UID: uid}, update)
}
func ShouldShowActivityLuckShop(uid int) bool {
if !IsActivityValid(common.ActivityIDLuckyShop) {
return false
}
if uid == 0 {
return true
}
return GetShowActivityLuckShopData(uid) != nil
}
func GetShowActivityLuckShopData(uid int) *common.ActivityLuckyShopData {
if uid == 0 {
return nil
}
re := GetRechargeInfo(uid)
if re.TotalRecharge == 0 {
return nil
}
datas := []*common.ActivityLuckyShopData{}
db.Mysql().QueryAll(fmt.Sprintf("uid = %d", uid), "type asc", &common.ActivityLuckyShopData{}, &datas)
now := time.Now().Unix()
// 先判断首充礼包,两种礼包互斥,弹了其中一种,另一种不会弹了
var rechargeData *common.ActivityLuckyShopData
for i, v := range datas {
if v.Type == common.ActivityLuckyShopTypeRechargeLess || v.Type == common.ActivityLuckyShopTypeRechargeMore {
rechargeData = datas[i]
break
}
}
if rechargeData != nil && rechargeData.IsValid() {
return rechargeData
}
for i := common.ActivityLuckyShopType + 1; i < common.ActivityLuckyShopTypeAll; i++ {
// 如果已有首充礼包,那么直接跳过后续判断
if rechargeData != nil {
if i == common.ActivityLuckyShopTypeRechargeLess || i == common.ActivityLuckyShopTypeRechargeMore {
continue
}
}
con := GetConfigActivityLuckShop(i)
var tmp *common.ActivityLuckyShopData
for i, v := range datas {
if con.Type == v.Type {
tmp = datas[i]
break
}
}
if tmp == nil {
if con.Type == common.ActivityLuckyShopTypeRechargeLess {
if re.TotalRecharge < con.Recharge {
return &common.ActivityLuckyShopData{UID: uid, Type: con.Type, Push: now, ProductID: con.ProductID}
}
continue
}
if con.Type == common.ActivityLuckyShopTypeRechargeMore {
if re.TotalRecharge >= con.Recharge {
return &common.ActivityLuckyShopData{UID: uid, Type: con.Type, Push: now, ProductID: con.ProductID}
}
continue
}
p, _ := GetUserXInfo(uid, "birth")
tmp := p.Birth + 3*24*3600
if util.IsSameDayTimeStamp(now, tmp) || now > tmp {
return &common.ActivityLuckyShopData{UID: uid, Type: con.Type, Push: now, ProductID: con.ProductID}
}
} else if tmp.IsValid() {
return tmp
}
}
return nil
}
// IsActivitySingleDay 返回活动是否是单数天
func IsActivitySingleDay(id int) bool {
act := GetConfigActivityByID(id)
if act == nil || !act.IsValid() {
return false
}
// if config.GetBase().Release {
diff := int((util.GetZeroTime(time.Now()).Unix() - util.GetZeroTime(time.Unix(act.Start, 0)).Unix()) / (24 * 60 * 60))
return util.IsSingle(diff)
// }
// now := time.Now()
// _, m, _ := now.Clock()
// return util.IsSingle(m / 5)
}
func GetUserActivitySuperData(uid int) *common.ActivitySuperData {
p, _ := GetUserXInfo(uid, "birth")
data := &common.ActivitySuperData{UID: uid}
db.Mysql().Get(data)
if util.GetZeroTime(time.Now()).Unix()-util.GetZeroTime(time.Unix(p.Birth, 0)).Unix() < 5*common.OneDay {
data.Type = 1
} else {
data.Type = 2
}
data.CanBuy = !util.IsSameDayTimeStamp(time.Now().Unix(), data.Time)
if data.ID == 0 {
db.Mysql().Create(data)
}
return data
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,388 @@
package call
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"runtime"
"server/common"
"server/db"
"server/natsClient"
"server/pb"
"server/util"
"time"
"github.com/liangdas/mqant/log"
"gorm.io/gorm"
)
var (
ErrNotEnoughBalance = errors.New("not enough balance")
)
const (
ProTypeSettle = iota
ProTypeMineCash // 扣除可退出余额,判断余额是否足够
ProTypeAll
)
// BaseCurrency 更新玩家字段的基本对象
type BaseCurrency struct {
subCurrency subCurrency
tx *gorm.DB
*common.CurrencyBalance
notNotify bool // 是否需要通知客户端
notifyChan chan *ProRes
ProType int
// IsMine bool // 是否判断玩家余额是否充足
// IsRecharge bool // 是否更新充值账户
}
// NewCurrency 创建一个更新玩家字段对象
func NewCurrency(data *common.UpdateCurrency) *BaseCurrency {
b := new(BaseCurrency)
if data.CurrencyBalance.Type <= 0 || data.CurrencyBalance.Type >= common.CurrencyAll {
return nil
}
if data.Value == 0 {
return nil
}
b.notNotify = data.NotNotify
b.tx = data.Tx
b.CurrencyBalance = data.CurrencyBalance
b.Time = time.Now().Unix()
if b.ChannelID == 0 {
playerInfo, _ := GetUserXInfo(data.UID, "channel_id")
b.ChannelID = playerInfo.ChannelID
}
log.Debug("new update:%+v", *b.CurrencyBalance)
return b
}
// UpdateCurrency 更新玩家数据并通知客户端
func UpdateCurrency(data *common.UpdateCurrency, tx *gorm.DB) error {
b := NewCurrency(data)
if b == nil {
return errors.New("invalid update")
}
b.tx = tx
err := b.UpdateCurrency()
if err != nil {
return err
}
b.Notify()
return nil
}
func (b *BaseCurrency) Notify() {
if err := Publish(natsClient.TopicInnerRefreshGold, &pb.InnerRefreshGold{UID: uint32(b.UID), Pair: []*pb.CurrencyPair{{Type: int64(b.Type), Value: b.Value}},
Event: uint32(b.Event)}); err != nil {
log.Error("err:%v", err)
}
if b.notNotify {
return
}
var resp pb.PlayerBalanceResp
resp.Type = int64(b.Type)
resp.Balance = b.Balance
resp.Value = b.Value
resp.Event = int64(b.Event)
if caller != nil {
SendNR(b.UID, int(pb.ServerCommonResp_CommonPlayerBalanceResp), &resp, "common")
}
}
func Notify(uid int, bal, changeVal int64, t common.CurrencyType, event common.CurrencyEvent, exs1, exs2 string) {
var resp pb.PlayerBalanceResp
resp.Balance = bal
resp.Type = int64(t)
resp.Event = int64(event)
resp.Exs1 = exs1
resp.Exs2 = exs2
resp.Value = changeVal
if caller != nil {
SendNR(uid, int(pb.ServerCommonResp_CommonPlayerBalanceResp), &resp, "common")
}
}
// ProRes 存储过程返回结构
type ProRes struct {
Result int
Type common.CurrencyType
Balance int64 // 余额
Err error
}
// 存储过程修改金币
func UpdateCurrencyPro(data *common.UpdateCurrency) (*ProRes, error) {
b := NewCurrency(data)
if b == nil {
return nil, errors.New("invalid update")
}
b.notifyChan = make(chan *ProRes, 1)
b.UpdateCurrencyPro()
// retPro := new(ProRes)
// for pro := range b.notifyChan {
// if pro.Err != nil {
// return pro, pro.Err
// }
// retPro = pro
// break
// }
retPro := <-b.notifyChan
b.Notify()
return retPro, nil
}
// 存储过程修改金币,立即返回,失败后不重试(不判断玩家余额是否充足,可能扣成负数)
func UpdateCurrencyProReal(data *common.UpdateCurrency) *ProRes {
pro := &ProRes{}
b := NewCurrency(data)
if b == nil {
pro.Err = errors.New("invalid update")
return pro
}
pro, err := b.UpdatePro()
if err != nil {
pro.Err = err
return pro
}
if pro.Err != nil {
return pro
}
b.Notify()
return pro
}
// 存储过程修改金币,立即返回,失败后不重试(会判断玩家余额是否充足)
func MineCurrencyProReal(data *common.UpdateCurrency) *ProRes {
pro := &ProRes{}
b := NewCurrency(data)
if b == nil {
pro.Err = errors.New("invalid update")
return pro
}
b.ProType = ProTypeMineCash
pro, err := b.UpdatePro()
if err != nil {
pro.Err = err
return pro
}
if pro.Err != nil {
return pro
}
if pro.Result == 1 {
pro.Err = ErrNotEnoughBalance
return pro
}
b.Notify()
return pro
}
// 通过存储过程改变金币(不判断玩家余额是否充足,可能扣成负数)
func (b *BaseCurrency) UpdateCurrencyPro() {
util.IndexTryCallback(func() error {
pro, err := b.UpdatePro()
if err != nil {
return err
}
b.notifyChan <- pro
return nil
}, func() {
b.notifyChan <- &ProRes{Err: fmt.Errorf("index try fail")}
})
}
func (b *BaseCurrency) UpdatePro() (*ProRes, error) {
uid := b.UID
field := b.Type.GetCurrencyName()
pro := &ProRes{Type: b.Type}
callName := "settleCurrency"
if b.ProType == ProTypeMineCash {
callName = "mineCurrency"
}
err := db.Mysql().C().Raw(fmt.Sprintf("call %s(%d,'%v',%d,%d,@a,@b)", callName, uid, field, b.Value, b.NeedBet)).Scan(pro).Error
if err != nil {
log.Error("err:%v", err)
return pro, err
}
b.Balance = pro.Balance
util.Go(func() {
WriteBalance(b.CurrencyBalance)
})
return pro, nil
}
func (b *BaseCurrency) UpdateCurrency() (err error) {
tx := b.tx
if tx == nil {
tx = db.Mysql().C()
}
defer func() {
if r := recover(); r != nil {
buf := make([]byte, 1024)
runtime.Stack(buf, false)
log.Error(string(buf))
return
}
}()
uid := b.UID
field := b.Type.GetCurrencyName()
log.Debug("player %v update currency:%+v", uid, *b)
pc := &common.PlayerCurrency{UID: uid}
tableName := pc.TableName()
err = db.Mysql().C().Table(tableName).Where(&common.PlayerCurrency{UID: uid}).Select(field).Scan(&b.Balance).Error
if err != nil {
return
}
if b.Value > 0 {
err = tx.Model(&common.PlayerCurrency{UID: uid}).Updates(map[string]interface{}{field: gorm.Expr(fmt.Sprintf("%s + ?", field), b.Value)}).Error
if err != nil {
return
}
} else {
if b.Balance < -b.Value {
err = errors.New("not enough balance")
return
}
res := tx.Table(tableName).Where(&common.PlayerCurrency{UID: uid}).Where(fmt.Sprintf("uid = %d and %s>=%d", uid, field, -b.Value)).
Updates(map[string]interface{}{field: gorm.Expr(fmt.Sprintf("%s + ?", field), -b.Value)})
if res.RowsAffected == 0 || res.Error != nil {
log.Error("err:%e", res.Error)
err = errors.New("not enough balance")
return
}
}
if b.NeedBet > 0 {
err = tx.Model(&common.PlayerProfile{}).Where("uid = ?", uid).Updates(map[string]interface{}{"need_bet": gorm.Expr("need_bet + ?", b.NeedBet)}).Error
if err != nil {
log.Error("err:%v", err)
return
}
}
b.Balance += b.Value
err = WriteBalance(b.CurrencyBalance, tx)
if err != nil {
log.Error("err:%v", err)
return
}
if b.subCurrency != nil {
err = b.subCurrency.updateCurrency()
if err != nil {
log.Error("err:%v", err)
}
return
}
return
}
type subCurrency interface {
updateCurrency() error
}
func WriteBalance(b *common.CurrencyBalance, d ...*gorm.DB) error {
tx := db.Mysql().C()
if d != nil {
tx = d[0]
}
if len(b.Exs1) > 64 {
b.Exs1 = b.Exs1[:64]
}
if len(b.Exs2) > 64 {
b.Exs2 = b.Exs2[:64]
}
if len(b.Exs3) > 64 {
b.Exs3 = b.Exs3[:64]
}
err := tx.Table(b.TableName()).Create(b).Error
if err != nil {
log.Error("dbUpdateCurrency AddCurrencyBalance error:%v", err)
return err
}
db.ES().InsertToESGO(common.ESIndexBalance, b)
return nil
}
// 汇率转换(转成美元)
func Rate(t common.CurrencyType, amount int64) int64 {
switch t {
case common.CurrencyBrazil:
// 汇率每天刷新一次
rate := GetConfigCurrencyRateUSD(t)
if rate == 0 {
rate = 2000
}
return amount * rate / 10000
default:
return amount
}
}
func RateBRL(t common.CurrencyType, amount int64) int64 {
switch t {
case common.CurrencyBrazil:
return amount
case common.CurrencyUSDT:
// 汇率每天刷新一次
rate := GetConfigCurrencyRateUSD(common.CurrencyBrazil)
if rate == 0 {
rate = 2000
}
return amount * 10000 / rate
default:
return amount
}
}
const (
RateKey = "0P0U7HP7G0GIDJJ6" // 汇率查询网站apikey
)
type FXRate struct {
FromCurrencyCode string `json:"1. From_Currency Code"`
FromCurrencyName string `json:"2. From_Currency Name"`
ToCurrencyCode string `json:"3. To_Currency Code"`
ToCurrencyName string `json:"4. To_Currency Name"`
ExchangeRate float64 `json:"5. Exchange Rate,string"`
}
// GetRateFromAPI 查询货币汇率,返回万分位
func GetRateFromAPI(t common.CurrencyType) int64 {
if t == common.CurrencyUSDT {
return 10000
}
url := fmt.Sprintf("https://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE&from_currency=%v&to_currency=USD&apikey=%v", t.GetCurrencyName(), RateKey)
resp, err := http.Get(url)
if err != nil {
log.Error("err:%v", err)
return 0
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Error("err:%v", err)
return 0
}
log.Debug("GetRateFromAPI:%v", string(body))
var data map[string]FXRate
err = json.Unmarshal(body, &data)
if err != nil {
log.Error("err:%v", err)
return 0
}
fxRate, ok := data["Realtime Currency Exchange Rate"]
if !ok {
return 0
}
return int64(fxRate.ExchangeRate * 10000)
}

@ -0,0 +1,46 @@
package call
import (
"fmt"
"server/common"
"server/db"
"server/util"
"github.com/liangdas/mqant/log"
"gorm.io/gorm"
)
func UpdateJackpot(t, tid int, amount int64) {
if err := db.Mysql().C().Exec(fmt.Sprintf("call jackpot(%v,%v,%v)", t, tid, amount)).Error; err != nil {
log.Error("err:%v", err)
}
}
func GetJackpot(t, tid int) int64 {
data := &common.Jackpot{Type: t, TypeID: tid}
db.Mysql().Get(data)
return data.Amount
}
func GetJack(t, tid int) *common.Jackpot {
data := &common.Jackpot{Type: t, TypeID: tid}
db.Mysql().Get(data)
return data
}
func UpdateGameJackpot(t, tid int, amount, playerAmount int64) {
jack := GetJack(t, tid)
u := map[string]interface{}{"player_amount": gorm.Expr("player_amount + ?", playerAmount)}
if jack.Amount+amount >= jack.Max {
u["amnout"] = jack.Max
} else {
u["amount"] = gorm.Expr("amount + ?", amount)
}
db.Mysql().Update(&common.Jackpot{Type: t, TypeID: tid}, u)
}
func UpdateGameSort(provider, gameID int) {
util.Go(func() {
db.Mysql().Update(&common.ConfigGameList{GameProvider: provider, GameID: gameID}, map[string]interface{}{"sort": gorm.Expr("sort + 1")})
})
}

@ -0,0 +1,40 @@
package call
import (
"fmt"
"server/common"
"server/db"
"time"
)
func GetUserItem(uid, itemID int) []*common.PlayerItems {
list := []*common.PlayerItems{}
db.Mysql().QueryAll(fmt.Sprintf("uid = %d and item_id = %d", uid, itemID), "", &common.PlayerItems{}, &list)
return list
}
func GetUserValidItems(uid, itemID int) []*common.PlayerItems {
list := []*common.PlayerItems{}
db.Mysql().QueryAll(fmt.Sprintf("uid = %d and item_id = %d and status = %d", uid, itemID, common.ItemStatusNormal), "", &common.PlayerItems{}, &list)
return list
}
func GetUserItemByExi1(uid, itemID, exi1 int) []*common.PlayerItems {
list := []*common.PlayerItems{}
db.Mysql().QueryAll(fmt.Sprintf("uid = %d and item_id = %d and exi1 = %d and status = %d", uid, itemID, exi1, common.ItemStatusNormal), "", &common.PlayerItems{}, &list)
return list
}
// 获取力度最大的折扣券
func GetUserBestDiscountTicket(uid int) *common.PlayerItems {
list := []*common.PlayerItems{}
db.Mysql().QueryAll(fmt.Sprintf("uid = %d and item_id = %d and status = %d", uid, common.ItemDiscountTicket, common.ItemStatusNormal), "exi1 desc", &common.PlayerItems{}, &list)
if len(list) > 0 {
return list[0]
}
return nil
}
func AddUserDiscountTicket(uid, exi1 int) {
db.Mysql().Create(&common.PlayerItems{UID: uid, ItemID: common.ItemDiscountTicket, Time: time.Now().Unix(), Status: common.ItemStatusNormal, Exi1: exi1})
}

@ -0,0 +1,65 @@
package call
import (
"fmt"
"server/common"
"server/db"
"time"
"github.com/liangdas/mqant/log"
"gorm.io/gorm"
)
func checkMail(uid int, red *common.PlayerRed) {
data := &common.PlayerData{UID: uid}
db.Mysql().Get(data)
t := data.LastSysEmailDraw
all := []common.Mail{}
// mailCount := db.Mysql().QueryNewMailCount(uid)
mailCount := 0
db.Mysql().QueryAll(fmt.Sprintf("receiver = %v and time > %v", 0, t), "", &common.Mail{}, &all)
if len(all) > 0 {
now := time.Now().Unix()
u, err := db.Mysql().UpdateRes(&common.PlayerData{UID: uid, LastSysEmailDraw: data.LastSysEmailDraw}, &common.PlayerData{LastSysEmailDraw: now})
if err != nil || u == 0 {
log.Error("err:%v", err)
return
}
for _, v := range all {
one := v
one.ID = 0
one.Receiver = uid
db.Mysql().Create(&one)
mailCount++
}
if red.ID == 0 {
red.Mail = mailCount
db.Mysql().Create(red)
} else {
db.Mysql().Update(red, map[string]interface{}{"mail": gorm.Expr("mail + ?", mailCount)})
}
}
red.Mail += mailCount
}
const (
MailWithdrawType2 = "Your withdrawal order is already in payment. We've paid cash to bank, the final time is determined by the bank, please be patient!\nIf cash has not yet arrived, please click online customer service on the upper right corner or WhatsApp us at %v."
MailWithdrawType3 = "1.Please check your bank/UPI information and try to withdraw again: Bank IFSC Code is formatted as 'AAAA0XXXXXX'; there shouldn't be space in UPI account;\n2.If withdrawal still fails, please click online customer service on the upper right corner or WhatsApp us at %v."
)
func SendWithdrawMail(uid int, contentType string) {
one := &common.Mail{
Sender: "System",
Receiver: uid,
Title: "Withdraw Notice",
Content: fmt.Sprintf(contentType, GetConfigPlatform().Whatsapp),
Time: time.Now().Unix(),
}
db.Mysql().Create(one)
UpsertRedPointAndNotify(uid, 1, ModuleMail)
}
func SendMail(mail *common.Mail) {
db.Mysql().Create(mail)
UpsertRedPointAndNotify(mail.Receiver, 1, ModuleMail)
}

@ -0,0 +1,70 @@
package call
import (
"strconv"
"github.com/liangdas/mqant/registry"
"github.com/liangdas/mqant/selector"
)
func GetGameOriginID(id int) int {
return id / 100 * 100
}
// 选择器
var (
WorkIDSelector = func(nodeID string) selector.SelectOption {
return selector.WithFilter(func(services []*registry.Service) []*registry.Service {
// log.Debug("nodeID:%v", nodeID)
ret := []*registry.Service{}
for _, service := range services {
nodes := []*registry.Node{}
for _, node := range service.Nodes {
if node.Metadata["workID"] == nodeID {
// log.Debug("find node:%v", node)
nodes = append(nodes, node)
}
}
service.Nodes = nodes
ret = append(ret, service)
}
return ret
})
}
// 服务器版本选择器
VersionSelector = func(nodeID interface{}) selector.SelectOption {
return selector.WithFilter(func(services []*registry.Service) []*registry.Service {
origin := 0
switch t := nodeID.(type) {
case int:
origin = t
case string:
origin, _ = strconv.Atoi(t)
default:
return services
}
if origin >= 3000 {
origin = GetGameOriginID(origin)
}
version := GetServerVersion(origin)
// log.Debug("nodeID:%v,version:%v", nodeID, version)
if version == 0 {
return services
}
ret := []*registry.Service{}
for _, service := range services {
nodes := []*registry.Node{}
for _, node := range service.Nodes {
ver, _ := strconv.Atoi(node.Metadata["version"])
if ver == version {
// log.Debug("find node:%v", node)
nodes = append(nodes, node)
}
}
service.Nodes = nodes
ret = append(ret, service)
}
return ret
})
}
)

@ -0,0 +1,813 @@
package call
import (
"context"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"server/common"
"server/config"
"server/db"
"server/natsClient"
"server/pb"
"server/util"
"time"
"github.com/gogo/protobuf/proto"
"github.com/liangdas/mqant/log"
mqrpc "github.com/liangdas/mqant/rpc"
"gorm.io/gorm"
)
func GetRechargeInfo(uid int) *common.RechargeInfo {
info := &common.RechargeInfo{UID: uid}
err := db.Mysql().Get(info)
if err != nil {
return info
}
now := time.Now().Unix()
if !util.IsSameDayTimeStamp(now, info.LastRecharge) {
info.DayRecharge = 0
}
return info
}
// Recharge 内部充值调用
func Recharge(data *pb.InnerRechargeReq) (*pb.InnerRechargeResp, error) {
to, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
module := "pay"
if data.PaySource == common.PaySourceBlockPay {
module = "blockpay"
}
ret, err := GetCaller().GetApp().Call(to, module, "recharge", mqrpc.Param(data))
if err != "" {
return nil, errors.New(err)
}
retData := new(pb.InnerRechargeResp)
if err := proto.Unmarshal(ret.([]byte), retData); err != nil {
log.Error("err:%v", err)
return nil, err
}
return retData, nil
}
// Withdraw 内部退出调用
func Withdraw(data *pb.InnerWithdrawReq) (*pb.InnerWithdrawResp, error) {
log.Debug("withdraw req:%+v", *data)
to, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
module := "pay"
if data.PaySource == common.PaySourceBlockPay {
module = "blockpay"
}
ret, err := GetCaller().GetApp().Call(to, module, "withdraw", mqrpc.Param(data))
retData := new(pb.InnerWithdrawResp)
if data, ok := ret.([]byte); ok {
if err := proto.Unmarshal(data, retData); err != nil {
log.Error("err:%v", err)
}
}
if err != "" {
return retData, errors.New(err)
}
return retData, nil
}
// RechargeCallback 充值回调
func RechargeCallback(r *common.RechargeOrder, success bool, payAccount, extra string) (err error) {
log.Info("RechargeCallback:%+v,%v,%v,%v,", r, success, payAccount, extra)
if r == nil {
return errors.New("order invalid")
}
if !success {
ro := &common.RechargeOrder{OrderID: r.OrderID, Status: common.StatusROrderCreate}
return db.Mysql().Update(ro, &common.RechargeOrder{Status: common.StatusROrderFail})
}
uid := r.UID
re := new(common.RechargeInfo)
re.UID = uid
err = db.Mysql().Get(re)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
log.Error("get recharage info err:%v,uid:%v", err, r.UID)
return err
}
// product := GetConfigPayProductByID(r.ProductID)
// if product == nil {
// log.Error("unkonwn product:%d", r.ProductID)
// return errors.New("unkonwn product")
// }
amount := r.Amount
notCharge := re.TotalRecharge == 0
re.TotalRecharge += amount
now := time.Now().Unix()
// var dayR, weekR bool
var dayR bool
if util.IsSameDayTimeStamp(re.LastRecharge, now) || re.LastRecharge == 0 {
dayR = true
re.DayRecharge += amount
}
// if util.IsSameWeek(re.LastRecharge, now) || re.LastRecharge == 0 {
// weekR = true
// re.WeekRecharge += amount
// }
re.LastRecharge = now
re.TotalRechargeCount++
// re.ProductPayCount = common.AddProductPayCount(re.ProductPayCount, r.ProductID)
// if product.IsFirstPayProduct() {
// json.Unmarshal([]byte(re.ProductFirstPay), &re.ProductFirstPaySub)
// if util.SliceContain(re.ProductFirstPaySub, product.ProductID) { // 该商品已购买,替换为可多次购买的同价值商品
// product = GetConfigPayProductShopByAmount(product.Amount)
// if product == nil {
// return errors.New("product invalid")
// }
// } else {
// re.ProductFirstPaySub = append(re.ProductFirstPaySub, int(product.ProductID))
// str, _ := json.Marshal(re.ProductFirstPaySub)
// re.ProductFirstPay = string(str)
// }
// }
// var per int64 = 0
// level := GetConfigFirstPayLevelByAmount(r.Amount)
// playerPayData := GetPlayerPayData(uid)
tx := db.Mysql().Begin()
defer func() {
if err == nil {
if err := tx.Commit().Error; err != nil {
tx.Rollback()
return
}
} else {
log.Error("err:%v", err)
tx.Rollback()
return
}
}()
// 第一步,更新订单状态
updates := common.RechargeOrder{Status: common.StatusROrderPay, APIPayID: r.APIPayID, PayAccount: payAccount, Extra: extra, CallbackTime: now}
dbtx := tx.Table("recharge_order").Where(fmt.Sprintf("orderid = '%v' and status <> %v", r.OrderID, common.StatusROrderPay)).Updates(updates)
if dbtx.Error != nil {
return fmt.Errorf("update order err:%v", dbtx.Error)
}
// 已处理的单不返回错误了
if dbtx.RowsAffected == 0 {
return nil
}
// 更新paydata
// if playerPayData.ID == 0 {
// err = tx.Model(playerPayData).Create(playerPayData).Error
// if err != nil {
// log.Error("err:%v", err)
// return
// }
// } else {
// playerPayData.SubFirstPay = append(playerPayData.SubFirstPay, level)
// updatePayData, _ := json.Marshal(playerPayData.SubFirstPay)
// res := tx.Model(playerPayData).Where("id = ? and first_pay = ?", playerPayData.ID, playerPayData.FirstPay).Updates(map[string]interface{}{"first_pay": string(updatePayData)})
// if res.RowsAffected == 0 {
// log.Error("err:%v", err)
// return errors.New("update payData fail")
// }
// if err != nil {
// log.Error("update payData err:%v", err)
// return err
// }
// }
// 第二步,更新recharge_info
payData := &common.ESPlayerPayData{UID: uid, Channel: r.ChannelID, Type: 1, CurrencyType: r.CurrencyType}
if re.ID == 0 {
err = tx.Model(re).Create(re).Error
if err != nil {
// 说明数据库出问题或者两单并发回调,一分钟后重试
time.AfterFunc(1*time.Minute, func() {
RechargeCallback(r, success, payAccount, extra)
})
log.Error("err:%v", err)
return
}
payData.FirstAmount = amount
} else {
updates := map[string]interface{}{
"total_recharge_count": gorm.Expr("total_recharge_count + 1"),
"total_recharge": gorm.Expr("total_recharge + ?", amount),
"last_recharge": now,
// "product_paycount": re.ProductPayCount,
// "product_firstpay": re.ProductFirstPay,
}
if dayR {
updates["day_recharge"] = gorm.Expr("day_recharge + ?", amount)
} else {
updates["day_recharge"] = amount
}
// if weekR {
// updates["week_recharge"] = gorm.Expr("week_recharge + ?", amount)
// } else {
// updates["week_recharge"] = amount
// }
err = tx.Model(re).Where("uid=?", re.UID).Updates(updates).Error
}
if err != nil {
log.Error("recharge err:%v", err)
return err
}
// 第三步,给玩家发货
// 正常商城充值
var bonus int64
if r.ProductID == 0 {
amount := PayExtra(r) // 判断特殊购买,如优惠券
if amount == 0 {
amount = r.Amount
}
// cb := &common.CurrencyBalance{
// UID: r.UID,
// Type: r.CurrencyType,
// Value: amount,
// Event: common.CurrencyEvent(r.Event),
// Exs1: r.OrderID,
// Exi1: int(amount), // 充值金额传递
// Exi2: r.ProductID,
// NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceRecharge, amount),
// }
// err = UpdateCurrencyProReal(&common.UpdateCurrency{
// CurrencyBalance: cb,
// }).Err
// if err != nil {
// return
// }
// } else {
per := GetConfigFirstPayPerByAmount(notCharge, amount)
if per > 0 {
bonus = amount * per / 100
}
cb := &common.CurrencyBalance{
UID: r.UID,
Type: r.CurrencyType,
Value: amount + bonus,
Event: common.CurrencyEvent(r.Event),
Exs1: r.OrderID,
Exi1: int(amount), // 充值金额传递
Exi2: r.ProductID,
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceRecharge, amount) + GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, bonus),
}
err = UpdateCurrencyProReal(&common.UpdateCurrency{
CurrencyBalance: cb,
}).Err
if err != nil {
return
}
}
// 以上逻辑为处理订单,更新玩家充值信息,给玩家加钱。
// 下面逻辑处理活动,数据统计等,不影响以上效率,接下来逻辑并发执行
util.Go(func() {
// 更新活动数据上传
if bonus > 0 {
UploadActivityData(uid, common.ActivityIDRecharge, common.ActivityDataJoin, bonus)
}
user, _ := GetUserInfo(uid)
PayActivity(r, notCharge, user)
if r.Event != int(common.CurrencyEventGMRecharge) {
payData.Amount = amount
WritePlayerPayData(payData)
}
var uploads []func()
uploads = append(uploads, func() { UploadAdjust(common.AdjustEventAllPay, user, nil) })
// 24小时内注册的用户所有付费事件上报
if now-user.Birth <= 24*60*60 {
uploads = append(uploads, func() {
UploadAdjust(common.AdjustEventNewPay, user, map[string]string{"revenue": util.RoundFloat(float64(amount/1e6)/100, 2), "currency": "BRL"})
})
// 上报fb
UploadFB(uid, FBEventPurchase, amount/common.DecimalDigits)
UploadKwai(uid, KwaiEventPay, amount)
}
for _, f := range uploads {
f()
}
})
return nil
}
func WithdrawCallback(order *common.WithdrawOrder) error {
uid := order.UID
amount := order.Amount
var err error
// 不成功退款
if order.Status == common.StatusROrderFail {
err = ReturnBackWithdraw(order, common.StatusROrderFinish, common.StatusROrderFail)
} else {
tx := db.Mysql().Begin()
or := new(common.WithdrawOrder)
or.ID = order.ID
or.Status = uint8(common.StatusROrderFinish)
or.CallbackTime = time.Now().Unix()
or.APIPayID = order.APIPayID
or.FailReason = order.FailReason
if len(or.FailReason) > 200 {
or.FailReason = or.FailReason[:200]
}
res := tx.Model(or).Where("id = ? and status <> ?", or.ID, common.StatusROrderFinish).Updates(or)
if res.Error != nil {
log.Error("Withdraw callback err:%v", res.Error)
tx.Rollback()
return err
}
// 已处理的情况不返回错误了
if res.RowsAffected == 0 {
log.Error("Withdraw callback order:%v done", order.OrderID)
tx.Rollback()
return nil
}
rei := &common.RechargeInfo{UID: uid}
db.Mysql().Get(rei)
payData := &common.ESPlayerPayData{UID: uid, Channel: order.ChannelID, Amount: amount, Type: 2}
if rei.TotalWithdrawCount == 0 {
payData.FirstAmount = amount
}
WritePlayerPayData(payData)
u := map[string]interface{}{
"total_withdraw_count": gorm.Expr("total_withdraw_count + ?", 1),
"total_withdraw": gorm.Expr("total_withdraw + ?", order.Amount),
"total_withdrawing": gorm.Expr("total_withdrawing - ?", amount),
"withdrawing_cash": gorm.Expr("withdrawing_cash - ?", order.WithdrawCash),
}
err = tx.Model(rei).Where("uid = ?", uid).Updates(u).Error
if err != nil {
log.Error("BaseWithdraw err :%v", err)
tx.Rollback()
return err
}
// err = UpdatePlayerRechargeInfoCurrency(uid, order.CurrencyType, map[string]interface{}{
// "total_withdrawing": gorm.Expr("total_withdrawing - ?", order.WithdrawCash),
// "total_withdraw": gorm.Expr("total_withdraw + ?", order.Amount),
// }, tx)
// if err != nil {
// log.Error("BaseWithdraw err :%v", err)
// tx.Rollback()
// return err
// }
if err := tx.Commit().Error; err != nil {
log.Error("ZYWithdraw callback err:%v", err)
tx.Rollback()
return err
}
PublishWarn(WarnTypeWithdraw, 2, []int64{int64(order.ChannelID), int64(order.UID)})
con := GetBroadcastConfigWithID(common.BrocastIDWithdraw)
if con != nil {
up := con.ConditionUp
down := con.ConditionDown
if (amount <= int64(up) || up <= 0) && amount >= int64(down) {
BroadcastReq(con, fmt.Sprintf(con.Content, uid, amount))
}
}
// util.Go(func() {
// SendRealWithdrawMail(order)
// })
}
if err != nil {
return err
}
Publish(natsClient.TopicInnerPlayerWithdraw, &pb.InnerWithdrawCallback{UID: uint32(uid)})
return nil
}
// ReturnBackWithdraw 退出被拒绝或者失败,返还金币
func ReturnBackWithdraw(or *common.WithdrawOrder, originStatus, status uint8, payChannel ...int) error {
order := &common.WithdrawOrder{}
order.ID = or.ID
tx := db.Mysql().Begin()
u := map[string]interface{}{
"status": status,
"fail_reason": or.FailReason,
"callback_time": time.Now().Unix(),
}
if len(payChannel) > 0 {
u["pay_channel"] = payChannel[0]
}
if len(or.APIPayID) > 0 {
u["apipayid"] = or.APIPayID
}
update := tx.Model(order).Where("status <= ?", originStatus).Updates(u)
if update.Error != nil {
log.Error("err:%v", update.Error)
tx.Rollback()
return update.Error
}
// 已处理的情况不返回错误了
if update.RowsAffected == 0 {
err := fmt.Errorf("update fail:%+v", or)
log.Error("err:%v", err)
tx.Rollback()
return nil
}
uid := or.UID
re := new(common.RechargeInfo)
re.UID = uid
updateRe := map[string]interface{}{
"withdrawing_cash": gorm.Expr("withdrawing_cash - ?", or.WithdrawCash),
"total_withdrawing": gorm.Expr("total_withdrawing - ?", or.Amount),
"day_withdraw": gorm.Expr("day_withdraw - ?", or.Amount),
}
if status == common.StatusROrderFail {
updateRe["withdraw_count"] = gorm.Expr("withdraw_count + ?", -1)
}
err := tx.Model(re).Where("uid = ? and withdrawing_cash >= ? and total_withdrawing >= ?", or.UID, or.WithdrawCash, or.Amount).
Updates(updateRe).Error
if err != nil {
log.Error("err :%v", err)
tx.Rollback()
return err
}
if err := UpdateCurrency(&common.UpdateCurrency{
CurrencyBalance: &common.CurrencyBalance{
UID: or.UID,
Type: or.CurrencyType,
Value: or.WithdrawCash,
Event: common.CurrencyEventWithDrawBack,
Exs1: or.OrderID,
},
}, tx); err != nil {
log.Error("Withdraw callback err:%v", err)
tx.Rollback()
return err
}
// 退还代付券
// if or.Extra == "useFreeWithdraw" {
// if err := tx.Model(&common.PlayerItems{UID: uid}).Updates(map[string]interface{}{"free_withdraw": gorm.Expr("free_withdraw + 1")}).Error; err != nil {
// log.Error("err:%v", err)
// tx.Rollback()
// return err
// }
// }
if err := tx.Commit().Error; err != nil {
log.Error("err:%v", err)
tx.Rollback()
return err
}
// 失败的时候才发送邮件
// if status == common.StatusROrderFail {
// util.Go(func() {
// SendWithdrawMail(uid, MailWithdrawType3)
// SendRealWithdrawMail(or)
// })
// }
return nil
}
func WritePlayerPayData(data *common.ESPlayerPayData) {
data.Time = time.Now().Unix()
ret, _ := GetUserXInfo(data.UID, "birth")
data.IsNew = IsNewPlayer(ret.Birth)
data.IsNew = util.IsSameDayTimeStamp(ret.Birth, data.Time)
db.ES().InsertToESGO(common.ESIndexBackPlayerPayData, data)
}
// PayExtra 支付extra字段判断
func PayExtra(r *common.RechargeOrder) (amount int64) {
if len(r.Extra) == 0 {
return
}
extraData := &common.ActivityRechargeData{}
json.Unmarshal([]byte(r.Extra), extraData)
switch extraData.ID {
case common.ItemDiscountTicket:
list := GetUserItemByExi1(r.UID, common.ItemDiscountTicket, extraData.I1)
if len(list) == 0 {
return
}
item := list[0]
rows, err := db.Mysql().UpdateRes(&common.PlayerItems{ID: item.ID, Status: common.ItemStatusNormal},
map[string]interface{}{"status": common.ItemStatusInvalid})
if err != nil || rows == 0 {
log.Error("err:%v", err)
return
}
amount = extraData.I2
}
return
}
// PayActivity 支付活动
func PayActivity(r *common.RechargeOrder, notCharge bool, user *common.PlayerDBInfo) (err error) {
// VIP
UpdateVip(r.UID, r.Amount, 0, 0)
// 检查任务
CheckTask(r)
// 检查所有活动
CheckAllActivity(r)
// 更新loginrecord
if notCharge {
InsertLoginRecord(r.UID, r.ChannelID, user.IP, user.Birth, user.Platform)
CheckShare(r)
}
return nil
}
func CheckTask(r *common.RechargeOrder) {
now := time.Now().Unix()
con := GetConfigTask()
for _, v := range con {
if (v.Type == common.TaskTypeOnceRecharge || v.Type == common.TaskTypeFirstRecharge) && r.Amount >= v.Target { // 单次充值任务 || 首次充值任务
data := GetUserTaskDataByTaskID(r.UID, v.TaskID)
if data.ID == 0 {
db.Mysql().Create(&common.TaskData{UID: r.UID, TaskID: v.TaskID, Time: now, Progress: v.Target})
} else if data.Progress == 0 {
db.Mysql().Update(&common.TaskData{UID: r.UID, TaskID: v.TaskID}, map[string]interface{}{"progress": v.Target, "time": now})
}
} else if v.Type == common.TaskTypeTotalRecharge { // 累充任务
data := GetUserTaskDataByTaskID(r.UID, v.TaskID)
if data.ID == 0 {
db.Mysql().Create(&common.TaskData{UID: r.UID, TaskID: v.TaskID, Time: now, Progress: r.Amount})
} else if data.Progress >= 0 {
db.Mysql().Update(&common.TaskData{UID: r.UID, TaskID: v.TaskID}, map[string]interface{}{"progress": gorm.Expr("progress + ?", r.Amount), "time": now})
}
}
}
}
func ActivityFirstRechargeBack(r *common.RechargeOrder) {
now := time.Now().Unix()
if IsActivityValid(common.ActivityIDFirstRechargeBack) {
rechargeBackData := GetUserFirstRechargeBackData(r.UID)
if rechargeBackData.RechargeTime == 0 {
db.Mysql().Create(&common.ActivityFirstRechargeBackData{UID: r.UID, RechargeTime: time.Now().Unix(), Amount: r.Amount})
} else if now-rechargeBackData.RechargeTime < common.ActivityFirstRechargeBackTime {
db.Mysql().Update(&common.ActivityFirstRechargeBackData{UID: r.UID}, map[string]interface{}{"amount": gorm.Expr("amount + ?", r.Amount)})
}
}
}
func CheckAllActivity(r *common.RechargeOrder) {
// 首充返还活动
ActivityFirstRechargeBack(r)
var product *common.ConfigPayProduct
if r.ProductID > 0 {
product = GetConfigPayProductByID(r.ProductID)
}
// slots奖池活动
ActivitySlots(r, product)
if product == nil {
return
}
switch product.ActivityID {
case common.ActivityIDBreakGift:
ActivityBreakGift(r, product)
case common.ActivityIDWeekCard:
ActivityWeekCard(r, product)
case common.ActivityIDLuckyShop:
ActivityLuckyShop(r, product)
case common.ActivityIDSevenDayBox:
ActivitySevenDayBox(r, product)
case common.ActivityIDSuper:
ActivitySuper(r, product)
}
}
func ActivityBreakGift(r *common.RechargeOrder, product *common.ConfigPayProduct) {
payData := GetPlayerPayData(r.UID)
gift := GetConfigActivityBreakGiftByProductID(r.ProductID)
if util.SliceContain(payData.SubBreakGift, gift.Level) {
return
}
payData.SubBreakGift = append(payData.SubBreakGift, gift.Level)
str, _ := json.Marshal(payData.SubBreakGift)
rows, err := db.Mysql().UpdateRes(&common.PlayerPayData{UID: r.UID, BreakGift: payData.BreakGift}, map[string]interface{}{"break_gift": string(str)})
if rows == 0 || err != nil {
log.Error("err:%v", err)
return
}
// ok
UpdateCurrencyPro(&common.UpdateCurrency{
CurrencyBalance: &common.CurrencyBalance{
UID: r.UID,
Value: product.Value,
Event: common.CurrencyEventActivityBreakGift,
Type: common.CurrencyBrazil,
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, product.Value),
ChannelID: r.ChannelID,
Exi1: product.ProductID,
},
})
UploadActivityData(r.UID, common.ActivityIDBreakGift, common.ActivityDataJoin, product.Value)
}
func ActivityWeekCard(r *common.RechargeOrder, product *common.ConfigPayProduct) {
level := product.Exi
card := GetUserWeekCard(r.UID, level)
con := GetConfigActivityWeekCardByLevel(level)
if con == nil {
return
}
if card.ID == 0 {
err := db.Mysql().Create(&common.ActivityWeekCardData{
UID: r.UID,
Level: level,
DayReward: con.DayReward,
Day: con.Day,
// LastDraw: time.Now().Unix(),
})
if err != nil {
return
}
} else {
if card.Day > 0 {
return
}
rows, err := db.Mysql().UpdateResW(&common.ActivityWeekCardData{}, map[string]interface{}{
"day": con.Day, "day_reward": con.DayReward, "get_discount": 0, "last_draw": 0},
fmt.Sprintf("uid = %d and level = %d and day = 0", r.UID, level))
if err != nil || rows == 0 {
log.Error("err:%v", err)
return
}
}
// ok
UpdateCurrencyPro(&common.UpdateCurrency{
CurrencyBalance: &common.CurrencyBalance{
UID: r.UID,
Value: product.Value,
Event: common.CurrencyEventActivityWeekCard,
Type: common.CurrencyBrazil,
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, product.Value),
ChannelID: r.ChannelID,
Exi1: product.ProductID,
},
})
UploadActivityData(r.UID, common.ActivityIDWeekCard, common.ActivityDataJoin, product.Value)
}
func ActivityLuckyShop(r *common.RechargeOrder, product *common.ConfigPayProduct) {
rows, err := db.Mysql().UpdateResW(&common.ActivityLuckyShopData{}, map[string]interface{}{"buy": 1},
fmt.Sprintf("uid = %d and product_id = %d and buy = 0", r.UID, product.ProductID))
value := product.Value
if rows == 0 || err != nil {
// 直接给玩家按商品原价加钱
value = r.Amount
}
UpdateCurrencyProReal(&common.UpdateCurrency{
CurrencyBalance: &common.CurrencyBalance{
UID: r.UID,
Type: r.CurrencyType,
Value: value,
Event: common.CurrencyEvent(r.Event),
Exs1: r.OrderID,
Exi1: int(r.Amount), // 充值金额传递
Exi2: r.ProductID,
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, value),
},
})
UploadActivityData(r.UID, common.ActivityIDLuckyShop, common.ActivityDataJoin, product.Value)
}
func ActivitySlots(r *common.RechargeOrder, product *common.ConfigPayProduct) {
if !IsActivityValid(common.ActivityIDSlots) {
return
}
if product != nil && product.ActivityID == common.ActivityIDSlots {
if product.Exi > 0 {
UpdateUserActivitySlotsData(r.UID, int(product.Exi))
}
UpdateCurrencyProReal(&common.UpdateCurrency{
CurrencyBalance: &common.CurrencyBalance{
UID: r.UID,
Type: r.CurrencyType,
Value: product.Value,
Event: common.CurrencyEvent(r.Event),
Exs1: r.OrderID,
Exi1: int(r.Amount), // 充值金额传递
Exi2: r.ProductID,
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, product.Value),
},
})
return
}
count := r.Amount / 1000000000
if count >= 1 {
UpdateUserActivitySlotsData(r.UID, int(count))
}
}
func ActivitySevenDayBox(r *common.RechargeOrder, product *common.ConfigPayProduct) {
data := &common.ActivitySevenDayBoxData{UID: r.UID}
db.Mysql().Get(data)
now := time.Now().Unix()
value := product.Value
if util.IsSameDayTimeStamp(now, data.Time) { // 一天只能买一次
value = r.Amount
} else {
if data.ID == 0 {
data.Time = now
data.Count = 1
err := db.Mysql().Create(data)
if err != nil {
value = r.Amount
}
} else {
rows, err := db.Mysql().UpdateResW(&common.ActivitySevenDayBoxData{}, map[string]interface{}{"count": gorm.Expr("count + 1"), "time": now},
fmt.Sprintf("uid = %d and count = %d and time = %d", r.UID, data.Count, data.Time))
if rows == 0 || err != nil {
// 直接给玩家按商品原价加钱
value = r.Amount
}
}
}
if value > 0 {
UpdateCurrencyProReal(&common.UpdateCurrency{
CurrencyBalance: &common.CurrencyBalance{
UID: r.UID,
Type: r.CurrencyType,
Value: value,
Event: common.CurrencyEvent(r.Event),
Exs1: r.OrderID,
Exi1: int(r.Amount), // 充值金额传递
Exi2: r.ProductID,
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, value),
},
})
}
}
func ActivitySuper(r *common.RechargeOrder, product *common.ConfigPayProduct) {
data := GetUserActivitySuperData(r.UID)
value := product.Value
if !data.CanBuy {
value = r.Amount
} else {
rows, err := db.Mysql().UpdateResW(&common.ActivitySuperData{}, map[string]interface{}{"open": 0, "time": time.Now().Unix()},
fmt.Sprintf("uid = %d and time = %d", r.UID, data.Time))
if rows == 0 || err != nil {
log.Error("err:%v", err)
value = r.Amount
}
}
if value > 0 {
UpdateCurrencyProReal(&common.UpdateCurrency{
CurrencyBalance: &common.CurrencyBalance{
UID: r.UID,
Type: r.CurrencyType,
Value: value,
Event: common.CurrencyEvent(r.Event),
Exs1: r.OrderID,
Exi1: int(r.Amount), // 充值金额传递
Exi2: r.ProductID,
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, value),
},
})
}
}
type IFSCRet struct {
Ifsc string `json:"IFSC"`
}
func CheckIFSC(ifsc string) bool {
ret := &IFSCRet{}
client := http.Client{
Timeout: 2 * time.Second,
}
url := config.GetConfig().Web.IFSCURL + "/" + ifsc
log.Debug("url:%v", url)
resp, err := client.Get(url)
if err != nil {
log.Error("get err:%v", err)
return true
}
// if resp.StatusCode != http.StatusOK {
// log.Error("req fail err code:%v", resp.StatusCode)
// return true
// }
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Error("read err %v", err)
return true
}
json.Unmarshal(data, ret)
return ret.Ifsc != ""
}
func GetTotalRechargePer(thisWithdraw int64) int64 {
zero := util.GetZeroTime(time.Now()).Unix()
recharge := db.Mysql().Sum(&common.RechargeOrder{}, fmt.Sprintf("create_time >= %d and event = %d and status = %d", zero, common.CurrencyEventReCharge, common.StatusROrderPay), "amount")
withdraw := db.Mysql().Sum(&common.WithdrawOrder{}, fmt.Sprintf("create_time >= %d and event = %d and status = %d", zero, common.CurrencyEventWithDraw, common.StatusROrderFinish), "amount")
withdraw += thisWithdraw
if recharge == 0 {
return withdraw * 100 / common.DecimalDigits
}
return withdraw * 100 / recharge
}

@ -0,0 +1,38 @@
package call
import (
"server/common"
"server/pb"
"strconv"
"strings"
"github.com/liangdas/mqant/log"
)
func GetModuleName(id int) string {
if id == 1000 {
return "hall"
}
if id == 1100 {
return "common"
}
if id == 1101 {
return "matching"
}
return common.GetGameModuleName(id)
}
func GetModuleID(name string) int {
if name == "hall" {
return int(pb.ServerType_ServerTypeGate)
}
if name == "common" {
return int(pb.ServerType_ServerTypeCommon)
}
name = strings.ReplaceAll(name, common.GameModulePrefix, "")
id, err := strconv.Atoi(name)
if err != nil {
log.Error("err:%v", err)
}
return id
}

@ -0,0 +1,47 @@
package call
import "server/util"
var (
execQueue = NewQueue()
)
// 顺序执行并发操作
func InitExecQueue() {
execQueue.Run()
}
func AddQueue(f func()) {
execQueue.AddQueue(f)
}
type ExecQueue struct {
c chan func()
}
func (e *ExecQueue) Run() {
util.Go(func() {
for {
f := <-e.c
func() {
defer util.Recover()
f()
}()
}
})
}
func (e *ExecQueue) AddQueue(f func()) {
e.c <- f
}
func NewQueue(size ...int) *ExecQueue {
e := &ExecQueue{}
if size != nil {
e.c = make(chan func(), size[0])
} else {
e.c = make(chan func(), 10000)
}
e.Run()
return e
}

@ -0,0 +1,203 @@
package call
import (
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"math/rand"
"net/smtp"
"server/common"
"server/config"
"server/db"
"strings"
"time"
"github.com/liangdas/mqant/log"
)
const (
RealMailSuccessTitle = "Withdrawal succeeded! [%v]"
RealMailSuccessContext = "Deal %v:\n" +
"\n" +
"Congratulations! Your latest withdrawal has been successfully transferred to your bank account. Please check your account." +
"If there is any question about this order, please feel free to contact our customer service below.\n" +
"\n" +
"Email:%v\n" +
"\n" +
"Whatsapp:%v\n" +
"\n" +
"Thanks for your playing!\n" +
"\n" +
"\n" +
"Best wishes\n" +
"\n" +
"%v"
RealMailFailTitle = "Withdrawal failure! [%v]"
RealMailFailContext = "Deal %v:\n" +
"\n" +
"Important information about your withdrawal order:\n" +
"\n" +
"AccountName:%v\n" +
"\n" +
"Mobile:%v\n" +
"\n" +
"%v\n" +
"\n" +
"Your latest withdrawal order has failed for the following reasons:\n" +
"\n" +
"\t1.Wrong UPI/BANK information you submitted. Please CAREFULLY check your UPI/BANK information and try to withdraw again:\n" +
"\n" +
"\t\t(1) The UPI/BANK account shall not have any space;\n" +
"\t\t(2) The bank IFSC Code shall be 11 digital letters formatted as 'AAAA0XXXXXX;\n" +
"\n" +
"\t2.Bank refused. The bank refused this order because of your bank account problems.\n" +
"\n" +
"If withdrawal still fails after all your information was checked, please get in touch with customer service:\n" +
"\n" +
"\t1.Email:%v\n" +
"\t2.Whatsapp:%v\n" +
"\n" +
"Do not worry! The refunds of the withdrawal order that failed will be returned to your game account.\n" +
"\n" +
"\n" +
"Kind regards\n" +
"\n" +
"%v"
)
type realMail struct {
user string
passwd string
}
// 初始化用户名和密码
func NewMail(u string, p string) *realMail {
temp := &realMail{user: u, passwd: p}
return temp
}
// 标题 文本 目标邮箱
func (m *realMail) Send(title string, text string, toId string) error {
auth := smtp.PlainAuth("", m.user, m.passwd, "smtp.gmail.com")
tlsconfig := &tls.Config{
InsecureSkipVerify: true,
ServerName: "smtp.gmail.com",
}
conn, err := tls.Dial("tcp", "smtp.gmail.com:465", tlsconfig)
if err != nil {
log.Error("real:%+v,err:%v", *m, err)
return err
}
client, err := smtp.NewClient(conn, "smtp.gmail.com")
if err != nil {
log.Error("real:%+v,err:%v", *m, err)
return err
}
if err = client.Auth(auth); err != nil {
log.Error("real:%+v,err:%v", *m, err)
return err
}
if err = client.Mail(m.user); err != nil {
log.Error("real:%+v,err:%v", *m, err)
return err
}
if err = client.Rcpt(toId); err != nil {
log.Error("real:%+v,toId:%v,err:%v", *m, toId, err)
return err
}
w, err := client.Data()
if err != nil {
log.Error("real:%+v,err:%v", *m, err)
return err
}
msg := fmt.Sprintf("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s", m.user, toId, title, text)
_, err = w.Write([]byte(msg))
if err != nil {
log.Error("real:%+v,err:%v", *m, err)
return err
}
err = w.Close()
if err != nil {
log.Error("real:%+v,err:%v", *m, err)
return err
}
client.Quit()
return nil
}
// SendRealWithdrawMail 给玩家真实的邮箱发送邮件
func SendRealWithdrawMail(or *common.WithdrawOrder) error {
withdrawCommon := &common.WithdrawCommon{}
if err := json.Unmarshal([]byte(or.PayAccount), withdrawCommon); err != nil {
log.Error("err:%v", err)
return err
}
if withdrawCommon.Email == "" {
log.Error("or:%+v,withdrawCommon:%+v,email is null", or, withdrawCommon)
return fmt.Errorf("or:%+v,email is null", or)
}
if strings.Contains(GetConfigPlatform().Email, withdrawCommon.Email) {
return nil
}
accounts := config.GetBase().Mails.Accounts
if len(accounts) == 0 {
return nil
}
channel := GetChannelByID(or.ChannelID)
if channel == nil {
return errors.New("unknown channel")
}
title := ""
context := ""
status := 0
if or.Status == common.StatusROrderFail {
status = 0
payInfo := ""
// if withdrawCommon.DrawType == common.WithdrawTypeUPI {
// payInfo = fmt.Sprintf("UPI Account:%v", withdrawCommon.BankCode)
// } else if withdrawCommon.DrawType == common.WithdrawTypeBank {
// payInfo = fmt.Sprintf("BankCard Number:%v\n\nIFSC Code:%v", withdrawCommon.BankCardNo, withdrawCommon.BankCode)
// }
title = fmt.Sprintf(RealMailFailTitle, channel.Name)
context = fmt.Sprintf(RealMailFailContext, withdrawCommon.Name, withdrawCommon.Name,
withdrawCommon.Mobile, payInfo, GetConfigPlatform().Email, GetConfigPlatform().Whatsapp, channel.Name)
} else if or.Status == common.StatusROrderFinish {
status = 1
title = fmt.Sprintf(RealMailSuccessTitle, channel.Name)
context = fmt.Sprintf(RealMailSuccessContext, withdrawCommon.Name, GetConfigPlatform().Email,
GetConfigPlatform().Whatsapp, channel.Name)
}
if db.Redis().Exist(common.GetRedisKeyRealMail(or.UID, status)) {
return nil
}
pass := config.GetBase().Mails.Pass
rans := rand.Perm(len(accounts))
// 只尝试一次
for i := 0; i < 1; i++ {
index := rans[i]
if index > len(pass)-1 {
break
}
m := NewMail(accounts[index], pass[index])
if err := m.Send(title, context, withdrawCommon.Email); err == nil {
// 每24小时同类型邮件只发送一次
db.Redis().SetData(common.GetRedisKeyRealMail(or.UID, status), 1, 24*time.Hour)
return nil
}
}
return errors.New("send fail")
}

@ -0,0 +1,53 @@
package call
import (
"fmt"
"reflect"
"server/common"
"server/db"
"server/pb"
"strings"
"gorm.io/gorm"
)
const (
ModuleMail = "Mail"
)
// UpsertRedPointAndNotify 更新红点并通知客户端
func UpsertRedPointAndNotify(uid, num int, module string) {
red := &common.PlayerRed{UID: uid}
db.Mysql().Get(red)
val := reflect.ValueOf(red).Elem().FieldByName(module)
diff := int(val.Int()) + num
if red.ID == 0 {
if diff < 0 {
diff = 0
}
val.SetInt(int64(diff))
db.Mysql().Create(red)
} else {
update := map[string]interface{}{}
if num == 0 || diff <= 0 {
update[module] = 0
val.SetInt(0)
} else {
update[module] = gorm.Expr(fmt.Sprintf("%v + ?", strings.ToLower(module)), num)
val.SetInt(int64(diff))
}
db.Mysql().Update(&common.PlayerRed{UID: uid}, update)
}
send := &pb.RedPoint{}
reflect.ValueOf(send).Elem().FieldByName(module).SetUint(uint64(diff))
SendNR(uid, int(pb.ServerCommonResp_CommonRedPointResp), send, "common")
}
func PushRed(uid int) {
redPoints := &common.PlayerRed{UID: uid}
db.Mysql().Get(redPoints)
checkMail(uid, redPoints)
one := new(pb.RedPoint)
one.Mail = uint32(redPoints.Mail)
SendNR(uid, int(pb.ServerCommonResp_CommonRedPointResp), one, "common")
}

@ -0,0 +1,442 @@
package call
import (
"server/common"
"server/natsClient"
"server/pb"
"github.com/liangdas/mqant/log"
"github.com/nats-io/nats.go"
)
var (
reloadFuncs = map[int][]func(*pb.ReloadGameConfig) error{}
)
func LoadConfigs(funcs map[int][]func(*pb.ReloadGameConfig) error) error {
if funcs == nil {
funcs = map[int][]func(*pb.ReloadGameConfig) error{}
}
CommonReload(funcs)
for _, v := range funcs {
for _, k := range v {
if err := k(nil); err != nil {
log.Error("err:%v", err)
// return err
}
}
}
reloadFuncs = funcs
return nil
}
// LoadSomeConfigs 加载特定配置
func LoadSomeConfigs(funcs map[int][]func(*pb.ReloadGameConfig) error) error {
for _, v := range funcs {
for _, k := range v {
if err := k(nil); err != nil {
log.Error("err:%v", err)
return err
}
}
}
reloadFuncs = funcs
return nil
}
func InitReload(conn *nats.Conn) {
natsClient.NewReloadNats(conn, ReloadConfig)
}
func ReloadConfig(c *pb.ReloadGameConfig) {
log.Debug("reload %v", c.Type)
if fs, ok := reloadFuncs[int(c.Type)]; ok {
for _, v := range fs {
if err := v(c); err != nil {
log.Error("err:%v", err)
return
}
}
}
}
func CommonReload(c map[int][]func(*pb.ReloadGameConfig) error) {
if _, ok := c[common.ReloadWhiteList]; !ok {
c[common.ReloadWhiteList] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := InitWhite(); err != nil {
log.Error("err:%v", err)
return err
}
return nil
}}
}
if _, ok := c[common.ReloadChannel]; !ok {
c[common.ReloadChannel] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadChannels(); err != nil {
log.Error("err:%v", err)
return err
}
return nil
}}
}
if _, ok := c[common.ReloadPlatform]; !ok {
c[common.ReloadPlatform] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigPlatform(); err != nil {
log.Error("err:%v", err)
return err
}
return nil
}}
}
if _, ok := c[common.ReloadNotice]; !ok {
c[common.ReloadNotice] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigNotice(); err != nil {
log.Error("从mysql加载公告失败, error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadBroadcast]; !ok {
c[common.ReloadBroadcast] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigBroadcast(); err != nil {
log.Error("从mysql加载广播失败, error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigActivity]; !ok {
c[common.ReloadConfigActivity] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigActivity(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigPayProduct]; !ok {
c[common.ReloadConfigPayProduct] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigPayProduct(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigPayWeight]; !ok {
c[common.ReloadConfigPayWeight] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigPayChannels(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigWithdrawWeight]; !ok {
c[common.ReloadConfigWithdrawWeight] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigWithdrawChannels(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigVip]; !ok {
c[common.ReloadConfigVip] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigVIP(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigTron]; !ok {
c[common.ReloadConfigTron] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigTron(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigWithdrawProduct]; !ok {
c[common.ReloadConfigWithdrawProduct] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigWithdrawProduct(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigGameProvider]; !ok {
c[common.ReloadConfigGameProvider] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadGames(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigGameList]; !ok {
c[common.ReloadConfigGameList] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadGames(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigGameTypes]; !ok {
c[common.ReloadConfigGameTypes] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigGameTypes(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigGameMarks]; !ok {
c[common.ReloadConfigGameMarks] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigGameMarks(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigFirstPageGames]; !ok {
c[common.ReloadConfigFirstPageGames] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigFirstPageGames(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigRWPer]; !ok {
c[common.ReloadConfigRWPer] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigRWPer(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigCurrencyRateUSD]; !ok {
c[common.ReloadConfigCurrencyRateUSD] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigCurrencyRateUSD(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigServerVersion]; !ok {
c[common.ReloadConfigServerVersion] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadServerVersions(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigGameRoom]; !ok {
c[common.ReloadConfigGameRoom] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigGameRooms(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigRobot]; !ok {
c[common.ReloadConfigRobot] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigRobots(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigAppSpin]; !ok {
c[common.ReloadConfigAppSpin] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigAppSpin(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigShare]; !ok {
c[common.ReloadConfigShare] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigShare(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigShareSys]; !ok {
c[common.ReloadConfigShareSys] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigShareSys(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigActivityPddSpin]; !ok {
c[common.ReloadConfigActivityPddSpin] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigActivityPddSpin(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigActivityPdd]; !ok {
c[common.ReloadConfigActivityPdd] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigActivityPdd(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigTask]; !ok {
c[common.ReloadConfigTask] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigTask(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigCurrencyResource]; !ok {
c[common.ReloadConfigCurrencyResource] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigCurrencyResource(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigFirstPay]; !ok {
c[common.ReloadConfigFirstPay] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigFirstPay(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigActivityFreeSpin]; !ok {
c[common.ReloadConfigActivityFreeSpin] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigActivityFreeSpin(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigActivityFirstRechargeBack]; !ok {
c[common.ReloadConfigActivityFirstRechargeBack] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigActivityFirstRechargeBack(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigBanner]; !ok {
c[common.ReloadConfigBanner] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigBanner(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigLuckyCode]; !ok {
c[common.ReloadConfigLuckyCode] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigActivityLuckCode(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigActivitySign]; !ok {
c[common.ReloadConfigActivitySign] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigActivitySign(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigActivityBreakGift]; !ok {
c[common.ReloadConfigActivityBreakGift] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigActivityBreakGift(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigShareRobot]; !ok {
c[common.ReloadConfigShareRobot] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigShareRobot(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigActivityWeekCard]; !ok {
c[common.ReloadConfigActivityWeekCard] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigActivityWeekCard(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigActivitySlots]; !ok {
c[common.ReloadConfigActivitySlots] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigActivitySlots(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigActivityLuckyShop]; !ok {
c[common.ReloadConfigActivityLuckyShop] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigActivityLuckyShop(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigServerFlag]; !ok {
c[common.ReloadConfigServerFlag] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigServerFlag(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
if _, ok := c[common.ReloadConfigActivitySevenDayBox]; !ok {
c[common.ReloadConfigActivitySevenDayBox] = []func(*pb.ReloadGameConfig) error{func(rgc *pb.ReloadGameConfig) error {
if err := LoadConfigActivitySevenDayBox(); err != nil {
log.Error("error : [%s]", err.Error())
return err
}
return nil
}}
}
}

@ -0,0 +1,155 @@
package call
import (
"context"
"fmt"
"server/common"
"server/db"
"server/natsClient"
"server/pb"
"server/util"
"strconv"
"github.com/gogo/protobuf/proto"
"github.com/liangdas/mqant/gate"
basegate "github.com/liangdas/mqant/gate/base"
"github.com/liangdas/mqant/log"
"github.com/liangdas/mqant/module"
mqrpc "github.com/liangdas/mqant/rpc"
"github.com/liangdas/mqant/selector"
)
var (
caller module.Module
)
// NewCaller 新建一个调用对象
func NewCaller(m module.Module) {
caller = m
}
func GetCaller() module.Module {
return caller
}
func GetTopicName() string {
name := caller.GetType()
return name
}
// SendSS 给玩家发送消息
func SendSS(session gate.Session, pid int, data proto.Message, t ...string) error {
payload := []byte{}
var err error
if data != nil {
payload, err = proto.Marshal(data)
if err != nil {
log.Error("err:%v", err)
return err
}
}
moduleName := ""
if t != nil {
moduleName = t[0]
} else {
moduleName = GetTopicName()
}
// moduleType := pb.ServerType_name[pb.ModuleType_value[moduleName]]
// moduleType := GetModuleID(moduleName)
topic := fmt.Sprintf("%v:%v", moduleName, strconv.Itoa(pid))
// log.Debug("topic:%v", topic)
session.SendNR(topic, payload)
return nil
}
// SendSSBytes 给玩家发送消息
func SendSSBytes(session gate.Session, pid int, payload []byte) error {
// moduleType := GetModuleID(caller.GetType())
// moduleType := pb.ServerType_name[pb.ModuleType_value[caller.GetType()]]
topic := fmt.Sprintf("%v:%v", GetTopicName(), pid)
session.SendNR(topic, payload)
return nil
}
// SendNR 给玩家发送消息 注意:必须先调用NewCaller初始化
func SendNR(uid int, pid int, data proto.Message, t ...string) {
util.Go(func() {
payload, err := proto.Marshal(data)
if err != nil {
log.Error("err:%v", err)
return
}
moduleName := ""
if t != nil {
moduleName = t[0]
} else {
moduleName = GetTopicName()
}
// moduleType := GetModuleID(moduleName)
// moduleType := pb.ServerType_name[pb.ModuleType_value[moduleName]]
topic := fmt.Sprintf("%v:%v", moduleName, pid)
g := GetUserSession(uid)
if g == nil {
// log.Error("get session fail")
return
}
if err := g.Send(topic, payload); err != "" {
log.Error("err:%v", err)
return
}
})
}
// Publish 发布消息
func Publish(topic string, data proto.Message) error {
send, _ := proto.Marshal(data)
err := caller.GetApp().Transport().Publish(topic, send)
if err != nil {
log.Error("err:%v", err)
return err
}
return nil
}
// Publish 发布消息
func PublishRequest(topic, reply string, data proto.Message) error {
send, _ := proto.Marshal(data)
return caller.GetApp().Transport().PublishRequest(topic, reply, send)
}
// RPC 服务器内部调用
func RPC(module, method string, param proto.Message, opts ...selector.SelectOption) (interface{}, string) {
return caller.GetApp().Call(context.Background(), module, method, mqrpc.Param(param), opts...)
}
func GetUserSession(uid int) gate.Session {
s := db.Redis().GetUserSession(uid)
if s == nil {
// log.Error("get session fail")
return nil
}
g, _ := basegate.NewSession(caller.GetApp(), nil)
g.SetSessionID(s.SessionID)
g.SetServerID(s.GateID)
g.SetUserID(strconv.Itoa(uid))
return g
}
// Broadcast 发送广播
func BroadcastReq(one *common.ConfigBroadcast, content ...string) {
c := one.Content
for _, v := range content {
c = v
}
data := &pb.InnerBroadcast{
ID: int32(one.ID),
Content: c,
Priority: int32(one.Priority),
Frequency: int32(one.LoopFrequency),
Interval: int32(one.Interval),
}
// log.Debug("broadcastReq:%+v", data)
send, _ := proto.Marshal(data)
caller.GetApp().Transport().Publish(natsClient.TopicBroadcastReq, send)
}

@ -0,0 +1,156 @@
package call
import (
"fmt"
"reflect"
"server/common"
"server/db"
"server/pb"
"server/util"
"time"
"github.com/liangdas/mqant/log"
"gorm.io/gorm"
)
func GetShareInfo(uid int) *common.ShareInfo {
shareInfo := &common.ShareInfo{UID: uid}
db.Mysql().Get(shareInfo)
if shareInfo.ID <= 0 {
info, _ := GetUserXInfo(uid, "channel_id")
shareInfo.ChannelID = info.ChannelID
shareInfo.Share = util.GetShareCode(uid)
shareInfo.Time = time.Now().Unix()
db.Mysql().Create(shareInfo)
}
return shareInfo
}
// 分享查询
func ShareBind(share string, isOld bool, uid, cid int) {
// 绑定
if share == "" || isOld {
return
}
// 一级
upInfo := &common.ShareInfo{Share: share}
db.Mysql().Get(upInfo)
if upInfo.ID <= 0 {
return
}
shareInfo := &common.ShareInfo{UID: uid, UP1: upInfo.UID, UP2: upInfo.UP1, UP3: upInfo.UP2, Time: time.Now().Unix(), ChannelID: cid, Share: util.GetShareCode(uid)}
db.Mysql().Create(shareInfo)
// 更新上级邀请玩家数
db.Mysql().Update(&common.ShareInfo{UID: upInfo.UID}, map[string]interface{}{"invites": gorm.Expr("invites + 1")})
}
// 判断分享,发放有效用户奖励
func CheckShare(r *common.RechargeOrder) {
reward := GetConfigShareSys().ShareReward
if reward <= 0 {
return
}
if r.Amount < GetConfigShareSys().ShareRecharge {
return
}
share := GetShareInfo(r.UID)
if share.UP1 == 0 {
return
}
// 发放奖励
db.Mysql().Update(&common.ShareInfo{UID: share.UP1}, map[string]interface{}{
"invalid_invites": gorm.Expr("invalid_invites + 1"),
"invite_reward": gorm.Expr("invite_reward + ?", reward),
"available_reward": gorm.Expr("available_reward + ?", reward),
})
}
// 投注奖励结算
func ShareSettle(d *pb.InnerAfterSettle) {
shareInfo := &common.ShareInfo{UID: int(d.UID)}
db.Mysql().Get(shareInfo)
if shareInfo.UP1 == 0 {
return
}
db.Mysql().Update(&common.ShareInfo{UID: int(d.UID)}, map[string]interface{}{"bet": gorm.Expr("bet + ?", d.TotalBet)})
ref := reflect.ValueOf(shareInfo).Elem()
// 循环查询上级
for i := 1; i <= 3; i++ {
uid := int(ref.FieldByName(fmt.Sprintf("UP%d", i)).Int())
if uid == 0 {
break
}
con := GetConfigShareByLevel(i)
if con == nil {
log.Error("unknown config share level:%v", i)
continue
}
// 发奖
reward := d.TotalBet * con.Per / 1000
if reward <= 0 {
continue
}
db.Mysql().Update(&common.ShareInfo{UID: uid}, map[string]interface{}{
"bet_reward": gorm.Expr("bet_reward + ?", reward),
"available_reward": gorm.Expr("available_reward + ?", reward),
})
}
}
func PackLevelSql(uid, level int) (sql string) {
if level == 0 {
sql = fmt.Sprintf("up1 = %d or up2 = %d or up3 = %d", uid, uid, uid)
} else {
sql = fmt.Sprintf("up%d = %d", level, uid)
}
return
}
// GetUserShares 查询玩家下级数量
func GetUserShares(uid, level int) int64 {
return db.Mysql().Count(&common.ShareInfo{}, PackLevelSql(uid, level))
}
// GetUserShareRecharges 查询玩家下级充值人数
func GetUserShareRecharges(uid, level int) (count int64) {
sql := fmt.Sprintf(`SELECT count(*) as count from
(SELECT uid from share_info WHERE %s)a
INNER JOIN
(SELECT uid from recharge_info WHERE total_recharge > 0)b
on a.uid = b.uid`, PackLevelSql(uid, level))
err := db.Mysql().C().Raw(sql).Scan(&count).Error
if err != nil {
log.Error("err:%v", err)
}
return
}
// GetUserShareValidRecharges 查询玩家下级有效充值人数
func GetUserShareValidRecharges(uid, level int) (count int64) {
sql := fmt.Sprintf(`SELECT count(*) as count from
(SELECT uid from share_info WHERE %s)a
INNER JOIN
(SELECT uid from recharge_info WHERE total_recharge >= %d)b
on a.uid = b.uid`, PackLevelSql(uid, level), GetConfigShareSys().ShareRecharge)
err := db.Mysql().C().Raw(sql).Scan(&count).Error
if err != nil {
log.Error("err:%v", err)
}
return
}
// GetUserShareRechargeAmount 查询玩家下级充值总额
func GetUserShareRechargeAmount(uid, level int) (count int64) {
sql := fmt.Sprintf(`SELECT sum(b.total_recharge) as count from
(SELECT uid from share_info WHERE %s)a
INNER JOIN
(SELECT uid,total_recharge from recharge_info WHERE total_recharge > 0)b
on a.uid = b.uid`, PackLevelSql(uid, level))
err := db.Mysql().C().Raw(sql).Scan(&count).Error
if err != nil {
log.Error("err:%v", err)
}
return
}

@ -0,0 +1,573 @@
package call
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"net/url"
"server/common"
"server/config"
"server/db"
"server/util"
"strconv"
"strings"
"time"
"github.com/liangdas/mqant/log"
)
// 初始化在线人数上报
func InitOnline(f func() []*common.ESNewOnline) {
now := time.Now()
zero := util.GetZeroTime(now)
h, m, _ := now.Clock()
m -= m % 5
lastRecord := zero.Add(time.Duration(h) * time.Hour).Add(time.Duration(m) * time.Minute)
next := lastRecord.Add(5 * time.Minute).Sub(now)
time.AfterFunc(next, func() {
WriteOnline(lastRecord.Add(5*time.Minute).Unix(), f)
InitOnline(f)
})
}
// WriteOnline 写入在线统计
func WriteOnline(time int64, f func() []*common.ESNewOnline) {
data := f()
if len(data) == 0 {
return
}
for i := range data {
if data[i].Total == 0 {
continue
}
data[i].Time = time
db.ES().InsertToESGO(common.ESIndexBackPlayerOnline, data[i])
}
}
type FBEvents struct {
EventName string `json:"event_name"`
EventTime int64 `json:"event_time"`
UserData struct {
Em string `json:"em,omitempty"`
Ph string `json:"ph,omitempty"`
FN string `json:"fn,omitempty"`
LN string `json:"ln,omitempty"`
Country string `json:"country,omitempty"`
IP string `json:"client_ip_address,omitempty"`
ClientUserAgent string `json:"client_user_agent"`
FBC string `json:"fbc,omitempty"`
FBP string `json:"fbp,omitempty"`
ExternalID string `json:"external_id,omitempty"`
CT string `json:"ct,omitempty"` // 城市,哈希处理
ST string `json:"st,omitempty"` // 州,哈希处理
ZP string `json:"zp,omitempty"` // 邮编,哈希处理
} `json:"user_data"`
CustomData struct {
Currency string `json:"currency"`
Value int64 `json:"value"`
} `json:"custom_data"`
ActionSource string `json:"action_source"`
// AppData struct {
// AdvertiserTrackingEnabled int `json:"advertiser_tracking_enabled"`
// ApplicationTrackingEnabled int `json:"application_tracking_enabled"`
// Extinfo []string `json:"extinfo"`
// } `json:"app_data"`
}
type FBEvent int
const (
FBEventRegist FBEvent = iota
FBEventPurchase
)
func (f FBEvent) GetName() string {
switch f {
case FBEventRegist:
return "CompleteRegistration"
case FBEventPurchase:
return "Purchase"
default:
return ""
}
}
// UploadFB 上报fb数据
func UploadFB(uid int, event FBEvent, amount int64) {
u := &common.PlayerDBInfo{Id: uid}
db.Mysql().Get(u)
channel := GetChannelByID(u.ChannelID)
if channel == nil || channel.FBPixelID == "" || channel.FBAccessToken == "" || config.GetBase().AD.FBAPIURL == "" {
return
}
if channel.ADUpload != common.ADFB {
return
}
pi := &common.PayInfo{UID: uid}
db.Mysql().Get(pi)
randPi := &common.PayInfo{}
db.Mysql().C().Raw("SELECT * FROM pay_info ORDER BY RAND() LIMIT 1").Scan(randPi)
pa := &common.PlayerADData{UID: uid}
db.Mysql().GetLast(pa)
if pa.FBC == "" {
pa = &common.PlayerADData{ChannelID: u.ChannelID}
db.Mysql().C().Raw("SELECT * FROM player_ad_data ORDER BY RAND() LIMIT 1").Scan(pa)
}
// 拿取玩家信息
em := pi.Email
if em == "" {
em = randPi.Email
}
ph := u.Mobile
if ph == "" {
ph = randPi.Mobile
}
fn, ln := util.FormatUserName(pi.Name)
if fn == "" {
fn, ln = util.FormatUserName(randPi.Name)
}
ua := "$CLIENT_USER_AGENT"
if pa.UserAgent != "" {
ua = pa.UserAgent
}
// 分析ip
var ct, st, zp string
ipinfo, err := SearchIP(u.IP)
if err != nil {
log.Error("err:%v", err)
} else {
ct = util.CalculateSHA256(strings.ToLower(ipinfo.City.Names["en"]))
if len(ipinfo.Subdivisions) > 0 {
st = util.CalculateSHA256(strings.ToLower(ipinfo.Subdivisions[0].Names["en"]))
}
zp = util.CalculateSHA256(strings.ToLower(ipinfo.Postal.Code))
}
util.IndexTry(func() error {
// 准备事件数据
var requestBody bytes.Buffer
multipartWriter := multipart.NewWriter(&requestBody)
// 添加文本字段
events := []FBEvents{{
EventName: event.GetName(),
EventTime: time.Now().Unix(),
}}
events[0].UserData.Em = util.CalculateSHA256(strings.ToLower(em))
events[0].UserData.Ph = util.CalculateSHA256("91" + ph)
events[0].UserData.FN = util.CalculateSHA256(strings.ToLower(fn))
events[0].UserData.LN = util.CalculateSHA256(strings.ToLower(ln))
events[0].UserData.IP = u.IP
events[0].UserData.ClientUserAgent = ua
events[0].UserData.FBC = pa.FBC
events[0].UserData.FBP = pa.FBP
events[0].UserData.Country = util.CalculateSHA256("in")
events[0].UserData.ExternalID = util.CalculateSHA256(fmt.Sprintf("%d", uid))
events[0].UserData.ST = st
events[0].UserData.CT = ct
events[0].UserData.ZP = zp
events[0].ActionSource = "website"
if event == FBEventPurchase {
events[0].CustomData.Currency = "brl"
events[0].CustomData.Value = amount
}
evJson, _ := json.Marshal(events)
err = multipartWriter.WriteField("data", string(evJson))
if err != nil {
log.Error("Error writing text field:%v", err)
return err
}
err = multipartWriter.WriteField("access_token", channel.FBAccessToken)
if err != nil {
log.Error("Error writing text field:%v", err)
return err
}
multipartWriter.Close()
req, err := http.NewRequest("POST", config.GetBase().AD.FBAPIURL+channel.FBPixelID+"/events?access_token="+channel.FBAccessToken, &requestBody)
if err != nil {
log.Error("err:%v", err)
return err
}
// 设置请求头,包括 Content-Type
req.Header.Set("Content-Type", multipartWriter.FormDataContentType())
// 发送请求
client := &http.Client{
Timeout: 10 * time.Second,
}
log.Debug("UploadFB:%+v", req)
resp, err := client.Do(req)
if err != nil {
log.Error("err:%v", err)
return err
}
defer resp.Body.Close()
ret, err := io.ReadAll(resp.Body)
if err != nil {
log.Error("http read body err:%v", err)
return err
}
log.Debug("fbres:%v", string(ret))
return nil
})
}
// UploadAdjust 上报adjust数据
func UploadAdjust(event common.AdjustEventType, u *common.PlayerDBInfo, param map[string]string) {
channel := GetChannelByID(u.ChannelID)
if channel == nil || (u.ADID == "" && u.GPSADID == "") || channel.AdjustAppToken == "" {
return
}
if channel.ADUpload != common.ADJust {
return
}
util.IndexTry(func() error {
var err error
// if u == nil {
// u, err = GetUserXInfo("channel_id", "adid", "gps_adid")
// if err != nil {
// log.Error("err:%v", err)
// return
// }
// }
reqURL, _ := url.Parse(config.GetConfig().Web.Adjust.URL)
params := url.Values{}
params.Add("app_token", channel.AdjustAppToken)
params.Add("event_token", channel.GetAdjustEventID(int(event)))
params.Add("s2s", "1")
params.Add("created_at", strconv.FormatInt(time.Now().Unix(), 10))
params.Add("adid", u.ADID)
params.Add("gps_adid", u.GPSADID)
params.Add("web_uuid", u.GPSADID)
for k, v := range param {
params.Add(k, v)
}
reqURL.RawQuery = params.Encode()
req, err := http.NewRequest("GET", reqURL.String(), nil)
if err != nil {
log.Error("err:%v", err)
return err
}
req.Header.Set("Authorization", "Bearer "+channel.AdjustAuth)
client := &http.Client{
Timeout: 5 * time.Second,
}
log.Debug("UploadAdjust:%+v", req)
res, err := client.Do(req)
if err != nil {
log.Error("http post call err:%v", err)
return err
}
ret, err := io.ReadAll(res.Body)
defer res.Body.Close()
if err != nil {
log.Error("http read body err:%v", err)
return err
}
log.Debug("adjustRes:%v", string(ret))
return nil
})
}
// IsOrganic 查询设备是否是自然量 count 重试次数
func IsOrganic(gpsID, appToken string, cid int, count int) (is bool) {
count--
// reqURL, _ := url.Parse(config.GetConfig().Web.Adjust.APIURL)
reqURL, _ := url.Parse("https://api.adjust.com/device_service/api/v1/inspect_device")
params := url.Values{}
params.Add("advertising_id", gpsID)
params.Add("app_token", appToken)
reqURL.RawQuery = params.Encode()
var lg string
defer func() {
if count > 0 && is {
return
}
db.ES().InsertToESByIDGO(common.ESIndexBackABLog, fmt.Sprintf("%d_%s", cid, gpsID), &common.ESABLog{
Channel: cid,
Time: time.Now().Unix(),
DeviceID: gpsID,
IsA: is,
Log: lg,
})
}()
req, err := http.NewRequest("GET", reqURL.String(), nil)
if err != nil {
log.Error("err:%v", err)
lg = err.Error()
return
}
// req.Header.Set("Authorization", "Bearer "+config.GetConfig().Web.Adjust.APIToken)
req.Header.Set("Authorization", "Bearer _2ZGYezfdZ7yD2he-zWx")
client := &http.Client{
Timeout: 5 * time.Second,
}
log.Debug("check organic:%+v", req)
res, err := client.Do(req)
if err != nil {
log.Error("http post call err:%v", err)
lg = err.Error()
return
}
if res.Status == http.StatusText(http.StatusNotFound) {
is = true
lg = "http not found"
return
}
ret, err := ioutil.ReadAll(res.Body)
defer res.Body.Close()
if err != nil {
log.Error("http read body err:%v", err)
lg = err.Error()
return
}
log.Debug("AdjustDeviceResp:%v", string(ret))
ad := new(AdjustDeviceResp)
if err := json.Unmarshal(ret, ad); err != nil {
log.Error("err:%v", err)
lg = string(ret)
}
is = ad.TrackerName == "Organic"
if is {
lg = "Organic"
}
if is && count > 0 {
time.Sleep(time.Second)
return IsOrganic(gpsID, appToken, cid, count)
}
return
}
// IsOrganic2 查询设备是否是自然量(更为严格,凡是找不到设备号的,一律禁止) count 重试次数
func IsOrganic2(gpsID, appToken string, cid int, count int) (is bool) {
count--
// reqURL, _ := url.Parse(config.GetConfig().Web.Adjust.APIURL)
reqURL, _ := url.Parse("https://api.adjust.com/device_service/api/v1/inspect_device")
params := url.Values{}
params.Add("advertising_id", gpsID)
params.Add("app_token", appToken)
reqURL.RawQuery = params.Encode()
var lg string
defer func() {
if count > 0 && is {
return
}
db.ES().InsertToESByIDGO(common.ESIndexBackABLog, fmt.Sprintf("%d_%s", cid, gpsID), &common.ESABLog{
Channel: cid,
Time: time.Now().Unix(),
DeviceID: gpsID,
IsA: is,
Log: lg,
})
}()
req, err := http.NewRequest("GET", reqURL.String(), nil)
if err != nil {
is = true
log.Error("err:%v", err)
lg = err.Error()
return
}
// req.Header.Set("Authorization", "Bearer "+config.GetConfig().Web.Adjust.APIToken)
req.Header.Set("Authorization", "Bearer _2ZGYezfdZ7yD2he-zWx")
client := &http.Client{
Timeout: 5 * time.Second,
}
log.Debug("check organic:%+v", req)
res, err := client.Do(req)
if err != nil {
is = true
log.Error("http post call err:%v", err)
lg = err.Error()
return
}
if res.Status == http.StatusText(http.StatusNotFound) {
is = true
lg = "http not found"
return
}
ret, err := ioutil.ReadAll(res.Body)
defer res.Body.Close()
if err != nil {
is = true
log.Error("http read body err:%v", err)
lg = err.Error()
return
}
log.Debug("AdjustDeviceResp2:%v", string(ret))
ad := new(AdjustDeviceResp)
if err := json.Unmarshal(ret, ad); err != nil {
log.Error("err:%v", err)
is = true
lg = string(ret)
}
if !is {
is = ad.TrackerName == "Organic"
if is {
lg = "Organic"
}
}
if is && count > 0 {
time.Sleep(time.Second)
return IsOrganic2(gpsID, appToken, cid, count)
}
return
}
type AdjustDeviceResp struct {
Adid string `json:"Adid"`
AdvertisingID string `json:"AdvertisingId"`
Tracker string `json:"Tracker"`
TrackerName string `json:"TrackerName"`
// ClickTime time.Time `json:"ClickTime"`
// InstallTime time.Time `json:"InstallTime"`
// LastAppVersion string `json:"LastAppVersion"`
// LastAppVersionShort string `json:"LastAppVersionShort"`
// LastSessionTime time.Time `json:"LastSessionTime"`
// LastEventTimes struct {
// Zcqz1Y time.Time `json:"zcqz1y"`
// } `json:"LastEventTimes"`
// PushToken string `json:"PushToken"`
// State string `json:"State"`
// InstallState string `json:"InstallState"`
// SignatureAcceptanceStatus string `json:"SignatureAcceptanceStatus"`
// SignatureVerificationResult string `json:"SignatureVerificationResult"`
}
// WriteRealOnline 写入各场次实时在线
func WriteRealOnline(field string, f func() map[int]*common.RedisRealOnline) {
now := time.Now()
zero := util.GetZeroTime(now)
h, m, _ := now.Clock()
m -= m % 5
lastRecord := zero.Add(time.Duration(h) * time.Hour).Add(time.Duration(m) * time.Minute)
next := lastRecord.Add(5 * time.Minute).Sub(now)
// _, _, s := now.Clock()
// next := now.Add(time.Duration(60-s) * time.Second).Sub(now)
log.Debug("next real:%v", next)
time.AfterFunc(next, func() {
real := f()
for i, v := range real {
keyField := fmt.Sprintf("%v", field)
if i > 0 {
keyField += fmt.Sprintf(":%v", i)
}
key := common.GetRedisKeyOnlineKey(keyField)
if !db.Redis().Exist(key) {
if err := db.Redis().HSet(key, v); err != nil {
log.Error("err:%v", err)
continue
}
if err := db.Redis().Expire(key, next-2*time.Second); err != nil {
log.Error("err:%v", err)
continue
}
} else {
if err := db.Redis().HIncrBy(key, "Total", int64(v.Total)); err != nil {
log.Error("err:%v", err)
continue
}
if err := db.Redis().HIncrBy(key, "New", int64(v.New)); err != nil {
log.Error("err:%v", err)
continue
}
}
}
WriteRealOnline(field, f)
})
}
type KwaiReq struct {
Clickid string `json:"clickid"`
EventName string `json:"event_name"`
PixelID string `json:"pixelId"`
AccessToken string `json:"access_token"`
TestFlag bool `json:"testFlag"`
TrackFlag bool `json:"trackFlag"`
IsAttributed int `json:"is_attributed"` // 归因标记,此处需写死为1
Mmpcode string `json:"mmpcode"` // 标记数据来源,此处需写死为 PL
PixelSdkVersion string `json:"pixelSdkVersion"` // 版本信息,此处需写死为,9.9.9
Properties string `json:"properties"`
}
type KwaiResp struct {
Result int `json:"result"` // 返回状态码
ErrorMsg string `json:"error_msg"` // 返回信息详情
}
type KwaiProperties struct {
Currency string `json:"currency"`
Price float64 `json:"price"`
}
const (
KwaiEventRegist = iota
KwaiEventPay
)
func GetKwaiEventName(event int) string {
switch event {
case KwaiEventRegist:
return "EVENT_COMPLETE_REGISTRATION"
case KwaiEventPay:
return "EVENT_PURCHASE"
}
return ""
}
func UploadKwai(uid, event int, amount int64) {
u := &common.PlayerDBInfo{Id: uid}
db.Mysql().Get(u)
channel := GetChannelByID(u.ChannelID)
if channel == nil || (u.ADID == "" && u.GPSADID == "") || channel.AdjustAppToken == "" {
return
}
if channel.ADUpload != common.ADKwai {
return
}
pa := &common.PlayerADData{UID: uid}
db.Mysql().GetLast(pa)
if pa.FBC == "" {
pa = &common.PlayerADData{ChannelID: u.ChannelID}
db.Mysql().C().Raw("SELECT * FROM player_ad_data ORDER BY RAND() LIMIT 1").Scan(pa)
}
send := &KwaiReq{
Clickid: pa.FBC,
EventName: GetKwaiEventName(event),
PixelID: channel.FBPixelID,
AccessToken: channel.FBAccessToken,
TestFlag: false,
TrackFlag: !config.GetBase().Release,
IsAttributed: 1,
Mmpcode: "PL",
PixelSdkVersion: "9.9.9",
}
if event == KwaiEventPay {
pro := &KwaiProperties{
Currency: "brl",
Price: float64(amount/1e6) / 100,
}
byt, _ := json.Marshal(pro)
send.Properties = string(byt)
}
util.IndexTry(func() error {
ret := &KwaiResp{}
return util.HttpPost(config.GetBase().AD.KwaiAPIURL, send, ret, nil)
})
}

@ -0,0 +1,183 @@
package call
import (
"fmt"
"server/common"
"server/config"
"server/db"
"sync"
"time"
"github.com/liangdas/mqant/log"
"github.com/olivere/elastic/v7"
)
// WhitePass 白名单鉴权
func WhitePass(ip, uuid, path string, version, channel int) bool {
if !IsWhiteOpen(channel, version, path) {
return true
}
log.Debug("check white ip:%v,uuid:%v,path:%v,version:%v,channel:%v", ip, uuid, path, version, channel)
one := GetWhite(ip, uuid)
log.Debug("white:%+v", one)
if one != nil {
// if one.Version < version {
// return false
// }
return one.PowerPass(path)
}
return false
}
var (
ChannelWhiteMap sync.Map
Whites []*common.WhiteList
)
const (
SysListType = iota // 用作系统开关时的值
WhiteListType
BlackListType
)
func ReloadWhite(channel, opt int) {
val, ok := ChannelWhiteMap.Load(channel)
if !ok {
return
}
w := val.(*common.WhiteList)
w.LimitType = opt
}
func IsWhiteOpen(channel, version int, path string) bool {
val, ok := ChannelWhiteMap.Load(channel)
if !ok {
return false
}
w := val.(*common.WhiteList)
if w.LimitType == 2 {
return false
}
// 如果当前版本号大于白名单开启的发布版本,直接全功能限制
if version > w.Version {
return true
}
// 如果当前版本小与等于白名单发布版本,只限制部分功能
if common.IsLimitMap(path) {
return true
}
return false
}
func GetWhite(ip, uuid string) *common.WhiteList {
for i, v := range Whites {
if v.Content == ip || v.Content == uuid {
return Whites[i]
}
}
return nil
}
func IsWhite(ip, uuid string) bool {
for _, v := range Whites {
if ip != "" && v.Content == ip {
return true
}
if uuid != "" && v.Content == uuid {
return true
}
}
return false
}
func InitWhite() error {
one := []*common.WhiteList{}
if _, err := db.ES().QueryList(common.ESIndexBackWhiteList, 0, 5000, elastic.NewTermQuery("ListType", SysListType), &one); err != nil {
log.Error("err:%v", err)
return err
}
for _, v := range one {
log.Debug("all white:%+v", *v)
}
for i := range one {
ChannelWhiteMap.Store(one[i].Channel, one[i])
}
Whites = []*common.WhiteList{}
q := elastic.NewBoolQuery()
// q.MustNot(elastic.NewMatchQuery("ListType", SysListType))
q.Must(elastic.NewMatchQuery("ListType", WhiteListType))
if _, err := db.ES().QueryList(common.ESIndexBackWhiteList, 0, 5000, q, &Whites); err != nil {
log.Error("err:%v", err)
return err
}
for _, v := range Whites {
log.Debug("all Whites:%+v", *v)
}
return nil
}
// IsExamine 是否是审核人员
func IsExamine(ip string) bool {
log.Debug("check examine ip:%v", ip)
return db.ES().Exist(common.ESIndexBackExamineList, ip)
}
// CheckChannel 检查渠道是否要屏蔽
func CheckChannel(cid int, ip string) bool {
sip, err := SearchIP(ip)
if err != nil {
log.Error("err:%v", err)
return true
}
switch cid {
case 10002:
for _, v := range config.GetConfig().Web.PassRegion {
if sip.Subdivisions[0].Names["en"] == v {
return true
}
}
}
return false
}
// CheckExamine 检查是否进审核服
func CheckExamine(version int, ip, gpsID string, channel *common.Channel) (isExamine bool) {
if IsWhite(ip, "") || common.IsShareChannel(channel.ChannelID) {
return
}
if version == channel.Version {
log.Debug("examine ip:%v", ip)
isExamine = true
db.ES().InsertToESByIDGO(common.ESIndexBackExamineList, ip, &common.ExamineList{Time: time.Now().Unix()})
return
}
// else if IsExamine(ip) {
// isExamine = true
// } else
if config.GetBase().Release {
ipInfo, err := SearchIP(ip)
if err != nil {
log.Error("err:%v", err)
return
}
if ipInfo.Country.IsoCode == "CN" {
isExamine = true
return
}
}
if channel.IgnoreOrganic == 2 && len(gpsID) > 0 {
if IsOrganic(gpsID, channel.AdjustAppToken, channel.ChannelID, 3) {
var count int64
if channel.ChannelID >= 46 {
count = db.Mysql().Count(&common.PlayerDBInfo{}, fmt.Sprintf("channel_id = %v and deviceid = '%v'", channel.ChannelID, gpsID))
} else {
count = db.Mysql().Count(&common.PlayerDBInfo{}, fmt.Sprintf("channel_id = %v and (deviceid = '%v' or gps_adid = '%v')", channel.ChannelID, gpsID, gpsID))
}
if count == 0 {
isExamine = true
return
}
}
}
return
}

@ -0,0 +1,16 @@
package call
import (
"server/util"
"time"
timewheel "github.com/liangdas/mqant/module/modules/timer"
)
func InitTimeWheel(closeSig chan bool) {
timewheel.GetTimeWheel().Stop()
timewheel.SetTimeWheel(timewheel.New(100*time.Millisecond, 36))
util.Go(func() {
timewheel.GetTimeWheel().Start(closeSig)
})
}

@ -0,0 +1,664 @@
package call
import (
"encoding/json"
"errors"
"fmt"
"math/rand"
"reflect"
"server/common"
"server/config"
"server/db"
"server/natsClient"
"server/pb"
"server/util"
"strconv"
"time"
"github.com/liangdas/mqant/log"
"gorm.io/gorm"
)
// 查询用户的信息
func GetUserInfo(uid int) (ret *common.PlayerDBInfo, err error) {
ret = db.Redis().GetUserData(uid)
if ret != nil {
return
}
ret = &common.PlayerDBInfo{Id: uid}
err = db.Mysql().Get(ret)
return
}
// 查询用户的信息
func GetUserXInfo(uid int, fields ...string) (ret *common.PlayerDBInfo, err error) {
ret = new(common.PlayerDBInfo)
err = db.Redis().GetUserXInfo(uid, ret, fields...)
if err == nil {
return
}
// sqlFields := []string{}
// for _, v := range fields {
// sqlFields = append(sqlFields, v)
// }
ret = &common.PlayerDBInfo{Id: uid}
err = db.Mysql().SelectField(ret, fields...)
return
}
// 查询用户的信息
func GetUserXInfoByDB(uid int, fields ...string) (ret *common.PlayerDBInfo, err error) {
ret = &common.PlayerDBInfo{Id: uid}
err = db.Mysql().SelectField(ret, fields...)
return
}
// UpdateUserXinfo更新玩家信息
func UpdateUserXInfo(p *common.PlayerDBInfo, update map[string]interface{}) error {
if err := db.Mysql().Update(p, update); err != nil {
log.Error("err:%v", err)
return err
}
if err := db.Redis().UpdateUserFields(p.Id, update); err != nil {
log.Error("err:%v", err)
return err
}
return nil
}
// AddUserXInfo 更新玩家某个字段
func AddUserXInfo(uid int, field string, value int64, tx ...*gorm.DB) error {
p := &common.PlayerDBInfo{Id: uid}
dbUpdate := map[string]interface{}{field: gorm.Expr(fmt.Sprintf("%v + ?", field), value)}
if tx == nil {
if err := db.Mysql().Update(p, dbUpdate); err != nil {
log.Error("err:%v", err)
return err
}
} else {
if err := tx[0].Model(p).Where(p).Updates(dbUpdate).Error; err != nil {
log.Error("err:%v", err)
return err
}
}
if err := db.Redis().HIncrBy(common.GetRedisKeyUser(uid), field, value); err != nil {
log.Error("err:%v", err)
return err
}
return nil
}
func initPlayer(uid, channel int) {
db.Mysql().Create(&common.PlayerData{UID: uid})
initCoin := GetConfigPlatform().NewPlayerGift
if initCoin < 0 {
initCoin = 0
}
db.Mysql().Create(&common.PlayerCurrency{UID: uid, ChannelID: channel, BRL: initCoin})
// db.Mysql().C().Table(common.PlayerRechargeTableName).Create(&common.PlayerCurrency{UID: uid, ChannelID: channel})
db.Mysql().Create(&common.PlayerProfile{UID: uid, ChannelID: channel, NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, initCoin)})
}
func NewUser(info *common.PlayerDBInfo, ip, share, fbc, fbp, agent string) error {
// if info.AreaCode == "" {
// i, err := call.SearchIP(ip)
// log.Debug("searchip:%v,res:%v", ip, i)
// if err != nil {
// log.Error("err:%v", err)
// }
// id := call.GetCountryIDByCName(i.Country)
// log.Debug("i.Country:%v", i.Country)
// if id == "" {
// id = "US"
// }
// info.AreaCode = id
// }
isOld := false
if config.GetBase().Release && !IsWhite(ip, "") {
// 首先判断ip
// if db.Mysql().Count(&common.PlayerDBInfo{}, fmt.Sprintf("ip = '%s' and channel_id = %d", ip, info.ChannelID)) >= int64(config.GetConfig().Web.MaxPlayerAccountIP) {
// log.Debug("ip:%v 创建过多账号", ip)
// return errors.New("ip")
// }
if info.DeviceId != "" {
if IsBlackListPlayer(&common.BlackList{DeviceID: info.DeviceId, Phone: info.Mobile}) {
log.Debug("deviceid:%v 在黑名单里", info.DeviceId)
return errors.New("ip")
}
count := db.Mysql().Count(&common.PlayerDBInfo{}, fmt.Sprintf("deviceid = '%v' and channel_id = %d", info.DeviceId, info.ChannelID))
isOld = count > 1
if count >= int64(config.GetConfig().Web.MaxPlayerAccountIP) {
log.Debug("deviceid:%v 创建过多账号", info.DeviceId)
return errors.New("ip")
}
}
}
r := []rune(info.Nick)
if len(r) > 13 {
info.Nick = string(r[:13])
}
if info.Avatar == "" {
info.Avatar = RandomUserAvatar()
}
info.Status = common.AccountStatusNormal
info.Birth = time.Now().Unix()
info.Country = GetCountry(ip)
// initCoin := GetConfigPlatform().NewPlayerGift
// if info.AccountType == common.PlatformPhone {
// initCoin += GetConfigPlatform().BindPhoneGift
// }
// info.BindCash = initCoin
if err := db.Mysql().Create(info); err != nil {
return err
}
// 游客昵称
if len(r) < 2 {
info.Nick = fmt.Sprintf("User%v", info.Id)
if err := db.Mysql().Update(&common.PlayerDBInfo{Id: info.Id}, map[string]interface{}{"nick": info.Nick}); err != nil {
log.Error("err:%v", err)
return err
}
}
uid := info.Id
cid := info.ChannelID
// balance := &common.CurrencyBalance{UID: uid, Type: common.CurrencyTypeBindCash,
// Event: common.CurrencyEventNewPlayer, Value: initCoin, ChannelID: info.ChannelID,
// Balance: initCoin, Time: time.Now().Unix(), Exs1: "NewPlayer"}
util.Go(func() {
initPlayer(uid, cid)
UploadAdjust(common.AdjustEventNewPlayer, info, nil)
ShareBind(share, isOld, uid, cid)
// 新手赠送
first := config.GetConfig().Web.FreeSpinFirst
if first > 0 {
UpdateCurrencyPro(&common.UpdateCurrency{
CurrencyBalance: &common.CurrencyBalance{
UID: uid,
Value: first,
ChannelID: info.ChannelID,
Type: common.CurrencyBrazil,
Event: common.CurrencyEventActivityFreeSpin,
NeedBet: GetConfigCurrencyResourceNeedBet(common.CurrencyResourceBonus, first),
},
})
}
FBBind(ip, uid, cid, fbc, fbp, agent)
UploadFB(uid, FBEventRegist, 0)
UploadKwai(uid, KwaiEventRegist, 0)
})
return nil
}
// fb绑定
func FBBind(ip string, uid, cid int, fbc, fbp, agent string) {
// 优先ip绑定
pa := &common.PlayerADData{IP: ip, ChannelID: cid}
db.Mysql().GetLast(pa)
if pa.ID != 0 {
if pa.UID == 0 {
db.Mysql().Update(pa, map[string]interface{}{"uid": uid})
} else {
newPa := &common.PlayerADData{UID: uid, IP: ip, ChannelID: cid, FBC: pa.FBC, FBP: pa.FBP, UserAgent: agent}
db.Mysql().Create(newPa)
}
return
}
// 绑定fb数据
if len(fbc) != 0 || len(fbp) != 0 {
pa := &common.PlayerADData{ChannelID: cid, FBC: fbc, FBP: fbp}
db.Mysql().GetLast(pa)
if pa.ID == 0 {
newPa := &common.PlayerADData{UID: uid, IP: ip, ChannelID: cid, FBC: pa.FBC, FBP: pa.FBP, UserAgent: agent}
db.Mysql().Create(newPa)
return
}
if pa.UID == 0 {
db.Mysql().Update(pa, map[string]interface{}{"uid": uid})
return
}
newPa := &common.PlayerADData{UID: uid, IP: ip, ChannelID: cid, FBC: pa.FBC, FBP: pa.FBP, UserAgent: agent}
db.Mysql().Create(newPa)
return
}
}
func RandomUserAvatar() string {
max := GetConfigPlatform().AvatarCount
if max <= 0 {
max = 15
}
ran := rand.Intn(max) + 1
return strconv.Itoa(ran)
}
func RandomRobotAvatar() string {
ranMethod := rand.Intn(100)
// 30%使用卡通头像
if ranMethod < 30 {
return RandomUserAvatar()
}
max := GetConfigPlatform().AvatarCount
if max <= 0 {
max = 200
}
ran := rand.Intn(max)
return strconv.Itoa(ran)
}
func IsUserNickValid(nick string) bool {
n := []rune(nick)
if len(n) < 1 || len(n) > 15 {
return false
}
return true
}
func InsertLoginRecord(uid, channel int, ip string, birth int64, deviceType int) {
date := time.Now().Format("20060102")
one := &common.LoginRecord{UID: uid, ChannelID: channel, Date: date}
db.Mysql().Get(one)
re := GetRechargeInfo(uid)
isRecharge := 2
if re.TotalRecharge > 0 {
isRecharge = 1
}
if one.ID > 0 {
u := &common.LoginRecord{}
u.ID = one.ID
db.Mysql().Update(u, map[string]interface{}{"time": time.Now().Unix(), "platform": deviceType, "ip": ip, "is_recharge": isRecharge})
return
}
one.IP = ip
one.UID = uid
one.Date = date
one.ChannelID = channel
one.Time = time.Now().Unix()
one.Platform = deviceType
one.FirstTime = util.GetZeroTime(time.Unix(birth, 0)).Unix()
one.IsRecharge = isRecharge
if util.IsSameDayTimeStamp(birth, one.Time) {
one.Status = common.NewUser
} else {
one.Status = common.OldUser
}
db.Mysql().Create(one)
}
func GetVIP(uid int) *common.VipData {
data := &common.VipData{UID: uid}
err := db.Mysql().Get(data)
if err == gorm.ErrRecordNotFound {
re := &common.RechargeInfo{UID: uid}
db.Mysql().Get(re)
data.Exp = re.TotalRecharge
if data.Exp > 0 {
cons := GetConfigVIP()
for i := len(cons) - 1; i >= 0; i-- {
if data.Exp >= cons[i].Exp && cons[i].Exp >= 0 {
data.Level = cons[i].Level + 1
break
}
}
}
util.Go(func() {
db.Mysql().Create(data)
})
} else {
level := GetVipLevel(data.Exp, data.Bet)
if level != data.Level {
data.Level = level
db.Mysql().UpdateRes(&common.VipData{UID: uid}, map[string]interface{}{"level": level})
}
}
return data
}
func GetVipCon(uid int) *common.ConfigVIP {
data := &common.VipData{UID: uid}
err := db.Mysql().Get(data)
if err == gorm.ErrRecordNotFound {
util.Go(func() {
db.Mysql().Create(data)
})
}
return GetConfigVIPByLevel(data.Level)
}
func GetVipLevel(exp, bet int64) int {
con := GetConfigVIP()
for i := len(con) - 2; i >= 0; i-- {
if con[i].Exp > 0 && exp >= con[i].Exp && con[i].Bet > 0 && bet >= con[i].Bet { // 升级
return con[i].Level
}
}
return 0
}
// UpdateVip 增加vip经验
func UpdateVip(uid int, exp, bet, settle int64) {
for i := 0; i < 3; i++ {
vip := GetVIP(uid)
update := map[string]interface{}{}
if exp > 0 {
update["exp"] = gorm.Expr("exp + ?", exp)
}
if bet > 0 {
update["bet"] = gorm.Expr("bet + ?", bet)
}
con := GetVipCon(uid)
win := bet - settle
// 刷新返利盈利
now := time.Now().Unix()
reset := false
if config.GetBase().Release {
reset = !util.IsSameDayTimeStamp(now, vip.ProfitTime)
} else {
reset = util.GetNext5MinUnix()-vip.ProfitTime >= 5*60
}
if reset {
if con != nil && vip.ProfitTime != 0 {
update["cashback"] = vip.Profit * con.Cashback / 1000
}
update["profit"] = win
update["profit_time"] = now
} else {
update["profit"] = gorm.Expr("profit + ?", win)
}
level := GetVipLevel(vip.Exp+exp, vip.Bet+bet)
if level != vip.Level { // 升级
update["level"] = level
}
res := db.Mysql().C().Model(&common.VipData{}).Where("uid = ? and exp = ? and bet = ?", uid, vip.Exp, vip.Bet).Updates(update)
if res.Error != nil {
log.Error("err:%v", res.Error)
}
if res.RowsAffected > 0 {
// 通知客户端等级变动
if update["level"] != nil {
SendNR(uid, int(pb.ServerCommonResp_CommonVipResp), &pb.ConfigChangeResp{Type: pb.ConfigChangeType_ConfigVipLevel}, "common")
}
break
}
}
}
// IsBlackListPlayer 判断用户是否是黑名单用户
func IsBlackListPlayer(data *common.BlackList) bool {
if GetConfigPlatform().BlackList == 0 {
return false
}
phone := data.Phone
payAccount := data.PayAccount
email := data.Email
deviceID := data.DeviceID
if phone == "" && payAccount == "" && email == "" && deviceID == "" {
return false
}
sql := ""
if len(phone) > 0 {
sql += fmt.Sprintf("phone = '%s' ", phone)
}
if len(payAccount) > 0 {
if len(sql) > 0 {
sql += fmt.Sprintf("or pay_account = '%s' ", payAccount)
} else {
sql += fmt.Sprintf("pay_account = '%s' ", payAccount)
}
}
if len(deviceID) > 0 {
if len(sql) > 0 {
sql += fmt.Sprintf("or deviceid = '%s' ", deviceID)
} else {
sql += fmt.Sprintf("deviceid = '%s' ", deviceID)
}
}
if len(email) > 0 {
if len(sql) > 0 {
sql += fmt.Sprintf("or email = '%s' ", email)
} else {
sql += fmt.Sprintf("email = '%s' ", email)
}
}
if len(sql) == 0 {
return false
}
var count int64
db.Mysql().C().Model(&common.BlackList{}).Where(sql).Limit(1).Count(&count)
return count > 0
}
// 封号
func KickPlayer(uid int) {
UpdateUserXInfo(&common.PlayerDBInfo{Id: uid}, map[string]interface{}{"status": 2})
player, _ := GetUserXInfo(uid, "token")
if player.Token != "" {
db.Redis().Delkey(common.GetRedisKeyToken(player.Token))
}
db.Redis().Delkey(common.GetRedisKeyUser(uid))
Publish(natsClient.TopicInnerOptPlayer, &pb.InnerOptPlayer{UID: uint32(uid), Opt: common.OptPlayerTypeKick})
}
// BlackListAndKick 判断用户是否是黑名单用户并且直接封号
func BlackListAndKick(uid int, data *common.BlackList) bool {
if IsBlackListPlayer(data) {
KickPlayer(uid)
db.ES().InsertToESGO(common.ESIndexBackBlackList, &common.ESBlackList{UID: uid, Name: data.Name,
PayAccount: data.PayAccount, Email: data.Email, Phone: data.Phone, Time: time.Now().Unix()})
return true
}
return false
}
// GetItems 拉取用户道具
func GetItems(uid int) *common.PlayerItems {
data := &common.PlayerItems{UID: uid}
err := db.Mysql().Get(data)
if err == gorm.ErrRecordNotFound {
util.Go(func() {
db.Mysql().Create(data)
})
}
return data
}
// IsUserBan 判断用户是否被禁
func IsUserBan(uid int) bool {
p, _ := GetUserXInfo(uid, "status")
return p.Status == common.AccountStatusLimit
}
// 赢钱账户的总额
func GetUserCurrency(uid int, t common.CurrencyType) int64 {
var ret int64
db.Mysql().C().Model(&common.PlayerCurrency{UID: uid}).Select(t.GetCurrencyName()).Scan(&ret)
return ret
}
// 获取充值账户的总额
func GetUserCurrencyRecharge(uid int, t common.CurrencyType) int64 {
var pcr int64
db.Mysql().C().Table(common.PlayerRechargeTableName).Where("uid = ?", uid).Select(t.GetCurrencyName()).Scan(&pcr)
return pcr
}
// 获取充值账户+赢钱账户的总额
func GetUserCurrencyTotal(uid int, t common.CurrencyType) int64 {
var pc, pcr int64
db.Mysql().C().Model(&common.PlayerCurrency{UID: uid}).Select(t.GetCurrencyName()).Scan(&pc)
db.Mysql().C().Table(common.PlayerRechargeTableName).Where("uid = ?", uid).Select(t.GetCurrencyName()).Scan(&pcr)
return pc + pcr
}
func GetUserCurrencyFloat(uid int, t common.CurrencyType, num int) float64 {
var pc, pcr int64
if err := db.Mysql().C().Model(&common.PlayerCurrency{UID: uid}).Select(t.GetCurrencyName()).Scan(&pc).Error; err != nil {
log.Error("err:%v", err)
}
if err := db.Mysql().C().Table(common.PlayerRechargeTableName).Where("uid = ?", uid).Select(t.GetCurrencyName()).Scan(&pcr).Error; err != nil {
log.Error("err:%v", err)
}
return util.Decimal(float64(pc+pcr)/common.DecimalDigits, num)
}
func GetUserCurrencyByName(uid int, currencyName string) int64 {
pc := &common.PlayerCurrency{UID: uid}
db.Mysql().Get(pc)
ref := reflect.ValueOf(pc).Elem().FieldByName(currencyName)
if ref.IsValid() {
return ref.Int()
}
return 0
}
func IsNewPlayer(birth int64) bool {
return time.Now().Unix()-birth < 24*60*60
}
func GetPlayerRechargeInfoByCurrency(uid int, t common.CurrencyType) *common.RechargeInfoCurrency {
reu := &common.RechargeInfoCurrency{}
tableName := fmt.Sprintf("recharge_info_%s", t.GetCurrencyName())
db.Mysql().C().Table(tableName).Where("uid = ?", uid).Scan(reu)
return reu
}
func UpdatePlayerRechargeInfoCurrency(uid int, t common.CurrencyType, u map[string]interface{}, tx ...*gorm.DB) error {
tableName := fmt.Sprintf("recharge_info_%s", t.GetCurrencyName())
if len(tx) > 0 {
return tx[0].Table(tableName).Where("uid = ?", uid).Updates(u).Error
}
return db.Mysql().C().Table(tableName).Where("uid = ?", uid).Updates(u).Error
}
func GetPlayerProfileByCurrency(uid int, t common.CurrencyType) *common.PlayerProfile {
pp := &common.PlayerProfile{}
tableName := fmt.Sprintf("player_profile_%s", t.GetCurrencyName())
db.Mysql().C().Table(tableName).Where("uid = ?", uid).Scan(pp)
return pp
}
func UpdatePlayerProfile(data *common.ESGameData) error {
t := data.Type
bet := data.BetAmount
settle := data.SettleAmount
uid := data.UID
var err error
if data.Channel == 0 || data.Birth == 0 {
p, _ := GetUserXInfo(uid, "channel_id", "birth")
data.Channel = p.ChannelID
data.Birth = p.Birth
}
log.Debug("UpdatePlayerProfile:%+v", data)
u := map[string]interface{}{"total_bet": gorm.Expr("total_bet + ?", bet), "total_settle": gorm.Expr("total_settle + ?", settle),
"total_counts": gorm.Expr("total_counts + 1")}
if db.Mysql().Exist(&common.PlayerProfile{UID: uid}) {
// 先更新总数据
db.Mysql().Update(&common.PlayerProfile{UID: uid}, u)
} else {
db.Mysql().Create(&common.PlayerProfile{UID: uid, ChannelID: data.Channel, TotalBet: bet, TotalCounts: 1, TotalSettle: settle})
}
// if err != nil {
// log.Error("err:%v", err)
// return err
// }
UpdateUserNeedBet(uid, data.BetAmount)
// 更新货币数据
tableName := fmt.Sprintf("player_profile_%s", t.GetCurrencyName())
var count int64
db.Mysql().C().Table(tableName).Where("uid = ?", uid).Count(&count)
if count > 0 {
u["total_bet"] = gorm.Expr("total_bet + ?", bet)
u["total_settle"] = gorm.Expr("total_settle + ?", settle)
err = db.Mysql().C().Table(tableName).Where("uid = ?", uid).Updates(u).Error
} else {
err = db.Mysql().C().Table(tableName).Create(&common.PlayerProfile{UID: uid, ChannelID: data.Channel, TotalBet: bet, TotalCounts: 1, TotalSettle: settle}).Error
}
if err != nil {
log.Error("err:%v", err)
}
util.Go(func() {
// 更新vip
UpdateVip(uid, 0, bet, settle)
})
// 写入es
data.Time = time.Now().Unix()
data.IsNew = util.IsSameDayTimeStamp(data.Time, data.Birth)
db.ES().InsertToESGO(common.ESIndexGameData, data)
return nil
}
func GetPlayerData(uid int) *common.PlayerData {
data := &common.PlayerData{UID: uid}
db.Mysql().Get(data)
return data
}
func GetPlayerPayData(uid int) *common.PlayerPayData {
data := &common.PlayerPayData{UID: uid}
db.Mysql().Get(data)
if data.ID == 0 {
db.Mysql().Create(data)
}
if data.BreakGift != "" {
err := json.Unmarshal([]byte(data.BreakGift), &data.SubBreakGift)
if err != nil {
log.Error("err:%v", err)
}
}
return data
}
func GetUserNeedBet(uid int) int64 {
pro := &common.PlayerProfile{UID: uid}
db.Mysql().Get(pro)
return pro.NeedBet
}
func GetUserTaskData(uid int) (ret []common.TaskData) {
if uid == 0 {
return
}
db.Mysql().QueryAll(fmt.Sprintf("uid = %d", uid), "", &common.TaskData{}, &ret)
return
}
func GetUserTaskDataByTaskID(uid, taskID int) *common.TaskData {
data := &common.TaskData{UID: uid, TaskID: taskID}
db.Mysql().Get(data)
return data
}
func UpdateUserNeedBet(uid int, amount int64) {
util.Go(func() {
for i := 0; i < 3; i++ {
pro := &common.PlayerProfile{UID: uid}
db.Mysql().Get(pro)
if pro.NeedBet == 0 {
return
}
var rows int64
var err error
if pro.NeedBet < amount {
rows, err = db.Mysql().UpdateResW(&common.PlayerProfile{}, map[string]interface{}{"need_bet": 0}, fmt.Sprintf("uid = %d and need_bet = %d", uid, pro.NeedBet))
} else {
rows, err = db.Mysql().UpdateResW(&common.PlayerProfile{}, map[string]interface{}{"need_bet": gorm.Expr("need_bet - ?", amount)},
fmt.Sprintf("uid = %d and need_bet = %d", uid, pro.NeedBet))
}
if rows == 0 || err != nil {
log.Error("err:%v", err)
time.Sleep(time.Second)
continue
}
return
}
})
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,479 @@
package common
import (
"time"
)
const (
ActivityID = iota + 10000
ActivityIDRecharge // 首充活动
ActivityIDAppSpin // 下载转盘活动
ActivityIDPDD // pdd活动
ActivityIDFreeSpin // 每日免费转盘
ActivityIDFirstRechargeBack // 首日充值返还
ActivityIDLuckyCode // 幸运码活动
ActivityIDSign // 签到活动
ActivityIDBreakGift // 破产礼包
ActivityIDWeekCard // 周卡
ActivityIDSlots // slots奖池活动
ActivityIDLuckyShop // 幸运商店活动
ActivityIDSevenDayBox // 7日签到宝箱
ActivityIDSuper // 超级1+2
)
const (
ActivityDataZero = iota
ActivityDataClick
ActivityDataJoin
ActivityDataAll
)
// ConfigBanner banner配置
type ConfigBanner struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"ID" web:"id"`
ActivityID int `gorm:"column:activity_id;uniqueIndex:activity_id" json:"ActivityID" web:"activity_id"`
Sort int `gorm:"column:sort;type:int(11);" json:"Sort" web:"sort"`
Start int64 `gorm:"column:start;type:bigint(20);" json:"Start" web:"start"`
End int64 `gorm:"column:end;type:bigint(20);" json:"End" web:"end"`
IsRelease int `gorm:"column:is_release;type:int(11);default:1;comment:是否开启 1关闭 2开启" json:"IsRelease" web:"is_release"`
Push int `gorm:"column:push;type:int(11);default:1;comment:是否推送 1不推送 2推送" json:"Push" web:"push"`
PushFrequency int `gorm:"column:push_frequency;type:int(11);default:1;comment:推送频率" json:"PushFrequency" web:"push_frequency"`
Type int `gorm:"column:type;type:int(11);default:1;comment:类型" json:"Type" web:"type"`
Pic string `gorm:"column:pic;type:varchar(255);comment:活动图片" json:"Pic" web:"pic"`
Data string `gorm:"column:data;type:varchar(255);comment:跳转数据" json:"Data" web:"data"`
}
func (c *ConfigBanner) TableName() string {
return "config_banner"
}
func (s *ConfigBanner) IsValid() bool {
now := time.Now().Unix()
if s.IsRelease != 2 || s.Start > now || (s.End < now && s.End > 0) {
return false
}
return true
}
// ConfigActivity
type ConfigActivity struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"ID" web:"id"`
ActivityID int `gorm:"column:activity_id;uniqueIndex:activity_id" json:"ActivityID" web:"activity_id"`
Sort int `gorm:"column:sort;type:int(11);" json:"Sort" web:"sort"`
Start int64 `gorm:"column:start;type:bigint(20);" json:"Start" web:"start"`
End int64 `gorm:"column:end;type:bigint(20);" json:"End" web:"end"`
IsRelease int `gorm:"column:is_release;type:int(11);default:1;comment:是否开启 1关闭 2开启" json:"IsRelease" web:"is_release"`
Push int `gorm:"column:push;type:int(11);default:1;comment:是否推送 1推送 2不推送" json:"Push" web:"push"`
PushFrequency int `gorm:"column:push_frequency;type:int(11);default:1;comment:推送频率" json:"PushFrequency" web:"push_frequency"`
Type int `gorm:"column:type;type:int(11);default:1;comment:类型" json:"Type" web:"type"`
Pic string `gorm:"column:pic;type:varchar(255);comment:活动图片" json:"Pic" web:"pic"`
Data string `gorm:"column:data;type:varchar(255);comment:跳转数据" json:"Data" web:"data"`
}
func (a *ConfigActivity) TableName() string {
return "config_activity"
}
// Expire 判断活动是否可用
func (s *ConfigActivity) IsValid() bool {
now := time.Now().Unix()
if s.IsRelease != 2 || s.Start > now || (s.End < now && s.End > 0) {
return false
}
return true
}
type PddData struct {
ID int `gorm:"primarykey"`
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
Time int64 `gorm:"column:time;type:bigint(20);comment:创建时间"`
Amount int64 `gorm:"column:amount;type:bigint(20);comment:当前金额"`
Spin int `gorm:"column:spin;type:int(11);comment:剩余旋转次数"`
FreeSpinTime int64 `gorm:"column:free_spin_time;type:bigint(20);comment:免费旋转时间"`
NewRecordTime int64 `gorm:"column:new_record_time;type:bigint(20);comment:判断新邀请用户标记时间"`
}
func (a *PddData) TableName() string {
return "pdd_data"
}
// 拼多多活动转盘物品类型
const (
ActivityPddItemType = iota
ActivityPddItemTypeFinish // 直接补齐差额
ActivityPddItemTypeCash // 固定金额
ActivityPddItemTypeRandomCash // 随机金额
ActivityPddItemTypeAll
)
// ConfigActivityPddSpin 拼多多分享活动转盘配置
type ConfigActivityPddSpin struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"ID"`
AmountDown int64 `gorm:"column:amount_down;type:bigint(20);default:0;uniqueIndex:amount_sort;comment:区间金额下限" web:"amount_down"`
AmountUp int64 `gorm:"column:amount_up;type:bigint(20);default:0;comment:区间金额上限" web:"amount_up"`
Type int `gorm:"column:type;type:int(11);default:3;comment:物品类型" web:"type"`
Amount int64 `gorm:"column:amount;type:bigint(20);default:0;comment:物品数量" web:"amount"`
Weight int `gorm:"column:weight;type:int(11);default:0;comment:权重" web:"weight"`
Sort int `gorm:"column:sort;type:int(11);default:0;uniqueIndex:amount_sort;comment:排序" web:"sort"`
CashDown int64 `gorm:"column:cash_down;type:bigint(20);default:0;comment:当type是随机金额的时候,表示随机金额的下限" web:"cash_down"`
CashUp int64 `gorm:"column:cash_up;type:bigint(20);default:0;comment:当type是随机金额的时候,表示随机金额的上限" web:"cash_up"`
}
func (c *ConfigActivityPddSpin) TableName() string {
return "config_activity_pdd_spin"
}
// ConfigActivityPdd 拼多多分享活动配置
type ConfigActivityPdd struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id"`
WithdrawAmount int64 `gorm:"column:withdraw_amount;type:bigint(20);default:0;comment:可退出门槛" web:"withdraw_amount"`
AmountDown int64 `gorm:"column:amount_down;type:bigint(20);default:0;comment:随机金额下限" web:"amount_down"`
AmountUp int64 `gorm:"column:amount_up;type:bigint(20);default:0;comment:随机金额上限" web:"amount_up"`
Expire int64 `gorm:"column:expire;type:bigint(20);default:0;comment:过期时间,单位分钟" web:"expire"`
}
func (c *ConfigActivityPdd) TableName() string {
return "config_activity_pdd"
}
// ConfigFirstPay 首充奖励配置
type ConfigFirstPay struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id"`
Level int `gorm:"column:level;type:int(11);default:0;comment:等级" web:"level"`
Amount int64 `gorm:"column:amount;type:bigint(20);default:0;comment:充值额度" web:"amount"`
FirstPer int64 `gorm:"column:first_per;type:bigint(20);default:0;comment:首次充值赠送比例,百分位" web:"first_per"`
Per int64 `gorm:"column:per;type:bigint(20);default:0;comment:后续充值赠送比例,百分位" web:"per"`
}
func (c *ConfigFirstPay) TableName() string {
return "config_first_pay"
}
// ConfigActivityFreeSpin 每日免费转盘配置
type ConfigActivityFreeSpin struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"ID"`
Type int `gorm:"column:type;type:int(11);default:3;comment:物品类型,对应枚举" web:"type"`
Amount int64 `gorm:"column:amount;type:bigint(20);default:0;comment:物品数量" web:"amount"`
Weight int `gorm:"column:weight;type:int(11);default:0;comment:权重" web:"weight"`
Sort int `gorm:"column:sort;type:int(11);default:0;uniqueIndex:amount_sort;comment:排序" web:"sort"`
CashDown int64 `gorm:"column:cash_down;type:bigint(20);default:0;comment:当type是随机金额的时候,表示随机金额的下限" web:"cash_down"`
CashUp int64 `gorm:"column:cash_up;type:bigint(20);default:0;comment:当type是随机金额的时候,表示随机金额的上限" web:"cash_up"`
}
func (c *ConfigActivityFreeSpin) TableName() string {
return "config_activity_free_spin"
}
// 拼多多活动转盘物品类型
const (
ActivityFreeSpinItem = iota
ActivityFreeSpinItemNone // 转到无奖励
ActivityFreeSpinItemCash // 固定金额
ActivityFreeSpinItemRandomCash // 随机金额
ActivityFreeSpinItemDoubleCash // 双倍奖励
ActivityFreeSpinItemAll
)
// ActivityFreeSpinData
type ActivityFreeSpinData struct {
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
LastSpin int64 `gorm:"column:last_spin;default:0;type:bigint(20);comment:上次旋转时间"`
}
func (c *ActivityFreeSpinData) TableName() string {
return "activity_free_spin_data"
}
// 首次充值后判断间隔
const (
ActivityFirstRechargeBackTime = 86400 // 一天
)
// ConfigActivityFirstRechargeBack 首日充值返还
type ConfigActivityFirstRechargeBack struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"ID"`
MinRecharge int64 `gorm:"column:min_recharge;type:bigint(20);default:10000000000;comment:最低充值额度" web:"min_recharge"`
MaxBack int64 `gorm:"column:max_back;type:bigint(20);default:-1;comment:最大返还额度" web:"max_back"`
}
func (c *ConfigActivityFirstRechargeBack) TableName() string {
return "config_activity_first_recharge_back"
}
type ActivityFirstRechargeBackData struct {
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
RechargeTime int64 `gorm:"column:recharge_time;type:bigint(20);default:0;comment:首次充值时间"`
Amount int64 `gorm:"column:amount;type:bigint(20);default:0;comment:总充值金额"`
Lost int64 `gorm:"column:lost;type:bigint(20);default:0;comment:活动时间内总损失"`
}
func (c *ActivityFirstRechargeBackData) TableName() string {
return "activity_first_recharge_back_data"
}
const (
LuckyCodeTypeZero = iota
LuckyCodeTypeNormal
LuckyCodeTypeAll
)
type ConfigActivityLuckyCode struct {
ID int `gorm:"primarykey"`
Type int `gorm:"column:type;type:int(11);default:1;comment:类型" web:"type"`
Reward int64 `gorm:"column:reward;not null;type:bigint(20);comment:奖励的物品" web:"reward"`
Per int64 `gorm:"column:per;type:int(11);default:60;comment:奖品的权重" web:"per"`
}
func (c *ConfigActivityLuckyCode) TableName() string {
return "config_activity_lucky_code"
}
type ActivityLuckyCodeData struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id"`
Type int `gorm:"column:type;default:1;type:int(11);"`
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
LastDraw int64 `gorm:"column:last_draw;default:0;type:bigint(20)"`
}
func (c *ActivityLuckyCodeData) TableName() string {
return "activity_lucky_code_data"
}
// 存放每天的兑换码记录
type ActivityLuckyCode struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id"`
Type int `gorm:"column:type;default:1;type:int(11);"`
Code int `gorm:"column:code;default:0;type:int(11)"`
Date string `gorm:"column:date;default:'';type:varchar(64);uniqueIndex:date;comment:日期"`
}
func (c *ActivityLuckyCode) TableName() string {
return "activity_lucky_code"
}
type ConfigActivitySign struct {
ID int `gorm:"primarykey"`
Day int `gorm:"column:day;type:int(11);default:1;comment:签到天数" web:"day"`
Reward int64 `gorm:"column:reward;not null;type:bigint(20);comment:奖励" web:"reward"`
Recharge int64 `gorm:"column:recharge;type:bigint(20);default:0;comment:所需充值金额" web:"recharge"`
}
func (c *ConfigActivitySign) TableName() string {
return "config_activity_sign"
}
type ActivitySignData struct {
ID int `gorm:"primarykey"`
UID int `gorm:"column:uid;type:int(11);uniqueIndex:uid"`
Sign int `gorm:"column:sign;type:int(11);comment:签到天数,二进制"`
Time int64 `gorm:"column:time;type:bigint(20);comment:首次参与时间"`
}
func (c *ActivitySignData) TableName() string {
return "activity_sign_data"
}
type ConfigActivityBreakGift struct {
ID int `gorm:"primarykey"`
Level int `gorm:"column:level;type:int(11);default:1;comment:等级" web:"level"`
RechargeDown int64 `gorm:"column:recharge_down;type:bigint(11);default:1000000000;comment:充值金额下限" web:"recharge_down"`
RechargeUp int64 `gorm:"column:recharge_up;type:bigint(20);default:2000000000;comment:充值金额上限" web:"recharge_up"`
CountDown int `gorm:"column:count_down;type:int(11);default:30;comment:倒计时" web:"count_down"`
ProductID int `gorm:"column:product_id;type:int(11);default:0;comment:商品id" web:"product_id"`
}
func (c *ConfigActivityBreakGift) TableName() string {
return "config_activity_break_gift"
}
type ConfigActivityWeekCard struct {
ID int `gorm:"primarykey"`
Level int `gorm:"column:level;type:int(11);default:1;comment:等级" web:"level"`
ProductID int `gorm:"column:product_id;type:int(11);default:0;comment:商品id" web:"product_id"`
DayReward int64 `gorm:"column:day_reward;type:bigint(11);default:700000000;comment:每日可领取奖励" web:"day_reward"`
OriginPrice int64 `gorm:"column:origin_price;type:bigint(11);default:5000000000;comment:显示的原价" web:"origin_price"`
Day int `gorm:"column:day;type:int(11);default:6;comment:可领取天数" web:"day"`
Discount int `gorm:"column:discount;type:int(11);default:70;comment:折扣率,百分位" web:"discount"`
Rebate int `gorm:"column:rebate;type:int(11);default:240;comment:返利率,百分位" web:"rebate"`
Range string `gorm:"column:range;default:'[2000000000,100000000000]';type:varchar(255);comment:充值可用范围"`
SubRange []int64 `gorm:"-" json:"-"`
}
func (c *ConfigActivityWeekCard) TableName() string {
return "config_activity_week_card"
}
const (
ActivityWeekCardTicketExpireTime = 48 * 3600 // 两个小时
)
type ActivityWeekCardData struct {
ID int `gorm:"primarykey"`
UID int `gorm:"column:uid;type:int(11);uniqueIndex:ul"`
Level int `gorm:"column:level;type:int(11);default:0;uniqueIndex:ul;comment:周卡等级"`
DayReward int64 `gorm:"column:day_reward;type:bigint(11);default:700000000;comment:每日可领取奖励"`
Day int `gorm:"column:day;type:int(11);default:6;comment:可领取天数"`
LastDraw int64 `gorm:"column:last_draw;type:bigint(20);default:0;comment:上次领取时间"`
GetDiscount int `gorm:"column:get_discount;type:tinyint(4);default:0;comment:前面是否已经获得了折扣券"`
}
func (c *ActivityWeekCardData) TableName() string {
return "activity_week_card_data"
}
// 支付时带有一些信息,如折扣券,赋值在recharge_order的extra字段
type ActivityRechargeData struct {
ID int `json:"ID,omitempty"` // 活动id
I1 int `json:"I1,omitempty"` // 携带的信息1,不同活动可能含义不同,折扣券活动代表折扣券等级
I2 int64 `json:"I2,omitempty"` // 携带信息2,不同活动可能含义不同,折扣券活动代表实际发放金额
}
type ConfigActivitySlots struct {
ID int `gorm:"primarykey"`
RankDown int `gorm:"column:rank_down;type:int(11);default:1;comment:排名下限" web:"rank_down"`
RankUp int `gorm:"column:rank_up;type:int(11);default:1;comment:排名上限" web:"rank_up"`
Reward int64 `gorm:"column:reward;type:bigint(11);default:99900000000;comment:奖励" web:"reward"`
}
func (c *ConfigActivitySlots) TableName() string {
return "config_activity_slots"
}
// 1,2通过对当天日期取余决定
type ActivitySlotsData struct {
ID int `gorm:"primarykey"`
UID int `gorm:"column:uid;type:int(11);uniqueIndex:uid"`
Avatar string `gorm:"column:avatar;default:'';type:varchar(255);comment:头像"`
Nick string `gorm:"column:nick;default:'';type:varchar(255);comment:昵称"`
Spin int `gorm:"column:spin;type:int(11);default:0;comment:抽奖次数"`
BestNumber1 int `gorm:"column:best_number1;type:int(11);default:0;comment:抽到的最大的数字1"`
Time1 int64 `gorm:"column:time1;type:bigint(20);comment:参与时间1"`
BestNumber2 int `gorm:"column:best_number2;type:int(11);default:0;comment:抽到的最大的数字2"`
Time2 int64 `gorm:"column:time2;type:bigint(20);comment:参与时间2"`
Role int `gorm:"column:role;type:int(11);default:0;comment:角色,1代表机器人,2初始默认的机器人"`
}
func (c *ActivitySlotsData) TableName() string {
return "activity_slots_data"
}
// 结算记录
type ActivitySlotsRecord struct {
ID int `gorm:"primarykey"`
Date string `gorm:"column:date;default:'';type:varchar(255);uniqueIndex:du;comment:日期"`
UID int `gorm:"column:uid;type:int(11);uniqueIndex:du"`
Settle int `gorm:"column:settle;type:int(11);default:0;comment:是否结算,1代表已结算"`
BestNumber int `gorm:"column:best_number;type:int(11);default:0;comment:当日的最大的数字"`
Reward int64 `gorm:"column:reward;type:bigint(20);default:0;comment:奖励" web:"reward"`
MyNumber int `gorm:"column:my_number;type:int(11);default:0;comment:玩家的数字"`
Rank int `gorm:"column:rank;type:int(11);default:0;comment:排名"`
}
func (c *ActivitySlotsRecord) TableName() string {
return "activity_slots_Record"
}
const (
ActivityLuckyShopType = iota
ActivityLuckyShopTypeRechargeLess
ActivityLuckyShopTypeRechargeMore
ActivityLuckyShopTypeLogin
ActivityLuckyShopTypeAll
)
type ConfigActivityLuckyShop struct {
ID int `gorm:"primarykey"`
Type int `gorm:"column:type;type:int(11);default:1;comment:类型,1是首充小于弹出,2是首充大于弹出,3是付费玩家登录弹出" web:"type"`
Recharge int64 `gorm:"column:recharge;type:bigint(20);default:2000000000;comment:首充玩家弹出的充值额度" web:"recharge"`
ProductID int `gorm:"column:product_id;type:int(11);default:0;comment:商品id" web:"product_id"`
}
func (c *ConfigActivityLuckyShop) TableName() string {
return "config_activity_lucky_shop"
}
const (
ActivityLuckyShopExpire = 2 * 3600 // 2小时过期
)
type ActivityLuckyShopData struct {
ID int `gorm:"primarykey"`
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:ut"`
Type int `gorm:"column:type;type:int(11);default:1;uniqueIndex:ut;comment:类型,1是首充小于弹出,2是首充大于弹出,3是付费玩家登录弹出"`
Push int64 `gorm:"column:push;type:bigint(20);default:0;comment:弹窗弹出时间"`
Buy int `gorm:"column:buy;type:tinyint(4);default:0;comment:前面是否已经完成购买"`
ProductID int `gorm:"column:product_id;type:int(11);default:0;comment:商品id"`
}
func (c *ActivityLuckyShopData) TableName() string {
return "activity_lucky_shop_data"
}
func (c *ActivityLuckyShopData) IsValid() bool {
if c.Buy == 1 {
return false
}
return time.Now().Unix()-c.Push < ActivityLuckyShopExpire
}
const (
ActivitySevenDayBoxType = iota
ActivitySevenDayBoxTypeCash
ActivitySevenDayBoxTypeDiscountTicket
ActivitySevenDayBoxTypeAll
)
type ConfigActivitySevenDayBox struct {
ID int `gorm:"primarykey"`
Recharge int64 `gorm:"column:recharge;type:bigint(20);default:10000000000;comment:充值额度" web:"recharge"`
Type int `gorm:"column:type;type:int(11);default:1;comment:奖励类型 1金币 2折扣券" web:"type"`
CashRange string `gorm:"column:cash_range;type:varchar(255);default:[1000000000,2000000000];comment:随机金币范围,当type为1时有用" web:"cash_range"`
Discount int `gorm:"column:discount;type:int(11);default:70;comment:折扣,type为2时有用" web:"discount"`
Per int `gorm:"column:per;type:int(11);default:60;comment:概率" web:"per"`
SubCashRange []int64 `gorm:"-" json:"-"`
ProductID int `gorm:"column:product_id;type:int(11);default:0;comment:商品id" web:"product_id"`
}
func (c *ConfigActivitySevenDayBox) TableName() string {
return "config_activity_seven_day_box"
}
type ActivitySevenDayBoxData struct {
ID int `gorm:"primarykey"`
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
Count int `gorm:"column:count;type:int(11);default:0;comment:剩余开宝箱次数" web:"count"`
Time int64 `gorm:"column:time;type:bigint(20);comment:购买时间"`
}
func (c *ActivitySevenDayBoxData) TableName() string {
return "activity_seven_day_box_data"
}
type ConfigActivitySuper struct {
ID int `gorm:"primarykey"`
Type int `gorm:"column:type;type:int(11);default:1;comment:类型 1新用户 2老用户" web:"type"`
Recharge int64 `gorm:"column:recharge;type:bigint(20);default:20000000000;comment:充值额度" web:"recharge"`
Index int `gorm:"column:index;type:int(11);default:1;comment:奖池编号" web:"index"`
RewardType int `gorm:"column:reward_type;type:bigint(20);default:1;comment:奖励的类型 1金币 2折扣券" web:"reward_type"`
Reward int64 `gorm:"column:reward;default:0;type:bigint(20);comment:奖励的物品数量(折扣券时为折扣数额)" web:"reward"`
Sort int `gorm:"column:sort;type:int(11);default:0;comment:排序" web:"sort"`
Per int `gorm:"column:per;type:int(11);default:60;comment:概率" web:"per"`
ProductID int `gorm:"column:product_id;type:int(11);default:0;comment:商品id" web:"product_id"`
}
func (c *ConfigActivitySuper) TableName() string {
return "config_activity_super"
}
type ActivitySuperData struct {
ID int `gorm:"primarykey"`
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
Open int `gorm:"column:open;default:0;type:int(11);comment:箱子开启情况,二进制"`
Time int64 `gorm:"column:time;type:bigint(20);comment:购买时间"`
Type int `gorm:"-"`
CanBuy bool `gorm:"-"`
}
func (c *ActivitySuperData) TableName() string {
return "activity_super_data"
}

@ -0,0 +1,539 @@
package common
// 重新加载配置的id
const (
ReloadWhiteList = iota + 1
ReloadChannel
ReloadPlatform
ReloadNotice
ReloadBroadcast
ReloadConfigServerVersion // 服务器版本配置
ReloadConfigRWPer // 充提比配置
ReloadConfigActivity // 活动配置
ReloadConfigPayWeight // 支付渠道权重配置
ReloadConfigWithdrawWeight // 退出渠道配置
ReloadConfigPayProduct // 商品配置
ReloadConfigGameSwitch // 游戏开关配置变动
ReloadConfigVip // VIP
ReloadConfigH5 // h5配置
ReloadConfigTron // tron配置
ReloadConfigWithdrawProduct // 退出商品配置
ReloadConfigGameList // 游戏列表配置
ReloadConfigGameProvider // 游戏提供商配置
ReloadConfigGameTypes // 游戏类别配置
ReloadConfigGameMarks // 游戏角标配置
ReloadConfigFirstPageGames // 首页游戏配置
ReloadConfigBroadcast // 广播配置
ReloadConfigCurrencyRateUSD // 汇率配置
ReloadConfigGameRoom // 房间配置
ReloadConfigWater // 水位配置
ReloadConfigRobot // 机器人配置
ReloadConfigAppSpin // 下载app转盘
ReloadConfigShare // 分享相关配置
ReloadConfigShareSys // 分享系统相关配置
ReloadConfigActivityPddSpin // 拼多多转盘配置
ReloadConfigActivityPdd // 拼多多配置
ReloadConfigTask // 任务配置
ReloadConfigCurrencyResource // 奖励来源配置
ReloadConfigFirstPay // 首充配置
ReloadConfigActivityFreeSpin // 免费转盘活动
ReloadConfigActivityFirstRechargeBack // 首日充值返还
ReloadConfigLuckyCode // 幸运码活动
ReloadConfigBanner // banner配置
ReloadConfigActivitySign // 签到配置
ReloadConfigActivityBreakGift // 破产礼包
ReloadConfigShareRobot // 分享机器人
ReloadConfigActivityWeekCard // 周卡
ReloadConfigActivitySlots // slots奖池活动
ReloadConfigActivityLuckyShop // 幸运商店活动
ReloadConfigServerFlag // 服务器配置
ReloadConfigActivitySevenDayBox // 7日宝箱活动
ReloadConfigActivitySuper // 超级1+2
)
// GetConfigStructByType 获取相应配置的结构
func GetConfigStructByType(t int) (interface{}, interface{}) {
switch t {
case ReloadConfigRWPer:
return &ConfigRWPer{}, &[]ConfigRWPer{}
case ReloadConfigActivity:
return &ConfigActivity{}, &[]ConfigActivity{}
case ReloadConfigPayProduct:
return &ConfigPayProduct{}, &[]ConfigPayProduct{}
case ReloadConfigPayWeight:
return &ConfigPayChannels{}, &[]ConfigPayChannels{}
case ReloadConfigWithdrawWeight:
return &ConfigWithdrawChannels{}, &[]ConfigWithdrawChannels{}
case ReloadConfigH5:
return &ConfigH5{}, &[]ConfigH5{}
case ReloadConfigTron:
return &ConfigTron{}, &[]ConfigTron{}
case ReloadConfigWithdrawProduct:
return &ConfigWithdrawProduct{}, &[]ConfigWithdrawProduct{}
case ReloadConfigGameList:
return &ConfigGameList{}, &[]ConfigGameList{}
case ReloadConfigGameProvider:
return &ConfigGameProvider{}, &[]ConfigGameProvider{}
case ReloadConfigGameTypes:
return &ConfigGameType{}, &[]ConfigGameType{}
case ReloadConfigGameMarks:
return &ConfigGameMark{}, &[]ConfigGameMark{}
case ReloadConfigFirstPageGames:
return &ConfigFirstPageGames{}, &[]ConfigFirstPageGames{}
case ReloadConfigBroadcast:
return &ConfigBroadcast{}, &[]ConfigBroadcast{}
case ReloadConfigVip:
return &ConfigVIP{}, &[]ConfigVIP{}
case ReloadConfigCurrencyRateUSD:
return &ConfigCurrencyRateUSD{}, &[]ConfigCurrencyRateUSD{}
case ReloadConfigGameRoom:
return &ConfigGameRoom{}, &[]ConfigGameRoom{}
case ReloadConfigWater:
return &ConfigWater{}, &[]ConfigWater{}
case ReloadConfigRobot:
return &ConfigRobot{}, &[]ConfigRobot{}
case ReloadConfigAppSpin:
return &ConfigAppSpin{}, &[]ConfigAppSpin{}
case ReloadConfigShare:
return &ConfigShare{}, &[]ConfigShare{}
case ReloadConfigShareSys:
return &ConfigShareSys{}, &[]ConfigShareSys{}
case ReloadConfigActivityPddSpin:
return &ConfigActivityPddSpin{}, &[]ConfigActivityPddSpin{}
case ReloadConfigActivityPdd:
return &ConfigActivityPdd{}, &[]ConfigActivityPdd{}
case ReloadConfigTask:
return &ConfigTask{}, &[]ConfigTask{}
case ReloadConfigCurrencyResource:
return &ConfigCurrencyResource{}, &[]ConfigCurrencyResource{}
case ReloadConfigFirstPay:
return &ConfigFirstPay{}, &[]ConfigFirstPay{}
case ReloadConfigActivityFreeSpin:
return &ConfigActivityFreeSpin{}, &[]ConfigActivityFreeSpin{}
case ReloadConfigActivityFirstRechargeBack:
return &ConfigActivityFirstRechargeBack{}, &[]ConfigActivityFirstRechargeBack{}
case ReloadConfigLuckyCode:
return &ConfigActivityLuckyCode{}, &[]ConfigActivityLuckyCode{}
case ReloadConfigBanner:
return &ConfigBanner{}, &[]ConfigBanner{}
case ReloadConfigActivitySign:
return &ConfigActivitySign{}, &[]ConfigActivitySign{}
case ReloadConfigActivityBreakGift:
return &ConfigActivityBreakGift{}, &[]ConfigActivityBreakGift{}
case ReloadConfigShareRobot:
return &ConfigShareRobot{}, &[]ConfigShareRobot{}
case ReloadConfigActivityWeekCard:
return &ConfigActivityWeekCard{}, &[]ConfigActivityWeekCard{}
case ReloadConfigActivitySlots:
return &ConfigActivitySlots{}, &[]ConfigActivitySlots{}
case ReloadConfigActivityLuckyShop:
return &ConfigActivityLuckyShop{}, &[]ConfigActivityLuckyShop{}
case ReloadConfigServerFlag:
return &ConfigServerFlag{}, &[]ConfigServerFlag{}
case ReloadConfigActivitySevenDayBox:
return &ConfigActivitySevenDayBox{}, &[]ConfigActivitySevenDayBox{}
case ReloadConfigActivitySuper:
return &ConfigActivitySuper{}, &[]ConfigActivitySuper{}
default:
return nil, nil
}
}
// 平台配置
// BreakAmount 破产金币
// NewPlayerGift 新玩家初始赠送
// NewGuideFirst 新手引导初始赠送
// NewGuideGift 完成新手引导赠送
// BindPhoneGift 绑定手机赠送
// WithdrawRecharge 退出需付费的金额
// NewControlEnd 新手调控结束阀值
type ConfigPlatform struct {
ID int `gorm:"primarykey"`
NewPlayerGift int64 `gorm:"column:new_player_gift;type:int(11);default:1000;comment:新玩家赠送金币" json:"NewPlayerGift" web:"new_player_gift"`
BindPhoneGift int64 `gorm:"column:bind_phone_gift;type:int(11);default:1000;comment:绑定手机赠送" json:"BindPhoneGift" web:"bind_phone_gift"`
AvatarCount int `gorm:"column:avatar_count;type:int(11);default:400;comment:最大头像数目" json:"AvatarCount" web:"avatar_count"`
CartoonCount int `gorm:"column:cartoon_count;type:int(11);default:15;comment:卡通头像数目" json:"CartoonCount" web:"cartoon_count"`
SmsChannel int `gorm:"column:sms_channel;type:int(11);default:1;comment:短信服务商 1Antgst 2Buka" json:"SmsChannel" web:"sms_channel"`
Telegram string `gorm:"column:telegram;type:varchar(256);default:'+66636640245';comment:客服telegram" json:"Telegram" web:"telegram"`
Whatsapp string `gorm:"column:whatsapp;type:varchar(256);default:'+66636640245';comment:客服whatsapp" json:"Whatsapp" web:"whatsapp"`
Email string `gorm:"column:email;type:varchar(256);default:'rummywallah@gmail.com';comment:客服email" json:"Email" web:"email"`
PayTips string `gorm:"column:pay_tips;type:varchar(256);default:'';comment:充值提示语" json:"PayTips" web:"pay_tips"`
WithdrawTips string `gorm:"column:withdraw_tips;type:varchar(256);default:'';comment:tx提示语" json:"WithdrawTips" web:"withdraw_tips"`
BlackList int `gorm:"column:black_list;type:int(11);default:0;comment:是否开启黑名单 0不开 1开启" json:"BlackList" web:"black_list"`
}
func (c *ConfigPlatform) TableName() string {
return "config_platform"
}
const (
RWPerTypeZero = iota
RWPerTypeFirst
RWPerTypeMulti
RWPerTypeAll
)
// ConfigRWPer 充提比配置
type ConfigRWPer struct {
ID int `gorm:"primarykey"`
Down int64 `gorm:"column:down;type:bigint(20);default:0;comment:充值范围下限" json:"Down" web:"down"`
Up int64 `gorm:"column:up;type:bigint(20);default:0;comment:充值范围上限" json:"Up" web:"up"`
Per int64 `gorm:"column:per;type:int(11);default:10;comment:充提比" json:"Per" web:"per"`
Type int `gorm:"column:type;type:int(11);default:1;comment:类型 1首次 2非首次" json:"Type" web:"type"`
}
func (c *ConfigRWPer) TableName() string {
return "config_rwper"
}
const (
PayKindBank = iota + 1
PayKindTron
)
// ConfigPayProduct
type ConfigPayProduct struct {
ID int `gorm:"primarykey"`
Pic string `gorm:"column:pic;type:varchar(256);default:'';comment:图片" web:"pic"`
ProductID int `gorm:"column:product_id;type:int(11);default:0;comment:商品id" web:"product_id"`
ActivityID int `gorm:"column:activityid;type:int(11);default:0;comment:活动id" web:"activityid"`
Sort int `gorm:"column:sort;type:int(11);default:0;comment:排序" web:"sort"`
Recommend int `gorm:"column:recommend;type:int(11);default:0;comment:是否推荐 1推荐 2不推荐" web:"recommend"`
OriginAmount int64 `gorm:"column:origin_amount;type:bigint(20);default:0;comment:显示价格" web:"origin_amount"`
Amount int64 `gorm:"column:amount;type:bigint(20);default:0;comment:实际价格" web:"amount"`
Value int64 `gorm:"column:value;type:bigint(20);default:0;comment:发放金额" web:"value"`
Type CurrencyType `gorm:"column:type;type:int(11);default:1;comment:货币类型" web:"type"`
IfSell int `gorm:"column:if_sell;type:int(11);default:1;comment:是否上架 1上架 2不上架" web:"if_sell"`
Kind int `gorm:"column:kind;type:int(11);default:1;comment:支付类型 1银行 2区块链" web:"kind"`
Exi int `gorm:"column:exi;type:int(11);default:0;comment:商品额外信息" web:"exi"`
Channels []int `gorm:"-"`
}
func (c *ConfigPayProduct) TableName() string {
return "config_pay_product"
}
// ConfigPayChannels 代收渠道配置
type ConfigPayChannels struct {
ID int `gorm:"primarykey"`
ChannelID int `gorm:"column:channel_id;not null;type:int(11);uniqueIndex:channel_id" web:"ChannelID"`
PayPer int `gorm:"column:pay_per;type:int(11);default:0;comment:代收权重" json:"PayPer" web:"pay_per"`
PayDown int64 `gorm:"column:pay_down;type:bigint(20);default:1;comment:代收下限" json:"PayDown" web:"pay_down"`
PayUp int64 `gorm:"column:pay_up;type:bigint(20);default:1;comment:代收上限" json:"PayUp" web:"pay_up"`
CurrencyType CurrencyType `gorm:"column:currency_type;type:bigint(20);default:1;uniqueIndex:channel_id;comment:货币类型" json:"CurrencyType" web:"currency_type"`
Kind int64 `gorm:"column:kind;type:bigint(20);default:1;comment:协议类型" json:"Kind" web:"kind"`
}
func (c *ConfigPayChannels) TableName() string {
return "config_pay_channels"
}
// ConfigWithdrawChannels 代付渠道配置
type ConfigWithdrawChannels struct {
ID int `gorm:"primarykey"`
ChannelID int `gorm:"column:channel_id;not null;type:int(11);uniqueIndex:channel_id" web:"ChannelID"`
WithdrawPer int `gorm:"column:withdraw_per;type:int(11);default:0;comment:代付权重" json:"WithdrawPer" web:"WithdrawPer"`
PayDown int64 `gorm:"column:pay_down;type:bigint(20);default:1;comment:代收下限" json:"PayDown" web:"pay_down"`
PayUp int64 `gorm:"column:pay_up;type:bigint(20);default:1;comment:代收上限" json:"PayUp" web:"pay_up"`
CurrencyType CurrencyType `gorm:"column:currency_type;type:bigint(20);default:1;uniqueIndex:channel_id;comment:货币类型" json:"CurrencyType" web:"currency_type"`
Kind int64 `gorm:"column:kind;type:bigint(20);default:1;comment:协议类型" json:"Kind" web:"kind"`
}
func (c *ConfigWithdrawChannels) TableName() string {
return "config_withdraw_channels"
}
// ConfigVIP vip配置
// Exp 该等级需要的经验值
// WithdrawCount 每日可代付次数
// Cashback 返利比例(千分位)
// Bonus 等级奖励
// Bet 升级所需下注额
// Fee 代付手续费(千分位)
type ConfigVIP struct {
ID int `gorm:"primarykey;AUTO_INCREMENT;column:id"`
Level int `gorm:"column:level;not null;type:int(11);default:0;comment:vip等级" json:"Level" web:"level"`
Exp int64 `gorm:"column:exp;not null;type:bigint(20);default:0;comment:该等级需要的经验值" json:"Exp" web:"exp"`
WithdrawCount int `gorm:"column:withdraw_count;not null;type:int(11);default:0;comment:每日可代付次数" json:"WithdrawCount" web:"withdraw_count"`
Cashback int64 `gorm:"column:cashback;type:bigint(20);default:0;comment:返利比例千分位" json:"Cashback" web:"cashback"`
Bonus int64 `gorm:"column:bonus;type:bigint(20);default:0;comment:等级奖励" json:"Bonus" web:"bonus"`
Bet int64 `gorm:"column:bet;type:bigint(20);default:0;comment:升级所需下注额" json:"Bet" web:"bet"`
Fee int64 `gorm:"column:fee;type:bigint(20);default:0;comment:手续费率千分比" json:"Fee" web:"fee"`
UFee int64 `gorm:"column:u_fee;type:bigint(20);default:0;comment:u手续费(固定值)" json:"UFee" web:"u_fee"`
}
func (c *ConfigVIP) TableName() string {
return "config_vip"
}
// vip商品类型
const (
VIPProductTypeDay = iota + 1
VIPProductTypeWeek
VIPProductTypeMonth
)
// H5配置
type ConfigH5 struct {
ID int `gorm:"primarykey"`
CollectReward int64 `gorm:"column:collect_reward;type:bigint(20);default:0;comment:收藏奖励" web:"collect_reward"`
DownloadReward int64 `gorm:"column:download_reward;type:bigint(20);default:0;comment:下载奖励" web:"download_reward"`
}
func (c *ConfigH5) TableName() string {
return "config_h5"
}
// ConfigTron
type ConfigTron struct {
ID int `gorm:"primarykey"`
CurrentBlock int64 `gorm:"column:current_block;type:bigint(20);default:0;comment:当前扫描的区块" web:"current_block"`
CurrentBlockTest int64 `gorm:"column:current_block_test;type:bigint(20);default:0;comment:当前扫描的区块(测试链)" web:"current_block_test"`
Rate int64 `gorm:"column:rate;type:bigint(20);default:8193;comment:1U转换成当前货币的汇率,百分位" web:"rate"`
}
func (c *ConfigTron) TableName() string {
return "config_tron"
}
// ConfigWithdrawProduct
type ConfigWithdrawProduct struct {
ID int `gorm:"primarykey"`
Pic string `gorm:"column:pic;type:varchar(256);default:'';comment:图片" web:"pic"`
ProductID int `gorm:"column:product_id;type:int(11);default:0;comment:商品id" web:"product_id"`
Sort int `gorm:"column:sort;type:int(11);default:0;comment:排序" web:"sort"`
Amount int64 `gorm:"column:amount;type:bigint(20);default:0;comment:金额" web:"amount"`
Type CurrencyType `gorm:"column:type;type:int(11);default:1;comment:货币类型" web:"type"`
IfSell int `gorm:"column:if_sell;type:int(11);default:1;comment:是否上架 1上架 2不上架" web:"if_sell"`
Kind int `gorm:"column:kind;type:int(11);default:1;comment:支付类型 1银行 2区块链" web:"kind"`
Channels []int `gorm:"-"`
}
func (c *ConfigWithdrawProduct) TableName() string {
return "config_withdraw_product"
}
// ConfigGameList 游戏列表配置
// GameID 游戏id
// Icon 游戏图标
// URL 跳转url
// GameProvider 提供商id
// Mark 角标
// Sort 排序(玩家每玩一次,sort值会自增1)
// Jackpot 奖池
// Demo 是否支持demo 1支持 2不支持
// SubID 一些游戏有子id 如桌子号
type ConfigGameList struct {
ID int `gorm:"primarykey"`
GameID int `gorm:"column:game_id;not null;type:int(11);uniqueIndex:game;comment:游戏id" web:"game_id"`
GameCode string `gorm:"column:game_code;type:varchar(255);default:'';comment:一些游戏的唯一识别" web:"game_code"`
GameType int `gorm:"column:game_type;not null;type:int(11);comment:游戏类别id" web:"game_type"`
Name string `gorm:"column:name;not null;type:varchar(255);comment:游戏名" web:"name"`
Icon string `gorm:"column:icon;type:varchar(255);comment:游戏图标" web:"icon"`
URL string `gorm:"column:url;type:varchar(255);comment:跳转地址" web:"url"`
GameProvider int `gorm:"column:game_provider;not null;type:int(11);uniqueIndex:game;comment:游戏提供商" web:"game_provider"`
Mark int `gorm:"column:mark;default:0;type:int(11);comment:角标" web:"mark"`
Sort uint64 `gorm:"column:sort;type:bigint(20);comment:游戏排序,玩家每玩一次,sort值会自增1" web:"sort"`
Open int `gorm:"column:open;type:int(11);default:1;comment:是否开启 1开2不开" web:"open"`
Orientation int `gorm:"column:orientation;type:int(11);default:1;comment:横屏竖屏 1竖屏2横屏3两者都可" web:"orientation"`
Demo int `gorm:"column:demo;type:int(11);default:1;comment:是否支持demo 1支持 2不支持" web:"demo"`
SubID string `gorm:"column:subid;type:varchar(255);default:'';comment:一些游戏有子id" web:"subid"`
Jackpot int64 `gorm:"-" web:"-"`
}
func (c *ConfigGameList) TableName() string {
return "config_game_list"
}
// ConfigGameProvider 游戏提供商配置
type ConfigGameProvider struct {
ID int `gorm:"primarykey"`
ProviderID int `gorm:"column:provider_id;not null;type:int(11);uniqueIndex:id;comment:游戏提供商id"`
ProviderName string `gorm:"column:provider_name;type:varchar(255);comment:游戏提供商名称" web:"provider_name"`
Icon string `gorm:"column:icon;type:varchar(255);comment:供应商图标" web:"icon"`
Sort int `gorm:"column:sort;type:int(11);comment:供应商排序" web:"sort"`
Callback string `gorm:"column:callback;type:varchar(255);comment:回调地址" web:"callback"`
WhiteIPs string `gorm:"column:white_ips;type:varchar(1024);comment:ip白名单" web:"white_ips"`
SubIp []string `gorm:"-" web:"-"`
GamesNum int `gorm:"-" web:"-"`
Open int `gorm:"column:open;type:int(11);default:1;comment:是否开启 1开2不开" web:"open"`
Show int `gorm:"column:show;type:int(11);default:1;comment:是否显示在banner栏 1显示2不显示" web:"show"`
Method int `gorm:"column:method;type:int(11);default:1;comment:打开方式 1正常url 2html格式" web:"method"`
}
func (c *ConfigGameProvider) TableName() string {
return "config_game_provider"
}
func (c *ConfigGameProvider) IsIpWhite(ip string) bool {
if len(c.SubIp) == 0 {
return true
}
for _, v := range c.SubIp {
if v == ip {
return true
}
}
return false
}
type ConfigGameType struct {
ID int `gorm:"primarykey"`
TypeID int `gorm:"column:type_id;not null;type:int(11);uniqueIndex:type_id;comment:游戏类别id" web:"type_id"`
TypeName string `gorm:"column:type_name;type:varchar(64);comment:游戏类别名" web:"type_name"`
Icon string `gorm:"column:icon;type:varchar(255);comment:游戏类别图标" web:"icon"`
Sort int `gorm:"column:sort;type:int(11);comment:排序" web:"sort"`
Open int `gorm:"column:open;type:int(11);default:0;comment:是否打开 1打开" web:"open"`
}
func (c *ConfigGameType) TableName() string {
return "config_game_type"
}
type ConfigGameMark struct {
ID int `gorm:"primarykey"`
MarkID int `gorm:"column:mark_id;not null;type:int(11);uniqueIndex:type_id;comment:游戏角标id" web:"mark_id"`
MarkName string `gorm:"column:mark_name;type:varchar(64);comment:游戏角标名" web:"mark_name"`
Icon string `gorm:"column:icon;type:varchar(255);comment:游戏角标图标" web:"icon"`
Sort int `gorm:"column:sort;type:int(11);comment:排序" web:"sort"`
}
func (c *ConfigGameMark) TableName() string {
return "config_game_mark"
}
type ConfigFirstPageGames struct {
ID int `gorm:"primarykey"`
Icon string `gorm:"column:icon;type:varchar(255);comment:游戏标题图标" web:"icon"`
Name string `gorm:"column:name;type:varchar(64);comment:游戏标题名" web:"name"`
JumpType int `gorm:"column:jump_type;default:1;type:int(11);comment:跳转类型 1type 2mark" web:"jump_type"`
JumpID int `gorm:"column:jump_id;default:1;type:int(11);comment:跳转查询id" web:"jump_id"`
Sort int `gorm:"column:sort;type:int(11);comment:排序" web:"sort"`
Open int `gorm:"column:open;type:int(11);default:0;comment:是否打开 1打开" web:"open"`
}
func (c *ConfigFirstPageGames) TableName() string {
return "config_first_page_games"
}
type ConfigBroadcast struct {
ID int `gorm:"primarykey"`
BroadcastID int `gorm:"column:broadcast_id;type:int(11);comment:广播类型id" web:"broadcast_id"`
Content string `gorm:"column:content;type:varchar(255);comment:广播正文" web:"content"`
Open int `gorm:"column:open;type:int(11);comment:是否打开 1打开" web:"open"`
Event int `gorm:"column:event;type:int(11);comment:事件" web:"event"`
TargetID int `gorm:"column:target_id;type:int(11);comment:跳转id" web:"target_id"`
Type int `gorm:"column:type;type:int(11);comment:类型" web:"type"`
Priority int `gorm:"column:priority;type:int(11);comment:优先级" web:"priority"`
LoopFrequency int `gorm:"column:loop_frequency;type:int(11);comment:循环次数" web:"loop_frequency"`
Interval int `gorm:"column:interval;type:int(11);comment:间隔" web:"interval"`
ConditionDown int `gorm:"column:condition_down;type:int(11);comment:触发条件下限" web:"condition_down"`
ConditionUp int `gorm:"column:condition_up;type:int(11);comment:触发条件上限" web:"condition_up"`
}
func (c *ConfigBroadcast) TableName() string {
return "config_broadcast"
}
type ConfigNotice struct {
ID int `gorm:"primarykey"`
Title1 string `gorm:"column:title1;type:varchar(255);comment:标题1" web:"title1"` // 公告标题_1(英语)
Content1 string `gorm:"column:content1;type:varchar(255);comment:正文1" web:"content1"` // 公告内容_1(英语)
Title2 string `gorm:"column:title2;type:varchar(255);comment:标题2" web:"title2"` // 公告标题_2
Content2 string `gorm:"column:content2;type:varchar(255);comment:正文2" web:"content2"` // 公告内容_2
Type int `gorm:"column:type;type:int(11);comment:公告类型 (1.紧急 2.常规)" web:"type"` // 公告类型 (1.紧急 2.常规)
Open int `gorm:"column:open;type:int(11);comment:是否打开 1打开" web:"open"` // 是否发布
Method int `gorm:"column:method;type:int(11);comment:发布方式" web:"method"` // 发布方式
Time int64 `gorm:"column:time;type:int(11);comment:发布时间" web:"time"` // 发布时间
Interval int `gorm:"column:interval;type:int(11);comment:间隔" web:"interval"`
PushTimes int `gorm:"column:push_times;type:int(11);comment:推送次数" web:"push_times"` // 推送次数
}
func (c *ConfigNotice) TableName() string {
return "config_notice"
}
// 货币汇率(各种货币转换成美元的汇率)
type ConfigCurrencyRateUSD struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id"`
CurrencyType CurrencyType `gorm:"column:currency_type;type:int(11);default:1;comment:货币类型"`
Rate int64 `gorm:"column:rate;type:int(11);default:1;comment:汇率(万分位)"`
RefreshTime int64 `gorm:"column:refresh_time;type:bigint(20);default:0;comment:刷新时间,一天刷一次"`
}
func (c *ConfigCurrencyRateUSD) TableName() string {
return "config_currency_rate_usd"
}
type ConfigGameRoom struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id"`
GameID int `gorm:"column:game_id;type:int(11);default:0;comment:游戏id" web:"game_id"`
RoomID int `gorm:"column:room_id;type:int(11);default:0;comment:房间id" web:"room_id"`
RoomName string `gorm:"column:room_name;type:varchar(64);default:0;comment:房间名字" web:"room_name"`
RoomType int `gorm:"column:room_type;type:int(11);default:0;comment:房间类型 1金币 2练习" web:"room_type"`
Open bool `gorm:"column:open;type:int(11);default:0;comment:是否开放 0不开 1开" web:"open"`
Initial int64 `gorm:"column:initial;type:int(11);default:0;comment:初始额度" web:"initial"`
BetTime int64 `gorm:"column:bet_time;type:int(11);default:0;comment:下注时长" web:"bet_time"`
SettleTime int64 `gorm:"column:settle_time;type:int(11);default:0;comment:结算时长" web:"settle_time"`
MaxSeats int `gorm:"column:max_seats;type:int(11);default:0;comment:座位数" web:"max_seats"`
BetLimitStr string `gorm:"column:bet_limit_str;type:varchar(256);default:'[0]';comment:下注限额数组形式[0,0]" web:"bet_limit_str"`
BetLimit []int64 `gorm:"-" json:"-"`
}
func (c *ConfigGameRoom) TableName() string {
return "config_game_room"
}
// 水位
type ConfigWater struct {
ID int `gorm:"primarykey"`
GameID int `gorm:"column:game_id;not null;type:int(11);comment:游戏id" json:"GameID" web:"game_id"`
RoomID int `gorm:"column:room_id;not null;type:int(11);comment:房间id" json:"RoomID" web:"room_id"`
WaterLower int64 `gorm:"column:water_lower;not null;type:bigint(20);comment:下水位" json:"WaterLower" web:"water_lower"`
WaterUp int64 `gorm:"column:water_up;not null;type:bigint(20);comment:上水位" json:"WaterUp" web:"water_up"`
// ControlPer int `gorm:"column:control_per;not null;type:int(11);comment:控制概率" json:"ControlPer" web:"control_per"`
// RebatePer int64 `gorm:"column:rebate_per;not null;type:int(11);comment:返税比例" json:"RebatePer" web:"rebate_per"`
Value int64 `gorm:"column:vale;not null;type:bigint(20);comment:当前水位" web:"value"`
Rtp int64 `gorm:"column:rtp;not null;type:int(11);comment:正常时候的rtp,万分位" web:"rtp"`
DownRtp int64 `gorm:"column:down_rtp;not null;type:int(11);comment:下水位的rtp,万分位" web:"down_rtp"`
UpRtp int64 `gorm:"column:up_rtp;not null;type:int(11);comment:上水位的rtp,万分位" web:"up_rtp"`
}
func (c *ConfigWater) TableName() string {
return "config_water"
}
// 机器人
type ConfigRobot struct {
ID int `gorm:"primarykey"`
Avatar string `gorm:"column:avatar;type:varchar(512);default:''" web:"avatar"`
Nick string `gorm:"column:nick;type:varchar(512);default:''" web:"nick"`
}
func (c *ConfigRobot) TableName() string {
return "config_robot"
}
// 下载app奖励转盘
type ConfigAppSpin struct {
ID int `gorm:"primarykey"`
Amount int64 `gorm:"column:amount;type:bigint(20);default:0" web:"amount"`
CurrencyType CurrencyType `gorm:"column:type;type:int(11);default:1;comment:货币类型" web:"type"`
Sort int `gorm:"column:sort;type:int(11);default:1;comment:排序" web:"sort"`
Weight int `gorm:"column:weight;type:int(11);default:1;comment:权重" web:"weight"`
}
func (c *ConfigAppSpin) TableName() string {
return "config_app_spin"
}
// ConfigCurrencyResource 奖励来源配置
type ConfigCurrencyResource struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id"`
Type CurrencyRes `gorm:"column:type;type:int(11);default:0;uniqueIndex:type;comment:奖励类型" web:"type"`
Multiple int64 `gorm:"column:multiple;type:bigint(20);default:2000;comment:所需下注倍数,百分位" web:"multiple"`
}
func (c *ConfigCurrencyResource) TableName() string {
return "config_Currency_resource"
}

@ -0,0 +1,239 @@
package common
import (
"fmt"
"reflect"
"strconv"
"strings"
"gorm.io/gorm"
)
// 货币类型
type CurrencyType int
const (
CurrencyTypeZero CurrencyType = iota
CurrencyBrazil
CurrencyUSDT
CurrencyAll
)
type CurrencyRes int
// 货币来源(会影响所需下注量)
const (
CurrencyResourceZero CurrencyRes = iota
CurrencyResourceRecharge // 一般充值
CurrencyResourceBonus // 额外赠送
CurrencyResourceAll
)
const (
USDTKindZero = iota
USDTKindTRC20
USDTKindAll
)
func (t CurrencyType) IsValid() bool {
return t > CurrencyTypeZero && t < CurrencyAll
}
func (t CurrencyType) GetCurrencyName() string {
return strings.ToLower(reflect.TypeOf(PlayerCurrency{}).Field(int(t + 1)).Name)
}
func (t CurrencyType) GetRechargeInfoTable() string {
return fmt.Sprintf("recharge_info_%s", t.GetCurrencyName())
}
func GetCurrencyID(currency string) CurrencyType {
str := strings.ToUpper(currency)
ref := reflect.ValueOf(PlayerCurrency{})
reft := reflect.TypeOf(PlayerCurrency{})
for i := 2; i < ref.NumField(); i++ {
if reft.Field(i).Name == str {
return CurrencyType(i - 1)
}
}
return 0
}
type CurrencyEvent int
const (
CurrencyEventZero CurrencyEvent = iota // 无意义
CurrencyEventNewPlayer // 新注册赠送
CurrencyEventGameSettle // 游戏场结算
CurrencyEventGameBet // 游戏场牌局模式下注
CurrencyEventGameCancelBet // 取消下注
CurrencyEventReCharge // 充值
CurrencyEventWithDraw // 退出
CurrencyEventWithDrawBack // 退出失败退回
CurrencyEventMailDraw // 邮件领取
CurrencyEventGameVoidSettle // 游戏取消结算
CurrencyEventGameActivity // 游戏场活动赠与
CurrencyEventGameReSettle // 游戏场调整结算
CurrencyEventGameAdjustment // 游戏场调整余额
CurrencyEventBindPhone // 绑定手机奖励
CurrencyEventVIPBonus // 领取vip等级奖励
CurrencyEventVIPCashback // 领取vip返利
CurrencyEventActivityAppSpin // 下载app转盘奖励
CurrencyEventShareWithdraw // 分享奖励领取
CurrencyEventActivityPdd // pdd分享奖励领取
CurrencyEventGameAdjustBet // 投注额调整
CurrencyEventGameBonus // 游戏场bonus
CurrencyEventGameJackpot // 游戏场jackpot
CurrencyEventGameBuyIn // 游戏场扣钱操作
CurrencyEventGameBuyOut // 游戏场加钱操作
CurrencyEventTask // 任务奖励
CurrencyEventActivityFreeSpin // 免费旋转
CurrencyEventActivityFirstRechargeBack // 首日充值返还
CurrencyEventActivityLuckyCode // 兑换码活动
CurrencyEventActivitySign // 签到活动
CurrencyEventActivityBreakGift // 破产礼包活动
CurrencyEventActivityWeekCard // 周卡
CurrencyEventActivitySlots // slots奖池
CurrencyEventActivitySuper // 超级1+2
CurrencyEventAll
CurrencyEventGM = 1000 // 后台修改货币
CurrencyEventGMRecharge = 1001 // 后台模拟充值
)
func GetCurrencyTypeName(ct CurrencyEvent) string {
switch ct {
case CurrencyEventNewPlayer:
return "新增注册赠送"
case CurrencyEventGameSettle:
return "游戏场结算"
case CurrencyEventGameBet:
return "游戏场下注"
case CurrencyEventGameCancelBet:
return "游戏场取消下注"
case CurrencyEventReCharge:
return "充值"
case CurrencyEventWithDraw:
return "退出"
case CurrencyEventWithDrawBack:
return "退出失败返回"
case CurrencyEventMailDraw:
return "邮件领取"
case CurrencyEventGameVoidSettle:
return "游戏场取消结算"
case CurrencyEventGameActivity:
return "游戏场活动赠与"
case CurrencyEventGameReSettle:
return "游戏场调整结算"
case CurrencyEventGameAdjustment:
return "游戏场调整余额"
case CurrencyEventBindPhone:
return "绑定手机奖励"
case CurrencyEventVIPBonus:
return "领取vip等级奖励"
case CurrencyEventVIPCashback:
return "领取输钱返利"
case CurrencyEventActivityAppSpin:
return "下载转盘奖励"
case CurrencyEventShareWithdraw:
return "分享奖励领取"
case CurrencyEventActivityPdd:
return "拼多多奖励领取"
case CurrencyEventGameAdjustBet:
return "调整投注"
case CurrencyEventGameBonus:
return "游戏场bonus奖励"
case CurrencyEventGameJackpot:
return "游戏场jackpot奖励"
case CurrencyEventGameBuyIn:
return "游戏场扣钱操作"
case CurrencyEventGameBuyOut:
return "游戏场加钱操作"
case CurrencyEventGM:
return "后台修改货币"
case CurrencyEventGMRecharge:
return "后台模拟充值"
case CurrencyEventTask:
return "领取任务奖励"
case CurrencyEventActivityFreeSpin:
return "免费转盘"
case CurrencyEventActivityFirstRechargeBack:
return "首充返还"
case CurrencyEventActivityLuckyCode:
return "幸运码活动"
case CurrencyEventActivitySign:
return "签到"
case CurrencyEventActivityBreakGift:
return "破产礼包活动"
case CurrencyEventActivityWeekCard:
return "周卡活动"
case CurrencyEventActivitySlots:
return "slots奖池活动"
case CurrencyEventActivitySuper:
return "超级1+2活动"
}
return strconv.Itoa(int(ct))
}
func GetGameEvents() []interface{} {
return []interface{}{CurrencyEventGameSettle, CurrencyEventGameBet, CurrencyEventGameCancelBet, CurrencyEventGameVoidSettle,
CurrencyEventGameActivity, CurrencyEventGameReSettle, CurrencyEventGameAdjustment, CurrencyEventGameAdjustBet,
CurrencyEventGameBonus, CurrencyEventGameJackpot, CurrencyEventGameBuyIn, CurrencyEventGameBuyOut}
}
// 游戏投入
func GetGameInEvents() []interface{} {
return []interface{}{CurrencyEventGameBet, CurrencyEventGameCancelBet, CurrencyEventGameAdjustBet, CurrencyEventGameBuyIn}
}
// 游戏产出
func GetGameOutEvents() []interface{} {
return []interface{}{CurrencyEventGameSettle, CurrencyEventGameVoidSettle,
CurrencyEventGameActivity, CurrencyEventGameReSettle, CurrencyEventGameAdjustment,
CurrencyEventGameBonus, CurrencyEventGameJackpot, CurrencyEventGameBuyOut}
}
// RoundCurrency 去除法币的无意义小数位数
func RoundCurrency(t CurrencyType, amount int64) int64 {
switch t {
case CurrencyBrazil:
return amount / 1e6 * 1e6
case CurrencyUSDT:
return amount / 100 * 100
default:
return amount
}
}
type UpdateCurrency struct {
NotNotify bool // 为true时不通知客户端
Tx *gorm.DB
*CurrencyBalance
}
// Time 时间
// Value 变化的值
// Event 事件
// Type 货币类型
type CurrencyBalance struct {
Id int `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"id" redis:"id"`
UID int `gorm:"column:uid" json:"uid"`
Time int64 `gorm:"column:time" json:"time"`
Value int64 `gorm:"column:value" json:"value"`
Balance int64 `gorm:"column:balance;type:bigint(20);default:0" json:"balance"`
Event CurrencyEvent `gorm:"column:event" json:"event"`
Type CurrencyType `gorm:"column:type" json:"type"`
ChannelID int `gorm:"column:channel_id;type:bigint(20);default:1;comment:渠道id" json:"channel_id"`
NeedBet int64 `gorm:"column:resource;type:bigint(20);default:0;comment:本次流水增加的打码量" json:"need_bet"`
Exi1 int `gorm:"column:exi1;type:bigint(20);default:0;comment:额外int字段1" json:"exi1"`
Exi2 int `gorm:"column:exi2;type:bigint(20);default:0;comment:额外int字段2" json:"exi2"`
Exi3 int `gorm:"column:exi3;type:bigint(11);default:0;comment:额外int字段3" json:"exi3"`
Exs1 string `gorm:"column:exs1;type:varchar(64);comment:额外string字段1" json:"exs1"`
Exs2 string `gorm:"column:exs2;type:varchar(64);comment:额外string字段2" json:"exs2"`
Exs3 string `gorm:"column:exs3;type:varchar(64);comment:额外string字段3" json:"exs3"`
}
func (c *CurrencyBalance) TableName() string {
return fmt.Sprintf("currency_balance_%02d", c.UID%100)
}

@ -0,0 +1,89 @@
package common
import "server/pb"
// type Mail struct {
// ID int `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"id" redis:"id"`
// Sender int `gorm:"column:sender;type:int(11);default:0;comment:发件人uid,系统为0" json:"sender" redis:"sender"`
// Receiver int `gorm:"column:receiver;type:int(11);default:0;comment:收件人uid,系统为0" json:"receiver" redis:"receiver"`
// }
const (
MailExpireTime = 30 * 24 * 60 * 60 // 30天
MailMaxCount = 100
)
const (
MailTypeNormal = iota + 1
MailTypeUrgent
)
const (
MailSendMethodImmediately = iota + 1
MailSendMethodTiming
)
const (
MailStatusDelete = iota
MailStatusNew
MailStatusRead
MailStatusDraw
)
// Mail 邮件
// DraftID 发送邮件的模板id
// sender 发件人
// Receiver 收件人uid 0是系统邮件
// Type 邮件类型 1跳转游戏
// Status 邮件状态 0删除 1未读 2已读未领取 3已领取
// Time 收到邮件的时间
type Mail struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"ID"`
DraftID string `gorm:"column:draft_id;type:varchar(256);comment:发送邮件的模板id" json:"DraftID"`
Sender string `gorm:"column:sender;type:varchar(64);default:0;comment:发件人名称" json:"Sender"`
Receiver int `gorm:"column:receiver;type:int(11);default:0;comment:收件人uid,系统为0" json:"Receiver"`
Tag int `gorm:"column:tag;type:int(11);default:1;comment:页签 1平台 2个人" json:"Tag"`
Type int `gorm:"column:type;type:int(11);default:0;comment:邮件类型 1正常 2紧急" json:"Type"`
Data string `gorm:"column:data;type:varchar(512);default:'';comment:数据" json:"Data"`
Title string `gorm:"column:title;type:varchar(256);default:0;comment:标题" json:"Title"`
Content string `gorm:"column:content;type:varchar(512);default:0;comment:正文" json:"Content"`
Status int `gorm:"column:status;type:tinyint(4);default:1;comment:邮件状态 0删除 1未读 2已读未领取 3已领取" json:"Status"`
Time int64 `gorm:"column:time;type:bigint(20);default:0;comment:收到邮件时间" json:"Time"`
}
func (u *Mail) TableName() string {
return "mail"
}
const (
MailDraftStatusDelete = iota
MailDraftStatusNew
MailDraftStatusSent
MailDraftStatusBack // 撤销
)
// MailDraft 邮件草稿
// ID 草稿ID
// sender 发件人
// Receiver 收件人uid(可以是数组),空数组代表所有人
// Type 邮件类型 1正常 2紧急
// Enclosure 附件
// SendMethod 发送方式 1立刻 2定时
// SendTime 发送时间
// Status 邮件状态 0删除 1未发送 2已发送 3已撤销
// Operator 操作人
// Time 创建或修改的时间戳
type MailDraft struct {
ID string
Sender string
Receiver []int
Type int
Title string
Content string
Enclosure []*pb.CurrencyPair
SendMethod int
SendTime int64
Status int
Operator string
Time int64
}

@ -0,0 +1,331 @@
package common
const (
ESIndexBalance = "bal" // 流水记录,改为别名
ESIndexJackpot = "jackpot" // 游戏奖池中奖记录
ESIndexLongPay = "long_pay" // 充值返回速度过慢记录
ESIndexTron = "tron" // tron转账记录
ESIndexGameData = "game_data" // 玩家游戏记录
ESIndexShareProfitReport = "share_profit_report" // 分享者每日收益汇总
ESIndexShareProfitRecord = "share_profit_record" // 分享者所有推荐人贡献的每日收益详情
)
// backend
const (
ESIndexBackMailDraft = "back_mail_draft" // 后台邮件草稿
ESIndexBackWhiteList = "back_white_list" // 后台白名单
ESIndexBackPlayerOnline = "back_player_online" // 后台在线统计
ESIndexBackExamineList = "back_examine_list" // 后台审核人员名单
ESIndexBackWarn = "back_warn" // 后台预警
ESIndexBackDailyData = "back_daily_data" // 后台每日统计数据
ESIndexBackOpenRecord = "back_open_record" // 后台统计玩家打开安装数
ESIndexBackIncomeStatistics = "back_income_statistics" // 后台收入统计
ESIndexBackPlayerPayData = "back_player_pay_data" // 后台玩家充值/退出统计
ESIndexBackReviewData = "back_review_data" // 数据概要
ESIndexBackAppSummary = "back_app_summary" // 应用概要
ESIndexBackRechargeFrequency = "back_recharge_frequency" // 付费分析
ESIndexBackKeepData = "back_keep_data" // 留存
ESIndexBackBlackList = "back_black_list" // 封号拉黑的玩家
ESIndexBackABLog = "back_ab_log" // 玩家进入ab面统计
ESIndexBackMillionGameRecord = "back_million_game_record"
ESIndexBackMillionPlayerRecord = "back_million_player_record"
ESIndexBackPddRecord = "back_pdd_record"
ESIndexBackFeedback = "back_feedback"
ESIndexBackActivity = "back_activity"
)
// GroupBuckets group聚合查询对象
type GroupBuckets struct {
Buckets []struct {
Key interface{}
Doc_count int
}
}
// GroupCardBuckets group聚合查询对象
type GroupCardBuckets struct {
Buckets []struct {
Key interface{}
Doc_count int
Sub struct {
Value int
}
}
}
// Group2CardBuckets group聚合查询对象
type Group2CardBuckets struct {
Buckets []struct {
Key interface{}
Doc_count int
Sub1 struct {
Buckets []struct {
Key interface{}
Doc_count int
Sub2 struct {
Value int
}
}
}
}
}
// GroupSumBuckets group聚合查询对象
type GroupSumBuckets struct {
Buckets []struct {
Key interface{}
Doc_count int
Value struct {
Value float64
}
}
}
// Group2SumBuckets group聚合查询对象
type Group2SumBuckets struct {
Buckets []struct {
Key interface{}
Doc_count int
Sub1 struct {
Buckets []struct {
Key interface{}
Doc_count int
Sub2 struct {
Value float64
}
}
}
}
}
// SumByResult sum聚合查询对象
type SumByResult struct {
Value float64
}
// ESPlayerStats 玩家充值/退出记录表
type ESPlayerPayData struct {
ID string `json:"-"`
UID int `json:"UID"`
Channel int `json:"Channel"`
Time int64 `json:"Time"`
IsNew bool `json:"IsNew"`
Type int `json:"Type"` // 类型 1充值 2退出
CurrencyType CurrencyType `json:"CurrencyType"`
Amount int64 `json:"Amount"` // 充值/退出金额
FirstAmount int64 `json:"FirstAmount"` // 是否是首次,如果是,则金额大于0
}
type ESNewOnline struct {
Channel int `json:"Channel"`
Time int64 `json:"Time"`
Total int `json:"Total"`
GameID int `json:"GameID"`
Recharge int `json:"Recharge"`
New int `json:"New"`
Old int `json:"Old"`
}
// ESNewOnlineBucket 在线聚合对象
type ESNewOnlineBucket struct {
Buckets []struct {
Key interface{}
Doc_count int
Total struct {
Value float64
}
Recharge struct {
Value float64
}
New struct {
Value float64
}
Old struct {
Value float64
}
}
}
// ESDailySysData 每日系统统计的一些数据
// USDT USDT总量
// BRL BRL总量
// Time 统计日零点时间戳
// Date 日期
type ESDailySysData struct {
Date string
Channel int
Time int64
USDT int64
BRL int64
}
// ESOpenRecord 统计安装打开app的数目
type ESOpenRecord struct {
Time int64
UUID string
Channel int
}
// ESGameJackpot 游戏场jackpot大奖记录
type ESGameJackpot struct {
UID int // 用户uid
Nick string // 用户昵称
Time int64 // 时间
Avatar string // 用户头像
Channel int // 渠道
Bet int64 // 投注总额
Get int64 // 获得的奖励
Total int64 // 总奖励
GameID int
RoomID int
Winners int // 瓜分奖池的总玩家
Multi int // 倍率
}
// ESBlackList 游戏拉黑玩家
type ESBlackList struct {
UID int // 用户uid
Name string
Phone string
Email string
PayAccount string
Time int64
}
// ESLongPay 充值返回记录
type ESLongPay struct {
Channel int
Time int64
Date string
Cost int64 // 时间消耗单位毫秒
UID int
Amount int64
}
// ESTron 转账记录
type ESTron struct {
TxID string // 交易号
From string
To string
OrderID string // 系统订单号
Amount int64
Time int64
Type int // 1trx 2usdt
Success bool
Status int // 1玩家退出打u 2系统自动从玩家地址转u回主地址 3后台转账操作
}
// ESABLog 进入ab面统计
type ESABLog struct {
Channel int
Time int64
DeviceID string
IsA bool // 是否进入A面
Log string // 日志记录
}
// ESGameData 玩家游戏记录
type ESGameData struct {
UID int // 用户uid
Channel int
Provider int // 提供商
GameID int // 游戏id
UUID string // 厂商唯一id
Type CurrencyType
BetAmount int64 // 下注金额
SettleAmount int64 // 输赢金额
MyUUID string // 自己的唯一id
Time int64
Birth int64
PlayTime int64
SubID int
IsNew bool
}
// ESIncomeStatistics 收入统计
// Investment 投入资金
// Period 回本周期
type ESIncomeStatistics struct {
Time int64 // 时间
Channel int // 渠道
Investment int64 // 投入资金
Period int64 // 回本周期
}
// ESMillionGameRecord 百人模式游戏数据统计
type ESMillionGameRecord struct {
Time int64
GameID int // 游戏id
RoomID int // 场次id
UUID string
PlayerCount int // 本局总人数
PlayerBet int64 // 用户下注金额
Reward int64 // 发放金额
Profit int64 // 盈亏
Result string // 开奖结果
ResultDetail string // 开奖结果 具体的牌/骰子
Channel int
Area int // 区域
IsWin bool // 该区域是否获胜
}
// ESMillionPlayerRecord 百人模式游戏数据统计
type ESMillionPlayerRecord struct {
UID int
Time int64
GameID int // 游戏id
RoomID int // 场次id
UUID string
Settle int64 // 本局结算结果
Result string // 开奖结果
Channel int
Bets []int64
}
// ESShareProfitReport 分享者每日分享收益记录
type ESShareProfitReport struct {
UID int // 分享者
Regist int64 // 注册人数
Bet int64 // 有效下注
Level int // 分享者等级
Reward int64
Date string
Time int64
}
// ESShareProfitRecord 分享推荐收益记录
type ESShareProfitRecord struct {
UID int // 被分享人
Bet int64 // 被分享人投注
DownBet int64 // 被分享人的下级投注总和
Up int // 分享者uid
Reward int64 // 佣金
Date string
Time int64
}
// UID int 被分享人
// Referer int 分享人
type ESPddRecord struct {
UID int // 被分享人
Referer int // 分享人
Time int64
Nick string
Avatar string
}
type ESFeedback struct {
UID int
QuestionIndex int
Choose int
Context string
Time int64
}
type ESActivity struct {
ActivityID int
UID int
Time int64
Type int // 1点击 2参与
Amount int64 // 赠送金额
}

@ -0,0 +1,79 @@
package common
import "fmt"
const (
JackpotTypeActivity = iota + 1
JackpotTypeGame
)
var (
GameModulePrefix = "game" // 游戏模块名字前缀
)
func GetGameModuleName(gid int) string {
return fmt.Sprintf("%v%v", GameModulePrefix, gid)
}
// Jackpot 记录各个奖池
type Jackpot struct {
ID int `gorm:"primarykey"`
Type int `gorm:"column:type;not null;type:int(11);comment:类型 活动1 游戏2" json:"Type"`
TypeID int `gorm:"column:type_id;not null;type:int(11);uniqueIndex:type_id;comment:奖池标记id,可以是活动id,游戏id" json:"TypeID"`
Amount int64 `gorm:"column:amount;type:bigint(20);default:0;comment:奖池" json:"Amount"`
Max int64 `gorm:"column:max;type:bigint(20);default:0;comment:奖池最大额度" json:"Max"`
}
func (j *Jackpot) TableName() string {
return "jackpot"
}
const (
SessionTypeBet = iota + 1
SessionTypeSettle
SessionTypeActivity
SessionTypeAdjustment // 调整玩家余额
SessionTypeJackpot
SessionTypeBonus
SessionTypeBuyIn // 直接扣钱操作
SessionTypeBuyOut // 直接加钱操作
)
// 提供商下单记录
type ProviderBetRecord struct {
ID int `gorm:"primarykey"`
UID int `gorm:"column:uid;not null;type:int(11);index:uid;comment:uid"`
Provider int `gorm:"column:provider;not null;type:int(11);uniqueIndex:p_uuid;comment:供应商id"`
Currency string `gorm:"column:currency;type:varchar(64);comment:货币名称"`
CurrencyType CurrencyType `gorm:"column:currency_type;default:1;type:int(11);comment:货币id"`
GameID int `gorm:"column:game_id;not null;type:int(11);comment:游戏id"`
GameName string `gorm:"column:game_name;type:varchar(64);default:'';comment:游戏名"`
UUID string `gorm:"column:uuid;type:varchar(255);uniqueIndex:p_uuid;comment:供应商唯一识别值"`
SessionID string `gorm:"column:session_id;type:varchar(255);comment:牌局类型时的牌局id"`
Type int `gorm:"column:type;type:bigint(20);uniqueIndex:p_uuid;comment:类型 1下注 2结算"`
Time int64 `gorm:"column:time;type:bigint(20);default:0;comment:时间戳"`
ProviderTime int64 `gorm:"column:provider_time;type:bigint(20);default:0;comment:厂商时间戳"`
Amount int64 `gorm:"column:amount;type:bigint(20);default:0;comment:下注额"`
Settle int64 `gorm:"column:settle;type:bigint(20);default:0;comment:结算额"`
Preserve int64 `gorm:"column:preserve;type:bigint(20);default:0;comment:预扣款"`
TurnOver int64 `gorm:"column:turnover;type:bigint(20);default:0;comment:有效投注额"`
MyUUID int64 `gorm:"column:my_uuid;type:bigint(20);comment:我方唯一识别值"`
Esi int64 `gorm:"column:esi;type:bigint(20);default:1;comment:额外字段"` // tada 表示本局是否已失败 2已失败,后续不再接收
Esi1 int64 `gorm:"column:esi1;type:bigint(20);default:1;comment:额外字段1"` // awc标识注单无效原因
Ess string `gorm:"column:ess;type:varchar(64);default:'';comment:额外字符串字段"` // 活动时,标识活动代码
}
func (t *ProviderBetRecord) TableName() string {
return "provider_bet_record"
}
const (
GameType = iota
GameTypeInHouse
GameTypeSlots
GameTypeLive
GameTypeTable
GameTypeSpecial
GameTypeESport
GameTypeSportBook
)

@ -0,0 +1,20 @@
package common
const (
EN = "en"
PT = "pt"
)
func IsLangValid(lan string) bool {
if lan != EN && lan != PT {
return false
}
return true
}
func CheckLang(lan string) string {
if lan != EN && lan != PT {
return EN
}
return lan
}

@ -0,0 +1,373 @@
package common
import (
"fmt"
"server/util"
"strconv"
"strings"
)
// 平台登录方式
const (
AccountTypeGuest = iota
AccountTypePhone
AccountTypeFacebook
AccountTypeGoogleplay
AccountTypeEmail
AccountTypeAccount
AccountTypeRobot = 100
)
// 账号状态
const (
AccountStatus = iota
AccountStatusNormal // 正常
AccountStatusLimit // 封禁
AccountStatusAll
)
// 对账号进行操作
const (
OptPlayerType = iota
OptPlayerTypeKick // 踢出玩家
OptPlayerTypeDisconnect // 操作玩家断线
OptPlayerTypeAll
)
const (
LanguageEN = iota + 1
LanguageHindi
)
const (
NewUser = iota + 1 // 新用户登录
OldUser // 老用户登录
)
const (
DecimalDigits = 100000000 // 计算时精确到小数点后8位
)
var (
DecimalCounts = 0
OneDay int64 = 24 * 60 * 60 // 一天的秒数
)
func init() {
tmp := DecimalDigits
for {
if tmp <= 1 {
break
}
tmp /= 10
DecimalCounts++
}
}
func CashFloat64ToInt64(value float64) int64 {
negative := value < 0
// 将浮点数转换为字符串
text := fmt.Sprintf("%v", value)
// 查找小数点位置
pointIndex := strings.Index(text, ".")
var left, right string
var big, small int64
if pointIndex != -1 {
left = text[:pointIndex]
// 去除小数点后面尾随的0
right = strings.TrimRight(text[pointIndex+1:], "0")
} else {
left = text
}
diff := len(right) - DecimalCounts
if diff > 0 {
right = right[:DecimalCounts]
} else {
for i := 0; i < -diff; i++ {
right += "0"
}
}
big, _ = strconv.ParseInt(left, 10, 64)
small, _ = strconv.ParseInt(right, 10, 64)
ret := util.Abs(big*DecimalDigits) + small
if negative {
return -ret
}
return ret
}
const (
DeviceType = iota
DeviceTypeMobile
DeviceTypePC
DeviceTypeWebview
DeviceTypeIOSH5
DeviceTypeMac
DeviceTypePWA
DeviceTypeAll
)
func IsPC(t int) bool {
return t == DeviceTypePC
}
func GetAccountPre(t int) string {
switch t {
case AccountTypeGuest:
return "guest"
case AccountTypePhone:
return "phone"
case AccountTypeFacebook:
return "fb"
case AccountTypeGoogleplay:
return "gp"
case AccountTypeEmail:
return "email"
case AccountTypeAccount:
return "account"
case AccountTypeRobot:
return "robot"
}
return ""
}
// 渠道号分区
var (
ChannelRegionGoogle = []int{2, 10000}
ChannelRegionVivo = []int{10001, 11000}
)
const (
BrocastIDAll = iota // 全服广播
BrocastIDWithdraw // tx事件
)
// 平台号
const (
PlatformIDGoogle = iota + 1
PlatformIDVivo
PlatformIDAll
)
func GetRegionByPlatformID(id int) []int {
switch id {
case PlatformIDGoogle:
return ChannelRegionGoogle
case PlatformIDVivo:
return ChannelRegionVivo
default:
return nil
}
}
type AdjustEventType int
// adjust事件顺序
const (
AdjustEventFinishLoad AdjustEventType = iota // 加载完成
AdjustEventFirstPage // 首屏加载
AdjustEventClickDemo // 点击游戏demo
AdjustEventClickPlay // 点击游戏play
AdjustEventNewPay // 新用户付费
AdjustEventAllPay // 所有用户付费
AdjustEventNewPlayer // 注册完成
)
const (
ADZero = iota
ADFB
ADKwai
ADJust
ADAll
)
// Channel 渠道表
// GameControlm 游戏控制,0关闭,1开启
type Channel struct {
ID uint `gorm:"primarykey"`
IgnoreOrganic int `gorm:"column:ignore_organic;type:tinyint(4);default:1;comment:是否屏蔽自然量 1不屏蔽 2屏蔽" json:"ignore_organic"`
AdjustEventID string `gorm:"column:adjust_eventid;type:varchar(256);not null;comment:adjust事件id,按顺序隔开" json:"adjust_eventid"`
AdjustAppToken string `gorm:"column:adjust_app_token;type:varchar(256);not null;comment:adjust应用token" json:"adjust_app_token"`
AdjustAuth string `gorm:"column:adjust_auth;type:varchar(256);not null;comment:adjust验证码" json:"adjust_auth"`
Name string `gorm:"column:name;type:varchar(32);not null;comment:渠道" json:"name"`
PackName string `gorm:"column:pack_name;type:varchar(256);not null;comment:包名" json:"pack_name"`
Version int `gorm:"column:version;type:int(11);not null;comment:审核版本号" json:"version"`
MainVersion int `gorm:"column:main_version;type:int(11);not null;comment:正式服版本号" json:"main_version"`
ChannelID int `gorm:"column:channel_id;type:bigint(20);uniqueIndex:channel_id;comment:渠道id" json:"channel_id"`
PlatformID int `gorm:"column:platform_id;type:int(11);comment:平台id,1 googleplay 2 vivo" json:"platform_id"`
IsHot int `gorm:"column:ishot;type:tinyint(4);default:1;comment:是否热更,1不热更,2热更" json:"ishot"`
URL string `gorm:"column:url;type:varchar(64);not null;default:'';comment:域名" json:"url"`
Show int `gorm:"column:show;type:int(11);default:0;comment:是否打开,1不打开,2打开" json:"show"`
FBPixelID string `gorm:"column:fb_pixelid;type:varchar(256);not null;comment:fb像素id" json:"fb_pixelid"`
FBAccessToken string `gorm:"column:fb_accesstoken;type:varchar(256);not null;comment:fb验证码" json:"fb_accesstoken"`
UP int `gorm:"column:up;type:int(11);default:0;comment:上级渠道" json:"up"`
ADUpload int `gorm:"column:ad_upload;type:int(11);default:0;comment:上报事件的平台" json:"ad_upload"`
}
func (c *Channel) TableName() string {
return "channel"
}
// ServerVersion 服务器版本表
// GameControlm 游戏控制,0关闭,1开启
type ServerVersion struct {
ID uint `gorm:"primarykey"`
ServerID int `gorm:"column:server_id;type:int(11);uniqueIndex:server_id;default:0;comment:服务器id" json:"server_id" redis:"server_id"`
Version int `gorm:"column:version;type:int(11);default:0;comment:服务器最新版本" json:"version" redis:"version"`
}
func (c *ServerVersion) TableName() string {
return "server_version"
}
func (c *Channel) GetAdjustEventID(e int) string {
s := strings.Split(c.AdjustEventID, ",")
if e > len(s)-1 {
return ""
}
return s[e]
}
// 红点提示
const (
RedpointMail = iota + 1 // 邮件
)
// WhiteList 白名单
// ListType 名单类型 1白名单 2黑名单(当为0时,用作系统开关)
// LimitType 限制类型 1ip限制 2设备限制(用作系统开关时 1开启 2关闭)
// Content ip或者设备码
// Platform 平台类型 facebook 2 gooleplay 3
// Channel 渠道号
// Version 版本号
// CreateTime 创建时间
// Operator 操作人
// Powers 权限
//
// 第1位控制 手机/游客/渠道
// 第2位控制 注册账号
// 第3位控制 绑定账号
// 第4位控制 账号充值
// 第5位控制 账号退出
// 第6位控制 游戏玩牌
// 第7位控制 版本热更
type WhiteList struct {
ID string
ListType int
LimitType int
Content string
Platform int
Channel int
Version int
Powers []int
CreateTime int64
Operator string
}
var (
PowerMap = map[string]int{
"/account/phoneCode/login": 0,
"/account/guestLogin": 0,
"/account/gpLogin": 0,
"/account/phoneCode/regist": 1,
"/account/phoneCode/bind": 2,
"/balance/recharge/do": 3,
"/balance/withdraw/do": 4,
"playCard": 5,
// "/sys/hotUpdate": 6,
}
LimitMap = map[string]struct{}{
"/sys/hotUpdate": {},
}
)
func IsLimitMap(path string) bool {
_, ok := LimitMap[path]
return ok
}
// PowerPass 鉴权
func (w *WhiteList) PowerPass(path string) bool {
po, ok := PowerMap[path]
if !ok {
index := -1
for k, v := range PowerMap {
if strings.Contains(path, k) {
index = v
break
}
}
if index == -1 {
return true
}
po = index
}
if po > len(w.Powers) {
return false
}
power := w.Powers[po]
if po == 0 {
index := strings.LastIndex(path, "/")
newStr := path[index:]
switch newStr {
case "/login":
return power&4 == 4
case "/guestLogin":
return power&2 == 2
case "/gpLogin":
return power&1 == 1
default:
return false
}
}
return power == 1
}
// ExamineList 审核人员列表
type ExamineList struct {
Time int64
}
// LoginRecord 玩家登录记录表
type LoginRecord struct {
ID int `gorm:"primarykey"`
FirstTime int64 `gorm:"column:first_time;default:0;type:bigint(20);comment:首次登录时间"`
Time int64 `gorm:"column:time;default:0;type:bigint(20);unixIndex:ut;comment:最后登录时间"`
UID int `gorm:"column:uid;not null;type:int(11);unixIndex:ut;comment:玩家id"`
IP string `gorm:"column:ip;type:varchar(256);comment:玩家登录ip"`
Date string `gorm:"column:date;type:varchar(64);default:'';comment:日期"`
ChannelID int `gorm:"column:channel_id;type:bigint(20);default:0;comment:渠道id"`
Status int `gorm:"column:status;type:int(11);comment:1是新用户,2是老用户"`
Platform int `gorm:"column:platform;type:int(11);default:1;comment:最新登录平台"`
IsRecharge int `gorm:"column:is_recharge;type:tinyint(4);default:1;comment:1未充值,2已充值"`
}
func (c *LoginRecord) TableName() string {
return "login_record"
}
// RedisRealOnline 各场次实时在线
type RedisRealOnline struct {
Total int // 总在线人数
New int // 新用户在线人数
}
// IsShareChannel 是否是分享渠道
func IsShareChannel(cid int) bool {
return cid > 10000
}
// BlackList 黑名单
type BlackList struct {
ID int `gorm:"primarykey"`
Name string `gorm:"column:name;type:varchar(64);default:'';not null;uniqueIndex:black_all;comment:名字" json:"Name" web:"name"`
Phone string `gorm:"column:phone;type:varchar(64);default:'';not null;uniqueIndex:black_all;comment:手机号" json:"Phone" web:"phone"`
Email string `gorm:"column:email;type:varchar(64);default:'';not null;uniqueIndex:black_all;comment:email" json:"Email" web:"email"`
PayAccount string `gorm:"column:pay_account;type:varchar(255);default:'';not null;uniqueIndex:black_all;comment:支付账号" json:"PayAccount" web:"pay_account"`
DeviceID string `gorm:"column:deviceid;type:varchar(255);default:'';not null;uniqueIndex:black_all;comment:设备号" json:"DeviceID" web:"deviceid"`
IP string `gorm:"column:ip;type:varchar(64);default:'';not null;uniqueIndex:black_all;comment:ip" json:"IP" web:"ip"`
}
func (c *BlackList) TableName() string {
return "black_list"
}

@ -0,0 +1,309 @@
package common
import (
"fmt"
"reflect"
)
// 账号身份
const (
PlayerRoleNormal = iota
PlayerRoleRobot = 100
)
// 玩家状态
const (
PlayerStatusNormal = iota + 1
PlayerStatusMatching
PlayerStatusPlaying
)
// 玩家是否在线
const (
PlayerOnline = iota + 1
PlayerOffline
)
type PlayerDBInfo struct {
Id int `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"id" redis:"id"`
ADID string `gorm:"column:adid;type:varchar(256);comment:玩家adjustID" json:"adid" redis:"adid"`
GPSADID string `gorm:"column:gps_adid;type:varchar(256);comment:玩家google广告ID" json:"gps_adid" redis:"gps_adid"`
Openid *string `gorm:"column:openid;type:varchar(128);uniqueIndex:channel_openid;comment:唯一识别号" json:"-" redis:"openid"`
IP string `gorm:"column:ip;type:varchar(256);comment:玩家登录ip" json:"ip" redis:"ip"`
Pass string `gorm:"column:pass;type:varchar(64)" json:"pass" redis:"pass"`
Nick string `gorm:"column:nick;type:varchar(64)" json:"nick" redis:"nick"`
Mobile string `gorm:"column:mobile;default:null;type:varchar(64);uniqueIndex:channel_mobile" json:"mobile" redis:"mobile"`
Avatar string `gorm:"column:avatar;type:varchar(512);default:''" json:"avatar" redis:"avatar"`
DeviceId string `gorm:"column:deviceid;type:varchar(256);default:'';comment:设备号" json:"deviceid" redis:"deviceid"`
SessionID string `gorm:"-" json:"sessionID" redis:"sessionID"`
AccountName string `gorm:"column:account_name;default:null;uniqueIndex:channel_account_name;commont:账户名" json:"account_name" redis:"account_name"`
GateID string `gorm:"-" json:"gateID" redis:"gateID"`
Token string `gorm:"-" json:"token" redis:"token"`
Birth int64 `gorm:"column:birth;type:bigint(20);default:0;comment:账号创建时间,时间戳" json:"birth" redis:"birth"`
Role int `gorm:"column:role;type:smallint(8);default:0;comment:玩家角色0普通玩家,100机器人" json:"role" redis:"role"`
ChannelID int `gorm:"column:channel_id;type:bigint(20);uniqueIndex:channel_openid;uniqueIndex:channel_mobile;uniqueIndex:channel_account_name;default:1;comment:渠道id" json:"channel_id" redis:"channel_id"`
AccountType int `gorm:"column:account_type;comment:0游客,1fb,2gp" json:"account_type" redis:"account_type"`
Status int `gorm:"column:status;type:tinyint(4);default:1;comment:账号状态,1正常,2封禁" json:"status" redis:"status"`
Online int `gorm:"column:online;type:tinyint(4);default:2;comment:是否在线,1在线,2不在线" json:"online" redis:"online"`
Tag string `gorm:"column:tag; type:varchar(512);default:'';comment:后台管理给账户打的标签,用户不可见" json:"tag" redis:"tag"`
Platform int `gorm:"column:platform;type:int(11);default:1;comment:最新登录平台" json:"platform" redis:"platform"`
LastLogin int64 `gorm:"column:last_login;type:bigint(20);default:0;comment:最近登录时间" json:"last_login" redis:"last_login"`
Country string `gorm:"column:country;type:varchar(64);default:'';comment:国家" json:"country" redis:"country"`
}
func (u *PlayerDBInfo) TableName() string {
return "users"
}
// PlayerSession 玩家会话信息
type PlayerSession struct {
SessionID string `json:"sessionID" redis:"sessionID"`
GateID string `json:"gateID" redis:"gateID"`
Nick string `json:"nick" redis:"nick"`
}
// FacebookUserInfo facebook返回的登录接口
type FacebookUserInfo struct {
ID string
Name string
Picture struct {
Data struct {
URL string `json:"url"`
Height int
Width int
IsSilhouette bool
} `json:"data"`
} `json:"picture"`
}
// GooglePlayUserInfo googlePlay返回的登录接口
type GooglePlayUserInfo struct {
ID string `json:"sub"`
Email string
Name string
Given_name string
Family_name string
Picture string
Locale string
Verified_email bool
}
// PlayerStatus 玩家状态
// type PlayerStatus struct {
// GameName string `json:"GameName" redis:"GameName"`
// UUID string `json:"UUID" redis:"UUID"`
// TableID string `json:"TableID" redis:"TableID"`
// ActiveTime int64 `json:"ActiveTime" redis:"ActiveTime"`
// WorkID int `json:"WorkID" redis:"WorkID"`
// MatchID uint32 `json:"MatchID" redis:"MatchID"`
// Status uint32 `json:"Status" redis:"Status"`
// GameID uint32 `json:"GameID" redis:"GameID"`
// }
// func (s *PlayerStatus) MarshalBinary() ([]byte, error) {
// return json.Marshal(s)
// }
// func (s *PlayerStatus) UnmarshalBinary(data []byte) error {
// return json.Unmarshal(data, s)
// }
// NormalPlayerSql 返回查询正常用户的sql条件语句
func NormalPlayerSql(channel ...*int) string {
sql := ""
for _, v := range channel {
if v == nil {
continue
}
if sql == "" {
sql += fmt.Sprintf("(channel_id = %v", *v)
} else {
sql += fmt.Sprintf(" or channel_id = %v", *v)
}
}
if len(sql) > 0 {
sql += ")"
}
sql += fmt.Sprintf(" and role <> %v and status = %v", PlayerRoleRobot, AccountStatusNormal)
return sql
}
// PlayerData 保存一些玩家记录
type PlayerData struct {
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
LastSysEmailDraw int64 `gorm:"column:last_sys_email_draw;type:bigint(20);default:0;comment:最近一次接收系统邮件的时间"`
LastAppSpinDraw int64 `gorm:"column:last_app_spin_draw;type:bigint(20);default:0;comment:上次领取app下载转盘的时间"`
FeedbackTime int64 `gorm:"column:feedback_time;type:bigint(20);default:0;comment:完成问卷调查的时间"`
}
func (u *PlayerData) TableName() string {
return "player_data"
}
// PlayerRed 玩家红点信息
type PlayerRed struct {
ID uint `gorm:"primarykey"`
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
Mail int `gorm:"column:mail;type:int(11);comment:未读取邮件数" json:"Mail"`
}
func (u *PlayerRed) TableName() string {
return "player_red"
}
const (
ItemStatusZero = iota
ItemStatusNormal // 正常
ItemStatusInvalid // 不可用
ItemStatusAll
)
// 物品的枚举
const (
ItemZero = iota
ItemDiscountTicket
ItemAll
)
// PlayerItems 玩家道具
type PlayerItems struct {
ID int `gorm:"primarykey"`
UID int `gorm:"column:uid;type:int(11)"`
ItemID int `gorm:"column:item_id;default:0;comment:物品id"`
Time int64 `gorm:"column:time;type:bigint(20);default:0;comment:获得的时间"`
Status int `gorm:"column:status;type:int(11);default:0;comment:物品状态"`
Exi1 int `gorm:"column:exi1;type:int(11);default:0;comment:物品标识字段1"`
}
func (p *PlayerItems) TableName() string {
return "player_items"
}
// PlayerH5Data 玩家H5数据
type PlayerH5Data struct {
UID int `gorm:"primary_key;column:uid;type:int(11)"`
Collect int `gorm:"column:collect;type:int(11);default:1;comment:是否已领取H5收藏奖励,1未领取,2已领取"`
Download int `gorm:"column:download;type:int(11);default:1;comment:是否已领取H5下载奖励,1未领取,2已领取"`
}
func (p *PlayerH5Data) TableName() string {
return "player_h5data"
}
var (
PlayerRechargeTableName = "player_currency_recharge" // 玩家充值账户
)
// PlayerCurrency 玩家货币数据(此结构只能往后新增字段,前面字段不能修改顺序)
type PlayerCurrency struct {
UID int `gorm:"primary_key;column:uid;type:int(11)"`
ChannelID int `gorm:"column:channel_id;type:bigint(20);default:1;comment:渠道id"`
BRL int64 `gorm:"column:brl;type:bigint(20);default:0;comment:雷亚尔"`
USDT int64 `gorm:"column:usdt;type:bigint(20);default:0;comment:usdt"`
}
func (p *PlayerCurrency) TableName() string {
return "player_currency"
}
func (p *PlayerCurrency) GetBalanceByType(ct CurrencyType) int64 {
ref := reflect.ValueOf(p).Elem()
val := ref.Field(int(ct) + 1)
if val.IsValid() {
return val.Int()
}
return 0
}
func (p *PlayerCurrency) SetBalance(ct CurrencyType, value int64) {
ref := reflect.ValueOf(p).Elem()
val := ref.Field(int(ct) + 1)
if val.IsValid() {
val.SetInt(value)
}
}
// PlayerProfile 玩家生涯数据
type PlayerProfile struct {
UID int `gorm:"primary_key;column:uid;type:int(11)"`
ChannelID int `gorm:"column:channel_id;type:bigint(20);default:1;comment:渠道id"`
NeedBet int64 `gorm:"column:need_bet;type:bigint(20);comment:当前所需下注量"`
TotalBet int64 `gorm:"column:total_bet;type:bigint(20);comment:总下注"`
TotalCounts int64 `gorm:"column:total_counts;type:bigint(20);comment:总下注次数"`
TotalSettle int64 `gorm:"column:total_settle;type:bigint(20);comment:总派发"`
}
func (p *PlayerProfile) TableName() string {
return "player_profile"
}
// Level vip等级
// Bet 下注额
// Exp vip经验
// Draws 已经领取的vip等级奖励,从右至左,等级低到高
//
// Cashback 当前可领取的cashback
type VipData struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"ID"`
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid" json:"UID"`
Level int `gorm:"column:level;not null;type:int(11);default:0;comment:vip等级" json:"Level"`
Bet int64 `gorm:"column:bet;not null;type:bigint(20);default:0;comment:下注额" json:"Bet"`
Exp int64 `gorm:"column:exp;not null;type:bigint(20);default:0;comment:vip经验" json:"Exp"`
Draws int64 `gorm:"column:draws;not null;type:bigint(20);default:0;comment:已经领取的vip等级奖励,从右至左,等级低到高" json:"Draws"`
Profit int64 `gorm:"column:profit;not null;type:bigint(20);default:0;comment:计算周期内的盈亏" json:"Profit"`
ProfitTime int64 `gorm:"column:profit_time;not null;type:bigint(20);default:0;comment:开始计算时间节点" json:"ProfitTime"`
Cashback int64 `gorm:"column:cashback;not null;type:bigint(20);default:0;comment:当前可领取的cashback" json:"Cashback"`
}
func (c *VipData) TableName() string {
return "vip_data"
}
type TronData struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id"`
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
Addr string `gorm:"column:addr; type:varchar(256);default:'';comment:钱包地址"`
Usdt int64 `gorm:"column:usdt;type:bigint(20);default:0;comment:地址里的u存量,单位1e6"`
}
func (c *TronData) TableName() string {
return "tron_data"
}
// PlayerStatus 玩家状态
type PlayerStatus struct {
ModuleName string `json:"ModuleName" redis:"ModuleName"`
WorkID int `json:"WorkID" redis:"WorkID"`
GameID int `json:"GameID" redis:"GameID"`
SubID int `json:"SubID" redis:"SubID"`
TableID string `json:"TableID" redis:"TableID"`
}
// 玩家广告相关数据
type PlayerADData struct {
ID int `gorm:"primarykey"`
UID int `gorm:"column:uid;type:int(11);index:uid"`
IP string `gorm:"column:ip;type:varchar(256);comment:玩家ip"`
FBC string `gorm:"column:fbc;type:varchar(256);comment:玩家点击识别号"`
FBP string `gorm:"column:fbp;type:varchar(256);comment:玩家浏览器识别号"`
ChannelID int `gorm:"column:channel_id;type:bigint(20);default:1000;comment:渠道id"`
UserAgent string `gorm:"column:user_agent;type:varchar(256);comment:玩家浏览器版本"`
}
func (c *PlayerADData) TableName() string {
return "player_ad_data"
}
// 玩家购买记录
type PlayerPayData struct {
ID uint `gorm:"primarykey"`
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
BreakGift string `gorm:"column:break_gift;type:varchar(256);default:'';comment:已购买破产礼包的档位"`
SubBreakGift []int `gorm:"-"`
// FirstPay string `gorm:"column:first_pay;default:'';type:varchar(256);comment:首次购买商品记录"`
// SubFirstPay []int `gorm:"-"`
}
func (c *PlayerPayData) TableName() string {
return "player_pay_data"
}

@ -0,0 +1,67 @@
package common
import "server/config"
const (
ProviderZero = iota
ProviderInhouse
ProviderTada
ProviderSexy
ProviderPGSoft
ProviderEvolutionGaming
ProviderAllBet
ProviderBigGaming
ProviderSAGaming
ProviderPragmaticPlay
ProviderCQ9
ProviderPlayTech
ProviderJoker
ProviderDragonSoft
ProviderTFGaming
ProviderWMCasino
ProviderKing855
ProviderAMAYA
ProviderHabanero
ProviderIBC
ProviderReevo
ProviderEvoPlay
ProviderPlayStar
ProviderDreamGaming
ProviderNexus4D
ProviderSlotXo
ProviderBTI
ProviderEzugi
ProviderAll
)
const (
ProviderAPIType = iota
ProviderAPITypeJson
ProviderAPITypePostform
ProviderAPITypeAll
)
// ConfigServerFlag 配置服务器编号配置
type ConfigServerFlag struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id"`
Flag string `gorm:"column:flag;type:varchar(255);default:'b';uniqueIndex:flag;comment:服务器编号" web:"flag"`
APIURL string `gorm:"column:api_url;type:varchar(255);default:'';comment:api请求地址" web:"api_url"`
}
func (c *ConfigServerFlag) TableName() string {
return "config_server_flag"
}
func GetProviderUserName(name string) string {
if config.GetBase().ServerFlag != "a" {
name = config.GetBase().ServerFlag + name
}
return name
}
func GetProviderUserToken(token string) string {
if config.GetBase().ServerFlag != "a" {
token = config.GetBase().ServerFlag + token
}
return token
}

@ -0,0 +1,235 @@
package common
const (
StatusROrderWaitting = iota // 等待提交状态
StatusROrderCreate
StatusROrderPay
StatusROrderFinish
StatusROrderFail
StatusROrderRefuse
StatusROrderPending // 挂起
StatusROrderAll
)
type PayType int
// 支付类型,巴西代表cpf|cnpj|email|phone|evp
const (
PayTypeInvalid PayType = iota
PayTypeCPF
PayTypeCNPJ
PayTypePhone
PayTypeEmail
PayTypeEVP
PayTypeAll
)
func (p PayType) Isvalid() bool {
return p > PayTypeInvalid && p < PayTypeAll
}
func (p PayType) String() string {
switch p {
case PayTypeCPF:
return "CPF"
case PayTypeCNPJ:
return "CNPJ"
case PayTypePhone:
return "PHONE"
case PayTypeEmail:
return "EMAIL"
case PayTypeEVP:
return "EVP"
default:
return ""
}
}
// ProductTypeRechargeWait 商品类型id
const (
ProductTypeRechargeWait = iota + 1
ProductTypeAll
)
// 非常规支付方式
const (
PayTypePerson = -1 // 个卡支付
)
// 首充活动id
const (
WelcomeBonusProductID = 1111
)
// 支付方式
const (
PaySourceZero = iota + 1
PaySourceModulePay // pay模块支付
PaySourceBlockPay // 区块链支付
PaySourceAll
)
// 用于记录商品id对应的购买次数,一个bigint可记录最多16个商品的最多15次购买记录
var (
ProductIDMap = map[int]int{}
)
func GetProductPayCount(total int64, id int) int {
// log.Debug("total%v,id:%v", total, id)
tmp, ok := ProductIDMap[id]
if !ok {
return 0
}
return int((total >> (tmp * 4)) & 15)
}
func AddProductPayCount(total int64, id int) int64 {
tmp, ok := ProductIDMap[id]
if !ok {
return total
}
// 右移,将当前需要操作的商品移动到最右侧
pos := tmp * 4
num := total >> (pos)
// 拿到操作商品右侧的商品信息值
right := 1
for i := 0; i < pos; i++ {
right *= 2
}
right--
rightNum := total & int64(right)
// 拿到需要操作的商品真实次数
realNum := num & 15
if realNum >= 15 {
return total
}
num++
return rightNum | (num << (pos))
}
type RechargeOrder struct {
ID uint `gorm:"primarykey"`
UID int `gorm:"column:uid;not null;type:int(11);index:uid"`
CreateTime int64 `gorm:"column:create_time;type:bigint(20);comment:创建时间" redis:"create_time"`
OrderID string `gorm:"column:orderid;not null;type:varchar(255);uniqueIndex:orderid;comment:本地ID"`
APIPayID string `gorm:"column:apipayid;not null;type:varchar(255);comment:支付第三方生成的id"`
Extra string `gorm:"column:extra;type:varchar(255);comment:额外信息字段"`
PayAccount string `gorm:"column:payaccount;not null;type:varchar(512);comment:支付账户"`
Amount int64 `gorm:"column:amount;not null;type:bigint(20);comment:单位8位小数"`
PaySource int `gorm:"column:pay_source;not null;type:int(11);comment:支付来源"`
PayChannel int `gorm:"column:pay_channel;type:int(11);comment:具体支付渠道"`
Event int `gorm:"column:event;not null;type:smallint(4);comment:事件类型"`
CurrencyType CurrencyType `gorm:"column:currency_type;not null;type:int(11);comment:货币类型"`
ProductID int `gorm:"column:productid;not null;type:int(11)"`
Status uint8 `gorm:"column:status;not null;type:tinyint(4);comment:1新建,2支付完成,3发货完成,4支付失败,5取消"`
FailReason string `gorm:"column:fail_reason;type:varchar(255);comment:失败原因"`
ChannelID int `gorm:"column:channel_id;type:bigint(20);default:1;comment:渠道id" redis:"channel_id"`
Remarks string `gorm:"column:remarks;type:varchar(255);comment:备注" redis:"remarks"`
CallbackTime int64 `gorm:"column:callback_time;type:bigint(20);comment:到账时间" redis:"callback_time"`
UPI int `gorm:"column:upi;not null;type:int(11);comment:玩家选择的upi"`
}
func (r *RechargeOrder) TableName() string {
return "recharge_order"
}
const (
WithdrawOrderTypeZero = iota
WithdrawOrderTypeNormal
WithdrawOrderTypeShare
WithdrawOrderTypeAll
)
type WithdrawOrder struct {
ID uint `gorm:"primarykey"`
UID int `gorm:"column:uid;not null;type:int(11)"`
CreateTime int64 `gorm:"column:create_time;type:bigint(20);comment:创建时间"`
OrderID string `gorm:"column:orderid;not null;type:varchar(255);uniqueIndex:orderid;comment:本地ID"`
APIPayID string `gorm:"column:apipayid;not null;type:varchar(255);comment:支付第三方生成的id"`
Extra string `gorm:"column:extra;type:varchar(64);comment:额外信息字段"`
PayAccount string `gorm:"column:payaccount;not null;type:varchar(512);comment:支付账户"`
Amount int64 `gorm:"column:amount;not null;type:bigint(20);comment:单位分"`
WithdrawCash int64 `gorm:"column:withdraw_cash;type:bigint(20);default:0;comment:退出扣除的金币"`
PaySource int `gorm:"column:pay_source;not null;type:int(11);comment:支付来源"`
CurrencyType CurrencyType `gorm:"column:currency_type;not null;type:int(11);comment:货币类型"`
PayChannel int `gorm:"column:pay_channel;type:int(11);comment:具体支付渠道"`
Event int `gorm:"column:event;not null;type:smallint(4);comment:事件类型"`
ProductID int `gorm:"column:productid;not null;type:int(11)"`
Status uint8 `gorm:"column:status;not null;type:tinyint(4);comment:1新建,2支付完成,3发货完成,4支付失败,5取消"`
FailReason string `gorm:"column:fail_reason;type:varchar(255);comment:失败原因"`
ChannelID int `gorm:"column:channel_id;type:bigint(20);default:1;comment:渠道id"`
Remarks string `gorm:"column:remarks;type:varchar(255);comment:备注"`
AuditTime int64 `gorm:"column:audit_time;type:bigint(20);comment:审核时间"`
CallbackTime int64 `gorm:"column:callback_time;type:bigint(20);comment:到账时间"`
UPI int `gorm:"column:upi;not null;type:int(11);comment:玩家选择的upi"`
Operator string `gorm:"column:operator;type:varchar(255);comment:操作人账号名"`
OrderType int `gorm:"column:order_type;default:1;type:int(11);comment:订单类型 1普通 2分享单"`
}
func (r *WithdrawOrder) TableName() string {
return "withdraw_order"
}
// RechargeInfo 玩家充值信息记录表
type RechargeInfo struct {
ID uint `gorm:"primarykey"`
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
ProductPayCount int64 `gorm:"column:product_paycount;type:bigint(20);default:0;comment:记录玩家购买商品次数,映射表在代码里"`
DayRecharge int64 `gorm:"column:day_recharge;type:bigint(20);default:0;comment:日充值"`
TotalRechargeCount int64 `gorm:"column:total_recharge_count;type:bigint(20);default:0;comment:总充值次数"`
LastRecharge int64 `gorm:"column:last_recharge;type:bigint(20);default:0;comment:最近一次充值的时间戳"`
TotalRecharge int64 `gorm:"column:total_recharge;type:bigint(20);default:0;comment:总充值数额,不论货币"`
TotalWithdrawCount int64 `gorm:"column:total_withdraw_count;type:bigint(20);default:0;comment:总退出次数"`
TotalWithdraw int64 `gorm:"column:total_withdraw;type:bigint(20);default:0;comment:总退出数额,不论货币"`
TotalWithdrawing int64 `gorm:"column:total_withdrawing;type:bigint(20);default:0;comment:提现中的钱"`
DayWithdraw int64 `gorm:"column:day_withdraw;type:bigint(20);default:0;comment:当日退出数额,不论货币"`
LastWithdraw int64 `gorm:"column:last_withdraw;type:bigint(20);default:0;comment:最近一次退出的时间戳"`
WithdrawCount int `gorm:"column:withdraw_count;type:int(11);default:0;comment:当天累计退出次数"`
WithdrawingCash int64 `gorm:"column:withdrawing_cash;type:bigint(20);default:0;comment:提现中的金币" json:"withdrawing_cash"`
}
func (r *RechargeInfo) TableName() string {
return "recharge_info"
}
// RechargeInfoCurrency 玩家各货币充值信息记录表模板
type RechargeInfoCurrency struct {
ID uint `gorm:"primarykey"`
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
TotalRecharge int64 `gorm:"column:total_recharge;type:bigint(20);default:0;comment:总充值" json:"total_recharge"`
TotoalWithdraw int64 `gorm:"column:total_withdraw;type:bigint(20);default:0;comment:总退出" json:"total_withdraw"`
TotoalWithdrawing int64 `gorm:"column:total_withdrawing;type:bigint(20);default:0;comment:总退出中" json:"total_withdrawing"`
}
// PayInfo 支付信息
// Name 收款人姓名
// Mobile 收款人手机号码
// Email 收款人邮箱
// PayType 收款方式
// Number 卡号或收款信息
type PayInfo struct {
ID uint `gorm:"primarykey"`
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
Name string `gorm:"column:name;default:'';type:varchar(256);comment:收款人姓名"`
Mobile string `gorm:"column:mobile;default:'';type:varchar(256);comment:收款人手机号码"`
Email string `gorm:"column:email;default:'';type:varchar(256);comment:收款人邮箱"`
PayType PayType `gorm:"column:pay_type;default:1;type:int(11);comment:收款方式"`
Number string `gorm:"column:number;default:'';type:varchar(256);comment:卡号或收款信息"`
}
func (p *PayInfo) TableName() string {
return "pay_info"
}
// WithdrawCommon 支付信息公共部分 地址格式{"city":"Mumbai","street":"sarang street","houseNumber":"-54/a"}
type WithdrawCommon struct {
Name string // 收款人姓名
Mobile string // 收款人手机号码
Email string // 收款人邮箱
PayType PayType
Number string
Address string
IP string
}

@ -0,0 +1,191 @@
package common
import (
"fmt"
"time"
)
const (
RedisExpireLock = 10 * time.Second
RedisExpireToken = 7 * 24 * time.Hour
RedisExpireCode = 180 * time.Second
RedisExpireCodeCD = 60 * time.Second
RedisExpireMail = 3 * time.Second
RedisExpireControl = 30 * 24 * time.Hour
RedisExpireActivityRed = 1 * time.Minute // 红包雨活动,给予客户端1分钟去做领取
RedisExpireGameEnter = 12 * time.Hour // 进入游戏记录玩家币种的超时时间
)
const (
RedisTimeoutTx = 10 * time.Second
)
const (
RedisKeyUser = "user"
RedisKeyCode = "Code"
RedisKeyCodeCD = "CodeCD"
RedisKeyToken = "token"
RedisKeyPlayerStatus = "playerStatus" // 玩家当前游戏状态, 用于断线重连
RedisKeyRobotPlaying = "robotPlaying" // 已使用的机器人
RedisKeyGameFlow = "gameFlow" // 游戏流水总额统计,用于调控
// RedisKeyPlayerControl = "playerControl" // 玩家幸运值/愤怒值
RedisKeyWarn = "warn" // 后台预警
RedisKeyActivityRed = "activityRed" // 红包雨活动
RedisOnline = "online" // 实时在线
RedisWaterLevel = "waterLevel" // 水位
RedisKeyPayWeight = "payWeight" // 支付渠道权重
RedisKeyWitdhrawWeight = "withrawWeight" // 支付渠道权重
RedisKeyGamePlay = "gamePlay" // 各游戏玩家游戏局数
RedisKeyGameResult = "gameResult" // 记录牌局结果,重启时直接拉取恢复
RedisKeyGameWinner = "gameWinner" // 记录历史牌局大赢家
RedisKeyCollectCardLottery = "collectCardLottery" // 本次大奖开奖控制
RedisKeyCollectCardLotteryCards = "collectCardLotteryCards" // 本次大奖结果
RedisKeyPayStatus = "payStatus" // 支付渠道策略
RedisKeyRealMail = "realMail" // 给玩家发真实邮件控制
// RedisKeyPlayerPay = "playerPay" // 玩家10分钟内付费拉起的渠道记录
RedisKeyPlayerPayInterval = "playerPayInterval" // 玩家拉单间隔限制
RedisKeyGameCurrency = "gameCurrency" // 玩家进入游戏时选择的币种
)
const (
RedisLockKeyIP = "lockKeyIP" // 玩家操作频率限制
RedisLockKeyEnter = "lockKeyEnter" // 玩家进游戏锁
RedisLockKeyControl = "lockKeyControl" // 玩家更新控制参数锁
)
func GetRedisKeyGameCurrency(uid int) string {
return fmt.Sprintf("%v:%v", RedisKeyGameCurrency, uid)
}
func GetRedisKeyPlayerPayInterval(uid int) string {
return fmt.Sprintf("%v:%v", RedisKeyPlayerPayInterval, uid)
}
// func GetRedisKeyPlayerPay(uid int) string {
// return fmt.Sprintf("%v:%v", RedisKeyPlayerPay, uid)
// }
// status 发邮件的模板,0是失败邮件,1是成功邮件
func GetRedisKeyRealMail(uid int, status int) string {
desc := "fail"
if status == 1 {
desc = "success"
}
return fmt.Sprintf("%v:%v:%v", RedisKeyRealMail, desc, uid)
}
func GetRedisKeyGameWinner(gid int) string {
return fmt.Sprintf("%v:%v", RedisKeyGameWinner, gid)
}
func GetRedisKeyGameResult(gid, rid int) string {
return fmt.Sprintf("%v:%v:%v", RedisKeyGameResult, gid, rid)
}
func GetRedisKeyWaterLevel(gid, rid int) string {
return fmt.Sprintf("%v:%v:%v", RedisWaterLevel, gid, rid)
}
func GetActivityRedKey(uid int) string {
return fmt.Sprintf("%v:%v", RedisKeyActivityRed, uid)
}
func GetRedisKeyOnlineKey(field string) string {
return fmt.Sprintf("%v:%v", RedisOnline, field)
}
func GetWarnKey(id int) string {
return fmt.Sprintf("%v:%v", RedisKeyWarn, id)
}
func GetRedisLockKeyControl(uid int) string {
return fmt.Sprintf("%v:%v", RedisLockKeyControl, uid)
}
func GetRedisLockKeyEnter(uid int) string {
return fmt.Sprintf("%v:%v", RedisLockKeyEnter, uid)
}
func GetRedisLockKeyIP(ip string) string {
return fmt.Sprintf("%v:%v", RedisLockKeyIP, ip)
}
// func GetRedisKeyPlayerControl(uid int) string {
// return fmt.Sprintf("%v:%v", RedisKeyPlayerControl, uid)
// }
func GetRedisKeyRobotPlaying(rid int) string {
return fmt.Sprintf("%v:%v", RedisKeyRobotPlaying, rid)
}
func GetRedisKeyCode(content string) string {
return RedisKeyCode + ":" + content
}
func GetRedisKeyCodeCD(content string) string {
return RedisKeyCodeCD + ":" + content
}
func GetRedisKeyUser(uid int) string {
return fmt.Sprintf("%s:%d", RedisKeyUser, uid)
}
func GetRedisKeyToken(token string) string {
return RedisKeyToken + ":" + token
}
func GetRedisKeyPlayerStatus(uid int) string {
return fmt.Sprintf("%v:%v", RedisKeyPlayerStatus, uid)
}
const (
EventTrackDataVersion = "EventTrackDataVersion" // 打点数据version存入redis的key hash
)
// ==============================================================配置文件
const (
RedisKeyConfigRoom = "config:Room"
RedisKeyConfigMillionRobotBet = "config:MillionRobotBet"
RedisKeyConfigRoomChat = "config:RoomChat"
RedisKeyConfigRecharge = "config:Recharge"
RedisKeyConfigRobotConfig = "config:RobotConfig"
RedisKeyConfigRobotPlayConfig = "config:RobotPlayConfig"
RedisKeyConfigTPRobotOperate = "config:TPRobotOperate"
RedisKeyConfigRobotTeenpatti = "config:RobotTeenpatti"
RedisKeyConfigRobotAKTeenpatti = "config:RobotAKTeenpatti"
RedisKeyConfigRobotJTeenpatti = "config:RobotJTeenpatti"
RedisKeyConfigWithdrawAmount = "config:WithdrawAmount"
RedisKeyConfigWithdrawCondition = "config:WithdrawCondition"
RedisKeyConfigActivityConfig = "config:ActivityConfig"
RedisKeyConfigReportActivityConfig = "config:ReportActivityConfig"
RedisKeyConfigRecharge1ActivityConfig = "config:Recharge1ActivityConfig"
RedisKeyConfigGoodsConfig = "config:GoodsConfig"
RedisKeyConfigMatchingTableConfig = "config:MatchingTableConfig"
RedisKeyConfigNoticeConfig = "config:NoticeConfig"
RedisKeyConfigBroadcastConfig = "config:BroadcastConfig"
RedisKeyConfigHelpConfig = "config:HelpConfig"
RedisKeyConfigDramaAction = "config:DramaAction"
RedisKeyConfigDramaDeal = "config:DramaDeal"
)
func GetRedisKeyTPRobotOperateConfig(gameID, roomID int) string {
return fmt.Sprintf("%v:%v:%v", RedisKeyConfigTPRobotOperate, gameID, roomID)
}
// ==============================================================后台
const (
BackendToken = "backendToken"
BackendReview = "backendReview"
)
func GetBackendTokenKey(token string) string {
return BackendToken + ":" + token
}
func GetBackendReviewKey(date string, channel *int) string {
ret := fmt.Sprintf("%v:%v", BackendReview, date)
if channel != nil {
ret += fmt.Sprintf(":%v", *channel)
}
return ret
}

@ -0,0 +1,9 @@
package common
import (
"github.com/gin-gonic/gin"
)
func HealthCheck(c *gin.Context) {
c.String(200, "ok")
}

@ -0,0 +1,109 @@
package common
// 分享配置
type ConfigShare struct {
ID int `gorm:"primarykey"`
Level int `gorm:"column:level;type:int(11);default:0;comment:等级" web:"level"`
Bet int64 `gorm:"column:bet;type:bigint(20);default:0;comment:档次投注额" web:"bet"`
Per int64 `gorm:"column:per;type:bigint(20);default:0;comment:佣金比例,万分位" web:"per"`
}
func (c *ConfigShare) TableName() string {
return "config_share"
}
// 分享配置
type ConfigShareSys struct {
ID int `gorm:"primarykey"`
WithdrawLimit int64 `gorm:"column:withdraw_limit;type:bigint(20);default:100000000;comment:最低领取数额" web:"withdraw_limit"`
ShareRecharge int64 `gorm:"column:share_recharge;type:bigint(20);default:2000000000;comment:有效玩家充值需求" web:"share_recharge"`
ShareReward int64 `gorm:"column:share_reward;type:bigint(20);default:1000000000;comment:分享有效玩家奖励" web:"share_reward"`
FakeInviteReward int64 `gorm:"column:fake_invite_reward;type:bigint(20);default:1250000000000000;comment:虚拟邀请奖励" web:"fake_invite_reward"`
FakeBetReward int64 `gorm:"column:fake_bet_reward;type:bigint(20);default:980000000000000;comment:虚拟投注奖励" web:"fake_bet_reward"`
}
func (c *ConfigShareSys) TableName() string {
return "config_share_sys"
}
// 绑定关系
type ShareInfo struct {
ID int `gorm:"primarykey"`
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
Share string `gorm:"column:share;not null;type:varchar(64);uniqueIndex:share;comment:分享码"`
// UP int `gorm:"column:up;not null;type:int(11);comment:上级"`
UP1 int `gorm:"column:up1;type:int(11);default:0;comment:一级"`
UP2 int `gorm:"column:up2;type:int(11);default:0;comment:二级"`
UP3 int `gorm:"column:up3;type:int(11);default:0;comment:三级"`
ChannelID int `gorm:"column:channel_id;type:int(11);default:0;comment:渠道id"`
Invites int `gorm:"column:invites;type:int(11);default:0;comment:邀请人数"`
InvaidInvites int `gorm:"column:invalid_invites;type:int(11);default:0;comment:有效邀请人数"`
InviteReward int64 `gorm:"column:invite_reward;type:bigint(20);default:0;comment:邀请获得的奖励金额"`
BetReward int64 `gorm:"column:bet_reward;type:bigint(20);default:0;comment:邀请人下注获得的金额"`
AvailableReward int64 `gorm:"column:available_reward;type:bigint(20);default:0;comment:可支配佣金"`
Time int64 `gorm:"column:time;type:bigint(20);default:0;comment:加入的时间"`
}
// 绑定关系
// type ShareInfo struct {
// ID int `gorm:"primarykey"`
// UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid"`
// Share string `gorm:"column:share;not null;type:varchar(64);uniqueIndex:share;comment:分享码"`
// UP int `gorm:"column:up;not null;type:int(11);comment:上级"`
// Level int `gorm:"column:level;default:1;type:int(11);comment:等级"`
// ChannelID int `gorm:"column:channel_id;type:bigint(20);comment:渠道id"`
// Bet int64 `gorm:"column:bet;type:bigint(20);default:0;comment:待结算下注额,结算后会清零"`
// TodayBet int64 `gorm:"column:today_bet;type:bigint(20);default:0;comment:今日总下注"`
// TotalBet int64 `gorm:"column:total_bet;type:bigint(20);default:0;comment:总下注"`
// TodayAgentsBet int64 `gorm:"column:today_agents_bet;type:decimal(38);default:0;comment:团队今日下注"`
// TotalAgentsBet int64 `gorm:"column:total_agents_bet;type:decimal(38);default:0;comment:团队总下注"`
// TodayAgents int64 `gorm:"column:today_agents;type:bigint(20);default:0;comment:今日下级数量"`
// TotalAgents int64 `gorm:"column:total_agents;type:bigint(20);default:0;comment:总下级数量"`
// TodayRealAgents int64 `gorm:"column:today_real_agents;type:bigint(20);default:0;comment:今日有效下级数量"`
// TotalRealAgents int64 `gorm:"column:total_real_agents;type:bigint(20);default:0;comment:总有效下级数量"`
// TodayReward int64 `gorm:"column:today_reward;type:bigint(20);default:0;comment:今日佣金"`
// TotalReward int64 `gorm:"column:total_reward;type:bigint(20);default:0;comment:总佣金"`
// TodayUpReward int64 `gorm:"column:today_up_reward;type:bigint(20);default:0;comment:今日给上级创造的佣金"`
// AvailableReward int64 `gorm:"column:available_reward;type:bigint(20);default:0;comment:可支配佣金"`
// Time int64 `gorm:"column:time;type:bigint(20);default:0;comment:加入的时间"`
// }
func (a *ShareInfo) TableName() string {
return "share_info"
}
type ShareOrder struct {
ID int `gorm:"primarykey"`
UID int `gorm:"column:uid;not null;type:int(11)"`
CreateTime int64 `gorm:"column:create_time;type:bigint(20);comment:创建时间"`
ExamineTime int64 `gorm:"column:examine_time;type:bigint(20);default:0;comment:审核时间"`
OrderID string `gorm:"column:orderid;not null;type:varchar(255);uniqueIndex:orderid;comment:本地ID"`
Amount int64 `gorm:"column:amount;not null;type:bigint(20);comment:单位8位小数"`
ChannelID int `gorm:"column:channel_id;type:bigint(20);comment:渠道id"`
Status int `gorm:"column:status;not null;type:tinyint(4);comment:1新建,2支付完成,3发货完成,4支付失败,5取消"`
}
func (a *ShareOrder) TableName() string {
return "share_order"
}
// 机器人
type ConfigShareRobot struct {
ID int `gorm:"primarykey"`
RobotID int `gorm:"column:robot_id;type:int(11);default:0" web:"robot_id"`
Avatar string `gorm:"column:avatar;type:varchar(255);default:''" web:"avatar"`
Nick string `gorm:"column:nick;type:varchar(255);default:''" web:"nick"`
InitCash int64 `gorm:"column:init_cash;type:bigint(20);default:0;comment:初始金币" web:"init_cash"`
DayCashDown int64 `gorm:"column:day_cash_down;type:bigint(20);default:0;comment:每日增加金币数下限" web:"day_cash_down"`
DayCashUp int64 `gorm:"column:day_cash_up;type:bigint(20);default:0;comment:每日增加金币数上限" web:"day_cash_up"`
}
func (c *ConfigShareRobot) TableName() string {
return "config_share_robot"
}

@ -0,0 +1,66 @@
package common
const (
TaskTypeZero = iota
TaskTypeRegist // 注册任务
TaskTypeDownload // 下载app任务
TaskTypeTotalRecharge // 累充任务
TaskTypeOnceRecharge // 单次充值任务
TaskTypeFirstRecharge // 首次充值任务
TaskTypeAll
)
// 判读任务的目标是否是次数
func IsNumTaskType(t int) bool {
return t == TaskTypeRegist || t == TaskTypeDownload
}
func GetTaskTitle(task *ConfigTask) string {
// switch task.Type {
// case TaskTypeTotalRecharge:
// return fmt.Sprintf(task.Title, task.Target/DecimalDigits)
// case TaskTypeOnceRecharge:
// return fmt.Sprintf(task.Title, task.Target/DecimalDigits)
// }
return task.Title
}
const (
TaskKindZero = iota
TaskKindOnce
TaskKindCycle
TaskKindAll
)
// ConfigTask 任务配置
// Kind 1单次 2循环
// Type 1注册 2下载 3累充 4单次充
type ConfigTask struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id"`
TaskID int `gorm:"column:task_id;type:int(11);default:0;uniqueIndex:task_id;comment:任务id" web:"task_id"`
Target int64 `gorm:"column:target;type:bigint(20);default:0;comment:任务目标" web:"target"`
Reward int64 `gorm:"column:reward;type:bigint(20);default:0;comment:奖励" web:"reward"`
Open int `gorm:"column:open;type:int(11);default:1;comment:开关 1打开" web:"open"`
Kind int `gorm:"column:kind;type:int(11);default:1;comment:1单次 2循环" web:"kind"`
Type int `gorm:"column:type;type:int(11);default:1;comment:1注册 2下载" web:"type"`
Title string `gorm:"column:title;type:varchar(256);default:'';comment:标题" web:"title"`
Icon string `gorm:"column:icon;type:varchar(256);default:'';comment:图标" web:"icon"`
Sort int `gorm:"column:sort;type:int(11);default:0;comment:排序" web:"sort"`
Action int `gorm:"column:action;type:int(11);default:1;comment:跳转类型" web:"action"`
}
func (c *ConfigTask) TableName() string {
return "config_task"
}
type TaskData struct {
ID int `gorm:"primary_key;AUTO_INCREMENT;column:id" json:"ID"`
UID int `gorm:"column:uid;not null;type:int(11);uniqueIndex:uid" json:"UID"`
Time int64 `gorm:"column:time;not null;type:bigint(20);default:0;comment:任务生成时间" json:"Time"`
TaskID int `gorm:"column:task_id;type:int(11);default:0;uniqueIndex:uid;comment:任务id" web:"task_id"`
Progress int64 `gorm:"column:progress;type:bigint(20);default:0;comment:进度" web:"progress"`
}
func (c *TaskData) TableName() string {
return "task_data"
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save