Maison > Applet WeChat > Développement WeChat > le corps du texte

Développement C# du portail et de l'application WeChat (4) - Suivre la liste des utilisateurs et la gestion détaillée des informations

高洛峰
Libérer: 2017-02-16 16:34:12
original
1565 Les gens l'ont consulté

Le mois dernier, j'ai présenté le développement de portails et d'applications WeChat en C# et j'ai écrit plusieurs essais à partager. En raison de contraintes de temps, je n'ai pas continué à écrire cette série de blogs depuis un moment. mais nous avons continué à explorer la technologie dans ce domaine en profondeur afin de mieux l'appliquer, nous nous sommes concentrés sur le développement de la technologie sous-jacente.

Une caractéristique très importante de WeChat est qu'il peut tirer parti de l'énorme base d'utilisateurs de sa plateforme, il est donc facile à intégrer dans le système CRM (Customer Relationship Management), les comptes et les abonnements du service peuvent pousser de manière pertinente. des informations aux abonnés, des nouvelles sur les produits et des conversations interactives avec des utilisateurs actifs qui ont répondu aux messages et aux événements dans les 48 heures. Par conséquent, les informations sur les utilisateurs sont une partie très importante de l'API WeChat. Cet essai présente principalement comment obtenir les utilisateurs suivants et afficher les informations sur les utilisateurs. , gestion de groupe, etc. Développer des applications.

1. Suivre la liste des utilisateurs et les informations du groupe d'utilisateurs

Sur la plateforme de gestion WeChat, nous pouvons voir les utilisateurs qui suivent notre compte et les informations du groupe d'utilisateurs, comme indiqué ci-dessous.

C#开发微信门户及应用(4)--关注用户列表及详细信息管理

Dans l'interface de gestion ci-dessus, vous pouvez voir les informations de base des utilisateurs suiveurs, mais ce que vous obtenez en utilisant l'API WeChat est une liste appelée OpenID. Comprenons cela d'abord. Quel est le problème ? La description de l'API WeChat donne l'analyse suivante :

La liste des abonnés est constituée d'une chaîne d'OpenID (identifiants WeChat cryptés). L'OpenID de chaque utilisateur pour chaque compte officiel est unique. Pour différents comptes officiels, le même. l'openid de l'utilisateur est différent). Les comptes officiels peuvent utiliser cette interface pour obtenir des informations utilisateur de base basées sur OpenID, notamment le surnom, l'avatar, le sexe, la ville, la langue et l'heure de suivi.

Le sens de l'analyse ci-dessus est très clair, c'est-à-dire que si un utilisateur suit notre compte officiel, peu importe combien de fois il le suit, c'est une certaine valeur pour notre compte officiel cependant, un utilisateur ; Pour les autres comptes publics, ils ont des OpenID différents.

WeChat fournit quelques informations sur les mots clés pour enregistrer le contenu lié à l'utilisateur. Sur la base des définitions pertinentes de l'utilisateur, nous définissons une classe d'entité pour placer les informations utilisateur récupérées.

    /// <summary>
    /// 高级接口获取的用户信息。    /// 在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID    /// (加密后的微信号,每个用户对每个公众号的OpenID是唯一的。对于不同公众号,同一用户的openid不同)。    /// 公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称、头像、性别、所在城市、语言和关注时间。    /// </summary>
    public class UserJson : BaseJsonResult
    {        /// <summary>
        /// 用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。        /// </summary>
        public int subscribe { get; set; }        /// <summary>
        /// 用户的标识,对当前公众号唯一        /// </summary>
        public string openid { get; set; }        /// <summary>
        /// 用户的昵称        /// </summary>
        public string nickname { get; set; }        /// <summary>
        /// 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知        /// </summary>
        public int sex { get; set; }        /// <summary>
        /// 用户的语言,简体中文为zh_CN        /// </summary>
        public string language { get; set; }        /// <summary>
        /// 用户所在城市        /// </summary>
        public string city { get; set; }        /// <summary>
        /// 用户所在省份        /// </summary>
        public string province { get; set; }        /// <summary>
        /// 用户所在国家        /// </summary>
        public string country { get; set; }        /// <summary>
        /// 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空        /// </summary>
        public string headimgurl { get; set; }        /// <summary>
        /// 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间        /// </summary>
        public long subscribe_time { get; set; }
    }
Copier après la connexion

Selon la définition des informations de regroupement, nous définissons des informations de classe d'entité groupées.

    /// <summary>
    /// 分组信息    /// </summary>
    public class GroupJson : BaseJsonResult
    {        /// <summary>
        /// 分组id,由微信分配        /// </summary>
        public int id { get; set; }        /// <summary>
        /// 分组名字,UTF8编码        /// </summary>
        public string name { get; set; }
    }
Copier après la connexion

2. Obtenez le jeton de l'appelant AIP

Lors du développement de l'API WeChat, nous devons souvent saisir un jeton d'accès. , qui est une chaîne qui distingue l'appelant et enregistre les informations de session. Par conséquent, avant d'apprendre tout le développement d'API, nous devons avoir une bonne compréhension de ce paramètre de contrôle d'accès.

C#开发微信门户及应用(4)--关注用户列表及详细信息管理

Nous pouvons en apprendre davantage sur la définition de cet objet à partir de la description de l'API de WeChat.

access_token est le ticket globalement unique du compte public. Le compte public doit utiliser access_token lors de l'appel de chaque interface. Dans des circonstances normales, access_token est valide pendant 7 200 secondes. Une acquisition répétée rendra le dernier access_token invalide. Étant donné que le nombre d'appels API pour obtenir access_token est très limité, il est recommandé aux développeurs de stocker et de mettre à jour access_token à l'échelle mondiale. L'actualisation fréquente de access_token limitera les appels API et affectera leur propre activité.

Selon la définition ci-dessus, nous pouvons voir qu'il s'agit d'un paramètre lié à l'identité et à la durée de la session, et il y a une limite au nombre de fois qu'il peut être généré, nous besoin Il est mis en cache et réutilisé.Avant l'expiration de la session, nous devons réutiliser ce paramètre autant que possible pour éviter les demandes répétées, augmenter la pression sur le serveur et le temps d'appel.

J'ai défini une méthode pour construire et générer le jeton d'accès associé, et elle a la fonction de mise en cache, mais comment le mettre en cache et l'utiliser est transparent pour l'appel à mon API. Lorsque nous l'utilisons, il suffit d'appeler. il.

        /// 获取凭证接口        /// </summary>
        /// <param name="appid">第三方用户唯一凭证</param>
        /// <param name="secret">第三方用户唯一凭证密钥,既appsecret</param>
        string GetAccessToken(string appid, string secret);
Copier après la connexion

Le cache est principalement basé sur MemoryCache, une bibliothèque de classes ajoutée dans .NET4. C'est une très bonne classe de cache.

Mon code d'implémentation d'opération pour obtenir AccessToken est le suivant.

        /// <summary>
        /// 获取每次操作微信API的Token访问令牌        /// </summary>
        /// <param name="appid">应用ID</param>
        /// <param name="secret">开发者凭据</param>
        /// <returns></returns>
        public string GetAccessToken(string appid, string secret)
        {            //正常情况下access_token有效期为7200秒,这里使用缓存设置短于这个时间即可
            string access_token = MemoryCacheHelper.GetCacheItem<string>("access_token", delegate()
                {                    string grant_type = "client_credential";                    var url = string.Format("http://www.php.cn/{0}&appid={1}&secret={2}",
                                            grant_type, appid, secret);

                    HttpHelper helper = new HttpHelper();                    string result = helper.GetHtml(url);                    string regex = "\"access_token\":\"(?<token>.*?)\"";
                    string token = CRegex.GetText(result, regex, "token");                    return token;
                },                new TimeSpan(0, 0, 7000)//7000秒过期            );            return access_token;            
        }
Copier après la connexion

Comme nous savons qu'AccessToken expire dans 7200 secondes par défaut, nous utilisons le cache autant que possible pour enregistrer sa valeur pendant cette période. ce temps est dépassé, lorsque nous appellerons cette méthode, elle nous obtiendra automatiquement une nouvelle valeur.

3. Obtenez la liste des utilisateurs suivants

Obtenez la liste des utilisateurs suivants. Un appel d'API pull peut extraire jusqu'à 10 000 OpenID. plusieurs fois. des moyens de répondre aux besoins. La définition de l'interface de WeChat est la suivante.

Méthode de requête http : GET (veuillez utiliser le protocole https)
http://www.php.cn/

这个接口返回的数据是

{"total":2,"count":2,"data":{"openid":["","OPENID1","OPENID2"]},"next_openid":"NEXT_OPENID"}
Copier après la connexion

根据返回的Json数据定义,我们还需要定义两个实体类,用来存放返回的结果。

    /// <summary>
    /// 获取关注用户列表的Json结果    /// </summary>
    public class UserListJsonResult : BaseJsonResult
    {        /// <summary>
        /// 关注该公众账号的总用户数        /// </summary>
        public int total { get; set; }        /// <summary>
        /// 拉取的OPENID个数,最大值为10000        /// </summary>
        public int count { get; set; }        /// <summary>
        /// 列表数据,OPENID的列表        /// </summary>
        public OpenIdListData data { get; set; }        /// <summary>
        /// 拉取列表的后一个用户的OPENID        /// </summary>
        public string next_openid { get; set; }
    }    /// <summary>
    /// 列表数据,OPENID的列表    /// </summary>
    public class OpenIdListData
    {        /// <summary>
        /// OPENID的列表        /// </summary>
        public List<string> openid { get; set; }
    }
Copier après la connexion

为了获取相关的用户信息,我定义了一个接口,用来获取用户的信息,接口定义如下所示。

    /// <summary>
    /// 微信用户管理的API接口    /// </summary>
    public interface IUserApi
    {        /// <summary>
        /// 获取关注用户列表        /// </summary>
        /// <param name="accessToken">调用接口凭证</param>
        /// <param name="nextOpenId">第一个拉取的OPENID,不填默认从头开始拉取</param>
        /// <returns></returns>
        List<string> GetUserList(string accessToken, string nextOpenId = null);        /// <summary>
        /// 获取用户基本信息        /// </summary>
        /// <param name="accessToken">调用接口凭证</param>
        /// <param name="openId">普通用户的标识,对当前公众号唯一</param>
        /// <param name="lang">返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语</param>
        UserJson GetUserDetail(string accessToken, string openId, Language lang = Language.zh_CN);
Copier après la connexion

然后在实现类里面,我们分别对上面两个接口进行实现,获取用户列表信息如下所示。

        /// <summary>
        /// 获取关注用户列表        /// </summary>
        /// <param name="accessToken">调用接口凭证</param>
        /// <param name="nextOpenId">第一个拉取的OPENID,不填默认从头开始拉取</param>
        /// <returns></returns>
        public List<string> GetUserList(string accessToken, string nextOpenId = null)
        {
            List<string> list = new List<string>();            string url = string.Format("http://www.php.cn/{0}", accessToken);            if (!string.IsNullOrEmpty(nextOpenId))
            {
                url += "&next_openid=" + nextOpenId;
            }

            UserListJsonResult result = JsonHelper<UserListJsonResult>.ConvertJson(url);            if (result != null && result.data != null)
            {
                list.AddRange(result.data.openid);
            }            return list;
        }
Copier après la connexion

我们看到,转换的逻辑已经放到了JsonHelper里面去了,这个辅助类里面分别对数值进行了获取内容,验证返回值,然后转换正确实体类几个部分的操作。

获取内容,通过辅助类HttpHelper进行,这个在我的公用类库里面,里面的逻辑主要就是通过HttpRequest进行数据的获取操作,不在赘述

HttpHelper helper = new HttpHelper();string content = helper.GetHtml(url);
Copier après la connexion

由于返回的内容,我们需要判断它是否正确返回所需的结果,如果没有,抛出自定义的相关异常,方便处理,具体如下所示。

        /// <summary>
        /// 检查返回的记录,如果返回没有错误,或者结果提示成功,则不抛出异常        /// </summary>
        /// <param name="content">返回的结果</param>
        /// <returns></returns>
        private static bool VerifyErrorCode(string content)
        {            if (content.Contains("errcode"))
            {
                ErrorJsonResult errorResult = JsonConvert.DeserializeObject<ErrorJsonResult>(content);                //非成功操作才记录异常,因为有些操作是返回正常的结果({"errcode": 0, "errmsg": "ok"})
                if (errorResult != null && errorResult.errcode != ReturnCode.请求成功)
                {                    string error = string.Format("微信请求发生错误!错误代码:{0},说明:{1}", (int)errorResult.errcode, errorResult.errmsg);
                    LogTextHelper.Error(errorResult);                    throw new WeixinException(error);//抛出错误                }
            }            return true;
        }
Copier après la connexion

然后转换为相应的格式,就是通过Json.NET的类库进行转换。

            T result = JsonConvert.DeserializeObject<T>(content);            return result;
Copier après la connexion

这样我们就可以在ConvertJson函数实体里面,完整的进行处理和转换了,转换完整的函数代码如下所示。

    /// 
    /// Json字符串操作辅助类    /// 
    public class JsonHelper where T : class, new()
    {        /// <summary>
        /// 检查返回的记录,如果返回没有错误,或者结果提示成功,则不抛出异常        /// </summary>
        /// <param name="content">返回的结果</param>
        /// <returns></returns>
        private static bool VerifyErrorCode(string content)
        {            if (content.Contains("errcode"))
            {
                ErrorJsonResult errorResult = JsonConvert.DeserializeObject<ErrorJsonResult>(content);                //非成功操作才记录异常,因为有些操作是返回正常的结果({"errcode": 0, "errmsg": "ok"})
                if (errorResult != null && errorResult.errcode != ReturnCode.请求成功)
                {                    string error = string.Format("微信请求发生错误!错误代码:{0},说明:{1}", (int)errorResult.errcode, errorResult.errmsg);
                    LogTextHelper.Error(errorResult);                    throw new WeixinException(error);//抛出错误                }
            }            return true;
        }        /// 
        /// 转换Json字符串到具体的对象        /// 
        /// 返回Json数据的链接地址
        /// 
        public static T ConvertJson(string url)
        {
            HttpHelper helper = new HttpHelper();            string content = helper.GetHtml(url);
            VerifyErrorCode(content);

            T result = JsonConvert.DeserializeObject<T>(content);            return result;
        }
}
Copier après la connexion

调用这个API的界面层代码如下所示(测试代码)

            IUserApi userBLL = new UserApi();
            List<string> userList = userBLL.GetUserList(token)
Copier après la connexion

 

4、获取用户详细信息

上面的获取列表操作,相对比较简单,而且不用POST任何数据,因此通过Get协议就能获取到所需的数据。

本小节继续介绍获取用户详细信息的操作,这个操作也是通过GET协议就可以完成的。

这个API的调用定义如下所示:

http请求方式: GET
https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
Copier après la connexion

通过传入一个OpenId,我们就能很好获取到用户的相关信息了。

前面小节我们已经定义了它的接口,说明了传入及返回值,根据定义,它的实现函数如下所示。

        /// <summary>
        /// 获取用户基本信息        /// </summary>
        /// <param name="accessToken">调用接口凭证</param>
        /// <param name="openId">普通用户的标识,对当前公众号唯一</param>
        /// <param name="lang">返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语</param>
        public UserJson GetUserDetail(string accessToken, string openId, Language lang = Language.zh_CN)
        {            string url = string.Format("http://www.php.cn/{0}&openid={1}&lang={2}",
                   accessToken, openId, lang.ToString());

            UserJson result = JsonHelper<UserJson>.ConvertJson(url);            return result;
        }
Copier après la connexion

最后,我们结合获取用户列表和获取用户详细信息的两个API,我们看看调用的代码(测试代码)。

        private void btnGetUsers_Click(object sender, EventArgs e)
        {
            IUserApi userBLL = new UserApi();
            List<string> userList = userBLL.GetUserList(token);            foreach (string openId in userList)
            {
                UserJson userInfo = userBLL.GetUserDetail(token, openId);                if (userInfo != null)
                {                    
                    string tips = string.Format("{0}:{1}", userInfo.nickname, userInfo.openid);
                    Console.WriteLine(tips);
                }
            }
        }
Copier après la connexion

 

更多C#开发微信门户及应用(4)--关注用户列表及详细信息管理 相关文章请关注PHP中文网!

Étiquettes associées:
source:php.cn
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal