>  기사  >  위챗 애플릿  >  WeChat 공개 플랫폼 개발: AccessToken 자동 관리 메커니즘

WeChat 공개 플랫폼 개발: AccessToken 자동 관리 메커니즘

高洛峰
高洛峰원래의
2017-02-27 13:40:543046검색

"WeChat 공개 플랫폼 개발: 일반 인터페이스 설명"에서는 AccessToken(유니버설 인터페이스)을 얻는 방법을 소개했습니다.

실제 개발 과정에서 모든 상위 인터페이스는 AccessToken을 제공해야 하므로 상위 인터페이스를 호출하기 전에 매번 AccessToken을 얻는 메서드를 실행해야 합니다. 예:

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

또는 appId 및 appSecret을 전체적으로 등록한 후 다음을 수행할 수도 있습니다:

var accessToken = AccessTokenContainer.GetAccessToken(_appId);

그런 다음 이 accessToken을 사용하여 고급 인터페이스의 메소드를 입력할 수 있습니다. 예를 들어 다음과 같은 메뉴를 얻을 수 있습니다. 🎜>

var result = CommonApi.GetMenu(accessToken);

일반적으로 이는 이미 매우 간단한 API 호출 프로세스입니다. 그러나 우리는 거기서 멈추고 싶지 않습니다. 거의 모든 API 호출을 한 줄로 단축할 것입니다.

이 작업을 수행하는 동안 코드를 더 간단하게 만드는 것 외에도 두 가지 희망사항이 있습니다.

API가 변경된 AccessToken을 자동으로 처리하도록 합니다(로드 등 여러 서버가 동시에 작동하는 경우). 밸런싱) WeChat 공식 계정의 경우 AccessToken이 외부적으로 새로 고쳐져 로컬 AccessToken이 무효화될 수 있습니다.) 최종 올바른 API 결과를 다시 얻어서 반환해야 합니다.

현재 API 호출 방법을 변경하지 않으며 이전 버전과 완전히 호환됩니다.

호출 코드

수정 후 이 줄을 사용하여 API를 직접 호출할 수 있으며 매번 appId만 제공하면 됩니다.

var result = CommonApi.GetMenu(appId);

현재 실행하기 전에 이전과 같이 appId 및 appSecret을 전역으로 등록해야 합니다.

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

보시다시피 원래 accessToken은 appId로 대체되며(새 버전에서는 여전히 accessToken 입력을 지원함) accessToken을 얻는 프로세스가 제거됩니다. . 구체적인 과정은 아래에 설명되어 있습니다.

SDK 소스 코드 구현 프로세스

이전에는 (예기치 않게) 만료된 AccessToken을 자동으로 처리하기 위해 SDK에서 Senparc.Weixin.MP/AccessTokenHandlerWapper.Do() 메서드를 제공했습니다. 이번 업그레이드에서는 AccessTokenHandlerWapper.cs의 이름이 ApiHandlerWapper.cs로 바뀌고 Do() 메서드가 폐지되었으며 TryCommonApi() 메서드가 추가되었습니다. 코드는 다음과 같습니다.

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

해당 API의 소스 코드는 원래 다음과 같습니다. :

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

이제 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);
}

다음과 같은 변경 사항을 관찰할 수 있습니다.

1. 원래 accessToken 변수 이름이 accessTokenOrAppId로 변경됩니다(모두 새 버전에서는 인터페이스가 모두 이렇게 변경됩니다.

수정 후 이 매개변수는 accessToken(이전 버전과 호환됨) 또는 appId(accessToken을 얻을 필요 없음)를 사용하여 입력할 수 있습니다. SDK는 문자열 길이에 따라 해당 매개변수 유형이 속하는지 자동으로 결정합니다. 3가지 가능한 매개변수가 제공됩니다:

a) appId. appId를 사용하려면 위에서 언급한 대로 appId 및 appSecret의 전역 등록이 필요합니다. API 호출 중에 캐시된 AccessToken이 만료된 것으로 확인되면 SDK는 자동으로 AccessToken을 새로 고치고 API 요청을 다시 시도하여 올바른 결과가 나오는지 확인합니다. 돌아왔다. appId가 등록되지 않은 경우 예외가 발생합니다.

b) accessToken. 이 경우 원래 요청 방법이 사용됩니다. accessToken이 유효하지 않으면 재시도 없이 직접 예외가 발생합니다.

c) null. accessTokenOrAppId 매개변수가 null이면 SDK는 전역적으로 등록된 첫 번째 appId를 자동으로 가져옵니다. 특정 WeChat ID에 대해서만 애플리케이션을 개발하는 경우 이 방법을 사용할 수 있습니다. 전역적으로 등록된 appId가 없으면 예외가 발생합니다.

2. 원래 메소드에서 API에 액세스하기 위한 코드는 어떤 방식으로도 수정되지 않았습니다. 단지 return ApiHandlerWapper.TryCommonApi(accessToken =>{...},accessTokenOrAppId) 메소드에 중첩되어 있을 뿐입니다. 위임 목적은 가능한 첫 번째 요청이 실패한 후 SDK가 동일한 코드를 자동으로 실행할 수 있도록 하는 것입니다.

이 기능은 Senparc.Weixin.MP v12.1에서 출시되었습니다.


WeChat 공개 플랫폼 개발과 관련된 더 많은 기사를 보려면: AccessToken 자동 관리 메커니즘, PHP 중국어 웹사이트에 주목하세요!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.