Browse Source

消息推送

baishaojie 4 tuần trước cách đây
mục cha
commit
c1ae6db783

+ 7 - 0
apiserver/model/http/message.go

@@ -66,3 +66,10 @@ func (m MessageTypeReq) Validate() (err error) {
 func (p MessageReq) Validate() error {
 	return nil
 }
+
+type Public struct {
+	ID      int    `gorm:"id"`
+	Wxid    string `gorm:"wxid"`
+	Context string `gorm:"context"`
+	Create  string `gorm:"create"`
+}

+ 1 - 1
apiserver/model/message.go

@@ -14,7 +14,7 @@ type Message struct {
 	BodyData   string    `gorm:"column:body_data" json:"body_data"  `
 	CreatedAt  time.Time `gorm:"column:created_at"`
 	UpdatedAt  time.Time `gorm:"column:updated_at"`
-	status     int       `gorm:"column:status"`
+	Status     int       `gorm:"column:status"`
 	PushCount  int       `gorm:"column:push_count"`
 	PushLimit  int       `gorm:"column:push_limit"`
 }

+ 14 - 0
apiserver/server/message.go

@@ -49,3 +49,17 @@ func getMsgType(c *gin.Context) {
 	eJSON(c, res, err)
 
 }
+
+func handleMessage(c *gin.Context) {
+	responseXML := svc.HandleMessage(c)
+	c.Data(200, "application/xml", responseXML)
+}
+
+func handleVerification(c *gin.Context) {
+	res, echostr := svc.HandleVerification(c)
+	if res {
+		c.String(200, echostr)
+	} else {
+		c.String(401, "Invalid signature")
+	}
+}

+ 29 - 0
apiserver/server/server.go

@@ -84,8 +84,37 @@ func route(e *gin.Engine) {
 	e.GET("/notice/msgtype", getMsgType)
 	// save notice type
 	e.POST("/notice/msgtype", postMsgType)
+
+	e.POST("/wechat", handleMessage)
+	e.GET("/wechat", handleVerification)
 }
 
+// // func main() {
+// // 	r := gin.Default()
+// // 	r.GET("/wechat", handleVerification)
+// // 	r.POST("/wechat", handleMessage)
+// // 	fmt.Println("Server started on :80")
+// // 	r.Run(":80")
+// // }
+
+// func (svc *Service) HandleVerification(c *gin.Context) {
+// 	signature := c.Query("signature")
+// 	timestamp := c.Query("timestamp")
+// 	nonce := c.Query("nonce")
+// 	echostr := c.Query("echostr")
+// 	fmt.Println(signature)
+// 	fmt.Println(timestamp)
+// 	fmt.Println(nonce)
+// 	fmt.Println(echostr)
+// 	if checkSignature(signature, timestamp, nonce) {
+// 		c.String(200, echostr)
+// 	} else {
+// 		c.String(401, "Invalid signature")
+// 	}
+// }
+
+// func (svc *Service) HandleMessage(c *gin.Context) {
+
 /*
 	http 响应
 */

+ 3 - 0
apiserver/service/job.go

@@ -14,6 +14,8 @@ import (
 
 func JobInit() {
 	c := cron.New()
+	// ReadMsgs()
+	// notice.SendMessage(nil)
 	c.AddFunc("30 * * * * *", ReadMsgs)
 	c.Start()
 }
@@ -37,6 +39,7 @@ func ReadMsgs() {
 }
 
 func SendMsg(val *model.Message) (err error) {
+	svc.UpdateMessageStatus(val.ID)
 	// if val.SysName != "tmrWatch_test" {
 	// 	return
 	// } else {

+ 183 - 0
apiserver/service/message.go

@@ -1,8 +1,15 @@
 package service
 
 import (
+	"crypto/sha1"
+	"encoding/xml"
+	"fmt"
+	"io/ioutil"
+	"sort"
+	"strings"
 	"time"
 
+	"github.com/gin-gonic/gin"
 	"github.com/pkg/errors"
 	"kpt.notice/apiserver/model"
 	"kpt.notice/apiserver/model/http"
@@ -48,6 +55,15 @@ func (svc *Service) UpdateMessage(msg *model.Message) (err error) {
 	return
 }
 
+func (svc *Service) UpdateMessageStatus(id int) (err error) {
+	err = svc.DB.Exec(` update message set status = -1 where id = ? `, id).Error
+	if err != nil {
+		log.Error(err)
+		return
+	}
+	return
+}
+
 func (svc *Service) QueryMsg() (msgs []model.Message, err error) {
 
 	sql := `select m.* from message m join message_type mt
@@ -124,6 +140,15 @@ func (svc *Service) InsertMessage(msg *http.MessageReq, body []byte) (resp *http
 		data[v] = msg.Content[i]
 	}
 	tmp["data"] = data
+
+	status := -1
+	for _, target := range targetList {
+		if target != "" {
+			status = 0
+			break
+		}
+	}
+
 	msgDb := model.Message{
 		SysName:    msg.SysName,
 		PastureID:  msg.PastureID,
@@ -133,6 +158,7 @@ func (svc *Service) InsertMessage(msg *http.MessageReq, body []byte) (resp *http
 		MsgContent: util.MarshalToString(tmp),
 		UpdatedAt:  time.Now(),
 		BodyData:   string(body),
+		Status:     status,
 	}
 
 	if err = svc.DB.Create(&msgDb).Error; err != nil {
@@ -217,3 +243,160 @@ func (svc *Service) QueryMsgType(req *http.MessageTypeReq) (m []http.MessageType
 	}
 	return
 }
+
+type WechatMessage struct {
+	ToUserName   string `xml:"ToUserName"`
+	FromUserName string `xml:"FromUserName"`
+	CreateTime   int64  `xml:"CreateTime"`
+	MsgType      string `xml:"MsgType"`
+	Content      string `xml:"Content"`
+}
+
+// type WechatTransferResponse struct {
+// 	XMLName      xml.Name `xml:"xml"`
+// 	ToUserName   string   `xml:"ToUserName"`
+// 	FromUserName string   `xml:"FromUserName"`
+// 	CreateTime   int64    `xml:"CreateTime"`
+// 	MsgType      string   `xml:"MsgType"`
+// 	// TransInfo    TransInfo `xml:"TransInfo"`
+// }
+
+type WechatResponse struct {
+	XMLName      xml.Name `xml:"xml"`
+	ToUserName   string   `xml:"ToUserName"`
+	FromUserName string   `xml:"FromUserName"`
+	CreateTime   int64    `xml:"CreateTime"`
+	MsgType      string   `xml:"MsgType"`
+	Content      string   `xml:"Content"`
+}
+
+// func main() {
+// 	r := gin.Default()
+// 	r.GET("/wechat", handleVerification)
+// 	r.POST("/wechat", handleMessage)
+// 	fmt.Println("Server started on :80")
+// 	r.Run(":80")
+// }
+
+func (svc *Service) HandleVerification(c *gin.Context) (bool, string) {
+	signature := c.Query("signature")
+	timestamp := c.Query("timestamp")
+	nonce := c.Query("nonce")
+	echostr := c.Query("echostr")
+	fmt.Println(signature)
+	fmt.Println(timestamp)
+	fmt.Println(nonce)
+	fmt.Println(echostr)
+
+	return checkSignature(signature, timestamp, nonce), echostr
+}
+
+func (svc *Service) HandleMessage(c *gin.Context) []byte {
+	body, _ := ioutil.ReadAll(c.Request.Body)
+	fmt.Println(string(body))
+	defer c.Request.Body.Close()
+
+	var msg WechatMessage
+	xml.Unmarshal(body, &msg)
+
+	var count int64
+	svc.DB.Table("public").Where("`create` between  DATE_SUB(NOW(), INTERVAL 10 MINUTE)  and NOW() ").Where(" wxid = ? ", msg.ToUserName).Count(&count)
+
+	p := new(http.Public)
+	p.Wxid = msg.ToUserName
+	p.Context = msg.Content
+	p.Create = time.Now().Format("2006-01-02 15:04:05")
+	svc.DB.Table("public").Create(p)
+
+	var content string
+	if count == 0 {
+		content = `您好!感谢您关注科湃腾!您哪个系统需要服务?
+<a href="weixin://bizmsgmenu?msgmenucontent=精准饲喂&msgmenuid=1">👉精准饲喂</a>
+<a href="weixin://bizmsgmenu?msgmenucontent=智能脖环&msgmenuid=1">👉智能脖环</a>
+<a href="weixin://bizmsgmenu?msgmenucontent=智能喷淋&msgmenuid=1">👉智能喷淋</a>
+<a href="weixin://bizmsgmenu?msgmenucontent=系统开发服务&msgmenuid=1">👉系统开发服务</a>
+<a href="weixin://bizmsgmenu?msgmenucontent=其他&msgmenuid=1">👉其他</a>
+专线: 021- 6630 1586`
+	} else if p.Context == "精准饲喂" || p.Context == "智能脖环" || p.Context == "智能喷淋" || p.Context == "系统开发服务" || p.Context == "其他" {
+
+		content = `您所属那个大区?
+<a href="weixin://bizmsgmenu?msgmenucontent=东北大区&msgmenuid=1">👉东北大区</a>
+<a href="weixin://bizmsgmenu?msgmenucontent=西北大区&msgmenuid=1">👉西北大区</a>
+<a href="weixin://bizmsgmenu?msgmenucontent=华北大区&msgmenuid=1">👉华北大区</a>
+<a href="weixin://bizmsgmenu?msgmenucontent=南方大区&msgmenuid=1">👉南方大区</a>`
+
+	} else if p.Context == "东北大区" || p.Context == "西北大区" || p.Context == "华北大区" || p.Context == "南方大区" {
+		content = `东北大区服务老师联系方式
+谭佳悦:18888309870
+喻旭超:13594927924
+您可通过电话进行咨询,若您现在不方便电话联系,可以留下您的联系方式,简单描述一下问题或者拍照,我们安排服务人员在4小时内联系您,请您留意电话接听,祝您生活愉快!`
+
+		// new(notice.MessageRequest)
+		// notice.SendMessage(nil)
+	} else {
+
+	}
+
+	response := WechatResponse{
+		ToUserName:   msg.FromUserName,
+		FromUserName: msg.ToUserName,
+		CreateTime:   time.Now().Unix(),
+		MsgType:      "text",
+		Content:      content,
+	}
+
+	responseXML, _ := xml.Marshal(response)
+	return responseXML
+}
+
+func checkSignature(signature, timestamp, nonce string) bool {
+	token := "e10adc3949ba59abbe56e057f20f883e"
+	tmpList := []string{token, timestamp, nonce}
+	sort.Strings(tmpList)
+	tmpStr := strings.Join(tmpList, "")
+	h := sha1.New()
+	h.Write([]byte(tmpStr))
+	digest := fmt.Sprintf("%x", h.Sum(nil))
+	return digest == signature
+}
+
+type Message struct {
+	ToUser  string `json:"touser"`
+	MsgType string `json:"msgtype"`
+	Text    struct {
+		Content string `json:"content"`
+	} `json:"text"`
+}
+
+// func sendCustomMessage(accessToken, openID, content string) error {
+// 	url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s", accessToken)
+
+// 	message := Message{
+// 		ToUser:  openID,
+// 		MsgType: "text",
+// 		Text: struct {
+// 			Content string `json:"content"`
+// 		}{
+// 			Content: content,
+// 		},
+// 	}
+
+// 	payload, err := json.Marshal(message)
+// 	if err != nil {
+// 		return err
+// 	}
+
+// 	resp, err := http1.Post(url, "application/json", bytes.NewBuffer(payload))
+// 	if err != nil {
+// 		return err
+// 	}
+// 	defer resp.Body.Close()
+
+// 	var result map[string]interface{}
+// 	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
+// 		return err
+// 	}
+
+// 	fmt.Println("Response:", result)
+// 	return nil
+// }

BIN
cmd/apiserver/notice


+ 84 - 10
middleware/notice/wxoffice.go

@@ -1,12 +1,16 @@
 package notice
 
 import (
+	"encoding/json"
 	"fmt"
+	"io/ioutil"
+	"net/http"
 
 	"github.com/fastwego/offiaccount"
 	"kpt.notice/pkg/log"
 
 	"github.com/fastwego/offiaccount/apis/account"
+	"github.com/fastwego/offiaccount/apis/message/mass"
 	"github.com/fastwego/offiaccount/apis/message/template"
 	"github.com/pkg/errors"
 )
@@ -16,6 +20,28 @@ type wxMessage struct {
 	Content string `json:"content"`
 }
 
+type Groups struct {
+	Id   int    `json:"id"`
+	Name string `json:"name"`
+	// Count int `json:"count"`
+}
+
+type Filter struct {
+	IsToAll bool   `json:"is_to_all"`
+	GroupID string `json:"group_id"`
+}
+
+type Text struct {
+	Content string `json:"content"`
+}
+
+type MessageRequest struct {
+	Filter    *Filter `json:"filter"`
+	Text      *Text   `json:"text"`
+	MsgType   string  `json:"msgtype"`
+	GroupName string
+}
+
 var ServerAcc *offiaccount.OffiAccount = offiaccount.New(offiaccount.Config{
 	Appid:          "wxe1cc563ba393dd1a",
 	Secret:         "25e56243da9581eab6f4d67a12ef4658",
@@ -53,16 +79,64 @@ func MsgTemplate(msg []byte) (resp []byte, err error) {
 	}
 	fmt.Println(string(resp))
 	log.Info("notice.MsgTemplate{resp ==> ", string(resp))
+	// *offiaccount.OffiAccount
+	// customservice.SendMessage()
+	return
+}
+
+func SendMessage(msgData MessageRequest) (resp []byte, err error) {
+	token, _ := ServerAcc.Client.Ctx.AccessToken.GetAccessTokenHandler(ServerAcc.Client.Ctx)
+	groups := getGroups(token)
+	fmt.Println(groups)
+	var groupId string
+	for _, g := range groups {
+		if g.Name == msgData.GroupName {
+			groupId = fmt.Sprintf("%d", g.Id)
+			break
+		}
+	}
+
+	filter := new(Filter)
+	filter.GroupID = groupId
+	filter.IsToAll = false
+
+	msgData.Filter = filter
+	data, _ := json.Marshal(msgData)
+	fmt.Println(string(data))
+	_, err = mass.SendAll(ServerAcc, []byte(data))
 	return
 }
 
-// func OfficeInit() {
-// 	if ServerAcc == nil {
-// 		ServerAcc = offiaccount.New(offiaccount.Config{
-// 			Appid:          "wxe1cc563ba393dd1a",
-// 			Secret:         "25e56243da9581eab6f4d67a12ef4658",
-// 			Token:          "123",
-// 			EncodingAESKey: "6yYJ4sS5y1hJgvIXEqavV2rmCutyXkywndxUQFgX54f",
-// 		})
-// 	}
-// }
+func getGroups(accessToken string) []*Groups {
+
+	req, err := http.NewRequest("GET", fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/groups/get?access_token=%s", accessToken), nil)
+	if err != nil {
+		// logs.Error(err)
+		return nil
+	}
+
+	req.Header.Set("Content-Type", "application/json")
+	client := &http.Client{}
+	resp, err := client.Do(req)
+	if err != nil {
+		// logs.Error(err)
+		return nil
+	}
+	defer resp.Body.Close()
+
+	body, _ := ioutil.ReadAll(resp.Body)
+	fmt.Println(string(body))
+	groupMap := make(map[string][]*Groups)
+	json.Unmarshal(body, &groupMap)
+	if _, ok := groupMap["groups"]; ok {
+		return groupMap["groups"]
+	}
+	return nil
+}
+
+var ServerAcc1 *offiaccount.OffiAccount = offiaccount.New(offiaccount.Config{
+	Appid:          "wx076cd0ea116abe78",
+	Secret:         "25e56243da9581eab6f4d67a12ef4658",
+	Token:          "e10adc3949ba59abbe56e057f20f883e",
+	EncodingAESKey: "cMjk2jEKw1HNlrH7jsjVzyYEF7785Dc8SEIqXREP5iW",
+})