|
@@ -6,6 +6,7 @@ import (
|
6
|
6
|
"encoding/json"
|
7
|
7
|
"io/ioutil"
|
8
|
8
|
"net/http"
|
|
9
|
+ "strings"
|
9
|
10
|
"wechat-conf/models"
|
10
|
11
|
"wechat-conf/models/model"
|
11
|
12
|
"wechat-conf/service/autoreply"
|
|
@@ -26,6 +27,8 @@ type WechatController struct {
|
26
|
27
|
wechatServ *wechat.WechatServ
|
27
|
28
|
}
|
28
|
29
|
|
|
30
|
+var nilData = []byte("success")
|
|
31
|
+
|
29
|
32
|
// Constructor 初始化 Controller
|
30
|
33
|
// @Title Constructor
|
31
|
34
|
// @Description 初始化 Controller, 系统自动调用
|
|
@@ -53,37 +56,37 @@ func (c *WechatController) ComponentPush() {
|
53
|
56
|
resMsg, err := xp.Parse(string(con))
|
54
|
57
|
if err != nil {
|
55
|
58
|
utils.LogError("xml解析失败:", err)
|
56
|
|
- c.ResponseRaw([]byte("success"))
|
|
59
|
+ c.ResponseRaw(nilData)
|
57
|
60
|
}
|
58
|
61
|
encrypt := resMsg["Encrypt"]
|
59
|
62
|
conf, err := c.wechatServ.GetComponentInfo()
|
60
|
63
|
if err != nil || conf == nil || conf.Appid == "" {
|
61
|
64
|
utils.LogError("读取微信配置文件失败")
|
62
|
|
- c.ResponseRaw([]byte("success"))
|
|
65
|
+ c.ResponseRaw(nilData)
|
63
|
66
|
}
|
64
|
67
|
EncodingAESKey := conf.Aeskey
|
65
|
68
|
|
66
|
69
|
AESKey, err := base64.StdEncoding.DecodeString(EncodingAESKey + "=")
|
67
|
70
|
if err != nil {
|
68
|
71
|
utils.LogError("DecodeString失败:", err)
|
69
|
|
- c.ResponseRaw([]byte("success"))
|
|
72
|
+ c.ResponseRaw(nilData)
|
70
|
73
|
}
|
71
|
74
|
EncryptVal, err := base64.StdEncoding.DecodeString(encrypt)
|
72
|
75
|
if err != nil {
|
73
|
76
|
utils.LogError("密文base64解析", err)
|
74
|
|
- c.ResponseRaw([]byte("success"))
|
|
77
|
+ c.ResponseRaw(nilData)
|
75
|
78
|
}
|
76
|
79
|
msgbyte, err := utils.AesDecrypt(EncryptVal, AESKey)
|
77
|
80
|
if err != nil {
|
78
|
81
|
utils.LogError("解密失败:", err)
|
79
|
|
- c.ResponseRaw([]byte("success"))
|
|
82
|
+ c.ResponseRaw(nilData)
|
80
|
83
|
}
|
81
|
84
|
utils.LogError("解密成功")
|
82
|
85
|
// 解析xml
|
83
|
86
|
msg, err := xp.Parse(string(msgbyte))
|
84
|
87
|
if err != nil {
|
85
|
88
|
utils.LogError("xml解析失败:", err)
|
86
|
|
- c.ResponseRaw([]byte("success"))
|
|
89
|
+ c.ResponseRaw(nilData)
|
87
|
90
|
}
|
88
|
91
|
utils.LogError("xml解析成功:", msg)
|
89
|
92
|
switch msg["InfoType"] {
|
|
@@ -106,7 +109,7 @@ func (c *WechatController) ComponentPush() {
|
106
|
109
|
wxclient := utils.WechatInit(cert, c.wechatServ.UpdateToken)
|
107
|
110
|
if wxclient == nil {
|
108
|
111
|
utils.LogError("获取wxclient失败")
|
109
|
|
- c.ResponseRaw([]byte("success"))
|
|
112
|
+ c.ResponseRaw(nilData)
|
110
|
113
|
}
|
111
|
114
|
beego.Error(wxclient)
|
112
|
115
|
utils.AppendWxClient(wxclient)
|
|
@@ -115,7 +118,7 @@ func (c *WechatController) ComponentPush() {
|
115
|
118
|
info, err := wxclient.GetWechatInfo()
|
116
|
119
|
if err != nil {
|
117
|
120
|
utils.LogError("获取微信信息失败")
|
118
|
|
- c.ResponseRaw([]byte("success"))
|
|
121
|
+ c.ResponseRaw(nilData)
|
119
|
122
|
}
|
120
|
123
|
beego.Error(info)
|
121
|
124
|
authorizerInfo := (info["authorizer_info"]).(map[string]interface{})
|
|
@@ -140,7 +143,7 @@ func (c *WechatController) ComponentPush() {
|
140
|
143
|
err = c.wechatServ.SaveWechatConf(conf)
|
141
|
144
|
if err != nil {
|
142
|
145
|
utils.LogError("保存微信授权信息失败:", err)
|
143
|
|
- c.ResponseRaw([]byte("success"))
|
|
146
|
+ c.ResponseRaw(nilData)
|
144
|
147
|
}
|
145
|
148
|
break
|
146
|
149
|
case INFOTYPE_UPDATEAUTHORIZED:
|
|
@@ -155,7 +158,7 @@ func (c *WechatController) ComponentPush() {
|
155
|
158
|
utils.Component.DelWxClient(appid)
|
156
|
159
|
break
|
157
|
160
|
}
|
158
|
|
- c.ResponseRaw([]byte("success"))
|
|
161
|
+ c.ResponseRaw(nilData)
|
159
|
162
|
}
|
160
|
163
|
|
161
|
164
|
// WechatInfo 微信接入
|
|
@@ -171,121 +174,179 @@ func (c *WechatController) WechatInfo() {
|
171
|
174
|
|
172
|
175
|
// WxReceive 微信消息接收
|
173
|
176
|
func (c *WechatController) WxReceive() {
|
174
|
|
- beego.Error("微信消息接入")
|
|
177
|
+ utils.LogInfo("接收微信事件, URI: ", c.Ctx.Input.URI())
|
|
178
|
+
|
|
179
|
+ // 初始化微信客户端
|
175
|
180
|
appid := c.GetString(":appid")
|
176
|
181
|
wechat, err := utils.Component.GetWxClient(appid)
|
177
|
182
|
if err != nil {
|
178
|
183
|
utils.LogError("获取微信失败: " + err.Error())
|
|
184
|
+ c.ResponseRaw(nilData)
|
179
|
185
|
}
|
180
|
|
- msg, err := wechat.TransformMessage(string(c.Ctx.Input.RequestBody))
|
181
|
|
- if err != nil {
|
182
|
|
- utils.LogError("读取微信服务发送内容失败: " + err.Error())
|
183
|
|
- c.ResponseRaw([]byte(""))
|
184
|
|
- }
|
185
|
|
- xp := &core.XMLParse{}
|
186
|
|
- beego.Error("消息:", msg)
|
187
|
|
- encrypt := msg["Encrypt"]
|
|
186
|
+
|
188
|
187
|
conf, err := c.wechatServ.GetComponentInfo()
|
189
|
188
|
if err != nil || conf == nil || conf.Appid == "" {
|
190
|
|
- utils.LogError("读取微信配置文件失败")
|
191
|
|
- c.ResponseRaw([]byte("success"))
|
|
189
|
+ utils.LogError("读取微信配置文件失败", err)
|
|
190
|
+ c.ResponseRaw(nilData)
|
192
|
191
|
}
|
193
|
|
- EncodingAESKey := conf.Aeskey
|
194
|
192
|
|
195
|
|
- AESKey, err := base64.StdEncoding.DecodeString(EncodingAESKey + "=")
|
|
193
|
+ // 校验接收数据
|
|
194
|
+ receiveData, err := c.validReceiveData(c.Ctx.Input.RequestBody, conf.Aeskey, wechat)
|
196
|
195
|
if err != nil {
|
197
|
|
- utils.LogError("DecodeString失败:", err)
|
198
|
|
- c.ResponseRaw([]byte("success"))
|
|
196
|
+ c.ResponseRaw(nilData)
|
199
|
197
|
}
|
200
|
|
- EncryptVal, err := base64.StdEncoding.DecodeString(encrypt)
|
|
198
|
+
|
|
199
|
+ // 获取返回内容
|
|
200
|
+ replyMessage, err := c.getReplayMessage(receiveData, wechat)
|
|
201
|
+ if err != nil || replyMessage == nil || len(replyMessage) == 0 {
|
|
202
|
+ c.ResponseRaw(nilData)
|
|
203
|
+ }
|
|
204
|
+
|
|
205
|
+ utils.LogInfo("反馈微信内容: ", string(replyMessage))
|
|
206
|
+
|
|
207
|
+ // 加密内容
|
|
208
|
+ sendData, err := c.encryptMessage(replyMessage, conf.Aeskey, conf.OriginToken, wechat)
|
|
209
|
+ if err != nil {
|
|
210
|
+ c.ResponseRaw(nilData)
|
|
211
|
+ }
|
|
212
|
+
|
|
213
|
+ sendMessage := string(sendData)
|
|
214
|
+
|
|
215
|
+ // 去掉多余的回车
|
|
216
|
+ sendMessage = strings.Replace(sendMessage, "\n\n", "\n", -1)
|
|
217
|
+ sendMessage = strings.Trim(sendMessage, "\n")
|
|
218
|
+ utils.LogInfo("反馈加密内容: ", sendMessage)
|
|
219
|
+
|
|
220
|
+ c.Ctx.Output.Header("Content-Type", "text/xml; charset=utf-8")
|
|
221
|
+ c.ResponseRaw([]byte(sendMessage))
|
|
222
|
+}
|
|
223
|
+
|
|
224
|
+// validReceiveData 校验接收信息
|
|
225
|
+// 没有通过 signature 校验,默认是正确的
|
|
226
|
+func (c *WechatController) validReceiveData(receiveData []byte, aesKey string, wechat *component.WxClient) (data map[string]string, err error) {
|
|
227
|
+ receiveMessage := string(receiveData)
|
|
228
|
+ utils.LogInfo("事件内容: ", receiveMessage)
|
|
229
|
+
|
|
230
|
+ var msg map[string]string
|
|
231
|
+ msg, err = wechat.TransformMessage(receiveMessage)
|
|
232
|
+ if err != nil {
|
|
233
|
+ utils.LogError("读取微信服务发送内容失败: " + err.Error())
|
|
234
|
+ return
|
|
235
|
+ }
|
|
236
|
+
|
|
237
|
+ var key []byte
|
|
238
|
+ var encryptData []byte
|
|
239
|
+ var decryptData []byte
|
|
240
|
+
|
|
241
|
+ key, err = base64.StdEncoding.DecodeString(aesKey + "=")
|
|
242
|
+ if err != nil {
|
|
243
|
+ utils.LogError("Base64 decode aes-key 失败:", err)
|
|
244
|
+ return
|
|
245
|
+ }
|
|
246
|
+
|
|
247
|
+ encryptData, err = base64.StdEncoding.DecodeString(msg["Encrypt"])
|
201
|
248
|
if err != nil {
|
202
|
249
|
utils.LogError("密文base64解析", err)
|
203
|
|
- c.ResponseRaw([]byte("success"))
|
|
250
|
+ return
|
204
|
251
|
}
|
205
|
|
- msgbyte, err := utils.AesDecrypt(EncryptVal, AESKey)
|
|
252
|
+
|
|
253
|
+ decryptData, err = utils.AesDecrypt(encryptData, key)
|
206
|
254
|
if err != nil {
|
207
|
255
|
utils.LogError("解密失败:", err)
|
208
|
|
- c.ResponseRaw([]byte("success"))
|
|
256
|
+ return
|
209
|
257
|
}
|
210
|
|
- utils.LogError("解密成功")
|
|
258
|
+
|
|
259
|
+ utils.LogInfo("内容解密: ", string(decryptData))
|
|
260
|
+
|
211
|
261
|
// 解析xml
|
212
|
|
- val, err := xp.Parse(string(msgbyte))
|
|
262
|
+ xp := &core.XMLParse{}
|
|
263
|
+ data, err = xp.Parse(string(decryptData))
|
213
|
264
|
if err != nil {
|
214
|
265
|
utils.LogError("xml解析失败:", err)
|
215
|
|
- c.ResponseRaw([]byte("success"))
|
|
266
|
+ return
|
|
267
|
+ }
|
|
268
|
+
|
|
269
|
+ return
|
|
270
|
+}
|
|
271
|
+
|
|
272
|
+// 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())
|
|
275
|
+ // cipher, err := core.NewCipher("pamtest", "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG", "wxb11529c136998cb6")
|
|
276
|
+ if err != nil {
|
|
277
|
+ utils.LogError("NewCipher 失败: " + err.Error())
|
|
278
|
+ return nil, err
|
216
|
279
|
}
|
217
|
|
- utils.LogError("xml解析成功:", val)
|
218
|
|
- var replay = new(model.TaAutoReply)
|
219
|
|
- switch val["MsgType"] {
|
|
280
|
+
|
|
281
|
+ dt := bytes.NewBuffer([]byte{})
|
|
282
|
+
|
|
283
|
+ nonce := c.GetString("nonce")
|
|
284
|
+ timestamp := c.GetString("timestamp")
|
|
285
|
+
|
|
286
|
+ cipher.Encrypt(dt, message, nonce, timestamp)
|
|
287
|
+
|
|
288
|
+ return dt.Bytes(), nil
|
|
289
|
+}
|
|
290
|
+
|
|
291
|
+func (c *WechatController) getReplayMessage(receviceData map[string]string, wechat *component.WxClient) (message []byte, err error) {
|
|
292
|
+ var replay *model.TaAutoReply
|
|
293
|
+
|
|
294
|
+ msgType := receviceData["MsgType"]
|
|
295
|
+ from := receviceData["ToUserName"]
|
|
296
|
+ openID := receviceData["FromUserName"]
|
|
297
|
+ appID := wechat.GetAppID()
|
|
298
|
+
|
|
299
|
+ // 暂时支持 文本以及订阅事件消息
|
|
300
|
+ switch msgType {
|
220
|
301
|
case "text":
|
221
|
|
- content := val["Content"]
|
222
|
|
- // 获取数据库存储返回类型
|
223
|
|
- replay, err = c.serv.GetAutoReplayByAppID(appid, content)
|
|
302
|
+ if replay, err = c.serv.GetAutoReplayByAppID(appID, receviceData["Content"]); err != nil {
|
|
303
|
+ utils.LogError("获取微信自动回复信息失败: " + err.Error())
|
|
304
|
+ return
|
|
305
|
+ }
|
|
306
|
+
|
224
|
307
|
break
|
225
|
308
|
case "event":
|
226
|
|
- beego.Error(val)
|
227
|
|
- switch val["Event"] {
|
|
309
|
+ switch receviceData["Event"] {
|
228
|
310
|
case "subscribe":
|
229
|
|
- replay, err = c.serv.GetSubscribeByAppID(appid)
|
|
311
|
+ if replay, err = c.serv.GetSubscribeByAppID(appID); err != nil {
|
|
312
|
+ utils.LogError("获取微信自动回复信息失败: " + err.Error())
|
|
313
|
+ return
|
|
314
|
+ }
|
|
315
|
+
|
230
|
316
|
break
|
231
|
|
- case "LICK":
|
232
|
|
- // 点击事件
|
233
|
|
- // key:=val["EventKey"]
|
234
|
|
- // keyreplay,err:=c.serv.GetReplayByKey(appid,key)
|
235
|
|
- // if err!=nil{
|
236
|
|
- // utils.LogError("获取按钮点击key失败: " + err.Error())
|
237
|
|
- // c.ResponseRaw([]byte(""))
|
238
|
|
- // }
|
239
|
|
- // if keyreplay!=nil && keyreplay.KeywordsId==""{
|
240
|
|
- // c.ResponseRaw([]byte(""))
|
241
|
|
- // }
|
|
317
|
+ case "CLICK":
|
|
318
|
+ target := receviceData["EventKey"]
|
|
319
|
+ if target != "" {
|
|
320
|
+ var replyText string
|
|
321
|
+ replyText, err = c.wechatServ.GetMenuReplyText(target)
|
|
322
|
+ if err != nil {
|
|
323
|
+ utils.LogError("获取菜单回复信息失败: " + err.Error())
|
|
324
|
+ return
|
|
325
|
+ }
|
242
|
326
|
|
|
327
|
+ replay = &model.TaAutoReply{
|
|
328
|
+ MessageType: models.MESSAGE_TYPE_PARAGRAPH,
|
|
329
|
+ MessageParagraph: replyText,
|
|
330
|
+ IsUse: models.AUTOREPLY_IS_USE_ON,
|
|
331
|
+ }
|
|
332
|
+ }
|
243
|
333
|
break
|
244
|
334
|
}
|
245
|
335
|
|
246
|
336
|
break
|
247
|
337
|
}
|
248
|
|
- if err != nil {
|
249
|
|
- utils.LogError("获取微信自动回复信息失败: " + err.Error())
|
250
|
|
- c.ResponseRaw([]byte(""))
|
251
|
|
- }
|
252
|
|
- if replay == nil {
|
253
|
|
- c.ResponseRaw([]byte(""))
|
254
|
|
- }
|
255
|
|
- openID := val["FromUserName"]
|
256
|
|
- message, err := c.getReplayMessage(replay, openID, wechat)
|
257
|
|
- if err != nil {
|
258
|
|
- utils.LogError("转换回复信息失败: " + err.Error())
|
259
|
|
- c.ResponseRaw([]byte(""))
|
260
|
|
- }
|
261
|
338
|
|
262
|
|
- cipher, err := core.NewCipher(utils.Component.GetToken(), EncodingAESKey, appid)
|
263
|
|
- if err != nil {
|
264
|
|
- utils.LogError("获取解密失败: " + err.Error())
|
265
|
|
- c.ResponseRaw([]byte(""))
|
|
339
|
+ if replay == nil {
|
|
340
|
+ return
|
266
|
341
|
}
|
267
|
342
|
|
268
|
|
- dt := bytes.NewBuffer([]byte{})
|
269
|
|
- cipher.Encrypt(dt, []byte(message))
|
270
|
|
- beego.Error("=========>", dt)
|
271
|
|
-
|
272
|
|
- c.ResponseRaw(dt.Bytes())
|
273
|
|
- // c.ResponseRaw([]byte("success"))
|
274
|
|
-}
|
275
|
|
-
|
276
|
|
-func (c *WechatController) getReplayMessage(replay *model.TaAutoReply, openid string, wx *component.WxClient) ([]byte, error) {
|
277
|
343
|
switch replay.MessageType {
|
278
|
344
|
case models.MESSAGE_TYPE_PARAGRAPH:
|
279
|
|
- msg, err := wx.ResponseMessageText(openid, replay.MessageParagraph)
|
280
|
|
- return msg, err
|
|
345
|
+ return wechat.ResponseMessageText(from, openID, replay.MessageParagraph)
|
281
|
346
|
case models.MESSAGE_TYPE_IMG:
|
282
|
|
- msg, err := wx.ResponseMessageImage(openid, replay.MessageImg)
|
283
|
|
- return msg, err
|
284
|
|
- // case models.MESSAGE_TYPE_PARAGRAPH:
|
285
|
|
- // msg, err := wx.ResponseMessageNews(openid, replay.MessageImg)
|
286
|
|
- // return msg, err
|
|
347
|
+ return wechat.ResponseMessageImage(from, openID, replay.MessageImg)
|
287
|
348
|
}
|
288
|
|
- return nil, nil
|
|
349
|
+ return
|
289
|
350
|
}
|
290
|
351
|
|
291
|
352
|
// GetPreAuthCode 获取预授权码
|