| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- package subscribe
- import (
- "encoding/json"
- "fmt"
- "github.com/silenceper/wechat/v2/miniprogram/context"
- "github.com/silenceper/wechat/v2/util"
- )
- const (
- // 发送订阅消息
- // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html
- subscribeSendURL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send"
- // 获取当前帐号下的个人模板列表
- // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.getTemplateList.html
- getTemplateURL = "https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate"
- // 添加订阅模板
- // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.addTemplate.html
- addTemplateURL = "https://api.weixin.qq.com/wxaapi/newtmpl/addtemplate"
- // 删除私有模板
- // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.deleteTemplate.html
- delTemplateURL = "https://api.weixin.qq.com/wxaapi/newtmpl/deltemplate"
- // 统一服务消息
- // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/uniform-message/uniformMessage.send.html
- uniformMessageSend = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send"
- // getCategoryURL 获取类目
- getCategoryURL = "https://api.weixin.qq.com/wxaapi/newtmpl/getcategory?access_token=%s"
- // getPubTemplateKeyWordsByIDURL 获取关键词列表
- getPubTemplateKeyWordsByIDURL = "https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatekeywords?access_token=%s&tid=%s"
- // getPubTemplateTitleListURL 获取所属类目下的公共模板
- getPubTemplateTitleListURL = "https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatetitles?access_token=%s&ids=%s&start=%d&limit=%d"
- // setUserNotifyURL 激活与更新服务卡片
- setUserNotifyURL = "https://api.weixin.qq.com/wxa/set_user_notify?access_token=%s"
- // setUserNotifyExtURL 更新服务卡片扩展信息
- setUserNotifyExtURL = "https://api.weixin.qq.com/wxa/set_user_notifyext?access_token=%s"
- // getUserNotifyURL 查询服务卡片状态
- getUserNotifyURL = "https://api.weixin.qq.com/wxa/get_user_notify?access_token=%s"
- )
- // Subscribe 订阅消息
- type Subscribe struct {
- *context.Context
- }
- // NewSubscribe 实例化
- func NewSubscribe(ctx *context.Context) *Subscribe {
- return &Subscribe{Context: ctx}
- }
- // Message 订阅消息请求参数
- type Message struct {
- ToUser string `json:"touser"` // 必选,接收者(用户)的 openid
- TemplateID string `json:"template_id"` // 必选,所需下发的订阅模板id
- Page string `json:"page"` // 可选,点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。
- Data map[string]*DataItem `json:"data"` // 必选, 模板内容
- MiniprogramState string `json:"miniprogram_state"` // 可选,跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
- Lang string `json:"lang"` // 入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN
- }
- // DataItem 模版内某个 .DATA 的值
- type DataItem struct {
- Value interface{} `json:"value"`
- Color string `json:"color"`
- }
- // TemplateItem template item
- type TemplateItem struct {
- PriTmplID string `json:"priTmplId"`
- Title string `json:"title"`
- Content string `json:"content"`
- Example string `json:"example"`
- Type int64 `json:"type"`
- KeywordEnumValueList []KeywordEnumValue `json:"keywordEnumValueList"`
- }
- // KeywordEnumValue 枚举参数值范围
- type KeywordEnumValue struct {
- EnumValueList []string `json:"enumValueList"`
- KeywordCode string `json:"keywordCode"`
- }
- // TemplateList template list
- type TemplateList struct {
- util.CommonError
- Data []TemplateItem `json:"data"`
- }
- // resTemplateSend 发送获取 msg id
- type resTemplateSend struct {
- util.CommonError
- MsgID int64 `json:"msgid"`
- }
- // Send 发送订阅消息
- func (s *Subscribe) Send(msg *Message) (err error) {
- var accessToken string
- accessToken, err = s.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s", subscribeSendURL, accessToken)
- response, err := util.PostJSON(uri, msg)
- if err != nil {
- return
- }
- return util.DecodeWithCommonError(response, "Send")
- }
- // SendGetMsgID 发送订阅消息返回 msgid
- func (s *Subscribe) SendGetMsgID(msg *Message) (msgID int64, err error) {
- var accessToken string
- accessToken, err = s.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s", subscribeSendURL, accessToken)
- response, err := util.PostJSON(uri, msg)
- if err != nil {
- return
- }
- var result resTemplateSend
- if err = json.Unmarshal(response, &result); err != nil {
- return
- }
- if result.ErrCode != 0 {
- err = fmt.Errorf("template msg send error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
- return
- }
- msgID = result.MsgID
- return
- }
- // ListTemplates 获取当前帐号下的个人模板列表
- // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.getTemplateList.html
- func (s *Subscribe) ListTemplates() (*TemplateList, error) {
- accessToken, err := s.GetAccessToken()
- if err != nil {
- return nil, err
- }
- uri := fmt.Sprintf("%s?access_token=%s", getTemplateURL, accessToken)
- response, err := util.HTTPGet(uri)
- if err != nil {
- return nil, err
- }
- templateList := TemplateList{}
- err = util.DecodeWithError(response, &templateList, "ListTemplates")
- if err != nil {
- return nil, err
- }
- return &templateList, nil
- }
- // UniformMessage 统一服务消息
- type UniformMessage struct {
- ToUser string `json:"touser"`
- WeappTemplateMsg struct {
- TemplateID string `json:"template_id"`
- Page string `json:"page"`
- FormID string `json:"form_id"`
- Data map[string]*DataItem `json:"data"`
- EmphasisKeyword string `json:"emphasis_keyword"`
- } `json:"weapp_template_msg"`
- MpTemplateMsg struct {
- Appid string `json:"appid"`
- TemplateID string `json:"template_id"`
- URL string `json:"url"`
- Miniprogram struct {
- Appid string `json:"appid"`
- Pagepath string `json:"pagepath"`
- } `json:"miniprogram"`
- Data map[string]*DataItem `json:"data"`
- } `json:"mp_template_msg"`
- }
- // UniformSend 发送统一服务消息
- func (s *Subscribe) UniformSend(msg *UniformMessage) (err error) {
- var accessToken string
- accessToken, err = s.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s", uniformMessageSend, accessToken)
- response, err := util.PostJSON(uri, msg)
- if err != nil {
- return
- }
- return util.DecodeWithCommonError(response, "UniformSend")
- }
- type resSubscribeAdd struct {
- util.CommonError
- TemplateID string `json:"priTmplId"`
- }
- // Add 添加订阅消息模板
- func (s *Subscribe) Add(ShortID string, kidList []int, sceneDesc string) (templateID string, err error) {
- var accessToken string
- accessToken, err = s.GetAccessToken()
- if err != nil {
- return
- }
- var msg = struct {
- TemplateIDShort string `json:"tid"`
- SceneDesc string `json:"sceneDesc"`
- KidList []int `json:"kidList"`
- }{TemplateIDShort: ShortID, SceneDesc: sceneDesc, KidList: kidList}
- uri := fmt.Sprintf("%s?access_token=%s", addTemplateURL, accessToken)
- var response []byte
- response, err = util.PostJSON(uri, msg)
- if err != nil {
- return
- }
- var result resSubscribeAdd
- err = util.DecodeWithError(response, &result, "AddSubscribe")
- return result.TemplateID, err
- }
- // Delete 删除私有模板
- func (s *Subscribe) Delete(templateID string) (err error) {
- var accessToken string
- accessToken, err = s.GetAccessToken()
- if err != nil {
- return
- }
- var msg = struct {
- TemplateID string `json:"priTmplId"`
- }{TemplateID: templateID}
- uri := fmt.Sprintf("%s?access_token=%s", delTemplateURL, accessToken)
- var response []byte
- response, err = util.PostJSON(uri, msg)
- if err != nil {
- return
- }
- return util.DecodeWithCommonError(response, "DeleteSubscribe")
- }
- // GetCategoryResponse 获取类目响应
- type GetCategoryResponse struct {
- util.CommonError
- Data []Category `json:"data"`
- }
- // Category 类目
- type Category struct {
- ID int64 `json:"id"`
- Name string `json:"name"`
- }
- // GetCategory 获取类目
- // see https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-message-management/subscribe-message/getCategory.html
- func (s *Subscribe) GetCategory() ([]Category, error) {
- var (
- accessToken string
- err error
- )
- if accessToken, err = s.GetAccessToken(); err != nil {
- return nil, err
- }
- var response []byte
- if response, err = util.HTTPGet(fmt.Sprintf(getCategoryURL, accessToken)); err != nil {
- return nil, err
- }
- result := &GetCategoryResponse{}
- err = util.DecodeWithError(response, result, "GetCategory")
- return result.Data, err
- }
- // GetPubTemplateKeywordsByIDResponse 获取关键词列表响应
- type GetPubTemplateKeywordsByIDResponse struct {
- util.CommonError
- Count int64 `json:"count"`
- Data []PubTemplateKeywords `json:"data"`
- }
- // PubTemplateKeywords 关键词
- type PubTemplateKeywords struct {
- KID int64 `json:"kid"`
- Name string `json:"name"`
- Example string `json:"example"`
- Rule string `json:"rule"`
- }
- // GetPubTemplateKeywordsByID 获取关键词列表
- // see https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-message-management/subscribe-message/getPubTemplateKeyWordsById.html
- func (s *Subscribe) GetPubTemplateKeywordsByID(tid string) (*GetPubTemplateKeywordsByIDResponse, error) {
- var (
- accessToken string
- err error
- )
- if accessToken, err = s.GetAccessToken(); err != nil {
- return nil, err
- }
- var response []byte
- if response, err = util.HTTPGet(fmt.Sprintf(getPubTemplateKeyWordsByIDURL, accessToken, tid)); err != nil {
- return nil, err
- }
- result := &GetPubTemplateKeywordsByIDResponse{}
- err = util.DecodeWithError(response, result, "GetPubTemplateKeywordsByID")
- return result, err
- }
- // GetPubTemplateTitleListRequest 获取所属类目下的公共模板请求
- type GetPubTemplateTitleListRequest struct {
- Start int64
- Limit int64
- IDs string
- }
- // GetPubTemplateTitleListResponse 获取所属类目下的公共模板响应
- type GetPubTemplateTitleListResponse struct {
- util.CommonError
- Count int64 `json:"count"`
- Data []PubTemplateTitle `json:"data"`
- }
- // PubTemplateTitle 模板标题
- type PubTemplateTitle struct {
- Type int64 `json:"type"`
- TID string `json:"tid"`
- Title string `json:"title"`
- CategoryID string `json:"categoryId"`
- }
- // GetPubTemplateTitleList 获取所属类目下的公共模板
- // see https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-message-management/subscribe-message/getPubTemplateTitleList.html
- func (s *Subscribe) GetPubTemplateTitleList(req *GetPubTemplateTitleListRequest) (*GetPubTemplateTitleListResponse, error) {
- var (
- accessToken string
- err error
- )
- if accessToken, err = s.GetAccessToken(); err != nil {
- return nil, err
- }
- var response []byte
- if response, err = util.HTTPGet(fmt.Sprintf(getPubTemplateTitleListURL, accessToken, req.IDs, req.Start, req.Limit)); err != nil {
- return nil, err
- }
- result := &GetPubTemplateTitleListResponse{}
- err = util.DecodeWithError(response, result, "GetPubTemplateTitleList")
- return result, err
- }
- // SetUserNotifyRequest 激活与更新服务卡片请求
- type SetUserNotifyRequest struct {
- OpenID string `json:"openid"`
- NotifyType int64 `json:"notify_type"`
- NotifyCode string `json:"notify_code"`
- ContentJSON string `json:"content_json"`
- CheckJSON string `json:"check_json,omitempty"`
- }
- // SetUserNotify 激活与更新服务卡片
- // see https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-message-management/subscribe-message/setUserNotify.html
- func (s *Subscribe) SetUserNotify(req *SetUserNotifyRequest) error {
- var (
- accessToken string
- err error
- )
- if accessToken, err = s.GetAccessToken(); err != nil {
- return err
- }
- var response []byte
- if response, err = util.PostJSON(fmt.Sprintf(setUserNotifyURL, accessToken), req); err != nil {
- return err
- }
- return util.DecodeWithCommonError(response, "SetUserNotify")
- }
- // SetUserNotifyExtRequest 更新服务卡片扩展信息请求
- type SetUserNotifyExtRequest struct {
- OpenID string `json:"openid"`
- NotifyType int64 `json:"notify_type"`
- NotifyCode string `json:"notify_code"`
- ExtJSON string `json:"ext_json"`
- }
- // SetUserNotifyExt 更新服务卡片扩展信息
- // see https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-message-management/subscribe-message/setUserNotifyExt.html
- func (s *Subscribe) SetUserNotifyExt(req *SetUserNotifyExtRequest) error {
- var (
- accessToken string
- err error
- )
- if accessToken, err = s.GetAccessToken(); err != nil {
- return err
- }
- var response []byte
- if response, err = util.PostJSON(fmt.Sprintf(setUserNotifyExtURL, accessToken), req); err != nil {
- return err
- }
- return util.DecodeWithCommonError(response, "SetUserNotifyExt")
- }
- // GetUserNotifyRequest 查询服务卡片状态请求
- type GetUserNotifyRequest struct {
- OpenID string `json:"openid"`
- NotifyType int64 `json:"notify_type"`
- NotifyCode string `json:"notify_code"`
- }
- // GetUserNotifyResponse 查询服务卡片状态响应
- type GetUserNotifyResponse struct {
- util.CommonError
- NotifyInfo NotifyInfo `json:"notify_info"`
- }
- // NotifyInfo 卡片状态
- type NotifyInfo struct {
- NotifyType int64 `json:"notify_type"`
- ContentJSON string `json:"content_json"`
- CodeState int64 `json:"code_state"`
- CodeExpireTime int64 `json:"code_expire_time"`
- }
- // GetUserNotify 查询服务卡片状态
- // see https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-message-management/subscribe-message/getUserNotify.html
- func (s *Subscribe) GetUserNotify(req *GetUserNotifyRequest) (*GetUserNotifyResponse, error) {
- var (
- accessToken string
- err error
- )
- if accessToken, err = s.GetAccessToken(); err != nil {
- return nil, err
- }
- var response []byte
- if response, err = util.PostJSON(fmt.Sprintf(getUserNotifyURL, accessToken), req); err != nil {
- return nil, err
- }
- result := &GetUserNotifyResponse{}
- err = util.DecodeWithError(response, result, "GetUserNotify")
- return result, err
- }
|