Code Monkey home page Code Monkey logo

weixin's Introduction

微信公众平台库 – Go语言版本

简介

这是一个使用Go语言对微信公众平台的封装。参考了微信公众平台API文档

Build Status GoDoc

入门

安装

通过执行下列语句就可以完成安装

go get github.com/wizjin/weixin

注册微信公众平台

注册微信公众平台,填写验证微信公众平台的Token

示例

package main

import (
	"github.com/wizjin/weixin"
	"net/http"
)

// 文本消息的处理函数
func Echo(w weixin.ResponseWriter, r *weixin.Request) {
	txt := r.Content			// 获取用户发送的消息
	w.ReplyText(txt)			// 回复一条文本消息
	w.PostText("Post:" + txt)	// 发送一条文本消息
}

// 关注事件的处理函数
func Subscribe(w weixin.ResponseWriter, r *weixin.Request) {
	w.ReplyText("欢迎关注") // 有新人关注,返回欢迎消息
}

func main() {
	// my-token 验证微信公众平台的Token
	// app-id, app-secret用于高级API调用。
	// 如果仅使用接收/回复消息,则可以不填写,使用下面语句
	// mux := weixin.New("my-token", "", "")
	mux := weixin.New("my-token", "app-id", "app-secret")
	// 设置AES密钥,如果不使用AES可以省略这行代码
	mux.SetEncodingAESKey("encoding-AES-key")
	// 注册文本消息的处理函数
	mux.HandleFunc(weixin.MsgTypeText, Echo)
	// 注册关注事件的处理函数
	mux.HandleFunc(weixin.MsgTypeEventSubscribe, Subscribe)
	http.Handle("/", mux) // 注册接收微信服务器数据的接口URI
	http.ListenAndServe(":80", nil) // 启动接收微信数据服务器
}

微信公众平台要求在收到消息后5秒内回复消息(Reply接口) 如果时间操作很长,则可以使用Post接口发送消息 如果只使用Post接口发送消息,则需要先调用ReplyOK来告知微信不用等待回复。

处理函数

处理函数的定义可以使用下面的形式

func Func(w weixin.ResponseWriter, r *weixin.Request) {
	...
}

可以注册的处理函数类型有以下几种

  • weixin.MsgTypeText 接收文本消息
  • weixin.MsgTypeImage 接收图片消息
  • weixin.MsgTypeVoice 接收语音消息
  • weixin.MsgTypeVideo 接收视频消息
  • weixin.MsgTypeShortVideo 接收小视频消息
  • weixin.MsgTypeLocation 接收地理位置消息
  • weixin.MsgTypeLink 接收链接消息
  • weixin.MsgTypeEventSubscribe 接收关注事件
  • weixin.MsgTypeEventUnsubscribe 接收取消关注事件
  • weixin.MsgTypeEventScan 接收扫描二维码事件
  • weixin.MsgTypeEventView 接收点击菜单跳转链接时的事件
  • weixin.MsgTypeEventClick 接收自定义菜单事件
  • weixin.MsgTypeEventLocation 接收上报地理位置事件
  • weixin.MsgTypeEventTemplateSent 接收模版消息发送结果

发送被动响应消息

需要发送被动响应消息,可通过weixin.ResponseWriter的下列方法完成

  • ReplyOK() 无同步消息回复
  • ReplyText(text) 回复文本消息
  • ReplyImage(mediaId) 回复图片消息
  • ReplyVoice(mediaId) 回复语音消息
  • ReplyVideo(mediaId, title, description) 回复视频消息
  • ReplyMusic(music) 回复音乐消息
  • ReplyNews(articles) 回复图文消息

发送客服消息

  • PostText(text) 发送文本消息
  • PostImage(mediaId) 发送图片消息
  • PostVoice(mediaId) 发送语音消息
  • PostVideo(mediaId, title, description) 发送视频消息
  • PostMusic(music) 发送音乐消息
  • PostNews(articles) 发送图文消息

发送模版消息

如需要发送模版消息,需要先获取模版ID,之后再根据ID发送。

func GetTemplateId(wx *weixin.Weixin) {
	tid, err := wx.AddTemplate("TM00015")
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(ips)	// 模版ID
	}
}

随后可以发送模版消息了。

func SendTemplateMessage(w weixin.ResponseWriter, r *weixin.Request) {
	templateId := ...
	url := ...
	msgid, err := w.PostTemplateMessage(templateId, url,
		weixin.TmplData{ "first": weixin.TmplItem{"Hello World!", "#173177"}})
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(msgid)
	}
}

在模版消息发送成功后,还会通过类型为MsgTypeEventTemplateSent的消息推送获得发送结果。

  • TemplateSentStatusSuccess 发送成功
  • TemplateSentStatusUserBlock 发送失败,用户拒绝接收
  • TemplateSentStatusSystemFailed 发送失败,系统原因

上传/下载多媒体文件

使用如下函数可以用来上传多媒体文件:

UploadMediaFromFile(mediaType string, filepath string)

示例 (用一张本地图片来返回图片消息):

func ReciveMessage(w weixin.ResponseWriter, r *weixin.Request) {
	// 上传本地文件并获取MediaID
	mediaId, err := w.UploadMediaFromFile(weixin.MediaTypeImage, "/my-file-path")
	if err != nil {
		w.ReplyText("上传图片失败")
	} else {
		w.ReplyImage(mediaId)	// 利用获取的MediaId来返回图片消息
	}
}

使用如下函数可以用来下载多媒体文件:

DownloadMediaToFile(mediaId string, filepath string)

示例 (收到一条图片消息,然后保存图片到本地文件):

func ReciveImageMessage(w weixin.ResponseWriter, r *weixin.Request) {
	// 下载文件并保存到本地
	err := w.DownloadMediaToFile(r.MediaId, "/my-file-path")
	if err != nil {
		w.ReplyText("保存图片失败")
	} else {
		w.ReplyText("保存图片成功")
	}
}

获取微信服务器IP地址

示例,获取微信服务器IP地址列表

func GetIpList(wx *weixin.Weixin) {
	ips, err := wx.GetIpList()
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(ips)	// Ip地址列表
	}
}

获取AccessToken

示例,获取AccessToken

func GetAccessToken(wx *weixin.Weixin) {
	a := wx.GetAccessToken
	if time.Until(token.Expires).Seconds() > 0 {
		fmt.Println(a.Token)	// AccessToken
	} else {
		fmt.Println("Timeout")	// 超时
	}
}

创建/换取二维码

示例,创建临时二维码

func CreateQRScene(wx *weixin.Weixin) {
	// 二维码ID - 1000
	// 过期时间 - 1800秒
	qr, err := wx.CreateQRScene(1000, 1800)
	if err != nil {
		fmt.Println(err)
	} else {
		url := qr.ToURL() // 获取二维码的URL
		fmt.Println(url)
	}
}

示例,创建永久二维码

func CreateQRScene(wx *weixin.Weixin) {
	// 二维码ID - 1001
	qr, err := wx.CreateQRLimitScene(1001)
	if err != nil {
		fmt.Println(err)
	} else {
		url := qr.ToURL() // 获取二维码的URL
		fmt.Println(url)
	}
}

长链接转短链接接口

func ShortURL(wx *weixin.Weixin) {
	// 长链接转短链接
	url, err := wx.ShortURL("http://mp.weixin.qq.com/wiki/10/165c9b15eddcfbd8699ac12b0bd89ae6.html")
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(url)
	}
}

自定义菜单

示例,创建自定义菜单

func CreateMenu(wx *weixin.Weixin) {
	menu := &weixin.Menu{make([]weixin.MenuButton, 2)}
	menu.Buttons[0].Name = "我的菜单"
	menu.Buttons[0].Type = weixin.MenuButtonTypeUrl
	menu.Buttons[0].Url = "https://mp.weixin.qq.com"
	menu.Buttons[1].Name = "我的子菜单"
	menu.Buttons[1].SubButtons = make([]weixin.MenuButton, 1)
	menu.Buttons[1].SubButtons[0].Name = "测试"
	menu.Buttons[1].SubButtons[0].Type = weixin.MenuButtonTypeKey
	menu.Buttons[1].SubButtons[0].Key = "MyKey001"
	err := wx.CreateMenu(menu)
	if err != nil {
		fmt.Println(err)
	}
}

自定义菜单的类型有如下几种

  • weixin.MenuButtonTypeKey 点击推事件
  • weixin.MenuButtonTypeUrl 跳转URL
  • weixin.MenuButtonTypeScancodePush 扫码推事件
  • weixin.MenuButtonTypeScancodeWaitmsg 扫码推事件且弹出“消息接收中”提示框
  • weixin.MenuButtonTypePicSysphoto 弹出系统拍照发图
  • weixin.MenuButtonTypePicPhotoOrAlbum 弹出拍照或者相册发图
  • weixin.MenuButtonTypePicWeixin 弹出微信相册发图器
  • weixin.MenuButtonTypeLocationSelect 弹出地理位置选择器
  • weixin.MenuButtonTypeMediaId 下发消息(除文本消息)
  • weixin.MenuButtonTypeViewLimited 跳转图文消息URL

示例,获取自定义菜单

func DeleteMenu(wx *weixin.Weixin) {
	menu, err := wx.GetMenu()
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(menu)
	}
}

示例,删除自定义菜单

func DeleteMenu(wx *weixin.Weixin) {
	err := wx.DeleteMenu()
	if err != nil {
		fmt.Println(err)
	}
}

JSSDK签名

示例,生成JSSDK签名

func SignJSSDK(wx *weixin.Weixin, url string) {
	timestamp := time.Now().Unix()
	noncestr := fmt.Sprintf("%d", c.randreader.Int())
	sign, err := wx.JsSignature(url, timestamp, noncestr)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(sign)
	}
}

重定向URL生成

示例,生成重定向URL

func CreateRedirect(wx *weixin.Weixin, url string) {
	redirect := wx.CreateRedirectURL(url, weixin.RedirectURLScopeBasic, "")
}

URL的类型有如下几种:

  • RedirectURLScopeBasic 基本授权,仅用来获取OpenId或UnionId
  • RedirectURLScopeUserInfo 高级授权,可以用于获取用户基本信息,需要用户同意

用户OpenId和UnionId获取

示例,获取用户OpenId和UnionId

func GetUserId(wx *weixin.Weixin, code string) {
	user, err := wx.GetUserAccessToken(code)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(user.OpenId)
		fmt.Println(user.UnionId)
	}
}

用户信息获取

示例,获取用户信息

func GetUserInfo(wx *weixin.Weixin, openid string) {
	user, err := wx.GetUserInfo(openid)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(user.Nickname)
		fmt.Println(user.Sex)
		fmt.Println(user.City)
		fmt.Println(user.Country)
		fmt.Println(user.Province)
		fmt.Println(user.HeadImageUrl)
		fmt.Println(user.SubscribeTime)
		fmt.Println(user.Remark)
	}
}

参考连接

版权声明

This project is licensed under the MIT license, see LICENSE.

更新日志

Version 0.5.4 - upcoming

  • 用户管理
  • 支持AES

Version 0.5.3 - 2016/01/05

  • 添加模版消息送

Version 0.5.2 - 2015/12/05

  • 添加JSSDK签名生成
  • 添加重定向URL生成
  • 添加获取用户OpenId和UnionId
  • 添加获取授权用户信息

Version 0.5.1 - 2015/06/26

  • 获取微信服务器IP地址
  • 接收小视频消息

Version 0.5.0 - 2015/06/25

  • 自定义菜单
  • 长链接转短链接

Version 0.4.1 - 2014/09/07

  • 添加将消息转发到多客服功能

Version 0.4.0 - 2014/02/07

  • 创建/换取二维码

Version 0.3.0 - 2014/01/07

  • 多媒体文件处理:上传/下载多媒体文件

Version 0.2.0 - 2013/12/19

  • 发送客服消息:文本消息,图片消息,语音消息,视频消息,音乐消息,图文消息

Version 0.1.0 – 2013/12/17

  • Token验证URL有效性
  • 接收普通消息:文本消息,图片消息,语音消息,视频消息,地理位置消息,链接消息
  • 接收事件推送:关注/取消关注,扫描二维码事件,上报地理位置,自定义菜单
  • 发送被动响应消息:文本消息,图片消息,语音消息,视频消息,音乐消息,图文消息

weixin's People

Contributors

chaegumi avatar hyacinthus avatar wizjin avatar xxuejie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

weixin's Issues

downloadMedia

多媒体文件下载的时候 Content-Type: text/plain以外的情况下:
只返回r.Body(其他类型的处理好像也都是只返回r.Body).
同样的是多媒体类型之图片的时候,没法判断获取的内容是什么类型的文件.
比如jpg/png就无法区分,但是又要在开始的时候创建文件.

发送模板消息出现 `json: cannot unmarshal number into Go struct field .msgid of type int32` 错误

完整信息 json: cannot unmarshal number 445263598701395969 into Go struct field .msgid of type int32

weixin/weixin.go

Lines 763 to 768 in e9f0f20

var resp struct {
MsgID int64 `json:"msgid,omitempty"`
}
if err := json.Unmarshal(reply, &resp); err != nil {
return 0, err
}

原因在于int32 不能包含 445263598701395969 ,它也比较解决 int64 的最大值

https://golang.org/pkg/encoding/json/#Number 可能是最后的解决方案

Create QR code

Method: Post
URL: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN

QR Scene Body:

{
    "expire_seconds": 1800,
    "action_name": "QR_SCENE",
    "action_info": {
        "scene": {
            "scene_id": 123
        }
    }
}

PS. scene_id max 100000

QR Limit Scene Body:

{
    "action_name": "QR_LIMIT_SCENE",
    "action_info": {
        "scene": {
            "scene_id": 123
        }
    }
}

PS. scene_id max 1000

Result:

{
    "ticket":"<QR Code Ticket>",
    "expire_seconds":1800
}

Token的存储和共享问题

在集群环境下,Token是需要进行集中化管理的,而现在的这种模式,我觉得做集中化管理比较困难把~能不能有办法解决呢?

create jsApi error

noncestr := fmt.Sprintf("%d", c.randreader.Int())
what is the point of the above sentence?

Button type

// Button type
MenuButtonTypeKey = "click"
MenuButtonTypeUrl = "view"

    这个是不是应该是
MenuButtonTypeKey = "CLICK"
MenuButtonTypeUrl = "VIEW"

不成功!

mux := weixin.New("tk_wx_xxx", "", "")
mux.HandleFunc(weixin.MsgTypeText, Echo)
http.Handle("/wx/signature", mux)

func Echo(w weixin.ResponseWriter, r *weixin.Request) {
txt := r.Content // 获取用户发送的消息
w.ReplyText(txt) // 回复一条文本消息
w.PostText("Post:" + txt) // 发送一条文本消息
}

我的这个地址 会报404错误

Can't create menu when using openauth url with "&"

Json lib will encoding the "&" to \u0026 , so if you want to create openauth url like:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
That will cause the CreateMenu fail.

The related code:
https://github.com/wizjin/weixin/blob/master/weixin.go#L418

I've got quick-and-dirty patch by repalce it to "&"
https://github.com/imzjy/weixin/blob/master/weixin.go#L391

Maybe there is good way to fix it, just hightlight the issue here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.