首頁 微信小程式 微信開發 微信公眾平台SDK過程詳解

微信公眾平台SDK過程詳解

Apr 27, 2017 pm 01:49 PM

服務號碼說明:提供企業和組織更強大的業務服務與使用者管理能力,幫助企業快速實現全新的公眾號服務平台。

.NETSDK:Loogn.WeiXinSDK (net2.0原始碼,下面程式碼只是大概,不太正確,請自行下載原始碼)

由於本人用的還是NOKIA-C5,沒用過微信,對微信的了解肯定沒你多,但公司有需求,只好硬著頭皮直接看接口文件了。

看後發現也挺有趣的,一個很有用的作用就是,當用戶給公眾帳號發送訊息時,程式可以根據用戶發送的內容自動回覆用戶,例如給一個物流公司的公眾帳號發個運單號,

對方自動回覆你這個運單號的物流詳細,感覺挺酷!為了說明方便,先給予申請好的公眾帳號資訊:

下圖為表示上面查看物流詳細的訊息流程(虛線的編號表示流程的順序):

 

微信會向你的URL發送兩大類訊息:

一是用戶的一般訊息,如上面用戶發送的單號;

二是使用者的行為(即文件中所說的事件)  ,如使用者追蹤了你的公用帳號、掃描了公有帳號的二維碼、點選了你自訂的選單等。

 你的URL就可以根據收到的訊息類型和內容做出回應以實現強大的業務服務,如上面返回的物流詳細。訊息全部是以XML格式傳遞,而SDK做的就是把XML轉換成.NET對象,以便你寫業務邏輯。訊息的框架類別圖表示為(點擊查看包含子類別的全圖):

 首先有個訊息基類,然後是收到的訊息(RecEventBaseMsg)和回覆的訊息(ReplyBaseMsg),上面說了,收到的訊息分成兩大類,即一般訊息(RecBaseMsg)和事件訊息(EventBaseMsg),收到的訊息類型用枚舉表示可以是:

其他的型別不說,而當MsgType為Event時,訊息就是EventBaseMsg的子類別了,所有EventBaseMsg的子類別的MsgType都是Event,所以EventBaseMsg型別又有個EventType來區分不同的事件,如果你看過接口文檔,你應該知道,它的事件類型對我們判斷到底是哪個事件不太友好,掃描二維碼事件分了用戶已關注和未關注兩種情況,已關注時EvenType是scan,未關注時EventType是subscribe,而用戶關注事件的EventType也是subscribe,所以SDK裡又加了個MyEventType:

現在訊息的流程基本上清楚了,呼叫SDK回覆訊息如下:

using System.Web;using Loogn.WeiXinSDK;using Loogn.WeiXinSDK.Message;namespace WebTest
{    /// <summary>
    /// 微信->服务器配置URL    /// </summary>
    public class WeiXinAPI : IHttpHandler
    {        static string Token = "Token";//这里是Token不是Access_Token
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";            var signature = context.Request["signature"];            var timestamp = context.Request["timestamp"];            var nonce = context.Request["nonce"];            if (WeiXin.CheckSignature(signature, timestamp, nonce, Token))//验证是微信给你发的消息            {                //根据注册的消息、事件处理程序回复,                //如果得到没用注册的消息或事件,会返回ReplyEmptyMsg.Instance,即GetXML()为string.Empty,符合微信的要求
                var replyMsg = WeiXin.ReplyMsg();                var xml = replyMsg.GetXML();                //WriteLog(xml); //这里可以查看回复的XML消息                context.Response.Write(xml);
            }            else
            {
                context.Response.Write("fuck you!");
            }
        }        static WeiXinAPI()
        {
            WeiXin.ConfigGlobalCredential("appid", "appSecret");            //注册一个消息处理程序,当用户发"ABC",你回复“你说:ABC”;
            WeiXin.RegisterMsgHandler<RecTextMsg>((msg) =>
            {                return new ReplyTextMsg
                {
                    Content = "你说:" + msg.Content                    //FromUserName = msg.ToUserName,  默认就是这样,不用设置!                    //ToUserName = msg.FromUserName,  默认就是这样,不用设置!                    //CreateTime = DateTime.Now.Ticks     默认就是这样,不用设置!                };
            });            //注册一个用户关注的事件处理程序,当用户关注你的公众账号时,你回复“Hello!”
            WeiXin.RegisterEventHandler<EventAttendMsg>((msg) =>
            {                return new ReplyTextMsg
                {
                    Content = "Hello !"
                };
            });            //还可以继续注册你感兴趣的消息、事件处理程序        }        public bool IsReusable
        {            get
            {                return false;
            }
        }
    }
}
登入後複製

 SDK包含了除(OAuth2.0網頁授權)的所有介面的封裝,類別名稱及方法名稱都很明顯,這裡就不一一演示,有興趣的朋友可以下載dll自行測試,這是一張付費認證過的介面圖:

#接下來談談實作的幾個細節:

一、憑證(access_token)過期

「access_token是公眾號的全域唯一票據,公眾號呼叫各介面時都需使用access_token。正常情況下access_token有效期限為7200秒 ,重複取得將導致上次取得的access_token失效。

根據文件上說的,我們可以想到用快取(不可能每次用每次取吧!),快取程式碼是很簡單的,主要是在這種情況下要能想到用緩存,下面是非完整程式碼:

 
       access_token { ;  
         
          expires_in { ;  Dictionary<, Credential> creds =  Dictionary<, Credential>  TokenUrl =   Credential GetCredential( appId, =  (creds.TryGetValue(appId,  (cred.add_time.AddSeconds(cred.expires_in - ) <=  json = Util.HttpGet2(= Util.JsonTo<Credential>
登入後複製

 二、錯誤碼訊息

上面說到得到憑證的程式碼不完整就是因為沒有處理可能傳回的錯誤碼,微信錯誤碼以json格式傳回,如:

{"errcode":40013,"errmsg":"invalid appid"}
登入後複製

大部分由我們主動呼叫的介面都有可能傳回錯誤碼,錯誤碼格式與正常回傳的資料格式完全不一樣,在SDK裡,我是這樣處理的,先定義好錯誤碼的模型類,我這裡叫ReturnCode,是因為錯誤碼裡還包含一個{"errcode":0,"errmsg":"ok"}的請求成功的情況:

       errcode { ;   errmsg { ;     + errcode +  + errmsg +
登入後複製

定義有錯誤碼的回傳訊息類別時我們就可以包含一個ReturnCode類型的屬性了,如建立二維碼介面:

    public class QRCodeTicket
    {        public string ticket { get; set; }        public int expire_seconds { get; set; }        public ReturnCode error { get; set; }
    }
登入後複製

從傳回的json到QRCodeTicket物件的程式碼大概就是這樣(其他的也是類似):

            var json = Util.HttpPost2(url, data);            if (json.IndexOf("ticket") > 0)
            {                return Util.JsonTo<QRCodeTicket>(json);
            }            else
            {
                QRCodeTicket tk = new QRCodeTicket();
                tk.error = Util.JsonTo<ReturnCode>(json);                return tk;
            }
登入後複製

所以用SDK呼叫介面後,得到的物件就可輕鬆判斷了:

            var qrcode = WeiXin.CreateQRCode(true, 23);            if (qrcode.error == null)
            {                //返回错误,可以用qrcode.error查看错误消息            }            else
            { 
                //返回正确,可以操作qrcode.ticket
            }
登入後複製

三、反序列化

微信接口返回的json有时候对我们映射到对象并不太直接(json格式太灵活了!),比如创建分组成功后返回的json:

{    "group": {        "id": 107, 
        "name": "test"
    }
}
登入後複製

如果想直接用json通过反序列化得到对象,那么这个对象的类的定义有可能会是这样:

    public class GroupInfo
    {        public Group group { get; set; }        public class Group
        {            public int id { get; set; }            public string name { get; set; }
        }
    }
登入後複製

访问的时候也会是gp.group.name,所以我说不太直接,我们想要的类的定义肯定是只有上面那个子类的样子:

    public class GroupInfo
    {            public int id { get; set; }            public string name { get; set; }
    }
登入後複製

如果微信接口返回的是这样:

    {        "id": 107, 
        "name": "test"
    }
登入後複製

就再好不过了,但人家的代码,我们修改不了,我们只有自己想办法.

1,要简单类,2不手动分析json(如正则),3,不想多定义一个类,你有想到很好的方法吗?如果有可以回复给我,而我选择用字典来做中间转换。

因为基本所有的json格式都可以反序列化为字典(嵌套字典,嵌套字典集合等),比如上面微信返回的json就可以用以下的类型来表示:

Dictionary<string, Dictionary<string, object>>
登入後複製

json--->dict--->GroupInfo

var dict = Util.JsonTo(json);var gi = new GroupInfo();var gpdict = dict["group"];
gi.id = Convert.ToInt32(gpdict["id"]);
gi.name = gpdict["name"].ToString();
登入後複製

四、消息处理的优化

"万物简单为美",我就是一个非常非常喜欢简单的程序员。还记得最开始的那个消息(事件属于消息,这里统称为消息)处理吧,我感觉是很简单的,需要处理哪个消息就注册哪个消息的处理程序。但一开始的时候不是这样的,开始的时候要手动判断消息类型,就像:

using System.Web;using Loogn.WeiXinSDK;using Loogn.WeiXinSDK.Message;namespace WebTest
{    /// <summary>
    /// 微信->服务器配置URL    /// </summary>
    public class WeiXinAPI : IHttpHandler
    {        static string Token = "Token";//这里是Token不是Access_Token
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";            var signature = context.Request["signature"];            var timestamp = context.Request["timestamp"];            var nonce = context.Request["nonce"];            if (WeiXin.CheckSignature(signature, timestamp, nonce, Token))//验证是微信给你发的消息            {                var replyMsg = WeiXin.ReplyMsg((recEvtMsg) =>
                {                    switch (recEvtMsg.MsgType)
                    {                        case MsgType.text:
                            {                                var msg = recEvtMsg as RecTextMsg; //这里要转型,麻烦
                                return new ReplyTextMsg
                                {
                                    Content = "你说:" + msg.Content
                                };
                            }                        case MsgType.Event:
                            {                                var evtMsg = recEvtMsg as EventBaseMsg;//这里要转型到事件消息的基本,麻烦
                                switch (evtMsg.MyEventType)
                                {                                    case MyEventType.Attend:                                        var msg = evtMsg as EventAttendMsg;//这个例子不需要这行代码,但其他要用消息内容还是要转型,麻烦
                                        return new ReplyTextMsg
                                        {
                                            Content = "Hello !"
                                        };                                        
                                    default:                                        break;
                                }                                break;
                            }                        default:                            break;
                    }                    return ReplyEmptyMsg.Instance;                    //嵌套switch,而且每个case都有好几个,这也不优雅                });                var xml = replyMsg.GetXML();                //WriteLog(xml); //这里可以查看回复的XML消息                context.Response.Write(xml);
            }            else
            {
                context.Response.Write("fuck you!");
            }
        }        public bool IsReusable
        {            get
            {                return false;
            }
        }
    }
}
登入後複製

做优化的时候,先是试着看能不能在MsgType和MyEventType上做文章,比如注册时传入MsgType和处理程序(lamba)两个参数:

public static void RegisterMsgHandler(MsgType type, Func<RecEventBaseMsg, ReplyBaseMsg> handler)
{    //add handler}
登入後複製

 这样的确是可以行的通的,但是在调用SDK注册的时候还是要手动转换类型:

 WeiXin.RegisterMsgHandler(MsgType.text, (recEvtMsg) => msg = recEvtMsg   ReplyTextMsg { Content =  +
登入後複製

 那么能不能每个子类型写一个呢?

    public static void RegisterMsgHandler(MsgType type, Func<RecTextMsg, ReplyBaseMsg> handler)
    {        //add handler    }    public static void RegisterMsgHandler(MsgType type, Func<RecImageMsg, ReplyBaseMsg> handler)
    {        //add handler    }    //.............
登入後複製

 定义是可以的,来看看调用:

//可以RegisterMsgHandler(MsgType.text, new Func<RecTextMsg, ReplyBaseMsg>((msg) =>{    return new ReplyTextMsg { Content = "你说:" + msg.Content };
}));//可以RegisterMsgHandler(MsgType.text, new Func<RecImageMsg, ReplyBaseMsg>((msg) =>{    return new ReplyTextMsg { Content = "你发的图片:" + msg.PicUrl };
}));//可以,注意这里msg的智能提示是RecTextMsg类型RegisterMsgHandler(MsgType.text, (msg) =>{    return new ReplyTextMsg { Content = "你说:" +msg.Content};
});//可以,注意这里msg的智能提示还是RecTextMsg类型,但用了类型推断,运行时可以确定是RecImageMsg,所以可以RegisterMsgHandler(MsgType.text, (msg) =>{    return new ReplyTextMsg { Content = "你发的图片:" + msg.PicUrl };
});//不可以,注意这里msg的智能提示还是RecTextMsg类型,但lamba body里没有用msg的特定子类的属性,类型推断不了,所以调用不明RegisterMsgHandler(MsgType.text, (msg) =>{    return new ReplyTextMsg { Content = "你发了个消息" };
});
登入後複製

 从上面调用可知,想用这种方法调用,就不能随意的用lamba表达式,我所不欲也!最后,终于用泛型搞定了

public static void RegisterMsgHandler<TMsg>(Func<TMsg, ReplyBaseMsg> handler) where TMsg : RecBaseMsg
        {            var type = typeof(TMsg);            var key = string.Empty;            if (type == typeof(RecTextMsg))
            {
                key = MsgType.text.ToString();
            }            else if (type == typeof(RecImageMsg))
            {
                key = MsgType.image.ToString();
            }            else if (type == typeof(RecLinkMsg))
            {
                key = MsgType.link.ToString();
            }            else if (type == typeof(RecLocationMsg))
            {
                key = MsgType.location.ToString();
            }            else if (type == typeof(RecVideoMsg))
            {
                key = MsgType.video.ToString();
            }            else if (type == typeof(RecVoiceMsg))
            {
                key = MsgType.voice.ToString();
            }            else
            {                return;
            }
            m_msgHandlers[key] = (Func<RecEventBaseMsg, ReplyBaseMsg>)handler;
        }
登入後複製

经过这样的变换,我们才可以像开始那样用简洁的lamba表达式注册。

以上是微信公眾平台SDK過程詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

微軟正在為 Windows 11 開發新的模糊效果 微軟正在為 Windows 11 開發新的模糊效果 May 13, 2023 am 09:04 AM

用於build22523的新Windows11SDK透露,微軟正在為Windows11開發新的模糊效果。此效果稱為Tabbed,並且是對Acrylic和Mica的補充。 22523SDK中的新DWMWA_SYSTEMBACKDROP_TYPE、雲母、亞克力的公共Win32API及其奇怪的新「選項卡」混合:pic.twitter.com/dbsu7ZFiIi-一切都回來了(@StartIsBack)2021年12月15日可以在以下SDK的範例應用程式

掌握Java海康SDK二次開發的必備技巧 掌握Java海康SDK二次開發的必備技巧 Sep 06, 2023 am 08:10 AM

掌握Java海康SDK二次開發的必備技巧引言:隨著資訊科技的快速發展,視訊監控系統在各領域得到了廣泛的應用。而作為國內領先的視訊監控解決方案提供商,海康威視的產品和技術一直在市場中佔有重要的地位。為了滿足不同專案的需求,海康威視提供了SDK供開發者進行二次開發。本文將介紹一些掌握Java海康SDK二次開發的必備技巧,並附上對應的程式碼範例。一、了解海康威視

sdk是什麼 sdk是什麼 Jan 06, 2023 pm 03:26 PM

sdk全名為“Software Development Kit”,中文意思是“軟體開發工具包”,是由硬體平台、作業系統(OS)或程式語言的製造商提供的一套工具。 SDK可協助軟體開發人員為特定的平台、系統或程式語言建立應用程式。一個基本的SDK通常由編譯器、偵錯器和應用程式介面(API)組成,但也可能包含其他內容,例如:文件、函式庫、執行時間/開發環境、測試/分析工具、網路協定等。

Windows App SDK 1.2 現已上線,這是新功能 Windows App SDK 1.2 現已上線,這是新功能 May 12, 2023 pm 06:07 PM

WindowsAppSDK是一組工具和API,開發人員可以在其Windows應用程式中使用這些工具和API,以便在使用Windows10(版本1809及更高版本)和Windows11的各種裝置上提供「一致」的功能。了解它確實很重要它不會取代現有的應用程式類型,例如.NET或WindowsSDK,它只是提供一個統一的API工具集,可以用來補充您現有的應用程式。今天,微軟發布了具有許多新功能的WindowsAppSDK1.2版本。此版本的亮點可能是第三方開發人

PHP微信開發:如何實作訊息加密解密 PHP微信開發:如何實作訊息加密解密 May 13, 2023 am 11:40 AM

PHP是一種開源的腳本語言,廣泛應用於網頁開發和伺服器端編程,尤其在微信開發中得到了廣泛的應用。如今,越來越多的企業和開發者開始使用PHP進行微信開發,因為它成為了真正的易學易用的開發語言。在微信開發中,訊息的加密和解密是一個非常重要的問題,因為它們涉及資料的安全性。對於沒有加密和解密方式的消息,駭客可以輕鬆取得其中的數據,對用戶造成威脅

微信小程式PHP SDK的安裝及使用 微信小程式PHP SDK的安裝及使用 Mar 27, 2024 am 09:33 AM

微信小程式PHPSDK的安裝及使用隨著行動互聯網的快速發展,微信小程式成為了越來越多企業開展業務、推廣產品的新方式。微信小程式PHPSDK則為開發者提供了方便快速的開發工具,可以大幅提高開發效率。本文將介紹微信小程式PHPSDK的安裝及使用。一、安裝SDK1.在GitHub上下載專案文件微信小程式PHPSDK是一個開源項目,開發者可以在GitHub上

linux中的sdk是什麼資料夾 linux中的sdk是什麼資料夾 Jul 11, 2023 pm 01:38 PM

linux中的sdk是一個包含了編譯器、偵錯器、函式庫檔案、頭檔等工具和資源的資料夾。 sdk是「software development kit」的縮寫,是軟體開發工具包的意思,是為開發人員提供的一個整合環境,用於開發和構建應用程序,特別是那些運行在Linux作業系統上的應用程式。

詳解PHP怎麼安裝支付寶SDK? (指南分享) 詳解PHP怎麼安裝支付寶SDK? (指南分享) Mar 22, 2023 am 11:24 AM

本文將提供關於 PHP 支付寶 SDK 的詳細安裝指南,幫助開發人員在幾個簡單的步驟中完成 SDK 的安裝。

See all articles