Maison  >  Article  >  Applet WeChat  >  Développement de la plateforme publique WeChat : mécanisme de gestion automatique AccessToken

Développement de la plateforme publique WeChat : mécanisme de gestion automatique AccessToken

高洛峰
高洛峰original
2017-02-27 13:40:543046parcourir

Dans "Développement de la plateforme publique WeChat : description générale de l'interface", j'ai présenté la méthode d'obtention d'AccessToken (interface universelle).

Dans le processus de développement actuel, toutes les interfaces de haut niveau doivent fournir AccessToken, donc chaque fois que nous appelons l'interface de haut niveau, nous devons exécuter une méthode pour obtenir l'AccessToken, par exemple :

var accessToken = AccessTokenContainer.TryGetAccessToken(appId, appSecret);

Ou après avoir enregistré globalement appId et appSecret, vous pouvez également faire ceci :

var accessToken = AccessTokenContainer.GetAccessToken(_appId);

Utilisez ensuite cet accessToken pour saisir la méthode de l'interface avancée. Par exemple, nous pouvons obtenir. le menu comme ceci :

var result = CommonApi.GetMenu(accessToken);

Normalement, il s'agit déjà d'un processus d'appel d'API très simple. Mais nous ne voulons pas nous arrêter là, nous allons réduire presque tous les appels API à une seule ligne.

Ce faisant, en plus de simplifier le code, nous avons également deux souhaits :

Laisser l'API gérer automatiquement l'AccessToken modifié (lorsque plusieurs serveurs fonctionnent en même temps, comme lors du chargement équilibrage) Dans le cas d'un compte officiel WeChat, l'AccessToken peut être actualisé en externe, ce qui rend l'AccessToken local invalide), et le résultat final correct de l'API doit être à nouveau obtenu et renvoyé.

Ne modifie pas la méthode d'appel de l'API actuelle et est entièrement rétrocompatible.

Code d'appel

Après modification, nous pouvons appeler directement l'API sur une seule ligne comme celle-ci, et n'avons besoin de fournir qu'un seul appId à chaque fois :

var result = CommonApi.GetMenu(appId);

Actuellement, avant l'exécution, nous devons enregistrer globalement appId et appSecret comme avant :

AccessTokenContainer.Register(_appId, _appSecret);//全局只需注册一次,例如可以放在Global的Application_Start()方法中。

Comme vous pouvez le voir, l'accessToken d'origine est remplacé par appId (la nouvelle version prend toujours en charge la saisie d'accessToken) , éliminant ainsi le besoin d'obtenir le processus accessToken. Le processus spécifique est expliqué ci-dessous.

Processus d'implémentation du code source du SDK

Auparavant, afin de gérer automatiquement les AccessToken expirés (de manière inattendue), le SDK a fourni la méthode Senparc.Weixin.MP/AccessTokenHandlerWapper.Do(). Cette mise à niveau a renommé AccessTokenHandlerWapper.cs en ApiHandlerWapper.cs, a supprimé la méthode Do() et a ajouté la méthode TryCommonApi(). Le code est le suivant :

namespace Senparc.Weixin.MP
{
    /// <summary>
    /// 针对AccessToken无效或过期的自动处理类
    /// </summary>
    public static class ApiHandlerWapper
    {
        /// <summary>
        /// 使用AccessToken进行操作时,如果遇到AccessToken错误的情况,重新获取AccessToken一次,并重试。
        /// 使用此方法之前必须使用AccessTokenContainer.Register(_appId, _appSecret);或JsApiTicketContainer.Register(_appId, _appSecret);方法对账号信息进行过注册,否则会出错。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fun"></param>
        /// <param name="accessTokenOrAppId">AccessToken或AppId。如果为null,则自动取已经注册的第一个appId/appSecret来信息获取AccessToken。</param>
        /// <param name="retryIfFaild">请保留默认值true,不用输入。</param>
        /// <returns></returns>
        public static T TryCommonApi<T>(Func<string, T> fun, string accessTokenOrAppId = null, bool retryIfFaild = true) where T : WxJsonResult
        {
            string appId = null;
            string accessToken = null;
 
            if (accessTokenOrAppId == null)
            {
                appId = AccessTokenContainer.GetFirstOrDefaultAppId();
                if (appId == null)
                {
                    throw new WeixinException("尚无已经注册的AppId,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!");
                }
            }
            else if (ApiUtility.IsAppId(accessTokenOrAppId))
            {
                if (!AccessTokenContainer.CheckRegistered(accessTokenOrAppId))
                {
                    throw new WeixinException("此appId尚未注册,请先使用AccessTokenContainer.Register完成注册(全局执行一次即可)!");
                }
 
                appId = accessTokenOrAppId;
            }
            else
            {
                //accessToken
                accessToken = accessTokenOrAppId;
            }
 
 
            T result = null;
 
            try
            {
                if (accessToken == null)
                {
                    var accessTokenResult = AccessTokenContainer.GetAccessTokenResult(appId, false);
                    accessToken = accessTokenResult.access_token;
                }
                result = fun(accessToken);
            }
            catch (ErrorJsonResultException ex)
            {
                if (!retryIfFaild
                    && appId != null
                    && ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效)
                {
                    //尝试重新验证
                    var accessTokenResult = AccessTokenContainer.GetAccessTokenResult(appId, true);
                    accessToken = accessTokenResult.access_token;
                    result = TryCommonApi(fun, appId, false);
                }
            }
            return result;
        }
    }
}

Le code source de l'API correspondante était initialement présent. comme ceci :

/// <summary>
/// 获取当前菜单,如果菜单不存在,将返回null
/// </summary>
/// <param name="accessToken"></param>
/// <returns></returns>
public static GetMenuResult GetMenu(string accessToken)
{
    var url = string.Format("https://api.weixin.qq.com/cgi-bin/menu/get?access_token={0}", accessToken);
 
    var jsonString = HttpUtility.RequestUtility.HttpGet(url, Encoding.UTF8);
    //var finalResult = GetMenuFromJson(jsonString);
 
    GetMenuResult finalResult;
    JavaScriptSerializer js = new JavaScriptSerializer();
    try
    {
        var jsonResult = js.Deserialize<GetMenuResultFull>(jsonString);
        if (jsonResult.menu == null || jsonResult.menu.button.Count == 0)
        {
            throw new WeixinException(jsonResult.errmsg);
        }
 
        finalResult = GetMenuFromJsonResult(jsonResult);
    }
    catch (WeixinException ex)
    {
        finalResult = null;
    }
 
    return finalResult;
}

Maintenant, après avoir utilisé la méthode TryCommonApi() :

/// <summary>
/// 获取当前菜单,如果菜单不存在,将返回null
/// </summary>
/// <param name="accessTokenOrAppId">AccessToken或AppId。当为AppId时,如果AccessToken错误将自动获取一次。当为null时,获取当前注册的第一个AppId。</param>
/// <returns></returns>
public static GetMenuResult GetMenu(string accessTokenOrAppId)
{
    return ApiHandlerWapper.TryCommonApi(accessToken =>
      {
          var url = string.Format("https://api.weixin.qq.com/cgi-bin/menu/get?access_token={0}", accessToken);
 
          var jsonString = HttpUtility.RequestUtility.HttpGet(url, Encoding.UTF8);
          //var finalResult = GetMenuFromJson(jsonString);
 
          GetMenuResult finalResult;
          JavaScriptSerializer js = new JavaScriptSerializer();
          try
          {
              var jsonResult = js.Deserialize<GetMenuResultFull>(jsonString);
              if (jsonResult.menu == null || jsonResult.menu.button.Count == 0)
              {
                  throw new WeixinException(jsonResult.errmsg);
              }
 
              finalResult = GetMenuFromJsonResult(jsonResult);
          }
          catch (WeixinException ex)
          {
              finalResult = null;
          }
 
          return finalResult;
      }, accessTokenOrAppId);
}

Nous pouvons observer les changements suivants :

1. Le nom de la variable accessToken d'origine est remplacé par accessTokenOrAppId (toutes les interfaces associées changeront de cette manière dans la nouvelle version).

Après modification, ce paramètre peut être saisi avec accessToken (rétrocompatible) ou appId (pas besoin d'obtenir accessToken). Le SDK déterminera automatiquement à quel type de paramètre il appartient en fonction de la longueur de la chaîne. Il y a 3 paramètres possibles fournis :

a) appId. L'utilisation d'appId nécessite un enregistrement global d'appId et appSecret à l'avance (comme mentionné ci-dessus). Lorsque le AccessToken mis en cache a expiré lors de l'appel d'API, le SDK actualisera automatiquement l'AccessToken et réessayera la demande d'API pour s'assurer que le résultat est correct. revenu. Si l'appId n'a pas été enregistré, une exception sera levée.

b) accessToken. Dans ce cas, la méthode de requête d'origine sera utilisée si le accessToken n'est pas valide, une exception sera levée directement sans réessayer.

c) nul. Lorsque le paramètre accessTokenOrAppId est nul, le SDK obtiendra automatiquement le premier appId enregistré globalement. Si une application est développée uniquement pour un certain identifiant WeChat, cette méthode peut être utilisée. Lorsqu’aucun appId n’est enregistré globalement, une exception sera levée.

2. Le code d'accès à l'API dans la méthode d'origine n'a été modifié en aucune façon. Il est simplement imbriqué dans la méthode return ApiHandlerWapper.TryCommonApi(accessToken =>{...},accessTokenOrAppId) à. délégué Le but est de permettre au SDK d'exécuter automatiquement le même code après l'échec de la première requête possible.

Cette fonctionnalité a été publiée dans Senparc.Weixin.MP v12.1.


Pour plus d'articles liés au développement de la plateforme publique WeChat : mécanisme de gestion automatique AccessToken, veuillez faire attention au site Web PHP chinois !


Déclaration:
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