




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第GO制作微信機(jī)器人的流程分析目錄0.回顧流程1.項(xiàng)目基礎(chǔ)配置2.Redis封裝3.消息體封裝4.核心代碼5.本地測(cè)試這些天在學(xué)習(xí)Go,也寫(xiě)了幾篇關(guān)于閱讀Gin后端項(xiàng)目代碼的博客。但編程這種,一定要實(shí)際上手練習(xí),要不然都是紙上談兵。于是就想上手自己實(shí)際寫(xiě)一些代碼來(lái)練練手。思來(lái)想去,不知道能寫(xiě)些什么來(lái)練手。后來(lái)突然想到,之前寫(xiě)過(guò)用Python做微信聊天機(jī)器人(博客傳送門(mén)),當(dāng)時(shí)代碼沒(méi)有放到git上,后來(lái)重置了服務(wù)器導(dǎo)致代碼全部沒(méi)了?,F(xiàn)在正好苦于不知道做什么項(xiàng)目練手,可以用Go也實(shí)現(xiàn)一套微信聊天機(jī)器人。
說(shuō)干就干,照著之前自己寫(xiě)的博客,看了下當(dāng)時(shí)Python的代碼。轉(zhuǎn)而用Go優(yōu)化了下并實(shí)現(xiàn)。
0.回顧流程
根據(jù)之前Python寫(xiě)的自動(dòng)發(fā)消息的機(jī)器人可知,要想發(fā)消息就需要三個(gè)參數(shù):company_id、secret、angent_id。對(duì)于這三個(gè)參數(shù)如何獲取,可參考文章開(kāi)頭的傳送門(mén)。整個(gè)發(fā)送消息過(guò)程就是首先通過(guò)company_id和secret來(lái)調(diào)用接口獲取token,再通過(guò)token和angent_id來(lái)給對(duì)應(yīng)接口發(fā)送post請(qǐng)求,就可以把post請(qǐng)求體中的信息發(fā)送到微信上。
1.項(xiàng)目基礎(chǔ)配置
由于目前對(duì)Go的項(xiàng)目布局學(xué)習(xí)的還不是特別熟練,而且對(duì)于項(xiàng)目基礎(chǔ)部分如果從頭開(kāi)始做的話,需要耗費(fèi)大量時(shí)間。因此我使用了基于開(kāi)源gin項(xiàng)目進(jìn)行二次開(kāi)發(fā)的方法,實(shí)現(xiàn)這個(gè)機(jī)器人。
前幾天在學(xué)習(xí)Gin時(shí),發(fā)現(xiàn)了一位老哥封裝了個(gè)Gin腳手架,可以達(dá)到開(kāi)箱即用目的。項(xiàng)目地址:github傳送門(mén)。里邊把讀取配置文件,編寫(xiě)路由,連接數(shù)據(jù)庫(kù)等多個(gè)操作均進(jìn)行了實(shí)現(xiàn)。因此可以基于這個(gè)項(xiàng)目來(lái)進(jìn)行二次開(kāi)發(fā),做微信機(jī)器人。
在把項(xiàng)目clone下來(lái)后,可以先看下整個(gè)項(xiàng)目的布局,主要的業(yè)務(wù)核心代碼都放在了internal下面。如果我們要實(shí)現(xiàn)一個(gè)主動(dòng)給微信發(fā)消息的功能,那么多說(shuō)了就是寫(xiě)一個(gè)發(fā)送消息的方法,讓后端調(diào)用這個(gè)方法即可。
要想基于此項(xiàng)目來(lái)開(kāi)發(fā)微信機(jī)器人,首先就要將三個(gè)參數(shù)配置上。項(xiàng)目中,對(duì)于各種參數(shù)均在config.yaml中配置,因?yàn)榭梢栽谶@個(gè)配置文件中增加這三個(gè)參數(shù)的配置:
然后在代碼的config/autoload目錄下新增一個(gè)weCaht.go文件,接收配置文件中的配置。
packageautoload
typeWeChatConfigstruct{
AgentIdstringini:"wechat"yaml:"agent_id"
Secretstringini:"wechat"yaml:"secret"
CompanyIdstringini:"wechat"yaml:"company_id"
varWeChat=WeChatConfig{}
并且,將此配置加入到項(xiàng)目的配置集合中。在config/config.go中添加如下代碼:
這樣操作,就可以通過(guò)代碼來(lái)讀取配置文件了。在其他包中,可以通過(guò)如下方式來(lái)訪問(wèn)對(duì)應(yīng)的值
config.Config.WeChat.CompanyId//yaml中的company_id字段
2.Redis封裝
因?yàn)橐o微信發(fā)送消息,首先要獲取到token,而官方介紹此token的有效時(shí)長(zhǎng)為2小時(shí)。在之前Python的項(xiàng)目中,是直接將token寫(xiě)到了文件中,通過(guò)文件來(lái)讀取。在此項(xiàng)目中,我想直接使用redis來(lái)存儲(chǔ)。因?yàn)槭褂胷edis來(lái)存儲(chǔ)的話,可以設(shè)置key值時(shí)長(zhǎng),過(guò)了這個(gè)時(shí)長(zhǎng)就自動(dòng)清除,這樣就方便了許多。
而我們基于這個(gè)gin-layout項(xiàng)目中,已經(jīng)對(duì)redis做了一層封裝,具體代碼可查看data/redis.go,主要是通過(guò)對(duì)外暴露一個(gè)Rdb的結(jié)構(gòu)體,來(lái)操作redis
而目前我們這邊使用redis,只會(huì)用到對(duì)應(yīng)的set和get方法。因此我對(duì)這個(gè)項(xiàng)目中的redis又做了一層封裝。只對(duì)外暴露set,get,del方法。
首先將Rdb變量名改為小寫(xiě),這樣就代表不對(duì)外暴露,然后在此文件中添加如下代碼
funcSetRedis(keystring,valuestring,tint64)bool{
expire:=time.Duration(t)*time.Second
iferr:=rdb.Set(ctx,key,value,expire).Err();err!=nil{
returnfalse
returntrue
funcGetRedis(keystring)string{
result,err:=rdb.Get(ctx,key).Result()
iferr!=nil{
return“”
returnresult
funcDelRedis(keystring)bool{
_,err:=rdb.Del(ctx,key).Result()
iferr!=nil{
returnfalse
returntrue
}
這樣,后續(xù)使用redis時(shí)候,只需要調(diào)用data.SetRedis(xxx)即可。
然后就是修改配置文件,啟用redis,這里根據(jù)實(shí)際的redis配置來(lái)寫(xiě)即可。
3.消息體封裝
在最終給微信服務(wù)器發(fā)送post請(qǐng)求時(shí),對(duì)應(yīng)的請(qǐng)求體格式如下:
{
“touser”:“@all”,
“msgtype”:“text”,
“agentid”:“xxxxx”,
“text”:{“content”:“xxxx”}
}
因此,接下來(lái)可以對(duì)這個(gè)結(jié)構(gòu)體做一個(gè)封裝。在model包下,新建一個(gè)send_msg.go文件
packagemodel
typewcSendcontentstruct{
Contentstringjson:"content"
typeWcSendMsgstruct{
ToUserstringjson:"touser"
MsgTypestringjson:"msgtype"
AgentIdstringjson:"agentid"
TextwcSendcontentjson:"text"
func(t*WcSendMsg)SetMessage(messagestring){
t.Text.Content=message
}
這里針對(duì)message信息,專(zhuān)門(mén)對(duì)外暴露了一個(gè)方法來(lái)進(jìn)行設(shè)置。
4.核心代碼
在設(shè)置好redis,消息體封裝后,就可以編寫(xiě)核心的代碼了。主要就是通過(guò)發(fā)送http請(qǐng)求,獲取token,再通過(guò)token發(fā)送post請(qǐng)求來(lái)發(fā)送消息。我們可以在service包下新建一個(gè)weChat.go的文件,里邊新建一個(gè)SendWeChat方法來(lái)進(jìn)行消息發(fā)送操作。
packageservice
import(
“bytes”
“encoding/json”
“errors”
“fmt”
c"/wannanbigpig/gin-layout/config"
"/wannanbigpig/gin-layout/data"
"/wannanbigpig/gin-layout/internal/model"
log"/wannanbigpig/gin-layout/internal/pkg/logger"
"/wannanbigpig/gin-layout/pkg/utils"
"/zap"
)
@description:給企微發(fā)送消息
@param{string}message消息內(nèi)容
@param{string}msgType消息類(lèi)型
@return{*}
funcSendWeChat(messagestring,msgTypestring)error{
redis_key:=“access_token”
//嘗試從redis中讀取token
accessToken:=data.GetRedis(redis_key)
http:=utils.HttpRequest{}
//若redis中的token已過(guò)期,則重新請(qǐng)求api獲取token
ifaccessToken==“”{
log.Logger.Info(“accesstokenisnull,willrecall”)
getTokenUrl:=fmt.Sprintf(“/cgi-bin/gettokencorpid=%scorpsecret=%s”,
c.Config.WeChat.CompanyId,c.Config.WeChat.Secret)
log.Logger.Info(“token_url”,zap.String(“url”,getTokenUrl))
http.Request(“GET”,getTokenUrl,nil)
ret:=make(map[string]interface{})
iferr:=http.ParseJson(ret);err!=nil{
returnerr
marshal,_:=json.Marshal(ret)
log.Logger.Info(string(marshal))
accessToken=fmt.Sprintf("%v",ret[“access_token”])
//寫(xiě)入redis有效期2小時(shí)
data.SetRedis(redis_key,accessToken,7200)
msg:=model.WcSendMsg{
ToUser:“@all”,
MsgType:msgType,
AgentId:c.Config.WeChat.AgentId,
msg.SetMessage(message)
sendMsgUrl:=fmt.Sprintf(“/cgi-bin/message/sendaccess_token=%v”,accessToken)
log.Logger.Info(“sendMsgUrl="+string(sendMsgUrl))
header:=map[string]string{“Content-Type”:“application/json”}
bytesData,_:=json.Marshal(msg)
http.Request(“POST”,sendMsgUrl,bytes.NewReader(bytesData),header)
log.Logger.Info(“bytesdata="+string(bytesData))
ret:=make(map[string]interface{})
err:=http.ParseJson(ret)
iferr!=nil{
returnerr
ifret[“errcode”].(float64)!=0{
errmsg:=fmt.Sprintf(”%v”,ret[“errmsg”])
returnerrors.New(errmsg)
returnnil
}
從上面代碼中可以看出,首先是通過(guò)redis來(lái)獲取token,若沒(méi)有則請(qǐng)求api獲取token,并將其寫(xiě)入到redis中,有效期為2小時(shí)。然后生成一個(gè)之前封裝的消息的結(jié)構(gòu)體,將AgentId和message進(jìn)行填充后,通過(guò)發(fā)送post請(qǐng)求,已達(dá)到發(fā)消息的目的。
5.本地測(cè)試
若想驗(yàn)證這個(gè)方法,可以通過(guò)對(duì)外提供一個(gè)接口,訪問(wèn)此接口后調(diào)用發(fā)送消息的方法。
可以在controller目錄下新建一個(gè)weChat.go,在里邊實(shí)現(xiàn)一個(gè)get請(qǐng)求的方法,獲取請(qǐng)求中的msg參數(shù),然后調(diào)用剛才實(shí)現(xiàn)的發(fā)送企微的方法。
packagewechat
import(
“/gin-gonic/gin”
“/wannanbigpig/gin-layout/internal/pkg/error_code”
log“/wannanbigpig/gin-layout/internal/pkg/logger”
r“/wannanbigpig/gin-layout/internal/pkg/response”
“/wannanbigpig/gin-layout/internal/service”
funcSendMsg(c*gin.Context){
msg,ok:=c.GetQuery(“msg”)
if!ok{
msg=“pleaseinputmessage”
log.Logger.Info("sendwechatmessage:"+msg)
err:=service.SendWeChat(msg,“text”)
iferr!=nil{
r.Resp().FailCode(c,error_code.FAILURE,err.Error())
re
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 電力備用資源優(yōu)化配置補(bǔ)充合同
- 家庭保險(xiǎn)受益人變更及保險(xiǎn)責(zé)任調(diào)整合同
- 《智慧養(yǎng)老的康復(fù)之路》課件
- 魔法肥皂實(shí)驗(yàn)室:親子科學(xué)手工皂DIY活動(dòng)
- 蕭宗六學(xué)校管理理論體系與實(shí)踐創(chuàng)新
- 醫(yī)學(xué)個(gè)人年度總結(jié)
- 《癌癥整合治療》課件
- 《急性敵敵畏中毒》課件
- 男性睪丸醫(yī)學(xué)科普
- 《T知識(shí)講解教程》課件
- 環(huán)境工程學(xué)復(fù)習(xí)資料大全不用再找了
- 常用急救藥品的劑量與用法課件
- 自動(dòng)控制原理-復(fù)習(xí)題及答案
- SAP固定資產(chǎn)各種折舊方法配置及操作手冊(cè)
- 奧數(shù)舉一反三簡(jiǎn)單推理
- 高中英語(yǔ)教師研修-羅馬建筑文化課件
- 貨物驗(yàn)收單(模板)
- 滬科版七年級(jí)下學(xué)期數(shù)學(xué)競(jìng)賽測(cè)試卷(含答案)
- 復(fù)旦大學(xué)大學(xué)生創(chuàng)業(yè)導(dǎo)論課件06創(chuàng)業(yè)的商業(yè)計(jì)劃書(shū)
- 醫(yī)療糾紛和解協(xié)議書(shū)(6篇)
- 農(nóng)村不動(dòng)產(chǎn)權(quán)籍調(diào)查工作指南
評(píng)論
0/150
提交評(píng)論