☰
RuoYi-Vue集成微信扫码登录:OAuth2.0与JWT链路实战
2026/10/19 5:50:11 网站建设 项目流程

很多人在RuoYi-Vue项目里接第三方登录时,第一反应是去找现成插件或者直接复制某篇文章的代码,结果往往卡在微信回调、token对接、权限适配这些环节上。我在实际项目里完整做过一遍微信扫码登录接入,把OAuth2.0的流程一点一点拆开,重新过了一遍RuoYi-Vue的登录链路,最后才算真正跑通。这篇文章就把整个过程记录下来:OAuth2.0的核心流程怎么理解、RuoYi-Vue的Security和JWT机制怎么与之衔接、数据库怎么设计、前端回调怎么处理,以及我踩过的那些坑和排查思路。

如果你准备在RuoYi-Vue里接入微信登录或其他第三方OAuth登录,这篇文章可以帮你省下至少一周的试错时间。

1. 集成前的准备与整体设计

1.1 先搞懂OAuth2.0授权码模式在干什么

微信扫码登录用的是OAuth2.0的Authorization Code模式,也就是授权码模式。不要被“授权码”三个字吓到,它的本质就是四个角色之间传递凭证:

  • 资源所有者:实际使用微信的用户。
  • 客户端:我们的RuoYi-Vue系统。
  • 授权服务器:微信开放平台。
  • 资源服务器:微信提供的用户信息接口。

整个流程可以简化成五步:

  1. 用户点击“微信登录”,后端生成一个带有appid、回调地址、state随机参数的授权链接,浏览器跳转到微信的二维码页面。
  2. 用户扫码并在手机上确认授权。
  3. 微信通过302重定向,带上一个一次性code和state参数,回到我们配置的回调地址。
  4. 后端用这个code换取access_token,需要同时传递appid、appsecret、code,验证身份。
  5. 后端拿着access_token调用微信的用户信息接口,拿到openid、nickname、avatar等资料,然后在自己系统里完成登录或注册。

这里有一个容易被新手忽略的点:微信开放平台和微信公众平台是两套体系。网站扫码登录使用的是微信开放平台,appid以wx开头;公众号内网页授权使用的是微信公众平台,虽然都叫“微信登录”,但接口地址和权限完全不是一回事。我们的目标是网站应用扫码登录,所以要去open.weixin.qq.com注册开发者账号并创建“网站应用”,审核通过后才有正式的appid和appsecret。

明白了整条链路的走向,后面每一步代码都只是把这条链路落地而已。

1.2 微信开放平台参数申请与回调域名配置

在代码动手之前,先把微信开放平台侧的配置准备好。

需要申请到的核心参数就两个:

  • AppID:应用的唯一标识,公开可见。
  • AppSecret:应用密钥,后端调用微信接口时使用,不能暴露在前端。

申请完应用后,微信开放平台会要求配置“授权回调域”。这里有个容易忽略的细节:填写的值是域名本身,不带http://,也不带路径,例如auth.example.com。同时这个域名必须通过ICP备案,否则无法保存。

回调地址的完整格式是在代码里拼出来的,例如:

http://auth.example.com/social/callback/wechat

注意,微信授权回调时只会走80或443端口,所以本地开发环境下比较麻烦。我在实践中常用的做法:本地改hosts,把正式域名指到127.0.0.1,然后在本机用Nginx监听80端口,转发到后端的8080端口。这样微信服务器能访问到域名,请求又能落到本地服务,联调效率高很多。

还有一个补充建议:在微信开放平台申请“高级接口权限”中的unionid获取权限。unionid可以让同一个微信用户在你名下的多个应用(公众号、小程序、网站应用)之间保持一致,当系统后续要扩展更多微信生态入口时,直接按unionid识别用户会比openid可靠得多。

1.3 RuoYi-Vue现有登录体系拆解

RuoYi-Vue的登录链路是理解第三方登录接入的关键。我以传统JWT版本为例说一下,新版如果使用的是Sa-Token版本,思路同样适用,只是token生成和校验的具体API不同。

默认情况下,前端login.vue把用户名密码提交到/login接口,流程是:

  1. SysLoginService.login方法接收用户名密码。
  2. 调用AuthenticationManager的authenticate方法,由Spring Security做密码校验。
  3. 校验通过后,加载用户的角色权限,构建一个LoginUser对象。
  4. 调用TokenService.createToken(loginUser),生成一串JWT,同时把用户信息写入Redis。
  5. 前端拿到token后保存到本地,之后每个请求都带上token,由JwtAuthenticationTokenFilter解析。

我们要接入第三方登录,最关键的一点是:把第1步和密码校验替换掉,但保留第3、4步。也就是说,微信用户信息拿到之后,如果查到已绑定系统用户,就直接构建对应的LoginUser,然后调用TokenService.createToken生成token。这样后续的请求认证、权限判断、操作日志等机制,完全复用RuoYi原有的逻辑。

另外要注意SecurityConfig里的白名单配置。RuoYi默认放行了/login、/captchaImage、/register等路径,微信登录的授权发起接口和回调接口必须单独加进白名单,否则会被Spring Security的过滤器拦截,导致明明回调到了后端却返回401。

1.4 方案选型:自研OAuth客户端还是用第三方封装库

这是集成前要想清楚的另一个问题。目前市面上有不少封装好的第三方登录SDK,最典型的是JustAuth,一个库就集成了微信、QQ、GitHub、Gitee等几十家平台。直接用集成库的好处是省事,接口统一,扩展平台时只需要加配置。

但我这次选择自己写微信OAuth客户端,原因有三个:

  1. 项目只需要微信一个平台,没必要引入一个膨胀的依赖。
  2. 微信扫码登录的接口非常稳定,参数也不复杂,自己写一遍反而能把OAuth2.0的原理彻底吃透。
  3. 自研代码便于在关键调用节点打印日志,排查问题时要清楚得多。

如果你的项目以后还要接多个平台,我建议在自研时预留好抽象的Service接口,例如:

public interface SocialLoginService { String buildAuthUrl(String state); SocialUserInfo getUserInfo(String code); }

微信、QQ、微博各自实现这个接口,上层业务调用的逻辑就完全不用改了。这样既保留了原理理解,又兼顾了以后的扩展性。

2. 数据库设计与后端OAuth2.0核心实现

2.1 第三方登录用户表设计思路

RuoYi-Vue的sys_user表是整个权限体系的核心,我不建议直接在这个表里加openid字段,理由很简单:一个系统用户可能绑定多个第三方平台账号,一个openid只属于某一个平台,直接在用户表上做字段会让表结构变得很糟糕,耦合度也高。

更合理的做法是新建一张独立的第三方用户绑定表,我命名为sys_social_user:

CREATE TABLE `sys_social_user` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', `user_id` bigint NOT NULL COMMENT '系统用户ID', `provider` varchar(32) NOT NULL COMMENT '第三方平台标识:wechat/qq/github', `openid` varchar(64) NOT NULL COMMENT '用户在第三方平台的openid', `unionid` varchar(64) DEFAULT NULL COMMENT '多应用下的unionid', `nickname` varchar(64) DEFAULT NULL COMMENT '第三方平台昵称', `avatar` varchar(255) DEFAULT NULL COMMENT '第三方平台头像', `create_time` datetime DEFAULT NULL COMMENT '绑定时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_provider_openid` (`provider`, `openid`) ) ENGINE=InnoDB COMMENT='第三方登录绑定表';

字段设计的几个要点:

  • provider加进去之后,这套表结构就能复用到多个平台,不需要每接一个平台就新建一张表。
  • provider+openid做联合唯一索引,保证同一个平台同一个用户只能有一条绑定记录。
  • unionid字段独立存,方便后续扩展同主体下的公众号、小程序应用时直接做用户关联。
  • user_id指向sys_user表的主键,这也是我们生成RuoYi登录token时的核心凭证。

这张表就是第三方登录“翻译”成系统登录身份的桥梁。后端拿到微信用户信息后,先查这张表,有记录就直接拿user_id去构建LoginUser,没记录就进入自动注册流程。

2.2 微信OAuth2.0服务封装与核心代码

后端我拆成了几个类,职责划分清晰一点,排查问题时心里有数。

首先是配置读取类:

@Component @ConfigurationProperties(prefix = "wechat.open") @Data public class WechatOpenProperties { private String appId; private String appSecret; private String redirectUri; }

配置文件里:

wechat: open: app-id: wx1234567890abcdef app-secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx redirect-uri: http://auth.example.com/social/callback/wechat

然后是微信API访问客户端,核心两个方法:构建授权地址、用code换取access_token、拉取用户信息。

@Service public class WechatOauthClient { private final WechatOpenProperties properties; public String buildAuthUrl(String state) { String redirectUri = URLEncoder.encode(properties.getRedirectUri(), StandardCharsets.UTF_8); return String.format( "https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_login&state=%s#wechat_redirect", properties.getAppId(), redirectUri, state); } public WechatAccessToken getAccessToken(String code) { String url = String.format( "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", properties.getAppId(), properties.getAppSecret(), code); RestTemplate restTemplate = new RestTemplate(); Map<String, String> result = restTemplate.getForObject(url, Map.class); if (result == null || result.containsKey("errcode")) { throw new RuntimeException("微信换取access_token失败: " + result); } WechatAccessToken token = new WechatAccessToken(); token.setAccessToken(result.get("access_token")); token.setOpenid(result.get("openid")); token.setUnionid(result.get("unionid")); return token; } public WechatUserInfo getUserInfo(String accessToken, String openid) { String url = String.format( "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s", accessToken, openid); RestTemplate restTemplate = new RestTemplate(); Map<String, String> result = restTemplate.getForObject(url, Map.class); if (result == null || result.containsKey("errcode")) { throw new RuntimeException("微信拉取用户信息失败: " + result); } WechatUserInfo userInfo = new WechatUserInfo(); userInfo.setOpenid(result.get("openid")); userInfo.setUnionid(result.get("unionid")); userInfo.setNickname(result.get("nickname")); userInfo.setAvatar(result.get("headimgurl")); return userInfo; } }

这段代码有两个细节容易被忽略,我在集成时都遇到过:

  • 回调时微信传过来的code只能用一次,而且有效期很短,所以拿到code后必须立即换token,不能做缓存,也不能反复使用同一个code去请求。
  • 微信的用户信息接口使用的access_token是授权接口返回的那个snsapi_access_token,不是普通接口的全局token,不能混用。

2.3 回调接口与首次登录自动注册策略

前端拿到state,我们需要在发起登录时把它存到Redis里,回调过来先校验,验证通过才能继续流程,防止CSRF攻击。

举个例子,发起授权的接口可以这样设计:

@GetMapping("/social/render/wechat") public AjaxResult renderWechat() { String state = UUID.randomUUID().toString().replace("-", ""); redisCache.setCacheObject("social_state:" + state, "wechat", 10 * 60 * 1000L); WechatOauthClient client = ...; return AjaxResult.success("success", client.buildAuthUrl(state)); }

注意这个接口返回到是授权URL,前端拿到后直接赋值给window.location.href跳转。也可以直接返回redirect:前缀由后端302,但前后端分离情况下我倾向返回JSON,让前端控制跳转,这样便于在跳转前追加一些统计埋点。

回调接口的流程:

@GetMapping("/social/callback/wechat") public void callback(String code, String state, HttpServletResponse response) { // 1. 校验state String savedState = redisCache.getCacheObject("social_state:" + state); if (savedState == null) { throw new ServiceException("state校验失败,疑似跨站请求"); } redisCache.deleteObject("social_state:" + state); // 2. code换取token和用户信息 WechatAccessToken token = wechatOauthClient.getAccessToken(code); WechatUserInfo userInfo = wechatOauthClient.getUserInfo(token.getAccessToken(), token.getOpenid()); // 3. 查询绑定关系,没有则自动注册 SysSocialUser socialUser = sysSocialUserService.findByProviderAndOpenid("wechat", userInfo.getOpenid()); SysUser sysUser; if (socialUser != null) { sysUser = sysUserService.selectUserById(socialUser.getUserId()); } else { sysUser = registerNewUser(userInfo); sysSocialUserService.bindUser("wechat", userInfo, sysUser.getUserId(), token.getUnionid()); } // 4. 构建LoginUser并生成token LoginUser loginUser = new LoginUser(sysUser, null); String token = tokenService.createToken(loginUser); // 5. 重定向到前端并携带token response.sendRedirect("http://front.example.com/social-callback?token=" + token); }

自动注册新用户时有一个坑:微信昵称可能是乱七八糟的emoji,甚至包含特殊字符,直接作为sys_user的user_name使用可能触发数据库字段长度或字符集问题。我处理的方式是用一个统一前缀加时间戳生成系统用户名,例如wx_20250101120000_8888,而把微信昵称只存到sys_social_user表里作为展示用。这样避免后续如果要走用户名密码登录逻辑时,还要去处理昵称重复和非法字符的问题。

新用户默认角色怎么定,取决于项目需求。我这边是给扫码登录用户默认分配一个“普通用户”角色,通过sys_user_role表插入数据即可。管理员后续可以在用户管理后台手动调整角色。

2.4 生成的token如何融入RuoYi-Vue权限体系

这一步是整个接入过程最关键但也是最少被人讲清楚的地方。

RuoYi-Vue中,TokenService.createToken(LoginUser)做的事情是:生成一个带uuid的token字符串,把LoginUser序列化后存储到Redis,key通常是login_tokens:uuid,然后把token以JWT的形式返回给前端。之后每次请求,JwtAuthenticationTokenFilter都会解析请求头里的Authorization,取出token字符串,去Redis里查LoginUser,再交给Spring Security的SecurityContextHolder完成认证。

所以第三方登录接入时,只要我们在回调里成功构造出LoginUser并调用createToken,后续的鉴权逻辑就和用户名密码登录完全一致了。这也是为什么我在前面强调要复用原框架的token生成机制,千万不要自己再去生成一套独立的session token,否则前端请求需要做两套认证逻辑,维护成本直接翻倍。

还要提醒一点:如果项目里改了SecurityUtils.getLoginUser()的获取逻辑,或者在过滤器里额外校验了登录用户类型,第三方登录生成token时也要对应处理。RuoYi-Vue原版LoginUser构造函数需要传入SysUser,权限集通过SysPermissionService.getMenuPermission和SysRoleService.selectRolePermissionByUserId加载。回调注册用户时,记得先插入角色关联,否则新用户登录后连基本菜单都看不到,表现就是登录成功但页面一片空白。

3. 前端对接微信登录与回调状态处理

3.1 登录页增加微信扫码入口

RuoYi-Vue的登录页逻辑很简单,核心就是调用store.dispatch('Login', ...)。加微信入口只需要在原来的登录表单下面放一个“微信登录”按钮,点击后调后端接口拿授权URL,然后跳转:

handleWechatLogin() { getWechatRenderUrl().then((res) => { window.location.href = res.url; }); }

这里需要注意一个体验问题:最好在点击按钮后先禁用按钮,防止用户连续点击导致生成多个state,污染Redis里的会话状态。我加了一个loading状态,跳转前再恢复。

3.2 前端回调页处理token

微信授权完成之后,后端会把用户重定向到我们指定的前端地址,形如:

http://front.example.com/social-callback?token=xxx

前端需要新建一个social-callback页面,这个页面不需要任何UI,它只做一件事:从URL参数中读取token,存储到Cookie,然后调一次用户信息接口,再跳转到系统首页。

const token = getQueryVariable('token'); if (token) { setToken(token); await store.dispatch('GetInfo'); router.push('/'); }

这里有一个顺序陷阱:RuoYi-Vue的GetInfo会调用后端接口获取用户信息,并把用户信息保存到Vuex里,同时前端路由守卫依赖store.getters.roles来判断是否已初始化。如果不调GetInfo直接跳转,路由守卫可能会误判为未登录,再次把用户踢回登录页。

如果后端接口返回AjaxResult结构,前端解析时注意用框架封装好的request.js,它已经统一处理了code和msg字段,不要用原生的fetch或者axios去裸调,否则token过期时的统一拦截逻辑会失效。

3.3 第三方登录状态的持久化与用户中心绑定

登录成功后,用户后续的操作都走RuoYi原有的token鉴权,我们不需要在前端做任何额外的登录状态管理。

但还有一个场景要处理好:用户已经通过微信扫码自动注册了这一套账号,但他想绑定自己已有的系统账号。这种绑定操作一般放在个人中心里,入口是“绑定微信账号”。

绑定流程如下:

  1. 用户先在自己系统里正常登录。
  2. 点击“绑定微信”按钮,后端生成一个新的state和授权URL,前端跳转微信扫码。
  3. 回调时后端发现sys_social_user里还没有记录,但当前请求上下文中用户已登录,于是把user_id写入绑定表,而不是自动注册新用户。

这个逻辑关键在于回调接口要能区分两个场景:是登录页发起的登录流程,还是个人中心发起的绑定流程。我的做法是在生成state时附加一个场景标记,例如Redis的value存login:wechat或bind:wechat,回调时根据标记决定走登录逻辑还是绑定逻辑。

3.4 多平台扩展时的前端适配

如果以后想再加QQ登录、GitHub登录,前端登录页除了增加一个按钮,还需要注意一点:多个平台的回调页可以共用一个social-callback,因为token的生成逻辑和后端统一,前端根本不需要关心具体走的是哪个平台。对于后端,只需要把provider参数区分开即可。

我在设计时把授权接口统一成了/social/render/{provider},回调接口统一成/social/callback/{provider},这样每新增一个平台,前端几乎不用改,后端也只需要增加一个SocialLoginService实现类和一行路由映射。

4. 安全加固与线上部署注意事项

4.1 state参数防CSRF的细节

前面已经提到我用了Redis保存state,但这还不够。在实际操作中,我遇到过一个边界情况:用户打开了微信二维码页面,放了一段时间才扫码,导致Redis里的state已经过期。这时候回调过来就会校验失败,用户体验很差。

解决方法是把state的过期时间放宽到15分钟,并配合提示信息让用户重新发起登录。另外,state校验应该在Redis里做原子删除,避免同一个state被并发消费两次。RuoYi的RedisCache封装默认提供deleteObject方法,但它是先取值再删除,严格来说不是原子的。我自己的处理是在校验时先删除再取返回值:

Object savedState = redisCache.deleteObject("social_state:" + state); if (savedState == null) { throw new ServiceException("state校验失败"); }

即使极端情况下两个并发请求同时过来,只有一个请求能拿到删除前的值,另一个会得到null,这样保证了state不会被重复使用。

4.2 回调地址的环境隔离与服务器部署

微信开放平台后台配置的回调域名是全局生效的,如果在本地调试时随便换个回调地址,微信会直接拒绝访问。我的经验是:

  • 生产环境使用独立的认证域名,正式域名只配置一个,避免混淆。
  • 本地调试通过改hosts实现,把认证域名解析到127.0.0.1,再用Nginx将80端口转发到本地后端服务。
  • 前后端分离部署时,回调地址需要指定到后端服务域名或网关域名,不要直接指到前端页面地址。后端回调接口收到微信请求之后,再通过sendRedirect把我们自己的token带到前端。

这样一个链路下来,微信侧只会与后端域名交互,前端和后端之间通过我们自己控制的URL传递登录结果,逻辑最清晰。

4.3 微信接口调用的异常容错

微信开放平台的接口偶尔会出现超时或返回系统繁忙错误,这在用户扫码高峰期并不罕见。我在实现时给所有微信HTTP调用加了一层超时控制,RestTemplate如果直接new出来,默认的SimpleClientHttpRequestFactory没有超时限制,会导致线程被外部接口卡住。下面是具体的超时配置:

@Bean public RestTemplate wechatRestTemplate() { SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(5000); factory.setReadTimeout(5000); return new RestTemplate(factory); }

同时在回调接口的入口处做了全局异常捕获,如果是微信侧异常,不要让用户看到一堆堆栈信息,直接重定向到前端的一个错误页面,并提示“微信授权失败,请稍后再试”。用户看到的永远是一个可理解的页面,而不是504或500。

4.4 日志打印与用户轨迹追踪

OAuth2.0的整个链路跨了两套系统,排查问题几乎全靠日志。我在回调接口里给每一步加了结构化日志,包括回调参数、code长度、state校验结果、微信返回的openid、用户注册方式、token生成状态等。

有一条经验相当重要:在日志中不要打印完整的appsecret!我会把敏感字段做脱敏处理,只保留后四位。否则一旦日志平台被扫描到,密钥就全暴露了。同样道理,回调URL拼出来的时候也不要记录完整state,这对排查意义不大,却属于敏感参数。

5. 常见问题与排查技巧实录

5.1 微信回调报错:redirect_uri参数错误

这个应该是接入过程中出现频率最高的错误。表面看是URL拼错了,但实际上大多数情况是三个原因之一:

  • 微信开放平台后台回调域名填写错误,与代码里的redirect_uri域名不一致。记住,后台只填域名,不带协议和路径。
  • 拼URL时没有对redirect_uri做URL编码,微信服务器解析的时候把参数搞混了。
  • 本地调试时用IP或带端口地址,微信默认拦截非备案域名。

排查顺序:先确认后台配置的域名,再确认拼出的URL编码是否正确,最后看浏览器实际跳转时输出了什么。

5.2 提示:state值不匹配或过期

如果用户从点登录到扫码间隔时间过长,就会出现这个提示。从代码层面排查时,先确认Redis里有没有存state,再确认取state和删state之间的逻辑顺序是否正确。

还有另一种情况:前端跳转时用了浏览器的预加载机制,导致同一个授权URL被请求了两次,第二次生成的state覆盖了第一次,第一次的回调过来就校验失败了。这种情况我在移动端WebView上遇到过,解决方法是后端生成state时直接用UUID,并且不要把state放在URL的query里由前端反复读取后再次拼接,前端只负责整体跳转,不要对URL做二次处理。

5.3 通过code换取access_token返回40029

这个错误码表示code无效。常见原因是同一个code被重复使用过一次了。微信的code是一次性的,第一次调用成功后立即失效,后续再用必然报错。如果业务逻辑里有重试机制,要对这个接口做幂等保护,比如前端回调时加一个“处理中”的防重复点击状态。

5.4 扫码登录成功后前端空白或404

这个问题的根因几乎都是token拿到了,但用户信息没拉取到,或者路由守卫拦截了。需要一步步排查:

  1. 打开浏览器控制台,看GetInfo请求是否返回200。
  2. 看store.getters.roles是否被正确设置,如果角色数组为空,路由会认为没有权限,直接跳回登录页。
  3. 如果新注册用户看不到菜单,检查sys_user_role表是否插入了角色关联,以及角色的菜单权限是否配置。

5.5 微信用户信息里没有unionid

如果之前没有申请unionid权限,或者应用没有通过认证,unionid字段可能返回为空。这时候以openid作为唯一关联键即可,但要注意两个不同开发者的应用可能不共享unionid体系。如果需要跨应用识别,必须申请并完成微信开放平台的开发者资质认证。

5.6 登录成功但系统提示账号已锁定或停用

自动注册的微信用户默认状态可能是正常的,但如果项目里sys_user表增加了额外的状态字段,比如需要管理员审核激活,那么自动注册逻辑里也必须同步设置这些字段。我在项目里遇到过一个问题:注册用户后没有初始化默认密码的加盐字段,导致有的地方反查用户信息时出现了空指针。所以在自动注册新用户时,尽量把sys_user表的关键必填字段都补齐,包括密码、加盐、状态、创建时间等。

5.7 前端回调页被微信内置浏览器拦截

部分App的内置WebView对跨域跳转有限制,后端sendRedirect到前端域名时可能出现白屏。稳妥的做法是回调时可以返回一张极简HTML页面,由页面里的脚本从URL参数中取出token再执行跳转,而不是依赖HTTP 302。这种方式兼顾了普通浏览器和WebView的情况。

写在最后的实操体会

把RuoYi-Vue和微信登录整个接完之后,我最深的体会是:第三方登录本身并不是多复杂的事,难点在于两个系统之间的状态转换和上下文衔接。OAuth2.0的授权码模式只要自己动手走一遍,很多概念自然就通了;而RuoYi-Vue的登录链路只要理清TokenService.createToken这一步,后面所有扩展都会变得很顺手。

如果重新做一次,我大概会先把时序图画完整,把state流转、code失效、token生命周期这些边界条件想清楚,再动手写代码。另外,尽量不要在项目里同时混用两套token体系,哪怕第三方接入的代码已经写好,也不要为了省事自创一套认证逻辑,否则后续维护的代价很高。

最后再补一句经验之谈:微信开放平台的接口返回有很强的时效性,调试过程中一旦某项配置做了调整,比如回调域名、释放回调接口、重新获取appsecret,都要清掉浏览器缓存或换一个无痕窗口再测一遍,很多时候查了半天代码,其实是旧配置没有刷新。希望这篇集成记录能帮你少走一些弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询