From 900a54ee065db952bb22c2ae5686773ebf8b80dd Mon Sep 17 00:00:00 2001 From: Chuanjian Wang Date: Tue, 15 Oct 2019 10:44:54 +0800 Subject: [PATCH 01/15] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E6=B0=B8=E4=B9=85=E7=B4=A0=E6=9D=90=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- material/material.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/material/material.go b/material/material.go index f4f1dfb..b7fdc32 100644 --- a/material/material.go +++ b/material/material.go @@ -13,6 +13,7 @@ const ( addNewsURL = "https://api.weixin.qq.com/cgi-bin/material/add_news" addMaterialURL = "https://api.weixin.qq.com/cgi-bin/material/add_material" delMaterialURL = "https://api.weixin.qq.com/cgi-bin/material/del_material" + getMaterialURL = "https://api.weixin.qq.com/cgi-bin/material/get_material" ) //Material 素材管理 @@ -36,6 +37,33 @@ type Article struct { ShowCoverPic int `json:"show_cover_pic"` Content string `json:"content"` ContentSourceURL string `json:"content_source_url"` + URL string `json:"url"` + DownURL string `json:"down_url"` +} + +// GetNews 获取/下载永久素材 +func (material *Material) GetNews(id string) ([]*Article, error) { + accessToken, err := material.GetAccessToken() + if err != nil { + return nil, err + } + uri := fmt.Sprintf("%s?access_token=%s", getMaterialURL, accessToken) + + var req struct { + MediaID string `json:"media_id"` + } + req.MediaID = id + responseBytes, err := util.PostJSON(uri, req) + + var res struct { + NewsItem []*Article `json:"news_item"` + } + err = json.Unmarshal(responseBytes, &res) + if err != nil { + return nil, err + } + + return res.NewsItem, nil } //reqArticles 永久性图文素材请求信息 From e09031b58cd3693f5e1071b979d8eea37dc4a684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E7=81=BF=E9=91=AB?= Date: Fri, 1 Nov 2019 23:21:25 +0800 Subject: [PATCH 02/15] =?UTF-8?q?fix:=20=E5=BA=8F=E5=88=97=E5=8C=96=20xml?= =?UTF-8?q?=20=E6=97=B6=E6=B7=BB=E5=8A=A0=20cdata=20=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- message/message.go | 24 ++++++++++++++++-------- message/text.go | 4 ++-- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/message/message.go b/message/message.go index 8c7ae2a..4e9b6d2 100644 --- a/message/message.go +++ b/message/message.go @@ -148,10 +148,10 @@ type MixMessage struct { UnionID string `xml:"UnionId"` // 内容审核相关 - IsRisky bool `xml:"isrisky"` - ExtraInfoJSON string `xml:"extra_info_json"` - TraceID string `xml:"trace_id"` - StatusCode int `xml:"status_code"` + IsRisky bool `xml:"isrisky"` + ExtraInfoJSON string `xml:"extra_info_json"` + TraceID string `xml:"trace_id"` + StatusCode int `xml:"status_code"` } //EventPic 发图事件推送 @@ -178,20 +178,28 @@ type ResponseEncryptedXMLMsg struct { // CommonToken 消息中通用的结构 type CommonToken struct { XMLName xml.Name `xml:"xml"` - ToUserName string `xml:"ToUserName"` - FromUserName string `xml:"FromUserName"` + ToUserName CDATA `xml:"ToUserName"` + FromUserName CDATA `xml:"FromUserName"` CreateTime int64 `xml:"CreateTime"` MsgType MsgType `xml:"MsgType"` } +type CDATA string + +func (c CDATA) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + return e.EncodeElement(struct { + string `xml:",cdata"` + }{string(c)}, start) +} + //SetToUserName set ToUserName func (msg *CommonToken) SetToUserName(toUserName string) { - msg.ToUserName = toUserName + msg.ToUserName = CDATA(toUserName) } //SetFromUserName set FromUserName func (msg *CommonToken) SetFromUserName(fromUserName string) { - msg.FromUserName = fromUserName + msg.FromUserName = CDATA(fromUserName) } //SetCreateTime set createTime diff --git a/message/text.go b/message/text.go index d981d96..88ac19a 100644 --- a/message/text.go +++ b/message/text.go @@ -3,12 +3,12 @@ package message //Text 文本消息 type Text struct { CommonToken - Content string `xml:"Content"` + Content CDATA `xml:"Content"` } //NewText 初始化文本消息 func NewText(content string) *Text { text := new(Text) - text.Content = content + text.Content = CDATA(content) return text } From bf456aa77b3e39b126bc96ace3daba026696da6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E7=81=BF=E9=91=AB?= Date: Fri, 8 Nov 2019 10:24:47 +0800 Subject: [PATCH 03/15] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=20CDATA=20?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- message/message.go | 1 + 1 file changed, 1 insertion(+) diff --git a/message/message.go b/message/message.go index 4e9b6d2..a0b47a4 100644 --- a/message/message.go +++ b/message/message.go @@ -184,6 +184,7 @@ type CommonToken struct { MsgType MsgType `xml:"MsgType"` } +// CDATA 使用该类型,在序列化为 xml 文本时文本会被解析器忽略 type CDATA string func (c CDATA) MarshalXML(e *xml.Encoder, start xml.StartElement) error { From 1475417a648ca370d2ed3693264eabb60b011937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E7=81=BF=E9=91=AB?= Date: Fri, 8 Nov 2019 11:05:56 +0800 Subject: [PATCH 04/15] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=20CDATA.Marshal?= =?UTF-8?q?XML=20=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- message/message.go | 1 + 1 file changed, 1 insertion(+) diff --git a/message/message.go b/message/message.go index a0b47a4..cd4d4f9 100644 --- a/message/message.go +++ b/message/message.go @@ -187,6 +187,7 @@ type CommonToken struct { // CDATA 使用该类型,在序列化为 xml 文本时文本会被解析器忽略 type CDATA string +// MarshalXML 实现自己的序列化方法 func (c CDATA) MarshalXML(e *xml.Encoder, start xml.StartElement) error { return e.EncodeElement(struct { string `xml:",cdata"` From f6d07aa714048acd5e6371e69eecf816a412a66d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E7=81=BF=E9=91=AB?= Date: Fri, 8 Nov 2019 11:17:11 +0800 Subject: [PATCH 05/15] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20CDATA.Marshal?= =?UTF-8?q?XML=20=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- message/message.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/message/message.go b/message/message.go index cd4d4f9..11f1535 100644 --- a/message/message.go +++ b/message/message.go @@ -187,7 +187,7 @@ type CommonToken struct { // CDATA 使用该类型,在序列化为 xml 文本时文本会被解析器忽略 type CDATA string -// MarshalXML 实现自己的序列化方法 +// MarshalXML 实现自己的序列化方法 func (c CDATA) MarshalXML(e *xml.Encoder, start xml.StartElement) error { return e.EncodeElement(struct { string `xml:",cdata"` From c30319c74ca4042f8d322cb71830426fcb2f6ae1 Mon Sep 17 00:00:00 2001 From: silenceper Date: Tue, 12 Nov 2019 15:05:07 +0800 Subject: [PATCH 06/15] =?UTF-8?q?Revert=20"fix:=20=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=8C=96=20xml=20=E6=97=B6=E6=B7=BB=E5=8A=A0=20cdata=20?= =?UTF-8?q?=E6=A0=87=E7=AD=BE"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- message/message.go | 26 ++++++++------------------ message/text.go | 4 ++-- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/message/message.go b/message/message.go index 11f1535..8c7ae2a 100644 --- a/message/message.go +++ b/message/message.go @@ -148,10 +148,10 @@ type MixMessage struct { UnionID string `xml:"UnionId"` // 内容审核相关 - IsRisky bool `xml:"isrisky"` - ExtraInfoJSON string `xml:"extra_info_json"` - TraceID string `xml:"trace_id"` - StatusCode int `xml:"status_code"` + IsRisky bool `xml:"isrisky"` + ExtraInfoJSON string `xml:"extra_info_json"` + TraceID string `xml:"trace_id"` + StatusCode int `xml:"status_code"` } //EventPic 发图事件推送 @@ -178,30 +178,20 @@ type ResponseEncryptedXMLMsg struct { // CommonToken 消息中通用的结构 type CommonToken struct { XMLName xml.Name `xml:"xml"` - ToUserName CDATA `xml:"ToUserName"` - FromUserName CDATA `xml:"FromUserName"` + ToUserName string `xml:"ToUserName"` + FromUserName string `xml:"FromUserName"` CreateTime int64 `xml:"CreateTime"` MsgType MsgType `xml:"MsgType"` } -// CDATA 使用该类型,在序列化为 xml 文本时文本会被解析器忽略 -type CDATA string - -// MarshalXML 实现自己的序列化方法 -func (c CDATA) MarshalXML(e *xml.Encoder, start xml.StartElement) error { - return e.EncodeElement(struct { - string `xml:",cdata"` - }{string(c)}, start) -} - //SetToUserName set ToUserName func (msg *CommonToken) SetToUserName(toUserName string) { - msg.ToUserName = CDATA(toUserName) + msg.ToUserName = toUserName } //SetFromUserName set FromUserName func (msg *CommonToken) SetFromUserName(fromUserName string) { - msg.FromUserName = CDATA(fromUserName) + msg.FromUserName = fromUserName } //SetCreateTime set createTime diff --git a/message/text.go b/message/text.go index 88ac19a..d981d96 100644 --- a/message/text.go +++ b/message/text.go @@ -3,12 +3,12 @@ package message //Text 文本消息 type Text struct { CommonToken - Content CDATA `xml:"Content"` + Content string `xml:"Content"` } //NewText 初始化文本消息 func NewText(content string) *Text { text := new(Text) - text.Content = CDATA(content) + text.Content = content return text } From 5b307df9695270ab0e12a4eb07e610708a785a08 Mon Sep 17 00:00:00 2001 From: "larry.liu" Date: Thu, 14 Nov 2019 19:30:33 +0800 Subject: [PATCH 07/15] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E7=AE=A1=E7=90=86=201.=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E6=8E=88=E6=9D=83=E6=96=B9=E6=B3=95=202.=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E4=BA=8C=E7=BB=B4=E7=A0=81=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- device/definitions.go | 95 +++++++++++++++++++++++++++++++++++++++++++ device/device.go | 87 +++++++++++++++++++++++++++++++++++++++ wechat.go | 6 +++ 3 files changed, 188 insertions(+) create mode 100644 device/definitions.go create mode 100644 device/device.go diff --git a/device/definitions.go b/device/definitions.go new file mode 100644 index 0000000..2bc1072 --- /dev/null +++ b/device/definitions.go @@ -0,0 +1,95 @@ +package device + +import "github.com/silenceper/wechat/util" + +const ( + //添加设备标识 + DEVICE_ADD = iota + //更新设备标识 + DEVCIE_UPGRADE +) +const ( + //android classic bluetooth + PROTOCOL_ANDROID_BLE = iota + //ios classic bluetooth + PROTOCOL_IOS_BLE + PROTOCOL_BLE + PROTOCOL_WIFI +) + +type reqDeviceAuthorize struct { + // 设备id的个数 + DeviceNum string `json:"device_num"` + // 设备id的列表,json的array格式,其size必须等于device_num + DeviceList []ReqDevice `json:"device_list"` + // 请求操作的类型,限定取值为:0:设备授权(缺省值为0) 1:设备更新(更新已授权设备的各属性值) + OpType string `json:"op_type,omitempty"` + // 设备的产品编号(由微信硬件平台分配)。可在公众号设备功能管理页面查询。 + //当 op_type 为‘0’,product_id 为‘1’时,不要填写 product_id 字段(会引起不必要错误); + //当 op_typy 为‘0’,product_id 不为‘1’时,必须填写 product_id 字段; + //当 op_type 为 1 时,不要填写 product_id 字段。 + ProductId string `json:"product_id,omitempty"` +} + +type ReqDevice struct { + // 设备的 device id + Id string `json:"id"` + // 设备的mac地址 格式采用16进制串的方式(长度为12字节), + // 不需要0X前缀,如: 1234567890AB + Mac string `json:"mac"` + // 支持以下四种连接协议: + // android classic bluetooth – 1 + // ios classic bluetooth – 2 + // ble – 3 + // wifi -- 4 + // 一个设备可以支持多种连接类型,用符号"|"做分割,客户端优先选择靠前的连接方式(优先级按|关系的排序依次降低),举例: + // 1:表示设备仅支持andiod classic bluetooth 1|2:表示设备支持andiod 和ios 两种classic bluetooth,但是客户端优先选择andriod classic bluetooth 协议,如果andriod classic bluetooth协议连接失败,再选择ios classic bluetooth协议进行连接 + // (注:安卓平台不同时支持BLE和classic类型) + ConnectProtocol string `json:"connect_protocol"` + //auth及通信的加密key,第三方需要将key烧制在设备上(128bit),格式采用16进制串的方式(长度为32字节),不需要0X前缀,如: 1234567890ABCDEF1234567890ABCDEF + AuthKey string `json:"auth_key"` + // 断开策略,目前支持: 1:退出公众号页面时即断开连接 2:退出公众号之后保持连接不断开 + CloseStrategy string `json:"close_strategy"` + //连接策略,32位整型,按bit位置位,目前仅第1bit和第3bit位有效(bit置0为无效,1为有效;第2bit已被废弃),且bit位可以按或置位(如1|4=5),各bit置位含义说明如下: + //1:(第1bit置位)在公众号对话页面,不停的尝试连接设备 + //4:(第3bit置位)处于非公众号页面(如主界面等),微信自动连接。当用户切换微信到前台时,可能尝试去连接设备,连上后一定时间会断开 + ConnStrategy string `json:"conn_strategy"` + // auth version,设备和微信进行auth时,会根据该版本号来确认auth buf和auth key的格式(各version对应的auth buf及key的具体格式可以参看“客户端蓝牙外设协议”),该字段目前支持取值: + // 0:不加密的version + // 1:version 1 + AuthVer string `json:"auth_ver"` + // 表示mac地址在厂商广播manufature data里含有mac地址的偏移,取值如下: + // -1:在尾部、 + // -2:表示不包含mac地址 其他:非法偏移 + ManuMacPos string `json:"manu_mac_pos"` + // 表示mac地址在厂商serial number里含有mac地址的偏移,取值如下: + // -1:表示在尾部 + // -2:表示不包含mac地址 其他:非法偏移 + SerMacPost string `json:"ser_mac_post"` + // 精简协议类型,取值如下:计步设备精简协议:1 (若该字段填1,connect_protocol 必须包括3。非精简协议设备切勿填写该字段) + BleSimpleProtocol string `json:"ble_simple_protocol,omitempty"` +} + +// 授权回调实体 +type resBaseInfo struct { + BaseInfo struct { + DeviceType string `json:"device_type"` + DeviceId string `json:"device_id"` + } `json:"base_info"` +} + +// 授权回调根信息 +type ResDeviceAuthorize struct { + util.CommonError + Resp []resBaseInfo `json:"resp"` +} + +type ResCreateQRCode struct { + util.CommonError + DeviceNum int `json:"device_num"` + CodeList []resQRCode `json:"code_list"` +} +type resQRCode struct { + DeviceId string `json:"device_id"` + Ticket string `json:"ticket"` +} diff --git a/device/device.go b/device/device.go new file mode 100644 index 0000000..91750b9 --- /dev/null +++ b/device/device.go @@ -0,0 +1,87 @@ +package device + +import ( + "encoding/json" + "fmt" + "github.com/silenceper/wechat/context" + "github.com/silenceper/wechat/util" +) + +const ( + deviceAuthorize = "https://api.weixin.qq.com/device/authorize_device" + deviceQRCode = "https://api.weixin.qq.com/device/create_qrcode" +) + +//Device struct +type Device struct { + *context.Context +} + +//NewDevice 实例 +func NewDevice(context *context.Context) *Device { + device := new(Device) + device.Context = context + return device +} + +// DeviceAuthorize 设备授权 +func (d *Device) DeviceAuthorize(devices []ReqDevice, opType int, productId string) (res []resBaseInfo, err error) { + var accessToken string + accessToken, err = d.GetAccessToken() + if err != nil { + return nil, err + } + + uri := fmt.Sprintf("%s?access_token=%s", deviceAuthorize, accessToken) + req := reqDeviceAuthorize{ + DeviceNum: fmt.Sprintf("%d", len(devices)), + DeviceList: devices, + OpType: fmt.Sprintf("%d", opType), + ProductId: productId, + } + response, err := util.PostJSON(uri, req) + if err != nil { + return nil, err + } + var result ResDeviceAuthorize + err = json.Unmarshal(response, &result) + if err != nil { + return + } + if result.ErrCode != 0 { + err = fmt.Errorf("DeviceAuthorize Error , errcode=%d , errmsg=%s", result.ErrCode, result.ErrMsg) + return + } + res = result.Resp + return +} + +// CreateQRCode 获取设备二维码 +func (d *Device) CreateQRCode(devices []string) (res []resQRCode, err error) { + var accessToken string + accessToken, err = d.GetAccessToken() + if err != nil { + return nil, err + } + uri := fmt.Sprintf("%s?access_token=%s", deviceQRCode, accessToken) + req := map[string]interface{}{ + "device_num": len(devices), + "device_id_list": devices, + } + fmt.Println(req) + response, err := util.PostJSON(uri, req) + if err != nil { + return + } + var result ResCreateQRCode + err = json.Unmarshal(response, &result) + if err != nil { + return + } + if result.ErrCode != 0 { + err = fmt.Errorf("CreateQRCode Error , errcode=%d , errmsg=%s", result.ErrCode, result.ErrMsg) + return + } + res = result.CodeList + return +} diff --git a/wechat.go b/wechat.go index f49ece9..6bbd9e8 100644 --- a/wechat.go +++ b/wechat.go @@ -1,6 +1,7 @@ package wechat import ( + "github.com/silenceper/wechat/device" "net/http" "sync" @@ -111,3 +112,8 @@ func (wc *Wechat) GetQR() *qr.QR { func (wc *Wechat) GetMiniProgram() *miniprogram.MiniProgram { return miniprogram.NewMiniProgram(wc.Context) } + +// GetDevice 获取智能设备的实例 +func (wc *Wechat) GetDevice() *device.Device { + return device.NewDevice(wc.Context) +} From f4e58b07120d36c34540f07a0294b008c26852b5 Mon Sep 17 00:00:00 2001 From: "larry.liu" Date: Fri, 15 Nov 2019 08:05:53 +0800 Subject: [PATCH 08/15] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- device/definitions.go | 12 ++---------- device/device.go | 4 ++-- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/device/definitions.go b/device/definitions.go index 2bc1072..df24067 100644 --- a/device/definitions.go +++ b/device/definitions.go @@ -8,14 +8,6 @@ const ( //更新设备标识 DEVCIE_UPGRADE ) -const ( - //android classic bluetooth - PROTOCOL_ANDROID_BLE = iota - //ios classic bluetooth - PROTOCOL_IOS_BLE - PROTOCOL_BLE - PROTOCOL_WIFI -) type reqDeviceAuthorize struct { // 设备id的个数 @@ -79,12 +71,12 @@ type resBaseInfo struct { } // 授权回调根信息 -type ResDeviceAuthorize struct { +type resDeviceAuthorize struct { util.CommonError Resp []resBaseInfo `json:"resp"` } -type ResCreateQRCode struct { +type resCreateQRCode struct { util.CommonError DeviceNum int `json:"device_num"` CodeList []resQRCode `json:"code_list"` diff --git a/device/device.go b/device/device.go index 91750b9..08d5c1f 100644 --- a/device/device.go +++ b/device/device.go @@ -43,7 +43,7 @@ func (d *Device) DeviceAuthorize(devices []ReqDevice, opType int, productId stri if err != nil { return nil, err } - var result ResDeviceAuthorize + var result resDeviceAuthorize err = json.Unmarshal(response, &result) if err != nil { return @@ -73,7 +73,7 @@ func (d *Device) CreateQRCode(devices []string) (res []resQRCode, err error) { if err != nil { return } - var result ResCreateQRCode + var result resCreateQRCode err = json.Unmarshal(response, &result) if err != nil { return From c4a361bbf646fe36821576624d4e447607aeeb7d Mon Sep 17 00:00:00 2001 From: "larry.liu" Date: Fri, 15 Nov 2019 14:46:16 +0800 Subject: [PATCH 09/15] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E6=99=BA=E8=83=BD=E7=A1=AC=E4=BB=B6=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- device/{definitions.go => authorize.go} | 45 ++++++++++++--- device/bind.go | 60 ++++++++++++++++++++ device/device.go | 73 +++++++------------------ device/message.go | 9 +++ device/qrcode.go | 73 +++++++++++++++++++++++++ 5 files changed, 199 insertions(+), 61 deletions(-) rename device/{definitions.go => authorize.go} (81%) create mode 100644 device/bind.go create mode 100644 device/message.go create mode 100644 device/qrcode.go diff --git a/device/definitions.go b/device/authorize.go similarity index 81% rename from device/definitions.go rename to device/authorize.go index df24067..9cca435 100644 --- a/device/definitions.go +++ b/device/authorize.go @@ -1,6 +1,10 @@ package device -import "github.com/silenceper/wechat/util" +import ( + "encoding/json" + "fmt" + "github.com/silenceper/wechat/util" +) const ( //添加设备标识 @@ -76,12 +80,35 @@ type resDeviceAuthorize struct { Resp []resBaseInfo `json:"resp"` } -type resCreateQRCode struct { - util.CommonError - DeviceNum int `json:"device_num"` - CodeList []resQRCode `json:"code_list"` -} -type resQRCode struct { - DeviceId string `json:"device_id"` - Ticket string `json:"ticket"` +// DeviceAuthorize 设备授权 +func (d *Device) DeviceAuthorize(devices []ReqDevice, opType int, productId string) (res []resBaseInfo, err error) { + var accessToken string + accessToken, err = d.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf("%s?access_token=%s", uriAuthorize, accessToken) + req := reqDeviceAuthorize{ + DeviceNum: fmt.Sprintf("%d", len(devices)), + DeviceList: devices, + OpType: fmt.Sprintf("%d", opType), + ProductId: productId, + } + var response []byte + response, err = util.PostJSON(uri, req) + if err != nil { + return nil, err + } + var result resDeviceAuthorize + err = json.Unmarshal(response, &result) + if err != nil { + return + } + if result.ErrCode != 0 { + err = fmt.Errorf("DeviceAuthorize Error , errcode=%d , errmsg=%s", result.ErrCode, result.ErrMsg) + return + } + res = result.Resp + return } diff --git a/device/bind.go b/device/bind.go new file mode 100644 index 0000000..370fe5a --- /dev/null +++ b/device/bind.go @@ -0,0 +1,60 @@ +package device + +import ( + "encoding/json" + "fmt" + "github.com/silenceper/wechat/util" +) + +type ReqBind struct { + Ticket string `json:"ticket"` + DeviceId string `json:"device_id"` + OpenId string `json:"open_id"` +} +type resBind struct { + BaseResp util.CommonError `json:"base_resp"` +} + +// Bind 设备绑定 +func (d *Device) Bind(req ReqBind) (err error) { + var accessToken string + if accessToken, err = d.GetAccessToken(); err != nil { + return + } + uri := fmt.Sprintf("%s?access_token=%s", uriBind, accessToken) + var response []byte + if response, err = util.PostJSON(uri, req); err != nil { + return + } + var result resBind + if err = json.Unmarshal(response, result); err != nil { + return + } + if result.BaseResp.ErrCode != 0 { + err = fmt.Errorf("DeviceBind Error , errcode=%d , errmsg=%s", result.BaseResp.ErrCode, result.BaseResp.ErrMsg) + return + } + return +} + +// Bind 设备解绑 +func (d *Device) Unbind(req ReqBind) (err error) { + var accessToken string + if accessToken, err = d.GetAccessToken(); err != nil { + return + } + uri := fmt.Sprintf("%s?access_token=%s", uriUnbind, accessToken) + var response []byte + if response, err = util.PostJSON(uri, req); err != nil { + return + } + var result resBind + if err = json.Unmarshal(response, result); err != nil { + return + } + if result.BaseResp.ErrCode != 0 { + err = fmt.Errorf("DeviceBind Error , errcode=%d , errmsg=%s", result.BaseResp.ErrCode, result.BaseResp.ErrMsg) + return + } + return +} diff --git a/device/device.go b/device/device.go index 08d5c1f..b2e9820 100644 --- a/device/device.go +++ b/device/device.go @@ -8,8 +8,12 @@ import ( ) const ( - deviceAuthorize = "https://api.weixin.qq.com/device/authorize_device" - deviceQRCode = "https://api.weixin.qq.com/device/create_qrcode" + uriAuthorize = "https://api.weixin.qq.com/device/authorize_device" + uriQRCode = "https://api.weixin.qq.com/device/create_qrcode" + uriVerifyQRCode = "https://api.weixin.qq.com/device/verify_qrcode" + uriBind = "https://api.weixin.qq.com/device/bind" + uriUnbind = "https://api.weixin.qq.com/device/unbind" + uriState = "https://api.weixin.qq.com/device/get_stat" ) //Device struct @@ -24,64 +28,29 @@ func NewDevice(context *context.Context) *Device { return device } -// DeviceAuthorize 设备授权 -func (d *Device) DeviceAuthorize(devices []ReqDevice, opType int, productId string) (res []resBaseInfo, err error) { - var accessToken string - accessToken, err = d.GetAccessToken() - if err != nil { - return nil, err - } - - uri := fmt.Sprintf("%s?access_token=%s", deviceAuthorize, accessToken) - req := reqDeviceAuthorize{ - DeviceNum: fmt.Sprintf("%d", len(devices)), - DeviceList: devices, - OpType: fmt.Sprintf("%d", opType), - ProductId: productId, - } - response, err := util.PostJSON(uri, req) - if err != nil { - return nil, err - } - var result resDeviceAuthorize - err = json.Unmarshal(response, &result) - if err != nil { - return - } - if result.ErrCode != 0 { - err = fmt.Errorf("DeviceAuthorize Error , errcode=%d , errmsg=%s", result.ErrCode, result.ErrMsg) - return - } - res = result.Resp - return +type resDeviceState struct { + util.CommonError + Status int `json:"status"` + StatusInfo string `json:"status_info"` } -// CreateQRCode 获取设备二维码 -func (d *Device) CreateQRCode(devices []string) (res []resQRCode, err error) { +// State 设备状态查询 +func (d *Device) State(deviceId string) (res resDeviceState, err error) { var accessToken string - accessToken, err = d.GetAccessToken() - if err != nil { - return nil, err - } - uri := fmt.Sprintf("%s?access_token=%s", deviceQRCode, accessToken) - req := map[string]interface{}{ - "device_num": len(devices), - "device_id_list": devices, - } - fmt.Println(req) - response, err := util.PostJSON(uri, req) - if err != nil { + if accessToken, err = d.GetAccessToken(); err != nil { return } - var result resCreateQRCode - err = json.Unmarshal(response, &result) - if err != nil { + uri := fmt.Sprintf("%s?access_token=%s&device_id=%s", uriState, accessToken, deviceId) + var response []byte + if response, err = util.HTTPGet(uri); err != nil { return } - if result.ErrCode != 0 { - err = fmt.Errorf("CreateQRCode Error , errcode=%d , errmsg=%s", result.ErrCode, result.ErrMsg) + if err = json.Unmarshal(response, &res); err != nil { + return + } + if res.ErrCode != 0 { + err = fmt.Errorf("DeviceState Error , errcode=%d , errmsg=%s", res.ErrCode, res.ErrMsg) return } - res = result.CodeList return } diff --git a/device/message.go b/device/message.go new file mode 100644 index 0000000..cfe5095 --- /dev/null +++ b/device/message.go @@ -0,0 +1,9 @@ +package device + +// 设备消息响应 +type MsgDevice struct { + DeviceType string + DeviceID string + SessionId string + OpenID string +} diff --git a/device/qrcode.go b/device/qrcode.go new file mode 100644 index 0000000..f31c300 --- /dev/null +++ b/device/qrcode.go @@ -0,0 +1,73 @@ +package device + +import ( + "encoding/json" + "fmt" + "github.com/silenceper/wechat/util" +) + +type resCreateQRCode struct { + util.CommonError + DeviceNum int `json:"device_num"` + CodeList []struct { + DeviceId string `json:"device_id"` + Ticket string `json:"ticket"` + } `json:"code_list"` +} + +// CreateQRCode 获取设备二维码 +func (d *Device) CreateQRCode(devices []string) (res resCreateQRCode, err error) { + var accessToken string + if accessToken, err = d.GetAccessToken(); err != nil { + return + } + uri := fmt.Sprintf("%s?access_token=%s", uriQRCode, accessToken) + req := map[string]interface{}{ + "device_num": len(devices), + "device_id_list": devices, + } + var response []byte + if response, err = util.PostJSON(uri, req); err != nil { + return + } + if err = json.Unmarshal(response, &res); err != nil { + return + } + if res.ErrCode != 0 { + err = fmt.Errorf("DeviceCreateQRCode Error , errcode=%d , errmsg=%s", res.ErrCode, res.ErrMsg) + return + } + return +} + +type resVerifyQRCode struct { + util.CommonError + DeviceType string `json:"device_type"` + DeviceId string `json:"device_id"` + Mac string `json:"mac"` +} + +// VerifyQRCode 验证设备二维码 +func (d *Device) VerifyQRCode(ticket string) (res resVerifyQRCode, err error) { + var accessToken string + if accessToken, err = d.GetAccessToken(); err != nil { + return + } + uri := fmt.Sprintf("%s?access_token=%s", uriVerifyQRCode, accessToken) + req := map[string]interface{}{ + "ticket": ticket, + } + fmt.Println(req) + var response []byte + if response, err = util.PostJSON(uri, req); err != nil { + return + } + if err = json.Unmarshal(response, &res); err != nil { + return + } + if res.ErrCode != 0 { + err = fmt.Errorf("DeviceCreateQRCode Error , errcode=%d , errmsg=%s", res.ErrCode, res.ErrMsg) + return + } + return +} From 33d00f45c5fe841758961a30da93adbc4ad8a047 Mon Sep 17 00:00:00 2001 From: "larry.liu" Date: Fri, 15 Nov 2019 14:46:50 +0800 Subject: [PATCH 10/15] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E5=9B=9E=E8=B0=83=E6=B6=88=E6=81=AF=E5=AE=9E=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- message/message.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/message/message.go b/message/message.go index 11f1535..74e2b36 100644 --- a/message/message.go +++ b/message/message.go @@ -1,6 +1,9 @@ package message -import "encoding/xml" +import ( + "encoding/xml" + "github.com/silenceper/wechat/device" +) // MsgType 基本消息类型 type MsgType string @@ -152,6 +155,9 @@ type MixMessage struct { ExtraInfoJSON string `xml:"extra_info_json"` TraceID string `xml:"trace_id"` StatusCode int `xml:"status_code"` + + //设备相关 + device.MsgDevice } //EventPic 发图事件推送 From 19e31741073f6580c87ae4f27ab28579a55e41af Mon Sep 17 00:00:00 2001 From: silenceper Date: Fri, 15 Nov 2019 15:01:03 +0800 Subject: [PATCH 11/15] Update .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index d983b50..b2d3ef6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: go go: + - 1.13.x - 1.12.x - 1.11.x - 1.10.x From 254ac9d7a670e9a04ee7a79b84a4d3409110ed90 Mon Sep 17 00:00:00 2001 From: "larry.liu" Date: Fri, 15 Nov 2019 15:34:17 +0800 Subject: [PATCH 12/15] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AF=B9=E8=B1=A1?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- device/bind.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/device/bind.go b/device/bind.go index 370fe5a..9383a64 100644 --- a/device/bind.go +++ b/device/bind.go @@ -27,7 +27,7 @@ func (d *Device) Bind(req ReqBind) (err error) { return } var result resBind - if err = json.Unmarshal(response, result); err != nil { + if err = json.Unmarshal(response, &result); err != nil { return } if result.BaseResp.ErrCode != 0 { @@ -49,7 +49,7 @@ func (d *Device) Unbind(req ReqBind) (err error) { return } var result resBind - if err = json.Unmarshal(response, result); err != nil { + if err = json.Unmarshal(response, &result); err != nil { return } if result.BaseResp.ErrCode != 0 { From 5617c9512d034cb6873ca2114432298e5d6fd495 Mon Sep 17 00:00:00 2001 From: "larry.liu" Date: Fri, 15 Nov 2019 15:56:38 +0800 Subject: [PATCH 13/15] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- device/authorize.go | 26 ++++++++++++++------------ device/bind.go | 8 +++++--- device/device.go | 8 +++++--- device/message.go | 4 ++-- device/qrcode.go | 15 +++++++++------ 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/device/authorize.go b/device/authorize.go index 9cca435..80b0152 100644 --- a/device/authorize.go +++ b/device/authorize.go @@ -3,14 +3,15 @@ package device import ( "encoding/json" "fmt" + "github.com/silenceper/wechat/util" ) const ( - //添加设备标识 - DEVICE_ADD = iota - //更新设备标识 - DEVCIE_UPGRADE + // DeviceAdd 添加设备标识 + DeviceAdd = iota + // DeviceUpgrade 更新设备标识 + DeviceUpgrade ) type reqDeviceAuthorize struct { @@ -24,12 +25,13 @@ type reqDeviceAuthorize struct { //当 op_type 为‘0’,product_id 为‘1’时,不要填写 product_id 字段(会引起不必要错误); //当 op_typy 为‘0’,product_id 不为‘1’时,必须填写 product_id 字段; //当 op_type 为 1 时,不要填写 product_id 字段。 - ProductId string `json:"product_id,omitempty"` + ProductID string `json:"product_id,omitempty"` } +//ReqDevice 设备授权实体 type ReqDevice struct { // 设备的 device id - Id string `json:"id"` + ID string `json:"id"` // 设备的mac地址 格式采用16进制串的方式(长度为12字节), // 不需要0X前缀,如: 1234567890AB Mac string `json:"mac"` @@ -66,22 +68,22 @@ type ReqDevice struct { BleSimpleProtocol string `json:"ble_simple_protocol,omitempty"` } -// 授权回调实体 -type resBaseInfo struct { +//ResBaseInfo 授权回调实体 +type ResBaseInfo struct { BaseInfo struct { DeviceType string `json:"device_type"` - DeviceId string `json:"device_id"` + DeviceID string `json:"device_id"` } `json:"base_info"` } // 授权回调根信息 type resDeviceAuthorize struct { util.CommonError - Resp []resBaseInfo `json:"resp"` + Resp []ResBaseInfo `json:"resp"` } // DeviceAuthorize 设备授权 -func (d *Device) DeviceAuthorize(devices []ReqDevice, opType int, productId string) (res []resBaseInfo, err error) { +func (d *Device) DeviceAuthorize(devices []ReqDevice, opType int, product string) (res []ResBaseInfo, err error) { var accessToken string accessToken, err = d.GetAccessToken() if err != nil { @@ -93,7 +95,7 @@ func (d *Device) DeviceAuthorize(devices []ReqDevice, opType int, productId stri DeviceNum: fmt.Sprintf("%d", len(devices)), DeviceList: devices, OpType: fmt.Sprintf("%d", opType), - ProductId: productId, + ProductID: product, } var response []byte response, err = util.PostJSON(uri, req) diff --git a/device/bind.go b/device/bind.go index 9383a64..5168a74 100644 --- a/device/bind.go +++ b/device/bind.go @@ -3,13 +3,15 @@ package device import ( "encoding/json" "fmt" + "github.com/silenceper/wechat/util" ) +// ReqBind 设备绑定解绑共通实体 type ReqBind struct { Ticket string `json:"ticket"` - DeviceId string `json:"device_id"` - OpenId string `json:"open_id"` + DeviceID string `json:"device_id"` + OpenID string `json:"open_id"` } type resBind struct { BaseResp util.CommonError `json:"base_resp"` @@ -37,7 +39,7 @@ func (d *Device) Bind(req ReqBind) (err error) { return } -// Bind 设备解绑 +// Unbind 设备解绑 func (d *Device) Unbind(req ReqBind) (err error) { var accessToken string if accessToken, err = d.GetAccessToken(); err != nil { diff --git a/device/device.go b/device/device.go index b2e9820..bdc1059 100644 --- a/device/device.go +++ b/device/device.go @@ -3,6 +3,7 @@ package device import ( "encoding/json" "fmt" + "github.com/silenceper/wechat/context" "github.com/silenceper/wechat/util" ) @@ -28,19 +29,20 @@ func NewDevice(context *context.Context) *Device { return device } -type resDeviceState struct { +// ResDeviceState 设备状态响应实体 +type ResDeviceState struct { util.CommonError Status int `json:"status"` StatusInfo string `json:"status_info"` } // State 设备状态查询 -func (d *Device) State(deviceId string) (res resDeviceState, err error) { +func (d *Device) State(device string) (res ResDeviceState, err error) { var accessToken string if accessToken, err = d.GetAccessToken(); err != nil { return } - uri := fmt.Sprintf("%s?access_token=%s&device_id=%s", uriState, accessToken, deviceId) + uri := fmt.Sprintf("%s?access_token=%s&device_id=%s", uriState, accessToken, device) var response []byte if response, err = util.HTTPGet(uri); err != nil { return diff --git a/device/message.go b/device/message.go index cfe5095..7efcbbb 100644 --- a/device/message.go +++ b/device/message.go @@ -1,9 +1,9 @@ package device -// 设备消息响应 +//MsgDevice 设备消息响应 type MsgDevice struct { DeviceType string DeviceID string - SessionId string + SessionID string OpenID string } diff --git a/device/qrcode.go b/device/qrcode.go index f31c300..fb2e9f8 100644 --- a/device/qrcode.go +++ b/device/qrcode.go @@ -3,20 +3,22 @@ package device import ( "encoding/json" "fmt" + "github.com/silenceper/wechat/util" ) -type resCreateQRCode struct { +//ResCreateQRCode 获取二维码的返回实体 +type ResCreateQRCode struct { util.CommonError DeviceNum int `json:"device_num"` CodeList []struct { - DeviceId string `json:"device_id"` + DeviceID string `json:"device_id"` Ticket string `json:"ticket"` } `json:"code_list"` } // CreateQRCode 获取设备二维码 -func (d *Device) CreateQRCode(devices []string) (res resCreateQRCode, err error) { +func (d *Device) CreateQRCode(devices []string) (res ResCreateQRCode, err error) { var accessToken string if accessToken, err = d.GetAccessToken(); err != nil { return @@ -40,15 +42,16 @@ func (d *Device) CreateQRCode(devices []string) (res resCreateQRCode, err error) return } -type resVerifyQRCode struct { +//ResVerifyQRCode 验证授权结果实体 +type ResVerifyQRCode struct { util.CommonError DeviceType string `json:"device_type"` - DeviceId string `json:"device_id"` + DeviceID string `json:"device_id"` Mac string `json:"mac"` } // VerifyQRCode 验证设备二维码 -func (d *Device) VerifyQRCode(ticket string) (res resVerifyQRCode, err error) { +func (d *Device) VerifyQRCode(ticket string) (res ResVerifyQRCode, err error) { var accessToken string if accessToken, err = d.GetAccessToken(); err != nil { return From 733c53a044440b3b4a0c97a1fde82ec5571f3483 Mon Sep 17 00:00:00 2001 From: "larry.liu" Date: Fri, 15 Nov 2019 16:32:25 +0800 Subject: [PATCH 14/15] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- device/bind.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- device/device.go | 2 ++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/device/bind.go b/device/bind.go index 5168a74..6d2b3d0 100644 --- a/device/bind.go +++ b/device/bind.go @@ -9,9 +9,9 @@ import ( // ReqBind 设备绑定解绑共通实体 type ReqBind struct { - Ticket string `json:"ticket"` + Ticket string `json:"ticket,omitempty"` DeviceID string `json:"device_id"` - OpenID string `json:"open_id"` + OpenID string `json:"openid"` } type resBind struct { BaseResp util.CommonError `json:"base_resp"` @@ -60,3 +60,47 @@ func (d *Device) Unbind(req ReqBind) (err error) { } return } + +// CompelBind 强制绑定用户和设备 +func (d *Device) CompelBind(req ReqBind) (err error) { + var accessToken string + if accessToken, err = d.GetAccessToken(); err != nil { + return + } + uri := fmt.Sprintf("%s?access_token=%s", uriCompelBind, accessToken) + var response []byte + if response, err = util.PostJSON(uri, req); err != nil { + return + } + var result resBind + if err = json.Unmarshal(response, &result); err != nil { + return + } + if result.BaseResp.ErrCode != 0 { + err = fmt.Errorf("DeviceBind Error , errcode=%d , errmsg=%s", result.BaseResp.ErrCode, result.BaseResp.ErrMsg) + return + } + return +} + +// CompelUnbind 强制解绑用户和设备 +func (d *Device) CompelUnbind(req ReqBind) (err error) { + var accessToken string + if accessToken, err = d.GetAccessToken(); err != nil { + return + } + uri := fmt.Sprintf("%s?access_token=%s", uriCompelUnbind, accessToken) + var response []byte + if response, err = util.PostJSON(uri, req); err != nil { + return + } + var result resBind + if err = json.Unmarshal(response, &result); err != nil { + return + } + if result.BaseResp.ErrCode != 0 { + err = fmt.Errorf("DeviceBind Error , errcode=%d , errmsg=%s", result.BaseResp.ErrCode, result.BaseResp.ErrMsg) + return + } + return +} diff --git a/device/device.go b/device/device.go index bdc1059..3c0074a 100644 --- a/device/device.go +++ b/device/device.go @@ -14,6 +14,8 @@ const ( uriVerifyQRCode = "https://api.weixin.qq.com/device/verify_qrcode" uriBind = "https://api.weixin.qq.com/device/bind" uriUnbind = "https://api.weixin.qq.com/device/unbind" + uriCompelBind = "https://api.weixin.qq.com/device/compel_bind" + uriCompelUnbind = "https://api.weixin.qq.com/device/compel_unbind" uriState = "https://api.weixin.qq.com/device/get_stat" ) From d7f371cb65bf16aff438dbbcf6fca3eb8a1c4fc8 Mon Sep 17 00:00:00 2001 From: silenceper Date: Mon, 18 Nov 2019 20:45:32 +0800 Subject: [PATCH 15/15] =?UTF-8?q?=E5=BA=8F=E5=88=97=E5=8C=96=20xml=20?= =?UTF-8?q?=E6=97=B6=E6=B7=BB=E5=8A=A0=20cdata=20=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- message/customer_message.go | 10 +++++----- message/message.go | 19 +++++++++++++++---- message/text.go | 4 ++-- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/message/customer_message.go b/message/customer_message.go index e697d13..7eaf2f6 100644 --- a/message/customer_message.go +++ b/message/customer_message.go @@ -3,8 +3,8 @@ package message import ( "encoding/json" "fmt" - "github.com/silenceper/wechat/util" "github.com/silenceper/wechat/context" + "github.com/silenceper/wechat/util" ) const ( @@ -139,14 +139,14 @@ type MediaMiniprogrampage struct { } //Send 发送客服消息 -func (manager *Manager) Send(msg *CustomerMessage) error { - accessToken,err:=manager.Context.GetAccessToken() - if err!=nil { +func (manager *Manager) Send(msg *CustomerMessage) error { + accessToken, err := manager.Context.GetAccessToken() + if err != nil { return err } uri := fmt.Sprintf("%s?access_token=%s", customerSendMessage, accessToken) response, err := util.PostJSON(uri, msg) - var result util.CommonError + var result util.CommonError err = json.Unmarshal(response, &result) if err != nil { return err diff --git a/message/message.go b/message/message.go index db2f5ca..471dcd4 100644 --- a/message/message.go +++ b/message/message.go @@ -2,6 +2,7 @@ package message import ( "encoding/xml" + "github.com/silenceper/wechat/device" ) @@ -181,22 +182,32 @@ type ResponseEncryptedXMLMsg struct { Nonce string `xml:"Nonce" json:"Nonce"` } +// CDATA 使用该类型,在序列化为 xml 文本时文本会被解析器忽略 +type CDATA string + +// MarshalXML 实现自己的序列化方法 +func (c CDATA) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + return e.EncodeElement(struct { + string `xml:",cdata"` + }{string(c)}, start) +} + // CommonToken 消息中通用的结构 type CommonToken struct { XMLName xml.Name `xml:"xml"` - ToUserName string `xml:"ToUserName"` - FromUserName string `xml:"FromUserName"` + ToUserName CDATA `xml:"ToUserName"` + FromUserName CDATA `xml:"FromUserName"` CreateTime int64 `xml:"CreateTime"` MsgType MsgType `xml:"MsgType"` } //SetToUserName set ToUserName -func (msg *CommonToken) SetToUserName(toUserName string) { +func (msg *CommonToken) SetToUserName(toUserName CDATA) { msg.ToUserName = toUserName } //SetFromUserName set FromUserName -func (msg *CommonToken) SetFromUserName(fromUserName string) { +func (msg *CommonToken) SetFromUserName(fromUserName CDATA) { msg.FromUserName = fromUserName } diff --git a/message/text.go b/message/text.go index d981d96..88ac19a 100644 --- a/message/text.go +++ b/message/text.go @@ -3,12 +3,12 @@ package message //Text 文本消息 type Text struct { CommonToken - Content string `xml:"Content"` + Content CDATA `xml:"Content"` } //NewText 初始化文本消息 func NewText(content string) *Text { text := new(Text) - text.Content = content + text.Content = CDATA(content) return text }