Documentation ¶
Overview ¶
微信公众平台(订阅号, 服务号)SDK
Index ¶
- Constants
- Variables
- func HttpResponseWriter(w io.Writer) http.ResponseWriter
- func ServeHTTP(w http.ResponseWriter, r *http.Request, urlValues url.Values, ...)
- func WriteAESResponse(w http.ResponseWriter, r *Request, msg interface{}) (err error)
- func WriteRawResponse(w http.ResponseWriter, r *Request, msg interface{}) (err error)
- type CommonMessageHeader
- type DefaultTokenServer
- type DefaultWechatServer
- func (srv *DefaultWechatServer) AppId() string
- func (srv *DefaultWechatServer) CurrentAESKey() (key [32]byte)
- func (srv *DefaultWechatServer) LastAESKey() (key [32]byte)
- func (srv *DefaultWechatServer) MessageHandler() MessageHandler
- func (srv *DefaultWechatServer) Token() string
- func (srv *DefaultWechatServer) UpdateAESKey(AESKey []byte) (err error)
- func (srv *DefaultWechatServer) WechatId() string
- type Error
- type InvalidRequestHandler
- type InvalidRequestHandlerFunc
- type MessageHandler
- type MessageHandlerFunc
- type MessageServeMux
- func (mux *MessageServeMux) DefaultEventHandle(handler MessageHandler)
- func (mux *MessageServeMux) DefaultEventHandleFunc(handler func(http.ResponseWriter, *Request))
- func (mux *MessageServeMux) DefaultMessageHandle(handler MessageHandler)
- func (mux *MessageServeMux) DefaultMessageHandleFunc(handler func(http.ResponseWriter, *Request))
- func (mux *MessageServeMux) EventHandle(eventType string, handler MessageHandler)
- func (mux *MessageServeMux) EventHandleFunc(eventType string, handler func(http.ResponseWriter, *Request))
- func (mux *MessageServeMux) MessageHandle(msgType string, handler MessageHandler)
- func (mux *MessageServeMux) MessageHandleFunc(msgType string, handler func(http.ResponseWriter, *Request))
- func (mux *MessageServeMux) ServeMessage(w http.ResponseWriter, r *Request)
- type MixedMessage
- type MultiWechatServerFrontend
- func (frontend *MultiWechatServerFrontend) DeleteAllWechatServer()
- func (frontend *MultiWechatServerFrontend) DeleteWechatServer(serverKey string)
- func (frontend *MultiWechatServerFrontend) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (frontend *MultiWechatServerFrontend) SetInvalidRequestHandler(handler InvalidRequestHandler)
- func (frontend *MultiWechatServerFrontend) SetWechatServer(serverKey string, server WechatServer)
- type Request
- type RequestHttpBody
- type ResponseHttpBody
- type TokenServer
- type WechatClient
- func (clt *WechatClient) GetCallbackIP() (ipList []string, err error)
- func (clt *WechatClient) GetJSON(incompleteURL string, response interface{}) (err error)
- func (clt *WechatClient) PostJSON(incompleteURL string, request interface{}, response interface{}) (err error)
- func (clt *WechatClient) UploadFromReader(incompleteURL, filename string, reader io.Reader, response interface{}) (err error)
- type WechatServer
- type WechatServerFrontend
Constants ¶
const ( ErrCodeOK = 0 ErrCodeInvalidCredential = 40001 // access_token 过期(无效)返回这个错误 ErrCodeTimeout = 42001 // access_token 过期(无效)返回这个错误(maybe!!!) )
const URLQueryWechatServerKeyName = "wechat_server"
回调 URL 上索引 WechatServer 的 key 的名称.
比如下面的回调地址里面就可以根据 wechat1 来索引对应的 WechatServer. http://www.xxx.com/?wechat_server=wechat1&signature=XXX×tamp=123456789&nonce=12345678
Variables ¶
var DefaultInvalidRequestHandler = InvalidRequestHandlerFunc(func(http.ResponseWriter, *http.Request, error) {})
var MediaHttpClient = &http.Client{ Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, Dial: (&net.Dialer{ Timeout: 5 * time.Second, KeepAlive: 30 * time.Second, }).Dial, TLSHandshakeTimeout: 5 * time.Second, }, Timeout: 300 * time.Second, }
多媒体上传下载请求的 http.Client
var TextHttpClient = &http.Client{ Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, Dial: (&net.Dialer{ Timeout: 5 * time.Second, KeepAlive: 30 * time.Second, }).Dial, TLSHandshakeTimeout: 5 * time.Second, }, Timeout: 15 * time.Second, }
一般请求的 http.Client
Functions ¶
func HttpResponseWriter ¶
func HttpResponseWriter(w io.Writer) http.ResponseWriter
将 io.Writer 从语义上实现 http.ResponseWriter.
某些 http 框架可能没有提供 http.ResponseWriter, 而只是提供了 io.Writer.
func ServeHTTP ¶
func ServeHTTP(w http.ResponseWriter, r *http.Request, urlValues url.Values, wechatServer WechatServer, invalidRequestHandler InvalidRequestHandler)
ServeHTTP 处理 http 消息请求
NOTE: 调用者保证所有参数有效
func WriteAESResponse ¶
func WriteAESResponse(w http.ResponseWriter, r *Request, msg interface{}) (err error)
回复消息给微信服务器(安全模式).
要求 msg 是有效的消息数据结构(经过 encoding/xml marshal 后符合消息的格式); 如果有必要可以修改 Request 里面的某些值, 比如 TimeStamp.
func WriteRawResponse ¶
func WriteRawResponse(w http.ResponseWriter, r *Request, msg interface{}) (err error)
回复消息给微信服务器(明文模式).
要求 msg 是有效的消息数据结构(经过 encoding/xml marshal 后符合消息的格式); 如果有必要可以修改 Request 里面的某些值, 比如 TimeStamp.
Types ¶
type CommonMessageHeader ¶
type CommonMessageHeader struct { ToUserName string `xml:"ToUserName" json:"ToUserName"` FromUserName string `xml:"FromUserName" json:"FromUserName"` CreateTime int64 `xml:"CreateTime" json:"CreateTime"` MsgType string `xml:"MsgType" json:"MsgType"` }
微信服务器推送过来的消息(事件)通用的消息头
type DefaultTokenServer ¶
type DefaultTokenServer struct {
// contains filtered or unexported fields
}
TokenServer 的简单实现.
NOTE: 1. 用于单进程环境. 2. 因为 DefaultTokenServer 同时也是一个简单的中控服务器, 而不是仅仅实现 TokenServer 接口, 所以整个系统只能存在一个 DefaultTokenServer 实例!
func NewDefaultTokenServer ¶
func NewDefaultTokenServer(appId, appSecret string, httpClient *http.Client) (srv *DefaultTokenServer)
创建一个新的 DefaultTokenServer.
如果 httpClient == nil 则默认使用 http.DefaultClient.
func (*DefaultTokenServer) Token ¶
func (srv *DefaultTokenServer) Token() (token string, err error)
func (*DefaultTokenServer) TokenRefresh ¶
func (srv *DefaultTokenServer) TokenRefresh() (token string, err error)
type DefaultWechatServer ¶
type DefaultWechatServer struct {
// contains filtered or unexported fields
}
func NewDefaultWechatServer ¶
func NewDefaultWechatServer(wechatId, token, appId string, AESKey []byte, messageHandler MessageHandler) (srv *DefaultWechatServer)
NewDefaultWechatServer 创建一个新的 DefaultWechatServer.
如果不知道自己的 AppId 是多少, 可以先随便填入一个字符串, 这样正常情况下会出现 AppId mismatch 错误, 错误的 have 后面的就是正确的 AppId.
func (*DefaultWechatServer) AppId ¶
func (srv *DefaultWechatServer) AppId() string
func (*DefaultWechatServer) CurrentAESKey ¶
func (srv *DefaultWechatServer) CurrentAESKey() (key [32]byte)
func (*DefaultWechatServer) LastAESKey ¶
func (srv *DefaultWechatServer) LastAESKey() (key [32]byte)
func (*DefaultWechatServer) MessageHandler ¶
func (srv *DefaultWechatServer) MessageHandler() MessageHandler
func (*DefaultWechatServer) Token ¶
func (srv *DefaultWechatServer) Token() string
func (*DefaultWechatServer) UpdateAESKey ¶
func (srv *DefaultWechatServer) UpdateAESKey(AESKey []byte) (err error)
func (*DefaultWechatServer) WechatId ¶
func (srv *DefaultWechatServer) WechatId() string
type InvalidRequestHandler ¶
type InvalidRequestHandler interface { // err 是错误信息 ServeInvalidRequest(w http.ResponseWriter, r *http.Request, err error) }
无效请求(非法或者错误)的处理接口.
type InvalidRequestHandlerFunc ¶
type InvalidRequestHandlerFunc func(http.ResponseWriter, *http.Request, error)
func (InvalidRequestHandlerFunc) ServeInvalidRequest ¶
func (fn InvalidRequestHandlerFunc) ServeInvalidRequest(w http.ResponseWriter, r *http.Request, err error)
type MessageHandler ¶
type MessageHandler interface {
ServeMessage(w http.ResponseWriter, r *Request)
}
微信服务器推送过来的消息(事件)处理接口
type MessageHandlerFunc ¶
type MessageHandlerFunc func(http.ResponseWriter, *Request)
func (MessageHandlerFunc) ServeMessage ¶
func (fn MessageHandlerFunc) ServeMessage(w http.ResponseWriter, r *Request)
type MessageServeMux ¶
type MessageServeMux struct {
// contains filtered or unexported fields
}
MessageServeMux 实现了一个简单的消息路由器, 同时也是一个 MessageHandler.
func NewMessageServeMux ¶
func NewMessageServeMux() *MessageServeMux
func (*MessageServeMux) DefaultEventHandle ¶
func (mux *MessageServeMux) DefaultEventHandle(handler MessageHandler)
注册 MessageHandler, 处理未知类型的事件.
func (*MessageServeMux) DefaultEventHandleFunc ¶
func (mux *MessageServeMux) DefaultEventHandleFunc(handler func(http.ResponseWriter, *Request))
注册 MessageHandlerFunc, 处理未知类型的事件.
func (*MessageServeMux) DefaultMessageHandle ¶
func (mux *MessageServeMux) DefaultMessageHandle(handler MessageHandler)
注册 MessageHandler, 处理未知类型的消息.
func (*MessageServeMux) DefaultMessageHandleFunc ¶
func (mux *MessageServeMux) DefaultMessageHandleFunc(handler func(http.ResponseWriter, *Request))
注册 MessageHandlerFunc, 处理未知类型的消息.
func (*MessageServeMux) EventHandle ¶
func (mux *MessageServeMux) EventHandle(eventType string, handler MessageHandler)
注册 MessageHandler, 处理特定类型的事件.
func (*MessageServeMux) EventHandleFunc ¶
func (mux *MessageServeMux) EventHandleFunc(eventType string, handler func(http.ResponseWriter, *Request))
注册 MessageHandlerFunc, 处理特定类型的事件.
func (*MessageServeMux) MessageHandle ¶
func (mux *MessageServeMux) MessageHandle(msgType string, handler MessageHandler)
注册 MessageHandler, 处理特定类型的消息.
func (*MessageServeMux) MessageHandleFunc ¶
func (mux *MessageServeMux) MessageHandleFunc(msgType string, handler func(http.ResponseWriter, *Request))
注册 MessageHandlerFunc, 处理特定类型的消息.
func (*MessageServeMux) ServeMessage ¶
func (mux *MessageServeMux) ServeMessage(w http.ResponseWriter, r *Request)
MessageServeMux 实现了 MessageHandler 接口.
type MixedMessage ¶
type MixedMessage struct { XMLName struct{} `xml:"xml" json:"-"` CommonMessageHeader // fuck, MsgId != MsgID MsgId int64 `xml:"MsgId" json:"MsgId"` MsgID int64 `xml:"MsgID" json:"MsgID"` Content string `xml:"Content" json:"Content"` MediaId string `xml:"MediaId" json:"MediaId"` PicURL string `xml:"PicUrl" json:"PicUrl"` Format string `xml:"Format" json:"Format"` Recognition string `xml:"Recognition" json:"Recognition"` ThumbMediaId string `xml:"ThumbMediaId" json:"ThumbMediaId"` LocationX float64 `xml:"Location_X" json:"Location_X"` LocationY float64 `xml:"Location_Y" json:"Location_Y"` Scale int `xml:"Scale" json:"Scale"` Label string `xml:"Label" json:"Label"` Title string `xml:"Title" json:"Title"` Description string `xml:"Description" json:"Description"` URL string `xml:"Url" json:"Url"` Event string `xml:"Event" json:"Event"` EventKey string `xml:"EventKey" json:"EventKey"` ScanCodeInfo struct { ScanType string `xml:"ScanType" json:"ScanType"` ScanResult string `xml:"ScanResult" json:"ScanResult"` } `xml:"ScanCodeInfo" json:"ScanCodeInfo"` SendPicsInfo struct { Count int `xml:"Count" json:"Count"` PicList []struct { PicMD5Sum string `xml:"PicMd5Sum" json:"PicMd5Sum"` } `xml:"PicList>item,omitempty" json:"PicList,omitempty"` } `xml:"SendPicsInfo" json:"SendPicsInfo"` SendLocationInfo struct { LocationX float64 `xml:"Location_X" json:"Location_X"` LocationY float64 `xml:"Location_Y" json:"Location_Y"` Scale int `xml:"Scale" json:"Scale"` Label string `xml:"Label" json:"Label"` Poiname string `xml:"Poiname" json:"Poiname"` } `xml:"SendLocationInfo" json:"SendLocationInfo"` Ticket string `xml:"Ticket" json:"Ticket"` Latitude float64 `xml:"Latitude" json:"Latitude"` Longitude float64 `xml:"Longitude" json:"Longitude"` Precision float64 `xml:"Precision" json:"Precision"` Status string `xml:"Status" json:"Status"` TotalCount int `xml:"TotalCount" json:"TotalCount"` FilterCount int `xml:"FilterCount" json:"FilterCount"` SentCount int `xml:"SentCount" json:"SentCount"` ErrorCount int `xml:"ErrorCount" json:"ErrorCount"` OrderId string `xml:"OrderId" json:"OrderId"` OrderStatus int `xml:"OrderStatus" json:"OrderStatus"` ProductId string `xml:"ProductId" json:"ProductId"` SKUInfo string `xml:"SkuInfo" json:"SkuInfo"` CardId string `xml:"CardId" json:"CardId"` IsGiveByFriend int `xml:"IsGiveByFriend" json:"IsGiveByFriend"` FriendUserName string `xml:"FriendUserName" json:"FriendUserName"` UserCardCode string `xml:"UserCardCode" json:"UserCardCode"` OuterId int64 `xml:"OuterId" json:"OuterId"` }
微信服务器推送过来的消息(事件)的合集.
type MultiWechatServerFrontend ¶
type MultiWechatServerFrontend struct {
// contains filtered or unexported fields
}
多个 WechatServer 的前端, 负责处理 http 请求, net/http.Handler 的实现
NOTE: MultiWechatServerFrontend 可以处理多个公众号的消息(事件),但是要求在回调 URL 上加上一个 查询参数,参考常量 URLQueryWechatServerKeyName,这个参数的值就是 MultiWechatServerFrontend 索引 WechatServer 的 key。 例如回调 URL 为 http://www.xxx.com/weixin?wechat_server=1234567890,那么就可以在后端调用 MultiWechatServerFrontend.SetWechatServer("1234567890", WechatServer) 来增加一个 WechatServer 来处理 wechat_server=1234567890 的消息(事件)。 MultiWechatServerFrontend 并发安全,可以在运行中动态增加和删除 WechatServer。
func (*MultiWechatServerFrontend) DeleteAllWechatServer ¶
func (frontend *MultiWechatServerFrontend) DeleteAllWechatServer()
删除所有的 WechatServer
func (*MultiWechatServerFrontend) DeleteWechatServer ¶
func (frontend *MultiWechatServerFrontend) DeleteWechatServer(serverKey string)
删除 serverKey 对应的 WechatServer
func (*MultiWechatServerFrontend) ServeHTTP ¶
func (frontend *MultiWechatServerFrontend) ServeHTTP(w http.ResponseWriter, r *http.Request)
实现 http.Handler
func (*MultiWechatServerFrontend) SetInvalidRequestHandler ¶
func (frontend *MultiWechatServerFrontend) SetInvalidRequestHandler(handler InvalidRequestHandler)
设置 InvalidRequestHandler, 如果 handler == nil 则使用默认的 DefaultInvalidRequestHandler
func (*MultiWechatServerFrontend) SetWechatServer ¶
func (frontend *MultiWechatServerFrontend) SetWechatServer(serverKey string, server WechatServer)
设置 serverKey-WechatServer pair. 如果 serverKey == "" 或者 server == nil 则不做任何操作
type Request ¶
type Request struct { HttpRequest *http.Request // 可以为 nil, 因为某些 http 框架没有提供此参数 QueryValues url.Values // 回调请求 URL 中的查询参数集合 Signature string // 回调请求 URL URL 中的签名: signature TimeStamp int64 // 回调请求 URL URL 中的时间戳: timestamp Nonce string // 回调请求 URL URL 中的随机数: nonce RawMsgXML []byte // "明文"消息的 XML 文本 MixedMsg *MixedMessage // RawMsgXML 解析后的消息 // 下面的字段是 AES 模式才有的 MsgSignature string // 请求 URL 中的消息体签名: msg_signature EncryptType string // 请求 URL 中的加密方式: encrypt_type AESKey [32]byte // 当前消息 AES 加密的 key Random []byte // 当前消息加密时所用的 random, 16 bytes // 下面字段是公众号的基本信息 WechatId string // 请求消息所属公众号的原始 ID, 等于 MixedMessage.ToUserName WechatToken string // 请求消息所属公众号的 Token WechatAppId string // 请求消息所属公众号的 AppId }
消息(事件)请求信息
type RequestHttpBody ¶
type RequestHttpBody struct { XMLName struct{} `xml:"xml" json:"-"` MixedMessage // ToUserName 始终有效 EncryptedMsg string `xml:"Encrypt" json:"Encrypt"` }
安全模式 和 兼容模式, 微信服务器推送过来的 http body
type ResponseHttpBody ¶
type ResponseHttpBody struct { XMLName struct{} `xml:"xml" json:"-"` EncryptedMsg string `xml:"Encrypt"` MsgSignature string `xml:"MsgSignature"` TimeStamp int64 `xml:"TimeStamp"` Nonce string `xml:"Nonce"` }
安全模式回复消息的 http body
type TokenServer ¶
type TokenServer interface { // 从中控服务器获取被缓存的 access_token. Token() (token string, err error) // 请求中控服务器到微信服务器刷新 access_token. // // 高并发场景下某个时间点可能有很多请求(比如缓存的access_token刚好过期时), 但是我们 // 不期望也没有必要让这些请求都去微信服务器获取 access_token(有可能导致api超过调用限制), // 实际上这些请求只需要一个新的 access_token 即可, 所以建议 TokenServer 从微信服务器 // 获取一次 access_token 之后的至多5秒内(收敛时间, 视情况而定, 理论上至多5个http或tcp周期) // 再次调用该函数不再去微信服务器获取, 而是直接返回之前的结果. TokenRefresh() (token string, err error) }
access_token 中控服务器接口, see token_server.png
type WechatClient ¶
type WechatClient struct { TokenServer HttpClient *http.Client }
微信公众号"主动"请求功能的基本封装.
func (*WechatClient) GetCallbackIP ¶
func (clt *WechatClient) GetCallbackIP() (ipList []string, err error)
如果公众号基于安全等考虑,需要获知微信服务器的IP地址列表,以便进行相关限制, 可以通过该接口获得微信服务器IP地址列表。
func (*WechatClient) GetJSON ¶
func (clt *WechatClient) GetJSON(incompleteURL string, response interface{}) (err error)
GET 微信资源, 然后将微信服务器返回的 JSON 用 encoding/json 解析到 response.
NOTE: 1. 一般不用调用这个方法, 请直接调用高层次的封装方法; 2. 最终的 URL == incompleteURL + access_token; 3. response 要求是 struct 的指针, 并且该 struct 拥有属性: ErrCode int `json:"errcode"` (可以是直接属性, 也可以是匿名属性里的属性)
func (*WechatClient) PostJSON ¶
func (clt *WechatClient) PostJSON(incompleteURL string, request interface{}, response interface{}) (err error)
用 encoding/json 把 request marshal 为 JSON, 放入 http 请求的 body 中, POST 到微信服务器, 然后将微信服务器返回的 JSON 用 encoding/json 解析到 response.
NOTE: 1. 一般不用调用这个方法, 请直接调用高层次的封装方法; 2. 最终的 URL == incompleteURL + access_token; 3. response 要求是 struct 的指针, 并且该 struct 拥有属性: ErrCode int `json:"errcode"` (可以是直接属性, 也可以是匿名属性里的属性)
func (*WechatClient) UploadFromReader ¶
func (clt *WechatClient) UploadFromReader(incompleteURL, filename string, reader io.Reader, response interface{}) (err error)
通用上传接口.
NOTE: 1. 一般不用调用这个方法, 请直接调用高层次的封装方法; 2. 最终的 URL == incompleteURL + access_token; 3. 参数 filename 不是文件路径, 是指定 multipart/form-data 里面文件名称 4. response 要求是 struct 的指针, 并且该 struct 拥有属性: ErrCode int `json:"errcode"` (可以是直接属性, 也可以是匿名属性里的属性)
type WechatServer ¶
type WechatServer interface { WechatId() string // 获取公众号的原始ID, 等于后台中的 公众号设置-->帐号详情-->原始ID Token() string // 获取公众号的Token, 和后台中的设置相等 AppId() string // 获取公众号的 AppId CurrentAESKey() [32]byte // 获取当前有效的 AES 加密 Key LastAESKey() [32]byte // 获取最后一个有效的 AES 加密 Key MessageHandler() MessageHandler // 获取 MessageHandler }
公众号服务端接口, 处理单个公众号的消息(事件)请求.
type WechatServerFrontend ¶
type WechatServerFrontend struct {
// contains filtered or unexported fields
}
实现了 http.Handler, 处理一个公众号的消息(事件)请求.
func NewWechatServerFrontend ¶
func NewWechatServerFrontend(server WechatServer, handler InvalidRequestHandler) *WechatServerFrontend
func (*WechatServerFrontend) ServeHTTP ¶
func (frontend *WechatServerFrontend) ServeHTTP(w http.ResponseWriter, r *http.Request)
实现 http.Handler.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
帐号管理接口.
|
帐号管理接口. |
微信卡券接口, V1.9
|
微信卡券接口, V1.9 |
数据统计接口.
|
数据统计接口. |
多客服接口.
|
多客服接口. |
js-sdk 服务器端接口.
|
js-sdk 服务器端接口. |
媒体相关操作.
|
媒体相关操作. |
自定义菜单接口.
|
自定义菜单接口. |
消息(接收和发送)接口.
|
消息(接收和发送)接口. |
custom
客服主动回复消息.
|
客服主动回复消息. |
mass
群发消息.
|
群发消息. |
mass/mass2all
群发消息给所有用户.
|
群发消息给所有用户. |
mass/mass2group
根据分组进行群发消息.
|
根据分组进行群发消息. |
mass/mass2users
根据OpenID列表群发消息.
|
根据OpenID列表群发消息. |
mass/preview
预览接口.
|
预览接口. |
request
被动接收基本的消息(事件).
|
被动接收基本的消息(事件). |
response
被动回复用户消息.
|
被动回复用户消息. |
template
模板消息接口.
|
模板消息接口. |
用户管理接口.
|
用户管理接口. |
oauth2
网页授权获取用户基本信息.
|
网页授权获取用户基本信息. |