Beschreibung des Dienstkontos: Bieten Sie Unternehmen und Organisationen leistungsfähigere Geschäftsdienste und Benutzerverwaltungsfunktionen und helfen Sie Unternehmen, schnell eine neue Plattform für öffentliche Kontodienste zu implementieren.
.NETSDK: Loogn.WeiXinSDK (net2.0-Quellcode, der folgende Code ist nur ungefähr und nicht sehr korrekt, bitte laden Sie den Quellcode selbst herunter)
Da ich immer noch NOKIA-C5 verwende Ich habe WeChat noch nie benutzt, ich weiß definitiv nicht so viel über WeChat wie Sie, aber das Unternehmen hat Bedürfnisse, also muss ich in den sauren Apfel beißen und die Schnittstellendokumentation direkt lesen.
Nachdem ich es gelesen hatte, fand ich es sehr interessant. Wenn der Benutzer eine Nachricht an ein öffentliches Konto sendet, kann das Programm dem Benutzer automatisch auf der Grundlage des vom Benutzer gesendeten Inhalts antworten Benutzer, beispielsweise das Senden einer Nachricht an das öffentliche Konto eines Logistikunternehmens,
Die andere Partei antwortet Ihnen automatisch mit den Logistikdetails dieser Frachtbriefnummer, was sich ziemlich cool anfühlt! Zur Vereinfachung der Erklärung werden zunächst die angewendeten öffentlichen Kontoinformationen angegeben:
Die folgende Abbildung zeigt den detaillierten Nachrichtenprozess zum Anzeigen der Logistik oben (die Zahlen in den gepunkteten Linien). Geben Sie die Reihenfolge des Vorgangs an):
WeChat sendet zwei Haupttypen von Nachrichten an Ihre URL:
Eine davon ist die allgemeine Nachricht des Benutzers, z die vom Benutzer oben gesendete Frachtbriefnummer; das zweite ist das Verhalten des Benutzers (d. h. die im Dokument erwähnten Ereignisse), z. B. wenn der Benutzer Ihrem öffentlichen Konto folgt, den QR-Code des öffentlichen Kontos scannt und klickt auf Ihrem individuellen Menü usw.
Ihre URL kann basierend auf dem empfangenen
Nachrichtentyp und -inhaltreagieren, um leistungsstarke Geschäftsdienste zu erzielen, wie z. B. die oben zurückgegebenen Logistikdetails. Alle Nachrichten werden im XML-Format übermittelt und das SDK konvertiert XML in .NET-Objekte, um Ihnen das Schreiben von Geschäftslogik zu erleichtern. Das Framework-Klassendiagramm der Nachricht wird wie folgt dargestellt (klicken Sie, um das vollständige Diagramm einschließlich der Unterklassen anzuzeigen):
Zuerst gibt es eine Nachrichtenbasisklasse, dann die empfangene Nachricht (RecEventBaseMsg ) und Antwortnachricht (ReplyBaseMsg), wie oben erwähnt, ist die empfangene Nachricht in zwei Kategorien unterteilt, nämlich allgemeine Nachricht (RecBaseMsg) und Ereignisnachricht (EventBaseMsg). Der Typ der empfangenen Nachricht kann durch eine Aufzählung dargestellt werden:
Ganz zu schweigen von anderen Typen: Wenn MsgType Event ist, ist die Nachricht eine Unterklasse von EventBaseMsg. Der MsgType aller Unterklassen von EventBaseMsg ist Event, sodass der EventBaseMsg-Typ auch einen EventType hat Ereignisse: Wenn Sie das Schnittstellendokument gelesen haben, sollten Sie wissen, dass der Ereignistyp für uns nicht sehr einfach ist, um zu bestimmen, um welches Ereignis es sich handelt. Das Scannen von QR-Code-Ereignissen ist in zwei Situationen unterteilt: Der Benutzer hat aufgepasst und der Benutzer hat darauf geachtet Beim Verfolgen ist der EventType „scan“, beim Nichtverfolgen ist der EventType „subscribe“ und der EventType des Ereignisses, dem der Benutzer folgt, ist ebenfalls „subscribe“, sodass ein weiterer MyEventType zum SDK hinzugefügt wird:
Jetzt ist der Nachrichtenfluss grundsätzlich klar. Die Antwortnachricht beim Aufruf des SDK lautet wie folgt:
Das SDK enthält die Kapselung aller Schnittstellen außer (OAuth2.0 Die Klassennamen und Methodennamen sind sehr offensichtlich, daher werde ich sie hier nicht einzeln auflisten. Interessierte Freunde können die DLL herunterladen und selbst testen. Dies ist ein kostenpflichtiges und zertifiziertes Schnittstellendiagramm 🎜>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; } } } }
Lassen Sie uns über ein paar Details der Implementierung sprechen:
1. Ablauf der Anmeldeinformationen (access_token)„access_token ist das weltweit eindeutige Ticket des offiziellen Kontos muss beim Aufrufen jeder Schnittstelle das Access_token verwendenAccess_token ist 7200 Sekunden lang gültig
, eine wiederholte Erfassung führt dazu, dass das letzte Access_token ungültig wird. Das öffentliche Konto kann AppID verwenden und AppSecret, um diese Schnittstelle aufzurufen, um access_token zu erhalten (Sie müssen ein Entwickler sein und das Konto hat keinen abnormalen Status). Denken Sie an die Verwendung von Caching (es ist unmöglich, es jedes Mal zu verwenden!). Indiesem Fall kann ich mir die Verwendung von Caching vorstellen > Code:
2. FehlercodeinformationenDer oben genannte Code zum Abrufen von Anmeldeinformationen ist unvollständig, da die möglicherweise zurückgegebenen Fehlercodes nicht verarbeitet werden, werden WeChat-Fehlercodes zurückgegeben im JSON-Format, wie zum Beispiel: Die meisten von uns aktiv aufgerufenen Schnittstellen geben möglicherweise Fehlercodes zurück, und das Fehlercodeformat ist das gleiche wie das normalerweise zurückgegebene Datenformat SDK, ich handhabe es so. Definiere zuerst die Modellklasse des Fehlercodes, da der Fehlercode auch {"errcode":0,"errmsg": "ok"} enthält. Anfrage ist erfolgreich:
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>
Beim Definieren einer Rückgabenachrichtenklasse mit einem Fehlercode können wir ein Attribut vom Typ ReturnCode einschließen, z. B. beim Erstellen einer QR-Code-Schnittstelle:
Der Code aus dem zurückgegebenen JSON zum QRCodeTicket-Objekt ist wahrscheinlich so (andere sind ähnlich):{"errcode":40013,"errmsg":"invalid appid"}
errcode { ; errmsg { ; + errcode + + errmsg +
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表达式注册。
Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des SDK-Prozesses der öffentlichen WeChat-Plattform. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!