server

package
v0.0.0-...-5f3fc38 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 22, 2015 License: Apache-2.0 Imports: 13 Imported by: 0

README

简介

封装微信服务器推送到回调 URL 的消息(事件)处理 Handler.

注意

server 提供了 AgentFrontend,MultiAgentFrontend

正常情况下使用 AgentFrontend 即可,即一个回调 URL 只能接受一个企业号应用的消息(事件), 如果需要处理多个企业号应用的消息(事件),可以调用 net/http.Handle 来动态增加 URL<-->AgentFrontend pair。

如果某些特殊情况下,给你的 URL 只有一个,但是你又想处理多个企业号应用的消息(事件),我们这里提供了 MultiAgentFrontend,这时企业号应用的回调 URL 就要增加一个查询参数 agentkey(根据需要你也可以 更改这个参数名称,如果更改了同时也要修改 URLQueryAgentKeyName 的值),这样回调 URL 的格式一般为

http://abc.xyz.com/weixin?agentkey=agentkey_value

MultiAgentFrontend 是并发安全的,可以动态增加(删除)Agent,如果你没有动态需求, 只是在初始化的时候配置各种参数,可以自己把 MultiAgentFrontend 里面的带有 rwmutex 的代码 都去掉,高并发没有锁的开销。

示例

package main

import (
	"log"
	"net/http"
	"time"

	"github.com/chanxuehong/wechat/corp/message/passive/request"
	"github.com/chanxuehong/wechat/corp/message/passive/response"
	"github.com/chanxuehong/wechat/corp/server"
	"github.com/chanxuehong/wechat/util"
)

// 实现 server.Agent
type CustomAgent struct {
	server.DefaultAgent // 可选, 不是必须!!! 提供了默认实现
}

// 文本消息处理函数
func (this *CustomAgent) ServeTextMsg(w http.ResponseWriter, r *http.Request,
	msg *request.Text, rawXMLMsg []byte, timestamp int64, nonce string, random []byte) {

	// TODO: 示例代码, 把用户发送过来的文本原样回复过去

	w.Header().Set("Content-Type", "application/xml; charset=utf-8") // 可选

	// NOTE: 时间戳也可以用传入的参数 timestamp, 即微信服务器请求 URL 中的 timestamp
	resp := response.NewText(msg.FromUserName, msg.ToUserName, msg.Content, time.Now().Unix())

	// timestamp, nonce, random 也可以自己生成
	if err := server.WriteText(w, resp, timestamp, nonce, this.GetAESKey(), random, this.GetCorpId(), this.GetToken()); err != nil {
		// TODO: 错误处理代码
	}
}

// 自定义错误请求处理函数
func CustomInvalidRequestHandlerFunc(w http.ResponseWriter, r *http.Request, err error) {
	// TODO: 这里只是简单的做下 log
	log.Println(err)
}

func init() {
	AESKey, err := util.AESKeyDecode("EncodingAESKey") // 后台里获取
	if err != nil {
		panic(err)
	}

	var agent CustomAgent
	agent.DefaultAgent.Init("CorpId", 1 /*AgentId*/, "Token", AESKey)

	agentFrontend := server.NewAgentFrontend(&agent,
		server.InvalidRequestHandlerFunc(CustomInvalidRequestHandlerFunc))

	// 注册这个 agentFrontend 到回调 URL 上
	// 比如你在公众平台后台注册的回调地址是 http://abc.xyz.com/weixin,那么可以这样注册
	http.Handle("/weixin", agentFrontend)
}

func main() {
	err := http.ListenAndServe(":80", nil)
	if err != nil {
		panic(err)
	}
}

Documentation

Overview

封装微信服务器推送过来的消息(事件)处理 Handler.

Index

Constants

View Source
const URLQueryAgentKeyName = "agentkey"

定义回调 URL 上指定 Agent 的查询参数名

Variables

This section is empty.

Functions

func ServeHTTP

func ServeHTTP(w http.ResponseWriter, r *http.Request,
	urlValues url.Values, agent Agent, invalidRequestHandler InvalidRequestHandler)

ServeHTTP 处理 http 消息请求

NOTE: 确保所有参数合法, r.Body 能正确读取数据

func WriteImage

func WriteImage(w io.Writer, msg *response.Image, timestamp int64, nonce string,
	AESKey [32]byte, random []byte, CorpId, Token string) (err error)

把 image 回复消息 msg 写入 writer w

func WriteNews

func WriteNews(w io.Writer, msg *response.News, timestamp int64, nonce string,
	AESKey [32]byte, random []byte, CorpId, Token string) (err error)

把 news 回复消息 msg 写入 writer w

func WriteText

func WriteText(w io.Writer, msg *response.Text, timestamp int64, nonce string,
	AESKey [32]byte, random []byte, CorpId, Token string) (err error)

把 text 回复消息 msg 写入 writer w

func WriteVideo

func WriteVideo(w io.Writer, msg *response.Video, timestamp int64, nonce string,
	AESKey [32]byte, random []byte, CorpId, Token string) (err error)

把 video 回复消息 msg 写入 writer w

func WriteVoice

func WriteVoice(w io.Writer, msg *response.Voice, timestamp int64, nonce string,
	AESKey [32]byte, random []byte, CorpId, Token string) (err error)

把 voice 回复消息 msg 写入 writer w

Types

type Agent

type Agent interface {
	GetCorpId() string   // 获取应用所属的企业号Id
	GetAgentId() int64   // 获取应用的Id
	GetToken() string    // 获取应用的Token
	GetAESKey() [32]byte // 获取 32bytes 的 AES 加密 Key

	// 未知类型的消息处理方法
	//  rawXMLMsg   是解密后的"明文" xml 消息体
	//  timestamp   是请求 URL 中的时间戳
	//  nonce       是请求 URL 中的随机数
	//  random      是请求 http body 中的密文消息加密时所用的 random, 16 bytes
	//  r *http.Request 的 Body 已经读取过了, 不要再读取了, 但是可以获取其他信息, 比如 r.URL.RawQuery
	ServeUnknownMsg(w http.ResponseWriter, r *http.Request, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

	// 消息处理函数
	//  msg 是成功解析的消息结构体
	//  rawXMLMsg   是解密后的"明文" xml 消息体
	//  timestamp   是请求 URL 中的时间戳
	//  nonce       是请求 URL 中的随机数
	//  random      是请求 http body 中的密文消息加密时所用的 random, 16 bytes
	//  r *http.Request 的 Body 已经读取过了, 不要再读取了, 但是可以获取其他信息, 比如 r.URL.RawQuery
	ServeTextMsg(w http.ResponseWriter, r *http.Request, msg *request.Text, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
	ServeImageMsg(w http.ResponseWriter, r *http.Request, msg *request.Image, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
	ServeVoiceMsg(w http.ResponseWriter, r *http.Request, msg *request.Voice, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
	ServeVideoMsg(w http.ResponseWriter, r *http.Request, msg *request.Video, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
	ServeLocationMsg(w http.ResponseWriter, r *http.Request, msg *request.Location, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

	// 事件处理函数
	//  event 是成功解析的消息结构体
	//  rawXMLMsg   是解密后的"明文" xml 消息体
	//  timestamp   是请求 URL 中的时间戳
	//  nonce       是请求 URL 中的随机数
	//  random      是请求 http body 中的密文消息加密时所用的 random, 16 bytes
	//  r *http.Request 的 Body 已经读取过了, 不要再读取了, 但是可以获取其他信息, 比如 r.URL.RawQuery
	ServeSubscribeEvent(w http.ResponseWriter, r *http.Request, event *request.SubscribeEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
	ServeUnsubscribeEvent(w http.ResponseWriter, r *http.Request, event *request.UnsubscribeEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
	ServeLocationEvent(w http.ResponseWriter, r *http.Request, event *request.LocationEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
	ServeMenuClickEvent(w http.ResponseWriter, r *http.Request, event *request.MenuClickEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
	ServeMenuViewEvent(w http.ResponseWriter, r *http.Request, event *request.MenuViewEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
	ServeMenuScanCodePushEvent(w http.ResponseWriter, r *http.Request, event *request.MenuScanCodePushEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
	ServeMenuScanCodeWaitMsgEvent(w http.ResponseWriter, r *http.Request, event *request.MenuScanCodeWaitMsgEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
	ServeMenuPicSysPhotoEvent(w http.ResponseWriter, r *http.Request, event *request.MenuPicSysPhotoEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
	ServeMenuPicPhotoOrAlbumEvent(w http.ResponseWriter, r *http.Request, event *request.MenuPicPhotoOrAlbumEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
	ServeMenuPicWeixinEvent(w http.ResponseWriter, r *http.Request, event *request.MenuPicWeixinEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
	ServeMenuLocationSelectEvent(w http.ResponseWriter, r *http.Request, event *request.MenuLocationSelectEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)
}

企业号单个应用对外暴露的接口

type AgentFrontend

type AgentFrontend struct {
	// contains filtered or unexported fields
}

Agent 的前端, 负责处理 http 请求, net/http.Handler 的实现

NOTE: 只能处理一个企业号应用的消息

func NewAgentFrontend

func NewAgentFrontend(agent Agent, invalidRequestHandler InvalidRequestHandler) *AgentFrontend

创建一个新的 AgentFrontend.

agent 不能为 nil, 如果 invalidRequestHandler == nil 则使用 DefaultInvalidRequestHandler

func (*AgentFrontend) ServeHTTP

func (this *AgentFrontend) ServeHTTP(w http.ResponseWriter, r *http.Request)

type DefaultAgent

type DefaultAgent struct {
	CorpId  string
	AgentId int64
	Token   string
	AESKey  [32]byte
}

func (*DefaultAgent) GetAESKey

func (this *DefaultAgent) GetAESKey() [32]byte

func (*DefaultAgent) GetAgentId

func (this *DefaultAgent) GetAgentId() int64

func (*DefaultAgent) GetCorpId

func (this *DefaultAgent) GetCorpId() string

func (*DefaultAgent) GetToken

func (this *DefaultAgent) GetToken() string

func (*DefaultAgent) Init

func (this *DefaultAgent) Init(CorpId string, AgentId int64, Token string, AESKey []byte)

func (*DefaultAgent) ServeImageMsg

func (this *DefaultAgent) ServeImageMsg(w http.ResponseWriter, r *http.Request, msg *request.Image, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeLocationEvent

func (this *DefaultAgent) ServeLocationEvent(w http.ResponseWriter, r *http.Request, event *request.LocationEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeLocationMsg

func (this *DefaultAgent) ServeLocationMsg(w http.ResponseWriter, r *http.Request, msg *request.Location, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeMenuClickEvent

func (this *DefaultAgent) ServeMenuClickEvent(w http.ResponseWriter, r *http.Request, event *request.MenuClickEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeMenuLocationSelectEvent

func (this *DefaultAgent) ServeMenuLocationSelectEvent(w http.ResponseWriter, r *http.Request, event *request.MenuLocationSelectEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeMenuPicPhotoOrAlbumEvent

func (this *DefaultAgent) ServeMenuPicPhotoOrAlbumEvent(w http.ResponseWriter, r *http.Request, event *request.MenuPicPhotoOrAlbumEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeMenuPicSysPhotoEvent

func (this *DefaultAgent) ServeMenuPicSysPhotoEvent(w http.ResponseWriter, r *http.Request, event *request.MenuPicSysPhotoEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeMenuPicWeixinEvent

func (this *DefaultAgent) ServeMenuPicWeixinEvent(w http.ResponseWriter, r *http.Request, event *request.MenuPicWeixinEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeMenuScanCodePushEvent

func (this *DefaultAgent) ServeMenuScanCodePushEvent(w http.ResponseWriter, r *http.Request, event *request.MenuScanCodePushEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeMenuScanCodeWaitMsgEvent

func (this *DefaultAgent) ServeMenuScanCodeWaitMsgEvent(w http.ResponseWriter, r *http.Request, event *request.MenuScanCodeWaitMsgEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeMenuViewEvent

func (this *DefaultAgent) ServeMenuViewEvent(w http.ResponseWriter, r *http.Request, event *request.MenuViewEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeSubscribeEvent

func (this *DefaultAgent) ServeSubscribeEvent(w http.ResponseWriter, r *http.Request, event *request.SubscribeEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeTextMsg

func (this *DefaultAgent) ServeTextMsg(w http.ResponseWriter, r *http.Request, msg *request.Text, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeUnknownMsg

func (this *DefaultAgent) ServeUnknownMsg(w http.ResponseWriter, r *http.Request, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeUnsubscribeEvent

func (this *DefaultAgent) ServeUnsubscribeEvent(w http.ResponseWriter, r *http.Request, event *request.UnsubscribeEvent, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeVideoMsg

func (this *DefaultAgent) ServeVideoMsg(w http.ResponseWriter, r *http.Request, msg *request.Video, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

func (*DefaultAgent) ServeVoiceMsg

func (this *DefaultAgent) ServeVoiceMsg(w http.ResponseWriter, r *http.Request, msg *request.Voice, rawXMLMsg []byte, timestamp int64, nonce string, random []byte)

type InvalidRequestHandler

type InvalidRequestHandler interface {
	// 非法请求的处理方法, err 是错误信息
	ServeInvalidRequest(w http.ResponseWriter, r *http.Request, err error)
}
var DefaultInvalidRequestHandler InvalidRequestHandler = InvalidRequestHandlerFunc(func(w http.ResponseWriter, r *http.Request, err error) {})

type InvalidRequestHandlerFunc

type InvalidRequestHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)

func (InvalidRequestHandlerFunc) ServeInvalidRequest

func (fn InvalidRequestHandlerFunc) ServeInvalidRequest(w http.ResponseWriter, r *http.Request, err error)

type MultiAgentFrontend

type MultiAgentFrontend struct {
	// contains filtered or unexported fields
}

多个 Agent 的前端, 负责处理 http 请求, net/http.Handler 的实现

NOTE:
MultiAgentFrontend 可以处理多个公众号的消息(事件),但是要求在回调 URL 上加上一个查询
参数,一般为 agentkey(参考常量 URLQueryAgentKeyName),这个参数的值就是 MultiAgentFrontend
索引 Agent 的 key。
例如回调 URL 为 http://www.xxx.com/weixin?agentkey=1234567890,那么就可以在后端调用

  MultiAgentFrontend.SetAgent("1234567890", agent)

来增加一个 Agent 来处理 agentkey=1234567890 的消息(事件)。

MultiAgentFrontend 并发安全,可以在运行中动态增加和删除 Agent。

func (*MultiAgentFrontend) DeleteAgent

func (this *MultiAgentFrontend) DeleteAgent(agentkey string)

删除 agentkey 对应的 Agent

func (*MultiAgentFrontend) DeleteAllAgent

func (this *MultiAgentFrontend) DeleteAllAgent()

删除所有的 Agent

func (*MultiAgentFrontend) ServeHTTP

func (this *MultiAgentFrontend) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (*MultiAgentFrontend) SetAgent

func (this *MultiAgentFrontend) SetAgent(agentkey string, agent Agent)

添加(设置) agentkey-agent pair, 如果 agent == nil 则不做任何操作

func (*MultiAgentFrontend) SetInvalidRequestHandler

func (this *MultiAgentFrontend) SetInvalidRequestHandler(handler InvalidRequestHandler)

设置 InvalidRequestHandler, 如果 handler == nil 则使用默认的 DefaultInvalidRequestHandler

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL