Maison Applet WeChat Développement WeChat Partager un article basé sur le SDK .NET WeChat

Partager un article basé sur le SDK .NET WeChat

Apr 27, 2017 pm 02:12 PM

1. Préface

Je suis une personne qui n'aime pas particulièrement les problèmes. J'ai récemment rencontré le développement de WeChat. J'ai téléchargé des « frameworks » de développement WeChat écrits par d'autres, mais j'étais dégoûté que la mise en œuvre soit trop lourde.

Ce que je n'aime pas le plus, c'est assembler les messages XML renvoyés par WeChat en classes d'entités Donc, de nos jours, la légèreté est préconisée, il y a donc un moyen d'éviter une grande taille. nombre de classes d’entités ?

Bien sûr, le packaging est relativement compliqué. Après avoir lu l'API officielle, regarder le "framework" rend les gens confus et pas assez clairs .

2. Mes idées d'implémentation

Mon SDK WeChat (je n'ose pas m'appeler un framework), le plus important est d'atteindre deux objectifs :

1 .Lightweight signifie abandonner les classes d'entité, déclarer Entity le moins possible et réduire la taille du SDK

2. Simple et clair, c'est-à-dire que la division des classes du SDK est cohérente avec la version officielle ; API, ce qui facilite la visualisation en un coup d'œil. Je comprends votre intention.

L'utilisateur envoie d'abord une requête en POST au serveur WeChat, puis en POST par le serveur WeChat sur mon serveur. Le message reçu est en XML. Je suppose pourquoi il s'agit de XML au lieu du JSON plus léger. compatibilité, XML est plus universel après tout (si je me trompe, veuillez le signaler). Lorsque nous appelons activement certaines API de WeChat, cela renvoie le format json. Bon sang, c'est tellement impressionnant. Votre vice-président Zhang Xiaolong n’est-il pas au courant ? Eh bien, c'est effectivement possible.

En fait, le principe de fonctionnement pour appeler WeChat est très simple. Il n'est pas nécessaire de proposer un framework ou quelque chose du genre. Je pense que n'importe quel programmeur qualifié peut le faire.

Notre serveur n'a besoin que d'un GET et d'un POST pour communiquer avec WeChat. De ce point de vue, le design est assez convivial. GET est utilisé pour se connecter à la vérification et à la vérification du service WeChat ; POST est utilisé pour recevoir des messages du serveur WeChat, puis assembler la réponse et la renvoyer.

3. Téléchargez le code

Bon, plus de bêtises.

Puisque le serveur WeChat Post nous donne un message XML et renvoie JSON, il doit être transféré l'un à l'autre. De cette manière, il existe trois types de formats. C'est également la raison pour laquelle le framework n'est pas assez léger en raison du grand nombre de classes d'entités définies par le framework.

Pour atteindre le premier objectif, j'ai principalement utilisé la fonctionnalité Dynamic de .net Framework 4.0, et une classe DynamicXml.cs qui convertit automatiquement les chaînes XML en objet dynamique, et un DynamicJson.cs classe qui convertit automatiquement les chaînes json en objets dynamiques.

Après de longues recherches, j'ai enfin trouvé ce que je voulais.

1. Ce qui suit est la classe DynamicXml.cs et l'en-tête du fichier contient les informations de droit d'auteur de l'auteur original.

/*--------------------------------------------------------------------------
 * https://www.captechconsulting.com/blog/kevin-hazzard/fluent-xml-parsing-using-cs-dynamic-type-part-1
 * 博客园网友 夜の魔王 友情借用此代码,用于微信开发。
 * http://www.cnblogs.com/deepleo/*--------------------------------------------------------------------------*/using System;using System.Collections.Generic;using System.Linq;using System.Dynamic;using System.Xml.Linq;using System.Collections;public class DynamicXml : DynamicObject, IEnumerable
{    private readonly List<XElement> _elements;    public DynamicXml(string text)
    {        var doc = XDocument.Parse(text);
        _elements = new List<XElement> { doc.Root };
    }    protected DynamicXml(XElement element)
    {
        _elements = new List<XElement> { element };
    }    protected DynamicXml(IEnumerable<XElement> elements)
    {
        _elements = new List<XElement>(elements);
    }    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = null;        if (binder.Name == "Value")
            result = _elements[0].Value;        else if (binder.Name == "Count")
            result = _elements.Count;        else
        {            var attr = _elements[0].Attribute(XName.Get(binder.Name));            if (attr != null)
                result = attr;            else
            {                var items = _elements.Descendants(XName.Get(binder.Name));                if (items == null || items.Count() == 0) return false;
                result = new DynamicXml(items);
            }
        }        return true;
    }    public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
    {        int ndx = (int)indexes[0];
        result = new DynamicXml(_elements[ndx]);        return true;
    }    public IEnumerator GetEnumerator()
    {        foreach (var element in _elements)            yield return new DynamicXml(element);
    }
}
Copier après la connexion

Afficher le code

Je n'ai pas regardé attentivement ce code , de toute façon. Cela fonctionne, pas d'erreurs.

2.

Ce qui suit est la classe DynamicJson.cs. L'en-tête du fichier contient les informations de copyright de l'auteur original

<. 🎜>

/*--------------------------------------------------------------------------
* DynamicJson
* ver 1.2.0.0 (May. 21th, 2010)
*
* created and maintained by neuecc <ils@neue.cc>
* licensed under Microsoft Public License(Ms-PL)
* http://neue.cc/* http://dynamicjson.codeplex.com/
 * 博客园网友 夜の魔王 友情借用此代码,用于微信开发。
 * http://www.cnblogs.com/deepleo/*--------------------------------------------------------------------------*/using System;using System.Collections;using System.Collections.Generic;using System.Diagnostics;using System.Dynamic;using System.IO;using System.Linq;using System.Reflection;using System.Runtime.Serialization.Json;using System.Text;using System.Xml;using System.Xml.Linq;namespace Codeplex.Data
{    public class DynamicJson : DynamicObject
    {        private enum JsonType
        {
            @string, number, boolean, @object, array, @null
        }        // public static methods

        /// <summary>from JsonSring to DynamicJson</summary>
        public static dynamic Parse(string json)
        {            return Parse(json, Encoding.Unicode);
        }        /// <summary>from JsonSring to DynamicJson</summary>
        public static dynamic Parse(string json, Encoding encoding)
        {            using (var reader = JsonReaderWriterFactory.CreateJsonReader(encoding.GetBytes(json), XmlDictionaryReaderQuotas.Max))
            {                return ToValue(XElement.Load(reader));
            }
        }        /// <summary>from JsonSringStream to DynamicJson</summary>
        public static dynamic Parse(Stream stream)
        {            using (var reader = JsonReaderWriterFactory.CreateJsonReader(stream, XmlDictionaryReaderQuotas.Max))
            {                return ToValue(XElement.Load(reader));
            }
        }        /// <summary>from JsonSringStream to DynamicJson</summary>
        public static dynamic Parse(Stream stream, Encoding encoding)
        {            using (var reader = JsonReaderWriterFactory.CreateJsonReader(stream, encoding, XmlDictionaryReaderQuotas.Max, _ => { }))
            {                return ToValue(XElement.Load(reader));
            }
        }        /// <summary>create JsonSring from primitive or IEnumerable or Object({public property name:property value})</summary>
        public static string Serialize(object obj)
        {            return CreateJsonString(new XStreamingElement("root", CreateTypeAttr(GetJsonType(obj)), CreateJsonNode(obj)));
        }        // private static methods

        private static dynamic ToValue(XElement element)
        {            var type = (JsonType)Enum.Parse(typeof(JsonType), element.Attribute("type").Value);            switch (type)
            {                case JsonType.boolean:                    return (bool)element;                case JsonType.number:                    return (double)element;                case JsonType.@string:                    return (string)element;                case JsonType.@object:                case JsonType.array:                    return new DynamicJson(element, type);                case JsonType.@null:                default:                    return null;
            }
        }        private static JsonType GetJsonType(object obj)
        {            if (obj == null) return JsonType.@null;            switch (Type.GetTypeCode(obj.GetType()))
            {                case TypeCode.Boolean:                    return JsonType.boolean;                case TypeCode.String:                case TypeCode.Char:                case TypeCode.DateTime:                    return JsonType.@string;                case TypeCode.Int16:                case TypeCode.Int32:                case TypeCode.Int64:                case TypeCode.UInt16:                case TypeCode.UInt32:                case TypeCode.UInt64:                case TypeCode.Single:                case TypeCode.Double:                case TypeCode.Decimal:                case TypeCode.SByte:                case TypeCode.Byte:                    return JsonType.number;                case TypeCode.Object:                    return (obj is IEnumerable) ? JsonType.array : JsonType.@object;                case TypeCode.DBNull:                case TypeCode.Empty:                default:                    return JsonType.@null;
            }
        }        private static XAttribute CreateTypeAttr(JsonType type)
        {            return new XAttribute("type", type.ToString());
        }        private static object CreateJsonNode(object obj)
        {            var type = GetJsonType(obj);            switch (type)
            {                case JsonType.@string:                case JsonType.number:                    return obj;                case JsonType.boolean:                    return obj.ToString().ToLower();                case JsonType.@object:                    return CreateXObject(obj);                case JsonType.array:                    return CreateXArray(obj as IEnumerable);                case JsonType.@null:                default:                    return null;
            }
        }        private static IEnumerable<XStreamingElement> CreateXArray<T>(T obj) where T : IEnumerable
        {            return obj.Cast<object>()
                .Select(o => new XStreamingElement("item", CreateTypeAttr(GetJsonType(o)), CreateJsonNode(o)));
        }        private static IEnumerable<XStreamingElement> CreateXObject(object obj)
        {            return obj.GetType()
                .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .Select(pi => new { Name = pi.Name, Value = pi.GetValue(obj, null) })
                .Select(a => new XStreamingElement(a.Name, CreateTypeAttr(GetJsonType(a.Value)), CreateJsonNode(a.Value)));
        }        private static string CreateJsonString(XStreamingElement element)
        {            using (var ms = new MemoryStream())            using (var writer = JsonReaderWriterFactory.CreateJsonWriter(ms, Encoding.Unicode))
            {
                element.WriteTo(writer);
                writer.Flush();                return Encoding.Unicode.GetString(ms.ToArray());
            }
        }        // dynamic structure represents JavaScript Object/Array

        readonly XElement xml;        readonly JsonType jsonType;        /// <summary>create blank JSObject</summary>
        public DynamicJson()
        {
            xml = new XElement("root", CreateTypeAttr(JsonType.@object));
            jsonType = JsonType.@object;
        }        private DynamicJson(XElement element, JsonType type)
        {
            Debug.Assert(type == JsonType.array || type == JsonType.@object);

            xml = element;
            jsonType = type;
        }        public bool IsObject { get { return jsonType == JsonType.@object; } }        public bool IsArray { get { return jsonType == JsonType.array; } }        /// <summary>has property or not</summary>
        public bool IsDefined(string name)
        {            return IsObject && (xml.Element(name) != null);
        }        /// <summary>has property or not</summary>
        public bool IsDefined(int index)
        {            return IsArray && (xml.Elements().ElementAtOrDefault(index) != null);
        }        /// <summary>delete property</summary>
        public bool Delete(string name)
        {            var elem = xml.Element(name);            if (elem != null)
            {
                elem.Remove();                return true;
            }            else return false;
        }        /// <summary>delete property</summary>
        public bool Delete(int index)
        {            var elem = xml.Elements().ElementAtOrDefault(index);            if (elem != null)
            {
                elem.Remove();                return true;
            }            else return false;
        }        /// <summary>mapping to Array or Class by Public PropertyName</summary>
        public T Deserialize<T>()
        {            return (T)Deserialize(typeof(T));
        }        private object Deserialize(Type type)
        {            return (IsArray) ? DeserializeArray(type) : DeserializeObject(type);
        }        private dynamic DeserializeValue(XElement element, Type elementType)
        {            var value = ToValue(element);            if (value is DynamicJson)
            {
                value = ((DynamicJson)value).Deserialize(elementType);
            }            return Convert.ChangeType(value, elementType);
        }        private object DeserializeObject(Type targetType)
        {            var result = Activator.CreateInstance(targetType);            var dict = targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .Where(p => p.CanWrite)
                .ToDictionary(pi => pi.Name, pi => pi);            foreach (var item in xml.Elements())
            {
                PropertyInfo propertyInfo;                if (!dict.TryGetValue(item.Name.LocalName, out propertyInfo)) continue;                var value = DeserializeValue(item, propertyInfo.PropertyType);
                propertyInfo.SetValue(result, value, null);
            }            return result;
        }        private object DeserializeArray(Type targetType)
        {            if (targetType.IsArray) // Foo[]            {                var elemType = targetType.GetElementType();
                dynamic array = Array.CreateInstance(elemType, xml.Elements().Count());                var index = 0;                foreach (var item in xml.Elements())
                {
                    array[index++] = DeserializeValue(item, elemType);
                }                return array;
            }            else // List<Foo>            {                var elemType = targetType.GetGenericArguments()[0];
                dynamic list = Activator.CreateInstance(targetType);                foreach (var item in xml.Elements())
                {
                    list.Add(DeserializeValue(item, elemType));
                }                return list;
            }
        }        // Delete
        public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
        {
            result = (IsArray)                ? Delete((int)args[0])
                : Delete((string)args[0]);            return true;
        }        // IsDefined, if has args then TryGetMember
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {            if (args.Length > 0)
            {
                result = null;                return false;
            }

            result = IsDefined(binder.Name);            return true;
        }        // Deserialize or foreach(IEnumerable)
        public override bool TryConvert(ConvertBinder binder, out object result)
        {            if (binder.Type == typeof(IEnumerable) || binder.Type == typeof(object[]))
            {                var ie = (IsArray)                    ? xml.Elements().Select(x => ToValue(x))
                    : xml.Elements().Select(x => (dynamic)new KeyValuePair<string, object>(x.Name.LocalName, ToValue(x)));
                result = (binder.Type == typeof(object[])) ? ie.ToArray() : ie;
            }            else
            {
                result = Deserialize(binder.Type);
            }            return true;
        }        private bool TryGet(XElement element, out object result)
        {            if (element == null)
            {
                result = null;                return false;
            }

            result = ToValue(element);            return true;
        }        public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
        {            return (IsArray)                ? TryGet(xml.Elements().ElementAtOrDefault((int)indexes[0]), out result)
                : TryGet(xml.Element((string)indexes[0]), out result);
        }        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {            return (IsArray)                ? TryGet(xml.Elements().ElementAtOrDefault(int.Parse(binder.Name)), out result)
                : TryGet(xml.Element(binder.Name), out result);
        }        private bool TrySet(string name, object value)
        {            var type = GetJsonType(value);            var element = xml.Element(name);            if (element == null)
            {
                xml.Add(new XElement(name, CreateTypeAttr(type), CreateJsonNode(value)));
            }            else
            {
                element.Attribute("type").Value = type.ToString();
                element.ReplaceNodes(CreateJsonNode(value));
            }            return true;
        }        private bool TrySet(int index, object value)
        {            var type = GetJsonType(value);            var e = xml.Elements().ElementAtOrDefault(index);            if (e == null)
            {
                xml.Add(new XElement("item", CreateTypeAttr(type), CreateJsonNode(value)));
            }            else
            {
                e.Attribute("type").Value = type.ToString();
                e.ReplaceNodes(CreateJsonNode(value));
            }            return true;
        }        public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
        {            return (IsArray)                ? TrySet((int)indexes[0], value)
                : TrySet((string)indexes[0], value);
        }        public override bool TrySetMember(SetMemberBinder binder, object value)
        {            return (IsArray)                ? TrySet(int.Parse(binder.Name), value)
                : TrySet(binder.Name, value);
        }        public override IEnumerable<string> GetDynamicMemberNames()
        {            return (IsArray)                ? xml.Elements().Select((x, i) => i.ToString())
                : xml.Elements().Select(x => x.Name.LocalName);
        }        /// <summary>Serialize to JsonString</summary>
        public override string ToString()
        {            // <foo type="null"></foo> is can&#39;t serialize. replace to <foo type="null" />
            foreach (var elem in xml.Descendants().Where(x => x.Attribute("type").Value == "null"))
            {
                elem.RemoveNodes();
            }            return CreateJsonString(new XStreamingElement("root", CreateTypeAttr(jsonType), xml.Elements()));
        }
    }
}
Copier après la connexion
Afficher le code

Je n'ai toujours pas regardé attentivement ce code, mais il fonctionne quand même sans aucune erreur.

Une fois cet obstacle majeur résolu, le reste se déroulera naturellement.

3. Prise en charge de base du packaging API

/*--------------------------------------------------------------------------
* BasicAPI.cs
 *Auth:deepleo
* Date:2013.12.31
* Email:2586662969@qq.com
*--------------------------------------------------------------------------*/using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net.Http;using Codeplex.Data;using System.IO;namespace Deepleo.Weixin.SDK
{    /// <summary>
    /// 对应微信API的 "基础支持"    /// </summary>
    public class BasicAPI
    {        /// <summary>
        /// 检查签名是否正确:        /// http://mp.weixin.qq.com/wiki/index.php?title=%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
        /// </summary>
        /// <param name="signature"></param>
        /// <param name="timestamp"></param>
        /// <param name="nonce"></param>
        /// <param name="token">AccessToken</param>
        /// <returns>
        /// true: check signature success        /// false: check failed, 非微信官方调用!        /// </returns>
        public static bool CheckSignature(string signature, string timestamp, string nonce, string token, out string ent)
        {            var arr = new[] { token, timestamp, nonce }.OrderBy(z => z).ToArray();            var arrString = string.Join("", arr);            var sha1 = System.Security.Cryptography.SHA1.Create();            var sha1Arr = sha1.ComputeHash(Encoding.UTF8.GetBytes(arrString));
            StringBuilder enText = new StringBuilder();            foreach (var b in sha1Arr)
            {
                enText.AppendFormat("{0:x2}", b);
            }
            ent = enText.ToString();            return signature == enText.ToString();
        }        /// <summary>
        /// 获取AccessToken        /// http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token
        /// </summary>
        /// <param name="grant_type"></param>
        /// <param name="appid"></param>
        /// <param name="secrect"></param>
        /// <returns>access_toke</returns>
        public static dynamic GetAccessToken( string appid, string secrect)
        {            var url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type={0}&appid={1}&secret={2}", "client_credential", appid, secrect);            var client = new HttpClient();            var result = client.GetAsync(url).Result;            if (!result.IsSuccessStatusCode) return string.Empty;            var token = DynamicJson.Parse(result.Content.ReadAsStringAsync().Result);            return token;
        }        /// <summary>
        /// 上传多媒体文件        /// http://mp.weixin.qq.com/wiki/index.php?title=%E4%B8%8A%E4%BC%A0%E4%B8%8B%E8%BD%BD%E5%A4%9A%E5%AA%92%E4%BD%93%E6%96%87%E4%BB%B6
        /// 1.上传的媒体文件限制:        ///图片(image) : 1MB,支持JPG格式        ///语音(voice):1MB,播放长度不超过60s,支持MP4格式        ///视频(video):10MB,支持MP4格式        ///缩略图(thumb):64KB,支持JPG格式        ///2.媒体文件在后台保存时间为3天,即3天后media_id失效        /// </summary>
        /// <param name="token"></param>
        /// <param name="type"></param>
        /// <param name="file"></param>
        /// <returns>media_id</returns>
        public static string UploadMedia(string token, string type, string file)
        {            var url = string.Format("http://api.weixin.qq.com/cgi-bin/media/upload?access_token={0}&type={1}&filename={2}", token, type, Path.GetFileName(file));            var client = new HttpClient();            var result = client.PostAsync(url, new StreamContent(new FileStream(file, FileMode.Open, FileAccess.Read)));            if (!result.Result.IsSuccessStatusCode) return string.Empty;            var media = DynamicJson.Parse(result.Result.Content.ReadAsStringAsync().Result);            return media.media_id;
        }
    }
}
Copier après la connexion
Afficher le code

4.发送消息包装

/*--------------------------------------------------------------------------
* SendMessageAPI.cs
 *Auth:deepleo
* Date:2013.12.31
* Email:2586662969@qq.com
*--------------------------------------------------------------------------*/using System;using System.Collections.Generic;using System.Linq;using System.Text;using Codeplex.Data;using System.Net;using System.Net.Http;namespace Deepleo.Weixin.SDK
{    /// <summary>
    /// 对应微信API的 "发送消息”    /// </summary>
    public class SendMessageAPI
    {        /// <summary>
        /// 被动回复消息        /// </summary>
        /// <param name="message">微信服务器推送的消息</param>
        /// <param name="executor">用户自定义的消息执行者</param>
        /// <returns></returns>
        public static string Relay(WeixinMessage message, IWeixinExecutor executor)
        {            return executor.Execute(message);
        }        /// <summary>
        /// 主动发送客服消息        /// http://mp.weixin.qq.com/wiki/index.php?title=%E5%8F%91%E9%80%81%E5%AE%A2%E6%9C%8D%E6%B6%88%E6%81%AF
        /// 当用户主动发消息给公众号的时候        /// 开发者在一段时间内(目前为24小时)可以调用客服消息接口,在24小时内不限制发送次数。        /// </summary>
        /// <param name="token"></param>
        /// <param name="msg">json格式的消息,具体格式请参考微信官方API</param>
        /// <returns></returns>
        public static bool Send(string token, string msg)
        {            var client = new HttpClient();            var task = client.PostAsync(string.Format("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={0}", token), new StringContent(msg)).Result;            return task.IsSuccessStatusCode;
        }
    }
}
Copier après la connexion

View Code

5.其他代码就不一一贴出来了。可以在文章最后自行下载完整代码查阅。

6.处理与微信服务器通信的WeixinController.cs,WeixinExecutor.cs

using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;using System.Web;using System.Web.Mvc;using System.Xml.Linq;using Deepleo.Weixin.SDK;using Deepleo.NewTon.Web.Services;using System.Xml;using Deepleo.NewTon.Framework.Services.Admin;using Deepleo.Log;namespace Deepleo.NewTon.Web.Controllers
{    public class WeixinController : Controller
    {        public WeixinController()
        {
        }        /// <summary>
        /// 微信后台验证地址(使用Get),微信后台的“接口配置信息”的Url        /// </summary>        [HttpGet]
        [ActionName("Index")]        public ActionResult Get(string signature, string timestamp, string nonce, string echostr)
        {            var token = new SettingsService().Get().Token;            if (string.IsNullOrEmpty(_token)) return Content("请先设置Token!");            var ent = "";            if (!BasicAPI.CheckSignature(signature, timestamp, nonce, _token, out ent))
            {                new WeixinLogService().Create(new Framework.Entities.WeixinLog("get(failed)", string.Format("(get weixin)signature:{0},timestamp:{1},nonce:{2},echostr:{3},ent:{4},token:{5}",
                    signature, timestamp, nonce, echostr, ent, _token)));                return Content("参数错误!");
            }        
            return Content(echostr); //返回随机字符串则表示验证通过        }        /// <summary>
        /// 用户发送消息后,微信平台自动Post一个请求到这里,并等待响应XML。        /// </summary>        [HttpPost]
        [ActionName("Index")]        public ActionResult Post(string signature, string timestamp, string nonce, string echostr)
        {
           
                WeixinMessage message = null;                using (var streamReader = new StreamReader(Request.InputStream))
                {
                    message = AcceptMessageAPI.Parse(streamReader.ReadToEnd());
                }              var  response = new WeixinExecutor().Execute(message);            return new ContentResult
            {
                Content = response,
                ContentType = "text/xml",
                ContentEncoding = System.Text.UTF8Encoding.UTF8
            };
        }

    }
}
Copier après la connexion

View Code

/*--------------------------------------------------------------------------
* WeixinExecutor.cs
 *Auth:deepleo
* Date:2013.12.31
* Email:2586662969@qq.com
*--------------------------------------------------------------------------*/using System;using System.Collections.Generic;using System.Linq;using System.Web;using Deepleo.Weixin.SDK;using System.Text;using System.Text.RegularExpressions;namespace Deepleo.Weixin
{    public class WeixinExecutor : IWeixinExecutor
    {        public WeixinExecutor()
        {
        }        public string Execute(WeixinMessage message)
        {            var result = "";            string openId = message.Body.FromUserName.Value;            var myUserName = message.Body.ToUserName.Value;            switch (message.Type)
            {                case WeixinMessageType.Text:                    string userMessage = message.Body.Content.Value;
                    result = RepayText(openId, myUserName, "欢迎使用");                    break;                case WeixinMessageType.Event:                    string eventType = message.Body.Event.Value.ToLower();                    string eventKey = message.Body.EventKey.Value;                    switch (eventType)
                    {                        case "subscribe":
                            result = RepayText(openId, myUserName, "欢迎订阅");                            break;                        case "unsubscribe":
                            result = RepayText(openId, myUserName, "欢迎再来");                            break;                        case "scan":
                            result = RepayText(openId, myUserName, "欢迎使用");                            break;                        case "location"://用户进入应用时记录用户地理位置
                            #region location                            var lat = message.Body.Latitude.Value.ToString();                            var lng = message.Body.Longitude.Value.ToString();                            var pcn = message.Body.Precision.Value.ToString();                            #endregion
                            break;                        case "click":                            switch (eventKey)//refer to: Recources/menu.json                            {                                case "myaccount":                                    #region 我的账户
                                    result = RepayText(openId, myUserName, "我的账户.");                                    #endregion
                                    break;                                default:
                                    result = string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName>" +                                         "<FromUserName><![CDATA[{1}]]></FromUserName>" +                                         "<CreateTime>{2}</CreateTime>" +                                         "<MsgType><![CDATA[text]]></MsgType>" +                                         "<Content><![CDATA[{3}]]></Content>" + "</xml>",
                                         openId, myUserName, DateTime.Now.ToBinary(), "没有响应菜单事件");                                    break;
                            }                            break;
                    }                    break;                default:
                    result = string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName>" +                                         "<FromUserName><![CDATA[{1}]]></FromUserName>" +                                         "<CreateTime>{2}</CreateTime>" +                                         "<MsgType><![CDATA[text]]></MsgType>" +                                         "<Content><![CDATA[{3}]]></Content>" + "</xml>",
                                         openId, myUserName, DateTime.Now.ToBinary(), string.Format("未处理消息类型:{0}", message.Type));                    break;
            }            return result;
        }        private string RepayText(string toUserName, string fromUserName, string content)
        {            return string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName>" +                                                   "<FromUserName><![CDATA[{1}]]></FromUserName>" +                                                   "<CreateTime>{2}</CreateTime>" +                                                   "<MsgType><![CDATA[text]]></MsgType>" +                                                   "<Content><![CDATA[{3}]]></Content>" + "</xml>",
                                                   toUserName, fromUserName, DateTime.Now.ToBinary(), content);
        }        private string RepayNews(string toUserName, string fromUserName, List<WeixinNews> news)
        {            var couponesBuilder = new StringBuilder();
            couponesBuilder.Append(string.Format("<xml><ToUserName><![CDATA[{0}]]></ToUserName>" +            "<FromUserName><![CDATA[{1}]]></FromUserName>" +            "<CreateTime>{2}</CreateTime>" +            "<MsgType><![CDATA[news]]></MsgType>" +            "<ArticleCount>{3}</ArticleCount><Articles>",
             toUserName, fromUserName,
             DateTime.Now.ToBinary(),
             news.Count
                ));            foreach (var c in news)
            {
                couponesBuilder.Append(string.Format("<item><Title><![CDATA[{0}]]></Title>" +                    "<Description><![CDATA[{1}]]></Description>" +                    "<PicUrl><![CDATA[{2}]]></PicUrl>" +                    "<Url><![CDATA[{3}]]></Url>" +                    "</item>",
                   c.Title, c.Description, c.PicUrl, c.Url
                 ));
            }
            couponesBuilder.Append("</Articles></xml>");            return couponesBuilder.ToString();
        }

    }    public class WeixinNews
    {        public string Title { set; get; }        public string Description { set; get; }        public string PicUrl { set; get; }        public string Url { set; get; }
    }
}
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Microsoft développe de nouveaux effets de flou pour Windows 11 Microsoft développe de nouveaux effets de flou pour Windows 11 May 13, 2023 am 09:04 AM

Le nouveau SDK Windows 11 pour la build 22523 a révélé que Microsoft développe un nouvel effet de flou pour Windows 11. Cet effet est appelé Tabbed et s'ajoute à l'acrylique et au mica. Le nouveau DWMWA_SYSTEMBACKDROP_TYPE dans le SDK 22523, Mica, l'API Win32 publique d'Acrylic et leur étrange nouveau mélange « d'onglets » : pic.twitter.com/dbsu7ZFiIi — Tout est de retour (@StartIsBack) 15 décembre 2021 Disponible dans l'exemple d'application du SDK suivant

Maîtriser les compétences essentielles au développement secondaire du SDK Java Hikvision Maîtriser les compétences essentielles au développement secondaire du SDK Java Hikvision Sep 06, 2023 am 08:10 AM

Maîtriser les compétences essentielles pour le développement secondaire du SDK Java Hikvision Introduction : Avec le développement rapide des technologies de l'information, les systèmes de vidéosurveillance ont été largement utilisés dans divers domaines. En tant que principal fournisseur national de solutions de vidéosurveillance, les produits et technologies de Hikvision ont toujours occupé une position importante sur le marché. Afin de répondre aux besoins des différents projets, Hikvision fournit un SDK permettant aux développeurs d'effectuer un développement secondaire. Cet article présentera quelques compétences essentielles pour maîtriser le développement secondaire du SDK Java Hikvision et joindra des exemples de code correspondants. 1. Comprendre Hikvision

qu'est-ce que le SDK qu'est-ce que le SDK Jan 06, 2023 pm 03:26 PM

Le nom complet du SDK est « Software Development Kit », qui signifie « kit de développement logiciel » en chinois. Il s'agit d'un ensemble d'outils fournis par le fabricant de la plate-forme matérielle, du système d'exploitation (OS) ou du langage de programmation. Les SDK aident les développeurs de logiciels à créer des applications pour des plates-formes, des systèmes ou des langages de programmation spécifiques. Un SDK de base se compose généralement d'un compilateur, d'un débogueur et d'une interface de programmation d'application (API), mais peut également inclure d'autres contenus, tels que : de la documentation, des bibliothèques, un environnement d'exécution/développement, des outils de test/analyse, des protocoles réseau, etc.

Windows App SDK 1.2 est maintenant en ligne, voici les nouveautés Windows App SDK 1.2 est maintenant en ligne, voici les nouveautés May 12, 2023 pm 06:07 PM

Le WindowsAppSDK est un ensemble d'outils et d'API que les développeurs peuvent utiliser dans leurs applications Windows pour fournir des fonctionnalités « cohérentes » sur une variété d'appareils utilisant Windows 10 (version 1809 et ultérieure) et Windows 11. Il est très important de comprendre qu'il ne remplace pas les types d'applications existants tels que .NET ou le SDK Windows, il fournit simplement un ensemble d'outils API unifié qui peut être utilisé pour compléter vos applications existantes. Aujourd'hui, Microsoft a publié la version 1.2 du SDK Windows App avec de nombreuses nouvelles fonctionnalités. Le point culminant de cette version pourrait être les développeurs tiers

Développement PHP WeChat : Comment implémenter le cryptage et le décryptage des messages Développement PHP WeChat : Comment implémenter le cryptage et le décryptage des messages May 13, 2023 am 11:40 AM

PHP est un langage de script open source largement utilisé dans le développement Web et la programmation côté serveur, notamment dans le développement de WeChat. Aujourd'hui, de plus en plus d'entreprises et de développeurs commencent à utiliser PHP pour le développement de WeChat, car il est devenu un langage de développement vraiment facile à apprendre et à utiliser. Dans le développement de WeChat, le cryptage et le décryptage des messages sont une question très importante car ils impliquent la sécurité des données. Pour les messages sans méthodes de cryptage et de décryptage, les pirates peuvent facilement obtenir les données, ce qui constitue une menace pour les utilisateurs.

Installation et utilisation du mini programme WeChat PHP SDK Installation et utilisation du mini programme WeChat PHP SDK Mar 27, 2024 am 09:33 AM

Installation et utilisation du programme WeChat Mini PHPSDK Avec le développement rapide de l'Internet mobile, le programme WeChat Mini est devenu un nouveau moyen pour de plus en plus d'entreprises de faire des affaires et de promouvoir leurs produits. WeChat Mini Program PHPSDK fournit aux développeurs des outils de développement pratiques et rapides, qui peuvent considérablement améliorer l'efficacité du développement. Cet article présentera l'installation et l'utilisation de l'applet WeChat PHPSDK. 1. Installer le SDK 1. Téléchargez le fichier du projet sur GitHub. L'applet WeChat PHPSDK est un projet open source. Les développeurs peuvent le télécharger sur GitHub.

Quel est le dossier SDK sous Linux Quel est le dossier SDK sous Linux Jul 11, 2023 pm 01:38 PM

Le SDK sous Linux est un dossier qui contient des outils et des ressources tels que des compilateurs, des débogueurs, des fichiers de bibliothèque, des fichiers d'en-tête, etc. SDK est l'abréviation de « kit de développement logiciel », qui signifie kit de développement logiciel. Il s'agit d'un environnement intégré permettant aux développeurs de développer et de créer des applications, en particulier celles fonctionnant sur le système d'exploitation Linux.

PHP implémente le SDK Kafka open source PHP implémente le SDK Kafka open source Jun 18, 2023 am 09:18 AM

Avec le développement rapide d'Internet, une grande quantité de données doit être transmise et traitée. Par conséquent, le système de messagerie, en tant qu'application classique de transmission et de traitement de données, est devenu un élément indispensable de l'architecture Internet. Kafka est largement utilisé dans l'architecture de données d'entreprise en tant que système de messagerie distribué et évolutif hautes performances prenant en charge le traitement des données en temps réel. Lors de l'utilisation de Kafka, un problème important est de savoir comment appeler l'API de Kafka. L'équipe de développement fournit à cet effet des clients open source dans plusieurs langages, ainsi que le KafkaS open source implémenté en PHP.

See all articles