Files
wechat_ipad_pro/db/message_callback.go

173 lines
5.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package db
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"regexp"
"strconv"
"time"
"xiawan/wx/db/table"
"xiawan/wx/protobuf/wechat"
"github.com/lunny/log"
)
// MessageCallbackPayload 消息回调内容体
type MessageCallbackPayload struct {
UUID string `json:"uuid"` // 微信UUID标识
MsgId string `json:"msg_id"` // 消息ID
FromUser string `json:"from_user"` // 发送方
ToUser string `json:"to_user"` // 接收方
MsgType int `json:"msg_type"` // 消息类型
Content string `json:"content"` // 消息内容
CreateTime int64 `json:"create_time"` // 消息创建时间
IsGroup bool `json:"is_group"` // 是否群消息
Attachments map[string]interface{} `json:"attachments,omitempty"` // 附件信息
RawData map[string]interface{} `json:"raw_data,omitempty"` // 原始数据
}
// decodeUnicodeEscapes 解码Unicode转义字符复用自 wxsocketmsg.go
func decodeUnicodeEscapes(s string) string {
// 处理JSON中的Unicode转义字符如\u003c
re := regexp.MustCompile(`\\u([0-9a-fA-F]{4})`)
result := re.ReplaceAllStringFunc(s, func(match string) string {
// 提取十六进制数字部分
hexStr := match[2:] // 去掉\u前缀
// 将十六进制转换为整数
if codePoint, err := strconv.ParseInt(hexStr, 16, 32); err == nil {
// 转换为Unicode字符
return string(rune(codePoint))
}
return match // 如果转换失败,返回原字符串
})
return result
}
// GenerateSignature 生成签名
func GenerateSignature(payload []byte, key string) string {
h := hmac.New(sha256.New, []byte(key))
h.Write(payload)
return hex.EncodeToString(h.Sum(nil))
}
// SendMessageCallback 发送消息回调
func SendMessageCallback(msg *wechat.AddMsg, uuid string) {
// 获取回调配置
config, err := GetMessageCallbackConfig(uuid)
if err != nil {
log.Errorf("获取回调配置失败 [UUID: %s]: %v", uuid, err)
return
}
if config == nil {
log.Debugf("[回调调试] 未找到回调配置 [UUID: %s]", uuid)
return
}
if !config.Enabled {
log.Debugf("[回调调试] 回调未启用 [UUID: %s]", uuid)
return
}
// 使用消息包装器包含UUID信息
msgWrapper := NewCallbackMessageWrapper(uuid, msg, "message")
jsonBytes, err := json.Marshal(msgWrapper)
if err != nil {
log.Errorf("Failed to marshal CallbackMessageWrapper: %v", err)
return
}
// 对JSON内容进行Unicode解码处理与 WebSocket 保持一致)
decodedJSON := decodeUnicodeEscapes(string(jsonBytes))
// 创建HTTP请求
req, err := http.NewRequest("POST", config.CallbackURL, bytes.NewBuffer([]byte(decodedJSON)))
if err != nil {
log.Errorf("Failed to create callback request: %v", err)
return
}
// 设置请求头
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Timestamp", fmt.Sprintf("%d", time.Now().Unix()))
// 发送请求
client := &http.Client{
Timeout: 5 * time.Second,
}
resp, err := client.Do(req)
if err != nil {
log.Errorf("Failed to send callback request: %v", err)
return
}
defer resp.Body.Close()
// 读取响应内容
_, err = ioutil.ReadAll(resp.Body)
if err != nil {
log.Errorf("Failed to read callback response: %v", err)
return
}
}
// TestMessageCallback 测试消息回调配置
func TestMessageCallback(config *table.MessageCallbackConfig) (bool, string) {
// 构造测试消息
testPayload := map[string]interface{}{
"uuid": config.UUID,
"type": "test",
"data": map[string]interface{}{
"message": "这是一条测试回调消息",
"timestamp": time.Now().Unix(),
},
}
jsonBytes, err := json.Marshal(testPayload)
if err != nil {
return false, fmt.Sprintf("序列化测试数据失败: %v", err)
}
// 创建HTTP请求
req, err := http.NewRequest("POST", config.CallbackURL, bytes.NewBuffer(jsonBytes))
if err != nil {
return false, fmt.Sprintf("创建请求失败: %v", err)
}
// 设置请求头
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Timestamp", fmt.Sprintf("%d", time.Now().Unix()))
req.Header.Set("X-Test", "true")
// 发送请求
client := &http.Client{
Timeout: 5 * time.Second,
}
resp, err := client.Do(req)
if err != nil {
return false, fmt.Sprintf("发送请求失败: %v", err)
}
defer resp.Body.Close()
// 读取响应
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return false, fmt.Sprintf("读取响应失败: %v", err)
}
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
log.Infof("✓ 测试回调成功 [UUID: %s] -> %s, 状态码: %d",
config.UUID, config.CallbackURL, resp.StatusCode)
return true, fmt.Sprintf("状态码: %d, 响应: %s", resp.StatusCode, string(body))
} else {
log.Warnf("✗ 测试回调失败 [UUID: %s] -> %s, 状态码: %d",
config.UUID, config.CallbackURL, resp.StatusCode)
return false, fmt.Sprintf("状态码: %d, 响应: %s", resp.StatusCode, string(body))
}
}