• 解决微信公众号OAuth出现40029(invalid code,不合法的oauth_code)的错误


    解决方案四(推荐★★★★★)

    利用同步锁,判断code的使用情况,这是最粗犷也是最彻底的方法,以 C# 使用 Senparc.Weixin SDK 为例,直接上代码:

    定义静态变量:

        static Dictionary<string, OAuthAccessTokenResult> OAuthCodeCollection = new Dictionary<string, OAuthAccessTokenResult>();
        static object OAuthCodeCollectionLock = new object();
            

    回调方法内:

        string openId;
        OAuthAccessTokenResult result = null;
    
        try
        {
            //通过,用code换取access_token
    
            var isSecondRequest = false;
            lock (OAuthCodeCollectionLock)
            {
                isSecondRequest = OAuthCodeCollection.ContainsKey(code);
            }
    
            if (!isSecondRequest)
            {
                //第一次请求
                LogUtility.Weixin.DebugFormat("第一次微信OAuth到达,code:{0}", code);
                lock (OAuthCodeCollectionLock)
                {
                    OAuthCodeCollection[code] = null;
                }
            }
            else
            {
                //第二次请求
                LogUtility.Weixin.DebugFormat("第二次微信OAuth到达,code:{0}", code);
    
                lock (OAuthCodeCollectionLock)
                {
                    result = OAuthCodeCollection[code];
                }
            }
    
            try
            {
                try
                {
                    result = result ?? OAuthApi.GetAccessToken(SiteConfig.YourAppId, SiteConfig.YourAppSecret, code);
                }
                catch (Exception ex)
                {
                    return Content("OAuth AccessToken错误:" + ex.Message);
                }
    
                if (result != null)
                {
                    lock (OAuthCodeCollectionLock)
                    {
                        OAuthCodeCollection[code] = result;
                    }
                }
            }
            catch (ErrorJsonResultException ex)
            {
                if (ex.JsonResult.errcode == ReturnCode.不合法的oauth_code)
                {
                    //code已经被使用过
                    lock (OAuthCodeCollectionLock)
                    {
                        result = OAuthCodeCollection[code];
                    }
                }
            }
    
            openId = result != null ? result.openid : null;
        }
        catch (Exception ex)
        {
            return Content("授权过程发生错误:" + ex.Message);
        }
    
        //使用result继续操作

    说明:
    1、上述静态Dicitonary的储存方式适用于单台服务器,如果是分布式的系统,这里的Dictionary请使用公共缓存(如Redis),并使用分布锁,否则如果两次请求命中了两台不同的服务器仍然会失效。
    2、请注意做好缓存清理工作

    解决方案总结

    以上解决方案没有绝对的好坏之分,要看具体的环境,因为都不会涉及到影响效率和安全性的问题,可以视情况组合使用。推荐指数更多倾向于通用性。

    参考资料

  • 相关阅读:
    - > 听学姐讲那过去的故事——打代码的小女孩
    - > 强烈推荐!!!
    - > 贪心基础入门讲解五——任务执行顺序
    - > 贪心基础入门讲解二——活动安排问题
    - > 贪心基础入门讲解三——活动安排问题二
    - > 贪心基础入门讲解四——独木舟问题
    django装饰器
    POJ——T2421 Constructing Roads
    洛谷——P3258 [JLOI2014]松鼠的新家
    BZOJ——1787: [Ahoi2008]Meet 紧急集合
  • 原文地址:https://www.cnblogs.com/raincedar/p/10297945.html
Copyright © 2020-2023  润新知