微信小程序 Java服务端 登录相关代码 工具类 2023最新版 home 编辑时间 2023/04/13 ![](/api/file/getImage?fileId=64377f35da74050013022f6e) ## 前言 必须先吐槽下微信的神奇操作 [小程序用户头像昵称获取规则调整公告(微信开放社区)](https://developers.weixin.qq.com/community/develop/doc/00022c683e8a80b29bed2142b56c01) 我记得微信没多久之前刚改过一次,废弃了`wx.getUserInfo`,改成了`wx.getUserProfile` 这才没多久,又改了😂 ![](https://s2.loli.net/2023/04/13/YJHnuRWL2FvMATh.gif) <br> 最新的方式参考这个链接 [头像昵称填写(微信开放文档)](https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/userProfile.html) 可以理解为用户自行上传头像填写昵称,过程中允许直接使用微信头像和昵称。 <br> ## 代码 本文主要更新一下后端的工具类和接口的大致思路 <br> 依赖包括 `Apache HttpClient5` `FastJSON2` `SrpingBootRedis` 等 建议直接参考我之前的笔记 [Java Http请求工具类 基于最新版 HttpClient5 Fluent](https://leanote.zzzmh.cn/blog/post/64377742da74050013022f62) [从零新建一个 Springboot 2.7.1 项目搭配 Swagger 3.0 Knife4j MyBatisPlus 等](https://leanote.zzzmh.cn/blog/post/admin/62d618a2da740500130121d2) 工具类 WechatUtils ```java import com.alibaba.fastjson2.JSONObject; import com.joinzs.auction.entity.wechat.PhoneInfo; import com.joinzs.auction.exception.RRException; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; /** * 微信核心工具类 */ @Component public class WechatUtils { @Value("${wechat.miniapp.appid}") private String miniAppAppid; @Value("${wechat.miniapp.secret}") private String miniAppSecret; @Value("${wechat.miniapp.expire}") private long expire; @Autowired private RedisUtils redisUtils; public String getAccessToken() { String accessToken = redisUtils.get("access_token_" + miniAppAppid); if (StringUtils.isBlank(accessToken)) { String url = "https://api.weixin.qq.com/cgi-bin/token" + "?" + "appid=" + miniAppAppid + "&secret=" + miniAppSecret + "&grant_type=client_credential"; JSONObject result = HttpClientUtils.doGet(url); if (result != null && result.containsKey("access_token")) { accessToken = result.getString("access_token"); Integer expires = result.getInteger("expires_in"); if (StringUtils.isNotBlank(accessToken) && expires != null) { redisUtils.set("access_token_" + miniAppAppid, accessToken, expires); } } } if (StringUtils.isBlank(accessToken)) { throw new RRException(700); } return accessToken; } /** * 微信登录授权 * https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html */ public JSONObject getLoginInfo(String code) { String url = "https://api.weixin.qq.com/sns/jscode2session?" + "appid=" + miniAppAppid + "&secret=" + miniAppSecret + "&js_code=" + code + "&grant_type=authorization_code"; //发送请求 JSONObject result = HttpClientUtils.doGet(url); if (result != null && result.containsKey("openid")) { String openid = result.getString("openid"); if (StringUtils.isNotBlank(openid)) { String sha256 = DigestUtils.sha256Hex(openid); redisUtils.set("login_" + sha256, openid, expire); return JSONObject.of("openid", openid, "key", sha256); } } throw new RRException(702); } /** * 获取用户手机号 * https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/phone-number/getPhoneNumber.html */ public PhoneInfo getPhoneInfo(String code) { String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + getAccessToken(); JSONObject result = HttpClientUtils.doPost(url, JSONObject.of("code", code)); if (result != null && result.getIntValue("errcode") == 0) { return result.getObject("phone_info", PhoneInfo.class); } throw new RRException(703); } } ``` 配置文件加这一段配置 替换成你自己的appid和secret `application-dev.yml` `application-prod.yml` ```yml wechat: miniapp: appid: xxxxxxxxxxxx secret: xxxxxxxxxxxx expire: 7200 ``` 返回值实体类 `PhoneInfo.java` ```java @Data @ApiModel("微信用户手机号") public class PhoneInfo { String phoneNumber; String purePhoneNumber; Integer countryCode; } ``` ##思路 在Controller中 ```java @ApiOperation("微信登录") @PostMapping("/login") public JSONObject login(@RequestParam String code) { // 先用code换openid JSONObject login = wechatUtils.getLoginInfo(code); // 再去数据库查openid是否存在 if(存在){ // 查看数据是否完整 if(完整){ // 登录成功直接发放token }else{ // 继续完善信息 } }else{ // 新增一条数据并完善信息 } return JSONObject.of(); } @ApiOperation("微信获取用户信息") @PostMapping("/getUserInfo") @Transactional(rollbackFor = Throwable.class) public JSONObject getUserInfo(@RequestBody WechatForm form) { // 上个接口的key去redis换openid // 头像昵称是从前端直接传字符串和文件 // 手机号用前端code代入方法getPhoneInfo换 ... // 最后登录成功返回token } ``` ## END 送人玫瑰,手留余香 赞赏 Wechat Pay Alipay Springboot 接收&返回 LocalDateTime 全自动时间戳互转 支持Swagger3 Java Http请求工具类 基于最新版 HttpClient5 Fluent