當(dāng)前位置:首頁(yè) > IT技術(shù) > 微信平臺(tái) > 正文

C#開(kāi)發(fā)微信門(mén)戶(hù)及應(yīng)用(29)--微信個(gè)性化菜單的實(shí)現(xiàn)
2021-07-26 10:24:11

C#開(kāi)發(fā)微信門(mén)戶(hù)及應(yīng)用(29)--微信個(gè)性化菜單的實(shí)現(xiàn)

有一段時(shí)間沒(méi)有接著微信的主題繼續(xù)介紹里面的功能模塊了,這段時(shí)間來(lái),微信也做了不少的變化改動(dòng),針對(duì)這些特性我全面核對(duì)了一下相關(guān)的微信公眾號(hào)和企業(yè)號(hào)的接口,對(duì)原有的微信API和系統(tǒng)管理做了全面的更新,本隨筆以及后面的隨筆就是基于這個(gè)工作上的總結(jié),以期把微信涉及的功能模塊,都使用C#實(shí)現(xiàn)的方式來(lái)介紹。本隨筆主要介紹微信公眾號(hào)的個(gè)性化菜單的實(shí)現(xiàn),雖然目前微信公眾號(hào)和企業(yè)號(hào)已經(jīng)在功能上接近一致,不過(guò)在企業(yè)號(hào)上還沒(méi)有個(gè)性化菜單的相關(guān)接口。

有一段時(shí)間沒(méi)有接著微信的主題繼續(xù)介紹里面的功能模塊了,這段時(shí)間來(lái),微信也做了不少的變化改動(dòng),針對(duì)這些特性我全面核對(duì)了一下相關(guān)的微信公眾號(hào)和企業(yè)號(hào)的接口,對(duì)原有的微信API和系統(tǒng)管理做了全面的更新,本隨筆以及后面的隨筆就是基于這個(gè)工作上的總結(jié),以期把微信涉及的功能模塊,都使用C#實(shí)現(xiàn)的方式來(lái)介紹。本隨筆主要介紹微信公眾號(hào)的個(gè)性化菜單的實(shí)現(xiàn),雖然目前微信公眾號(hào)和企業(yè)號(hào)已經(jīng)在功能上接近一致,不過(guò)在企業(yè)號(hào)上還沒(méi)有個(gè)性化菜單的相關(guān)接口。

1、個(gè)性化菜單介紹

我們先了解一下個(gè)性化菜單的介紹,根據(jù)官方的資料,如下介紹。

為了幫助公眾號(hào)實(shí)現(xiàn)靈活的業(yè)務(wù)運(yùn)營(yíng),微信公眾平臺(tái)新增了個(gè)性化菜單接口,開(kāi)發(fā)者可以通過(guò)該接口,讓公眾號(hào)的不同用戶(hù)群體看到不一樣的自定義菜單。該接口開(kāi)放給已認(rèn)證訂閱號(hào)和已認(rèn)證服務(wù)號(hào)。

開(kāi)發(fā)者可以通過(guò)以下條件來(lái)設(shè)置用戶(hù)看到的菜單:

1、用戶(hù)分組(開(kāi)發(fā)者的業(yè)務(wù)需求可以借助用戶(hù)分組來(lái)完成)
2、性別
3、手機(jī)操作系統(tǒng)
4、地區(qū)(用戶(hù)在微信客戶(hù)端設(shè)置的地區(qū))
5、語(yǔ)言(用戶(hù)在微信客戶(hù)端設(shè)置的語(yǔ)言)

個(gè)性化菜單接口說(shuō)明:

1、個(gè)性化菜單要求用戶(hù)的微信客戶(hù)端版本在iPhone6.2.2,Android 6.2.4以上。
2、菜單的刷新策略是,在用戶(hù)進(jìn)入公眾號(hào)會(huì)話(huà)頁(yè)或公眾號(hào)profile頁(yè)時(shí),如果發(fā)現(xiàn)上一次拉取菜單的請(qǐng)求在5分鐘以前,就會(huì)拉取一下菜單,如果菜單有更新,就會(huì)刷新客戶(hù)端的菜單。測(cè)試時(shí)可以嘗試取消關(guān)注公眾賬號(hào)后再次關(guān)注,則可以看到創(chuàng)建后的效果。
3、普通公眾號(hào)的個(gè)性化菜單的新增接口每日限制次數(shù)為2000次,刪除接口也是2000次,測(cè)試個(gè)性化菜單匹配結(jié)果接口為20000次
4、出于安全考慮,一個(gè)公眾號(hào)的所有個(gè)性化菜單,最多只能設(shè)置為跳轉(zhuǎn)到3個(gè)域名下的鏈接
5、創(chuàng)建個(gè)性化菜單之前必須先創(chuàng)建默認(rèn)菜單(默認(rèn)菜單是指使用普通自定義菜單創(chuàng)建接口創(chuàng)建的菜單)。如果刪除默認(rèn)菜單,個(gè)性化菜單也會(huì)全部刪除

個(gè)性化菜單匹配規(guī)則說(shuō)明:

當(dāng)公眾號(hào)創(chuàng)建多個(gè)個(gè)性化菜單時(shí),將按照發(fā)布順序,由新到舊逐一匹配,直到用戶(hù)信息與matchrule相符合。如果全部個(gè)性化菜單都沒(méi)有匹配成功,則返回默認(rèn)菜單。
例如公眾號(hào)先后發(fā)布了默認(rèn)菜單,個(gè)性化菜單1,個(gè)性化菜單2,個(gè)性化菜單3。那么當(dāng)用戶(hù)進(jìn)入公眾號(hào)頁(yè)面時(shí),將從個(gè)性化菜單3開(kāi)始匹配,如果個(gè)性化菜單3匹配成功,則直接返回個(gè)性化菜單3,否則繼續(xù)嘗試匹配個(gè)性化菜單2,直到成功匹配到一個(gè)菜單。
根據(jù)上述匹配規(guī)則,為了避免菜單生效時(shí)間的混淆,決定不予提供個(gè)性化菜單編輯API,開(kāi)發(fā)者需要更新菜單時(shí),需將完整配置重新發(fā)布一輪。

除正常的默認(rèn)菜單外,個(gè)性化菜單提供了下面幾個(gè)處理操作。

1 創(chuàng)建個(gè)性化菜單

2 刪除個(gè)性化菜單

3 測(cè)試個(gè)性化菜單匹配結(jié)果

4 查詢(xún)個(gè)性化菜單

5 刪除所有菜單

個(gè)性化自定義菜單功能,是指商家可以根據(jù)粉絲的分組、性別、手機(jī)操作系統(tǒng),甚至地區(qū),來(lái)分別展示公眾號(hào)的菜單。

比如,一家健身會(huì)所的公眾號(hào),將自定義菜單根據(jù)粉絲性別進(jìn)行了分開(kāi)設(shè)置。男性粉絲進(jìn)入公眾號(hào)會(huì)展示男生們比較感興趣菜單內(nèi)容,跆拳道、搏擊等;若是女性粉絲,則會(huì)展示瑜伽、舞蹈、防身術(shù)等女性粉絲感興趣的菜單課程等。

C#開(kāi)發(fā)微信門(mén)戶(hù)及應(yīng)用(29)--微信個(gè)性化菜單的實(shí)現(xiàn)_編程

?

2、個(gè)性化菜單的C#設(shè)計(jì)處理

微信的菜單是微信處理中很重要的一環(huán),因?yàn)樗俏⑿沤o用戶(hù)入口體驗(yàn)重要的一環(huán),也是很直觀的界面呈現(xiàn)之一,菜單的展示就是需要我們絞盡腦汁來(lái)精簡(jiǎn)的界面元素了,由于菜單的重要性以及功能的豐富性,我在之前好幾篇隨筆專(zhuān)門(mén)介紹了菜單的各種處理。

在《C#開(kāi)發(fā)微信門(mén)戶(hù)及應(yīng)用(6)--微信門(mén)戶(hù)菜單的管理操作》、《C#開(kāi)發(fā)微信門(mén)戶(hù)及應(yīng)用(9)-微信門(mén)戶(hù)菜單管理及提交到微信服務(wù)器》、《C#開(kāi)發(fā)微信門(mén)戶(hù)及應(yīng)用(11)--微信菜單的多種表現(xiàn)方式介紹》、《C#開(kāi)發(fā)微信門(mén)戶(hù)及應(yīng)用(20)-微信企業(yè)號(hào)的菜單管理》分別對(duì)相關(guān)的菜單有過(guò)介紹,有需要可以參考了解一下。

菜單模塊,在微信公眾號(hào)和企業(yè)號(hào),它們都可以共用一個(gè)模型,因此我們把這些內(nèi)容都放在微信共用模塊里面,包括它的實(shí)體類(lèi)信息(如菜單模塊),雖然有些地方,部分字段內(nèi)容沒(méi)有,但是我們可以通過(guò)實(shí)體類(lèi)的JSON標(biāo)識(shí)來(lái)進(jìn)行處理,從而實(shí)現(xiàn)比較彈性化的實(shí)體類(lèi)信息承載。

如下標(biāo)識(shí)代碼所示。

    /// <summary>
    /// 菜單基本信息(公眾號(hào)、企業(yè)號(hào)公用,其他部分一樣)
    /// </summary>
    public class MenuJson : BaseJsonResult
    {
        /// <summary>
        /// 按鈕描述,既按鈕名字,不超過(guò)16個(gè)字節(jié),子菜單不超過(guò)40個(gè)字節(jié)
        /// </summary>
        public string name { get; set; }

        /// <summary>
        /// 按鈕類(lèi)型(click或view)
        /// </summary>
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string type { get; set; }

        /// <summary>
        /// 按鈕KEY值,用于消息接口(event類(lèi)型)推送,不超過(guò)128字節(jié)
        /// </summary>
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string key { get; set; }

        /// <summary>
        /// 網(wǎng)頁(yè)鏈接,用戶(hù)點(diǎn)擊按鈕可打開(kāi)鏈接,不超過(guò)256字節(jié)
        /// </summary>
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string url { get; set; }

        /// <summary>
        /// media_id類(lèi)型和view_limited類(lèi)型必須,調(diào)用新增永久素材接口返回的合法media_id
        /// </summary>
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string media_id { get; set; }

        /// <summary>
        /// 子按鈕數(shù)組,按鈕個(gè)數(shù)應(yīng)為2~5個(gè)
        /// </summary>
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public List<MenuJson> sub_button { get; set; }

上面這個(gè)實(shí)體類(lèi)是菜單信息的基礎(chǔ)信息,我們需要從這個(gè)基礎(chǔ)上擴(kuò)展出來(lái)幾個(gè)實(shí)體類(lèi),方便在構(gòu)建,獲取菜單信息的時(shí)候進(jìn)行信息轉(zhuǎn)換,如下幾個(gè)類(lèi)圖的設(shè)計(jì)所示。

C#開(kāi)發(fā)微信門(mén)戶(hù)及應(yīng)用(29)--微信個(gè)性化菜單的實(shí)現(xiàn)_編程_02

通過(guò)這幾個(gè)類(lèi)的關(guān)系,我們就可以適應(yīng)所有的默認(rèn)菜單和個(gè)性化菜單,以及企業(yè)號(hào)的菜單信息轉(zhuǎn)換處理了,通過(guò)JSON轉(zhuǎn)換為對(duì)應(yīng)的實(shí)體類(lèi),實(shí)現(xiàn)信息的強(qiáng)類(lèi)型處理。

其中我們菜單處理的API實(shí)現(xiàn)類(lèi)代碼如下所示。

    /// <summary>
    /// 菜單的相關(guān)操作
    /// </summary>
    public class MenuApi : IMenuApi

這樣我們?cè)贗MenuApi的基礎(chǔ)上增加幾個(gè)個(gè)性化的接口。

        /// <summary>
        /// 創(chuàng)建個(gè)性化菜單
        /// </summary>
        /// <param name="accessToken">調(diào)用接口憑證</param>
        /// <param name="menuJson">菜單對(duì)象</param>
        /// <returns></returns>
        string CreateConditionalMenu(string accessToken, MenuListJson menuJson);

        /// <summary>
        /// 根據(jù)菜單ID刪除個(gè)性化菜單
        /// </summary>
        /// <param name="accessToken">調(diào)用接口憑證</param>
        /// <param name="menuid">菜單ID</param>
        /// <returns></returns>
        CommonResult DeleteConditionalMenu(string accessToken, string menuid);

        /// <summary>
        /// 測(cè)試個(gè)性化菜單匹配結(jié)果
        /// </summary>
        /// <param name="accessToken">調(diào)用接口憑證</param>
        /// <returns></returns>
        MenuListJson TryMatchConditionalMenu(string accessToken, string user_id);

然后在MenuApi實(shí)現(xiàn)類(lèi)里面實(shí)現(xiàn)相關(guān)的邏輯處理即可。

下面是創(chuàng)建個(gè)性化菜單的接口說(shuō)明。

創(chuàng)建個(gè)性化菜單

http請(qǐng)求方式:POST(請(qǐng)使用https協(xié)議)

https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=ACCESS_TOKEN

請(qǐng)求示例

{
 	"button":[
 	{	
    	"type":"click",
    	"name":"今日歌曲",
     	"key":"V1001_TODAY_MUSIC" 
	},
	{ 
		"name":"菜單",
		"sub_button":[
		{	
			"type":"view",
			"name":"搜索",
			"url":"http://www.soso.com/"
		},
		{
			"type":"view",
			"name":"視頻",
			"url":"http://v.qq.com/"
		},
		{
			"type":"click",
			"name":"贊一下我們",
			"key":"V1001_GOOD"
		}]
 }],
"matchrule":{
  "group_id":"2",
  "sex":"1",
  "country":"中國(guó)",
  "province":"廣東",
  "city":"廣州",
  "client_platform_type":"2"
  "language":"zh_CN"
  }
}

其中上面的信息,轉(zhuǎn)換為我們的實(shí)體類(lèi)對(duì)象信息就是如下所示。

MenuListJson menuJson

它API返回結(jié)果如下所示。

{
	"menuid":"208379533"
}

為了承載這個(gè)信息,我們需要定義一個(gè)實(shí)體類(lèi)來(lái)承載這個(gè)信息。

    /// <summary>
    /// 返回MenuId的結(jié)果
    /// </summary>
    public class MenuIdResult
    {       
        /// <summary>
        /// 菜單的ID
        /// </summary>
        public string menuid { get; set; }
    }

最后我們的API接口只需要獲取里面的菜單ID值,字符串類(lèi)型的就可以了,API具體實(shí)現(xiàn)代碼如下所示。

        /// <summary>
        /// 創(chuàng)建個(gè)性化菜單
        /// </summary>
        /// <param name="accessToken">調(diào)用接口憑證</param>
        /// <param name="menuJson">菜單對(duì)象</param>
        /// <returns></returns>
        public string CreateConditionalMenu(string accessToken, MenuListJson menuJson)
        {
            string result = "";
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token={0}", accessToken);
            //matchrule不能為空
            ArgumentValidation.CheckForNullReference(menuJson.matchrule, "matchrule");

            string postData = menuJson.ToJson();
            MenuIdResult list = JsonHelper<MenuIdResult>.ConvertJson(url, postData);
            if (list != null)
            {
                result = list.menuid;
            }
            return result;
        }

而刪除個(gè)性化菜單的接口也是類(lèi)似的處理,如下所示。

        /// <summary>
        /// 根據(jù)菜單ID刪除個(gè)性化菜單
        /// </summary>
        /// <param name="accessToken">調(diào)用接口憑證</param>
        /// <param name="menuid">菜單ID</param>
        /// <returns></returns>
        public CommonResult DeleteConditionalMenu(string accessToken, string menuid)
        {
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/menu/delconditional?access_token={0}", accessToken);
            var data = new
            {
                menuid = menuid
            };

            string postData = data.ToJson();
            return Helper.GetExecuteResult(url, postData);
        }

另外,對(duì)于個(gè)性化菜單來(lái)說(shuō),查詢(xún)、刪除所有的菜單操作接口和普通默認(rèn)菜單是一樣的,因此可以重用這兩個(gè)接口,不過(guò)由于我們擴(kuò)展了查詢(xún)返回的信息類(lèi),所以如果是個(gè)性化菜單,那么它返回的JSON字符串里面,包含了conditionalmenu的屬性,這個(gè)是一個(gè)集合 ,也就是說(shuō)個(gè)性化菜單是多個(gè)規(guī)則的個(gè)性化菜單的集合。

C#開(kāi)發(fā)微信門(mén)戶(hù)及應(yīng)用(29)--微信個(gè)性化菜單的實(shí)現(xiàn)_編程_03

菜單的JSON數(shù)據(jù)結(jié)構(gòu)如下所示。

C#開(kāi)發(fā)微信門(mén)戶(hù)及應(yīng)用(29)--微信個(gè)性化菜單的實(shí)現(xiàn)_微信公眾平臺(tái)及門(mén)戶(hù)應(yīng)用_04

?

3、個(gè)性化菜單封裝接口的使用

有了上面接口的封裝,我們可以在創(chuàng)建個(gè)性化菜單的時(shí)候很方便了,構(gòu)建個(gè)性化菜單的時(shí)候,我們需要把全部需要出現(xiàn)的菜單都需要放在一個(gè)conditionalmenu的單元里面,雖然這樣的單元在集合里面出現(xiàn)多個(gè)。

如下面是構(gòu)建一個(gè)個(gè)性化的菜單項(xiàng)目,和普通的默認(rèn)菜單不同,它需要指定一個(gè)matchrule的對(duì)象,如下代碼所示。

            MenuJson conditional = new MenuJson("相關(guān)鏈接", new MenuJson[] { 
                new MenuJson("個(gè)性化菜單", ButtonType.click, "event_company")
            });
            MatchRule rule = new MatchRule()
            {
                sex = "1"
            };

            MenuListJson menuJson = new MenuListJson();
            menuJson.button.AddRange(new MenuJson[] { conditional });
            menuJson.matchrule = rule;

通過(guò)上面的代碼了解,我們?nèi)绻枰黾佣鄠€(gè)個(gè)性化菜單,那么就是通過(guò)這個(gè)方法,每次創(chuàng)建一個(gè)個(gè)性化菜單的方式進(jìn)行構(gòu)建,當(dāng)然如果我們使用查詢(xún)個(gè)性化菜單的結(jié)果可以看到,如果創(chuàng)建多個(gè),那么conditionalmenu集合里面是多個(gè)對(duì)象的。

調(diào)用代碼每次添加一個(gè)個(gè)性化菜單的操作如下所示。

                string menuid = menuBLL.CreateConditionalMenu(token, menuJson);
                Console.WriteLine("創(chuàng)建菜單:" + (!string.IsNullOrEmpty(menuid) ? "成功:" + menuid : "失敗"));

我們創(chuàng)建多個(gè)規(guī)則后,可以通過(guò)TryMatch的方式來(lái)檢查匹配的結(jié)果,也就是對(duì)應(yīng)不同用戶(hù)(openid)會(huì)出現(xiàn)不同的個(gè)性化菜單列表了。

                    var myResult = menuBLL.TryMatchConditionalMenu(token, openId);
                    if (myResult != null)
                    {
                        Console.WriteLine(myResult.ToJson());
                    }

                    var userid_female = "oSiLnt2J4mYkhVG3aLTdMIF1hv-s";//女性的ID
                    myResult = menuBLL.TryMatchConditionalMenu(token, userid_female);
                    if (myResult != null)
                    {
                        Console.WriteLine(myResult.ToJson());
                    }

?

C#開(kāi)發(fā)微信門(mén)戶(hù)及應(yīng)用(29)--微信個(gè)性化菜單的實(shí)現(xiàn)_編程_05主要研究技術(shù):代碼生成工具、會(huì)員管理系統(tǒng)、客戶(hù)關(guān)系管理軟件、病人資料管理軟件、Visio二次開(kāi)發(fā)、酒店管理系統(tǒng)、倉(cāng)庫(kù)管理系統(tǒng)等共享軟件開(kāi)發(fā)
專(zhuān)注于Winform開(kāi)發(fā)框架/混合式開(kāi)發(fā)框架、Web開(kāi)發(fā)框架、Bootstrap開(kāi)發(fā)框架、微信門(mén)戶(hù)開(kāi)發(fā)框架的研究及應(yīng)用。
??轉(zhuǎn)載請(qǐng)注明出處:
C#開(kāi)發(fā)微信門(mén)戶(hù)及應(yīng)用(29)--微信個(gè)性化菜單的實(shí)現(xiàn)_編程_05撰寫(xiě)人:伍華聰? ?

本文摘自 :https://blog.51cto.com/w

開(kāi)通會(huì)員,享受整站包年服務(wù)立即開(kāi)通 >