Heim  >  Artikel  >  WeChat-Applet  >  Entwicklung der öffentlichen WeChat-Plattform: Automatischer Verwaltungsmechanismus von AccessToken

Entwicklung der öffentlichen WeChat-Plattform: Automatischer Verwaltungsmechanismus von AccessToken

高洛峰
高洛峰Original
2017-02-27 13:40:542981Durchsuche

In „WeChat Public Platform Development: Allgemeine Schnittstellenbeschreibung“ habe ich die Methode zum Erhalten von AccessToken (universelle Schnittstelle) vorgestellt.

Im eigentlichen Entwicklungsprozess müssen alle High-Level-Schnittstellen AccessToken bereitstellen. Daher müssen wir jedes Mal, wenn wir die High-Level-Schnittstelle aufrufen, eine Methode ausführen, um das AccessToken zu erhalten, zum Beispiel:

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

Oder nachdem Sie appId und appSecret global registriert haben, können Sie auch Folgendes tun:

var accessToken = AccessTokenContainer.GetAccessToken(_appId);

Dann verwenden Sie dieses accessToken, um es in die Methode der erweiterten Schnittstelle einzugeben. Wir können das Menü so erhalten:

var result = CommonApi.GetMenu(accessToken);

Normalerweise ist dies bereits ein sehr einfacher API-Aufrufprozess. Aber damit wollen wir nicht aufhören, wir werden fast alle API-Aufrufe auf eine Zeile kürzen.

Dabei haben wir neben der Vereinfachung des Codes auch zwei Wünsche:

Lassen Sie die API das geänderte AccessToken automatisch verarbeiten (wenn mehrere Server gleichzeitig arbeiten, z. B. beim Laden). Balancing) Im Falle eines offiziellen WeChat-Kontos kann das AccessToken extern aktualisiert werden, wodurch das lokale AccessToken ungültig wird. Das endgültige korrekte API-Ergebnis muss erneut abgerufen und zurückgegeben werden.

Ändert die aktuelle API-Aufrufmethode nicht und ist vollständig abwärtskompatibel.

Aufrufcode

Nach der Änderung können wir die API wie folgt direkt in einer Zeile aufrufen und müssen jedes Mal nur eine App-ID angeben:

var result = CommonApi.GetMenu(appId);

Derzeit in Vor der Ausführung müssen wir appId und appSecret wie zuvor global registrieren:

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

Wie Sie sehen können, wird das ursprüngliche accessToken durch appId ersetzt (die neue Version unterstützt weiterhin die Eingabe von accessToken). Dadurch entfällt die Notwendigkeit, den AccessToken-Prozess abzurufen. Der spezifische Prozess wird im Folgenden erläutert.

SDK-Quellcode-Implementierungsprozess

Um (unerwartet) abgelaufene AccessToken automatisch zu verarbeiten, stellte das SDK bisher die Methode Senparc.Weixin.MP/AccessTokenHandlerWapper.Do() bereit. Durch dieses Upgrade wurde AccessTokenHandlerWapper.cs in ApiHandlerWapper.cs umbenannt, die Do()-Methode abgeschafft und die TryCommonApi()-Methode hinzugefügt. Der Code lautet wie folgt:

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;
        }
    }
}

Der Quellcode der entsprechenden API sah ursprünglich aus so:

/// <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;
}

Jetzt nach Verwendung der TryCommonApi()-Methode:

/// <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);
}

Wir können die folgenden Änderungen beobachten:

1. Der ursprüngliche accessToken-Variablenname wird in accessTokenOrAppId geändert (Alle zugehörigen Schnittstellen werden sich in der neuen Version auf diese Weise ändern).

Nach der Änderung kann dieser Parameter mit accessToken (abwärtskompatibel) oder appId eingegeben werden (es ist kein Zugriff auf accessToken erforderlich). Das SDK bestimmt anhand der Zeichenfolgenlänge automatisch, zu welchem ​​Parametertyp er gehört. Es stehen 3 mögliche Parameter zur Verfügung:

a) appId. Für die Verwendung von appId ist eine globale Registrierung von appId und appSecret im Voraus erforderlich (wie oben erwähnt). Wenn festgestellt wird, dass das zwischengespeicherte AccessToken während des API-Aufrufs abgelaufen ist, aktualisiert das SDK automatisch das AccessToken und versucht die API-Anfrage erneut, um sicherzustellen, dass das richtige Ergebnis vorliegt zurückgegeben. Wenn die App-ID nicht registriert wurde, wird eine Ausnahme ausgelöst.

b) accessToken. In diesem Fall wird die ursprüngliche Anforderungsmethode verwendet. Wenn das accessToken ungültig ist, wird direkt eine Ausnahme ausgelöst, ohne dass es erneut versucht wird.

c) null. Wenn der Parameter „accessTokenOrAppId“ null ist, ruft das SDK automatisch die erste global registrierte App-ID ab. Wenn eine Anwendung nur für eine bestimmte WeChat-ID entwickelt wird, kann diese Methode verwendet werden. Wenn global keine App-ID registriert ist, wird eine Ausnahme ausgelöst.

2. Der Code für den Zugriff auf die API in der ursprünglichen Methode wurde in keiner Weise geändert. Er ist lediglich in der Methode return ApiHandlerWapper.TryCommonApi(accessToken =>{...},accessTokenOrAppId) verschachtelt. delegieren Der Zweck besteht darin, dem SDK zu ermöglichen, automatisch denselben Code auszuführen, nachdem die erste mögliche Anfrage fehlgeschlagen ist.

Diese Funktion wurde in Senparc.Weixin.MP v12.1 veröffentlicht.


Weitere Artikel zur Entwicklung der öffentlichen WeChat-Plattform: Automatischer Verwaltungsmechanismus von AccessToken finden Sie auf der chinesischen PHP-Website!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn