使用Golang开发微信公众平台.docx
《使用Golang开发微信公众平台.docx》由会员分享,可在线阅读,更多相关《使用Golang开发微信公众平台.docx(9页珍藏版)》请在冰点文库上搜索。
使用Golang开发微信公众平台
使用Golang开发微信公众平台
关注并使用过微信“飞常准”公众号的朋友们都有过如下体验:
查询一个航班情况后,这个航班的checkin、登机、起降等信息都会在后续陆续异步发给你,这个服务就是通过微信公众平台的客服消息实现的。
微信公众平台开发文档中关于客服消息的解释如下:
“当用户主动发消息给公众号的时候(包括发送信息、点击自定义菜单、订阅事件、扫描二维码事件、支付成功事件、用户维权),微信将会把消息数据推送给开发者,开发者在一段时间内(目前修改为48小时)可以调用客服消息接口,通过POST一个JSON数据包来发送消息给普通用户,在48小时内不限制发送次数。
此接口主要用于客服等有人工消息处理环节的功能,方便开发者为用户提供更加优质的服务”。
这篇文章我们就来说说如何用golang实现发送文本客服消息。
一、获取access_token
access_token是公众号的全局唯一票据,公众号调用微信平台各接口时都需使用access_token。
我们要主动给微信平台发送客服消息,该access_token就是我们的凭证。
在构造和下发客服消息前,我们需要获取这个access_token。
access_token的有效期为2小时(7200s),我们获取一次,两小时内均可使用。
微信公众平台开发文档也给出了access_token获取、保存以及刷新的技术建议。
但我们这里仅是Demo,无需考虑这么多。
通过httpsGET请求,我们可以得到属于我们的access_token,请求line为:
golang提供了默认的httpclient实现,通过默认的client实现我们可以很容器的获取access_token。
const(
token="wechat4go"
appID="wx8e0fb2659c2eexxx"
appSecret="22746009b0162fe50cb915851c53fyyy"
accessTokenFetchUrl="
)
funcfetchAccessToken()(string,float64,error){
requestLine:
=strings.Join([]string{accessTokenFetchUrl,
"?
grant_type=client_credential&appid=",
appID,
"&secret=",
appSecret},"")
resp,err:
=http.Get(requestLine)
iferr!
=nil||resp.StatusCode!
=http.StatusOK{
return"",0.0,err
}
deferresp.Body.Close()
body,err:
=ioutil.ReadAll(resp.Body)
iferr!
=nil{
return"",0.0,err
}
fmt.Println(string(body))
……
}
无论成功与否,微信平台都会返回一个包含json数据的应答:
如果获取正确,那么应答里的Json数据为:
{"access_token":
"0QCeHwiRtPRUCiM5MM0cSPYIP5QOUNYdb8usRSgVZcsFuVF6mu3vQq41OIifJdrtJPGn7b1x90HdvUanpb7eZHxg40B6bU_Sgszh2byyF40","expires_in":
7200}
如果获取错误,那么应答里的Json数据为:
{"errcode":
40001,"errmsg":
"invalidcredential"}
和xml数据包一样,golang也提供了json格式数据包的Marshal和Unmarshal方法,且使用方式相同,也是将一个json数据包与一个struct对应起来。
从上面来看,通过httpresponse,我们无法区分出是否成功获取了token,因此我们需要首先判断试下body中是否包含某些特征字符串,比如"access_token":
ifbytes.Contains(body,[]byte("access_token")){
//unmarshaltoAccessTokenResponsestruct
}else{
//unmarshaltoAccessTokenErrorResponsestruct
}
针对获取成功以及失败的两种Json数据,我们定义了两个结构体:
typeAccessTokenResponsestruct{
AccessTokenstring`json:
"access_token"`
ExpiresInfloat64`json:
"expires_in"`
}
typeAccessTokenErrorResponsestruct{
Errcodefloat64
Errmsgstring
}
Jsonunmarshal的代码片段如下:
//JsonDecoding
ifbytes.Contains(body,[]byte("access_token")){
atr:
=AccessTokenResponse{}
err=json.Unmarshal(body,&atr)
iferr!
=nil{
return"",0.0,err
}
returnatr.AccessToken,atr.ExpiresIn,nil
}else{
fmt.Println("returnerr")
ater:
=AccessTokenErrorResponse{}
err=json.Unmarshal(body,&ater)
iferr!
=nil{
return"",0.0,err
}
return"",0.0,fmt.Errorf("%s",ater.Errmsg)
}
我们的main函数如下:
funcmain(){
accessToken,expiresIn,err:
=fetchAccessToken()
iferr!
=nil{
log.Println("Getaccess_tokenerror:
",err)
return
}
fmt.Println(accessToken,expiresIn)
}
编译执行,成功获取access_token的输出如下:
0QCeHwiRtPRUCiM5MM0cSPYIP5QOUNYdb8usRSgVZcsFuVF6mu3vQq41OIifJdrtJPGn7b1x90HdvUanpb7eZHxg40B6bU_Sgszh2byyF407200
失败时,输出如下:
2014/12/3012:
39:
56Getaccess_tokenerror:
invalidcredential
二、发送客服消息
平台开发文档中定义了文本客服消息的body格式,一个json数据:
{
"touser":
"OPENID",
"msgtype":
"text",
"text":
{
"content":
"HelloWorld"
}
}
其中的touser填写的是openid。
之前的文章中提到过,每个微信用户针对某一个订阅号/服务号都有唯一的OpenID,这个ID可以在微信订阅号/服务号管理页面中看到,也可以在收到的微信平台转发的消息中看到(FromUserName)。
比如我个人订阅的我的测试体验号后得到的OpenID为:
BQcwuAbKpiSAbbvd_DEZg7q27QI
我们要做的就是构造这样一个json数据,并放入HTTPPost包中,发到:
从平台开发文档给出的json数据包样例来看,这是个嵌套json数据包,我们通过下面方法marshall:
typeCustomServiceMsgstruct{
ToUserstring`json:
"touser"`
MsgTypestring`json:
"msgtype"`
TextTextMsgContent`json:
"text"`
}
typeTextMsgContentstruct{
Contentstring`json:
"content"`
}
funcpushCustomMsg(accessToken,toUser,msgstring)error{
csMsg:
=&CustomServiceMsg{
ToUser:
toUser,
MsgType:
"text",
Text:
TextMsgContent{Content:
msg},
}
body,err:
=json.MarshalIndent(csMsg,"","")
iferr!
=nil{
returnerr
}
fmt.Println(string(body))
……
}
如果单纯输出上面marshal的结果,可以看到:
{
"touser":
"oBQcwuAbKpiSAbbvd_DEZg7q27QI",
"msgtype":
"text",
"text":
{
"content":
"你好"
}
}
接下来将marshal后的[]byte放入一个httppost的body中,发送到指定url中:
varopenID="oBQcwuAbKpiSAbbvd_DEZg7q27QI"
funcpushCustomMsg(accessToken,toUser,msgstring)error{
……
postReq,err:
=http.NewRequest("POST",
strings.Join([]string{customServicePostUrl,"?
access_token=",accessToken},""),
bytes.NewReader(body))
iferr!
=nil{
returnerr
}
postReq.Header.Set("Content-Type","application/json;encoding=utf-8")
client:
=&http.Client{}
resp,err:
=client.Do(postReq)
iferr!
=nil{
returnerr
}
resp.Body.Close()
returnnil
}
我们在main函数中加上客服消息的发送环节:
funcmain(){
//Fetchaccess_token
accessToken,expiresIn,err:
=fetchAccessToken()
iferr!
=nil{
log.Println("Getaccess_tokenerror:
",err)
return
}
fmt.Println(accessToken,expiresIn)
//Postcustomservicemessage
msg:
="你好"
err=pushCustomMsg(accessToken,openID,msg)
iferr!
=nil{
log.Println("Pushcustomservicemessageerr:
",err)
return
}
}
编译执行,手机响起提示音,打开观看,微信公众平台测试号发来消息:
“你好”。
上述Demo完整代码在这里可以看到,别忘了appID,appSecret改成你自己的值。
目前客服接口仅提供给认证后的订阅号以及服务号,对于未认证的订阅号,无法发送客服消息。
2014,bigwhite.版权所有.
Relatedposts:
使用Golang开发微信公众平台-接收文本消息
使用Golang开发微信公众平台-接收加密消息
使用Golang开发微信公众平台-接入验证
ShareSDKCocos2d-x专用组件的一个Bug
Cocos2d-x3.0rc2集成ShareSDK