使用golang快速開發微信公眾平台(三):定製菜單

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

在搞定使用golang快速開發公眾平台(二):擷取accessToken後,我們可以開始著手自訂菜單

自訂菜單簡單粗暴,post請求裡塞入要定義的菜單即可。

開始搓代碼

func PushWxMenuCreate(accessToken string, menuJsonBytes []byte) error {    postReq, err := http.NewRequest("POST",        strings.Join([]string{"https://api.weixin.qq.com/cgi-bin/menu/create", "?access_token=", accessToken}, ""),        bytes.NewReader(menuJsonBytes))    if err != nil {        fmt.Println("向發送菜單建立請求失敗", err)        logUtils.GetLog().Error("向發送菜單建立請求失敗", err)        return err    }    postReq.Header.Set("Content-Type", "application/json; encoding=utf-8")    client := &http.Client{}    resp, err := client.Do(postReq)    if err != nil {        fmt.Println("client向發送菜單建立請求失敗", err)        logUtils.GetLog().Error("client向發送菜單建立請求失敗", err)        return err    } else {        fmt.Println("向發送菜單建立成功")    }    defer resp.Body.Close()    return nil}func createWxMenu(o orm.Ormer) {    //btn1 := models.Btn{Name: "進入商城", Url: "http://www.baidu.com/", Btype: "view"}    //btn2 := models.Btn{Name: "測試人員中樞", Key: "molan_user_center", Btype: "click"}    //btn3 := models.Btn{Name: "我的", Url: "http://www.baidu.com/user_view", Btype: "view"}    //    //btns := []models.Btn{btn1, btn2, btn3}    //wxMenu := models.WxMenu{Button: btns}    //menuJsonBytes, err := json.Marshal(wxMenu)    menuStr := `{            "button": [            {                "name": "進入商城",                "type": "view",                "url": "http://www.baidu.com/"            },            {                "name":"管理中心",                 "sub_button":[                        {                        "name": "使用者中心",                        "type": "click",                        "key": "molan_user_center"                        },                        {                        "name": "公告",                        "type": "click",                        "key": "molan_institution"                        }]            },            {                "name": "資料修改",                "type": "view",                "url": "http://www.baidu.com/user_view"            }            ]        }`    //if err == nil {    //fmt.Println("產生的菜單json--->", menuStr)    at := models.WxAccessToken{Id: 1}    o.ReadOrCreate(&at, "id")    //發送建立菜單的post請求    WxPlatUtil.PushWxMenuCreate(at.AccessToken, []byte(menuStr))    //} else {    //  logUtils.GetLog().Error("菜單json轉換錯誤", err)    //}}

使用struct來產生json收到了慘不忍睹的效果,於是我乾脆粗暴的把json直接寫出來傳進去。。。

使用者在點擊菜單的時候,會把響應資訊以post請求的方式發送到我們在伺服器配置中填寫的URL中去,即使用beego快速開發公眾平台(一):開啟伺服器配置中的 /wx_connect。而這一點文檔壓根不提,如果你是上來就做的支付功能,做到這一步一定會問候文檔作者的八輩祖宗。

好在我們機智的把支付功能放在了後面,並未對咱們的思路造成混亂,所以接下來還是無壓力的。

當使用者點擊菜單,伺服器會post過來一個xml,類似這樣:

<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[FromUser]]></FromUserName><CreateTime>123456789</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[VIEW]]></Event><EventKey><![CDATA[www.qq.com]]></EventKey><MenuId>MENUID</MenuId></xml>

我們可以找到是發給誰的(ToUserName) 哪個使用者觸發的(FromUserName) 通過什麼方式觸發的(Event EventKey),解析這個xml就行

都閃開 我要搓代碼了:

WxConnect.go

//type WxMenuEvent struct {//  ToUserName   string        `xml:"ToUserName"`//  FromUserName string        `xml:"FromUserName"`//  CreateTime   int64        `xml:"CreateTime"`//  MsgType      string        `xml:"MsgType"`//  Event        string        `xml:"Event"`        //VIEW  //  EventKey     string        `xml:"EventKey"`//  MenuId       string        `xml:"MenuId"`//  ScanCodeInfo *ScanCodeInfo `xml:"ScanCodeInfo"` //專屬於掃碼//  Content      string `xml:"Content"`//  Ticket      string `xml:"Ticket"`//}//type ScanCodeInfo struct {//  ScanType   string `xml:"ScanType"`//  ScanResult string `xml:"ScanResult"`//}//菜單使用者點擊 掃碼響應func (c *WxConnectController) Post() {    if bytes, err := ioutil.ReadAll(c.Ctx.Request.Body); err == nil {        //解析xml        wxEvent := new(models.WxMenuEvent)        if err := xml.Unmarshal(bytes, wxEvent); err == nil {            //處理菜單點擊            dealWithMenuEvent(&wxEvent)        } else {            fmt.Println("菜單使用者點擊、掃碼響應錯誤", err)        }    } else {        fmt.Println("菜單使用者點擊、掃碼解析body錯誤", err)    }    c.EnableRender = false}func dealWithMenuEvent(wxEvent **models.WxMenuEvent){    switch wxEvent.Event {            case "VIEW"://說明是點擊底部功能表列進入商城頁面            case "CLICK"://點擊按鈕                if strings.EqualFold(wxEvent.EventKey, "molan_user_center") {                    //點擊使用者中心                } else if strings.EqualFold(wxEvent.EventKey, "molan_institution") {                    //點擊公告                }            case "subscribe"://掃碼            if strings.Contains(wxEvent.EventKey, "qrscene") {                //未關注過商城 掃描他人二維碼首次關注                upperId := strings.Split(wxEvent.EventKey, "_")[1]//EventKey:qrscene_16 這個16就是upper在資料庫的id 注意不是wxid            } else {                //關注(掃官方二維碼 而不是掃個人二維碼)            }            case "SCAN"://已關注 掃描他人二維碼            }}

這裡掃碼比較噁心,eventKey可以作為識別是目前使用者掃哪個使用者的碼,qrscene_xxxx 這個xxxx是你自己設的,大家知道就行。
到這一步,響應基本算是走完了。

但是 GRD需求總是不放過我們

老闆說了:我想知道是哪個使用者點了某個按鈕,然後根據不同使用者給予不同的響應。
這就需要用到WxMenuEvent.FromUserName,這個FromUserName是使用者openID,注意這玩意不是使用者的號。

官網是這樣寫的:

快閃開我憋不住了:

func FetchWxInfoAndIcon(o orm.Ormer, openid, wxUserInforUrl string) (*models.WxUserInfo, error) {    at := models.WxAccessToken{Id: 1}    o.ReadOrCreate(&at, "id")    requestLine := strings.Join([]string{wxUserInforUrl,        "?access_token=",        at.AccessToken,        "&openid=",        openid,        "&lang=zh_CN"}, "")    resp, err := http.Get(requestLine)    if err != nil || resp.StatusCode != http.StatusOK {        fmt.Println("發送get請求擷取 wxUserInfo 錯誤", err)        logUtils.GetLog().Error("發送get請求擷取 wxUserInfo 錯誤", err)        return nil, err    }    defer resp.Body.Close()    body, err := ioutil.ReadAll(resp.Body)    if err != nil {        fmt.Println("發送get請求擷取 wxUserInfo 讀取返回body錯誤", err)        logUtils.GetLog().Error("發送get請求擷取 wxUserInfo 讀取返回body錯誤", err)        return nil, err    }    if bytes.Contains(body, []byte("errcode")) {        ater := models.AccessTokenErrorResponse{}        err = json.Unmarshal(body, &ater)        if err != nil {            fmt.Printf("發送get請求擷取 wxUserInfo 的錯誤資訊 %+v\n", ater)            logUtils.GetLog().Error("發送get請求擷取 wxUserInfo 的錯誤資訊 %+v\n", ater)            return nil,  err        }        return nil, fmt.Errorf("%s", ater.Errmsg)    } else {        atr := models.WxUserInfo{}        err = json.Unmarshal(body, &atr)        if err != nil {            fmt.Println("發送get請求擷取 wxUserInfo 返回資料json解析錯誤", err)            logUtils.GetLog().Error("發送get請求擷取 wxUserInfo 返回資料json解析錯誤", err)            return nil, 0.0, err        }        return &atr, nil    }}

好了,我們現在拿到了使用者的暱稱頭像,搞定收工

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.