使用 Golang 开发的微信 SDK

licsdfvrwd 8年前
   <h2><strong>WeChat SDK for Go</strong></h2>    <p>使用Golang开发的微信SDK,简单、易用。</p>    <h2><strong>快速开始</strong></h2>    <p>以下是一个处理消息接收以及回复的例子:</p>    <pre>  <code class="language-go">//配置微信参数  config := &wechat.Config{      AppID:          "xxxx",      AppSecret:      "xxxx",      Token:          "xxxx",      EncodingAESKey: "xxxx",      Cache:          memCache  }  wc := wechat.NewWechat(config)    // 传入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()</code></pre>    <p>和主流框架配合使用</p>    <p>主要是request和responseWriter在不同框架中获取方式可能不一样:</p>    <ul>     <li>Beego: <a href="/misc/goto?guid=4959726545720998802" rel="nofollow,noindex">./examples/beego/beego.go</a></li>     <li>Gin Framework: <a href="/misc/goto?guid=4959726545808810066" rel="nofollow,noindex">./examples/gin/gin.go</a></li>    </ul>    <h2><strong>基本配置</strong></h2>    <pre>  <code class="language-go">memcache := cache.NewMemcache("127.0.0.1:11211")    wcConfig := &wechat.Config{      AppID:          cfg.AppID,      AppSecret:      cfg.AppSecret,      Token:          cfg.Token,      EncodingAESKey: cfg.EncodingAESKey,//消息加解密时用到      Cache:          memcache,  }</code></pre>    <p>Cache 设置</p>    <p>Cache主要用来保存全局access_token以及js-sdk中的ticket: 默认采用memcache存储。当然也可以直接实现 cache/cache.go 中的接口</p>    <h2><strong>基本API使用</strong></h2>    <ul>     <li>消息管理      <ul>       <li>接收普通消息</li>       <li>接收事件推送</li>       <li>被动回复消息        <ul>         <li>回复文本消息</li>         <li>回复图片消息</li>         <li>回复视频消息</li>         <li>回复音乐消息</li>         <li>回复图文消息</li>        </ul> </li>      </ul> </li>     <li>自定义菜单      <ul>       <li>自定义菜单创建接口</li>       <li>自定义菜单查询接口</li>       <li>自定义菜单删除接口</li>       <li>自定义菜单事件推送</li>       <li>个性化菜单接口        <ul>         <li>添加个性化菜单</li>         <li>删除个性化菜单</li>         <li>测试个性化菜单匹配结果</li>        </ul> </li>       <li>获取公众号菜单配置</li>      </ul> </li>     <li>微信网页开发      <ul>       <li>Oauth2 授权        <ul>         <li>发起授权</li>         <li>通过code换取access_token</li>         <li>拉取用户信息</li>         <li>刷新access_token</li>         <li>检验access_token是否有效</li>        </ul> </li>       <li>获取js-sdk配置</li>      </ul> </li>     <li>素材管理</li>    </ul>    <h2><strong>消息管理</strong></h2>    <p>通过 wechat.GetServer(request,responseWriter) 获取到server对象之后</p>    <p>调用 SetMessageHandler(func(msg message.MixMessage){}) 设置消息的处理函数,函数参数为message.MixMessage 结构如下:</p>    <pre>  <code class="language-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"`      }  }</code></pre>    <h3><strong>接收普通消息</strong></h3>    <pre>  <code class="language-go">server.SetMessageHandler(func(v message.MixMessage) *message.Reply {          switch v.MsgType {          //文本消息          case message.MsgTypeText:              //do something                //图片消息          case message.MsgTypeImage:              //do something                //语音消息          case message.MsgTypeVoice:              //do something                //视频消息          case message.MsgTypeVideo:              //do something                //小视频消息          case message.MsgTypeShortVideo:              //do something                //地理位置消息          case message.MsgTypeLocation:              //do something                //链接消息          case message.MsgTypeLink:              //do something                //事件推送消息          case message.MsgTypeEvent:            }  }</code></pre>    <h3><strong>接收事件推送</strong></h3>    <pre>  <code class="language-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        }</code></pre>    <h3><strong>被动回复消息</strong></h3>    <p>回复消息需要返回 *message.Reply 对象结构体如下:</p>    <pre>  <code class="language-go">type Reply struct {      MsgType MsgType  //消息类型      MsgData interface{}  //消息结构  }</code></pre>    <p>注意: retrun nil 表示什么也不做</p>    <p>回复文本消息</p>    <pre>  <code class="language-go">text := message.NewText("回复文本消息")      return &message.Reply{message.MsgTypeText, text}</code></pre>    <p>回复图片消息</p>    <pre>  <code class="language-go">//mediaID 可通过素材管理-上上传多媒体文件获得  image :=message.NewVideo("mediaID")  return &message.Reply{message.MsgTypeVideo, image}</code></pre>    <p>回复视频消息</p>    <pre>  <code class="language-go">video := message.NewVideo("mediaID", "视频标题", "视频描述")  return &message.Reply{message.MsgTypeVideo, video}</code></pre>    <p>回复音乐消息</p>    <pre>  <code class="language-go">music := message.NewMusic("title", "description", "musicURL", "hQMusicURL", "thumbMediaID")  return &message.Reply{message.MsgTypeMusic,music}</code></pre>    <p>字段说明:</p>    <p>Title:音乐标题</p>    <p>Description:音乐描述</p>    <p>MusicURL:音乐链接</p>    <p>HQMusicUrl:高质量音乐链接,WIFI环境优先使用该链接播放音乐</p>    <p>ThumbMediaId:缩略图的媒体id,通过素材管理接口上传多媒体文件,得到的id</p>    <p>回复图文消息</p>    <pre>  <code class="language-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}</code></pre>    <p>字段说明:</p>    <p>Title:图文消息标题</p>    <p>Description:图文消息描述</p>    <p>PicUrl :图片链接,支持JPG、PNG格式,较好的效果为大图360 <em>200,小图200</em> 200</p>    <p>Url :点击图文消息跳转链接</p>    <h2><strong>自定义菜单</strong></h2>    <p>通过 wechat.GetMenu(req, writer) 获取menu的实例</p>    <h3><strong>自定义菜单创建接口</strong></h3>    <p>以下是一个创建二级菜单的例子</p>    <pre>  <code class="language-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  }</code></pre>    <p>创建其他类型的菜单:</p>    <pre>  <code class="language-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)    //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) {</code></pre>    <h3><strong>自定义菜单查询接口</strong></h3>    <pre>  <code class="language-go">mu := wc.GetMenu(c.Request, c.Writer)  resMenu,err:=mu.GetMenu()</code></pre>    <p>返回结果 resMenu 结构参考 ./menu/menu.go 中ResMenu 结构体</p>    <h3><strong>自定义菜单删除接口</strong></h3>    <pre>  <code class="language-go">mu := wc.GetMenu(c.Request, c.Writer)  err:=mu.DeleteMenu()</code></pre>    <h3><strong>自定义菜单事件推送</strong></h3>    <p>请参考 消息管理 - 事件推送</p>    <h3><strong>个性化菜单接口</strong></h3>    <p>添加个性化菜单</p>    <pre>  <code class="language-go">func (menu *Menu) AddConditional(buttons []*Button, matchRule *MatchRule) error</code></pre>    <p>删除个性化菜单</p>    <pre>  <code class="language-go">//删除个性化菜单  func (menu *Menu) DeleteConditional(menuID int64) error</code></pre>    <p>测试个性化菜单匹配结果</p>    <pre>  <code class="language-go">//菜单匹配  func (menu *Menu) MenuTryMatch(userID string) (buttons []Button, err error) {</code></pre>    <h3><strong>获取公众号菜单配置</strong></h3>    <pre>  <code class="language-go">//获取自定义菜单配置接口  func (menu *Menu) GetCurrentSelfMenuInfo() (resSelfMenuInfo ResSelfMenuInfo, err error)</code></pre>    <h2><strong>微信网页开发</strong></h2>    <h3><strong>Oauth2 授权</strong></h3>    <p>具体授权流程请参考微信文档: <a href="/misc/goto?guid=4959726545907843523" rel="nofollow,noindex">网页授权</a></p>    <p>1.发起授权</p>    <pre>  <code class="language-go">oauth := wc.GetOauth(c.Request, c.Writer)  err := oauth.Redirect("跳转的绝对地址", "snsapi_userinfo", "123dd123")  if err != nil {      fmt.Println(err)  }</code></pre>    <p>如果不希望直接跳转,可通过 oauth.GetRedirectURL 获取跳转的url</p>    <p>2.通过code换取access_token</p>    <pre>  <code class="language-go">code := c.Query("code")  resToken, err := oauth.GetUserAccessToken(code)  if err != nil {      fmt.Println(err)      return  }</code></pre>    <p>3.拉取用户信息(需scope为 snsapi_userinfo)</p>    <pre>  <code class="language-go">//getUserInfo  userInfo, err := oauth.GetUserInfo(resToken.AccessToken, resToken.OpenID)  if err != nil {      fmt.Println(err)      return  }  fmt.Println(userInfo)</code></pre>    <p>刷新access_token</p>    <pre>  <code class="language-go">func (oauth *Oauth) RefreshAccessToken(refreshToken string) (result ResAccessToken, err error)</code></pre>    <p>检验access_token是否有效</p>    <pre>  <code class="language-go">func (oauth *Oauth) CheckAccessToken(accessToken, openID string) (b bool, err error)</code></pre>    <h3><strong>获取js-sdk配置</strong></h3>    <pre>  <code class="language-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)</code></pre>    <p>其中返回的cfg结构体如下:</p>    <pre>  <code class="language-go">type Config struct {      AppID     string      TimeStamp int64      NonceStr  string      Signature string  }</code></pre>    <h2><strong>素材管理</strong></h2>    <p><a href="/misc/goto?guid=4959726545989180689" rel="nofollow,noindex">素材管理API</a></p>    <p> </p>    <p> </p>    <p>来自:https://github.com/silenceper/wechat</p>    <p> </p>