neo лет назад: 2
Родитель
Сommit
5e2dee6ccf
15 измененных файлов с 76521 добавлено и 0 удалено
  1. 11 0
      .gitignore
  2. 8 0
      conf/neo/app.conf_ali
  3. 8 0
      conf/neo/app.conf_ali_test
  4. 1 0
      conf/neo/cfg.conf
  5. 11 0
      conf/neo/cfg_test.conf
  6. 36 0
      main.go
  7. 37 0
      run.sh
  8. 37 0
      run_test.sh
  9. 160 0
      sensitive/dfa.go
  10. 51 0
      sensitive/interface.go
  11. 75443 0
      sensitive/words.txt
  12. 76 0
      utils/mysql.go
  13. 224 0
      utils/redis.go
  14. 115 0
      utils/sign.go
  15. 303 0
      utils/util.go

+ 11 - 0
.gitignore

@@ -0,0 +1,11 @@
1
+
2
+*.pid
3
+*.xml
4
+*.xml
5
+*.xlsx
6
+*.out
7
+*.log
8
+box-3rdServer-*
9
+conf/app.conf
10
+go.mod
11
+go.sum

+ 8 - 0
conf/neo/app.conf_ali

@@ -0,0 +1,8 @@
1
+#
2
+# 订单
3
+#
4
+
5
+appname = box-3rdServer
6
+httpport = 7002
7
+runmode = product
8
+project = neo

+ 8 - 0
conf/neo/app.conf_ali_test

@@ -0,0 +1,8 @@
1
+#
2
+# 订单
3
+#
4
+
5
+appname = box-3rdServer
6
+httpport = 7344
7
+runmode = test
8
+project = neo

+ 1 - 0
conf/neo/cfg.conf

@@ -0,0 +1 @@
1
+[servers]

+ 11 - 0
conf/neo/cfg_test.conf

@@ -0,0 +1,11 @@
1
+[servers]
2
+
3
+[redis]
4
+count=1
5
+host_0=127.0.0.1
6
+port_0=6381
7
+auth_0=aGMtbmVvLWRldi0yMDIzMDQwNw==
8
+
9
+host_account=127.0.0.1
10
+port_account=6381
11
+auth_account=aGMtbmVvLWRldi0yMDIzMDQwNw==

+ 36 - 0
main.go

@@ -0,0 +1,36 @@
1
+/*
2
+ * @Descripttion:
3
+ * @version:
4
+ * @Author: Neo,Huang
5
+ * @Date: 2020-12-16 11:22:56
6
+ * @LastEditors: Neo,Huang
7
+ * @LastEditTime: 2022-04-27 20:20:13
8
+ */
9
+package main
10
+
11
+import (
12
+	"net/http"
13
+
14
+	"github.com/astaxie/beego"
15
+	"github.com/drone/routes"
16
+
17
+	"box-3rdServer/sensitive"
18
+	"box-3rdServer/utils"
19
+)
20
+
21
+func main() {
22
+	utils.InitProject()
23
+	utils.InitRedis()
24
+
25
+	mux := routes.New()
26
+
27
+	// 敏感词
28
+	sensitive.Init()
29
+	mux.Get("/sensitive/checkword", sensitive.HttpCheckWord)
30
+	mux.Post("/sensitive/checkword", sensitive.HttpCheckWord)
31
+	mux.Get("/sensitive/changeword", sensitive.HttpChangeWord)
32
+	mux.Post("/sensitive/changeword", sensitive.HttpChangeWord)
33
+
34
+	http.Handle("/", mux)
35
+	http.ListenAndServe(":"+beego.AppConfig.String("httpport"), nil)
36
+}

+ 37 - 0
run.sh

@@ -0,0 +1,37 @@
1
+###
2
+ # @Descripttion:
3
+ # @version:
4
+ # @Author: Neo,Huang
5
+ # @Date: 2020-11-06 09:53:23
6
+ # @LastEditors: Neo,Huang
7
+ # @LastEditTime: 2020-12-16 11:24:17
8
+###
9
+#!/bin/bash
10
+
11
+if [ $1 == "" ]; then
12
+    echo "请加上环境参数"
13
+    exit 1
14
+fi
15
+
16
+proName="box-3rdServer-"$1
17
+
18
+git pull
19
+go build -o $proName
20
+
21
+echo "kill $proName, copy new file"
22
+# kill -9 `cat ./$proName.pid`
23
+ps -ef|grep $proName |grep -v grep |awk '{print $2}' | xargs kill -9
24
+# kill -9 `ps -ef|grep $proName`
25
+# echo $pid
26
+# kill -9 $pid
27
+sleep 0.5
28
+
29
+cp conf/$1/app.conf_ali ./conf/app.conf
30
+
31
+rm -rf ./nohup_$1.out
32
+
33
+echo "restart "$proName
34
+nohup ./$proName > nohup_$1.log 2>&1 &
35
+
36
+echo "ok"
37
+exit 0;

+ 37 - 0
run_test.sh

@@ -0,0 +1,37 @@
1
+###
2
+ # @Descripttion:
3
+ # @version:
4
+ # @Author: Neo,Huang
5
+ # @Date: 2020-11-06 09:53:23
6
+ # @LastEditors: Neo,Huang
7
+ # @LastEditTime: 2020-12-16 11:24:24
8
+###
9
+#!/bin/bash
10
+
11
+if [ $1 == "" ]; then
12
+    echo "请加上环境参数"
13
+    exit 1
14
+fi
15
+
16
+proName="box-3rdServer-"$1
17
+
18
+git pull
19
+go build -o $proName
20
+
21
+echo "kill $proName, copy new file"
22
+# kill -9 `cat ./$proName.pid`
23
+ps -ef|grep $proName |grep -v grep |awk '{print $2}' | xargs kill -9
24
+# kill -9 `ps -ef|grep $proName`
25
+# echo $pid
26
+# kill -9 $pid
27
+sleep 0.5
28
+
29
+cp conf/$1/app.conf_ali_test ./conf/app.conf
30
+
31
+rm -rf ./nohup_$1.out
32
+
33
+echo "restart "$proName
34
+nohup ./$proName > nohup_$1.log 2>&1 &
35
+
36
+echo "ok"
37
+exit 0;

+ 160 - 0
sensitive/dfa.go

@@ -0,0 +1,160 @@
1
+/*
2
+ * @Descripttion:敏感词
3
+ * @version:
4
+ * @Author: Neo,Huang
5
+ * @Date: 2021-04-17 11:04:16
6
+ * @LastEditors: Neo,Huang
7
+ * @LastEditTime: 2021-08-06 14:12:44
8
+ */
9
+package sensitive
10
+
11
+import (
12
+	"bufio"
13
+	"fmt"
14
+	"io"
15
+	"os"
16
+	"strings"
17
+)
18
+
19
+type Null struct{}
20
+
21
+var sensitiveWord = make(map[string]interface{})
22
+var Set = make(map[string]Null)
23
+
24
+const InvalidWords = " ,~,!,@,#,$,%,^,&,*,(,),_,-,+,=,?,<,>,.,—,,,。,/,\\,|,《,》,?,;,:,:,',‘,;,“,"
25
+
26
+var InvalidWord = make(map[string]Null) //无效词汇,不参与敏感词汇判断直接忽略
27
+
28
+// 初始化
29
+func InitDFA() {
30
+	words := strings.Split(InvalidWords, ",")
31
+	for _, v := range words {
32
+		InvalidWord[v] = Null{}
33
+	}
34
+
35
+	f, err := os.Open("sensitive/words.txt")
36
+	if err != nil {
37
+		return
38
+	}
39
+	defer f.Close()
40
+
41
+	buff := bufio.NewReader(f)
42
+	for {
43
+		line, err := buff.ReadString('\n')
44
+
45
+		if err != nil || io.EOF == err {
46
+			break
47
+		}
48
+		line = strings.TrimSpace(line)
49
+
50
+		Set[line] = Null{}
51
+	}
52
+
53
+	AddSensitiveToMap(Set)
54
+}
55
+
56
+//生成违禁词集合
57
+func AddSensitiveToMap(set map[string]Null) {
58
+	for key := range set {
59
+		str := []rune(key)
60
+		nowMap := sensitiveWord
61
+		for i := 0; i < len(str); i++ {
62
+			if _, ok := nowMap[string(str[i])]; !ok { //如果该key不存在,
63
+				thisMap := make(map[string]interface{})
64
+				thisMap["isEnd"] = false
65
+				nowMap[string(str[i])] = thisMap
66
+				nowMap = thisMap
67
+			} else {
68
+				nowMap = nowMap[string(str[i])].(map[string]interface{})
69
+			}
70
+			if i == len(str)-1 {
71
+				nowMap["isEnd"] = true
72
+			}
73
+		}
74
+
75
+	}
76
+}
77
+func GetSensitiveMap() map[string]interface{} {
78
+	return sensitiveWord
79
+}
80
+
81
+//敏感词汇转换为*
82
+func ChangeSensitiveWords(txt string, sensitive map[string]interface{}) (word string) {
83
+	str := []rune(txt)
84
+	nowMap := sensitive
85
+	start := -1
86
+	tag := -1
87
+	for i := 0; i < len(str); i++ {
88
+		if _, ok := InvalidWord[(string(str[i]))]; ok || string(str[i]) == "," {
89
+			continue
90
+		}
91
+		if thisMap, ok := nowMap[string(str[i])].(map[string]interface{}); ok {
92
+			tag++
93
+			if tag == 0 {
94
+				start = i
95
+			}
96
+			isEnd, _ := thisMap["isEnd"].(bool)
97
+			if isEnd {
98
+				for y := start; y < i+1; y++ {
99
+					str[y] = 42
100
+				}
101
+				nowMap = sensitive
102
+				start = -1
103
+				tag = -1
104
+
105
+			} else {
106
+				nowMap = nowMap[string(str[i])].(map[string]interface{})
107
+			}
108
+
109
+		} else {
110
+			if start != -1 {
111
+				i = start
112
+			}
113
+			nowMap = sensitive
114
+			start = -1
115
+			tag = -1
116
+		}
117
+	}
118
+
119
+	return string(str)
120
+}
121
+
122
+// 敏感词检查
123
+func CheckSensitive(txt string, sensitive map[string]interface{}) string {
124
+	str := []rune(txt)
125
+	nowMap := sensitive
126
+	start := -1
127
+	tag := -1
128
+	for i := 0; i < len(str); i++ {
129
+		// 跳过无效字符
130
+		if _, ok := InvalidWord[(string(str[i]))]; ok || string(str[i]) == "," {
131
+			continue
132
+		}
133
+		if thisMap, ok := nowMap[string(str[i])].(map[string]interface{}); ok {
134
+			tag++
135
+			if tag == 0 {
136
+				start = i
137
+			}
138
+			isEnd, _ := thisMap["isEnd"].(bool)
139
+			if isEnd {
140
+				sensi := ""
141
+				for y := start; y < i+1; y++ {
142
+					sensi += string(str[y])
143
+				}
144
+				fmt.Printf("敏感词:%s\n", sensi)
145
+				return "false"
146
+			} else {
147
+				nowMap = nowMap[string(str[i])].(map[string]interface{})
148
+			}
149
+
150
+		} else {
151
+			if start != -1 {
152
+				i = start
153
+			}
154
+			nowMap = sensitive
155
+			start = -1
156
+			tag = -1
157
+		}
158
+	}
159
+	return "true"
160
+}

+ 51 - 0
sensitive/interface.go

@@ -0,0 +1,51 @@
1
+/*
2
+ * @Descripttion:敏感词
3
+ * @version:
4
+ * @Author: Neo,Huang
5
+ * @Date: 2021-04-17 11:04:16
6
+ * @LastEditors: Neo,Huang
7
+ * @LastEditTime: 2021-04-20 09:52:10
8
+ */
9
+package sensitive
10
+
11
+import (
12
+	"encoding/json"
13
+	"net/http"
14
+)
15
+
16
+// 初始化
17
+func Init() {
18
+	InitDFA()
19
+}
20
+
21
+// 敏感词检查
22
+// 方法:get
23
+// 参数:
24
+// 	word:检查字符串
25
+// 返回
26
+// 	true/false
27
+func HttpCheckWord(w http.ResponseWriter, r *http.Request) {
28
+	req := r.URL.Query()
29
+	word := req.Get("word")
30
+
31
+	cw := CheckSensitive(word, sensitiveWord)
32
+	// 发送成功
33
+	w.Write([]byte(cw))
34
+}
35
+
36
+// 敏感词检查
37
+// 方法:get
38
+// 参数:
39
+// 	word:检查字符串
40
+// 返回
41
+// 	true/false
42
+func HttpChangeWord(w http.ResponseWriter, r *http.Request) {
43
+	req := r.URL.Query()
44
+	word := req.Get("word")
45
+
46
+	ret := make(map[string]string)
47
+	ret["word"] = ChangeSensitiveWords(word, sensitiveWord)
48
+	pack, _ := json.Marshal(ret)
49
+	// 发送成功
50
+	w.Write(pack)
51
+}

Разница между файлами не показана из-за своего большого размера
+ 75443 - 0
sensitive/words.txt


+ 76 - 0
utils/mysql.go

@@ -0,0 +1,76 @@
1
+/*
2
+ * @Descripttion:
3
+ * @version:
4
+ * @Author: Neo,Huang
5
+ * @Date: 2020-10-16 14:29:56
6
+ * @LastEditors: Neo,Huang
7
+ * @LastEditTime: 2020-11-09 14:11:24
8
+ */
9
+package utils
10
+
11
+import (
12
+	"fmt"
13
+
14
+	"database/sql"
15
+	"log"
16
+
17
+	// import sql driver
18
+	_ "github.com/go-sql-driver/mysql"
19
+)
20
+
21
+// 获取数据库handler
22
+var mapMysql = make(map[string]*sql.DB)
23
+
24
+// GetMysqlHandler getMysqlHandler
25
+func GetMysqlHandler() (*sql.DB, error) {
26
+	var err error
27
+	project := GetProject()
28
+
29
+	if mapMysql[project] != nil {
30
+		err = mapMysql[project].Ping()
31
+		if err == nil {
32
+			return mapMysql[project], nil
33
+		}
34
+		log.Print("GetMysqlHandler PING:", err)
35
+		mapMysql[project].Close()
36
+	}
37
+
38
+	configFile := GetConfigFile()
39
+
40
+	connString := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8", //
41
+		GetConf("mysql::user", configFile), GetConf("mysql::password", configFile),
42
+		GetConf("mysql::host", configFile), GetConf("mysql::port", configFile), GetConf("mysql::database", configFile))
43
+
44
+	log.Println("GetMysqlHandler connString:", connString)
45
+	mapMysql[project], err = sql.Open("mysql", connString)
46
+	if err != nil {
47
+		log.Fatal("Open connection failed:", err.Error())
48
+		return nil, err
49
+	}
50
+	err = mapMysql[project].Ping()
51
+	if err != nil {
52
+		log.Print("PING:", err)
53
+		return nil, err
54
+	}
55
+
56
+	return mapMysql[project], nil
57
+}
58
+
59
+// 更新玩家状态
60
+func UpdatePlayerStatus(uid int, status int) error {
61
+	db, err := GetMysqlHandler()
62
+	if err != nil {
63
+		log.Println("UpdatePlayerStatus get_mahjong_db, Error: ", err)
64
+		return err
65
+	}
66
+
67
+	sql := fmt.Sprintf("UPDATE game_user SET status=%d WHERE uid=%d;", status, uid)
68
+	// log.Println("order_insert_db sql:", sql)
69
+	_, err = db.Exec(sql)
70
+	if err != nil {
71
+		log.Println("UpdatePlayerStatus update data Exec Failed, Error: ", err)
72
+		return err
73
+	}
74
+
75
+	return nil
76
+}

+ 224 - 0
utils/redis.go

@@ -0,0 +1,224 @@
1
+/*
2
+ * @Descripttion:
3
+ * @version:
4
+ * @Author: Neo,Huang
5
+ * @Date: 2020-10-16 14:29:56
6
+ * @LastEditors: Neo,Huang
7
+ * @LastEditTime: 2020-12-04 11:00:01
8
+ */
9
+package utils
10
+
11
+import (
12
+	"fmt"
13
+	"log"
14
+	"time"
15
+
16
+	"github.com/garyburd/redigo/redis"
17
+	redigo "github.com/gomodule/redigo/redis"
18
+)
19
+type Redis struct {
20
+	pool     *redigo.Pool
21
+}
22
+// 连接池
23
+var mapRedisPool = make(map[string](map[int]*Redis))
24
+var mapAccountRedisPool = make(map[string]*Redis)
25
+// 实例数量
26
+var mapRedisCount = make(map[string]int)
27
+
28
+// InitRedis 初始化redis
29
+func InitRedis() bool {
30
+	count := StringToInt(GetKeyConf("redis", "count"))
31
+
32
+	mapRedisCount[project] = count
33
+	return true
34
+}
35
+// 获取玩家连接池
36
+func GetPlayerRedisPool(uid int) *redigo.Pool {
37
+	project := GetProject()
38
+	index := uid % mapRedisCount[project]
39
+	if mapRedisPool[project] == nil {
40
+		mapRedisPool[project] = make(map[int]*Redis)
41
+	}
42
+	redisConn := mapRedisPool[project][index]
43
+
44
+	if redisConn == nil {
45
+		configFile := GetConfigFile()
46
+		redisAddr := GetConf(fmt.Sprintf("redis::host_%d", index), configFile) + ":" + GetConf(fmt.Sprintf("redis::port_%d", index), configFile)
47
+		redisAuth := GetConf(fmt.Sprintf("redis::auth_%d", index), configFile)
48
+
49
+		log.Println(fmt.Sprintf("GetPlayerRedisPool project[%s] connString[%s]", project, redisAddr))
50
+		redisConn = new(Redis)
51
+
52
+		redisConn.pool = &redigo.Pool{
53
+			MaxIdle:     10,
54
+			IdleTimeout: 300 * time.Second,
55
+			MaxActive:   100,
56
+			Dial: func() (redigo.Conn, error) {
57
+				c, err := redigo.Dial("tcp", redisAddr)
58
+				if err != nil {
59
+					return nil, err
60
+				}
61
+				if redisAuth != "" {
62
+					_, err := c.Do("AUTH", redisAuth)
63
+					if err != nil {
64
+						c.Close()
65
+						return nil, err
66
+					}
67
+				}
68
+				return c, err
69
+			},
70
+			TestOnBorrow: func(c redigo.Conn, t time.Time) error {
71
+				_, err := c.Do("PING")
72
+				return err
73
+			},
74
+		}
75
+		mapRedisPool[project][index] = redisConn
76
+	}
77
+	return redisConn.pool
78
+}
79
+// 获取account redis连接池
80
+func GetAccountRedisPool() *redigo.Pool {
81
+	project := GetProject()
82
+	redisConn := mapAccountRedisPool[project]
83
+
84
+	if redisConn == nil {
85
+		configFile := GetConfigFile()
86
+		redisAddr := GetConf(fmt.Sprintf("redis::host_account"), configFile) + ":" + GetConf(fmt.Sprintf("redis::port_account"), configFile)
87
+		redisAuth := GetConf(fmt.Sprintf("redis::auth_account"), configFile)
88
+
89
+		log.Println(fmt.Sprintf("GetAccountRedisPool project[%s] connString[%s]", project, redisAddr))
90
+		redisConn = new(Redis)
91
+
92
+		redisConn.pool = &redigo.Pool{
93
+			MaxIdle:     10,
94
+			IdleTimeout: 300 * time.Second,
95
+			MaxActive:   100,
96
+			Dial: func() (redigo.Conn, error) {
97
+				c, err := redigo.Dial("tcp", redisAddr)
98
+				if err != nil {
99
+					return nil, err
100
+				}
101
+				if redisAuth != "" {
102
+					_, err := c.Do("AUTH", redisAuth)
103
+					if err != nil {
104
+						c.Close()
105
+						return nil, err
106
+					}
107
+				}
108
+				return c, err
109
+			},
110
+			TestOnBorrow: func(c redigo.Conn, t time.Time) error {
111
+				_, err := c.Do("PING")
112
+				return err
113
+			},
114
+		}
115
+		mapAccountRedisPool[project] = redisConn
116
+	}
117
+	return redisConn.pool
118
+}
119
+
120
+// GetPlayerInfoFromRedis do hget
121
+func GetPlayerInfoFromRedis(uid int, subKey string) string {
122
+	pool := GetPlayerRedisPool(uid)
123
+	if pool == nil {
124
+		fmt.Println("get redis pool fail")
125
+		return ""
126
+	}
127
+	redisConn := pool.Get()
128
+	if redisConn == nil {
129
+		fmt.Println("get redis conn fail")
130
+		return ""
131
+	}
132
+	defer redisConn.Close()
133
+	key := fmt.Sprintf("player:uid:%d", uid)
134
+
135
+	reply, err := redisConn.Do("hget", key, subKey)
136
+	if err != nil {
137
+		fmt.Println("GetPlayerInfoFromRedis err:", err)
138
+		return ""
139
+	}
140
+	info, _ := redis.String(reply, err)
141
+	// fmt.Println(info)
142
+	return info
143
+}
144
+
145
+// SetPlayerInfoFromRedis do hget
146
+func SetPlayerInfoFromRedis(uid int, subKey string, val string) bool {
147
+	pool := GetPlayerRedisPool(uid)
148
+	if pool == nil {
149
+		fmt.Println("get redis pool fail")
150
+		return false
151
+	}
152
+	redisConn := pool.Get()
153
+	if redisConn == nil {
154
+		fmt.Println("get redis conn fail")
155
+		return false
156
+	}
157
+	defer redisConn.Close()
158
+	key := fmt.Sprintf("player:uid:%d", uid)
159
+
160
+	_, err := redisConn.Do("hset", key, subKey, []byte(val))
161
+	if err != nil {
162
+		fmt.Println("SetPlayerInfoFromRedis err:", err)
163
+		return false
164
+	}
165
+	return true
166
+}
167
+
168
+// 设置玩家支付信息
169
+func UpdatePlayerPayInfo(uid int, pay int, payCount int, detail []byte, records []byte) bool {
170
+	pool := GetPlayerRedisPool(uid)
171
+	if pool == nil {
172
+		fmt.Println("get redis pool fail")
173
+		return false
174
+	}
175
+	rd := pool.Get()
176
+	defer rd.Close()
177
+
178
+	key := fmt.Sprintf("player:uid:%d", uid)
179
+
180
+	val := IntToString(pay)
181
+	_, err := rd.Do("hset", key, "pay", []byte(val))
182
+	if err != nil {
183
+		log.Println("UpdatePlayerPayInfo pay hset fail!", err)
184
+		return false
185
+	}
186
+	val = IntToString(payCount)
187
+	_, err = rd.Do("hset", key, "pay_count", []byte(val))
188
+	if err != nil {
189
+		log.Println("UpdatePlayerPayInfo pay_count hset fail!", err)
190
+		return false
191
+	}
192
+	_, err = rd.Do("hset", key, "js:sd", detail)
193
+	if err != nil {
194
+		log.Println("UpdatePlayerPayInfo js:sd hset fail!", err)
195
+		return false
196
+	}
197
+	_, err = rd.Do("hset", key, "js:shop", records)
198
+	if err != nil {
199
+		log.Println("UpdatePlayerPayInfo js:shop hset fail!", err)
200
+		return false
201
+	}
202
+
203
+	return true
204
+}
205
+
206
+// 删除玩家
207
+func DelPlayerInfo(uid int) bool {
208
+	pool := GetPlayerRedisPool(uid)
209
+	if pool == nil {
210
+		fmt.Println("get redis pool fail")
211
+		return false
212
+	}
213
+	rd := pool.Get()
214
+	defer rd.Close()
215
+
216
+	key := fmt.Sprintf("player:uid:%d", uid)
217
+	_, err := rd.Do("del", key)
218
+	if err != nil {
219
+		log.Println("redis_del_order_info fail!", uid, err)
220
+		return false
221
+	}
222
+
223
+	return true
224
+}

+ 115 - 0
utils/sign.go

@@ -0,0 +1,115 @@
1
+/*
2
+ * @Descripttion:
3
+ * @version:
4
+ * @Author: Neo,Huang
5
+ * @Date: 2020-10-16 14:29:56
6
+ * @LastEditors: Neo,Huang
7
+ * @LastEditTime: 2020-12-16 14:27:06
8
+ */
9
+package utils
10
+
11
+import (
12
+	"crypto/md5"
13
+	"fmt"
14
+	"io"
15
+	"net/url"
16
+	"sort"
17
+	"github.com/astaxie/beego"
18
+	"strconv"
19
+	"encoding/hex"
20
+)
21
+
22
+// Kv struct
23
+type Kv struct {
24
+	Key, Value string
25
+}
26
+
27
+// Kvs typenmae
28
+type Kvs []*Kv
29
+
30
+func (a Kvs) Len() int           { return len(a) }
31
+func (a Kvs) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
32
+func (a Kvs) Less(i, j int) bool { return a[i].Key < a[j].Key }
33
+
34
+var secrets map[string]string
35
+
36
+func init_secrets()  {
37
+	secrets = make(map[string]string)
38
+	secrets["101"] = "39baf5e79adac446131b7c78608cfe3d"
39
+	secrets["102"] = "51f4e76fc3b42c56243e9aa504ddfc9e"
40
+}
41
+
42
+// 获取appkey对应的appSecret
43
+func GetSecretByKey(appKey string) string {
44
+	if appKey == "" {
45
+		return ""
46
+	}
47
+	secret, ok := secrets[appKey]
48
+	if ok == false {
49
+		init_secrets()
50
+		secret, ok = secrets[appKey]
51
+	}
52
+	return secret
53
+}
54
+
55
+//Md5 md5散列函数
56
+func Md5(str string) string {
57
+	h := md5.New()
58
+	io.WriteString(h, str)
59
+	return fmt.Sprintf("%x", h.Sum(nil))
60
+}
61
+
62
+var keyMahjong = "am0xNjAzOTUxODE2"
63
+
64
+// MakeSign 生成签名秘钥
65
+func MakeSign(m map[string]string, appKey string) string {
66
+	var kvs Kvs
67
+	for k, v := range m {
68
+		kvs = append(kvs, &Kv{k, url.QueryEscape(v)})
69
+	}
70
+	sort.Sort(kvs)
71
+
72
+	key := ""
73
+	for i := 0; i < kvs.Len(); i++ {
74
+		key += kvs[i].Key + kvs[i].Value
75
+	}
76
+	if appKey != "" {
77
+		key += appKey
78
+	}
79
+
80
+	return Md5(key)
81
+}
82
+
83
+// MakeSign 生成签名秘钥
84
+func MakeKeySign(m map[string]interface{}) string {
85
+	var kvs Kvs
86
+	for k, v := range m {
87
+		switch val := v.(type) {
88
+		case int:
89
+			kvs = append(kvs, &Kv{k, IntToString(val)})
90
+		case int64:
91
+			kvs = append(kvs, &Kv{k, strconv.FormatInt(val, 10)})
92
+		case string:
93
+			kvs = append(kvs, &Kv{k, url.QueryEscape(val)})
94
+		}
95
+	}
96
+	sort.Sort(kvs)
97
+
98
+	key := ""
99
+	for i := 0; i < kvs.Len(); i++ {
100
+		key += kvs[i].Key + kvs[i].Value
101
+	}
102
+	if beego.AppConfig.String("project") == "mj" {
103
+		key += keyMahjong
104
+	}
105
+
106
+	return Md5(key)
107
+}
108
+
109
+// Strtomd5 md5
110
+func Strtomd5(s string) string {
111
+	h := md5.New()
112
+	h.Write([]byte(s))
113
+	rs := hex.EncodeToString(h.Sum(nil))
114
+	return rs
115
+}

+ 303 - 0
utils/util.go

@@ -0,0 +1,303 @@
1
+/*
2
+ * @Descripttion:
3
+ * @version:
4
+ * @Author: Neo,Huang
5
+ * @Date: 2020-10-20 14:01:47
6
+ * @LastEditors: Please set LastEditors
7
+ * @LastEditTime: 2021-04-19 15:09:30
8
+ */
9
+package utils
10
+
11
+import (
12
+	"bytes"
13
+	"crypto/aes"
14
+	"crypto/cipher"
15
+	"encoding/hex"
16
+	"encoding/json"
17
+	"fmt"
18
+	"io/ioutil"
19
+	"log"
20
+	"net/http"
21
+	"net/url"
22
+	"os"
23
+	"sort"
24
+	"strconv"
25
+	"strings"
26
+	"time"
27
+
28
+	"github.com/astaxie/beego"
29
+	"github.com/astaxie/beego/config"
30
+)
31
+
32
+// StringToInt string to int
33
+func StringToInt(itf interface{}) int {
34
+	str, _ := itf.(string)
35
+	i, _ := strconv.Atoi(str)
36
+	return i
37
+}
38
+
39
+// IntToString int to string
40
+func IntToString(number int) string {
41
+	return strconv.Itoa(number)
42
+}
43
+
44
+// StringToInt64 string to int64
45
+func StringToInt64(itf interface{}) int64 {
46
+	str, _ := itf.(string)
47
+	i, _ := strconv.ParseInt(str, 10, 64)
48
+	return i
49
+}
50
+
51
+// Int64ToString int64 to string
52
+func Int64ToString(number int64) string {
53
+	return strconv.FormatInt(number, 10)
54
+}
55
+
56
+// GetConf config
57
+func GetConf(key string, file string) string {
58
+	iniconf, err := config.NewConfig("ini", file)
59
+	if err != nil {
60
+		fmt.Println(err.Error())
61
+	}
62
+	return iniconf.String(key)
63
+}
64
+
65
+// ResponseHTTPJSON return json
66
+func ResponseHTTPJSON(w http.ResponseWriter, m map[string]interface{}) {
67
+	str, _ := json.Marshal(m)
68
+	w.Header().Set("Content-Length", IntToString(len(str)))
69
+	w.Header().Set("Content-Type", "text/json")
70
+	w.Write([]byte(str))
71
+}
72
+
73
+// SendAndRecvHTTP send
74
+func SendAndRecvHTTP(method string, url string, body string) ([]byte, error) {
75
+	client := &http.Client{}
76
+	req, err1 := http.NewRequest(method, url, strings.NewReader(body))
77
+	if err1 != nil {
78
+		return nil, err1
79
+	}
80
+	req.Header.Set("Content-Type", "application/json")
81
+	req.Header.Set("Content-Length", IntToString(len(body)))
82
+	req.Header.Set("Connection", "close")
83
+
84
+	resp, err2 := client.Do(req)
85
+	if err2 != nil {
86
+		return nil, err2
87
+	}
88
+	defer resp.Body.Close()
89
+
90
+	return ioutil.ReadAll(resp.Body)
91
+}
92
+
93
+// 日志输出
94
+func SetEventLog(strLog string, strFile string) {
95
+	// 创建日志文件
96
+	filepath := fmt.Sprintf("/alidata/log/order/%s-%s.log", strFile, time.Now().Format("2006-01-02"))
97
+	file, err := os.OpenFile(filepath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
98
+	if err != nil {
99
+		log.Println("create log file failed! err:", err)
100
+	}
101
+	defer file.Close()
102
+
103
+	//获取当前程序执行的绝对路径
104
+	_, err = file.WriteString(strLog + "\n")
105
+	if err != nil {
106
+		log.Println("write string err:", err)
107
+	}
108
+}
109
+
110
+// 应答 - 无签名
111
+func ResponseUnsign(w http.ResponseWriter, m map[string]string) {
112
+	str, _ := json.Marshal(m)
113
+
114
+	w.Header().Set("Content-Length", IntToString(len(str)))
115
+	w.Header().Set("Content-Type", "text/plain")
116
+	w.Write([]byte(str))
117
+}
118
+
119
+// http请求 - json参数
120
+func RequestHttpJson(method string, url string, body string) ([]byte, error) {
121
+	client := &http.Client{}
122
+	req, err1 := http.NewRequest(method, url, strings.NewReader(body))
123
+	if err1 != nil {
124
+		return nil, err1
125
+	}
126
+	req.Header.Set("Content-Type", "application/json")
127
+	req.Header.Set("Content-Length", IntToString(len(body)))
128
+	req.Header.Set("Connection", "close")
129
+
130
+	resp, err2 := client.Do(req)
131
+	if err2 != nil {
132
+		return nil, err2
133
+	}
134
+	defer resp.Body.Close()
135
+
136
+	return ioutil.ReadAll(resp.Body)
137
+}
138
+
139
+// http请求 - url加密参数
140
+func RequestHttpEncoded(method string, url string, body string) ([]byte, error) {
141
+	client := &http.Client{}
142
+	req, err1 := http.NewRequest(method, url, strings.NewReader(body))
143
+	if err1 != nil {
144
+		return nil, err1
145
+	}
146
+	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
147
+	req.Header.Set("Content-Length", IntToString(len(body)))
148
+	req.Header.Set("Connection", "close")
149
+
150
+	resp, err2 := client.Do(req)
151
+	if err2 != nil {
152
+		return nil, err2
153
+	}
154
+	defer resp.Body.Close()
155
+
156
+	return ioutil.ReadAll(resp.Body)
157
+}
158
+
159
+// 序列化url参数
160
+func UrlSerial(values url.Values) (r string) {
161
+	keys := make([]string, 0, len(values))
162
+	for k := range values {
163
+		keys = append(keys, k)
164
+	}
165
+	sort.Strings(keys)
166
+	for _, v := range keys {
167
+		if r != "" {
168
+			r += "&"
169
+		}
170
+		r += v + "=" + values.Get(v)
171
+	}
172
+	return
173
+}
174
+
175
+// 获取游戏密钥
176
+func GetGameKey() string {
177
+	configFile := GetConfigFile()
178
+	gameKey := GetConf("servers::gameKey", configFile)
179
+	return gameKey
180
+}
181
+
182
+// 获取游戏服地址
183
+func GetGameHost() string {
184
+	configFile := GetConfigFile()
185
+	host := GetConf("servers::game", configFile)
186
+	return host
187
+}
188
+
189
+// 获取趣头条参数
190
+func GetQttConf(channel string, key string) string {
191
+	configFile := GetConfigFile()
192
+	host := GetConf(fmt.Sprintf("qttgame%s::%s", channel, key), configFile)
193
+	return host
194
+}
195
+
196
+// 获取配置参数
197
+func GetKeyConf(key string, subKey string) string {
198
+	configFile := GetConfigFile()
199
+	host := GetConf(fmt.Sprintf("%s::%s", key, subKey), configFile)
200
+	return host
201
+}
202
+
203
+// 项目
204
+var project string
205
+
206
+func InitProject() {
207
+	project = beego.AppConfig.String("project")
208
+}
209
+func GetProject() string {
210
+	return project
211
+}
212
+
213
+// 配置文件
214
+func GetConfigFile() string {
215
+	project := GetProject()
216
+	configFile := fmt.Sprintf("conf/%s/cfg.conf", project)
217
+	if beego.AppConfig.String("runmode") == "test" {
218
+		configFile = fmt.Sprintf("conf/%s/cfg_test.conf", project)
219
+	}
220
+
221
+	return configFile
222
+}
223
+
224
+// 获取配置文件目录
225
+func GetConfigPath() string {
226
+	project := GetProject()
227
+	return fmt.Sprintf("conf/%s/", project)
228
+}
229
+
230
+func pKCS5Padding(ciphertext []byte, blockSize int) []byte {
231
+	padding := blockSize - len(ciphertext)%blockSize
232
+	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
233
+	return append(ciphertext, padtext...)
234
+}
235
+
236
+func pKCS5UnPadding(origData []byte) []byte {
237
+	length := len(origData)
238
+	// 去掉最后一个字节 unpadding 次
239
+	unpadding := int(origData[length-1])
240
+	return origData[:(length - unpadding)]
241
+}
242
+
243
+//AesEncrypt aes加密函数,返回加密后的结果长度是16的倍数
244
+func AesEncrypt(origData, key []byte) ([]byte, error) {
245
+	block, err := aes.NewCipher(key)
246
+	if err != nil {
247
+		return nil, err
248
+	}
249
+	blockSize := block.BlockSize()
250
+	origData = pKCS5Padding(origData, blockSize)
251
+
252
+	// iv := make([]byte, aes.BlockSize)
253
+	iv := []byte("0304050607080910")
254
+	blockMode := cipher.NewCBCEncrypter(block, iv)
255
+	crypted := make([]byte, len(origData))
256
+	blockMode.CryptBlocks(crypted, origData)
257
+	return crypted, nil
258
+}
259
+
260
+//AesDecrypt aes解密函数,传入解密内容长度必须是16的倍数
261
+func AesDecrypt(crypted, key []byte) ([]byte, error) {
262
+	block, err := aes.NewCipher(key)
263
+	if err != nil {
264
+		return nil, err
265
+	}
266
+	// iv := make([]byte, aes.BlockSize)
267
+	iv := []byte("0304050607080910")
268
+	blockMode := cipher.NewCBCDecrypter(block, iv)
269
+	origData := make([]byte, len(crypted))
270
+	blockMode.CryptBlocks(origData, crypted)
271
+	origData = pKCS5UnPadding(origData)
272
+	return origData, nil
273
+}
274
+
275
+func EncodeData(ts string, data string, appKey string) string {
276
+	key := Md5(appKey + ts)
277
+	en, err := AesEncrypt([]byte(data), []byte(key))
278
+	if err != nil {
279
+		return ""
280
+	}
281
+	return strings.ToUpper(hex.EncodeToString(en))
282
+}
283
+
284
+func DecodeData(ts string, data string) (string, error) {
285
+	l := len(data)
286
+	if l == 0 || (l%16) != 0 {
287
+		return "", fmt.Errorf("decrype data error")
288
+	}
289
+
290
+	redAppKey := GetKeyConf("servers", "redAppKey")
291
+	key := Md5(redAppKey + ts)
292
+	buf, err1 := hex.DecodeString(data)
293
+	if err1 != nil {
294
+		return "", err1
295
+	}
296
+
297
+	de, err2 := AesDecrypt(buf, []byte(key))
298
+	if err2 != nil {
299
+		return "", err2
300
+	}
301
+
302
+	return string(de), nil
303
+}