国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
使用Golang開發(fā)微信公眾平臺

關(guān)注并使用過微信“飛常準(zhǔn)”公眾號的朋友們都有過如下體驗(yàn):查詢一個(gè)航班情況后,這個(gè)航班的checkin、登機(jī)、起降等信息都會(huì)在后續(xù)陸續(xù)異步發(fā)給你,這個(gè)服務(wù)就是通過微信公眾平臺的客服消息實(shí)現(xiàn)的。

微信公眾平臺開發(fā)文檔中關(guān)于客服消息的解釋如下:“當(dāng)用戶主動(dòng)發(fā)消息給公眾號的時(shí)候(包括發(fā)送信息、點(diǎn)擊自定義菜單、訂閱事件、掃描二維碼事件、支付成功 事件、用戶維權(quán)),微信將會(huì)把消息數(shù)據(jù)推送給開發(fā)者,開發(fā)者在一段時(shí)間內(nèi)(目前修改為48小時(shí))可以調(diào)用客服消息接口,通過POST一個(gè)JSON數(shù)據(jù)包來 發(fā)送消息給普通用戶,在48小時(shí)內(nèi)不限制發(fā)送次數(shù)。此接口主要用于客服等有人工消息處理環(huán)節(jié)的功能,方便開發(fā)者為用戶提供更加優(yōu)質(zhì)的服務(wù)”。

這篇文章我們就來說說如何用golang實(shí)現(xiàn)發(fā)送文本客服消息。

一、獲取access_token

access_token是公眾號的全局唯一票據(jù),公眾號調(diào)用微信平臺各接口時(shí)都需使用access_token。我們要主動(dòng)給微信平臺發(fā)送客服消息,該access_token就是我們的憑證。在構(gòu)造和下發(fā)客服消息前,我們需要獲取這個(gè)access_token。

access_token的有效期為2小時(shí)(7200s),我們獲取一次,兩小時(shí)內(nèi)均可使用。微信公眾平臺開發(fā)文檔也給出了access_token獲取、保存以及刷新的技術(shù)建議。但我們這里僅是Demo,無需考慮這么多。

通過https GET請求,我們可以得到屬于我們的access_token,請求line為:

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

golang提供了默認(rèn)的http client實(shí)現(xiàn),通過默認(rèn)的client實(shí)現(xiàn)我們可以很容器的獲取access_token。

const (
        token               = "wechat4go"
        appID               = "wx8e0fb2659c2eexxx"
        appSecret           = "22746009b0162fe50cb915851c53fyyy"
        accessTokenFetchUrl = "https://api.weixin.qq.com/cgi-bin/token"
)

func fetchAccessToken() (string, float64, error) {
        requestLine := strings.Join([]string{accessTokenFetchUrl,
                "?grant_type=client_credential&appid=",
                appID,
                "&secret=",
                appSecret}, "")

        resp, err := http.Get(requestLine)
        if err != nil || resp.StatusCode != http.StatusOK {
                return "", 0.0, err
        }

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

        fmt.Println(string(body))
        … …
}

無論成功與否,微信平臺都會(huì)返回一個(gè)包含json數(shù)據(jù)的應(yīng)答:

如果獲取正確,那么應(yīng)答里的Json數(shù)據(jù)為:

{"access_token":"0QCeHwiRtPRUCiM5MM0cSPYIP5QOUNYdb8usRSgVZcsFuVF6mu3vQq41OIifJdrtJPGn7b1x90HdvUanpb7eZHxg40B6bU_Sgszh2byyF40","expires_in":7200}

如果獲取錯(cuò)誤,那么應(yīng)答里的Json數(shù)據(jù)為:

{"errcode":40001,"errmsg":"invalid credential"}

和xml數(shù)據(jù)包一樣,golang也提供了json格式數(shù)據(jù)包的Marshal和Unmarshal方法,且使用方式相同,也是將一個(gè)json數(shù)據(jù)包與一 個(gè)struct對應(yīng)起來。從上面來看,通過http response,我們無法區(qū)分出是否成功獲取了token,因此我們需要首先判斷試下body中是否包含某些特征字符串,比 如"access_token":

if bytes.Contains(body, []byte("access_token")) {
    //unmarshal to AccessTokenResponse struct
} else {
    //unmarshal to AccessTokenErrorResponse struct
}

針對獲取成功以及失敗的兩種Json數(shù)據(jù),我們定義了兩個(gè)結(jié)構(gòu)體:

type AccessTokenResponse struct {
        AccessToken string  `json:"access_token"`
        ExpiresIn   float64 `json:"expires_in"`
}

type AccessTokenErrorResponse struct {
        Errcode float64
        Errmsg  string
}

Json unmarshal的代碼片段如下:

//Json Decoding
if bytes.Contains(body, []byte("access_token")) {
        atr := AccessTokenResponse{}
        err = json.Unmarshal(body, &atr)
        if err != nil {
            return "", 0.0, err
        }
        return atr.AccessToken, atr.ExpiresIn, nil
} else {
        fmt.Println("return err")
        ater := AccessTokenErrorResponse{}
        err = json.Unmarshal(body, &ater)
        if err != nil {
            return "", 0.0, err
        }
        return "", 0.0, fmt.Errorf("%s", ater.Errmsg)
}

我們的main函數(shù)如下:
func main() {
        accessToken, expiresIn, err := fetchAccessToken()
        if err != nil {
                log.Println("Get access_token error:", err)
                return
        }
        fmt.Println(accessToken, expiresIn)
}

編譯執(zhí)行,成功獲取access_token的輸出如下:

0QCeHwiRtPRUCiM5MM0cSPYIP5QOUNYdb8usRSgVZcsFuVF6mu3vQq41OIifJdrtJPGn7b1x90HdvUanpb7eZHxg40B6bU_Sgszh2byyF40 7200

失敗時(shí),輸出如下:

2014/12/30 12:39:56 Get access_token error: invalid credential

二、發(fā)送客服消息

平臺開發(fā)文檔中定義了文本客服消息的body格式,一個(gè)json數(shù)據(jù):

{
    "touser":"OPENID",
    "msgtype":"text",
    "text":
    {
         "content":"Hello World"
    }
}

其中的touser填寫的是openid。之前的文章中提到過,每個(gè)微信用戶針對某一個(gè)訂閱號/服務(wù)號都有唯一的OpenID,這個(gè)ID可以在微信訂閱號 /服務(wù)號管理頁面中看到,也可以在收到的微信平臺轉(zhuǎn)發(fā)的消息中看到(FromUserName)。比如我個(gè)人訂閱的我的測試體驗(yàn)號后得到的OpenID 為:

BQcwuAbKpiSAbbvd_DEZg7q27QI

我們要做的就是構(gòu)造這樣一個(gè)json數(shù)據(jù),并放入HTTP Post包中,發(fā)到:

https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN

從平臺開發(fā)文檔給出的json數(shù)據(jù)包樣例來看,這是個(gè)嵌套json數(shù)據(jù)包,我們通過下面方法marshall:

type CustomServiceMsg struct {
        ToUser  string         `json:"touser"`
        MsgType string         `json:"msgtype"`
        Text    TextMsgContent `json:"text"`
}

type TextMsgContent struct {
        Content string `json:"content"`
}

func pushCustomMsg(accessToken, toUser, msg string) error {
        csMsg := &CustomServiceMsg{
                ToUser:  toUser,
                MsgType: "text",
                Text:    TextMsgContent{Content: msg},
        }

        body, err := json.MarshalIndent(csMsg, " ", "  ")
        if err != nil {
                return err
        }
        fmt.Println(string(body))
        … …
}

如果單純輸出上面marshal的結(jié)果,可以看到:

{
   "touser": "oBQcwuAbKpiSAbbvd_DEZg7q27QI",
   "msgtype": "text",
   "text": {
     "content": "你好"
   }
 }

接下來將marshal后的[]byte放入一個(gè)http post的body中,發(fā)送到指定url中:

var openID = "oBQcwuAbKpiSAbbvd_DEZg7q27QI"

func pushCustomMsg(accessToken, toUser, msg string) error {
        … …

        postReq, err := http.NewRequest("POST",
                strings.Join([]string{customServicePostUrl, "?access_token=", accessToken}, ""),
                bytes.NewReader(body))
        if err != nil {
                return err
        }

        postReq.Header.Set("Content-Type", "application/json; encoding=utf-8")

        client := &http.Client{}
        resp, err := client.Do(postReq)
        if err != nil {
                return err
        }
        resp.Body.Close()

        return nil
}

我們在main函數(shù)中加上客服消息的發(fā)送環(huán)節(jié):

func main() {
        // Fetch access_token
        accessToken, expiresIn, err := fetchAccessToken()
        if err != nil {
                log.Println("Get access_token error:", err)
                return
        }
        fmt.Println(accessToken, expiresIn)

        // Post custom service message
        msg := "你好"
        err = pushCustomMsg(accessToken, openID, msg)
        if err != nil {
                log.Println("Push custom service message err:", err)
                return
        }
}

編譯執(zhí)行,手機(jī)響起提示音,打開觀看,微信公眾平臺測試號發(fā)來消息:“你好”。

上述Demo完整代碼在這里可以看到,別忘了appID,appSecret改成你自己的值。

目前客服接口僅提供給認(rèn)證后的訂閱號以及服務(wù)號,對于未認(rèn)證的訂閱號,無法發(fā)送客服消息。

2014, bigwhite. 版權(quán)所有.

Related posts:

  1. 使用Golang開發(fā)微信公眾平臺-接收文本消息
  2. 使用Golang開發(fā)微信公眾平臺-接收加密消息
  3. 使用Golang開發(fā)微信公眾平臺-接入驗(yàn)證
  4. ShareSDK Cocos2d-x專用組件的一個(gè)Bug
  5. Cocos2d-x 3.0rc2集成ShareSDK

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
【七天入門Go語言】 文件 && 包 | 第五天
使用 Casbin 在 Golang 項(xiàng)目中授權(quán)
在Gin下實(shí)現(xiàn)簡單的注冊登錄和狀態(tài)管理
Golang 新手可能會(huì)踩的 50 個(gè)坑
golang的json操作
誠之和:如何使用Go語言JSON 標(biāo)準(zhǔn)庫
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服