├── server ├── consts.go ├── encoding.go ├── callbackdefault.go ├── decoding.go └── server.go ├── communicate ├── consts.go └── http.go ├── example ├── full │ ├── testresource │ │ └── test.jpg │ ├── user │ │ └── user.go │ ├── event │ │ └── event.go │ ├── message │ │ └── message.go │ ├── sender │ │ └── sender.go │ ├── menu │ │ └── menu.go │ ├── store │ │ └── store.go │ ├── main.go │ ├── template │ │ └── template.go │ └── material │ │ └── material.go └── basic │ └── main.go ├── private ├── consts.go └── struct.go ├── template ├── struct.go ├── consts.go └── template.go ├── menu ├── struct.go ├── const.go └── menu.go ├── pay ├── consts.go ├── common_test.go ├── struct.go ├── paymentcode.go └── common.go ├── token ├── consts.go └── token.go ├── shop ├── struct.go ├── consts.go └── shop.go ├── common ├── consts.go ├── interface.go └── struct.go ├── sender ├── consts.go ├── reply.go └── sender.go ├── material ├── struct.go ├── consts.go └── material.go ├── user ├── struct.go ├── consts.go └── user.go ├── store ├── consts.go └── store.go ├── wechat.go ├── utils ├── filereader.go └── change.go └── README.md /server/consts.go: -------------------------------------------------------------------------------- 1 | package server 2 | -------------------------------------------------------------------------------- /server/encoding.go: -------------------------------------------------------------------------------- 1 | package server 2 | -------------------------------------------------------------------------------- /communicate/consts.go: -------------------------------------------------------------------------------- 1 | package communicate 2 | 3 | var ( 4 | AccessToken string = "access_token" 5 | ) 6 | -------------------------------------------------------------------------------- /example/full/testresource/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MwlLj/go-wechat/HEAD/example/full/testresource/test.jpg -------------------------------------------------------------------------------- /private/consts.go: -------------------------------------------------------------------------------- 1 | package private 2 | 3 | var ( 4 | ErrorCodeSuccess int = 0 5 | ErrorCodeTokenInvaild int = 40001 6 | ) 7 | -------------------------------------------------------------------------------- /private/struct.go: -------------------------------------------------------------------------------- 1 | package private 2 | 3 | type CCommonResponse struct { 4 | ErrCode int `json:"errcode"` 5 | ErrMsg string `json:"errmsg"` 6 | } 7 | -------------------------------------------------------------------------------- /template/struct.go: -------------------------------------------------------------------------------- 1 | package template 2 | 3 | type CCommonResponse struct { 4 | ErrCode int `json:"errcode"` 5 | ErrMsg string `json:"errmsg"` 6 | } 7 | -------------------------------------------------------------------------------- /menu/struct.go: -------------------------------------------------------------------------------- 1 | package menu 2 | 3 | import ( 4 | "github.com/MwlLj/go-wechat/common" 5 | ) 6 | 7 | type CMenuData struct { 8 | Buttons []common.CButton `json:"button"` 9 | } 10 | -------------------------------------------------------------------------------- /pay/consts.go: -------------------------------------------------------------------------------- 1 | package pay 2 | 3 | var ( 4 | SignField string = "sign" 5 | SignKeyField string = "key" 6 | ) 7 | 8 | var ( 9 | PayByPaymentCodeCommitUrl string = "https://api.mch.weixin.qq.com/pay/micropay" 10 | ) 11 | -------------------------------------------------------------------------------- /token/consts.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | var ( 4 | GrantType string = "grant_type" 5 | AppId string = "appid" 6 | AppSecret string = "secret" 7 | ) 8 | 9 | var ( 10 | ClientCredential string = "client_credential" 11 | ) 12 | 13 | var ( 14 | GetTokenUrl string = "https://api.weixin.qq.com/cgi-bin/token" 15 | ) 16 | -------------------------------------------------------------------------------- /menu/const.go: -------------------------------------------------------------------------------- 1 | package menu 2 | 3 | var ( 4 | AccessToken string = "access_token" 5 | ) 6 | 7 | var ( 8 | CreateMenuUrl string = "https://api.weixin.qq.com/cgi-bin/menu/create" 9 | GetMenuUrl string = "https://api.weixin.qq.com/cgi-bin/menu/get" 10 | DeleteMenuUrl string = "https://api.weixin.qq.com/cgi-bin/menu/delete" 11 | ) 12 | -------------------------------------------------------------------------------- /shop/struct.go: -------------------------------------------------------------------------------- 1 | package shop 2 | 3 | type CAddStockRequest struct { 4 | ProductId string `json:"product_id"` 5 | SkuInfo string `json:"sku_info"` 6 | Quantity int `json:"quantity"` 7 | } 8 | 9 | type CReduceStockRequest struct { 10 | ProductId string `json:"product_id"` 11 | SkuInfo string `json:"sku_info"` 12 | Quantity int `json:"quantity"` 13 | } 14 | -------------------------------------------------------------------------------- /common/consts.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | var ( 4 | ExpressIdNormalPost int64 = 10000027 5 | ExpressIdFastPost int64 = 10000028 6 | ExpressIdEMS int64 = 10000029 7 | ) 8 | 9 | var ( 10 | CommodityStatusGrounding int = 1 11 | CommodityStatusUnderCarriage int = 0 12 | ) 13 | 14 | var ( 15 | SignEncrypyTypeHMACSHA256 string = "HMAC-SHA256" 16 | SignEncrypyTypeMD5 string = "MD5" 17 | ) 18 | -------------------------------------------------------------------------------- /sender/consts.go: -------------------------------------------------------------------------------- 1 | package sender 2 | 3 | var ( 4 | GroupSendByTagUrl string = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall" 5 | GroupSendByOpenIdsUrl string = "https://api.weixin.qq.com/cgi-bin/message/mass/send" 6 | DeleteGroupSendUrl string = "https://api.weixin.qq.com/cgi-bin/message/mass/delete" 7 | PreviewMessageUrl string = "https://api.weixin.qq.com/cgi-bin/message/mass/preview" 8 | ) 9 | -------------------------------------------------------------------------------- /example/full/user/user.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/MwlLj/go-wechat" 7 | // "github.com/MwlLj/go-wechat/common" 8 | ) 9 | 10 | func GetFollowUsersTest(wc wechat.IWeChat) { 11 | user := wc.User() 12 | res, err := user.GetFollowUsers(3000) 13 | if err != nil { 14 | fmt.Println(err) 15 | return 16 | } 17 | b, err := json.Marshal(res) 18 | if err != nil { 19 | fmt.Println(err) 20 | return 21 | } 22 | fmt.Println(string(b)) 23 | } 24 | -------------------------------------------------------------------------------- /example/full/event/event.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/MwlLj/go-wechat" 5 | "github.com/MwlLj/go-wechat/common" 6 | ) 7 | 8 | func RegisterEventTest(wc wechat.IWeChat) { 9 | wc.RegisterEventFunc(func(reply common.IReply, event *common.CEvent, communicate common.CDataCommunicate, userData interface{}) error { 10 | msg := common.CMessage{} 11 | msg.Content = "event: " + event.Event 12 | msg.MsgType = common.MsgTypeText 13 | reply.SendMessage(&msg) 14 | return nil 15 | }, nil) 16 | } 17 | -------------------------------------------------------------------------------- /pay/common_test.go: -------------------------------------------------------------------------------- 1 | package pay 2 | 3 | import ( 4 | "fmt" 5 | "github.com/MwlLj/go-wechat/common" 6 | "testing" 7 | ) 8 | 9 | func TestSignValidateByStruct(t *testing.T) { 10 | request := CPayByPaymentCodeRequest{} 11 | request.Body = "hello" 12 | key := "test" 13 | sign, err := signValidateByStruct(&request, &key, &common.SignEncrypyTypeMD5) 14 | if err != nil { 15 | return 16 | } 17 | fmt.Println(*sign) 18 | } 19 | 20 | func TestGenRandomString(t *testing.T) { 21 | fmt.Println(string(genRandomString(32))) 22 | } 23 | -------------------------------------------------------------------------------- /material/struct.go: -------------------------------------------------------------------------------- 1 | package material 2 | 3 | type CGetTmpMaterialResponse struct { 4 | ErrCode int `json:"errcode"` 5 | ErrMsg string `json:"errmsg"` 6 | ResUrl interface{} `json:"-"` 7 | } 8 | 9 | type CGetTmpHDMaterialResponse struct { 10 | ErrCode int `json:"errcode"` 11 | ErrMsg string `json:"errmsg"` 12 | ResUrl interface{} `json:"-"` 13 | } 14 | 15 | type CAddForeverOtherMaterialFormnameDesc struct { 16 | Title string `json:"title"` 17 | Introduction string `json:"introduction"` 18 | } 19 | -------------------------------------------------------------------------------- /user/struct.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | type CUserOpenIdInfo struct { 4 | OpenId []string `json:"openid"` 5 | } 6 | 7 | // is NextOpenId is "" -> over 8 | type CSingleUsers struct { 9 | ErrCode int `json:"errcode"` 10 | ErrMsg string `json:"errmsg"` 11 | Total int `json:"total"` 12 | Count int `json:"count"` 13 | Data CUserOpenIdInfo `json:"data"` 14 | NextOpenId string `json:"next_openid"` 15 | } 16 | 17 | type CGetBlackListSingle struct { 18 | BeginOpenId string `json:"begin_openid"` 19 | } 20 | -------------------------------------------------------------------------------- /store/consts.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | var ( 4 | UploadImageUrl string = "https://api.weixin.qq.com/cgi-bin/media/uploadimg" 5 | CreateStoreUrl string = "https://api.weixin.qq.com/cgi-bin/poi/addpoi" 6 | GetStoreUrl string = "https://api.weixin.qq.com/cgi-bin/poi/getpoi" 7 | GetStoreListUrl string = "https://api.weixin.qq.com/cgi-bin/poi/getpoilist" 8 | ModifyStoreUrl string = "https://api.weixin.qq.com/cgi-bin/poi/updatepoi" 9 | DeleteStoreUrl string = "https://api.weixin.qq.com/cgi-bin/poi/delpoi" 10 | GetCategoryUrl string = "http://api.weixin.qq.com/cgi-bin/poi/getwxcategory" 11 | ) 12 | -------------------------------------------------------------------------------- /example/basic/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/MwlLj/go-wechat" 6 | "github.com/MwlLj/go-wechat/common" 7 | ) 8 | 9 | var _ = fmt.Println 10 | 11 | func main() { 12 | info := common.CUserInfo{ 13 | AppId: "wxfedcab8946a21ccc", 14 | AppSecret: "7ae3cc7b23b34a7b8d8cea44f7e9177f", 15 | Port: 80, 16 | Url: "/test/wechat/hello", 17 | Token: "c0082b4d-b46f-4d67-b0eb-7a0d15dd5ef2", 18 | } 19 | wc := wechat.New(&info) 20 | wc.RegisterMsgFunc(func(reply common.IReply, msg *common.CMessage, userData interface{}) error { 21 | reply.SendMessage(msg) 22 | return nil 23 | }, nil) 24 | wc.Loop() 25 | } 26 | -------------------------------------------------------------------------------- /template/consts.go: -------------------------------------------------------------------------------- 1 | package template 2 | 3 | var ( 4 | AccessToken string = "access_token" 5 | ) 6 | 7 | var ( 8 | SetIndustryUrl string = "https://api.weixin.qq.com/cgi-bin/template/api_set_industry" 9 | GetIndustryUrl string = "https://api.weixin.qq.com/cgi-bin/template/get_industry" 10 | GetTemplateIdByTemplLibIdUrl string = "https://api.weixin.qq.com/cgi-bin/template/api_add_template" 11 | GetTemplateListUrl string = "https://api.weixin.qq.com/cgi-bin/template/get_all_private_template" 12 | DeleteTemplateUrl string = "https://api.weixin.qq.com/cgi-bin/template/del_private_template" 13 | SendTemplateMsgUrl string = "https://api.weixin.qq.com/cgi-bin/message/template/send" 14 | ) 15 | -------------------------------------------------------------------------------- /server/callbackdefault.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "github.com/MwlLj/go-wechat/common" 5 | ) 6 | 7 | type CMsgCallbackDefault struct { 8 | MsgCallback common.FuncMsgCallback 9 | } 10 | 11 | func (this *CMsgCallbackDefault) OnMessage(reply common.IReply, msg *common.CMessage, communicate common.CDataCommunicate, userData interface{}) error { 12 | return this.MsgCallback(reply, msg, communicate, userData) 13 | } 14 | 15 | type CEventCallbackDefault struct { 16 | EventCallback common.FuncEventCallback 17 | } 18 | 19 | func (this *CEventCallbackDefault) OnEvent(reply common.IReply, event *common.CEvent, communicate common.CDataCommunicate, userData interface{}) error { 20 | return this.EventCallback(reply, event, communicate, userData) 21 | } 22 | -------------------------------------------------------------------------------- /wechat.go: -------------------------------------------------------------------------------- 1 | package wechat 2 | 3 | import ( 4 | "github.com/MwlLj/go-wechat/common" 5 | "github.com/MwlLj/go-wechat/server" 6 | ) 7 | 8 | type IWeChat interface { 9 | Menu() common.IMenu 10 | Template() common.ITemplate 11 | Material() common.IMaterial 12 | User() common.IUser 13 | Store() common.IStore 14 | Shop() common.IShop 15 | Sender() common.ISender 16 | PayByPaymengCode() common.IPayByPaymentCode 17 | RegisterEvent(callback common.IEvent, userData interface{}) 18 | RegisterEventFunc(callback common.FuncEventCallback, userData interface{}) 19 | RegisterMsg(callback common.IMessage, userData interface{}) 20 | RegisterMsgFunc(callback common.FuncMsgCallback, userData interface{}) 21 | Loop() 22 | } 23 | 24 | func New(info *common.CUserInfo) IWeChat { 25 | return server.New(info) 26 | } 27 | -------------------------------------------------------------------------------- /utils/filereader.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "bufio" 5 | "os" 6 | ) 7 | 8 | func FileIsEixsts(path *string) bool { 9 | _, err := os.Stat(*path) 10 | if os.IsNotExist(err) { 11 | return false 12 | } 13 | return true 14 | } 15 | 16 | type PicturePath2StreamCallback func(buf []byte) 17 | 18 | func PicturePath2Stream(path *string, callback PicturePath2StreamCallback) error { 19 | file, err := os.Open(*path) 20 | if err != nil { 21 | return err 22 | } 23 | defer file.Close() 24 | reader := bufio.NewReader(file) 25 | for { 26 | buf := make([]byte, 1024) 27 | n, err := reader.Read(buf) 28 | if err != nil && err.Error() != "EOF" { 29 | return err 30 | } 31 | if n == 0 { 32 | break 33 | } 34 | if callback != nil { 35 | callback(buf) 36 | } 37 | } 38 | return nil 39 | } 40 | -------------------------------------------------------------------------------- /example/full/message/message.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/MwlLj/go-wechat" 5 | "github.com/MwlLj/go-wechat/common" 6 | ) 7 | 8 | type CMessageCallback struct { 9 | } 10 | 11 | func (this *CMessageCallback) OnMessage(reply common.IReply, msg *common.CMessage, communicate common.CDataCommunicate, userData interface{}) error { 12 | msg.Content = "hello struct" 13 | reply.SendMessage(msg) 14 | return nil 15 | } 16 | 17 | func RegisterMsgTest(wc wechat.IWeChat) { 18 | wc.RegisterMsg(&CMessageCallback{}, nil) 19 | } 20 | 21 | func RegisterMsgFuncTest(wc wechat.IWeChat) { 22 | wc.RegisterMsgFunc(func(reply common.IReply, msg *common.CMessage, communicate common.CDataCommunicate, userData interface{}) error { 23 | msg.Content = "hello function" 24 | reply.SendMessage(msg) 25 | return nil 26 | }, nil) 27 | } 28 | -------------------------------------------------------------------------------- /shop/consts.go: -------------------------------------------------------------------------------- 1 | package shop 2 | 3 | var ( 4 | AddCommodityUrl string = "https://api.weixin.qq.com/merchant/create" 5 | DeleteCommodityUrl string = "https://api.weixin.qq.com/merchant/del" 6 | UpdateCommodityUrl string = "https://api.weixin.qq.com/merchant/update" 7 | GetCommodityUrl string = "https://api.weixin.qq.com/merchant/get" 8 | GetCommodityByStatusUrl string = "https://api.weixin.qq.com/merchant/getbystatus" 9 | UpdateCommodityStatusUrl string = "https://api.weixin.qq.com/merchant/modproductstatus" 10 | GetSubClassesByClassifyUrl string = "https://api.weixin.qq.com/merchant/category/getsub" 11 | GetAllSkuByClassifyUrl string = "https://api.weixin.qq.com/merchant/category/getsku" 12 | GetAllPropertyByClassifyUrl string = "https://api.weixin.qq.com/merchant/category/getproperty" 13 | 14 | AddStockUrl string = "https://api.weixin.qq.com/merchant/stock/add" 15 | ReduceStockUrl string = "https://api.weixin.qq.com/merchant/stock/reduce" 16 | ) 17 | -------------------------------------------------------------------------------- /pay/struct.go: -------------------------------------------------------------------------------- 1 | package pay 2 | 3 | import ( 4 | "encoding/xml" 5 | ) 6 | 7 | type CPayByPaymentCodeRequest struct { 8 | XMLName xml.Name `xml:"xml"` 9 | AppId string `xml:"appid"` 10 | MchId string `xml:"mch_id"` 11 | DeviceInfo string `xml:"device_info"` 12 | NonceStr string `xml:"nonce_str"` 13 | Sign string `xml:"sign"` 14 | SignType string `xml:"sign_type"` 15 | Body string `xml:"body"` 16 | Detail string `xml:"detail"` 17 | Attach string `xml:"attach"` 18 | OutTradeNo string `xml:"out_trade_no"` 19 | TotalFee int `xml:"total_fee"` 20 | FeeType string `xml:"fee_type"` 21 | SpbillCreateIp string `xml:"spbill_create_ip"` 22 | GoodsTag string `xml:"goods_tag"` 23 | LimitPay string `xml:"limit_pay"` 24 | TimeStart string `xml:"time_start"` 25 | TimeExpire string `xml:"time_expire"` 26 | Receipt string `xml:"receipt"` 27 | AuthCode string `xml:"auth_code"` 28 | SceneInfo string `xml:"scene_info"` 29 | } 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-wechat 2 | 封装微信调用接口 3 | 4 | ## install 5 | go get github.com/MwlLj/go-wechat 6 | 7 | ## import 8 | import ( 9 | "github.com/MwlLj/go-wechat" 10 | "github.com/MwlLj/go-wechat/common" 11 | ) 12 | 13 | ## sample example 14 | package main 15 | 16 | import ( 17 | "fmt" 18 | "github.com/MwlLj/go-wechat" 19 | "github.com/MwlLj/go-wechat/common" 20 | ) 21 | 22 | var _ = fmt.Println 23 | 24 | func main() { 25 | info := common.CUserInfo{ 26 | AppId: "your appid", 27 | AppSecret: "your appsecret", 28 | Port: 80, 29 | Url: "/xxx", 30 | Token: "your token", 31 | } 32 | wc := wechat.New(&info) 33 | wc.RegisterMsgFunc(func(reply common.IReply, msg *common.CMessage, userData interface{}) error { 34 | reply.SendMessage(msg) 35 | return nil 36 | }, nil) 37 | wc.Loop() 38 | } 39 | 40 | ## detail example 41 | [address](https://github.com/MwlLj/go-wechat/tree/master/example/full) 42 | 43 | ### 微信公众号测试帐号开发流程 44 | 1. 进入 https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index 45 | 2. 填写基本信息 46 | appID: 自动生成 47 | appsecret: 自动生成 48 | URL: 接收微信服务器的url, 如果不配置 nginx, 必须用 80 端口(直接 http://ip/xxx) 49 | Token: 任意填写, 但是如果是正式版的公众号, 请写得复杂一些 50 | 3. 可以将上面的例子(记得将 AppId 等基本信息改成你自己的)放在远程服务器上, go run main.go 51 | 4. 点击测试帐号的 提交, 只有步骤3启动之后, 测试帐号的配置信息提交才会成功 52 | -------------------------------------------------------------------------------- /example/full/sender/sender.go: -------------------------------------------------------------------------------- 1 | package sender 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/MwlLj/go-wechat" 7 | "github.com/MwlLj/go-wechat/common" 8 | ) 9 | 10 | func GroupSendByTagTest(wc wechat.IWeChat) { 11 | send := wc.Sender() 12 | request := common.CGroupSendByTagRequest{} 13 | request.Filter = common.CGroupSendFilterInfo{IsToAll: true, TagId: 1} 14 | request.ImgText = common.CGroupSendMsgContent{MediaId: "RcnqQNVBusVo6Fx-3qGKRej6CNJlQZslLdjrdDOWd48"} 15 | request.MsgType = common.GroupSendMsgTypeImgText 16 | res, err := send.GroupSendByTag(&request, 3000) 17 | if err != nil { 18 | fmt.Println(err) 19 | return 20 | } 21 | b, err := json.Marshal(res) 22 | if err != nil { 23 | fmt.Println(err) 24 | return 25 | } 26 | fmt.Println(string(b)) 27 | } 28 | 29 | func PreviewMessageTest(wc wechat.IWeChat) { 30 | send := wc.Sender() 31 | request := common.CPreviewMessageRequest{} 32 | // request.ToWxName = "wxid_4j5jlu27drb922" 33 | request.ToWxName = "lucky-xiqiao" 34 | request.ImgText = common.CGroupSendMsgContent{MediaId: "RcnqQNVBusVo6Fx-3qGKRej6CNJlQZslLdjrdDOWd48"} 35 | request.MsgType = common.GroupSendMsgTypeImgText 36 | res, err := send.PreviewMessage(&request, 3000) 37 | if err != nil { 38 | fmt.Println(err) 39 | return 40 | } 41 | b, err := json.Marshal(res) 42 | if err != nil { 43 | fmt.Println(err) 44 | return 45 | } 46 | fmt.Println(string(b)) 47 | } 48 | -------------------------------------------------------------------------------- /sender/reply.go: -------------------------------------------------------------------------------- 1 | package sender 2 | 3 | import ( 4 | "encoding/xml" 5 | "errors" 6 | "fmt" 7 | "github.com/MwlLj/go-wechat/common" 8 | "github.com/MwlLj/go-wechat/utils" 9 | "net/http" 10 | ) 11 | 12 | type CReply struct { 13 | ToUserName common.CData 14 | FromUserName common.CData 15 | ResponseWriter http.ResponseWriter 16 | m_isSend bool 17 | } 18 | 19 | func (this *CReply) SendMessage(msg *common.CMessage) error { 20 | if msg.MsgType == "" { 21 | return errors.New("msgType is empty") 22 | } 23 | ext := utils.CCommonExt{} 24 | ext.ToUserName = this.FromUserName 25 | ext.FromUserName = this.ToUserName 26 | resXml := utils.Message2ResXml(msg, &ext) 27 | res, err := xml.MarshalIndent(&resXml, " ", " ") 28 | if err != nil { 29 | return err 30 | } 31 | this.ResponseWriter.Header().Set("Content-Type", "text/xml") 32 | _, err = fmt.Fprint(this.ResponseWriter, string(res)) 33 | if err != nil { 34 | return err 35 | } 36 | this.m_isSend = true 37 | return nil 38 | } 39 | 40 | func (this *CReply) SendEmptyMessage() error { 41 | _, err := fmt.Fprint(this.ResponseWriter, "") 42 | if err != nil { 43 | return err 44 | } 45 | this.m_isSend = true 46 | return nil 47 | } 48 | 49 | func (this *CReply) IsSend() bool { 50 | return this.m_isSend 51 | } 52 | 53 | func NewReply(toUserName *common.CData, fromUserName *common.CData, w *http.ResponseWriter) common.IReply { 54 | reply := CReply{ 55 | ToUserName: *toUserName, 56 | FromUserName: *fromUserName, 57 | ResponseWriter: *w, 58 | m_isSend: false, 59 | } 60 | return &reply 61 | } 62 | -------------------------------------------------------------------------------- /user/consts.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | var ( 4 | GetUserBaseInfoParamOpenId string = "openid" 5 | GetUserBaseInfoParamLang string = "lang" 6 | GetFollowUsersParamNextOpenId string = "next_openid" 7 | ) 8 | 9 | var ( 10 | CreateTagUrl string = "https://api.weixin.qq.com/cgi-bin/tags/create" 11 | GetTagListUrl string = "https://api.weixin.qq.com/cgi-bin/tags/get" 12 | UpdateTagUrl string = "https://api.weixin.qq.com/cgi-bin/tags/update" 13 | DeleteTagUrl string = "https://api.weixin.qq.com/cgi-bin/tags/delete" 14 | GetTagUserListUrl string = "https://api.weixin.qq.com/cgi-bin/user/tag/get" 15 | AddTagToUsersUrl string = "https://api.weixin.qq.com/cgi-bin/tags/members/batchtagging" 16 | DeleteTagToUsersUrl string = "https://api.weixin.qq.com/cgi-bin/tags/members/batchuntagging" 17 | GetTagsByUserUrl string = "https://api.weixin.qq.com/cgi-bin/tags/getidlist" 18 | 19 | UpdateUserRemarkUrl string = "https://api.weixin.qq.com/cgi-bin/user/info/updateremark" 20 | 21 | GetUserBaseInfoUrl string = "https://api.weixin.qq.com/cgi-bin/user/info" 22 | GetUserBaseInfoMultiUrl string = "https://api.weixin.qq.com/cgi-bin/user/info/batchget" 23 | 24 | GetFollowUsersUrl string = "https://api.weixin.qq.com/cgi-bin/user/get" 25 | 26 | GetBlackListUsersUrl string = "https://api.weixin.qq.com/cgi-bin/tags/members/getblacklist" 27 | TakeUsersToBlackListUrl string = "https://api.weixin.qq.com/cgi-bin/tags/members/batchblacklist" 28 | UnTakeUsersToBlackListUrl string = "https://api.weixin.qq.com/cgi-bin/tags/members/batchunblacklist" 29 | ) 30 | -------------------------------------------------------------------------------- /server/decoding.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "encoding/xml" 5 | "github.com/MwlLj/go-wechat/common" 6 | ) 7 | 8 | var ( 9 | DecodeTypeResXml string = "resxml" 10 | DecodeTypeMessage string = "message" 11 | DecodeTypeEvent string = "event" 12 | ) 13 | 14 | type IDecoding interface { 15 | Parse(body []byte) interface{} 16 | } 17 | 18 | type CDecodeParam struct { 19 | DecodeType string 20 | } 21 | 22 | type CDecodeFactory struct { 23 | } 24 | 25 | func (this *CDecodeFactory) Decoding(param *CDecodeParam) IDecoding { 26 | if param.DecodeType == DecodeTypeMessage { 27 | return &CMessageDecoding{} 28 | } else if param.DecodeType == DecodeTypeEvent { 29 | return &CEventDecoding{} 30 | } else if param.DecodeType == DecodeTypeResXml { 31 | return &CResXmlDecoding{} 32 | } 33 | return nil 34 | } 35 | 36 | type CResXmlDecoding struct { 37 | } 38 | 39 | func (this *CResXmlDecoding) Parse(body []byte) interface{} { 40 | res := common.CWxResXml{} 41 | err := xml.Unmarshal(body, &res) 42 | if err != nil { 43 | return nil 44 | } 45 | return &res 46 | } 47 | 48 | type CMessageDecoding struct { 49 | } 50 | 51 | func (this *CMessageDecoding) Parse(body []byte) interface{} { 52 | msg := common.CMessage{} 53 | err := xml.Unmarshal(body, &msg) 54 | if err != nil { 55 | return nil 56 | } 57 | return &msg 58 | } 59 | 60 | type CEventDecoding struct { 61 | } 62 | 63 | func (this *CEventDecoding) Parse(body []byte) interface{} { 64 | event := common.CEvent{} 65 | err := xml.Unmarshal(body, &event) 66 | if err != nil { 67 | return nil 68 | } 69 | return &event 70 | } 71 | -------------------------------------------------------------------------------- /material/consts.go: -------------------------------------------------------------------------------- 1 | package material 2 | 3 | var ( 4 | CreateTmpMaterialParamType string = "type" 5 | CreateTmpMaterialFormname string = "media" 6 | GetTmpMaterialResUrls []string = []string{"video_url", "image_url", "voice_url", "thumb_url", "news_url"} 7 | GetTmpMaterialParamMediaId string = "media_id" 8 | GetTmpHDMaterialParamMediaId string = "media_id" 9 | UploadImageFormname string = "media" 10 | AddOtherMaterialParamType string = "type" 11 | AddOtherMaterialFormnameMedia string = "media" 12 | AddOtherMaterialFormnameDescription string = "description" 13 | ) 14 | 15 | var ( 16 | CreateTmpMaterialUrl string = "https://api.weixin.qq.com/cgi-bin/media/upload" 17 | GetTmpMaterialUrl string = "https://api.weixin.qq.com/cgi-bin/media/get" 18 | GetTmpHDMaterialUrl string = "https://api.weixin.qq.com/cgi-bin/media/get" 19 | AddForeverImgTextMaterialUrl string = "https://api.weixin.qq.com/cgi-bin/material/add_news" 20 | UploadImageUrl string = "https://api.weixin.qq.com/cgi-bin/media/uploadimg" 21 | UploadVideoUrl string = "https://api.weixin.qq.com/cgi-bin/media/uploadvideo" 22 | AddForeverOtherMaterialUrl string = "https://api.weixin.qq.com/cgi-bin/material/add_material" 23 | GetForeverMaterialUrl string = "https://api.weixin.qq.com/cgi-bin/material/get_material" 24 | DeleteForeverMaterialUrl string = "https://api.weixin.qq.com/cgi-bin/material/del_material" 25 | UpdateForeverImgTextMaterialUrl string = "https://api.weixin.qq.com/cgi-bin/material/update_news" 26 | GetMaterialTotal string = "https://api.weixin.qq.com/cgi-bin/material/get_materialcount" 27 | GetMaterialList string = "https://api.weixin.qq.com/cgi-bin/material/batchget_material" 28 | ) 29 | -------------------------------------------------------------------------------- /example/full/menu/menu.go: -------------------------------------------------------------------------------- 1 | package menu 2 | 3 | import ( 4 | "fmt" 5 | "github.com/MwlLj/go-wechat" 6 | "github.com/MwlLj/go-wechat/common" 7 | ) 8 | 9 | func DeleteMenuTest(wc wechat.IWeChat) { 10 | menu := wc.Menu() 11 | err := menu.DeleteAll(3000) 12 | if err != nil { 13 | fmt.Println(err) 14 | return 15 | } 16 | fmt.Println("delete menu success") 17 | } 18 | 19 | func CreateMenuTest(wc wechat.IWeChat) { 20 | // data 21 | buttons := []common.CButton{} 22 | button1 := common.CButton{} 23 | button1.Name = "下单" 24 | button1.Type = common.ButtonTypeClick 25 | button1.Key = "order" 26 | buttons = append(buttons, button1) 27 | buttonSearch := common.CButton{} 28 | searchButtons := []common.CButton{} 29 | buttonSearch.Name = "搜索" 30 | baiduSearch := common.CButton{} 31 | baiduSearch.Name = "百度一下" 32 | baiduSearch.Type = common.ButtonTypeView 33 | baiduSearch.Url = "https://www.baidu.com" 34 | searchButtons = append(searchButtons, baiduSearch) 35 | sougouSearch := common.CButton{} 36 | sougouSearch.Name = "搜狗搜索" 37 | sougouSearch.Type = common.ButtonTypeView 38 | sougouSearch.Url = "http://www.sogou.com" 39 | searchButtons = append(searchButtons, sougouSearch) 40 | buttonSearch.SubButton = searchButtons 41 | buttons = append(buttons, buttonSearch) 42 | button3 := common.CButton{} 43 | button3.Name = "扫一扫" 44 | button3.Type = common.ButtonTypeScancodeWaitmsg 45 | button3.Key = "take_photo" 46 | buttons = append(buttons, button3) 47 | // create 48 | menu := wc.Menu() 49 | err := menu.Create(&buttons, 3000) 50 | if err != nil { 51 | fmt.Println(err) 52 | return 53 | } 54 | fmt.Println("create menu success") 55 | } 56 | 57 | func GetMenuTest(wc wechat.IWeChat) { 58 | menu := wc.Menu() 59 | res, err := menu.GetAll(3000) 60 | if err != nil { 61 | fmt.Println(err) 62 | return 63 | } 64 | // print 65 | var _ = res 66 | fmt.Println("get menu success") 67 | } 68 | -------------------------------------------------------------------------------- /menu/menu.go: -------------------------------------------------------------------------------- 1 | package menu 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "github.com/MwlLj/go-wechat/common" 7 | "github.com/MwlLj/go-wechat/communicate" 8 | "net/http" 9 | ) 10 | 11 | type CCommonResponse struct { 12 | ErrCode int `json:"errcode"` 13 | ErrMsg string `json:"errmsg"` 14 | } 15 | 16 | type CMenu struct { 17 | m_token common.IToken 18 | } 19 | 20 | func (this *CMenu) Create(data *[]common.CButton, timeoutMS int64) error { 21 | menu := CMenuData{Buttons: *data} 22 | b, err := json.Marshal(&menu) 23 | if err != nil { 24 | return err 25 | } 26 | method := http.MethodPost 27 | body, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &CreateMenuUrl, &method, nil, nil, b) 28 | if err != nil { 29 | return err 30 | } 31 | response := CCommonResponse{} 32 | err = json.Unmarshal(body, &response) 33 | if err != nil { 34 | return err 35 | } 36 | if response.ErrCode != common.ErrorCodeSuccess { 37 | return errors.New(response.ErrMsg) 38 | } 39 | return nil 40 | } 41 | 42 | func (this *CMenu) GetAll(timeoutMS int64) (*common.CGetMenuJson, error) { 43 | method := http.MethodGet 44 | body, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetMenuUrl, &method, nil, nil, nil) 45 | if err != nil { 46 | return nil, err 47 | } 48 | response := common.CGetMenuJson{} 49 | err = json.Unmarshal(body, &response) 50 | if err != nil { 51 | return nil, err 52 | } 53 | return &response, nil 54 | } 55 | 56 | func (this *CMenu) DeleteAll(timeoutMS int64) error { 57 | method := http.MethodGet 58 | body, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &DeleteMenuUrl, &method, nil, nil, nil) 59 | if err != nil { 60 | return err 61 | } 62 | response := CCommonResponse{} 63 | err = json.Unmarshal(body, &response) 64 | if err != nil { 65 | return err 66 | } 67 | if response.ErrCode != common.ErrorCodeSuccess { 68 | return errors.New(response.ErrMsg) 69 | } 70 | return nil 71 | } 72 | 73 | func New(token common.IToken) common.IMenu { 74 | menu := CMenu{m_token: token} 75 | return &menu 76 | } 77 | -------------------------------------------------------------------------------- /example/full/store/store.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/MwlLj/go-wechat" 7 | "github.com/MwlLj/go-wechat/common" 8 | ) 9 | 10 | func CreateStoreTest(wc wechat.IWeChat) { 11 | st := wc.Store() 12 | info := common.CStoreBaseInfo{} 13 | request := common.CCreateStoreRequest{Business: common.CStoreBusiness{BaseInfo: info}} 14 | err := st.CreateStore(&request, 3000) 15 | if err != nil { 16 | fmt.Println(err) 17 | return 18 | } 19 | fmt.Println("success") 20 | } 21 | 22 | func GetStoreTest(wc wechat.IWeChat) { 23 | st := wc.Store() 24 | request := common.CGetStoreRequest{} 25 | res, err := st.GetStore(&request, 3000) 26 | if err != nil { 27 | fmt.Println(err) 28 | return 29 | } 30 | b, err := json.Marshal(res) 31 | if err != nil { 32 | fmt.Println(err) 33 | return 34 | } 35 | fmt.Println(string(b)) 36 | } 37 | 38 | func GetStoreListTest(wc wechat.IWeChat) { 39 | st := wc.Store() 40 | request := common.CGetStoreListRequest{} 41 | res, err := st.GetStoreList(&request, 3000) 42 | if err != nil { 43 | fmt.Println(err) 44 | return 45 | } 46 | b, err := json.Marshal(res) 47 | if err != nil { 48 | fmt.Println(err) 49 | return 50 | } 51 | fmt.Println(string(b)) 52 | } 53 | 54 | func ModifyStoreTest(wc wechat.IWeChat) { 55 | st := wc.Store() 56 | request := common.CModifyStoreRequest{} 57 | err := st.ModifyStore(&request, 3000) 58 | if err != nil { 59 | fmt.Println(err) 60 | return 61 | } 62 | fmt.Println("success") 63 | } 64 | 65 | func DeleteStoreTest(wc wechat.IWeChat) { 66 | st := wc.Store() 67 | request := common.CDeleteStoreRequest{} 68 | err := st.DeleteStore(&request, 3000) 69 | if err != nil { 70 | fmt.Println(err) 71 | return 72 | } 73 | fmt.Println("success") 74 | } 75 | 76 | func GetCategoryTest(wc wechat.IWeChat) { 77 | st := wc.Store() 78 | res, err := st.GetCategory(3000) 79 | if err != nil { 80 | fmt.Println(err) 81 | return 82 | } 83 | b, err := json.Marshal(res) 84 | if err != nil { 85 | fmt.Println(err) 86 | return 87 | } 88 | fmt.Println(string(b)) 89 | } 90 | -------------------------------------------------------------------------------- /pay/paymentcode.go: -------------------------------------------------------------------------------- 1 | package pay 2 | 3 | import ( 4 | "encoding/xml" 5 | "errors" 6 | "github.com/MwlLj/go-wechat/common" 7 | "github.com/MwlLj/go-wechat/communicate" 8 | "github.com/MwlLj/go-wechat/private" 9 | "net/http" 10 | "strconv" 11 | ) 12 | 13 | type CPayByPaymentCode struct { 14 | m_token common.IToken 15 | } 16 | 17 | func (this *CPayByPaymentCode) Commit(request *common.CPayByPaymentCodeRequest, timeoutMS int64) (*common.CPayByPaymentCodeResponse, error) { 18 | req := CPayByPaymentCodeRequest{} 19 | info := this.m_token.GetUserInfo() 20 | req.AppId = info.AppId 21 | req.Attach = request.Attach 22 | req.AuthCode = request.AuthCode 23 | req.Body = request.Body 24 | req.Detail = request.Detail 25 | req.DeviceInfo = request.DeviceInfo 26 | req.FeeType = request.FeeType 27 | req.GoodsTag = request.GoodsTag 28 | req.LimitPay = request.LimitPay 29 | req.MchId = request.MchId 30 | req.NonceStr = string(genRandomString(32)) 31 | req.OutTradeNo = request.OutTradeNo 32 | req.Receipt = request.Receipt 33 | req.SceneInfo = request.SceneInfo 34 | req.SignType = request.SignType 35 | req.SpbillCreateIp = request.SpbillCreateIp 36 | req.TimeExpire = request.TimeExpire 37 | req.TimeStart = request.TimeStart 38 | req.TotalFee = request.TotalFee 39 | sign, err := signValidateByStruct(&req, &request.Key, &request.SignType) 40 | if err != nil { 41 | return nil, err 42 | } 43 | req.Sign = *sign 44 | b, err := xml.Marshal(&req) 45 | if err != nil { 46 | return nil, err 47 | } 48 | method := http.MethodPost 49 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &PayByPaymentCodeCommitUrl, &method, nil, nil, b) 50 | if err != nil { 51 | return nil, err 52 | } 53 | response := common.CPayByPaymentCodeResponse{} 54 | err = xml.Unmarshal(resBody, &response) 55 | if err != nil { 56 | return nil, err 57 | } 58 | if response.ReturnCode != strconv.FormatInt(int64(private.ErrorCodeSuccess), 10) { 59 | return nil, errors.New(response.ReturnMsg) 60 | } 61 | return &response, nil 62 | } 63 | 64 | func (this *CPayByPaymentCode) QueryOrder() { 65 | } 66 | 67 | func NewPayByPaymentCode(token common.IToken) common.IPayByPaymentCode { 68 | pay := CPayByPaymentCode{m_token: token} 69 | return &pay 70 | } 71 | -------------------------------------------------------------------------------- /example/full/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/MwlLj/go-wechat" 6 | "github.com/MwlLj/go-wechat/common" 7 | "github.com/MwlLj/go-wechat/example/full/event" 8 | "github.com/MwlLj/go-wechat/example/full/material" 9 | "github.com/MwlLj/go-wechat/example/full/menu" 10 | "github.com/MwlLj/go-wechat/example/full/message" 11 | "github.com/MwlLj/go-wechat/example/full/sender" 12 | "github.com/MwlLj/go-wechat/example/full/store" 13 | "github.com/MwlLj/go-wechat/example/full/template" 14 | "github.com/MwlLj/go-wechat/example/full/user" 15 | ) 16 | 17 | var _ = fmt.Println 18 | 19 | func messageTest(wc wechat.IWeChat) { 20 | message.RegisterMsgTest(wc) 21 | message.RegisterMsgFuncTest(wc) 22 | } 23 | 24 | func eventTest(wc wechat.IWeChat) { 25 | event.RegisterEventTest(wc) 26 | } 27 | 28 | func menuTest(wc wechat.IWeChat) { 29 | menu.DeleteMenuTest(wc) 30 | menu.CreateMenuTest(wc) 31 | menu.GetMenuTest(wc) 32 | } 33 | 34 | func templateTest(wc wechat.IWeChat) { 35 | // template.SetIndustryTest(wc) 36 | // template.GetIndustryTest(wc) 37 | // template.GetTemplateListTest(wc) 38 | template.SendTemplateMsgTest(wc) 39 | } 40 | 41 | func materialTest(wc wechat.IWeChat) { 42 | // material.UploadImageTest(wc) 43 | // material.AddForeverOtherMaterialTest(wc) 44 | material.AddForeverImgTextMaterialTest(wc) 45 | material.GetMaterialTotalTest(wc) 46 | material.GetMaterialListTest(wc) 47 | } 48 | 49 | func userTest(wc wechat.IWeChat) { 50 | user.GetFollowUsersTest(wc) 51 | } 52 | 53 | func storeTest(wc wechat.IWeChat) { 54 | // store.UploadImageTest(wc) 55 | store.CreateStoreTest(wc) 56 | } 57 | 58 | func senderTest(wc wechat.IWeChat) { 59 | // sender.GroupSendByTagTest(wc) 60 | sender.PreviewMessageTest(wc) 61 | } 62 | 63 | func main() { 64 | info := common.CUserInfo{ 65 | // AppId: "wxfedcab8946a21ccc", 66 | AppSecret: "7ae3cc7b23b34a7b8d8cea44f7e9177f", 67 | Port: 80, 68 | Url: "/test/wechat/hello", 69 | Token: "c0082b4d-b46f-4d67-b0eb-7a0d15dd5ef2", 70 | } 71 | wc := wechat.New(&info) 72 | // message test 73 | messageTest(wc) 74 | // event test 75 | eventTest(wc) 76 | // menu test 77 | // menuTest(wc) 78 | // template test 79 | templateTest(wc) 80 | // material test 81 | // materialTest(wc) 82 | // user test 83 | // userTest(wc) 84 | // store test 85 | // storeTest(wc) 86 | // sender test 87 | senderTest(wc) 88 | wc.Loop() 89 | } 90 | -------------------------------------------------------------------------------- /example/full/template/template.go: -------------------------------------------------------------------------------- 1 | package template 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/MwlLj/go-wechat" 7 | "github.com/MwlLj/go-wechat/common" 8 | "time" 9 | ) 10 | 11 | func SetIndustryTest(wc wechat.IWeChat) { 12 | tl := wc.Template() 13 | request := common.CSetIndustryRequest{} 14 | request.FirstIndustryId = "1" 15 | request.SecondIndustryId = "2" 16 | err := tl.SetIndustry(&request, 3000) 17 | if err != nil { 18 | fmt.Println(err) 19 | return 20 | } 21 | } 22 | 23 | func GetIndustryTest(wc wechat.IWeChat) { 24 | tl := wc.Template() 25 | response, err := tl.GetIndustry(3000) 26 | if err != nil { 27 | fmt.Println(err) 28 | return 29 | } 30 | b, err := json.Marshal(response) 31 | if err != nil { 32 | fmt.Println(err) 33 | return 34 | } 35 | fmt.Println(string(b)) 36 | } 37 | 38 | func GetTemplateListTest(wc wechat.IWeChat) { 39 | tl := wc.Template() 40 | response, err := tl.GetTemplateList(3000) 41 | if err != nil { 42 | fmt.Println(err) 43 | return 44 | } 45 | b, err := json.Marshal(response) 46 | if err != nil { 47 | fmt.Println(err) 48 | return 49 | } 50 | fmt.Println(string(b)) 51 | } 52 | 53 | func getNowSecondFormat() string { 54 | timeUnix := time.Now().Unix() 55 | return time.Unix(timeUnix, 0).Format("2006-01-02 15:04:05") 56 | } 57 | 58 | func SendTemplateMsgTest(wc wechat.IWeChat) { 59 | tl := wc.Template() 60 | wc.RegisterEventFunc(func(reply common.IReply, event *common.CEvent, communicate common.CDataCommunicate, userData interface{}) error { 61 | if event.EventKey == "order" { 62 | request := common.CSendTemplateMsgRequest{} 63 | request.Touser = communicate.FromUserName 64 | request.TemplateId = "SOni-e9rT401RT1MiZ8gA9gPQwZImxuFduin9XMM8Ko" 65 | request.Url = "https://www.baidu.com" 66 | items := make(map[string]common.CTemplateMessageItem) 67 | items["first"] = common.CTemplateMessageItem{Value: "恭喜你购买成功", Color: "#173177"} 68 | items["product"] = common.CTemplateMessageItem{Value: "巧克力", Color: "#173177"} 69 | items["amount"] = common.CTemplateMessageItem{Value: "39.8元", Color: "#173177"} 70 | items["time"] = common.CTemplateMessageItem{Value: getNowSecondFormat(), Color: "#173177"} 71 | items["remark"] = common.CTemplateMessageItem{Value: "欢迎再次购买", Color: "#173177"} 72 | request.Data = items 73 | response, err := tl.SendTemplateMsg(&request, 3000) 74 | if err != nil { 75 | fmt.Println(err) 76 | return err 77 | } 78 | b, err := json.Marshal(response) 79 | if err != nil { 80 | fmt.Println(err) 81 | return err 82 | } 83 | var _ = b 84 | } 85 | return nil 86 | }, nil) 87 | } 88 | -------------------------------------------------------------------------------- /example/full/material/material.go: -------------------------------------------------------------------------------- 1 | package material 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/MwlLj/go-wechat" 7 | "github.com/MwlLj/go-wechat/common" 8 | ) 9 | 10 | func AddForeverOtherMaterialTest(wc wechat.IWeChat) { 11 | media := wc.Material() 12 | request := common.CAddForeverOtherMaterialRequest{} 13 | request.MaterialType = common.MaterialTypeImage 14 | request.Path = "./testresource/test.jpg" 15 | request.Title = "考拉资讯" 16 | request.Introduction = "考拉 ... 考拉 ..." 17 | res, err := media.AddForeverOtherMaterial(&request, 3000) 18 | if err != nil { 19 | fmt.Println(err) 20 | return 21 | } 22 | b, err := json.Marshal(res) 23 | if err != nil { 24 | fmt.Println(err) 25 | return 26 | } 27 | fmt.Println(string(b)) 28 | } 29 | 30 | func AddForeverImgTextMaterialTest(wc wechat.IWeChat) { 31 | media := wc.Material() 32 | request := common.CAddForeverImgTextMaterialRequest{} 33 | articles := []common.CImgTextMaterial{} 34 | article := common.CImgTextMaterial{} 35 | article.Title = "测试" 36 | article.ThumbMediaId = "RcnqQNVBusVo6Fx-3qGKRRueLS_k6vJ8gXqbhgfkzmQ" 37 | article.ShowCoverPic = 1 38 | article.Content = "Hello World" 39 | article.ContentSourceUrl = "https://www.baidu.com" 40 | articles = append(articles, article) 41 | request.Articles = articles 42 | res, err := media.AddForeverImgTextMaterial(&request, 3000) 43 | if err != nil { 44 | fmt.Println(err) 45 | return 46 | } 47 | b, err := json.Marshal(res) 48 | if err != nil { 49 | fmt.Println(err) 50 | return 51 | } 52 | fmt.Println(string(b)) 53 | } 54 | 55 | func UploadImageTest(wc wechat.IWeChat) { 56 | media := wc.Material() 57 | path := "./testresource/test.jpg" 58 | res, err := media.UploadImage(&path, 3000) 59 | if err != nil { 60 | fmt.Println(err) 61 | return 62 | } 63 | b, err := json.Marshal(res) 64 | if err != nil { 65 | fmt.Println(err) 66 | return 67 | } 68 | fmt.Println(string(b)) 69 | } 70 | 71 | func GetMaterialTotalTest(wc wechat.IWeChat) { 72 | media := wc.Material() 73 | res, err := media.GetMaterialTotal(3000) 74 | if err != nil { 75 | fmt.Println(err) 76 | return 77 | } 78 | b, err := json.Marshal(res) 79 | if err != nil { 80 | fmt.Println(err) 81 | return 82 | } 83 | fmt.Println(string(b)) 84 | } 85 | 86 | func GetMaterialListTest(wc wechat.IWeChat) { 87 | media := wc.Material() 88 | request := common.CGetMaterialListRequest{} 89 | request.Type = common.MaterialTypeImgText 90 | request.Offset = 0 91 | request.Count = 20 92 | res, err := media.GetMaterialList(&request, 3000) 93 | if err != nil { 94 | fmt.Println(err) 95 | return 96 | } 97 | b, err := json.Marshal(res) 98 | if err != nil { 99 | fmt.Println(err) 100 | return 101 | } 102 | fmt.Println(string(b)) 103 | } 104 | -------------------------------------------------------------------------------- /sender/sender.go: -------------------------------------------------------------------------------- 1 | package sender 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "github.com/MwlLj/go-wechat/common" 7 | "github.com/MwlLj/go-wechat/communicate" 8 | "github.com/MwlLj/go-wechat/private" 9 | "net/http" 10 | ) 11 | 12 | type CSender struct { 13 | m_token common.IToken 14 | } 15 | 16 | func (this *CSender) GroupSendByTag(request *common.CGroupSendByTagRequest, timeoutMS int64) (*common.CGroupSendByTagResponse, error) { 17 | b, err := json.Marshal(request) 18 | if err != nil { 19 | return nil, err 20 | } 21 | method := http.MethodPost 22 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GroupSendByTagUrl, &method, nil, nil, b) 23 | if err != nil { 24 | return nil, err 25 | } 26 | response := common.CGroupSendByTagResponse{} 27 | err = json.Unmarshal(resBody, &response) 28 | if err != nil { 29 | return nil, err 30 | } 31 | if response.ErrCode != private.ErrorCodeSuccess { 32 | return nil, errors.New(response.ErrMsg) 33 | } 34 | return &response, nil 35 | } 36 | 37 | func (this *CSender) GroupSendByOpenIds(request *common.CGroupSendByOpenIdsRequest, timeoutMS int64) (*common.CGroupSendByTagResponse, error) { 38 | b, err := json.Marshal(request) 39 | if err != nil { 40 | return nil, err 41 | } 42 | method := http.MethodPost 43 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GroupSendByTagUrl, &method, nil, nil, b) 44 | if err != nil { 45 | return nil, err 46 | } 47 | response := common.CGroupSendByTagResponse{} 48 | err = json.Unmarshal(resBody, &response) 49 | if err != nil { 50 | return nil, err 51 | } 52 | if response.ErrCode != private.ErrorCodeSuccess { 53 | return nil, errors.New(response.ErrMsg) 54 | } 55 | return &response, nil 56 | } 57 | 58 | func (this *CSender) DeleteGroupSend(request *common.CDeleteGroupSendRequest, timeoutMS int64) error { 59 | b, err := json.Marshal(request) 60 | if err != nil { 61 | return err 62 | } 63 | method := http.MethodPost 64 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &DeleteGroupSendUrl, &method, nil, nil, b) 65 | if err != nil { 66 | return err 67 | } 68 | response := private.CCommonResponse{} 69 | err = json.Unmarshal(resBody, &response) 70 | if err != nil { 71 | return err 72 | } 73 | if response.ErrCode != private.ErrorCodeSuccess { 74 | return errors.New(response.ErrMsg) 75 | } 76 | return nil 77 | } 78 | 79 | func (this *CSender) PreviewMessage(request *common.CPreviewMessageRequest, timeoutMS int64) (*common.CPreviewMessageResponse, error) { 80 | b, err := json.Marshal(request) 81 | if err != nil { 82 | return nil, err 83 | } 84 | method := http.MethodPost 85 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &PreviewMessageUrl, &method, nil, nil, b) 86 | if err != nil { 87 | return nil, err 88 | } 89 | response := common.CPreviewMessageResponse{} 90 | err = json.Unmarshal(resBody, &response) 91 | if err != nil { 92 | return nil, err 93 | } 94 | if response.ErrCode != private.ErrorCodeSuccess { 95 | return nil, errors.New(response.ErrMsg) 96 | } 97 | return &response, nil 98 | } 99 | 100 | func New(token common.IToken) common.ISender { 101 | sender := CSender{m_token: token} 102 | return &sender 103 | } 104 | -------------------------------------------------------------------------------- /utils/change.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "github.com/MwlLj/go-wechat/common" 5 | ) 6 | 7 | type CCommonExt struct { 8 | ToUserName common.CData 9 | FromUserName common.CData 10 | } 11 | 12 | func ResXml2DataCommunicate(resXml *common.CWxResXml) *common.CDataCommunicate { 13 | communicate := common.CDataCommunicate{} 14 | communicate.ToUserName = string(resXml.ToUserName) 15 | communicate.FromUserName = string(resXml.FromUserName) 16 | return &communicate 17 | } 18 | 19 | func DataCommunicate2ResXml(communicate *common.CDataCommunicate) *common.CWxResXml { 20 | resXml := common.CWxResXml{} 21 | resXml.ToUserName = common.CData(communicate.ToUserName) 22 | resXml.FromUserName = common.CData(communicate.FromUserName) 23 | return &resXml 24 | } 25 | 26 | func ResXml2Message(resXml *common.CWxResXml) *common.CMessage { 27 | msg := common.CMessage{} 28 | msg.CreateTime = resXml.CreateTime 29 | msg.MsgType = string(resXml.MsgType) 30 | msg.MsgId = resXml.MsgId 31 | msg.Content = string(resXml.Content) 32 | msg.PicUrl = string(resXml.PicUrl) 33 | msg.MediaId = resXml.MediaId 34 | msg.Format = string(resXml.Format) 35 | msg.ThumbMediaId = string(resXml.ThumbMediaId) 36 | msg.LocationX = resXml.Location_X 37 | msg.LocationY = resXml.Location_Y 38 | msg.Scale = resXml.Scale 39 | msg.Label = string(resXml.Label) 40 | msg.Title = string(resXml.Title) 41 | msg.Description = string(resXml.Description) 42 | msg.Url = string(resXml.Url) 43 | return &msg 44 | } 45 | 46 | func Message2ResXml(msg *common.CMessage, ext *CCommonExt) *common.CWxResXml { 47 | resXml := common.CWxResXml{} 48 | resXml.ToUserName = ext.ToUserName 49 | resXml.FromUserName = ext.FromUserName 50 | resXml.CreateTime = msg.CreateTime 51 | resXml.MsgType = common.CData(msg.MsgType) 52 | resXml.MsgId = msg.MsgId 53 | resXml.Content = common.CData(msg.Content) 54 | resXml.PicUrl = common.CData(msg.PicUrl) 55 | resXml.MediaId = msg.MediaId 56 | resXml.Format = common.CData(msg.Format) 57 | resXml.ThumbMediaId = common.CData(msg.ThumbMediaId) 58 | resXml.Location_X = msg.LocationX 59 | resXml.Location_Y = msg.LocationY 60 | resXml.Scale = msg.Scale 61 | resXml.Label = common.CData(msg.Label) 62 | resXml.Title = common.CData(msg.Title) 63 | resXml.Description = common.CData(msg.Description) 64 | resXml.Url = common.CData(msg.Url) 65 | return &resXml 66 | } 67 | 68 | func ResXml2Event(resXml *common.CWxResXml) *common.CEvent { 69 | event := common.CEvent{} 70 | event.CreateTime = resXml.CreateTime 71 | event.MsgType = string(resXml.MsgType) 72 | event.Event = string(resXml.Event) 73 | event.EventKey = string(resXml.EventKey) 74 | event.Ticket = string(resXml.Ticket) 75 | event.Latitude = resXml.Latitude 76 | event.Longitude = resXml.Longitude 77 | event.Precision = resXml.Precision 78 | event.Status = string(resXml.Status) 79 | return &event 80 | } 81 | 82 | func Event2ResXml(event *common.CEvent, ext *CCommonExt) *common.CWxResXml { 83 | resXml := common.CWxResXml{} 84 | resXml.ToUserName = ext.ToUserName 85 | resXml.FromUserName = ext.FromUserName 86 | resXml.CreateTime = event.CreateTime 87 | resXml.MsgType = common.CData(event.MsgType) 88 | resXml.Event = common.CData(event.Event) 89 | resXml.EventKey = common.CData(event.EventKey) 90 | resXml.Ticket = common.CData(event.Ticket) 91 | resXml.Latitude = event.Latitude 92 | resXml.Longitude = event.Longitude 93 | resXml.Precision = event.Precision 94 | resXml.Status = common.CData(event.Status) 95 | return &resXml 96 | } 97 | -------------------------------------------------------------------------------- /token/token.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "fmt" 7 | "github.com/MwlLj/go-wechat/common" 8 | "io/ioutil" 9 | "net/http" 10 | "time" 11 | ) 12 | 13 | type CTokenJson struct { 14 | AccessToken string `json:"access_token"` 15 | ExpiresIn int `json:"expires_in"` 16 | ErrCode int `json:"errcode"` 17 | ErrMsg string `json:"errmsg"` 18 | } 19 | 20 | type CToken struct { 21 | m_tokenJson CTokenJson 22 | m_userInfo common.CUserInfo 23 | m_isVaild bool 24 | m_updateTokenChannel chan bool 25 | } 26 | 27 | func (this *CToken) GetUserInfo() *common.CUserInfo { 28 | return &this.m_userInfo 29 | } 30 | 31 | func (this *CToken) GetToken(timeoutMS int64) (token []byte, e error) { 32 | var isTimeout bool = false 33 | if this.m_isVaild == false { 34 | if timeoutMS <= 0 { 35 | return nil, errors.New("token is vaild") 36 | } else { 37 | t := time.After(time.Duration(timeoutMS) * time.Millisecond) 38 | end: 39 | for { 40 | if this.m_isVaild == true { 41 | isTimeout = false 42 | break end 43 | } 44 | select { 45 | case <-t: 46 | isTimeout = true 47 | break end 48 | default: 49 | } 50 | time.Sleep(100 * time.Millisecond) 51 | } 52 | } 53 | } 54 | if isTimeout == true { 55 | return nil, errors.New("timeout") 56 | } 57 | return []byte(this.m_tokenJson.AccessToken), nil 58 | } 59 | 60 | func (this *CToken) UpdateToken(timeoutMS int64) (token []byte, e error) { 61 | this.m_updateTokenChannel <- true 62 | this.m_isVaild = false 63 | return this.GetToken(timeoutMS) 64 | } 65 | 66 | func (this *CToken) init(info *common.CUserInfo) { 67 | this.m_userInfo = *info 68 | this.m_updateTokenChannel = make(chan bool, 1) 69 | this.m_isVaild = false 70 | go func() { 71 | for { 72 | err := this.sendTokenRequest(info) 73 | if err != nil || this.m_tokenJson.AccessToken == "" { 74 | fmt.Println(err) 75 | time.Sleep(100 * time.Millisecond) 76 | continue 77 | } 78 | select { 79 | case <-this.m_updateTokenChannel: 80 | fmt.Println("[INFO] update token request") 81 | case <-time.After(time.Duration(this.m_tokenJson.ExpiresIn) * time.Second): 82 | this.m_isVaild = false 83 | fmt.Println("[INFO] token timeout") 84 | } 85 | } 86 | }() 87 | } 88 | 89 | func (this *CToken) sendTokenRequest(info *common.CUserInfo) error { 90 | url := GetTokenUrl 91 | req, err := http.NewRequest(http.MethodGet, url, nil) 92 | if err != nil { 93 | this.m_isVaild = false 94 | return err 95 | } 96 | values := req.URL.Query() 97 | values.Add(GrantType, ClientCredential) 98 | values.Add(AppId, info.AppId) 99 | values.Add(AppSecret, info.AppSecret) 100 | req.URL.RawQuery = values.Encode() 101 | res, err := http.DefaultClient.Do(req) 102 | if err != nil { 103 | this.m_isVaild = false 104 | return err 105 | } 106 | defer res.Body.Close() 107 | body, err := ioutil.ReadAll(res.Body) 108 | if err != nil { 109 | this.m_isVaild = false 110 | return err 111 | } 112 | err = json.Unmarshal(body, &this.m_tokenJson) 113 | if err != nil { 114 | this.m_isVaild = false 115 | return err 116 | } 117 | if this.m_tokenJson.ErrCode != common.ErrorCodeSuccess { 118 | this.m_isVaild = false 119 | return errors.New(this.m_tokenJson.ErrMsg) 120 | } 121 | this.m_isVaild = true 122 | return nil 123 | } 124 | 125 | func New(info *common.CUserInfo) common.IToken { 126 | t := CToken{} 127 | t.init(info) 128 | return &t 129 | } 130 | -------------------------------------------------------------------------------- /communicate/http.go: -------------------------------------------------------------------------------- 1 | package communicate 2 | 3 | import ( 4 | "bytes" 5 | "github.com/MwlLj/go-wechat/common" 6 | "io" 7 | "io/ioutil" 8 | "mime/multipart" 9 | "net/http" 10 | "os" 11 | "strings" 12 | ) 13 | 14 | var ( 15 | MultiDataTypeFile string = "file" 16 | MultiDataTypeText string = "text" 17 | ) 18 | 19 | type CMultiData struct { 20 | Type string 21 | FormName string 22 | ValueOrFilename string 23 | } 24 | 25 | func SendRequestWithToken(itoken common.IToken, timeoutMS int64, url *string, method *string, params *map[string]string, headers *map[string]string, payload []byte) (resBody []byte, e error) { 26 | var err error = nil 27 | token, err := itoken.GetToken(timeoutMS) 28 | if err != nil { 29 | return nil, err 30 | } 31 | var req *http.Request = nil 32 | if payload == nil { 33 | req, err = http.NewRequest(*method, *url, nil) 34 | } else { 35 | reader := strings.NewReader(string(payload)) 36 | req, err = http.NewRequest(*method, *url, reader) 37 | } 38 | if err != nil { 39 | return nil, err 40 | } 41 | values := req.URL.Query() 42 | values.Add(AccessToken, string(token)) 43 | if params != nil { 44 | for k, v := range *params { 45 | values.Add(k, v) 46 | } 47 | } 48 | req.URL.RawQuery = values.Encode() 49 | if headers != nil { 50 | for k, v := range *headers { 51 | req.Header.Add(k, v) 52 | } 53 | } 54 | res, err := http.DefaultClient.Do(req) 55 | if err != nil { 56 | return nil, err 57 | } 58 | defer res.Body.Close() 59 | return ioutil.ReadAll(res.Body) 60 | } 61 | 62 | func UploadFileWithToken(itoken common.IToken, timeoutMS int64, multiData *[]CMultiData, targetUrl *string, params *map[string]string, headers *map[string]string) (res []byte, e error) { 63 | token, err := itoken.GetToken(timeoutMS) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return SendMultiFormData(token, multiData, targetUrl, params, headers) 68 | } 69 | 70 | func SendMultiFormData(token []byte, multiData *[]CMultiData, targetUrl *string, params *map[string]string, headers *map[string]string) (res []byte, e error) { 71 | bodyBuf := &bytes.Buffer{} 72 | bodyWriter := multipart.NewWriter(bodyBuf) 73 | for _, multi := range *multiData { 74 | switch multi.Type { 75 | case MultiDataTypeFile: 76 | fileWriter, err := bodyWriter.CreateFormFile(multi.FormName, multi.ValueOrFilename) 77 | if err != nil { 78 | return nil, err 79 | } 80 | fh, err := os.Open(multi.ValueOrFilename) 81 | if err != nil { 82 | return nil, err 83 | } 84 | defer fh.Close() 85 | _, err = io.Copy(fileWriter, fh) 86 | if err != nil { 87 | return nil, err 88 | } 89 | case MultiDataTypeText: 90 | valueWriter, err := bodyWriter.CreateFormField(multi.FormName) 91 | if err != nil { 92 | return nil, err 93 | } 94 | valueReader := bytes.NewReader([]byte(multi.ValueOrFilename)) 95 | _, err = io.Copy(valueWriter, valueReader) 96 | if err != nil { 97 | return nil, err 98 | } 99 | } 100 | } 101 | contentType := bodyWriter.FormDataContentType() 102 | bodyWriter.Close() 103 | request, err := http.NewRequest(http.MethodPost, *targetUrl, bodyBuf) 104 | values := request.URL.Query() 105 | values.Add(AccessToken, string(token)) 106 | if params != nil { 107 | for k, v := range *params { 108 | values.Add(k, v) 109 | } 110 | } 111 | request.URL.RawQuery = values.Encode() 112 | request.Header.Set("Content-Type", contentType) 113 | if headers != nil { 114 | for k, v := range *headers { 115 | request.Header.Add(k, v) 116 | } 117 | } 118 | resp, err := http.DefaultClient.Do(request) 119 | if err != nil { 120 | return nil, err 121 | } 122 | defer resp.Body.Close() 123 | resBody, err := ioutil.ReadAll(resp.Body) 124 | if err != nil { 125 | return nil, err 126 | } 127 | return resBody, nil 128 | } 129 | -------------------------------------------------------------------------------- /store/store.go: -------------------------------------------------------------------------------- 1 | package store 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "github.com/MwlLj/go-wechat/common" 7 | "github.com/MwlLj/go-wechat/communicate" 8 | "github.com/MwlLj/go-wechat/private" 9 | "net/http" 10 | ) 11 | 12 | type CStore struct { 13 | m_token common.IToken 14 | } 15 | 16 | func (this *CStore) CreateStore(request *common.CCreateStoreRequest, timeoutMS int64) error { 17 | b, err := json.Marshal(request) 18 | if err != nil { 19 | return err 20 | } 21 | method := http.MethodPost 22 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &CreateStoreUrl, &method, nil, nil, b) 23 | if err != nil { 24 | return err 25 | } 26 | response := private.CCommonResponse{} 27 | err = json.Unmarshal(resBody, &response) 28 | if err != nil { 29 | return err 30 | } 31 | if response.ErrCode != private.ErrorCodeSuccess { 32 | return errors.New(response.ErrMsg) 33 | } 34 | return nil 35 | } 36 | 37 | func (this *CStore) GetStore(request *common.CGetStoreRequest, timeoutMS int64) (*common.CGetStoreResponse, error) { 38 | b, err := json.Marshal(request) 39 | if err != nil { 40 | return nil, err 41 | } 42 | method := http.MethodPost 43 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetStoreUrl, &method, nil, nil, b) 44 | if err != nil { 45 | return nil, err 46 | } 47 | response := common.CGetStoreResponse{} 48 | err = json.Unmarshal(resBody, &response) 49 | if err != nil { 50 | return nil, err 51 | } 52 | if response.ErrCode != private.ErrorCodeSuccess { 53 | return nil, errors.New(response.ErrMsg) 54 | } 55 | return &response, nil 56 | } 57 | 58 | func (this *CStore) GetStoreList(request *common.CGetStoreListRequest, timeoutMS int64) (*common.CGetStoreListResponse, error) { 59 | b, err := json.Marshal(request) 60 | if err != nil { 61 | return nil, err 62 | } 63 | method := http.MethodPost 64 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetStoreListUrl, &method, nil, nil, b) 65 | if err != nil { 66 | return nil, err 67 | } 68 | response := common.CGetStoreListResponse{} 69 | err = json.Unmarshal(resBody, &response) 70 | if err != nil { 71 | return nil, err 72 | } 73 | if response.ErrCode != private.ErrorCodeSuccess { 74 | return nil, errors.New(response.ErrMsg) 75 | } 76 | return &response, nil 77 | } 78 | 79 | func (this *CStore) ModifyStore(request *common.CModifyStoreRequest, timeoutMS int64) error { 80 | b, err := json.Marshal(request) 81 | if err != nil { 82 | return err 83 | } 84 | method := http.MethodPost 85 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &ModifyStoreUrl, &method, nil, nil, b) 86 | if err != nil { 87 | return err 88 | } 89 | response := private.CCommonResponse{} 90 | err = json.Unmarshal(resBody, &response) 91 | if err != nil { 92 | return err 93 | } 94 | if response.ErrCode != private.ErrorCodeSuccess { 95 | return errors.New(response.ErrMsg) 96 | } 97 | return nil 98 | } 99 | 100 | func (this *CStore) DeleteStore(request *common.CDeleteStoreRequest, timeoutMS int64) error { 101 | b, err := json.Marshal(request) 102 | if err != nil { 103 | return err 104 | } 105 | method := http.MethodPost 106 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &DeleteStoreUrl, &method, nil, nil, b) 107 | if err != nil { 108 | return err 109 | } 110 | response := private.CCommonResponse{} 111 | err = json.Unmarshal(resBody, &response) 112 | if err != nil { 113 | return err 114 | } 115 | if response.ErrCode != private.ErrorCodeSuccess { 116 | return errors.New(response.ErrMsg) 117 | } 118 | return nil 119 | } 120 | 121 | func (this *CStore) GetCategory(timeoutMS int64) (*common.CGetCategoryResponse, error) { 122 | method := http.MethodGet 123 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetCategoryUrl, &method, nil, nil, nil) 124 | if err != nil { 125 | return nil, err 126 | } 127 | response := common.CGetCategoryResponse{} 128 | err = json.Unmarshal(resBody, &response) 129 | if err != nil { 130 | return nil, err 131 | } 132 | if response.ErrCode != private.ErrorCodeSuccess { 133 | return nil, errors.New(response.ErrMsg) 134 | } 135 | return &response, nil 136 | } 137 | 138 | func New(token common.IToken) common.IStore { 139 | s := CStore{ 140 | m_token: token, 141 | } 142 | return &s 143 | } 144 | -------------------------------------------------------------------------------- /template/template.go: -------------------------------------------------------------------------------- 1 | package template 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "fmt" 7 | "github.com/MwlLj/go-wechat/common" 8 | "github.com/MwlLj/go-wechat/communicate" 9 | "net/http" 10 | ) 11 | 12 | var _ = fmt.Println 13 | 14 | type CTemplate struct { 15 | m_token common.IToken 16 | } 17 | 18 | func (this *CTemplate) SetIndustry(request *common.CSetIndustryRequest, timeoutMS int64) error { 19 | b, err := json.Marshal(request) 20 | if err != nil { 21 | return err 22 | } 23 | method := http.MethodPost 24 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &SetIndustryUrl, &method, nil, nil, b) 25 | if err != nil { 26 | return err 27 | } 28 | response := CCommonResponse{} 29 | err = json.Unmarshal(resBody, &response) 30 | if err != nil { 31 | return err 32 | } 33 | if response.ErrCode != common.ErrorCodeSuccess { 34 | return errors.New(response.ErrMsg) 35 | } 36 | return nil 37 | } 38 | 39 | func (this *CTemplate) GetIndustry(timeoutMS int64) (*common.CGetIndustryResponse, error) { 40 | method := http.MethodGet 41 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetIndustryUrl, &method, nil, nil, nil) 42 | if err != nil { 43 | return nil, err 44 | } 45 | response := common.CGetIndustryResponse{} 46 | err = json.Unmarshal(resBody, &response) 47 | if err != nil { 48 | return nil, err 49 | } 50 | if response.ErrCode != common.ErrorCodeSuccess { 51 | return nil, errors.New(response.ErrMsg) 52 | } 53 | return &response, nil 54 | } 55 | 56 | func (this *CTemplate) GetTemplateId(request *common.CGetTemplateIdRequest, timeoutMS int64) (*common.CGetTemplateIdResponse, error) { 57 | b, err := json.Marshal(request) 58 | if err != nil { 59 | return nil, err 60 | } 61 | method := http.MethodPost 62 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetTemplateIdByTemplLibIdUrl, &method, nil, nil, b) 63 | if err != nil { 64 | return nil, err 65 | } 66 | response := common.CGetTemplateIdResponse{} 67 | err = json.Unmarshal(resBody, &response) 68 | if err != nil { 69 | return nil, err 70 | } 71 | if response.ErrCode != common.ErrorCodeSuccess { 72 | return nil, errors.New(response.ErrMsg) 73 | } 74 | return &response, nil 75 | } 76 | 77 | func (this *CTemplate) GetTemplateList(timeoutMS int64) (*common.CGetTemplateListResponse, error) { 78 | method := http.MethodGet 79 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetTemplateListUrl, &method, nil, nil, nil) 80 | if err != nil { 81 | return nil, err 82 | } 83 | response := common.CGetTemplateListResponse{} 84 | err = json.Unmarshal(resBody, &response) 85 | if err != nil { 86 | return nil, err 87 | } 88 | if response.ErrCode != common.ErrorCodeSuccess { 89 | return nil, errors.New(response.ErrMsg) 90 | } 91 | return &response, nil 92 | } 93 | 94 | func (this *CTemplate) DeleteTemplate(request *common.CDeleteTemplateRequest, timeoutMS int64) error { 95 | b, err := json.Marshal(request) 96 | if err != nil { 97 | return err 98 | } 99 | method := http.MethodPost 100 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &DeleteTemplateUrl, &method, nil, nil, b) 101 | if err != nil { 102 | return err 103 | } 104 | response := CCommonResponse{} 105 | err = json.Unmarshal(resBody, &response) 106 | if err != nil { 107 | return err 108 | } 109 | if response.ErrCode != common.ErrorCodeSuccess { 110 | return errors.New(response.ErrMsg) 111 | } 112 | return nil 113 | } 114 | 115 | func (this *CTemplate) SendTemplateMsg(request *common.CSendTemplateMsgRequest, timeoutMS int64) (*common.CSendTemplateMsgResponse, error) { 116 | b, err := json.Marshal(request) 117 | if err != nil { 118 | return nil, err 119 | } 120 | method := http.MethodPost 121 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &SendTemplateMsgUrl, &method, nil, nil, b) 122 | if err != nil { 123 | return nil, err 124 | } 125 | response := common.CSendTemplateMsgResponse{} 126 | err = json.Unmarshal(resBody, &response) 127 | if err != nil { 128 | return nil, err 129 | } 130 | if response.ErrCode != common.ErrorCodeSuccess { 131 | return nil, errors.New(response.ErrMsg) 132 | } 133 | return &response, nil 134 | } 135 | 136 | func New(token common.IToken) common.ITemplate { 137 | template := CTemplate{m_token: token} 138 | return &template 139 | } 140 | -------------------------------------------------------------------------------- /pay/common.go: -------------------------------------------------------------------------------- 1 | package pay 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/md5" 6 | "crypto/sha256" 7 | "encoding/hex" 8 | "errors" 9 | "fmt" 10 | "github.com/MwlLj/go-wechat/common" 11 | "math/rand" 12 | "reflect" 13 | "regexp" 14 | "sort" 15 | "strconv" 16 | "strings" 17 | "time" 18 | ) 19 | 20 | var _ = fmt.Println 21 | 22 | func struct2map(data interface{}) (*[]string, *map[string]string) { 23 | kvs := make(map[string]string) 24 | var keys []string 25 | t := reflect.TypeOf(data) 26 | v := reflect.ValueOf(data) 27 | fieldNum := t.NumField() 28 | for i := 0; i < fieldNum; i++ { 29 | field := t.Field(i) 30 | tag := string(field.Tag) 31 | reg, err := regexp.Compile(`xml:"(.*?)"`) 32 | if err != nil { 33 | continue 34 | } 35 | rs := reg.FindStringSubmatch(tag) 36 | if len(rs) != 2 { 37 | continue 38 | } 39 | tagName := rs[1] 40 | typeString := field.Type.String() 41 | va := v.Field(i).Interface() 42 | var value string 43 | if typeString == "string" { 44 | value = va.(string) 45 | } else if typeString == "int64" { 46 | value = strconv.FormatInt(va.(int64), 10) 47 | } else if typeString == "int" || typeString == "int32" { 48 | value = strconv.Itoa(va.(int)) 49 | } else if typeString == "float64" { 50 | value = strconv.FormatFloat(va.(float64), 'f', 30, 32) 51 | } else if typeString == "bool" { 52 | value = strconv.FormatBool(va.(bool)) 53 | } else if typeString == "uint64" { 54 | value = strconv.FormatUint(va.(uint64), 10) 55 | } else if typeString == "unit" || typeString == "uint32" { 56 | value = strconv.Itoa(va.(int)) 57 | } 58 | if tagName == SignField || value == "" { 59 | continue 60 | } 61 | keys = append(keys, tagName) 62 | kvs[tagName] = value 63 | } 64 | return &keys, &kvs 65 | } 66 | 67 | func signValidateByStruct(request *CPayByPaymentCodeRequest, key *string, encrypyType *string) (*string, error) { 68 | keys, kvs := struct2map(*request) 69 | joinStrings := "" 70 | sort.Strings(*keys) 71 | // join kvs 72 | i := 0 73 | for _, k := range *keys { 74 | item := strings.Join([]string{k, (*kvs)[k]}, "=") 75 | if i == 0 { 76 | joinStrings = item 77 | } else { 78 | joinStrings = strings.Join([]string{joinStrings, item}, "&") 79 | } 80 | i++ 81 | } 82 | // join key 83 | joinStrings = strings.Join([]string{joinStrings, "&", SignKeyField, "=", *key}, "/") 84 | var sign string 85 | // MD5 86 | if *encrypyType == common.SignEncrypyTypeHMACSHA256 { 87 | // hmac sha256 88 | mac := hmac.New(sha256.New, []byte(*key)) 89 | mac.Write([]byte(joinStrings)) 90 | cipherStr := mac.Sum(nil) 91 | hmacSign := hex.EncodeToString(cipherStr) 92 | sign = strings.ToUpper(hmacSign) 93 | } else if *encrypyType == common.SignEncrypyTypeMD5 { 94 | h := md5.New() 95 | h.Write([]byte(joinStrings)) 96 | cipherStr := h.Sum(nil) 97 | md5Sign := hex.EncodeToString(cipherStr) 98 | sign = strings.ToUpper(md5Sign) 99 | } else { 100 | return nil, errors.New("encrypy type not support") 101 | } 102 | return &sign, nil 103 | } 104 | 105 | func signValidate(kvs *map[string]string, key *string, encrypyType *string) (*string, error) { 106 | // signValue := "" 107 | var keys []string 108 | for k, v := range *kvs { 109 | if k == SignField { 110 | // signValue = v 111 | } else { 112 | if v != "" { 113 | keys = append(keys, k) 114 | } 115 | } 116 | } 117 | joinStrings := "" 118 | sort.Strings(keys) 119 | // join kvs 120 | i := 0 121 | for _, k := range keys { 122 | item := strings.Join([]string{k, (*kvs)[k]}, "=") 123 | if i == 0 { 124 | joinStrings = item 125 | } else { 126 | joinStrings = strings.Join([]string{joinStrings, item}, "&") 127 | } 128 | i++ 129 | } 130 | // join key 131 | joinStrings = strings.Join([]string{joinStrings, "&", SignKeyField, "=", *key}, "/") 132 | var sign string 133 | // MD5 134 | if *encrypyType == common.SignEncrypyTypeHMACSHA256 { 135 | // hmac sha256 136 | mac := hmac.New(sha256.New, []byte(*key)) 137 | mac.Write([]byte(joinStrings)) 138 | cipherStr := mac.Sum(nil) 139 | hmacSign := hex.EncodeToString(cipherStr) 140 | sign = strings.ToUpper(hmacSign) 141 | } else if *encrypyType == common.SignEncrypyTypeMD5 { 142 | h := md5.New() 143 | h.Write([]byte(joinStrings)) 144 | cipherStr := h.Sum(nil) 145 | md5Sign := hex.EncodeToString(cipherStr) 146 | sign = strings.ToUpper(md5Sign) 147 | } else { 148 | return nil, errors.New("encrypy type not support") 149 | } 150 | return &sign, nil 151 | } 152 | 153 | func genRandomString(length int) []byte { 154 | str := "0123456789abcdefghijklmnopqrstuvwxyz" 155 | bytes := []byte(str) 156 | result := []byte{} 157 | r := rand.New(rand.NewSource(time.Now().UnixNano())) 158 | for i := 0; i < length; i++ { 159 | result = append(result, bytes[r.Intn(len(bytes))]) 160 | } 161 | return result 162 | } 163 | -------------------------------------------------------------------------------- /common/interface.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | type FuncMsgCallback func(reply IReply, msg *CMessage, communicate CDataCommunicate, userData interface{}) error 4 | type FuncEventCallback func(reply IReply, event *CEvent, communicate CDataCommunicate, userData interface{}) error 5 | 6 | type IEvent interface { 7 | OnEvent(sender IReply, event *CEvent, communicate CDataCommunicate, userData interface{}) error 8 | } 9 | 10 | type IMessage interface { 11 | OnMessage(sender IReply, msg *CMessage, communicate CDataCommunicate, userData interface{}) error 12 | } 13 | 14 | type ISender interface { 15 | GroupSendByTag(request *CGroupSendByTagRequest, timeoutMS int64) (*CGroupSendByTagResponse, error) 16 | GroupSendByOpenIds(request *CGroupSendByOpenIdsRequest, timeoutMS int64) (*CGroupSendByTagResponse, error) 17 | DeleteGroupSend(request *CDeleteGroupSendRequest, timeoutMS int64) error 18 | PreviewMessage(request *CPreviewMessageRequest, timeoutMS int64) (*CPreviewMessageResponse, error) 19 | } 20 | 21 | type IReply interface { 22 | SendMessage(msg *CMessage) error 23 | SendEmptyMessage() error 24 | IsSend() bool 25 | } 26 | 27 | type IToken interface { 28 | GetUserInfo() *CUserInfo 29 | GetToken(timeoutMS int64) (token []byte, e error) 30 | UpdateToken(timeoutMS int64) (token []byte, e error) 31 | } 32 | 33 | type IMenu interface { 34 | Create(data *[]CButton, timeoutMS int64) error 35 | GetAll(timeoutMS int64) (*CGetMenuJson, error) 36 | DeleteAll(timeoutMS int64) error 37 | } 38 | 39 | type ITemplate interface { 40 | SetIndustry(request *CSetIndustryRequest, timeoutMS int64) error 41 | GetIndustry(timeoutMS int64) (*CGetIndustryResponse, error) 42 | GetTemplateId(request *CGetTemplateIdRequest, timeoutMS int64) (*CGetTemplateIdResponse, error) 43 | GetTemplateList(timeoutMS int64) (*CGetTemplateListResponse, error) 44 | DeleteTemplate(request *CDeleteTemplateRequest, timeoutMS int64) error 45 | SendTemplateMsg(request *CSendTemplateMsgRequest, timeoutMS int64) (*CSendTemplateMsgResponse, error) 46 | } 47 | 48 | type IMaterial interface { 49 | CreateTmpMaterial(request *CCreateTmpMaterialRequest, timeoutMS int64) (*CCreateTmpMaterialResponse, error) 50 | GetTmpMaterial(request *CGetTmpMaterialRequest, timeoutMS int64) (*CGetTmpMaterialResponse, error) 51 | GetTmpHDMaterial(request *CGetTmpHDMaterialRequest, timeoutMS int64) (*CGetTmpHDMaterialResponse, error) 52 | AddForeverImgTextMaterial(request *CAddForeverImgTextMaterialRequest, timeoutMS int64) (*CAddForeverImgTextMaterialResponse, error) 53 | UploadImage(path *string, timeoutMS int64) (*CUploadImageResponse, error) 54 | UploadVideo(request *CUploadVideoRequest, timeoutMS int64) (*CUploadVideoResponse, error) 55 | AddForeverOtherMaterial(request *CAddForeverOtherMaterialRequest, timeoutMS int64) (*CAddForeverOtherMaterialResponse, error) 56 | GetForeverMaterial(request *CGetForeverMaterialRequest, timeoutMS int64) (*CGetForeverMaterialResponse, error) 57 | DeleteForeverMaterial(request *CDeleteForeverMaterialRequest, timeoutMS int64) error 58 | UpdateForeverImgTextMaterial(request *CUpdateForeverImgTextMaterialRequest, timeoutMS int64) error 59 | GetMaterialTotal(timeoutMS int64) (*CGetMaterialTotalResponse, error) 60 | GetMaterialList(request *CGetMaterialListRequest, timeoutMS int64) (*CGetMaterialListResponse, error) 61 | } 62 | 63 | type IUser interface { 64 | CreateTag(request *CCreateTagRequest, timeoutMS int64) (*CCreateTagResponse, error) 65 | GetTagList(timeoutMS int64) (*CGetTagListResponse, error) 66 | UpdateTag(request *CUpdateTagRequest, timeoutMS int64) error 67 | DeleteTag(request *CDeleteTagRequest, timeoutMS int64) error 68 | GetTagUserList(request *CGetTagUserListRequest, timeoutMS int64) (*CGetTagUserListResponse, error) 69 | AddTagToUsers(request *CAddTagToUsersRequest, timeoutMS int64) error 70 | DeleteTagToUsers(request *CDeleteTagToUsersRequest, timeoutMS int64) error 71 | GetTagsByUser(request *CGetTagsByUserRequest, timeoutMS int64) (*CGetTagsByUserResponse, error) 72 | UpdateUserRemark(request *CUpdateUserRemarkRequest, timeoutMS int64) error 73 | GetUserBaseInfo(request *CGetUserBaseInfoRequest, timeoutMS int64) (*CGetUserBaseInfoResponse, error) 74 | GetUserBaseInfoMulti(request *CGetUserBaseInfoMultiRequest, timeoutMS int64) (*CGetUserBaseInfoMultiResponse, error) 75 | GetFollowUsers(timeoutMS int64) (*CGetFollowUsersResponse, error) 76 | GetBlackListUsers(timeoutMS int64) (*CGetBlackListUsersResponse, error) 77 | TakeUsersToBlackList(request *CTakeUsersToBlackListRequest, timeoutMS int64) error 78 | UnTakeUsersToBlackList(request *CUnTakeUsersToBlackListRequest, timeoutMS int64) error 79 | } 80 | 81 | type IStore interface { 82 | CreateStore(request *CCreateStoreRequest, timeoutMS int64) error 83 | GetStore(request *CGetStoreRequest, timeoutMS int64) (*CGetStoreResponse, error) 84 | GetStoreList(request *CGetStoreListRequest, timeoutMS int64) (*CGetStoreListResponse, error) 85 | ModifyStore(request *CModifyStoreRequest, timeoutMS int64) error 86 | DeleteStore(request *CDeleteStoreRequest, timeoutMS int64) error 87 | GetCategory(timeoutMS int64) (*CGetCategoryResponse, error) 88 | } 89 | 90 | type IShop interface { 91 | AddCommodity(request *CAddCommodityRequest, timeoutMS int64) (*CAddCommodityResponse, error) 92 | DeleteCommodity(request *CDeleteCommodityRequest, timeoutMS int64) error 93 | UpdateCommodity(request *CUpdateCommodityRequest, timeoutMS int64) error 94 | GetCommodity(request *CGetCommodityRequest, timeoutMS int64) (*CGetCommodityResponse, error) 95 | GetCommodityByStatus(request *CGetCommodityByStatusRequest, timeoutMS int64) (*CGetCommodityByStatusResponse, error) 96 | UpdateCommodityStatus(request *CUpdateCommodityStatusRequest, timeoutMS int64) error 97 | GetSubClassesByClassify(request *CGetSubClassesByClassifyRequest, timeoutMS int64) (*CGetSubClassesByClassifyResponse, error) 98 | GetAllSkuByClassify(request *CGetAllSkuByClassifyRequest, timeoutMS int64) (*CGetAllSkuByClassifyResponse, error) 99 | GetAllPropertyByClassify(request *CGetAllPropertyByClassifyRequest, timeoutMS int64) (*CGetAllPropertyByClassifyResponse, error) 100 | AddStock(request *CAddStockRequest, timeoutMS int64) error 101 | ReduceStock(request *CReduceStockRequest, timeoutMS int64) error 102 | } 103 | 104 | type IPayByPaymentCode interface { 105 | } 106 | -------------------------------------------------------------------------------- /server/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "crypto/sha1" 5 | "errors" 6 | "fmt" 7 | "github.com/MwlLj/go-wechat/common" 8 | "github.com/MwlLj/go-wechat/material" 9 | "github.com/MwlLj/go-wechat/menu" 10 | "github.com/MwlLj/go-wechat/pay" 11 | "github.com/MwlLj/go-wechat/sender" 12 | "github.com/MwlLj/go-wechat/shop" 13 | "github.com/MwlLj/go-wechat/store" 14 | "github.com/MwlLj/go-wechat/template" 15 | "github.com/MwlLj/go-wechat/token" 16 | "github.com/MwlLj/go-wechat/user" 17 | "github.com/MwlLj/go-wechat/utils" 18 | "io" 19 | "io/ioutil" 20 | "net/http" 21 | "sort" 22 | "strconv" 23 | "strings" 24 | ) 25 | 26 | type CServer struct { 27 | m_exeChannel chan bool 28 | m_userInfo common.CUserInfo 29 | m_decodeFactory CDecodeFactory 30 | m_token common.IToken 31 | m_msgCallback common.IMessage 32 | m_msgCallbackUserdata interface{} 33 | m_eventCallback common.IEvent 34 | m_eventCallbackUserdata interface{} 35 | } 36 | 37 | func (this *CServer) init(info *common.CUserInfo) { 38 | this.m_token = token.New(info) 39 | this.startListen(info.Port, &info.Url) 40 | } 41 | 42 | func (this *CServer) Loop() { 43 | this.m_exeChannel = make(chan bool, 1) 44 | <-this.m_exeChannel 45 | close(this.m_exeChannel) 46 | } 47 | 48 | func (this *CServer) makeSignature(timestamp, nonce string) string { 49 | sl := []string{this.m_userInfo.Token, timestamp, nonce} 50 | sort.Strings(sl) 51 | s := sha1.New() 52 | io.WriteString(s, strings.Join(sl, "")) 53 | return fmt.Sprintf("%x", s.Sum(nil)) 54 | } 55 | 56 | func (this *CServer) validateUrl(w http.ResponseWriter, r *http.Request) bool { 57 | timestamp := strings.Join(r.Form["timestamp"], "") 58 | nonce := strings.Join(r.Form["nonce"], "") 59 | signatureGen := this.makeSignature(timestamp, nonce) 60 | 61 | signatureIn := strings.Join(r.Form["signature"], "") 62 | if signatureGen != signatureIn { 63 | return false 64 | } 65 | echostr := strings.Join(r.Form["echostr"], "") 66 | fmt.Fprint(w, echostr) 67 | return true 68 | } 69 | 70 | func (this *CServer) parseResContent(body []byte, w http.ResponseWriter) (*common.CWxResXml, error) { 71 | param := CDecodeParam{} 72 | param.DecodeType = DecodeTypeResXml 73 | decoding := this.m_decodeFactory.Decoding(¶m) 74 | if decoding == nil { 75 | fmt.Fprint(w, "decoding message error") 76 | return nil, errors.New("decoding message error") 77 | } 78 | message := decoding.Parse(body) 79 | if message == nil { 80 | fmt.Fprint(w, "parse message request error") 81 | return nil, errors.New("parse message request error") 82 | } 83 | msg := message.(*common.CWxResXml) 84 | return msg, nil 85 | } 86 | 87 | func (this *CServer) handleCheck(w http.ResponseWriter, r *http.Request) error { 88 | r.ParseForm() 89 | if !this.validateUrl(w, r) { 90 | fmt.Fprint(w, "check invalid") 91 | return errors.New("check invalid") 92 | } 93 | return nil 94 | } 95 | 96 | func (this *CServer) handlePost(w http.ResponseWriter, r *http.Request) error { 97 | var err error = nil 98 | body, err := ioutil.ReadAll(r.Body) 99 | if err != nil { 100 | return err 101 | } 102 | resXml, err := this.parseResContent(body, w) 103 | if resXml == nil { 104 | return err 105 | } 106 | if string(resXml.MsgType) != common.MsgTypeEvent { 107 | // message 108 | reply := sender.NewReply(&resXml.ToUserName, &resXml.FromUserName, &w) 109 | if this.m_msgCallback != nil { 110 | for { 111 | msg := utils.ResXml2Message(resXml) 112 | communicate := utils.ResXml2DataCommunicate(resXml) 113 | err = this.m_msgCallback.OnMessage(reply, msg, *communicate, this.m_msgCallbackUserdata) 114 | if err != nil { 115 | break 116 | } 117 | if reply.IsSend() == false { 118 | reply.SendEmptyMessage() 119 | } 120 | return nil 121 | } 122 | } 123 | } else { 124 | // event 125 | reply := sender.NewReply(&resXml.ToUserName, &resXml.FromUserName, &w) 126 | if this.m_eventCallback != nil { 127 | for { 128 | event := utils.ResXml2Event(resXml) 129 | communicate := utils.ResXml2DataCommunicate(resXml) 130 | err = this.m_eventCallback.OnEvent(reply, event, *communicate, this.m_eventCallbackUserdata) 131 | if err != nil { 132 | break 133 | } 134 | if reply.IsSend() == false { 135 | reply.SendEmptyMessage() 136 | } 137 | return nil 138 | } 139 | } 140 | } 141 | return err 142 | } 143 | 144 | func (this *CServer) handleRequest(w http.ResponseWriter, r *http.Request) { 145 | this.handleCheck(w, r) 146 | if r.Method == http.MethodPost { 147 | this.handlePost(w, r) 148 | } 149 | } 150 | 151 | func (this *CServer) startListen(port int, u *string) { 152 | handler := func(w http.ResponseWriter, r *http.Request) { 153 | this.handleRequest(w, r) 154 | } 155 | go func() { 156 | url := *u 157 | if string(url[0]) != "/" { 158 | url = strings.Join([]string{"/", url}, "") 159 | } 160 | host := strings.Join([]string{":", strconv.FormatInt(int64(port), 10)}, "") 161 | mux := http.NewServeMux() 162 | mux.HandleFunc(url, handler) 163 | err := http.ListenAndServe(host, mux) 164 | if err != nil { 165 | fmt.Println(err) 166 | this.m_exeChannel <- false 167 | } 168 | }() 169 | } 170 | 171 | func (this *CServer) RegisterMsg(callback common.IMessage, userData interface{}) { 172 | this.m_msgCallback = callback 173 | this.m_msgCallbackUserdata = userData 174 | } 175 | 176 | func (this *CServer) RegisterMsgFunc(callback common.FuncMsgCallback, userData interface{}) { 177 | this.RegisterMsg(&CMsgCallbackDefault{MsgCallback: callback}, userData) 178 | } 179 | 180 | func (this *CServer) RegisterEventFunc(callback common.FuncEventCallback, userData interface{}) { 181 | this.RegisterEvent(&CEventCallbackDefault{EventCallback: callback}, userData) 182 | } 183 | 184 | func (this *CServer) RegisterEvent(callback common.IEvent, userData interface{}) { 185 | this.m_eventCallback = callback 186 | this.m_eventCallbackUserdata = userData 187 | } 188 | 189 | func (this *CServer) Menu() common.IMenu { 190 | return menu.New(this.m_token) 191 | } 192 | 193 | func (this *CServer) Template() common.ITemplate { 194 | return template.New(this.m_token) 195 | } 196 | 197 | func (this *CServer) Material() common.IMaterial { 198 | return material.New(this.m_token) 199 | } 200 | 201 | func (this *CServer) User() common.IUser { 202 | return user.New(this.m_token) 203 | } 204 | 205 | func (this *CServer) Store() common.IStore { 206 | return store.New(this.m_token) 207 | } 208 | 209 | func (this *CServer) Shop() common.IShop { 210 | return shop.New(this.m_token) 211 | } 212 | 213 | func (this *CServer) Sender() common.ISender { 214 | return sender.New(this.m_token) 215 | } 216 | 217 | func (this *CServer) PayByPaymengCode() common.IPayByPaymentCode { 218 | return pay.NewPayByPaymentCode(this.m_token) 219 | } 220 | 221 | func New(info *common.CUserInfo) *CServer { 222 | server := CServer{m_userInfo: *info} 223 | server.init(info) 224 | return &server 225 | } 226 | -------------------------------------------------------------------------------- /shop/shop.go: -------------------------------------------------------------------------------- 1 | package shop 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "github.com/MwlLj/go-wechat/common" 7 | "github.com/MwlLj/go-wechat/communicate" 8 | "github.com/MwlLj/go-wechat/private" 9 | "net/http" 10 | "strings" 11 | ) 12 | 13 | type CShop struct { 14 | m_token common.IToken 15 | } 16 | 17 | func (this *CShop) stockSkuList2SkuInfo(stockSkuList *[]common.CStockSkuInfo) *string { 18 | result := "" 19 | i := 0 20 | for _, info := range *stockSkuList { 21 | item := strings.Join([]string{info.Id, info.Vid}, ":") 22 | if i == 0 { 23 | result = item 24 | } else { 25 | result = strings.Join([]string{result, item}, ";") 26 | } 27 | i++ 28 | } 29 | return &result 30 | } 31 | 32 | func (this *CShop) AddCommodity(request *common.CAddCommodityRequest, timeoutMS int64) (*common.CAddCommodityResponse, error) { 33 | b, err := json.Marshal(request) 34 | if err != nil { 35 | return nil, err 36 | } 37 | method := http.MethodPost 38 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &AddCommodityUrl, &method, nil, nil, b) 39 | if err != nil { 40 | return nil, err 41 | } 42 | response := common.CAddCommodityResponse{} 43 | err = json.Unmarshal(resBody, &response) 44 | if err != nil { 45 | return nil, err 46 | } 47 | if response.ErrCode != private.ErrorCodeSuccess { 48 | return nil, errors.New(response.ErrMsg) 49 | } 50 | return &response, nil 51 | } 52 | 53 | func (this *CShop) DeleteCommodity(request *common.CDeleteCommodityRequest, timeoutMS int64) error { 54 | b, err := json.Marshal(request) 55 | if err != nil { 56 | return err 57 | } 58 | method := http.MethodPost 59 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &DeleteCommodityUrl, &method, nil, nil, b) 60 | if err != nil { 61 | return err 62 | } 63 | response := private.CCommonResponse{} 64 | err = json.Unmarshal(resBody, &response) 65 | if err != nil { 66 | return err 67 | } 68 | if response.ErrCode != private.ErrorCodeSuccess { 69 | return errors.New(response.ErrMsg) 70 | } 71 | return nil 72 | } 73 | 74 | func (this *CShop) UpdateCommodity(request *common.CUpdateCommodityRequest, timeoutMS int64) error { 75 | b, err := json.Marshal(request) 76 | if err != nil { 77 | return err 78 | } 79 | method := http.MethodPost 80 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &UpdateCommodityUrl, &method, nil, nil, b) 81 | if err != nil { 82 | return err 83 | } 84 | response := private.CCommonResponse{} 85 | err = json.Unmarshal(resBody, &response) 86 | if err != nil { 87 | return err 88 | } 89 | if response.ErrCode != private.ErrorCodeSuccess { 90 | return errors.New(response.ErrMsg) 91 | } 92 | return nil 93 | } 94 | 95 | func (this *CShop) GetCommodity(request *common.CGetCommodityRequest, timeoutMS int64) (*common.CGetCommodityResponse, error) { 96 | b, err := json.Marshal(request) 97 | if err != nil { 98 | return nil, err 99 | } 100 | method := http.MethodPost 101 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetCommodityUrl, &method, nil, nil, b) 102 | if err != nil { 103 | return nil, err 104 | } 105 | response := common.CGetCommodityResponse{} 106 | err = json.Unmarshal(resBody, &response) 107 | if err != nil { 108 | return nil, err 109 | } 110 | if response.ErrCode != private.ErrorCodeSuccess { 111 | return nil, errors.New(response.ErrMsg) 112 | } 113 | return &response, nil 114 | } 115 | 116 | func (this *CShop) GetCommodityByStatus(request *common.CGetCommodityByStatusRequest, timeoutMS int64) (*common.CGetCommodityByStatusResponse, error) { 117 | b, err := json.Marshal(request) 118 | if err != nil { 119 | return nil, err 120 | } 121 | method := http.MethodPost 122 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetCommodityByStatusUrl, &method, nil, nil, b) 123 | if err != nil { 124 | return nil, err 125 | } 126 | response := common.CGetCommodityByStatusResponse{} 127 | err = json.Unmarshal(resBody, &response) 128 | if err != nil { 129 | return nil, err 130 | } 131 | if response.ErrCode != private.ErrorCodeSuccess { 132 | return nil, errors.New(response.ErrMsg) 133 | } 134 | return &response, nil 135 | } 136 | 137 | func (this *CShop) UpdateCommodityStatus(request *common.CUpdateCommodityStatusRequest, timeoutMS int64) error { 138 | b, err := json.Marshal(request) 139 | if err != nil { 140 | return err 141 | } 142 | method := http.MethodPost 143 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &UpdateCommodityStatusUrl, &method, nil, nil, b) 144 | if err != nil { 145 | return err 146 | } 147 | response := private.CCommonResponse{} 148 | err = json.Unmarshal(resBody, &response) 149 | if err != nil { 150 | return err 151 | } 152 | if response.ErrCode != private.ErrorCodeSuccess { 153 | return errors.New(response.ErrMsg) 154 | } 155 | return nil 156 | } 157 | 158 | func (this *CShop) GetSubClassesByClassify(request *common.CGetSubClassesByClassifyRequest, timeoutMS int64) (*common.CGetSubClassesByClassifyResponse, error) { 159 | b, err := json.Marshal(request) 160 | if err != nil { 161 | return nil, err 162 | } 163 | method := http.MethodPost 164 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetSubClassesByClassifyUrl, &method, nil, nil, b) 165 | if err != nil { 166 | return nil, err 167 | } 168 | response := common.CGetSubClassesByClassifyResponse{} 169 | err = json.Unmarshal(resBody, &response) 170 | if err != nil { 171 | return nil, err 172 | } 173 | if response.ErrCode != private.ErrorCodeSuccess { 174 | return nil, errors.New(response.ErrMsg) 175 | } 176 | return &response, nil 177 | } 178 | 179 | func (this *CShop) GetAllSkuByClassify(request *common.CGetAllSkuByClassifyRequest, timeoutMS int64) (*common.CGetAllSkuByClassifyResponse, error) { 180 | b, err := json.Marshal(request) 181 | if err != nil { 182 | return nil, err 183 | } 184 | method := http.MethodPost 185 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetAllSkuByClassifyUrl, &method, nil, nil, b) 186 | if err != nil { 187 | return nil, err 188 | } 189 | response := common.CGetAllSkuByClassifyResponse{} 190 | err = json.Unmarshal(resBody, &response) 191 | if err != nil { 192 | return nil, err 193 | } 194 | if response.ErrCode != private.ErrorCodeSuccess { 195 | return nil, errors.New(response.ErrMsg) 196 | } 197 | return &response, nil 198 | } 199 | 200 | func (this *CShop) GetAllPropertyByClassify(request *common.CGetAllPropertyByClassifyRequest, timeoutMS int64) (*common.CGetAllPropertyByClassifyResponse, error) { 201 | b, err := json.Marshal(request) 202 | if err != nil { 203 | return nil, err 204 | } 205 | method := http.MethodPost 206 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetAllPropertyByClassifyUrl, &method, nil, nil, b) 207 | if err != nil { 208 | return nil, err 209 | } 210 | response := common.CGetAllPropertyByClassifyResponse{} 211 | err = json.Unmarshal(resBody, &response) 212 | if err != nil { 213 | return nil, err 214 | } 215 | if response.ErrCode != private.ErrorCodeSuccess { 216 | return nil, errors.New(response.ErrMsg) 217 | } 218 | return &response, nil 219 | } 220 | 221 | func (this *CShop) AddStock(request *common.CAddStockRequest, timeoutMS int64) error { 222 | skuInfo := this.stockSkuList2SkuInfo(&request.SkuInfo) 223 | req := CAddStockRequest{} 224 | req.ProductId = request.ProductId 225 | req.Quantity = request.Quantity 226 | req.SkuInfo = *skuInfo 227 | b, err := json.Marshal(req) 228 | if err != nil { 229 | return err 230 | } 231 | method := http.MethodPost 232 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &AddStockUrl, &method, nil, nil, b) 233 | if err != nil { 234 | return err 235 | } 236 | response := private.CCommonResponse{} 237 | err = json.Unmarshal(resBody, &response) 238 | if err != nil { 239 | return err 240 | } 241 | if response.ErrCode != private.ErrorCodeSuccess { 242 | return errors.New(response.ErrMsg) 243 | } 244 | return nil 245 | } 246 | 247 | func (this *CShop) ReduceStock(request *common.CReduceStockRequest, timeoutMS int64) error { 248 | skuInfo := this.stockSkuList2SkuInfo(&request.SkuInfo) 249 | req := CReduceStockRequest{} 250 | req.ProductId = request.ProductId 251 | req.Quantity = request.Quantity 252 | req.SkuInfo = *skuInfo 253 | b, err := json.Marshal(req) 254 | if err != nil { 255 | return err 256 | } 257 | method := http.MethodPost 258 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &ReduceStockUrl, &method, nil, nil, b) 259 | if err != nil { 260 | return err 261 | } 262 | response := private.CCommonResponse{} 263 | err = json.Unmarshal(resBody, &response) 264 | if err != nil { 265 | return err 266 | } 267 | if response.ErrCode != private.ErrorCodeSuccess { 268 | return errors.New(response.ErrMsg) 269 | } 270 | return nil 271 | } 272 | 273 | func New(token common.IToken) common.IShop { 274 | shop := CShop{m_token: token} 275 | return &shop 276 | } 277 | -------------------------------------------------------------------------------- /material/material.go: -------------------------------------------------------------------------------- 1 | package material 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "github.com/MwlLj/go-wechat/common" 7 | "github.com/MwlLj/go-wechat/communicate" 8 | "github.com/MwlLj/go-wechat/private" 9 | "net/http" 10 | ) 11 | 12 | type CMaterial struct { 13 | m_token common.IToken 14 | } 15 | 16 | func (this *CMaterial) CreateTmpMaterial(request *common.CCreateTmpMaterialRequest, timeoutMS int64) (*common.CCreateTmpMaterialResponse, error) { 17 | params := make(map[string]string) 18 | params[CreateTmpMaterialParamType] = request.MaterialType 19 | multi := communicate.CMultiData{} 20 | multi.Type = communicate.MultiDataTypeFile 21 | multi.FormName = CreateTmpMaterialFormname 22 | multi.ValueOrFilename = request.Path 23 | multis := make([]communicate.CMultiData, 1) 24 | multis = append(multis, multi) 25 | resBody, err := communicate.UploadFileWithToken(this.m_token, timeoutMS, &multis, &CreateTmpMaterialUrl, ¶ms, nil) 26 | if err != nil { 27 | return nil, err 28 | } 29 | response := common.CCreateTmpMaterialResponse{} 30 | err = json.Unmarshal(resBody, &response) 31 | if err != nil { 32 | return nil, err 33 | } 34 | if response.ErrCode != private.ErrorCodeSuccess { 35 | return nil, errors.New(response.ErrMsg) 36 | } 37 | return &response, nil 38 | } 39 | 40 | func (this *CMaterial) GetTmpMaterial(request *common.CGetTmpMaterialRequest, timeoutMS int64) (*common.CGetTmpMaterialResponse, error) { 41 | method := http.MethodGet 42 | params := make(map[string]string) 43 | params[GetTmpMaterialParamMediaId] = request.MediaId 44 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetTmpMaterialUrl, &method, ¶ms, nil, nil) 45 | if err != nil { 46 | return nil, err 47 | } 48 | response := CGetTmpMaterialResponse{} 49 | err = json.Unmarshal(resBody, &response) 50 | if err != nil { 51 | return nil, err 52 | } 53 | if response.ErrCode != private.ErrorCodeSuccess { 54 | return nil, errors.New(response.ErrMsg) 55 | } 56 | res := common.CGetTmpMaterialResponse{} 57 | isFind := false 58 | for _, url := range GetTmpMaterialResUrls { 59 | r := response.ResUrl.(map[string]interface{})[url] 60 | if r != nil { 61 | res.ResUrl = r.(string) 62 | isFind = true 63 | break 64 | } 65 | } 66 | if isFind == false { 67 | return nil, errors.New("type error") 68 | } 69 | return &res, nil 70 | } 71 | 72 | func (this *CMaterial) GetTmpHDMaterial(request *common.CGetTmpHDMaterialRequest, timeoutMS int64) (*common.CGetTmpHDMaterialResponse, error) { 73 | method := http.MethodGet 74 | params := make(map[string]string) 75 | params[GetTmpHDMaterialParamMediaId] = request.MediaId 76 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetTmpHDMaterialUrl, &method, ¶ms, nil, nil) 77 | if err != nil { 78 | return nil, err 79 | } 80 | response := CGetTmpHDMaterialResponse{} 81 | err = json.Unmarshal(resBody, &response) 82 | if err != nil { 83 | return nil, err 84 | } 85 | if response.ErrCode != private.ErrorCodeSuccess { 86 | return nil, errors.New(response.ErrMsg) 87 | } 88 | res := common.CGetTmpHDMaterialResponse{} 89 | isFind := false 90 | for _, url := range GetTmpMaterialResUrls { 91 | r := response.ResUrl.(map[string]interface{})[url] 92 | if r != nil { 93 | res.ResUrl = r.(string) 94 | isFind = true 95 | break 96 | } 97 | } 98 | if isFind == false { 99 | return nil, errors.New("type error") 100 | } 101 | return &res, nil 102 | } 103 | 104 | func (this *CMaterial) AddForeverImgTextMaterial(request *common.CAddForeverImgTextMaterialRequest, timeoutMS int64) (*common.CAddForeverImgTextMaterialResponse, error) { 105 | b, err := json.Marshal(request) 106 | if err != nil { 107 | return nil, err 108 | } 109 | method := http.MethodPost 110 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &AddForeverImgTextMaterialUrl, &method, nil, nil, b) 111 | if err != nil { 112 | return nil, err 113 | } 114 | response := common.CAddForeverImgTextMaterialResponse{} 115 | err = json.Unmarshal(resBody, &response) 116 | if err != nil { 117 | return nil, err 118 | } 119 | if response.ErrCode != private.ErrorCodeSuccess { 120 | return nil, errors.New(response.ErrMsg) 121 | } 122 | return &response, nil 123 | } 124 | 125 | func (this *CMaterial) UploadImage(path *string, timeoutMS int64) (*common.CUploadImageResponse, error) { 126 | multi := communicate.CMultiData{} 127 | multi.Type = communicate.MultiDataTypeFile 128 | multi.FormName = UploadImageFormname 129 | multi.ValueOrFilename = *path 130 | multis := make([]communicate.CMultiData, 1) 131 | multis = append(multis, multi) 132 | resBody, err := communicate.UploadFileWithToken(this.m_token, timeoutMS, &multis, &UploadImageUrl, nil, nil) 133 | if err != nil { 134 | return nil, err 135 | } 136 | response := common.CUploadImageResponse{} 137 | err = json.Unmarshal(resBody, &response) 138 | if err != nil { 139 | return nil, err 140 | } 141 | if response.ErrCode != private.ErrorCodeSuccess { 142 | return nil, errors.New(response.ErrMsg) 143 | } 144 | return &response, nil 145 | } 146 | 147 | func (this *CMaterial) UploadVideo(request *common.CUploadVideoRequest, timeoutMS int64) (*common.CUploadVideoResponse, error) { 148 | b, err := json.Marshal(request) 149 | if err != nil { 150 | return nil, err 151 | } 152 | method := http.MethodPost 153 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &UploadVideoUrl, &method, nil, nil, b) 154 | if err != nil { 155 | return nil, err 156 | } 157 | response := common.CUploadVideoResponse{} 158 | err = json.Unmarshal(resBody, &response) 159 | if err != nil { 160 | return nil, err 161 | } 162 | if response.ErrCode != private.ErrorCodeSuccess { 163 | return nil, errors.New(response.ErrMsg) 164 | } 165 | return &response, nil 166 | } 167 | 168 | func (this *CMaterial) AddForeverOtherMaterial(request *common.CAddForeverOtherMaterialRequest, timeoutMS int64) (*common.CAddForeverOtherMaterialResponse, error) { 169 | params := make(map[string]string) 170 | params[AddOtherMaterialParamType] = request.MaterialType 171 | multis := make([]communicate.CMultiData, 1) 172 | multi := communicate.CMultiData{} 173 | // file 174 | multi.Type = communicate.MultiDataTypeFile 175 | multi.FormName = AddOtherMaterialFormnameMedia 176 | multi.ValueOrFilename = request.Path 177 | multis = append(multis, multi) 178 | // desc 179 | multi.Type = communicate.MultiDataTypeText 180 | multi.FormName = AddOtherMaterialFormnameDescription 181 | desc := CAddForeverOtherMaterialFormnameDesc{} 182 | desc.Title = request.Title 183 | desc.Introduction = request.Introduction 184 | b, err := json.Marshal(&desc) 185 | if err != nil { 186 | return nil, err 187 | } 188 | multi.ValueOrFilename = string(b) 189 | multis = append(multis, multi) 190 | resBody, err := communicate.UploadFileWithToken(this.m_token, timeoutMS, &multis, &AddForeverOtherMaterialUrl, ¶ms, nil) 191 | if err != nil { 192 | return nil, err 193 | } 194 | response := common.CAddForeverOtherMaterialResponse{} 195 | err = json.Unmarshal(resBody, &response) 196 | if err != nil { 197 | return nil, err 198 | } 199 | if response.ErrCode != private.ErrorCodeSuccess { 200 | return nil, errors.New(response.ErrMsg) 201 | } 202 | return &response, nil 203 | } 204 | 205 | func (this *CMaterial) GetForeverMaterial(request *common.CGetForeverMaterialRequest, timeoutMS int64) (*common.CGetForeverMaterialResponse, error) { 206 | b, err := json.Marshal(request) 207 | if err != nil { 208 | return nil, err 209 | } 210 | method := http.MethodPost 211 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetForeverMaterialUrl, &method, nil, nil, b) 212 | if err != nil { 213 | return nil, err 214 | } 215 | response := common.CGetForeverMaterialResponse{} 216 | err = json.Unmarshal(resBody, &response) 217 | if err != nil { 218 | return nil, err 219 | } 220 | if response.ErrCode != private.ErrorCodeSuccess { 221 | return nil, errors.New(response.ErrMsg) 222 | } 223 | return &response, nil 224 | } 225 | 226 | func (this *CMaterial) DeleteForeverMaterial(request *common.CDeleteForeverMaterialRequest, timeoutMS int64) error { 227 | b, err := json.Marshal(request) 228 | if err != nil { 229 | return err 230 | } 231 | method := http.MethodPost 232 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &DeleteForeverMaterialUrl, &method, nil, nil, b) 233 | if err != nil { 234 | return err 235 | } 236 | response := private.CCommonResponse{} 237 | err = json.Unmarshal(resBody, &response) 238 | if err != nil { 239 | return err 240 | } 241 | if response.ErrCode != private.ErrorCodeSuccess { 242 | return errors.New(response.ErrMsg) 243 | } 244 | return nil 245 | } 246 | 247 | func (this *CMaterial) UpdateForeverImgTextMaterial(request *common.CUpdateForeverImgTextMaterialRequest, timeoutMS int64) error { 248 | b, err := json.Marshal(request) 249 | if err != nil { 250 | return err 251 | } 252 | method := http.MethodPost 253 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &UpdateForeverImgTextMaterialUrl, &method, nil, nil, b) 254 | if err != nil { 255 | return err 256 | } 257 | response := private.CCommonResponse{} 258 | err = json.Unmarshal(resBody, &response) 259 | if err != nil { 260 | return err 261 | } 262 | if response.ErrCode != private.ErrorCodeSuccess { 263 | return errors.New(response.ErrMsg) 264 | } 265 | return nil 266 | } 267 | 268 | func (this *CMaterial) GetMaterialTotal(timeoutMS int64) (*common.CGetMaterialTotalResponse, error) { 269 | method := http.MethodGet 270 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetMaterialTotal, &method, nil, nil, nil) 271 | if err != nil { 272 | return nil, err 273 | } 274 | response := common.CGetMaterialTotalResponse{} 275 | err = json.Unmarshal(resBody, &response) 276 | if err != nil { 277 | return nil, err 278 | } 279 | if response.ErrCode != private.ErrorCodeSuccess { 280 | return nil, errors.New(response.ErrMsg) 281 | } 282 | return &response, nil 283 | } 284 | 285 | func (this *CMaterial) GetMaterialList(request *common.CGetMaterialListRequest, timeoutMS int64) (*common.CGetMaterialListResponse, error) { 286 | b, err := json.Marshal(request) 287 | if err != nil { 288 | return nil, err 289 | } 290 | method := http.MethodPost 291 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetMaterialList, &method, nil, nil, b) 292 | if err != nil { 293 | return nil, err 294 | } 295 | response := common.CGetMaterialListResponse{} 296 | err = json.Unmarshal(resBody, &response) 297 | if err != nil { 298 | return nil, err 299 | } 300 | if response.ErrCode != private.ErrorCodeSuccess { 301 | return nil, errors.New(response.ErrMsg) 302 | } 303 | return &response, nil 304 | } 305 | 306 | func New(token common.IToken) common.IMaterial { 307 | media := CMaterial{ 308 | m_token: token, 309 | } 310 | return &media 311 | } 312 | -------------------------------------------------------------------------------- /user/user.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "github.com/MwlLj/go-wechat/common" 7 | "github.com/MwlLj/go-wechat/communicate" 8 | "github.com/MwlLj/go-wechat/private" 9 | "net/http" 10 | ) 11 | 12 | type CUser struct { 13 | m_token common.IToken 14 | } 15 | 16 | func (this *CUser) CreateTag(request *common.CCreateTagRequest, timeoutMS int64) (*common.CCreateTagResponse, error) { 17 | b, err := json.Marshal(request) 18 | if err != nil { 19 | return nil, err 20 | } 21 | method := http.MethodPost 22 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &CreateTagUrl, &method, nil, nil, b) 23 | if err != nil { 24 | return nil, err 25 | } 26 | response := common.CCreateTagResponse{} 27 | err = json.Unmarshal(resBody, &response) 28 | if err != nil { 29 | return nil, err 30 | } 31 | if response.ErrCode != private.ErrorCodeSuccess { 32 | return nil, errors.New(response.ErrMsg) 33 | } 34 | return &response, nil 35 | } 36 | 37 | func (this *CUser) GetTagList(timeoutMS int64) (*common.CGetTagListResponse, error) { 38 | method := http.MethodGet 39 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetTagListUrl, &method, nil, nil, nil) 40 | if err != nil { 41 | return nil, err 42 | } 43 | response := common.CGetTagListResponse{} 44 | err = json.Unmarshal(resBody, &response) 45 | if err != nil { 46 | return nil, err 47 | } 48 | if response.ErrCode != private.ErrorCodeSuccess { 49 | return nil, errors.New(response.ErrMsg) 50 | } 51 | return &response, nil 52 | } 53 | 54 | func (this *CUser) UpdateTag(request *common.CUpdateTagRequest, timeoutMS int64) error { 55 | b, err := json.Marshal(request) 56 | if err != nil { 57 | return err 58 | } 59 | method := http.MethodPost 60 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &UpdateTagUrl, &method, nil, nil, b) 61 | if err != nil { 62 | return err 63 | } 64 | response := private.CCommonResponse{} 65 | err = json.Unmarshal(resBody, &response) 66 | if err != nil { 67 | return err 68 | } 69 | if response.ErrCode != private.ErrorCodeSuccess { 70 | return errors.New(response.ErrMsg) 71 | } 72 | return nil 73 | } 74 | 75 | func (this *CUser) DeleteTag(request *common.CDeleteTagRequest, timeoutMS int64) error { 76 | b, err := json.Marshal(request) 77 | if err != nil { 78 | return err 79 | } 80 | method := http.MethodPost 81 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &DeleteTagUrl, &method, nil, nil, b) 82 | if err != nil { 83 | return err 84 | } 85 | response := private.CCommonResponse{} 86 | err = json.Unmarshal(resBody, &response) 87 | if err != nil { 88 | return err 89 | } 90 | if response.ErrCode != private.ErrorCodeSuccess { 91 | return errors.New(response.ErrMsg) 92 | } 93 | return nil 94 | } 95 | 96 | func (this *CUser) GetTagUserList(request *common.CGetTagUserListRequest, timeoutMS int64) (*common.CGetTagUserListResponse, error) { 97 | b, err := json.Marshal(request) 98 | if err != nil { 99 | return nil, err 100 | } 101 | method := http.MethodPost 102 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetTagUserListUrl, &method, nil, nil, b) 103 | if err != nil { 104 | return nil, err 105 | } 106 | response := common.CGetTagUserListResponse{} 107 | err = json.Unmarshal(resBody, &response) 108 | if err != nil { 109 | return nil, err 110 | } 111 | if response.ErrCode != private.ErrorCodeSuccess { 112 | return nil, errors.New(response.ErrMsg) 113 | } 114 | return &response, nil 115 | } 116 | 117 | func (this *CUser) AddTagToUsers(request *common.CAddTagToUsersRequest, timeoutMS int64) error { 118 | b, err := json.Marshal(request) 119 | if err != nil { 120 | return err 121 | } 122 | method := http.MethodPost 123 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &AddTagToUsersUrl, &method, nil, nil, b) 124 | if err != nil { 125 | return err 126 | } 127 | response := private.CCommonResponse{} 128 | err = json.Unmarshal(resBody, &response) 129 | if err != nil { 130 | return err 131 | } 132 | if response.ErrCode != private.ErrorCodeSuccess { 133 | return errors.New(response.ErrMsg) 134 | } 135 | return nil 136 | } 137 | 138 | func (this *CUser) DeleteTagToUsers(request *common.CDeleteTagToUsersRequest, timeoutMS int64) error { 139 | b, err := json.Marshal(request) 140 | if err != nil { 141 | return err 142 | } 143 | method := http.MethodPost 144 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &DeleteTagToUsersUrl, &method, nil, nil, b) 145 | if err != nil { 146 | return err 147 | } 148 | response := private.CCommonResponse{} 149 | err = json.Unmarshal(resBody, &response) 150 | if err != nil { 151 | return err 152 | } 153 | if response.ErrCode != private.ErrorCodeSuccess { 154 | return errors.New(response.ErrMsg) 155 | } 156 | return nil 157 | } 158 | 159 | func (this *CUser) GetTagsByUser(request *common.CGetTagsByUserRequest, timeoutMS int64) (*common.CGetTagsByUserResponse, error) { 160 | b, err := json.Marshal(request) 161 | if err != nil { 162 | return nil, err 163 | } 164 | method := http.MethodPost 165 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetTagsByUserUrl, &method, nil, nil, b) 166 | if err != nil { 167 | return nil, err 168 | } 169 | response := common.CGetTagsByUserResponse{} 170 | err = json.Unmarshal(resBody, &response) 171 | if err != nil { 172 | return nil, err 173 | } 174 | if response.ErrCode != private.ErrorCodeSuccess { 175 | return nil, errors.New(response.ErrMsg) 176 | } 177 | return &response, nil 178 | } 179 | 180 | func (this *CUser) UpdateUserRemark(request *common.CUpdateUserRemarkRequest, timeoutMS int64) error { 181 | b, err := json.Marshal(request) 182 | if err != nil { 183 | return err 184 | } 185 | method := http.MethodPost 186 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &UpdateUserRemarkUrl, &method, nil, nil, b) 187 | if err != nil { 188 | return err 189 | } 190 | response := private.CCommonResponse{} 191 | err = json.Unmarshal(resBody, &response) 192 | if err != nil { 193 | return err 194 | } 195 | if response.ErrCode != private.ErrorCodeSuccess { 196 | return errors.New(response.ErrMsg) 197 | } 198 | return nil 199 | } 200 | 201 | func (this *CUser) GetUserBaseInfo(request *common.CGetUserBaseInfoRequest, timeoutMS int64) (*common.CGetUserBaseInfoResponse, error) { 202 | method := http.MethodGet 203 | params := make(map[string]string) 204 | params[GetUserBaseInfoParamOpenId] = request.OpenId 205 | params[GetUserBaseInfoParamLang] = request.Lang 206 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetUserBaseInfoUrl, &method, ¶ms, nil, nil) 207 | if err != nil { 208 | return nil, err 209 | } 210 | response := common.CGetUserBaseInfoResponse{} 211 | err = json.Unmarshal(resBody, &response) 212 | if err != nil { 213 | return nil, err 214 | } 215 | if response.ErrCode != private.ErrorCodeSuccess { 216 | return nil, errors.New(response.ErrMsg) 217 | } 218 | return &response, nil 219 | } 220 | 221 | func (this *CUser) GetUserBaseInfoMulti(request *common.CGetUserBaseInfoMultiRequest, timeoutMS int64) (*common.CGetUserBaseInfoMultiResponse, error) { 222 | b, err := json.Marshal(request) 223 | if err != nil { 224 | return nil, err 225 | } 226 | method := http.MethodPost 227 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetUserBaseInfoMultiUrl, &method, nil, nil, b) 228 | if err != nil { 229 | return nil, err 230 | } 231 | response := common.CGetUserBaseInfoMultiResponse{} 232 | err = json.Unmarshal(resBody, &response) 233 | if err != nil { 234 | return nil, err 235 | } 236 | if response.ErrCode != private.ErrorCodeSuccess { 237 | return nil, errors.New(response.ErrMsg) 238 | } 239 | return &response, nil 240 | } 241 | 242 | func (this *CUser) getFollowUserOnce(nextOpenId *string, openIds *[]string, timeoutMS int64) error { 243 | method := http.MethodGet 244 | params := make(map[string]string) 245 | params[GetFollowUsersParamNextOpenId] = *nextOpenId 246 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetFollowUsersUrl, &method, ¶ms, nil, nil) 247 | if err != nil { 248 | return err 249 | } 250 | response := CSingleUsers{} 251 | err = json.Unmarshal(resBody, &response) 252 | if err != nil { 253 | return err 254 | } 255 | if response.ErrCode != private.ErrorCodeSuccess { 256 | return errors.New(response.ErrMsg) 257 | } 258 | for _, v := range response.Data.OpenId { 259 | *openIds = append(*openIds, v) 260 | } 261 | if response.NextOpenId != "" { 262 | this.getFollowUserOnce(&response.NextOpenId, openIds, timeoutMS) 263 | } 264 | return nil 265 | } 266 | 267 | func (this *CUser) GetFollowUsers(timeoutMS int64) (*common.CGetFollowUsersResponse, error) { 268 | method := http.MethodGet 269 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetFollowUsersUrl, &method, nil, nil, nil) 270 | if err != nil { 271 | return nil, err 272 | } 273 | response := CSingleUsers{} 274 | err = json.Unmarshal(resBody, &response) 275 | if err != nil { 276 | return nil, err 277 | } 278 | if response.ErrCode != private.ErrorCodeSuccess { 279 | return nil, errors.New(response.ErrMsg) 280 | } 281 | if response.NextOpenId != "" { 282 | this.getFollowUserOnce(&response.NextOpenId, &response.Data.OpenId, timeoutMS) 283 | } 284 | var follows common.CGetFollowUsersResponse 285 | follows.OpenIds = response.Data.OpenId 286 | return &follows, nil 287 | } 288 | 289 | func (this *CUser) getBlackListUserOnce(nextOpenId *string, openIds *[]string, timeoutMS int64) error { 290 | request := CGetBlackListSingle{} 291 | request.BeginOpenId = *nextOpenId 292 | b, err := json.Marshal(&request) 293 | if err != nil { 294 | return err 295 | } 296 | method := http.MethodPost 297 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetBlackListUsersUrl, &method, nil, nil, b) 298 | if err != nil { 299 | return err 300 | } 301 | response := CSingleUsers{} 302 | err = json.Unmarshal(resBody, &response) 303 | if err != nil { 304 | return err 305 | } 306 | if response.ErrCode != private.ErrorCodeSuccess { 307 | return errors.New(response.ErrMsg) 308 | } 309 | for _, v := range response.Data.OpenId { 310 | *openIds = append(*openIds, v) 311 | } 312 | if response.NextOpenId != "" { 313 | this.getBlackListUserOnce(&response.NextOpenId, openIds, timeoutMS) 314 | } 315 | return nil 316 | } 317 | 318 | func (this *CUser) GetBlackListUsers(timeoutMS int64) (*common.CGetBlackListUsersResponse, error) { 319 | request := CGetBlackListSingle{} 320 | request.BeginOpenId = "" 321 | b, err := json.Marshal(&request) 322 | if err != nil { 323 | return nil, err 324 | } 325 | method := http.MethodPost 326 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &GetBlackListUsersUrl, &method, nil, nil, b) 327 | if err != nil { 328 | return nil, err 329 | } 330 | response := CSingleUsers{} 331 | err = json.Unmarshal(resBody, &response) 332 | if err != nil { 333 | return nil, err 334 | } 335 | if response.ErrCode != private.ErrorCodeSuccess { 336 | return nil, errors.New(response.ErrMsg) 337 | } 338 | if response.NextOpenId != "" { 339 | this.getBlackListUserOnce(&response.NextOpenId, &response.Data.OpenId, timeoutMS) 340 | } 341 | var blackList common.CGetBlackListUsersResponse 342 | blackList.OpenIds = response.Data.OpenId 343 | return &blackList, nil 344 | } 345 | 346 | func (this *CUser) TakeUsersToBlackList(request *common.CTakeUsersToBlackListRequest, timeoutMS int64) error { 347 | b, err := json.Marshal(request) 348 | if err != nil { 349 | return err 350 | } 351 | method := http.MethodPost 352 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &TakeUsersToBlackListUrl, &method, nil, nil, b) 353 | if err != nil { 354 | return err 355 | } 356 | response := private.CCommonResponse{} 357 | err = json.Unmarshal(resBody, &response) 358 | if err != nil { 359 | return err 360 | } 361 | if response.ErrCode != private.ErrorCodeSuccess { 362 | return errors.New(response.ErrMsg) 363 | } 364 | return nil 365 | } 366 | 367 | func (this *CUser) UnTakeUsersToBlackList(request *common.CUnTakeUsersToBlackListRequest, timeoutMS int64) error { 368 | b, err := json.Marshal(request) 369 | if err != nil { 370 | return err 371 | } 372 | method := http.MethodPost 373 | resBody, err := communicate.SendRequestWithToken(this.m_token, timeoutMS, &UnTakeUsersToBlackListUrl, &method, nil, nil, b) 374 | if err != nil { 375 | return err 376 | } 377 | response := private.CCommonResponse{} 378 | err = json.Unmarshal(resBody, &response) 379 | if err != nil { 380 | return err 381 | } 382 | if response.ErrCode != private.ErrorCodeSuccess { 383 | return errors.New(response.ErrMsg) 384 | } 385 | return nil 386 | } 387 | 388 | func New(token common.IToken) common.IUser { 389 | u := CUser{ 390 | m_token: token, 391 | } 392 | return &u 393 | } 394 | -------------------------------------------------------------------------------- /common/struct.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "encoding/xml" 5 | "time" 6 | ) 7 | 8 | var ( 9 | ErrorCodeSuccess int = 0 10 | ErrorCodeTokenInvaild int = 40001 11 | ) 12 | 13 | var ( 14 | MsgTypeText string = "text" 15 | MsgTypeImage string = "image" 16 | MsgTypeVoice string = "voice" 17 | MsgTypeVideo string = "video" 18 | MsgTypeShortVideo string = "shortvideo" 19 | MsgTypeLocation string = "location" 20 | MsgTypeLink string = "link" 21 | MsgTypeEvent string = "event" 22 | ) 23 | 24 | var ( 25 | MaterialTypeImage string = "image" 26 | MaterialTypeVoice string = "voice" 27 | MaterialTypeVideo string = "video" 28 | MaterialTypeThumb string = "thumb" 29 | MaterialTypeImgText string = "news" 30 | ) 31 | 32 | var ( 33 | GroupSendMsgTypeImgText string = "mpnews" 34 | GroupSendMsgTypeText string = "text" 35 | GroupSendMsgTypeVoice string = "voice" 36 | GroupSendMsgTypeImage string = "image" 37 | GroupSendMsgTypeVideo string = "mpvideo" 38 | GroupSendMsgTypeCard string = "wxcard" 39 | ) 40 | 41 | var ( 42 | // position event 43 | EventTypeLocation string = "LOCATION" 44 | ) 45 | 46 | var ( 47 | ButtonTypeClick string = "click" 48 | ButtonTypeView string = "view" 49 | ButtonTypeScancodeWaitmsg string = "scancode_waitmsg" 50 | ) 51 | 52 | type CUserInfo struct { 53 | AppId string 54 | AppSecret string 55 | Port int 56 | Url string 57 | Token string 58 | } 59 | 60 | type CData string 61 | 62 | func (c CData) MarshelXML(e *xml.Encoder, start xml.StartElement) error { 63 | return e.EncodeElement(struct { 64 | str string `xml:",cdata"` 65 | }{string(c)}, start) 66 | } 67 | 68 | type CWxResXml struct { 69 | XMLName xml.Name `xml:"xml"` 70 | ToUserName CData `xml:"ToUserName"` 71 | FromUserName CData `xml:"FromUserName"` 72 | CreateTime time.Duration `xml:"CreateTime"` 73 | MsgType CData `xml:"MsgType"` 74 | MsgId int64 `xml:"MsgId"` 75 | Content CData `xml:"Content"` 76 | PicUrl CData `xml:"PicUrl"` 77 | MediaId int64 `xml:"MediaId"` 78 | Format CData `xml:"Format"` 79 | ThumbMediaId CData `xml:"ThumbMediaId"` 80 | Location_X float64 `xml:"Location_X"` 81 | Location_Y float64 `xml:"Location_Y"` 82 | Scale int `xml:"Scale"` 83 | Label CData `xml:"Label"` 84 | Title CData `xml:"Title"` 85 | Description CData `xml:"Description"` 86 | Url CData `xml:"Url"` 87 | Event CData `xml:"Event"` 88 | EventKey CData `xml:"EventKey"` 89 | Ticket CData `xml:"Ticket"` 90 | Latitude float64 `xml:"Latitude"` 91 | Longitude float64 `xml:"Longitude"` 92 | Precision float64 `xml:"Precision"` 93 | Status CData `xml:"Status"` 94 | } 95 | 96 | type CDataCommunicate struct { 97 | ToUserName string 98 | FromUserName string 99 | } 100 | 101 | type CMessage struct { 102 | CreateTime time.Duration 103 | MsgType string 104 | MsgId int64 105 | Content string 106 | PicUrl string 107 | MediaId int64 108 | Format string 109 | ThumbMediaId string 110 | LocationX float64 111 | LocationY float64 112 | Scale int 113 | Label string 114 | Title string 115 | Description string 116 | Url string 117 | } 118 | 119 | type CEvent struct { 120 | CreateTime time.Duration 121 | MsgType string 122 | Event string 123 | EventKey string 124 | Ticket string 125 | Latitude float64 126 | Longitude float64 127 | Precision float64 128 | Status string 129 | } 130 | 131 | type CButton struct { 132 | SubButton []CButton `json:"sub_button"` 133 | Type string `json:"type"` 134 | Name string `json:"name"` 135 | Key string `json:"key"` 136 | Url string `json:"url"` 137 | MediaId string `json:"media_id"` 138 | MiniProgramAppId string `json:"appid"` 139 | MiniProgramPagePath string `json:"pagepath"` 140 | } 141 | 142 | type CGetMenuButton struct { 143 | Button []CButton `json:"button"` 144 | } 145 | 146 | type CGetMenuJson struct { 147 | Menu CGetMenuButton `json:"menu"` 148 | ConditionalMenu CGetMenuButton `json:"conditionalmenu"` 149 | } 150 | 151 | type CSetIndustryRequest struct { 152 | FirstIndustryId string `json:"industry_id1"` 153 | SecondIndustryId string `json:"industry_id2"` 154 | } 155 | 156 | type CGetIndustryInfo struct { 157 | FirstClass string `json:"first_class"` 158 | SecondClass string `json:"second_class"` 159 | } 160 | 161 | type CGetIndustryResponse struct { 162 | ErrCode int `json:"errcode"` 163 | ErrMsg string `json:"errmsg"` 164 | PrimaryIndustry CGetIndustryInfo `json:"primary_industry"` 165 | SecondaryIndustry CGetIndustryInfo `json:"secondary_industry"` 166 | } 167 | 168 | type CGetTemplateIdRequest struct { 169 | TemplateLibId string `json:"template_id_short"` 170 | } 171 | 172 | type CGetTemplateIdResponse struct { 173 | ErrCode int `json:"errcode"` 174 | ErrMsg string `json:"errmsg"` 175 | TemplateId string `json:"template_id"` 176 | } 177 | 178 | type CGetTemplateListInfo struct { 179 | TemplateId string `json:"template_id"` 180 | Title string `json:"title"` 181 | PrimaryIndustry string `json:"primary_industry"` 182 | DeputyIndustry string `json:"deputy_industry"` 183 | Content string `json:"content"` 184 | Example string `json:"example"` 185 | } 186 | 187 | type CGetTemplateListResponse struct { 188 | ErrCode int `json:"errcode"` 189 | ErrMsg string `json:"errmsg"` 190 | TemplateList []CGetTemplateListInfo `json:"template_list"` 191 | } 192 | 193 | type CDeleteTemplateRequest struct { 194 | TemplateId string `json:"template_id"` 195 | } 196 | 197 | type CTemplateMessageItem struct { 198 | Value string `json:"value"` 199 | Color string `json:"color"` 200 | } 201 | 202 | type CSendTemplateMsgRequest struct { 203 | Touser string `json:"touser"` 204 | TemplateId string `json:"template_id"` 205 | Url string `json:"url"` 206 | Data map[string]CTemplateMessageItem `json:"data"` 207 | } 208 | 209 | type CSendTemplateMsgResponse struct { 210 | ErrCode int `json:"errcode"` 211 | ErrMsg string `json:"errmsg"` 212 | MsgId int64 `json:"msgid"` 213 | } 214 | 215 | type CCreateTmpMaterialRequest struct { 216 | MaterialType string 217 | Path string 218 | } 219 | 220 | type CCreateTmpMaterialResponse struct { 221 | ErrCode int `json:"errcode"` 222 | ErrMsg string `json:"errmsg"` 223 | Type string `json:"type"` 224 | MediaId string `json:"media_id"` 225 | CreatedAt int64 `json:"created_at"` 226 | } 227 | 228 | type CGetTmpMaterialRequest struct { 229 | MediaId string 230 | } 231 | 232 | type CGetTmpMaterialResponse struct { 233 | ResUrl string 234 | } 235 | 236 | type CGetTmpHDMaterialRequest struct { 237 | MediaId string 238 | } 239 | 240 | type CGetTmpHDMaterialResponse struct { 241 | ResUrl string 242 | } 243 | 244 | type CImgTextMaterial struct { 245 | Title string `json:"title"` 246 | ThumbMediaId string `json:"thumb_media_id"` 247 | Author string `json:"author"` 248 | Digest string `json:"digest"` 249 | ShowCoverPic int `json:"show_cover_pic"` 250 | Content string `json:"content"` 251 | ContentSourceUrl string `json:"content_source_url"` 252 | NeedOpenComment int `json:"need_open_comment"` 253 | OnlyFansCanComment int `json:"only_fans_can_comment"` 254 | Url string `json:"url"` 255 | } 256 | 257 | type CAddForeverImgTextMaterialRequest struct { 258 | Articles []CImgTextMaterial `json:"articles"` 259 | } 260 | 261 | type CAddForeverImgTextMaterialResponse struct { 262 | ErrCode int `json:"errcode"` 263 | ErrMsg string `json:"errmsg"` 264 | MediaId string `json:"media_id"` 265 | } 266 | 267 | type CAddForeverOtherMaterialRequest struct { 268 | MaterialType string 269 | Path string 270 | Title string 271 | Introduction string 272 | } 273 | 274 | type CAddForeverOtherMaterialResponse struct { 275 | ErrCode int `json:"errcode"` 276 | ErrMsg string `json:"errmsg"` 277 | MediaId string `json:"media_id"` 278 | Url string `json:"url"` 279 | } 280 | 281 | type CUploadImageRequest struct { 282 | Media []byte `json:"media"` 283 | } 284 | 285 | type CUploadImageResponse struct { 286 | ErrCode int `json:"errcode"` 287 | ErrMsg string `json:"errmsg"` 288 | Url string `json:"url"` 289 | } 290 | 291 | type CUploadVideoRequest struct { 292 | // get from addOtherMaterial interface 293 | MediaId string `json:"media_id"` 294 | Title string `json:"title"` 295 | Description string `json:"description"` 296 | } 297 | 298 | type CUploadVideoResponse struct { 299 | Type string `json:"type"` 300 | MediaId string `json:"media_id"` 301 | CreatedAt int64 `json:"created_at"` 302 | ErrCode int `json:"errcode"` 303 | ErrMsg string `json:"errmsg"` 304 | } 305 | 306 | type CGetForeverMaterialRequest struct { 307 | MediaId string `json:"media_id"` 308 | } 309 | 310 | type CGetForeverMaterialResponse struct { 311 | NewsItem []CImgTextMaterial `json:"news_item"` 312 | Title string `json:"title"` 313 | Description string `json:"description"` 314 | DownUrl string `json:"down_url"` 315 | ErrCode int `json:"errcode"` 316 | ErrMsg string `json:"errmsg"` 317 | } 318 | 319 | type CDeleteForeverMaterialRequest struct { 320 | MediaId string `json:"media_id"` 321 | } 322 | 323 | type CUpdateForeverImgTextMaterialRequest struct { 324 | MediaId string `json:"media_id"` 325 | Index int `json:"index"` 326 | Articles CImgTextMaterial `json:"articles"` 327 | } 328 | 329 | type CGetMaterialTotalResponse struct { 330 | VoiceCount int `json:"voice_count"` 331 | VideoCount int `json:"video_count"` 332 | ImageCount int `json:"image_count"` 333 | NewsCount int `json:"news_count"` 334 | ErrCode int `json:"errcode"` 335 | ErrMsg string `json:"errmsg"` 336 | } 337 | 338 | type CImgTextMaterialListContent struct { 339 | NewsItem []CImgTextMaterial `json:"news_item"` 340 | } 341 | 342 | type CMaterialListItem struct { 343 | MediaId string `json:"media_id"` 344 | Content CImgTextMaterialListContent `json:"content"` 345 | UpdateTime int64 `json:"update_time"` 346 | Name string `json:"name"` 347 | Url string `json:"url"` 348 | } 349 | 350 | type CGetMaterialListRequest struct { 351 | Type string `json:"type"` 352 | Offset int `json:"offset"` 353 | Count int `json:"count"` 354 | } 355 | 356 | type CGetMaterialListResponse struct { 357 | TotalCount int `json:"total_count"` 358 | ItemCount int `json:"item_count"` 359 | Item []CMaterialListItem `json:"item"` 360 | ErrCode int `json:"errcode"` 361 | ErrMsg string `json:"errmsg"` 362 | } 363 | 364 | type CStorePhotoUrl struct { 365 | PhotoUrl string `json:"photo_url"` 366 | } 367 | 368 | type CStoreBaseInfo struct { 369 | Sid string `json:"sid"` 370 | BusinessName string `json:"business_name"` 371 | BranchName string `json:"branch_name"` 372 | Province string `json:"province"` 373 | City string `json:"city"` 374 | District string `json:"district"` 375 | Address string `json:"address"` 376 | Telephone string `json:"telephone"` 377 | Categories []string `json:"categories"` 378 | OffsetType int `json:"offset_type"` 379 | Longitude float64 `json:"longitude"` 380 | Latitude float64 `json:"latitude"` 381 | PhotoList []CStorePhotoUrl `json:"photo_list"` 382 | Recommend string `json:"recommend"` 383 | Special string `json:"special"` 384 | Introduction string `json:"introduction"` 385 | OpenTime string `json:"open_time"` 386 | AvgPrice int `json:"avg_price"` 387 | AvailableState int `json:"available_state'` 388 | UpdateStatus int `json:"update_status"` 389 | PoiId string `json:"poi_id"` 390 | } 391 | 392 | type CStoreBusiness struct { 393 | BaseInfo CStoreBaseInfo `json:"base_info"` 394 | } 395 | 396 | type CCreateStoreRequest struct { 397 | Business CStoreBusiness `json:"business"` 398 | } 399 | 400 | type CGetStoreRequest struct { 401 | PoiId string `json:"poi_id"` 402 | } 403 | 404 | type CGetStoreResponse struct { 405 | ErrCode int `json:"errcode"` 406 | ErrMsg string `json:"errmsg"` 407 | Business CStoreBusiness `json:"business"` 408 | } 409 | 410 | type CGetStoreListRequest struct { 411 | Begin int `json:"begin"` 412 | Limit int `json:"limit"` 413 | } 414 | 415 | type CGetStoreListResponse struct { 416 | ErrCode int `json:"errcode"` 417 | ErrMsg string `json:"errmsg"` 418 | BusinessList []CStoreBusiness `json:"business_list"` 419 | TotalCount string `json:"total_count"` 420 | } 421 | 422 | type CModifyStoreRequest struct { 423 | Business CStoreBusiness `json:"business"` 424 | } 425 | 426 | type CDeleteStoreRequest struct { 427 | PoiId string `json:"poi_id"` 428 | } 429 | 430 | type CGetCategoryResponse struct { 431 | ErrCode int `json:"errcode"` 432 | ErrMsg string `json:"errmsg"` 433 | CategoryList []string `json:"category_list"` 434 | } 435 | 436 | // user mgr 437 | type CTag struct { 438 | Id int64 `json:"id"` 439 | Name string `json:"name"` 440 | } 441 | 442 | type CTagName struct { 443 | Name string `json:"name"` 444 | } 445 | 446 | type CUserTag struct { 447 | Id int64 `json:"id"` 448 | Name string `json:"name"` 449 | Count int64 `json:"count"` 450 | } 451 | 452 | type CCreateTagRequest struct { 453 | Tag CTagName `json:"tag"` 454 | } 455 | 456 | type CCreateTagResponse struct { 457 | ErrCode int `json:"errcode"` 458 | ErrMsg string `json:"errmsg"` 459 | Tag CTag `json:"tag"` 460 | } 461 | 462 | type CGetTagListResponse struct { 463 | ErrCode int `json:"errcode"` 464 | ErrMsg string `json:"errmsg"` 465 | Tags []CUserTag `json:"tags"` 466 | } 467 | 468 | type CUpdateTagRequest struct { 469 | Tag CTag `json:"tag"` 470 | } 471 | 472 | type CDeleteTagRequest struct { 473 | Tag CTag `json:"tag"` 474 | } 475 | 476 | type CGetTagUserListRequest struct { 477 | TagId int64 `json:tagid"` 478 | NextOpenid string `json:"next_openid"` 479 | } 480 | 481 | type CGetTagUserListResponseData struct { 482 | OpenId []string `json:"openid"` 483 | } 484 | 485 | type CGetTagUserListResponse struct { 486 | ErrCode int `json:"errcode"` 487 | ErrMsg string `json:"errmsg"` 488 | Count int64 `json:"count"` 489 | Data CGetTagUserListResponseData `json:"data"` 490 | NextOpenid string `json:"next_openid"` 491 | } 492 | 493 | type CAddTagToUsersRequest struct { 494 | OpenIdList []string `json:"openid_list"` 495 | TagId int64 `json:"tagid"` 496 | } 497 | 498 | type CDeleteTagToUsersRequest struct { 499 | OpenIdList []string `json:"openid_list"` 500 | TagId int64 `json:"tagid"` 501 | } 502 | 503 | type CGetTagsByUserRequest struct { 504 | OpenId string `json:"openid"` 505 | } 506 | 507 | type CGetTagsByUserResponse struct { 508 | ErrCode int `json:"errcode"` 509 | ErrMsg string `json:"errmsg"` 510 | TagidList []string `json:"tagid_list"` 511 | } 512 | 513 | type CUpdateUserRemarkRequest struct { 514 | OpenId string `json:"openid"` 515 | Remark string `json:"remark"` 516 | } 517 | 518 | type CGetUserBaseInfoRequest struct { 519 | OpenId string 520 | Lang string 521 | } 522 | 523 | type CGetUserBaseInfoResponse struct { 524 | ErrCode int `json:"errcode"` 525 | ErrMsg string `json:"errmsg"` 526 | Subscribe int `json:"subscribe"` 527 | Openid string `json:"openid"` 528 | Nickname string `json:"nickname"` 529 | Sex int `json:"sex"` 530 | Language string `json:"language"` 531 | City string `json:"city"` 532 | Province string `json:"province"` 533 | Country string `json:"country"` 534 | HeadImgUrl string `json:"headimgurl"` 535 | SubscribeTime int64 `json:"subscribe_time"` 536 | UnionId string `json:"unionid"` 537 | Remark string `json:"remark"` 538 | GroupId int `json:"groupid"` 539 | TagidList []int `json:"tagid_list"` 540 | SubscribeScene string `json:"subscribe_scene"` 541 | QrScene uint64 `json:"qr_scene"` 542 | QrSceneStr string `json:"qr_scene_str"` 543 | } 544 | 545 | type CUserInfoMultiQuery struct { 546 | OpenId string `json:"openid"` 547 | Lang string `json:"lang"` 548 | } 549 | 550 | type CGetUserBaseInfoMultiRequest struct { 551 | UserList []CUserInfoMultiQuery `json:"user_list"` 552 | } 553 | 554 | type CUserBaseInfo struct { 555 | Subscribe int `json:"subscribe"` 556 | Openid string `json:"openid"` 557 | Nickname string `json:"nickname"` 558 | Sex int `json:"sex"` 559 | Language string `json:"language"` 560 | City string `json:"city"` 561 | Province string `json:"province"` 562 | Country string `json:"country"` 563 | HeadImgUrl string `json:"headimgurl"` 564 | SubscribeTime int64 `json:"subscribe_time"` 565 | UnionId string `json:"unionid"` 566 | Remark string `json:"remark"` 567 | GroupId int `json:"groupid"` 568 | TagidList []int `json:"tagid_list"` 569 | SubscribeScene string `json:"subscribe_scene"` 570 | QrScene uint64 `json:"qr_scene"` 571 | QrSceneStr string `json:"qr_scene_str"` 572 | } 573 | 574 | type CGetUserBaseInfoMultiResponse struct { 575 | ErrCode int `json:"errcode"` 576 | ErrMsg string `json:"errmsg"` 577 | UserInfoList []CUserBaseInfo `json:"user_info_list"` 578 | } 579 | 580 | type CGetFollowUsersResponse struct { 581 | OpenIds []string 582 | } 583 | 584 | type CGetBlackListUsersResponse struct { 585 | OpenIds []string 586 | } 587 | 588 | type CTakeUsersToBlackListRequest struct { 589 | OpenIdList []string `json:"openid_list"` 590 | } 591 | 592 | type CUnTakeUsersToBlackListRequest struct { 593 | OpenIdList []string `json:"openid_list"` 594 | } 595 | 596 | type CGroupSendFilterInfo struct { 597 | IsToAll bool `json:"is_to_all"` 598 | TagId int `json:"tag_id"` 599 | } 600 | 601 | type CGroupSendCardExt struct { 602 | Code string `json:"code"` 603 | TimeStamp string `json:"timestamp"` 604 | Signature string `json:"signature"` 605 | } 606 | 607 | type CGroupSendMsgContent struct { 608 | MediaId string `json:"media_id"` 609 | Title string `json:"title"` 610 | Description string `json:"description"` 611 | Content string `json:"content"` 612 | CardId string `json:"card_id"` 613 | CardExt CGroupSendCardExt `json:"card_ext"` 614 | } 615 | 616 | type CGroupSendByTagRequest struct { 617 | Filter CGroupSendFilterInfo `json:"filter"` 618 | ImgText CGroupSendMsgContent `json:"mpnews"` 619 | Text CGroupSendMsgContent `json:"text"` 620 | Voice CGroupSendMsgContent `json:"voice"` 621 | Image CGroupSendMsgContent `json:"image"` 622 | Video CGroupSendMsgContent `json:"mpvideo"` 623 | Card CGroupSendMsgContent `json:"wxcard"` 624 | MsgType string `json:"msgtype"` 625 | SendIgnoreReprint int `json:"send_ignore_reprint"` 626 | } 627 | 628 | type CGroupSendByTagResponse struct { 629 | MsgId int64 `json:"msg_id"` 630 | MsgDataId int64 `json:"msg_data_id"` 631 | ErrCode int `json:"errcode"` 632 | ErrMsg string `json:"errmsg"` 633 | } 634 | 635 | type CGroupSendByOpenIdsRequest struct { 636 | Touser []string `json:"touser"` 637 | ImgText CGroupSendMsgContent `json:"mpnews"` 638 | Text CGroupSendMsgContent `json:"text"` 639 | Voice CGroupSendMsgContent `json:"voice"` 640 | Image CGroupSendMsgContent `json:"image"` 641 | Video CGroupSendMsgContent `json:"mpvideo"` 642 | Card CGroupSendMsgContent `json:"wxcard"` 643 | MsgType string `json:"msgtype"` 644 | SendIgnoreReprint int `json:"send_ignore_reprint"` 645 | } 646 | 647 | type CGroupSendByOpenIdsResponse struct { 648 | MsgId int64 `json:"msg_id"` 649 | MsgDataId int64 `json:"msg_data_id"` 650 | ErrCode int `json:"errcode"` 651 | ErrMsg string `json:"errmsg"` 652 | } 653 | 654 | type CDeleteGroupSendRequest struct { 655 | MsgId int64 `json:"msg_id"` 656 | ArticleIdx int `json:"article_idx"` 657 | } 658 | 659 | type CPreviewMessageRequest struct { 660 | ToWxName string `json:"towxname"` 661 | Touser string `json:"touser"` 662 | ImgText CGroupSendMsgContent `json:"mpnews"` 663 | Text CGroupSendMsgContent `json:"text"` 664 | Voice CGroupSendMsgContent `json:"voice"` 665 | Image CGroupSendMsgContent `json:"image"` 666 | Video CGroupSendMsgContent `json:"mpvideo"` 667 | Card CGroupSendMsgContent `json:"wxcard"` 668 | MsgType string `json:"msgtype"` 669 | } 670 | 671 | type CPreviewMessageResponse struct { 672 | MsgId int64 `json:"msg_id"` 673 | ErrCode int `json:"errcode"` 674 | ErrMsg string `json:"errmsg"` 675 | } 676 | 677 | type CCommodityProperty struct { 678 | Id string `json:"id"` 679 | Vid string `json:"vid"` 680 | } 681 | 682 | type CCommoditySkuInfo struct { 683 | Id string `json:"id"` 684 | Vid []string `json:"vid"` 685 | } 686 | 687 | type CCommodityProductBaseDetail struct { 688 | Text string `json:"text"` 689 | Img string `json:"img` 690 | } 691 | 692 | type CCommodityProductBase struct { 693 | CategoryId []string `json:"category_id"` 694 | Property []CCommodityProperty `json:"property"` 695 | Name string `json:"name"` 696 | SkuInfo CCommoditySkuInfo `json:"sku_info"` 697 | MainImg string `json:"main_img"` 698 | DetailHtml string `json:"detail_html"` 699 | Img []string `json:"img"` 700 | Detail []CCommodityProductBaseDetail `json:"detail"` 701 | BuyLimit int `json:"buy_limit"` 702 | } 703 | 704 | type CCommoditySkuListItem struct { 705 | SkuId string `json:"sku_id"` 706 | Price string `json:"price"` 707 | IconUrl string `json:"icon_url"` 708 | ProductCode string `json:"product_code"` 709 | OriPrice int64 `json:"ori_price"` 710 | Quantity int `json:"quantity"` 711 | } 712 | 713 | type CCommodityAttrExtLocation struct { 714 | Country string `json:"country"` 715 | Province string `json:"province"` 716 | City string `json:"city"` 717 | Address string `json:"address"` 718 | } 719 | 720 | type CCommodityAttrExt struct { 721 | Location CCommodityAttrExtLocation `json:"location"` 722 | IsPostFree int `json:"isPostFree"` 723 | IsHasReceipt int `json:"isHasReceipt"` 724 | IsUnderGuaranty int `json:"isUnderGuaranty"` 725 | IsSupportReplace int `json:"isSupportReplace"` 726 | } 727 | 728 | type CCommodityDeliveryInfoExpress struct { 729 | Id int64 `json:"id"` 730 | Price int64 `json:"price"` 731 | } 732 | 733 | type CCommodityDeliveryInfo struct { 734 | DeliveryType int `json:"delivery_type"` 735 | TemplateId int `json:"template_id"` 736 | Express []CCommodityDeliveryInfoExpress `json:"express"` 737 | } 738 | 739 | type CAddCommodityRequest struct { 740 | ProductBase CCommodityProductBase `json:"product_base"` 741 | SkuList []CCommoditySkuListItem `json:"sku_list"` 742 | AttrExt CCommodityAttrExt `json:"attrext"` 743 | DeliveryInfo CCommodityDeliveryInfo `json:"delivery_info"` 744 | } 745 | 746 | type CAddCommodityResponse struct { 747 | ProductId string `json:"product_id"` 748 | ErrCode int `json:"errcode"` 749 | ErrMsg string `json:"errmsg"` 750 | } 751 | 752 | type CDeleteCommodityRequest struct { 753 | ProductId string `json:"product_id"` 754 | } 755 | 756 | type CUpdateCommodityRequest struct { 757 | ProductId string `json:"product_id"` 758 | ProductBase CCommodityProductBase `json:"product_base"` 759 | SkuList []CCommoditySkuListItem `json:"sku_list"` 760 | AttrExt CCommodityAttrExt `json:"attrext"` 761 | DeliveryInfo CCommodityDeliveryInfo `json:"delivery_info"` 762 | } 763 | 764 | type CCommodityDetail struct { 765 | ProductBase CCommodityProductBase `json:"product_base"` 766 | SkuList []CCommoditySkuListItem `json:"sku_list"` 767 | AttrExt CCommodityAttrExt `json:"attrext"` 768 | DeliveryInfo CCommodityDeliveryInfo `json:"delivery_info"` 769 | } 770 | 771 | type CGetCommodityRequest struct { 772 | ProductId string `json:"product_id"` 773 | } 774 | 775 | type CGetCommodityResponse struct { 776 | ProductInfo CCommodityDetail `json:"product_info"` 777 | ErrCode int `json:"errcode"` 778 | ErrMsg string `json:"errmsg"` 779 | } 780 | 781 | type CGetCommodityByStatusRequest struct { 782 | CommodityStatus int `json:"status"` 783 | } 784 | 785 | type CGetCommodityByStatusResponse struct { 786 | ProductInfo []CCommodityDetail `json:"product_info"` 787 | ErrCode int `json:"errcode"` 788 | ErrMsg string `json:"errmsg"` 789 | } 790 | 791 | type CUpdateCommodityStatusRequest struct { 792 | ProductId string `json:"product_id"` 793 | CommodityStatus int `json:"status"` 794 | } 795 | 796 | type CGetSubClassesByClassifyRequest struct { 797 | CateId int64 `json:"cate_id"` 798 | } 799 | 800 | type CCommodityCateInfo struct { 801 | Id string `json:"id"` 802 | Name string `json:"name"` 803 | } 804 | 805 | type CGetSubClassesByClassifyResponse struct { 806 | CateList []CCommodityCateInfo `json:"cate_list"` 807 | ErrCode int `json:"errcode"` 808 | ErrMsg string `json:"errmsg"` 809 | } 810 | 811 | type CGetAllSkuByClassifyRequest struct { 812 | CateId string `json:"cate_id"` 813 | } 814 | 815 | type CCommoditySkuValueList struct { 816 | Id string `json:"id"` 817 | Name string `json:"name"` 818 | } 819 | 820 | type CCommoditySkuTable struct { 821 | Id string `json:"id"` 822 | Name string `json:"name"` 823 | ValueList []CCommoditySkuValueList `json:"value_list"` 824 | } 825 | 826 | type CGetAllSkuByClassifyResponse struct { 827 | SkuTable CCommoditySkuTable `json:"sku_table"` 828 | ErrCode int `json:"errcode"` 829 | ErrMsg string `json:"errmsg"` 830 | } 831 | 832 | type CGetAllPropertyByClassifyRequest struct { 833 | CateId string `json:"cate_id"` 834 | } 835 | 836 | type CCommodityClassifyPropertyValue struct { 837 | Id string `json:"id"` 838 | Name string `json:"name"` 839 | } 840 | 841 | type CCommodityClassifyProperty struct { 842 | Id string `json:"id"` 843 | Name string `json:"name"` 844 | PropertyValue []CCommodityClassifyPropertyValue `json:"property_value"` 845 | } 846 | 847 | type CGetAllPropertyByClassifyResponse struct { 848 | Properties CCommodityClassifyProperty `json:"properties"` 849 | ErrCode int `json:"errcode"` 850 | ErrMsg string `json:"errmsg"` 851 | } 852 | 853 | type CStockSkuInfo struct { 854 | Id string 855 | Vid string 856 | } 857 | 858 | type CAddStockRequest struct { 859 | ProductId string 860 | SkuInfo []CStockSkuInfo 861 | Quantity int 862 | } 863 | 864 | type CReduceStockRequest struct { 865 | ProductId string 866 | SkuInfo []CStockSkuInfo 867 | Quantity int 868 | } 869 | 870 | type CPayByPaymentCodeRequest struct { 871 | Key string 872 | SignType string 873 | MchId string 874 | DeviceInfo string 875 | Body string 876 | Detail string 877 | Attach string 878 | OutTradeNo string 879 | TotalFee int 880 | FeeType string 881 | SpbillCreateIp string 882 | GoodsTag string 883 | LimitPay string 884 | TimeStart string 885 | TimeExpire string 886 | Receipt string 887 | AuthCode string 888 | SceneInfo string 889 | } 890 | 891 | type CPayByPaymentCodeResponse struct { 892 | XMLName xml.Name `xml:"xml"` 893 | ReturnCode string `xml:"return_code"` 894 | ReturnMsg string `xml:"return_msg"` 895 | Appid string `xml:"appid"` 896 | MchId string `xml:"mch_id"` 897 | DeviceInfo string `xml:"device_info"` 898 | NonceStr string `xml:"nonce_str"` 899 | Sign string `xml:"sign"` 900 | ResultCode string `xml:"result_code"` 901 | ErrCode string `xml:"err_code"` 902 | ErrCodeDes string `xml:"err_code_des"` 903 | OpenId string `xml:"openid"` 904 | IsSubscribe string `xml:"is_subscribe"` 905 | TradeType string `xml:"trade_type"` 906 | TradeState string `xml:"trade_state"` 907 | BankType string `xml:"bank_type"` 908 | FeeType string `xml:"fee_type"` 909 | TotalFee int `xml:"total_fee"` 910 | SettlementTotalFee int `xml:"settlement_total_fee"` 911 | CouponFee int `xml:"coupon_fee"` 912 | CouponCount int `xml:"coupon_count"` 913 | CouponType int `xml:"coupon_type_$n"` 914 | CashFeeType string `xml:"cash_fee_type"` 915 | CashFee int `xml:"cash_fee"` 916 | TransactionId string `xml:"transaction_id"` 917 | OutTradeNo string `xml:"out_trade_no"` 918 | Attach string `xml:"attach"` 919 | TimeEnd string `xml:"time_end"` 920 | PromotionDetail string `xml:"promotion_detail"` 921 | } 922 | 923 | type CQueryOrderRequest struct { 924 | MchId string 925 | TransactionId string 926 | OutTradeNo string 927 | SignType string 928 | } 929 | --------------------------------------------------------------------------------