WeChat public platform development: AccessToken automatic management mechanism

高洛峰
Release: 2017-02-27 13:40:54
Original
3039 people have browsed it

In "WeChat Public Platform Development: General Interface Description", I introduced the method of obtaining AccessToken (general interface).

In the actual development process, all high-level interfaces need to provide AccessToken, so every time we call the high-level interface, we need to execute a method to obtain AccessToken, for example:

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

Or after you have globally registered appId and appSecret, you can also do this:

var accessToken = AccessTokenContainer.GetAccessToken(_appId);
Copy after login

Then use this accessToken to enter the method of the advanced interface. For example, we can get the menu like this:

var result = CommonApi.GetMenu(accessToken);
Copy after login

Normally, this is already a very simple API calling process. But we don't want to stop there, we're going to shorten almost all API calls to one line.

While doing this, in addition to making the code simpler, we also have two wishes:

Let the API automatically handle the changed AccessToken (when multiple servers operate at the same time such as load balancing) In the case of a WeChat official account, the AccessToken may be refreshed externally, causing the local AccessToken to become invalid), and the final correct API result must be re-obtained and returned.

Does not change the current API calling method and is completely backward compatible.

Calling code

After modification, we can directly call the API with this line, and only need to provide an appId each time:

var result = CommonApi.GetMenu(appId);
Copy after login

Currently before execution , we need to register appId and appSecret globally as before:

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

As you can see, the original accessToken is replaced by appId (the new version still supports entering accessToken), eliminating the process of obtaining accessToken. The specific process is explained below.

SDK source code implementation process

Previously, in order to automatically handle (unexpected) expired AccessToken, the SDK has provided the Senparc.Weixin.MP/AccessTokenHandlerWapper.Do() method. This upgrade renamed AccessTokenHandlerWapper.cs to ApiHandlerWapper.cs, abolished the Do() method, and added the TryCommonApi() method. The code is as follows:

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;
        }
    }
}
Copy after login

The source code of the corresponding API originally looked like this:

/// <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;
}
Copy after login

Now after using the TryCommonApi() method:

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

We can observe several changes:

1. The original accessToken variable name was changed to accessTokenOrAppId (all related in the new version The interfaces will all change like this).

After modification, this parameter can be entered with accessToken (downward compatibility) or appId (no need to obtain accessToken). The SDK will automatically determine which type of parameter it belongs to based on the length of the string. There are 3 possible parameters provided:

a) appId. Using appId requires global registration of appId and appSecret in advance (as mentioned above). When the cached AccessToken is found to have expired during the API call, the SDK will automatically refresh the AccessToken and retry the API request to ensure that the correct result is returned. . If the appId has not been registered, an exception will be thrown.

b) accessToken. In this case, the original request method will be used. If the accessToken is invalid, an exception will be thrown directly without retrying.

c) null. When the accessTokenOrAppId parameter is null, the SDK will automatically obtain the first appId registered globally. If an application is only developed for a certain WeChat ID, this method can be used. When no appId is registered globally, an exception will be thrown.

2. The code for accessing the API in the original method has not been modified in any way. It is just nested into the method return ApiHandlerWapper.TryCommonApi(accessToken =>{...},accessTokenOrAppId) to delegate The purpose is to allow the SDK to automatically execute the exact same code after the first possible request fails.

This feature has been released in Senparc.Weixin.MP v12.1.


For more articles related to WeChat public platform development: AccessToken automatic management mechanism, please pay attention to the PHP Chinese website!


Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template