分享
  1. 首页
  2. 文章

golang 实现微信公众平台API引擎开发模式

songbohr · · 3614 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

/*
 *@author 菠菜君
 *@Version 0.2
 *@time 2013年10月29日
 *@golang实现微信公众平台API引擎开发模式
 *@青岛程序员 微信订阅号	qdprogrammer
 *@Golang 微信订阅号	gostock
 *@关于青岛程序员的技术,创业,生活 分享。
 *@开源 https://github.com/philsong/
 */
package main
import (
	"crypto/sha1"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"sort"
	"strings"
	"time"
)
const (
	TOKEN = "gostock"
	Text = "text"
	Location = "location"
	Image = "image"
	Link = "link"
	Event = "event"
	Music = "music"
	News = "news"
)
type msgBase struct {
	ToUserName string
	FromUserName string
	CreateTime time.Duration
	MsgType string
	Content string
}
type Request struct {
	XMLName xml.Name `xml:"xml"`
	msgBase // base struct
	Location_X, Location_Y float32
	Scale int
	Label string
	PicUrl string
	MsgId int
}
type Response struct {
	XMLName xml.Name `xml:"xml"`
	msgBase
	ArticleCount int `xml:",omitempty"`
	Articles []*item `xml:"Articles>item,omitempty"`
	FuncFlag int
}
type item struct {
	XMLName xml.Name `xml:"item"`
	Title string
	Description string
	PicUrl string
	Url string
}
func weixinEvent(w http.ResponseWriter, r *http.Request) {
	if weixinCheckSignature(w, r) == false {
		fmt.Println("auth failed, attached?")
		return
	}
	fmt.Println("auth success, parse POST")
	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Fatal(err)
		return
	}
	fmt.Println(string(body))
	var wreq *Request
	if wreq, err = DecodeRequest(body); err != nil {
		log.Fatal(err)
		return
	}
	wresp, err := dealwith(wreq)
	if err != nil {
		log.Fatal(err)
		return
	}
	data, err := wresp.Encode()
	if err != nil {
		fmt.Printf("error:%v\n", err)
		return
	}
	fmt.Println(string(data))
	fmt.Fprintf(w, string(data))
	return
}
func dealwith(req *Request) (resp *Response, err error) {
	resp = NewResponse()
	resp.ToUserName = req.FromUserName
	resp.FromUserName = req.ToUserName
	resp.MsgType = Text
	if req.MsgType == Event {
		if req.Content == "subscribe" {
			resp.Content = "欢迎关注微信订阅号qdprogrammer, 分享青岛程序员的技术,创业,生活。"
			return resp, nil
		}
	}
	if req.MsgType == Text {
		if strings.Trim(strings.ToLower(req.Content), " ") == "help" {
			resp.Content = "欢迎关注微信订阅号qdprogrammer, 分享青岛程序员的技术,创业,生活。"
			return resp, nil
		}
		resp.Content = "亲,菠菜君已经收到您的消息, 将尽快回复您."
	} else if req.MsgType == Image {
		var a item
		a.Description = "雅蠛蝶。。。^_^^_^1024你懂的"
		a.Title = "雅蠛蝶图文测试"
		a.PicUrl = "http://static.yaliam.com/gwz.jpg"
		a.Url = "http://blog.csdn.net/songbohr"
		resp.MsgType = News
		resp.ArticleCount = 1
		resp.Articles = append(resp.Articles, &a)
		resp.FuncFlag = 1
	} else {
		resp.Content = "暂时还不支持其他的类型"
	}
	return resp, nil
}
func weixinAuth(w http.ResponseWriter, r *http.Request) {
	if weixinCheckSignature(w, r) == true {
		var echostr string = strings.Join(r.Form["echostr"], "")
		fmt.Fprintf(w, echostr)
	}
}
func weixinHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		fmt.Println("GET begin...")
		weixinAuth(w, r)
		fmt.Println("GET END...")
	} else {
		fmt.Println("POST begin...")
		weixinEvent(w, r)
		fmt.Println("POST END...")
	}
}
func main() {
	http.HandleFunc("/check", weixinHandler)
	//http.HandleFunc("/", action)
	port := "80"
	println("Listening on port ", port, "...")
	err := http.ListenAndServe(":"+port, nil) //设置监听的端口
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
func str2sha1(data string) string {
	t := sha1.New()
	io.WriteString(t, data)
	return fmt.Sprintf("%x", t.Sum(nil))
}
func weixinCheckSignature(w http.ResponseWriter, r *http.Request) bool {
	r.ParseForm()
	fmt.Println(r.Form)
	var signature string = strings.Join(r.Form["signature"], "")
	var timestamp string = strings.Join(r.Form["timestamp"], "")
	var nonce string = strings.Join(r.Form["nonce"], "")
	tmps := []string{TOKEN, timestamp, nonce}
	sort.Strings(tmps)
	tmpStr := tmps[0] + tmps[1] + tmps[2]
	tmp := str2sha1(tmpStr)
	if tmp == signature {
		return true
	}
	return false
}
func DecodeRequest(data []byte) (req *Request, err error) {
	req = &Request{}
	if err = xml.Unmarshal(data, req); err != nil {
		return
	}
	req.CreateTime *= time.Second
	return
}
func NewResponse() (resp *Response) {
	resp = &Response{}
	resp.CreateTime = time.Duration(time.Now().Unix())
	return
}
func (resp Response) Encode() (data []byte, err error) {
	resp.CreateTime = time.Duration(time.Now().Unix())
	data, err = xml.Marshal(resp)
	return
}



有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:songbohr

查看原文:golang 实现微信公众平台API引擎开发模式

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
3614 次点击
1 回复 | 直到 2019年07月23日 15:47:33
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏