|
@@ -4,7 +4,6 @@ import (
|
4
|
4
|
"bytes"
|
5
|
5
|
"encoding/base64"
|
6
|
6
|
"encoding/json"
|
7
|
|
- "io/ioutil"
|
8
|
7
|
"net/http"
|
9
|
8
|
"strings"
|
10
|
9
|
"wechat-conf/models"
|
|
@@ -25,8 +24,22 @@ type WechatController struct {
|
25
|
24
|
BaseController
|
26
|
25
|
serv *autoreply.AutoreplyServ
|
27
|
26
|
wechatServ *wechat.WechatServ
|
|
27
|
+ compConf *model.SysComponentConf
|
|
28
|
+ cipher core.IOCipher
|
28
|
29
|
}
|
29
|
30
|
|
|
31
|
+const (
|
|
32
|
+ INFOTYPE_TICKET = "component_verify_ticket"
|
|
33
|
+ INFOTYPE_AUTHORIZED = "authorized"
|
|
34
|
+ INFOTYPE_UNAUTHORIZED = "unauthorized"
|
|
35
|
+ INFOTYPE_UPDATEAUTHORIZED = "updateauthorized"
|
|
36
|
+)
|
|
37
|
+
|
|
38
|
+const (
|
|
39
|
+ WX_OFFICE_TEST_APPID = "wx570bc396a51b8ff8"
|
|
40
|
+ WX_OFFICE_TEST_USERNAME = "gh_3c884a361561"
|
|
41
|
+)
|
|
42
|
+
|
30
|
43
|
var nilData = []byte("success")
|
31
|
44
|
|
32
|
45
|
// Constructor 初始化 Controller
|
|
@@ -35,83 +48,96 @@ var nilData = []byte("success")
|
35
|
48
|
func (c *WechatController) Constructor() {
|
36
|
49
|
c.serv = autoreply.NewAutoreplyServ(c.Context)
|
37
|
50
|
c.wechatServ = wechat.NewWechatServ(c.Context)
|
38
|
|
-}
|
39
|
51
|
|
40
|
|
-const (
|
41
|
|
- INFOTYPE_TICKET = "component_verify_ticket"
|
42
|
|
- INFOTYPE_AUTHORIZED = "authorized"
|
43
|
|
- INFOTYPE_UNAUTHORIZED = "unauthorized"
|
44
|
|
- INFOTYPE_UPDATEAUTHORIZED = "updateauthorized"
|
45
|
|
-)
|
|
52
|
+ var err error
|
|
53
|
+ c.compConf, err = c.wechatServ.GetComponentInfo()
|
|
54
|
+ if err != nil {
|
|
55
|
+ utils.LogError("获取平台配置失败", err)
|
|
56
|
+ return
|
|
57
|
+ }
|
46
|
58
|
|
47
|
|
-// ComponentPush 第三方平台推送
|
48
|
|
-func (c *WechatController) ComponentPush() {
|
49
|
|
- utils.LogError("推送开始")
|
50
|
|
- r := c.Ctx.Request
|
51
|
|
- defer r.Body.Close()
|
52
|
|
- con, _ := ioutil.ReadAll(r.Body)
|
53
|
|
- utils.LogError("推送消息:", string(con))
|
54
|
|
- // 解析xml
|
55
|
|
- xp := &core.XMLParse{}
|
56
|
|
- resMsg, err := xp.Parse(string(con))
|
|
59
|
+ c.cipher, err = core.NewCipher(c.compConf.OriginToken, c.compConf.Aeskey, c.compConf.Appid)
|
57
|
60
|
if err != nil {
|
58
|
|
- utils.LogError("xml解析失败:", err)
|
59
|
|
- c.ResponseRaw(nilData)
|
|
61
|
+ utils.LogError("初始化加解密算法失败", err)
|
|
62
|
+ return
|
60
|
63
|
}
|
61
|
|
- encrypt := resMsg["Encrypt"]
|
62
|
|
- conf, err := c.wechatServ.GetComponentInfo()
|
63
|
|
- if err != nil || conf == nil || conf.Appid == "" {
|
64
|
|
- utils.LogError("读取微信配置文件失败")
|
65
|
|
- c.ResponseRaw(nilData)
|
|
64
|
+}
|
|
65
|
+
|
|
66
|
+// preCheck 如果有需要用到加解密之前, 请先调用这个方法
|
|
67
|
+func (c *WechatController) preCheck(resp []byte) {
|
|
68
|
+ if c.compConf == nil || c.compConf.Appid == "" {
|
|
69
|
+ c.ResponseRaw(resp)
|
66
|
70
|
}
|
67
|
|
- EncodingAESKey := conf.Aeskey
|
68
|
71
|
|
69
|
|
- AESKey, err := base64.StdEncoding.DecodeString(EncodingAESKey + "=")
|
70
|
|
- if err != nil {
|
71
|
|
- utils.LogError("DecodeString失败:", err)
|
72
|
|
- c.ResponseRaw(nilData)
|
|
72
|
+ if c.cipher == nil {
|
|
73
|
+ c.ResponseRaw(resp)
|
73
|
74
|
}
|
74
|
|
- EncryptVal, err := base64.StdEncoding.DecodeString(encrypt)
|
75
|
|
- if err != nil {
|
76
|
|
- utils.LogError("密文base64解析", err)
|
|
75
|
+}
|
|
76
|
+
|
|
77
|
+// ComponentPush 接收第三方平台推送
|
|
78
|
+// 主要有 ticket, 取消授权等
|
|
79
|
+func (c *WechatController) ComponentPush() {
|
|
80
|
+ utils.LogInfo("接收平台推送")
|
|
81
|
+ c.preCheck(nilData)
|
|
82
|
+
|
|
83
|
+ // 接收内容
|
|
84
|
+ receiveData := string(c.Ctx.Input.RequestBody)
|
|
85
|
+ utils.LogInfo("接收内容", receiveData)
|
|
86
|
+ if receiveData == "" {
|
77
|
87
|
c.ResponseRaw(nilData)
|
78
|
88
|
}
|
79
|
|
- msgbyte, err := utils.AesDecrypt(EncryptVal, AESKey)
|
|
89
|
+
|
|
90
|
+ // 解密内容
|
|
91
|
+ r := bytes.NewBufferString(receiveData)
|
|
92
|
+ dt, err := c.cipher.Decrypt(r)
|
80
|
93
|
if err != nil {
|
81
|
|
- utils.LogError("解密失败:", err)
|
|
94
|
+ utils.LogError("解密数据失败", err)
|
82
|
95
|
c.ResponseRaw(nilData)
|
83
|
96
|
}
|
84
|
|
- utils.LogError("解密成功")
|
|
97
|
+
|
|
98
|
+ receiveMessage := string(dt)
|
|
99
|
+ utils.LogInfo("解密内容: ", receiveMessage)
|
|
100
|
+
|
85
|
101
|
// 解析xml
|
86
|
|
- msg, err := xp.Parse(string(msgbyte))
|
|
102
|
+ xp := &core.XMLParse{}
|
|
103
|
+ data, err := xp.Parse(receiveMessage)
|
87
|
104
|
if err != nil {
|
88
|
|
- utils.LogError("xml解析失败:", err)
|
|
105
|
+ utils.LogError("解析解密数据失败:", err)
|
89
|
106
|
c.ResponseRaw(nilData)
|
90
|
107
|
}
|
91
|
|
- utils.LogError("xml解析成功:", msg)
|
92
|
|
- switch msg["InfoType"] {
|
|
108
|
+
|
|
109
|
+ infoType := data["InfoType"]
|
|
110
|
+ fromWXOffice := data["AppId"] == WX_OFFICE_TEST_APPID
|
|
111
|
+
|
|
112
|
+ switch infoType {
|
93
|
113
|
case INFOTYPE_TICKET:
|
|
114
|
+ // 微信测试推送 component_verify_ticket, 只需要返回 success
|
|
115
|
+ if fromWXOffice {
|
|
116
|
+ c.ResponseRaw(nilData)
|
|
117
|
+ }
|
|
118
|
+
|
94
|
119
|
// 更新ticket
|
95
|
|
- conf.Ticket = msg["ComponentVerifyTicket"]
|
96
|
|
- err := c.wechatServ.UpdateComponentTicket(conf)
|
|
120
|
+ c.compConf.Ticket = data["ComponentVerifyTicket"]
|
|
121
|
+ err := c.wechatServ.UpdateComponentTicket(c.compConf)
|
97
|
122
|
if err != nil {
|
98
|
123
|
utils.LogError("修改ticket失败:", err)
|
99
|
124
|
}
|
100
|
|
- utils.RefreshComponentTicket(msg["ComponentVerifyTicket"])
|
|
125
|
+ utils.RefreshComponentTicket(data["ComponentVerifyTicket"])
|
101
|
126
|
break
|
|
127
|
+
|
102
|
128
|
case INFOTYPE_AUTHORIZED:
|
103
|
129
|
// 授权成功
|
104
|
130
|
var cert = map[string]string{
|
105
|
|
- "appid": msg["AuthorizerAppid"],
|
106
|
|
- "authorization_code": msg["AuthorizationCode"],
|
|
131
|
+ "appid": data["AuthorizerAppid"],
|
|
132
|
+ "authorization_code": data["AuthorizationCode"],
|
107
|
133
|
}
|
108
|
|
- beego.Error("授权成功参数:", cert)
|
|
134
|
+
|
109
|
135
|
wxclient := utils.WechatInit(cert, c.wechatServ.UpdateToken)
|
110
|
136
|
if wxclient == nil {
|
111
|
137
|
utils.LogError("获取wxclient失败")
|
112
|
138
|
c.ResponseRaw(nilData)
|
113
|
139
|
}
|
114
|
|
- beego.Error(wxclient)
|
|
140
|
+
|
115
|
141
|
utils.AppendWxClient(wxclient)
|
116
|
142
|
|
117
|
143
|
// 获取微信信息
|
|
@@ -120,18 +146,18 @@ func (c *WechatController) ComponentPush() {
|
120
|
146
|
utils.LogError("获取微信信息失败")
|
121
|
147
|
c.ResponseRaw(nilData)
|
122
|
148
|
}
|
123
|
|
- beego.Error(info)
|
|
149
|
+
|
124
|
150
|
authorizerInfo := (info["authorizer_info"]).(map[string]interface{})
|
125
|
|
- beego.Error(info["authorizer_info"])
|
|
151
|
+
|
126
|
152
|
// 插入数据库
|
127
|
|
- mjson, _ := json.Marshal(msg)
|
|
153
|
+ mjson, _ := json.Marshal(data)
|
128
|
154
|
HeadImg := ""
|
129
|
155
|
if authorizerInfo["head_img"] != nil {
|
130
|
156
|
HeadImg = authorizerInfo["head_img"].(string)
|
131
|
157
|
}
|
132
|
158
|
var conf = model.SysWechatConf{
|
133
|
|
- Appid: msg["AuthorizerAppid"],
|
134
|
|
- AuthorizationCode: msg["AuthorizationCode"],
|
|
159
|
+ Appid: data["AuthorizerAppid"],
|
|
160
|
+ AuthorizationCode: data["AuthorizationCode"],
|
135
|
161
|
AuthorizationInfo: string(mjson),
|
136
|
162
|
WxNikeName: authorizerInfo["nick_name"].(string),
|
137
|
163
|
HeadImg: HeadImg,
|
|
@@ -152,12 +178,13 @@ func (c *WechatController) ComponentPush() {
|
152
|
178
|
case INFOTYPE_UNAUTHORIZED:
|
153
|
179
|
// 取消授权
|
154
|
180
|
// 删除wechatConf信息,同时将org解绑
|
155
|
|
- appid := msg["AuthorizerAppid"]
|
|
181
|
+ appid := data["AuthorizerAppid"]
|
156
|
182
|
c.wechatServ.UnAuthorized(appid)
|
157
|
183
|
// 删除第三方中的微信信息
|
158
|
184
|
utils.Component.DelWxClient(appid)
|
159
|
185
|
break
|
160
|
186
|
}
|
|
187
|
+
|
161
|
188
|
c.ResponseRaw(nilData)
|
162
|
189
|
}
|
163
|
190
|
|
|
@@ -175,6 +202,7 @@ func (c *WechatController) WechatInfo() {
|
175
|
202
|
// WxReceive 微信消息接收
|
176
|
203
|
func (c *WechatController) WxReceive() {
|
177
|
204
|
utils.LogInfo("接收微信事件, URI: ", c.Ctx.Input.URI())
|
|
205
|
+ c.preCheck(nilData)
|
178
|
206
|
|
179
|
207
|
// 初始化微信客户端
|
180
|
208
|
appid := c.GetString(":appid")
|
|
@@ -184,14 +212,8 @@ func (c *WechatController) WxReceive() {
|
184
|
212
|
c.ResponseRaw(nilData)
|
185
|
213
|
}
|
186
|
214
|
|
187
|
|
- conf, err := c.wechatServ.GetComponentInfo()
|
188
|
|
- if err != nil || conf == nil || conf.Appid == "" {
|
189
|
|
- utils.LogError("读取微信配置文件失败", err)
|
190
|
|
- c.ResponseRaw(nilData)
|
191
|
|
- }
|
192
|
|
-
|
193
|
215
|
// 校验接收数据
|
194
|
|
- receiveData, err := c.validReceiveData(c.Ctx.Input.RequestBody, conf.Aeskey, wechat)
|
|
216
|
+ receiveData, err := c.validReceiveData(c.Ctx.Input.RequestBody, c.compConf.Aeskey, wechat)
|
195
|
217
|
if err != nil {
|
196
|
218
|
c.ResponseRaw(nilData)
|
197
|
219
|
}
|
|
@@ -205,7 +227,7 @@ func (c *WechatController) WxReceive() {
|
205
|
227
|
utils.LogInfo("反馈微信内容: ", string(replyMessage))
|
206
|
228
|
|
207
|
229
|
// 加密内容
|
208
|
|
- sendData, err := c.encryptMessage(replyMessage, conf.Aeskey, conf.OriginToken, wechat)
|
|
230
|
+ sendData, err := c.encryptMessage(replyMessage, c.compConf.Aeskey, c.compConf.OriginToken, c.compConf.Appid, wechat)
|
209
|
231
|
if err != nil {
|
210
|
232
|
c.ResponseRaw(nilData)
|
211
|
233
|
}
|
|
@@ -270,8 +292,8 @@ func (c *WechatController) validReceiveData(receiveData []byte, aesKey string, w
|
270
|
292
|
}
|
271
|
293
|
|
272
|
294
|
// encryptReceiveMessage 加密需要发送的信息
|
273
|
|
-func (c *WechatController) encryptMessage(message []byte, aesKey, token string, wechat *component.WxClient) ([]byte, error) {
|
274
|
|
- cipher, err := core.NewCipher(token, aesKey, wechat.GetAppID())
|
|
295
|
+func (c *WechatController) encryptMessage(message []byte, aesKey, token, appID string, wechat *component.WxClient) ([]byte, error) {
|
|
296
|
+ cipher, err := core.NewCipher(token, aesKey, appID)
|
275
|
297
|
// cipher, err := core.NewCipher("pamtest", "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG", "wxb11529c136998cb6")
|
276
|
298
|
if err != nil {
|
277
|
299
|
utils.LogError("NewCipher 失败: " + err.Error())
|
|
@@ -295,11 +317,31 @@ func (c *WechatController) getReplayMessage(receviceData map[string]string, wech
|
295
|
317
|
from := receviceData["ToUserName"]
|
296
|
318
|
openID := receviceData["FromUserName"]
|
297
|
319
|
appID := wechat.GetAppID()
|
|
320
|
+ fromWXOffice := openID == WX_OFFICE_TEST_USERNAME
|
298
|
321
|
|
299
|
322
|
// 暂时支持 文本以及订阅事件消息
|
300
|
323
|
switch msgType {
|
301
|
324
|
case "text":
|
302
|
|
- if replay, err = c.serv.GetAutoReplayByAppID(appID, receviceData["Content"]); err != nil {
|
|
325
|
+ content := receviceData["Content"]
|
|
326
|
+
|
|
327
|
+ // 微信文本消息测试
|
|
328
|
+ if fromWXOffice {
|
|
329
|
+ // 普通文本测试, 返回 TESTCOMPONENT_MSG_TYPE_TEXT_callback
|
|
330
|
+ if content == "TESTCOMPONENT_MSG_TYPE_TEXT" {
|
|
331
|
+ replay = &model.TaAutoReply{
|
|
332
|
+ MessageType: models.MESSAGE_TYPE_PARAGRAPH,
|
|
333
|
+ MessageParagraph: "TESTCOMPONENT_MSG_TYPE_TEXT_callback",
|
|
334
|
+ IsUse: models.AUTOREPLY_IS_USE_ON,
|
|
335
|
+ }
|
|
336
|
+
|
|
337
|
+ // 发送 query_auth_code , 返回空, 并立即调用客服接口
|
|
338
|
+ } else if strings.Index(content, "QUERY_AUTH_CODE") > -1 {
|
|
339
|
+ replay = nil
|
|
340
|
+ }
|
|
341
|
+ break
|
|
342
|
+ }
|
|
343
|
+
|
|
344
|
+ if replay, err = c.serv.GetAutoReplayByAppID(appID, content); err != nil {
|
303
|
345
|
utils.LogError("获取微信自动回复信息失败: " + err.Error())
|
304
|
346
|
return
|
305
|
347
|
}
|