mirror of
https://github.com/silenceper/wechat.git
synced 2026-02-04 12:52:27 +08:00
微信小程序回调消息兼容json格式 (#560)
This commit is contained in:
1
go.mod
1
go.mod
@@ -9,6 +9,7 @@ require (
|
|||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/spf13/cast v1.4.1
|
github.com/spf13/cast v1.4.1
|
||||||
github.com/stretchr/testify v1.7.1
|
github.com/stretchr/testify v1.7.1
|
||||||
|
github.com/tidwall/gjson v1.14.1
|
||||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
|
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
|
||||||
gopkg.in/h2non/gock.v1 v1.1.2
|
gopkg.in/h2non/gock.v1 v1.1.2
|
||||||
)
|
)
|
||||||
|
|||||||
6
go.sum
6
go.sum
@@ -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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
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=
|
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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ type MixMessage struct {
|
|||||||
URL string `xml:"Url"`
|
URL string `xml:"Url"`
|
||||||
|
|
||||||
// 事件相关
|
// 事件相关
|
||||||
Event EventType `xml:"Event"`
|
Event EventType `xml:"Event" json:"Event"`
|
||||||
EventKey string `xml:"EventKey"`
|
EventKey string `xml:"EventKey"`
|
||||||
Ticket string `xml:"Ticket"`
|
Ticket string `xml:"Ticket"`
|
||||||
Latitude string `xml:"Latitude"`
|
Latitude string `xml:"Latitude"`
|
||||||
@@ -149,6 +149,8 @@ type MixMessage struct {
|
|||||||
Poiname string `xml:"Poiname"`
|
Poiname string `xml:"Poiname"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subscribeMsgPopupEventList []SubscribeMsgPopupEvent `json:"-"`
|
||||||
|
|
||||||
SubscribeMsgPopupEvent []struct {
|
SubscribeMsgPopupEvent []struct {
|
||||||
List SubscribeMsgPopupEvent `xml:"List"`
|
List SubscribeMsgPopupEvent `xml:"List"`
|
||||||
} `xml:"SubscribeMsgPopupEvent"`
|
} `xml:"SubscribeMsgPopupEvent"`
|
||||||
@@ -209,9 +211,26 @@ type MixMessage struct {
|
|||||||
|
|
||||||
// SubscribeMsgPopupEvent 订阅通知事件推送的消息体
|
// SubscribeMsgPopupEvent 订阅通知事件推送的消息体
|
||||||
type SubscribeMsgPopupEvent struct {
|
type SubscribeMsgPopupEvent struct {
|
||||||
TemplateID string `xml:"TemplateId"`
|
TemplateID string `xml:"TemplateId" json:"TemplateId"`
|
||||||
SubscribeStatusString string `xml:"SubscribeStatusString"`
|
SubscribeStatusString string `xml:"SubscribeStatusString" json:"SubscribeStatusString"`
|
||||||
PopupScene int `xml:"PopupScene"`
|
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 发图事件推送
|
// EventPic 发图事件推送
|
||||||
@@ -248,10 +267,10 @@ func (c CDATA) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
|||||||
// CommonToken 消息中通用的结构
|
// CommonToken 消息中通用的结构
|
||||||
type CommonToken struct {
|
type CommonToken struct {
|
||||||
XMLName xml.Name `xml:"xml"`
|
XMLName xml.Name `xml:"xml"`
|
||||||
ToUserName CDATA `xml:"ToUserName"`
|
ToUserName CDATA `xml:"ToUserName" json:"ToUserName"`
|
||||||
FromUserName CDATA `xml:"FromUserName"`
|
FromUserName CDATA `xml:"FromUserName" json:"FromUserName"`
|
||||||
CreateTime int64 `xml:"CreateTime"`
|
CreateTime int64 `xml:"CreateTime" json:"CreateTime"`
|
||||||
MsgType MsgType `xml:"MsgType"`
|
MsgType MsgType `xml:"MsgType" json:"MsgType"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetToUserName set ToUserName
|
// SetToUserName set ToUserName
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -9,13 +10,14 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/silenceper/wechat/v2/officialaccount/context"
|
"github.com/silenceper/wechat/v2/officialaccount/context"
|
||||||
"github.com/silenceper/wechat/v2/officialaccount/message"
|
"github.com/silenceper/wechat/v2/officialaccount/message"
|
||||||
|
|
||||||
"github.com/silenceper/wechat/v2/util"
|
"github.com/silenceper/wechat/v2/util"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Server struct
|
// Server struct
|
||||||
@@ -35,10 +37,11 @@ type Server struct {
|
|||||||
ResponseRawXMLMsg []byte
|
ResponseRawXMLMsg []byte
|
||||||
ResponseMsg interface{}
|
ResponseMsg interface{}
|
||||||
|
|
||||||
isSafeMode bool
|
isSafeMode bool
|
||||||
random []byte
|
isJSONContent bool
|
||||||
nonce string
|
random []byte
|
||||||
timestamp int64
|
nonce string
|
||||||
|
timestamp int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer init
|
// NewServer init
|
||||||
@@ -98,6 +101,10 @@ func (srv *Server) handleRequest() (reply *message.Reply, err error) {
|
|||||||
srv.isSafeMode = true
|
srv.isSafeMode = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//set request contentType
|
||||||
|
contentType := srv.Request.Header.Get("Content-Type")
|
||||||
|
srv.isJSONContent = strings.Contains(contentType, "application/json")
|
||||||
|
|
||||||
// set openID
|
// set openID
|
||||||
srv.openID = srv.Query("openid")
|
srv.openID = srv.Query("openid")
|
||||||
|
|
||||||
@@ -125,9 +132,9 @@ func (srv *Server) getMessage() (interface{}, error) {
|
|||||||
var rawXMLMsgBytes []byte
|
var rawXMLMsgBytes []byte
|
||||||
var err error
|
var err error
|
||||||
if srv.isSafeMode {
|
if srv.isSafeMode {
|
||||||
var encryptedXMLMsg message.EncryptedXMLMsg
|
encryptedXMLMsg, dataErr := srv.getEncryptBody()
|
||||||
if err := xml.NewDecoder(srv.Request.Body).Decode(&encryptedXMLMsg); err != nil {
|
if dataErr != nil {
|
||||||
return nil, fmt.Errorf("从body中解析xml失败,err=%v", err)
|
return nil, dataErr
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证消息签名
|
// 验证消息签名
|
||||||
@@ -161,9 +168,48 @@ func (srv *Server) getMessage() (interface{}, error) {
|
|||||||
return srv.parseRequestMessage(rawXMLMsgBytes)
|
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) {
|
func (srv *Server) parseRequestMessage(rawXMLMsgBytes []byte) (msg *message.MixMessage, err error) {
|
||||||
msg = &message.MixMessage{}
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user