恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

微信扫码登录Spring Boot实现:OAuth2.0授权回调与登录态封装全攻略

  • 首页
  • 资讯中心
  • /
  • 微信扫码登录Spring Boot实现:OAuth2.0授权回调与登录态封装全攻略

相关资讯

DS90UB947 Linux驱动实战:FPD-Link III串行器内核适配与设备树绑定 2026/10/12 6:34:08
抖音式上下滑动视频的工程实现与性能避坑指南 2026/10/12 6:29:07
Linux下RAR命令行工具rarlinux部署与实战指南 2026/10/12 6:29:07

最新资讯

WASI 文件系统路径解析与沙箱机制深度剖析:从 openat 手动算法到 openat2 内核原语
基于Django+Vue.js的租房推荐系统设计与实现
AnyPS5项目解析:技术定位与合规开发边界
4个工具型网站帮你快速读懂陌生项目源码
智能桌面宠物开发实战:从悬浮窗透明到AI对话的完整工程路径
双离线支付技术拆解:原理、风险与测试方案

今日推荐

Debian新手入门:从部署到日常操作的完整指南
MongoDB复制集扩缩容实战:从rs.add到选主事故复盘
条形码目标检测数据集实战:从YOLOv8训练到部署

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

微信扫码登录Spring Boot实现:OAuth2.0授权回调与登录态封装全攻略

发布时间:2026/10/12 6:34:08
微信扫码登录Spring Boot实现:OAuth2.0授权回调与登录态封装全攻略 简介面向需要使用微信开放平台完成用户免密登录的Java开发人员这套基于SpringBoot的扫码登录项目演示了从获取二维码、接收授权code、换取access_token/openid到获取用户信息并完成本地登录的完整链路。工程以16个class、15个java为主要源码辅以properties、xml配置及Spring Security相关资源便于理解OAuth 2.0协议与微信Java SDK的配合方式项目还包含JWT令牌生成、状态码校验、回调地址管理等安全细节适合作为企业Web应用对接微信扫码功能的起步模板。压缩包共121个文件约172KB结构紧凑可直接导入IDE查看运行。已有11382人学习下载适合具备SpringBoot基础、希望快速掌握微信扫码登录落地方法的开发者参考。1. 微信扫码登录的工程本质一次 OAuth2.0 授权回调而不是黑匣子微信扫码登录在 Web 端的接入频率很高但我每次接手相关需求都会先确认一件事对方说的“微信登录”是公众平台网页授权还是开放平台扫码登录。两者都是 OAuth2.0 授权码流程但接口域名、scope 参数、回调配置完全不同混着用会得到一堆意想不到的错误码。微信扫码登录的本质是用户在 PC 端看到一个二维码用微信确认授权后微信把授权结果回调到你的后端后端用 code 换取 access_token再拉取 openid 和用户资料最终映射成自建登录态。下面以 Spring Boot 2.x 为开发背景从开放平台配置讲到回调换码、获取用户信息的完整代码链路并整理接入中容易踩的几个坑适合正在给 Web 端接入微信扫码登录、以及打算把微信账号体系和自建账号体系打通的开发者。2. 开放平台配置细节AppID、回调域与授权链接的三个关键参数接入微信扫码登录的第一步不是写代码而是先把开放平台后台的配置铺平。后台的差错会直接放大到代码层这里填错一个字符后面接口再完美也白搭。2.1 先分清开发平台网站应用和公众号应用不是一回事微信公众平台和微信开放平台是两个独立的开发者平台账号体系不互通。公众平台里的网页授权是给公众号内 H5 页面用的授权结果拿到的是公众号视角下的 openid开放平台里的网站应用是给 PC 网站扫码登录用的接口域名是 api.weixin.qq.comscope 固定为 snsapi_login。把这两套体系分开理解新手接入时的很多困惑就能解开。最常见的问题是拿公众号的 AppID 去调扫码接口微信返回 40125 invalid secret或者一直提示 redirect_uri 不合法。开放平台的网站应用创建流程并不复杂注册开发者账号创建应用填写应用名称、简介、官网地址和应用截图提交后等审核。审核通过后分配正式的 AppID 和 AppSecret。个人开发者也能创建网站应用只是不同类型的资质要求不一样审核周期也略有差异一般一两个工作日能出结果。关于 AppSecret有一点要提前说它只在创建时完整展示一次之后只能通过重置的方式重新生成。重置后旧 secret 立即失效线上服务如果没有同步新值扫码登录会集体报 40125。我习惯在配置中心单独开一个命名空间把公众号和开放平台的密钥分成两个条目管理避免换项目时拿错。注意开放平台后台的授权回调域只填域名不要带协议头和端口。2.2 授权回调域不是填完整 URL而是域名加校验文件开放平台后台的“网站应用—授权回调域”设置填的是域名不是带协议头的完整链接比如 login-api.example.com。第一次填写时微信会要求下载一个 txt 校验文件把它放到该域名服务器的 Web 根目录确保能直接访问到文件内容再回后台点击确认。这一步校验的是域名归属不校验子路径所以不要把它放到二级目录里。校验通过后实际回调地址由自己拼接路径可以任意比如 https://login-api.example.com/wechat/callback但域名部分必须和后台填写的完全一致。协议头可以用 http 也可以用 https端口则被限制在 80 和 443。如果你在本地起了 8080 端口微信服务器无法回调进来扫码后页面会一直停留在授权完成状态后端却收不到任何请求。很多团队卡在这一步开发环境没有公网域名怎么办。我常用的做法是准备一台公网测试机把回调域名解析到测试机本地代码打包上去跑日志打全联调完再撤。这样虽然多花几分钟但比在本机用各种别扭的方式模拟回调要省心得多。另外回调地址里的路径不需要在后台登记后台只校验域名归属路径完全由自己的应用控制。这一点和公众平台的网页授权域名逻辑类似但开放平台校验的是域名所有权不校验具体目录。2.3 授权链接拼接scope 固定为 snsapi_loginredirect_uri 要编码开放平台扫码登录的授权链接格式是固定的https://open.weixin.qq.com/connect/qrconnect?appidAPPIDredirect_uriREDIRECT_URIresponse_typecodescopesnsapi_loginstateSTATE#wechat_redirect参数拆解如下appid 用开放平台网站应用的 AppID公众号的拿过来无效。redirect_uri 是用户授权后跳回后端的地址必须进行 URL 编码否则链接里的参数可能被截断。编码前域名要和后台授权回调域一致。response_type 固定为 code表示走授权码模式。scope 固定为 snsapi_login这是开放平台扫码登录的专用值。state 由开发者生成要保证随机性并在本次请求生命周期内不变回调时用来校验来源。有一条经验分享二维码不能直接拿img标签指向这个授权链接。浏览器直接打开授权链接会看到微信的授权页面或提示页而不是一个可扫描的二维码。产品层面需要在前端用 qrcode 类组件把这个链接渲染成二维码图片或者把链接交给扫码组件处理。项目里最后选了前者用户点击“微信登录”后弹出层内展示二维码扫码动作完成前二维码自动定时刷新防止过期。配置项正确写法易错点AppID开放平台网站应用的 AppID误用公众号/小程序 AppIDAppSecret对应网站应用的 secret重置后旧 secret 立即失效授权回调域api.example.com填了 https:// 或带了端口校验文件放在域名的根目录放到了子目录导致验证失败回调地址/wechat/callback 任意路径域名必须与后台完全一致2.4 本地调试环境的妥协方案回到端口限制的问题我补充一种我常用的部署结构测试环境单独分配一个域名例如 wechat-test.example.com开放平台的授权回调域直接填这个测试域名。申请一个 80 或 443 端口的 Nginx 站点把 Spring Boot 服务挂在同机监听Nginx 转发到应用端口。这样微信回调请求进来时链路是完整的和线上一致只是请求的是测试应用而已。这样的妥协方案会带来一点点不便所有调试都要在测试机上看日志但换来的是扫码流程的端到端可验证而不是自己在本地 mock 一个回调。接口的时序、code 的一次性、token 的有效期这些都要真实验证才算数。我个人的习惯是本地保留一套完全 mock 的测试用例只验证 Service 层逻辑联调和验签则全部依赖测试环境两套东西互不干扰。3. 扫码流程的 Spring Boot 实现生成授权链接、回调换码与用户信息获取把后台配置做完代码实现就水到渠成了。我会按 Service 和 Controller 两层来组织先讲微信侧接口调用再讲业务侧接入。这里先说明一个选型问题为什么用 RestTemplate 而不是 OkHttp 或 WebClient因为微信扫码登录涉及到的接口都是简单 GET 请求不需要连接池、不需要异步回调RestTemplate 作为 Spring 内置客户端足够用少引入一个依赖将来维护成本也更低。3.1 授权链接生成让前端拿去渲染二维码先建一个配置类把微信开放平台的参数收拢起来别在业务代码里散落一堆魔法值Data ConfigurationProperties(prefix wechat.login) public class WechatLoginProperties { /** 开放平台网站应用的 AppID */ private String appId; /** 对应的 AppSecret */ private String secret; /** 扫码授权后的回调地址 */ private String redirectUri; }wechat: login: app-id: wx1234567890abcdef secret: 你的应用密钥 redirect-uri: https://login-api.example.com/wechat/callback这里有两个容易犯错的点。第一appId 看起来像数字但它是字符串千万别用 Long 或者 Integer 去接收。第二redirect-uri 必须和开放平台后台的授权回调域保持同域否则微信在扫码后跳转时直接提示 redirect_uri 参数错误。生成授权链接的方法放到 WechatLoginService 里Service public class WechatLoginService { private final RestTemplate restTemplate new RestTemplate(); private final WechatLoginProperties props; public WechatLoginService(WechatLoginProperties props) { this.props props; } /** 构造微信扫码授权链接 */ public String buildQrConnectUrl(String state) { String encodedRedirectUri URLEncoder.encode(props.getRedirectUri(), StandardCharsets.UTF_8); return String.format( https://open.weixin.qq.com/connect/qrconnect?appid%sredirect_uri%sresponse_typecodescopesnsapi_loginstate%s#wechat_redirect, props.getAppId(), encodedRedirectUri, state ); } }逻辑说明redirect_uri 必须编码否则链接里出现 时微信会把它当成参数分隔符导致回调地址参数丢失。state 是外部传入的Controller 里生成后先存缓存再传进来拼接这样回调时能取出来比对。参数方面scope 固定是 snsapi_login不要改成 snsapi_userinfo开放平台不支持。response_type 固定是 code微信才会在回调里带上授权码而不是直接返回 token。3.2 回调接口先用 code 换 access_token用户扫码确认后微信会重定向到回调地址带两个参数code 和 state。后端第一步是校验 state第二步就是用 code 换 access_token。这里先写一个数据模型Data public class WechatOauthToken { private String access_token; private Integer expires_in; private String refresh_token; private String openid; private String scope; private String unionid; private Integer errcode; private String errmsg; }为什么字段名不改成驼峰因为微信返回的 JSON 就是 snake_case用 JsonProperty 也能映射但直接沿用微信文档的字段名反序列化不容易出错换来换去反而容易漏。errmsg 是错误码正常响应里没有这个字段所以在交换 token 之后要检查一下 errcode 是否为 null。换 token 的方法public WechatOauthToken exchangeToken(String code) { String url String.format( https://api.weixin.qq.com/sns/oauth2/access_token?appid%ssecret%scode%sgrant_typeauthorization_code, props.getAppId(), props.getSecret(), code ); WechatOauthToken token restTemplate.getForObject(url, WechatOauthToken.class); if (token null || token.getErrcode() ! null) { throw new WechatLoginException(微信换取 access_token 失败: token); } return token; }逻辑说明grant_type 固定为 authorization_code微信文档里没有其他可选项。code 只能用一次一次交换完成后立即作废重复使用同一 code 会返回 40029。access_token 有效期 7200 秒refresh_token 有效期 30 天但在扫码登录这种一次性授权场景里我们拿到用户信息之后 token 就没用了不需要实现刷新逻辑。另外一个细节RestTemplate 默认的 SimpleClientHttpRequestFactory 在 GET 请求里会把 url 里的中文字符自动转义但如果回调参数里带了特殊字符建议统一用 UriComponentsBuilder 来构造。上面的 String.format 写法方便阅读生产环境我会换成 UriComponentsBuilder并设置 UTF-8 编码。3.3 获取用户信息openid、unionid、头像一个都不能漏换到 access_token 后马上请求用户信息接口public WechatUserInfo getUserInfo(String accessToken, String openid) { String url String.format( https://api.weixin.qq.com/sns/userinfo?access_token%sopenid%s, accessToken, openid ); WechatUserInfo userInfo restTemplate.getForObject(url, WechatUserInfo.class); if (userInfo null || userInfo.getErrcode() ! null) { throw new WechatLoginException(获取微信用户信息失败: userInfo); } return userInfo; }用户信息字段字段含义注意事项openid应用维度唯一标识换 AppID 后会变unionid开放平台账号统一标识绑定公众号/小程序后才返回nickname昵称可能有 emoji建表用 utf8mb4headimgurl头像 URL存库前建议转存到自己服务器province/city/country地区信息可能为空这里要解释一下 openid 和 unionid 的关系。openid 是用户在当前 AppID 下的唯一标识如果以后换了一个开放平台应用openid 就变了。unionid 是用户在同一个开放平台账号下所有应用的统一标识但前提是这些应用都要绑定到同一个开放平台账号下并且用户至少使用过其中的公众号或小程序。如果你的产品同时有 PC 网站、公众号和 App 小程序端最好用 unionid 作为用户主键这样各端数据能打通。关于 headimgurl微信 CDN 上的地址默认带一个尺寸参数直接存库问题不大但保存时间久了可能失效。我一般会在登录成功后把它抓下来转存到自己服务器的存储路径同时在库里保留原始地址字段用于排查。昵称里的 emoji 也是高频坑建表字符集如果用 utf8 会报错甚至存成问号用 utf8mb4 才能完整保存四字节字符。4. 登录态的打通与封装Controller 分层、user 映射与 token 生成微信侧的三次请求都封装好后真正落到业务系统的是最后两步把微信用户映射成本地用户生成登录态。这一步做得干净后续接小程序或者公众号登录时也能复用同一套账号体系。4.1 Controller 层只做编排不写微信参数Controller 拆成两个接口一个生成二维码链接一个处理微信回调RestController RequestMapping(/wechat) RequiredArgsConstructor public class WechatLoginController { private final WechatLoginService wechatLoginService; private final LocalUserService userService; private final LoginTokenService loginTokenService; private final RedisTemplateString, String redisTemplate; /** 前端拿这个链接去渲染二维码 */ GetMapping(/qr-url) public String qrUrl() { String state UUID.randomUUID().toString().replace(-, ); redisTemplate.opsForValue().set(wx:state: state, 1, Duration.ofMinutes(10)); return wechatLoginService.buildQrConnectUrl(state); } /** 微信扫码后回调 */ GetMapping(/callback) public String callback(RequestParam String code, RequestParam String state, HttpServletResponse response) throws IOException { // 1. 校验 state防止 CSRF String cacheKey wx:state: state; if (Boolean.FALSE.equals(redisTemplate.hasKey(cacheKey))) { throw new WechatLoginException(state 校验失败); } redisTemplate.delete(cacheKey); // 2. 换 token拿用户信息 WechatOauthToken oauthToken wechatLoginService.exchangeToken(code); WechatUserInfo userInfo wechatLoginService.getUserInfo(oauthToken.getAccess_token(), oauthToken.getOpenid()); // 3. 映射本地用户并生成登录态 LocalUser localUser userService.findOrCreateByOpenid( oauthToken.getOpenid(), oauthToken.getUnionid(), userInfo ); String token loginTokenService.generate(localUser.getId()); response.sendRedirect(/#/login?token token); return null; } }逻辑说明state 的存储约定是 10 分钟过期回调校验通过后立刻删除保证一次性使用。redisTemplate.hasKey 不要直接用 ! 取反因为 can还返回 null用 Boolean.FALSE.equals 包一下就安全了。code 换 token 和拉用户信息两步合在一起虽然也能拆成异步但扫码登录这种低频操作同步处理更简单微信接口本身也就几百毫秒的延迟不需要额外引入消息队列。回调里最终发起重定向把生成的登录 token 放在 URL 的 query 参数中前端在登录页读取后存入 localStorage 或 cookie。这种做法的好处是分离了微信域和业务域后续页面切换时只需要关心自己的 token。4.2 用户表设计openid 做唯一索引字符集用 utf8mb4数据库表结构参考CREATE TABLE t_wechat_user ( id bigint NOT NULL AUTO_INCREMENT, openid varchar(64) NOT NULL, unionid varchar(64) DEFAULT , nickname varchar(64) DEFAULT , avatar_url varchar(500) DEFAULT , created_at datetime DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_openid (openid) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这里的关键点openid 字段一定要加唯一索引findOrCreate 逻辑依赖这个约束来做并发防重。unionid 只作为普通索引因为不是所有用户都有 unionid空字符串允许重复。nickname 用 varchar(64)有的昵称包含中文加 emoji64 字符在 utf8mb4 下通常够用。avatar_url 留 500微信头像地址带参数时确实比较长。4.3 首登注册按 openid 维度做一次查询findOrCreateByOpenid 的实现思路值得单独说一下public LocalUser findOrCreateByOpenid(String openid, String unionid, WechatUserInfo userInfo) { LocalUser user userMapper.selectByOpenid(openid); if (user ! null) { // 老用户每次登录都刷新一下昵称和头像避免资料过期 user.setNickname(userInfo.getNickname()); user.setAvatarUrl(userInfo.getHeadimgurl()); userMapper.updateById(user); return user; } // 新用户用 openid 落库unionid 为空时存空串 LocalUser newUser new LocalUser(); newUser.setOpenid(openid); newUser.setUnionid(unionid null ? : unionid); newUser.setNickname(userInfo.getNickname()); newUser.setAvatarUrl(userInfo.getHeadimgurl()); userMapper.insert(newUser); return newUser; }说明首次登录的注册动作很简单不需要填手机号因为微信已经提供了身份信息。如果产品要求强制绑定手机号可以在登录成功后弹一个绑定页面把 openid 暂存在缓存里绑定完成后再写用户表。我见过一个项目他们会在扫码前先把用户建出来等回调回来再补资料结果产生大量只有 openid 的僵尸账号。更合理的方式是回调确认成功之后再落库这样用户至少是完整身份。4.4 登录态生成用自包含 token 而不是长 Session重定向携带 token 到前端时token 本身就是一个自包含的登录凭证。用 JWT 实现很简单把 userId 和过期时间放进去签名用应用自己的密钥。生成 Token 后回调接口把 token 拼在重定向 URL 里前端解析后保存后续请求在 Header 带上即可。public String generate(Long userId) { long expireAt System.currentTimeMillis() 7 * 24 * 60 * 60 * 1000L; String payload userId : expireAt; // 用应用密钥做签名防止篡改生产环境建议用成熟 JWT 库 String sign DigestUtils.sha256Hex(payload secretKey); return Base64.getUrlEncoder().encodeToString((payload . sign).getBytes(StandardCharsets.UTF_8)); }参数说明这里只做演示把 userId 和过期时间拼起来再做一次签名校验能挡住大部分篡改请求。生产环境其实没必要自己造轮子直接用成熟的 JWT 库把 userId 放进 subject 或自定义 claim用 HS256 签名即可。签名的密钥要和微信的 AppSecret 分开管理别混用否则微信侧密钥泄露会连累业务侧 token 安全。5. 微信扫码登录避坑记录五个真实翻车点与排查方式上面的流程在一个项目里跑通之后踩过的坑有一大半都能归到“微信文档没说清”。以下五条是我认为最值得提前记住的每条按现象、原因、解决三部分展开。5.1 code 被重复消费第二次回调报 40029现象回调接口处理成功后用户手一抖刷新了页面或者前端重试了一次请求第二次请求报 40029 invalid code。原因微信的 code 是一次性的换完 token 之后就作废。刷新页面会重新发起 callback参数还是同一个 code第二次必然失败。解决在回调逻辑里成功写入用户信息后立即重定向到业务页并携带自家 token。这样浏览器地址栏替换成业务页地址微信回调地址被挤掉刷新也只是刷新业务页。如果在这之前就收到重复 code可以在 Redis 里对 code 做临时去重key 是 codevalue 是已消费标记TTL 设置五分钟超时自动清理。5.2 state 校验失败登录一直跳回错误页现象回调接口报 state 校验失败或者扫码完成后莫名其妙回到首页。原因state 的生成和校验如果依赖 HttpSession项目一旦拆成多实例部署session 不共享第二个实例上校验自然失败。还有一种情况用户开了多个页面最早生成的 state 被后续页面的 state 覆盖回调对应不上。解决不要依赖单机 Session用 Redis 按 state 存一个带过期时间的占位符。生成后存进缓存回调时判断存在才放行用完即删。state 里可以再包一层随机数和时间戳提高复杂度避免被猜出来。多实例部署时Redis 是共享的天然不会出现上面说的 session 不互通问题。5.3 redirect_uri 参数错误或者回调 URL 里 code 丢失现象微信授权页面提示 redirect_uri 参数错误或者扫码后跳回的回调 URL 里 code 参数缺了一半。原因后台授权回调域填了协议头或端口微信校验失败或者 redirect_uri 没有做完整 URL 编码链接里带 或 ? 时被提前截断code 参数因此丢失。解决先核对后台填的域名去掉协议头和端口只填 domain。再用 URLEncoder.encode 对 redirect_uri 完整编码编码后再拼接到授权链接里。调通以后可以加一条测试用例把生成的授权链接整个打印出来人工核对参数顺序确认 redirect_uri 后面没有混入其他参数。5.4 unionid 返回为空跨端账号体系建不起来现象拉取用户信息后 unionid 是 null导致按 unionid 维度建立账号体系的方案失效。原因开放平台的 unionid 只有在同一开放平台账号下绑定了已认证的公众号或小程序且用户至少关注过其中一个的情况下才会返回。只创建了网站应用没有绑过公众号unionid 大概率是空。解决如果只需要 PC 端登录直接用 openid 作为用户主键就够。如果确实要跨端统一先在开放平台后台把公众号和小程序都绑到同一个账号下绑定关系生效后再用 unionid 走统一流程。这里要注意绑定完成后老用户只有在再次授权时才会补齐 unionid存量数据需要做一轮补偿更新。5.5 授权链接在 PC 端打不开或白屏现象前端把授权链接放进二维码组件扫码后用手机打开页面提示“请在微信客户端打开链接”或白屏。原因这里要区分开两个概念。开放平台扫码链接是给 PC 端浏览器展示二维码用的不是给手机端直接访问的。如果直接把授权链接作为二维码内容用户用微信扫出来的就是授权链接微信内置浏览器反而不认大概率白屏或报错。解决PC 端页面先把授权链接转换成二维码用户用微信扫这个二维码时微信服务器识别的是授权链接并引导授权授权完成后再跳转回调地址。真正要确保的是授权链接本身可以被微信域名正确解析而不是把链接放到img或者 a 标签里直接打开。6. 进阶技巧把扫码登录封装成一次配置就能运行的登录模板考虑到接入微信扫码的步骤虽然不多但代码链路在多个项目里都是同一套我后来把它抽象成了一个模板类业务系统只需要传入一个用户持久化接口。这样 Controller 里的职责就只剩下拿参数、调模板、重定向微信相关的接口细节被隔离在一层。public interface WechatUserRepository { LocalUser findOrCreate(String openid, String unionid, WechatUserInfo wxUser); } Component public class WechatLoginTemplate { private final WechatLoginProperties props; private final RedisTemplateString, String redisTemplate; private final RestTemplate restTemplate new RestTemplate(); public WechatLoginResult login(String code, String state) { // 1. 校验 state且只使用一次 String stateKey wx:state: state; if (Boolean.FALSE.equals(redisTemplate.hasKey(stateKey))) { throw new WechatLoginException(state 校验失败); } redisTemplate.delete(stateKey); // 2. 换 token 和用户信息 WechatOauthToken token exchangeToken(code); WechatUserInfo userInfo getUserInfo(token.getAccess_token(), token.getOpenid()); // 3. 由业务方决定怎么持久化 LocalUser localUser userRepository.findOrCreate(token.getOpenid(), token.getUnionid(), userInfo); return new WechatLoginResult(localUser.getId(), userInfo); } }模板化的好处是后面如果要接扫码登录的新项目只需要实现 WechatUserRepository 接口把用户映射逻辑交给业务方微信侧的时间序、状态校验、错误码处理都不需要再碰。验证这个模板组件是否好用的最快方式是写一个集成测试但微信 code 只能使用一次很难用真实 code 反复测试。更好的办法是在配置里加一个 mock 开关wechat: login: enabled: true mock-enabled: truemock 开关打开时用预设的 openid 和用户信息替代微信接口专门验证第3步之后的本地用户映射与 token 生成环节。这样即使微信回调域名在本地不可达业务侧的登录链路依然能完整测试。我第一次接这个项目的时候把 unionid 当成必然存在的字段来建主键结果测试账号怎么都拉不到 unionid查了半天才想起要绑定公众号。从那以后每次接扫码登录我都会强制走一遍检查先确认开放平台绑定关系再确认授权回调域里是不是漏掉了协议头最后确认 state 的存储和校验是不是同一套缓存。希望这篇文章能帮你把流程一次跑通省去那些同样折腾过我的时间。希望帮到你。本文还有配套的精品资源点击获取

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号