Skip to content

Commit

Permalink
微信小程序回调消息兼容json格式 (#560)
Browse files Browse the repository at this point in the history
  • Loading branch information
mxyue authored Apr 26, 2022
1 parent 4b972c7 commit e952b1d
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 17 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cast v1.4.1
github.com/stretchr/testify v1.7.1
github.com/tidwall/gjson v1.14.1
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
gopkg.in/h2non/gock.v1 v1.1.2
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo=
github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
Expand Down
35 changes: 27 additions & 8 deletions officialaccount/message/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ type MixMessage struct {
URL string `xml:"Url"`

// 事件相关
Event EventType `xml:"Event"`
Event EventType `xml:"Event" json:"Event"`
EventKey string `xml:"EventKey"`
Ticket string `xml:"Ticket"`
Latitude string `xml:"Latitude"`
Expand Down Expand Up @@ -149,6 +149,8 @@ type MixMessage struct {
Poiname string `xml:"Poiname"`
}

subscribeMsgPopupEventList []SubscribeMsgPopupEvent `json:"-"`

SubscribeMsgPopupEvent []struct {
List SubscribeMsgPopupEvent `xml:"List"`
} `xml:"SubscribeMsgPopupEvent"`
Expand Down Expand Up @@ -209,9 +211,26 @@ type MixMessage struct {

// SubscribeMsgPopupEvent 订阅通知事件推送的消息体
type SubscribeMsgPopupEvent struct {
TemplateID string `xml:"TemplateId"`
SubscribeStatusString string `xml:"SubscribeStatusString"`
PopupScene int `xml:"PopupScene"`
TemplateID string `xml:"TemplateId" json:"TemplateId"`
SubscribeStatusString string `xml:"SubscribeStatusString" json:"SubscribeStatusString"`
PopupScene int `xml:"PopupScene" json:"PopupScene,string"`
}

// SetSubscribeMsgPopupEvents 设置订阅消息事件
func (s *MixMessage) SetSubscribeMsgPopupEvents(list []SubscribeMsgPopupEvent) {
s.subscribeMsgPopupEventList = list
}

// GetSubscribeMsgPopupEvents 获取订阅消息事件数据
func (s *MixMessage) GetSubscribeMsgPopupEvents() []SubscribeMsgPopupEvent {
if s.subscribeMsgPopupEventList != nil {
return s.subscribeMsgPopupEventList
}
list := make([]SubscribeMsgPopupEvent, len(s.SubscribeMsgPopupEvent))
for i, item := range s.SubscribeMsgPopupEvent {
list[i] = item.List
}
return list
}

// EventPic 发图事件推送
Expand Down Expand Up @@ -248,10 +267,10 @@ func (c CDATA) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
// CommonToken 消息中通用的结构
type CommonToken struct {
XMLName xml.Name `xml:"xml"`
ToUserName CDATA `xml:"ToUserName"`
FromUserName CDATA `xml:"FromUserName"`
CreateTime int64 `xml:"CreateTime"`
MsgType MsgType `xml:"MsgType"`
ToUserName CDATA `xml:"ToUserName" json:"ToUserName"`
FromUserName CDATA `xml:"FromUserName" json:"FromUserName"`
CreateTime int64 `xml:"CreateTime" json:"CreateTime"`
MsgType MsgType `xml:"MsgType" json:"MsgType"`
}

// SetToUserName set ToUserName
Expand Down
64 changes: 55 additions & 9 deletions officialaccount/server/server.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package server

import (
"encoding/json"
"encoding/xml"
"errors"
"fmt"
Expand All @@ -9,13 +10,14 @@ import (
"reflect"
"runtime/debug"
"strconv"
"strings"

log "github.com/sirupsen/logrus"

"github.com/silenceper/wechat/v2/officialaccount/context"
"github.com/silenceper/wechat/v2/officialaccount/message"

"github.com/silenceper/wechat/v2/util"
"github.com/tidwall/gjson"
)

// Server struct
Expand All @@ -35,10 +37,11 @@ type Server struct {
ResponseRawXMLMsg []byte
ResponseMsg interface{}

isSafeMode bool
random []byte
nonce string
timestamp int64
isSafeMode bool
isJSONContent bool
random []byte
nonce string
timestamp int64
}

// NewServer init
Expand Down Expand Up @@ -98,6 +101,10 @@ func (srv *Server) handleRequest() (reply *message.Reply, err error) {
srv.isSafeMode = true
}

//set request contentType
contentType := srv.Request.Header.Get("Content-Type")
srv.isJSONContent = strings.Contains(contentType, "application/json")

// set openID
srv.openID = srv.Query("openid")

Expand Down Expand Up @@ -125,9 +132,9 @@ func (srv *Server) getMessage() (interface{}, error) {
var rawXMLMsgBytes []byte
var err error
if srv.isSafeMode {
var encryptedXMLMsg message.EncryptedXMLMsg
if err := xml.NewDecoder(srv.Request.Body).Decode(&encryptedXMLMsg); err != nil {
return nil, fmt.Errorf("从body中解析xml失败,err=%v", err)
encryptedXMLMsg, dataErr := srv.getEncryptBody()
if dataErr != nil {
return nil, dataErr
}

// 验证消息签名
Expand Down Expand Up @@ -161,9 +168,48 @@ func (srv *Server) getMessage() (interface{}, error) {
return srv.parseRequestMessage(rawXMLMsgBytes)
}

func (srv *Server) getEncryptBody() (*message.EncryptedXMLMsg, error) {
var encryptedXMLMsg = &message.EncryptedXMLMsg{}
if srv.isJSONContent {
if err := json.NewDecoder(srv.Request.Body).Decode(encryptedXMLMsg); err != nil {
return nil, fmt.Errorf("从body中解析json失败,err=%v", err)
}
} else {
if err := xml.NewDecoder(srv.Request.Body).Decode(encryptedXMLMsg); err != nil {
return nil, fmt.Errorf("从body中解析xml失败,err=%v", err)
}
}
return encryptedXMLMsg, nil
}

func (srv *Server) parseRequestMessage(rawXMLMsgBytes []byte) (msg *message.MixMessage, err error) {
msg = &message.MixMessage{}
err = xml.Unmarshal(rawXMLMsgBytes, msg)
if !srv.isJSONContent {
err = xml.Unmarshal(rawXMLMsgBytes, msg)
return
}
//parse json
err = json.Unmarshal(rawXMLMsgBytes, msg)
if err != nil {
return
}
// nonstandard json, 目前小程序订阅消息返回数据格式不标准,订阅消息模板单个List返回是对象,多个List返回是数组。
if msg.MsgType == message.MsgTypeEvent {
listData := gjson.Get(string(rawXMLMsgBytes), "List")
if listData.IsObject() {
listItem := message.SubscribeMsgPopupEvent{}
if parseErr := json.Unmarshal([]byte(listData.Raw), &listItem); parseErr != nil {
return msg, parseErr
}
msg.SetSubscribeMsgPopupEvents([]message.SubscribeMsgPopupEvent{listItem})
} else if listData.IsArray() {
listItems := make([]message.SubscribeMsgPopupEvent, 0)
if parseErr := json.Unmarshal([]byte(listData.Raw), &listItems); parseErr != nil {
return msg, parseErr
}
msg.SetSubscribeMsgPopupEvents(listItems)
}
}
return
}

Expand Down

0 comments on commit e952b1d

Please sign in to comment.