前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >go语言微信公众号开发后台接口封装

go语言微信公众号开发后台接口封装

作者头像
杨永贞
发布2020-08-04 11:11:37
2K0
发布2020-08-04 11:11:37
举报

个人整理的小功能,把微信公众号开发涉及的一些常用接口做了个封装。

业余时间做了个有意思的小功能,每天早上7点准时给发天气预报,每晚8点发布一条英语说说,提醒自己不能忘记学习。

封装实现的功能有:

开发者首次接入、

创建菜单、

删除菜单、

发送模板消息、

接收公众号前端推送、

获取Token,获取关注者信息,

获取用户个人信息,

根据code获取个人信息(微信前端第三方应用页面接入授权会涉及。)

这里再介绍下微信前端第三方应用如何获取微信个人openid和个人信息的功能实现思路。

如何在微信前端开发的应用界面,获取用户openid和个人信息呢?方法还是有的,思路靠谱。

就是文档里描述的那几步授权操作,先获取code,再跳转,后台获取在传给前端。

附代码封装:

代码语言:javascript
复制
// WxReceiveCommonMsg 接收普通消息
type WxReceiveCommonMsg struct {
	ToUserName   string //接收者 开发者 微信号
	FromUserName string //发送者 发送方帐号(一个OpenID)
	Content      string //文本内容
	CreateTime   int64  //创建时间
	MsgType      string //消息类型
	MsgId        int64  //消息id
	PicUrl       string //图片url
	MediaId      string //媒体id
	Event        string //事件类型,VIEW
	EventKey     string //事件KEY值,设置的跳转URL
	MenuId       string
	Format       string
	Recognition  string
	ThumbMediaId string //缩略图媒体ID
}

// WxReceiveFunc (接收到消息之后,会将消息交于这个函数处理)
var WxReceiveFunc func(msg WxReceiveCommonMsg) error

// WxMakeSign 计算签名
func WxMakeSign(token, timestamp, nonce string) string {
	strs := []string{token, timestamp, nonce}
	sort.Strings(strs)
	sha := sha1.New()
	io.WriteString(sha, strings.Join(strs, ""))
	return fmt.Sprintf("%x", sha.Sum(nil))
}

// WxGetAccessToken 获取微信accesstoken
func WxGetAccessToken() string {
	url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%v&secret=%v", APPID, APPSECRET)
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("获取微信token失败", err)
		return ""
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("微信token读取失败", err)
		return ""
	}

	token := token{}
	err = json.Unmarshal(body, &token)
	if err != nil {
		fmt.Println("微信token解析json失败", err)
		return ""
	}

	return token.AccessToken
}

// WxGetUserList 获取关注者列表
func WxGetUserList(accessToken string) []gjson.Result {
	url := "https://api.weixin.qq.com/cgi-bin/user/get?access_token=" + accessToken + "&next_openid="
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("获取关注列表失败", err)
		return nil
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("读取内容失败", err)
		return nil
	}
	flist := gjson.Get(string(body), "data.openid").Array()
	return flist
}

// WxPostTemplate 发送模板消息
func WxPostTemplate(accessToken string, reqdata string, fxurl string, templateid string, openid string) {

	url := "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken

	reqbody := "{\"touser\":\"" + openid + "\", \"template_id\":\"" + templateid + "\", \"url\":\"" + fxurl + "\", \"data\": " + reqdata + "}"
	fmt.Printf("WxPostTemplate:%#v\n", reqbody)
	resp, err := http.Post(url,
		"application/x-www-form-urlencoded",
		strings.NewReader(string(reqbody)))
	if err != nil {
		fmt.Println(err)
		return
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(string(body))
}

// ReceiveCommonMsg
func ReceiveCommonMsg(msgData []byte) (WxReceiveCommonMsg, error) {

	fmt.Printf("received weixin msgData:\n%s\n", msgData)
	msg := WxReceiveCommonMsg{}
	err := xml.Unmarshal(msgData, &msg)
	if WxReceiveFunc == nil {
		return msg, err
	}
	err = WxReceiveFunc(msg)
	return msg, err
}

// WxCreateMenu 创建菜单
func WxCreateMenu(accessToken, menustr string) (string, error) {

	url := "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" + accessToken
	fmt.Printf("WxCreateMenu:%s\n", menustr)
	resp, err := http.Post(url,
		"application/x-www-form-urlencoded",
		strings.NewReader(menustr))
	if err != nil {
		fmt.Println(err)
		return "", err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return "", err
	}

	fmt.Println(string(body))
	return string(body), nil

}

// WxDelMenu 删除菜单
func WxDelMenu(accessToken string) (string, error) {
	url := "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=" + accessToken
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("删除菜单失败", err)
		return "", err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("读取内容失败", err)
		return "", err
	}

	fmt.Println(string(body))
	return string(body), nil

}

// WxGetUserInfo 根据用户openid获取基本信息
func WxGetUserInfo(accessToken, openid string) (string, error) {
	url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN", accessToken, openid)
	fmt.Println(url)
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("获取信息失败", err)
		return "", err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("读取内容失败", err)
		return "", err
	}

	fmt.Println(string(body))
	return string(body), nil

}

// WxGetOpenidByCode 微信前端页面授权之后,会给前端页面路由里带一个code
func WxGetOpenidByCode(code string) (string, error) {
	url := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", APPID, APPSECRET, code)
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("获取openid失败", err)
		return "", err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("读取内容失败", err)
		return "", err
	}

	fmt.Println(string(body))
	return string(body), nil
}

// web API接口
// HandleWxLogin首次接入,成为开发者
func HandleWxLogin(c *gin.Context) {
	fmt.Printf("==>HandleWxLogin\n")
	echostr := c.DefaultQuery("echostr", "")
	if echostr != "" {
		fmt.Printf("==>echostr:%s\n", echostr)
		c.String(200, "%s", echostr)
		return
	}

}

// HandleWxPostRecv 处理微信公众号前端发起的消息事件
func HandleWxPostRecv(c *gin.Context) {
	fmt.Printf("==>HandleWxPostRecv Enter\n")
	data, err := c.GetRawData()
	if err != nil {
		log.Fatalln(err)
	}
	ReceiveCommonMsg(data)
}

// HandleWxGetOpenid
func HandleWxGetOpenid(c *gin.Context) {
	fmt.Printf("==>HandleWxGetOpenid Enter\n")
	code := c.Query("code")
	result, err := WxGetOpenidByCode(code)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "获取openid失败" + err.Error(),
		})
		return
	}
	//WxDelMenu(accessToken)
	c.JSON(http.StatusOK, gin.H{
		"code": 0,
		"msg":  "成功",
		"data": result,
	})
}

// HandleWxGetUserInfo 根据前端请求来的openid获取用户信息
func HandleWxGetUserInfo(c *gin.Context) {
	fmt.Printf("==>HandleWxGetUserInfo Enter\n")
	opid := c.Query("openid")
	fmt.Printf("openid:%s\n", opid)
	token := WxGetAccessToken()
	result, err := WxGetUserInfo(token, opid)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "获取用户信息失败" + err.Error(),
		})
		return
	}
	//WxDelMenu(accessToken)
	c.JSON(http.StatusOK, gin.H{
		"code": 0,
		"msg":  "成功",
		"data": result,
	})
}

func init() {
}

每日一句,每天发布一条英语句子,接口如下:

代码语言:javascript
复制
/**
每日一句api接口
*/
package apis

import (
	"encoding/json"
	"fmt"
	"github.com/tidwall/gjson"
	"io/ioutil"
	"net/http"
	"weixin/wxapi"
)

// SentTemplateID 每日一句的模板ID
var SentTemplateID = "Xhh6e2zuKbTXlplpMezHLkHuNIF0X1_ScJT3K3hi4wg"

// sentence 句子结构
type sentence struct {
	Content     string `json:"content"`
	Note        string `json:"note"`
	Translation string `json:"translation"`
}

// GetSay 获取每日一句
func GetSay() (sentence, string) {
	resp, err := http.Get("http://open.iciba.com/dsapi/?date")
	sent := sentence{}
	if err != nil {
		fmt.Println("获取每日一句失败", err)
		return sent, ""
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("读取内容失败", err)
		return sent, ""
	}

	err = json.Unmarshal(body, &sent)
	if err != nil {
		fmt.Println("每日一句解析json失败")
		return sent, ""
	}
	fenxiangurl := gjson.Get(string(body), "fenxiang_img").String()
	fmt.Println(sent)
	return sent, fenxiangurl
}

//SendEverydaySay 发送每日一句
func SendEverydaySay() {
	req, fxurl := GetSay()
	if req.Content == "" {
		return
	}
	accessToken := wxapi.WxGetAccessToken()
	if accessToken == "" {
		return
	}

	flist := wxapi.WxGetUserList(accessToken)
	if flist == nil {
		return
	}

	reqdata := "{\"content\":{\"value\":\"" + req.Content + "\", \"color\":\"#0000CD\"}, \"note\":{\"value\":\"" + req.Note + "\"}, \"translation\":{\"value\":\"" + req.Translation + "\"}}"
	for _, v := range flist {
		wxapi.WxPostTemplate(accessToken, reqdata, fxurl, SentTemplateID, v.Str)
	}
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
访问管理
访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档