Browse Source

完善文档

wenzl 9 years ago
parent
commit
f09af81be0
7 changed files with 621 additions and 35 deletions
  1. 1 0
      .gitignore
  2. 456 25
      README.md
  3. 45 0
      examples/beego/beego.go
  4. 47 0
      examples/gin/gin.go
  5. 48 0
      examples/http/http.go
  6. 19 5
      message/message.go
  7. 5 5
      wechat.go

+ 1 - 0
.gitignore

@@ -22,3 +22,4 @@ _testmain.go
 *.exe
 *.test
 *.prof
+.DS_Store

+ 456 - 25
README.md

@@ -1,4 +1,5 @@
 # WeChat SDK for Go
+[![Build Status](https://travis-ci.org/silenceper/wechat.svg?branch=develop)](https://travis-ci.org/silenceper/wechat)
 
 使用Golang开发的微信SDK,简单、易用。
 
@@ -7,44 +8,474 @@
 以下是一个处理消息接收以及回复的例子:
 
 ```go
+//配置微信参数
+config := &wechat.Config{
+	AppID:          "xxxx",
+	AppSecret:      "xxxx",
+	Token:          "xxxx",
+	EncodingAESKey: "xxxx",
+}
+wc := wechat.NewWechat(config)
 
-	//配置微信参数
-	config := &wechat.Config{
-		AppID:          "xxxx",
-		AppSecret:      "xxxx",
-		Token:          "xxxx",
-		EncodingAESKey: "xxxx",
+// 传入request和responseWriter 
+server := wc.GetServer(request, responseWriter)
+server.SetMessageHandler(func(msg message.MixMessage) *message.Reply {
+
+	//回复消息:演示回复用户发送的消息
+	text := message.NewText(msg.Content)
+	return &message.Reply{message.MsgText, text}
+})
+
+server.Serve()
+server.Send()
+
+```
+完整代码:[examples/http/http.go](./examples/http/http.go)
+
+#### 和主流框架配合使用
+
+主要是request和responseWriter在不同框架中获取方式可能不一样:
+
+- Beego配合使用 [./examples/beego/beego.go](./examples/beego/beego.go)
+- GinFrameworks [./examples/gin/gin.go](./examples/gin/gin.go)
+
+## 基本API使用
+
+## 消息管理
+
+通过`wechat.GetServer(request,responseWriter)`获取到server对象之后
+
+调用`SetMessageHandler(func(msg message.MixMessage){})`设置消息的处理函数,函数参数为message.MixMessage 结构如下:
+
+```go
+//MixMessage 存放所有微信发送过来的消息和事件
+type MixMessage struct {
+	CommonToken
+
+	//基本消息
+	MsgID        int64   `xml:"MsgId"`
+	Content      string  `xml:"Content"`
+	PicURL       string  `xml:"PicUrl"`
+	MediaID      string  `xml:"MediaId"`
+	Format       string  `xml:"Format"`
+	ThumbMediaID string  `xml:"ThumbMediaId"`
+	LocationX    float64 `xml:"Location_X"`
+	LocationY    float64 `xml:"Location_Y"`
+	Scale        float64 `xml:"Scale"`
+	Label        string  `xml:"Label"`
+	Title        string  `xml:"Title"`
+	Description  string  `xml:"Description"`
+	URL          string  `xml:"Url"`
+
+	//事件相关
+	Event     string `xml:"Event"`
+	EventKey  string `xml:"EventKey"`
+	Ticket    string `xml:"Ticket"`
+	Latitude  string `xml:"Latitude"`
+	Longitude string `xml:"Longitude"`
+	Precision string `xml:"Precision"`
+	
+	MenuID    string `xml:"MenuId"`
+	
+	//扫码事件
+	ScanCodeInfo struct {
+		ScanType   string `xml:"ScanType"`
+		ScanResult string `xml:"ScanResult"`
+	} `xml:"ScanCodeInfo"`
+
+	//发图事件
+	SendPicsInfo struct {
+		Count   int32      `xml:"Count"`
+		PicList []EventPic `xml:"PicList>item"`
+	} `xml:"SendPicsInfo"`
+	
+	//发送地理位置事件
+	SendLocationInfo struct {
+		LocationX float64 `xml:"Location_X"`
+		LocationY float64 `xml:"Location_Y"`
+		Scale     float64 `xml:"Scale"`
+		Label     string  `xml:"Label"`
+		Poiname   string  `xml:"Poiname"`
 	}
-	wc := wechat.NewWechat(config)
+}
+
+```
+
+具体参数请参考微信文档:[接收普通消息
+](http://mp.weixin.qq.com/wiki/17/f298879f8fb29ab98b2f2971d42552fd.html)
+
+### 接收普通消息
+```go
+server.SetMessageHandler(func(v message.MixMessage) *message.Reply {
+		switch v.MsgType {
+		//文本消息
+		case message.MsgTypeText:
+			//do something
+
+			//图片消息
+		case mesage.MsgTypeImage:
+			//do something
+
+			//语音消息
+		case message.MsgTypeVoice:
+			//do something
+
+			//视频消息
+		case message.MsgTypeVideo:
+			//do something
+
+			//小视频消息
+		case message.MsgTypeShortVideo:
+			//do something
+
+			//地理位置消息
+		case message.MsgTypeShortVideo:
+			//do something
+
+			//链接消息
+		case message.MsgTypeLink:
+			//do something
+
+			//事件推送消息
+		case message.MsgTypeEvent:
+
+		}
+}
+
+
+```
+ 
+
+### 接收事件推送
+```go
+//事件推送消息
+case message.MsgTypeEvent:
+	switch v.Event {
+		//EventSubscribe 订阅
+		case message.EventSubscribe:
+			//do something
+	
+			//取消订阅
+		case message.EventUnsubscribe:
+			//do something
+	
+			//用户已经关注公众号,则微信会将带场景值扫描事件推送给开发者
+		case message.EventScan:
+			//do something
+	
+			// 上报地理位置事件
+		case message.EventLocation:
+			//do something
+	
+			// 点击菜单拉取消息时的事件推送
+		case message.EventClick:
+			//do something
+	
+			// 点击菜单跳转链接时的事件推送
+		case message.EventView:
+			//do something
+	
+			// 扫码推事件的事件推送
+		case message.EventScancodePush:
+			//do something
+	
+			// 扫码推事件且弹出“消息接收中”提示框的事件推送
+		case message.EventScancodeWaitmsg:
+			//do something
+	
+			// 弹出系统拍照发图的事件推送
+		case message.EventPicSysphoto:
+			//do something
+	
+			// 弹出拍照或者相册发图的事件推送
+		case message.EventPicPhotoOrAlbum:
+			//do something
+	
+			// 弹出微信相册发图器的事件推送
+		case message.EventPicWeixin:
+			//do something
+	
+			// 弹出地理位置选择器的事件推送
+		case message.EventLocationSelect:
+			//do something
+	
+	}
+
+
+```
+
+
+### 被动回复消息
+
+回复消息需要返回 `*message.Reply` 对象结构体如下:
+
+```go
+type Reply struct {
+	MsgType MsgType  //消息类型
+	MsgData interface{}  //消息结构
+}
+
+```
+注意:`retrun nil`表示什么也不做
+
+####  回复文本消息
+```go
+	text := message.NewText("回复文本消息")
+	return &message.Reply{message.MsgTypeText, text}
+```
+####  回复图片消息
+```go
+//mediaID 可通过素材管理-上上传多媒体文件获得
+image :=message.NewVideo("mediaID")
+return &message.Reply{message.MsgTypeVideo, image}
+```
+####  回复视频消息
+```go
+video := message.NewVideo("mediaID", "视频标题", "视频描述")
+return &message.Reply{message.MsgTypeVideo, video}
+```
+####  回复音乐消息
+```go
+music := message.NewMusic("title", "description", "musicURL", "hQMusicURL", "thumbMediaID")
+return &message.Reply{message.MsgTypeMusic,music}
+```
+**字段说明:**
+
+Title:音乐标题
+
+Description:音乐描述
+
+MusicURL:音乐链接
+
+HQMusicUrl:高质量音乐链接,WIFI环境优先使用该链接播放音乐
+
+ThumbMediaId:缩略图的媒体id,通过素材管理接口上传多媒体文件,得到的id
+
+####  回复图文消息
+
+```go
+articles := make([]*message.Article, 1)
+
+article := new(message.Article)
+article.Title = "标题"
+article.Description = "描述信息信息信息"
+article.PicURL = "http://ww1.sinaimg.cn/large/65209136gw1f7vhjw95eqj20wt0zk40z.jpg"
+article.URL = "https://github.com/silenceper/wechat"
+articles[0] = article
+
+news := message.NewNews(articles)
+return &message.Reply{message.MsgTypeNews,news}
+```
+**字段说明:**
+
+Title:图文消息标题
+
+Description:图文消息描述
+
+PicUrl	:图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
+
+Url	:点击图文消息跳转链接
+
+
+## 自定义菜单
+
+通过` wechat.GetMenu(req, writer)`获取menu的实例
+
+### 自定义菜单创建接口
 
-	// 传入request和responseWriter 
-	server := wc.GetServer(request, responseWriter)
-	server.SetMessageHandler(func(msg message.MixMessage) *message.Reply {
+以下是一个创建二级菜单的例子
 
-		//回复消息:演示回复用户发送的消息
-		text := message.NewText(msg.Content)
-		return &message.Reply{message.MsgText, text}
-	})
+```go
+mu := wc.GetMenu(c.Request, c.Writer)
+	
+buttons := make([]*menu.Button, 1)
+btn := new(menu.Button)
+	
+//创建click类型菜单
+btn.SetClickButton("name", "key123")
+buttons[0] = btn
+
+//设置btn为二级菜单
+btn2 := new(menu.Button)
+btn2.SetSubButton("subButton", buttons)
+
+buttons2 := make([]*menu.Button, 1)
+buttons2[0] = btn2
+	
+//发送请求
+err := mu.SetMenu(buttons2)
+if err != nil {
+	fmt.Printf("err= %v", err)
+	return
+}
+
+```
+
+**创建其他类型的菜单:**
+
+```go
+//SetViewButton view类型
+func (btn *Button) SetViewButton(name, url string)
+
+// SetScanCodePushButton 扫码推事件
+func (btn *Button) SetScanCodePushButton(name, key string) 
+
+//SetScanCodeWaitMsgButton 设置 扫码推事件且弹出"消息接收中"提示框
+func (btn *Button) SetScanCodeWaitMsgButton(name, key string) 
 
-	server.Serve()
-	server.Send()
+//SetPicSysPhotoButton 设置弹出系统拍照发图按钮
+func (btn *Button) SetPicSysPhotoButton(name, key string)
 
+//SetPicPhotoOrAlbumButton 设置弹出拍照或者相册发图类型按钮
+func (btn *Button) SetPicPhotoOrAlbumButton(name, key string) {
+
+// SetPicWeixinButton 设置弹出微信相册发图器类型按钮
+func (btn *Button) SetPicWeixinButton(name, key string) 
+
+// SetLocationSelectButton 设置 弹出地理位置选择器 类型按钮
+func (btn *Button) SetLocationSelectButton(name, key string) 
+
+//SetMediaIDButton  设置 下发消息(除文本消息) 类型按钮
+func (btn *Button) SetMediaIDButton(name, mediaID string) 
+
+//SetViewLimitedButton  设置 跳转图文消息URL 类型按钮
+func (btn *Button) SetViewLimitedButton(name, mediaID string) {
+
+```
+
+### 自定义菜单查询接口
+
+```go
+mu := wc.GetMenu(c.Request, c.Writer)
+resMenu,err:=mu.GetMenu()
 ```
+>返回结果 resMenu 结构参考 ./menu/menu.go 中ResMenu 结构体
 
-## 更多API使用
+### 自定义菜单删除
+
+```go
+mu := wc.GetMenu(c.Request, c.Writer)
+err:=mu.DeleteMenu()
+```
+
+### 自定义菜单事件推送
+
+ 请参考 消息管理 - 事件推送 
+ 
+### 个性化菜单接口
+**添加个性化菜单**
+
+```go
+
+func (menu *Menu) AddConditional(buttons []*Button, matchRule *MatchRule) error 
+```
+
+**删除个性化菜单**
+
+```go
+//删除个性化菜单
+func (menu *Menu) DeleteConditional(menuID int64) error 
+
+```
+**测试个性化菜单匹配结果**
+
+```go
+//菜单匹配
+func (menu *Menu) MenuTryMatch(userID string) (buttons []Button, err error) {
+
+```
 
-[文档地址](https://github.com/gowechat/docs)
+**获取公众号菜单配置**
+
+```go
+//获取自定义菜单配置接口
+func (menu *Menu) GetCurrentSelfMenuInfo() (resSelfMenuInfo ResSelfMenuInfo, err error) 
+
+```
+
+## 微信网页开发
+
+### Oauth2 授权
+
+具体授权流程请参考微信文档:[网页授权](http://mp.weixin.qq.com/wiki/4/9ac2e7b1f1d22e9e57260f6553822520.html)
+
+**1.发起授权**
+
+```go
+oauth := wc.GetOauth(c.Request, c.Writer)
+err := oauth.Redirect("跳转的绝对地址", "snsapi_userinfo", "123dd123")
+if err != nil {
+	fmt.Println(err)
+}
+
+```
+> 如果不希望直接跳转,可通过 oauth.GetRedirectURL 获取跳转的url
+
+**2.通过code换取access_token**
+
+```go
+code := c.Query("code")
+resToken, err := oauth.GetUserAccessToken(code)
+if err != nil {
+	fmt.Println(err)
+	return
+}
+
+```
+**3.拉取用户信息(需scope为 snsapi_userinfo)**
+
+```go
+//getUserInfo
+userInfo, err := oauth.GetUserInfo(resToken.AccessToken, resToken.OpenID)
+if err != nil {
+	fmt.Println(err)
+	return
+}
+fmt.Println(userInfo)
+
+```
+**刷新access_token**
+
+```go
+func (oauth *Oauth) RefreshAccessToken(refreshToken string) (result ResAccessToken, err error) 
+
+```
+**检验access_token是否有效**
+
+```go
+func (oauth *Oauth) CheckAccessToken(accessToken, openID string) (b bool, err error)
+```
+
+### 获取js-sdk配置
+
+```go
+js := wc.GetJs(c.Request, c.Writer)
+cfg, err := js.GetConfig("传入需要的调用js-sdk的url地址")
+if err != nil {
+	fmt.Println(err)
+	return
+}
+fmt.Println(cfg)
+```
+其中返回的cfg结构体如下:
+
+```go
+type Config struct {
+	AppID     string
+	TimeStamp int64
+	NonceStr  string
+	Signature string
+}
+
+```
 
-## 已实现的微信平台接口
+## 素材管理
 
-- 消息管理(事件推送)
-- 网页授权Oauth2 ,Js-SDK
-- 菜单管理
-- 用户管理
-- 素材管理
+[素材管理API](https://godoc.org/github.com/silenceper/wechat/material#Material)
 
-持续完善中...
 
+更多API使用请参考 godoc :
+[https://godoc.org/github.com/silenceper/wechat](https://godoc.org/github.com/silenceper/wechat) 
 
 ## License
 

+ 45 - 0
examples/beego/beego.go

@@ -0,0 +1,45 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/astaxie/beego"
+	"github.com/astaxie/beego/context"
+	"github.com/silenceper/wechat"
+	"github.com/silenceper/wechat/message"
+)
+
+func hello(ctx *context.Context) {
+	//配置微信参数
+	config := &wechat.Config{
+		AppID:          "your app id",
+		AppSecret:      "your app secret",
+		Token:          "your token",
+		EncodingAESKey: "your encoding aes key",
+	}
+	wc := wechat.NewWechat(config)
+
+	// 传入request和responseWriter
+	server := wc.GetServer(ctx.Request, ctx.ResponseWriter)
+	//设置接收消息的处理方法
+	server.SetMessageHandler(func(msg message.MixMessage) *message.Reply {
+
+		//回复消息:演示回复用户发送的消息
+		text := message.NewText(msg.Content)
+		return &message.Reply{message.MsgTypeText, text}
+	})
+
+	//处理消息接收以及回复
+	err := server.Serve()
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	//发送回复的消息
+	server.Send()
+}
+
+func main() {
+	beego.Any("/", hello)
+	beego.Run(":8001")
+}

+ 47 - 0
examples/gin/gin.go

@@ -0,0 +1,47 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/gin-gonic/gin"
+	"github.com/silenceper/wechat"
+	"github.com/silenceper/wechat/message"
+)
+
+func main() {
+	router := gin.Default()
+
+	router.Any("/", hello)
+	router.Run(":8001")
+}
+
+func hello(c *gin.Context) {
+
+	//配置微信参数
+	config := &wechat.Config{
+		AppID:          "your app id",
+		AppSecret:      "your app secret",
+		Token:          "your token",
+		EncodingAESKey: "your encoding aes key",
+	}
+	wc := wechat.NewWechat(config)
+
+	// 传入request和responseWriter
+	server := wc.GetServer(c.Request, c.Writer)
+	//设置接收消息的处理方法
+	server.SetMessageHandler(func(msg message.MixMessage) *message.Reply {
+
+		//回复消息:演示回复用户发送的消息
+		text := message.NewText(msg.Content)
+		return &message.Reply{message.MsgTypeText, text}
+	})
+
+	//处理消息接收以及回复
+	err := server.Serve()
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	//发送回复的消息
+	server.Send()
+}

+ 48 - 0
examples/http/http.go

@@ -0,0 +1,48 @@
+package main
+
+import (
+	"fmt"
+	"net/http"
+
+	"github.com/silenceper/wechat"
+	"github.com/silenceper/wechat/message"
+)
+
+func hello(rw http.ResponseWriter, req *http.Request) {
+
+	//配置微信参数
+	config := &wechat.Config{
+		AppID:          "your app id",
+		AppSecret:      "your app secret",
+		Token:          "your token",
+		EncodingAESKey: "your encoding aes key",
+	}
+	wc := wechat.NewWechat(config)
+
+	// 传入request和responseWriter
+	server := wc.GetServer(req, rw)
+	//设置接收消息的处理方法
+	server.SetMessageHandler(func(msg message.MixMessage) *message.Reply {
+
+		//回复消息:演示回复用户发送的消息
+		text := message.NewText(msg.Content)
+		return &message.Reply{message.MsgTypeText, text}
+	})
+
+	//处理消息接收以及回复
+	err := server.Serve()
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	//发送回复的消息
+	server.Send()
+}
+
+func main() {
+	http.HandleFunc("/", hello)
+	err := http.ListenAndServe(":8001", nil)
+	if err != nil {
+		fmt.Printf("start server error , err=%v", err)
+	}
+}

+ 19 - 5
message/message.go

@@ -29,21 +29,35 @@ const (
 	MsgTypeNews = "news"
 	//MsgTypeTransfer 表示消息消息转发到客服
 	MsgTypeTransfer = "transfer_customer_service"
+	//MsgTypeEvent 表示事件推送消息
+	MsgTypeEvent = "event"
 )
 
 const (
 	//EventSubscribe 订阅
 	EventSubscribe EventType = "subscribe"
 	//EventUnsubscribe 取消订阅
-	EventUnsubscribe EventType = "unsubscribe"
+	EventUnsubscribe = "unsubscribe"
 	//EventScan 用户已经关注公众号,则微信会将带场景值扫描事件推送给开发者
-	EventScan EventType = "SCAN"
+	EventScan = "SCAN"
 	//EventLocation 上报地理位置事件
-	EventLocation EventType = "LOCATION"
+	EventLocation = "LOCATION"
 	//EventClick 点击菜单拉取消息时的事件推送
-	EventClick EventType = "CLICK"
+	EventClick = "CLICK"
 	//EventView 点击菜单跳转链接时的事件推送
-	EventView EventType = "VIEW"
+	EventView = "VIEW"
+	//EventScancodePush 扫码推事件的事件推送
+	EventScancodePush = "scancode_push"
+	//EventScancodeWaitmsg 扫码推事件且弹出“消息接收中”提示框的事件推送
+	EventScancodeWaitmsg = "scancode_waitmsg"
+	//EventPicSysphoto 弹出系统拍照发图的事件推送
+	EventPicSysphoto = "pic_sysphoto"
+	//EventPicPhotoOrAlbum 弹出拍照或者相册发图的事件推送
+	EventPicPhotoOrAlbum = "pic_photo_or_album"
+	//EventPicWeixin 弹出微信相册发图器的事件推送
+	EventPicWeixin = "pic_weixin"
+	//EventLocationSelect 弹出地理位置选择器的事件推送
+	EventLocationSelect = "location_select"
 )
 
 //MixMessage 存放所有微信发送过来的消息和事件

+ 5 - 5
wechat.go

@@ -44,33 +44,33 @@ func copyConfigToContext(cfg *Config, context *context.Context) {
 	context.SetJsApiTicketLock(new(sync.RWMutex))
 }
 
-//GetServer init
+//GetServer 消息管理
 func (wc *Wechat) GetServer(req *http.Request, writer http.ResponseWriter) *server.Server {
 	wc.Context.Request = req
 	wc.Context.Writer = writer
 	return server.NewServer(wc.Context)
 }
 
-//GetMaterial init
+//GetMaterial 素材管理
 func (wc *Wechat) GetMaterial() *material.Material {
 	return material.NewMaterial(wc.Context)
 }
 
-//GetOauth init
+//GetOauth oauth2网页授权
 func (wc *Wechat) GetOauth(req *http.Request, writer http.ResponseWriter) *oauth.Oauth {
 	wc.Context.Request = req
 	wc.Context.Writer = writer
 	return oauth.NewOauth(wc.Context)
 }
 
-//GetJs init
+//GetJs js-sdk配置
 func (wc *Wechat) GetJs(req *http.Request, writer http.ResponseWriter) *js.Js {
 	wc.Context.Request = req
 	wc.Context.Writer = writer
 	return js.NewJs(wc.Context)
 }
 
-//GetMenu init
+//GetMenu 菜单管理接口
 func (wc *Wechat) GetMenu(req *http.Request, writer http.ResponseWriter) *menu.Menu {
 	wc.Context.Request = req
 	wc.Context.Writer = writer