搜尋
首頁微信小程式微信開發微信公眾平台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;
            }
        }
    }
}</eventattendmsg></rectextmsg>

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

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

一、憑證(access_token)過期

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

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

 
       access_token { ;  
         
          expires_in { ;  Dictionary creds =  Dictionary  TokenUrl =   Credential GetCredential( appId, =  (creds.TryGetValue(appId,  (cred.add_time.AddSeconds(cred.expires_in - ) 

 二、錯誤碼訊息

上面說到得到憑證的程式碼不完整就是因為沒有處理可能傳回的錯誤碼,微信錯誤碼以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;
            }</returncode></qrcodeticket>

所以用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>></string>

json--->dict--->GroupInfo

var dict = Util.JsonTo<dictionary>>>(json);var gi = new GroupInfo();var gpdict = dict["group"];
gi.id = Convert.ToInt32(gpdict["id"]);
gi.name = gpdict["name"].ToString();</dictionary>

四、消息处理的优化

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

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> handler)
{    //add handler}</receventbasemsg>

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

 WeiXin.RegisterMsgHandler(MsgType.text, (recEvtMsg) => msg = recEvtMsg   ReplyTextMsg { Content =  +

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

    public static void RegisterMsgHandler(MsgType type, Func<rectextmsg> handler)
    {        //add handler    }    public static void RegisterMsgHandler(MsgType type, Func<recimagemsg> handler)
    {        //add handler    }    //.............</recimagemsg></rectextmsg>

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

//可以RegisterMsgHandler(MsgType.text, new Func<rectextmsg>((msg) =>{    return new ReplyTextMsg { Content = "你说:" + msg.Content };
}));//可以RegisterMsgHandler(MsgType.text, new Func<recimagemsg>((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 = "你发了个消息" };
});</recimagemsg></rectextmsg>

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

public static void RegisterMsgHandler<tmsg>(Func<tmsg> 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>)handler;
        }</receventbasemsg></tmsg></tmsg>

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

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

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
微软正在为 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的示例应用程序

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版本。此版本的亮点可能是第三方开发人

掌握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)组成,但也可能包含其他内容,比如:文档、库、运行时/开发环境、测试/分析工具、网络协议等。

PHP微信开发:如何实现消息加密解密PHP微信开发:如何实现消息加密解密May 13, 2023 am 11:40 AM

PHP是一种开源的脚本语言,广泛应用于Web开发和服务器端编程,尤其在微信开发中得到了广泛的应用。如今,越来越多的企业和开发者开始使用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实现开源Kafka SDKPHP实现开源Kafka SDKJun 18, 2023 am 09:18 AM

随着互联网的快速发展,大量的数据需要被传输和处理,因此消息系统作为数据传输和处理的经典应用之一成为了互联网架构中不可或缺的一部分。Kafka作为高性能、分布式、可伸缩、支持实时数据处理的消息系统被广泛地应用于企业数据架构中。在使用Kafka时,一个重要的问题是如何调用Kafka的API。开发团队为此提供了多种语言的开源客户端,而PHP实现的开源KafkaS

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

記事本++7.3.1

記事本++7.3.1

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

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中