【苍穹外卖Day6】微信小程序登录与 HttpClient 调用
HttpClient 的作用,就是让你的后端程序在运行时,主动去调用别的 Web 接口(HTTP 服务)。比如在“苍穹外卖”Day6里,你的后端需要拿着微信小程序传来的code这里微信的接口在互联网上,它不是你自己写的。所以你需要一个工具来,拿到微信返回的数据(openid等)。而就是干这件事的工具。
·
HTTPClient
HttpClient 的作用,就是让你的后端程序在运行时,主动去调用别的 Web 接口(HTTP 服务)。
比如在“苍穹外卖”Day6里,你的后端需要拿着微信小程序传来的 code 去访问微信官方的接口:
https://api.weixin.qq.com/sns/jscode2session?appid=xxx&secret=xxx&js_code=xxx
这里微信的接口在互联网上,它不是你自己写的。
所以你需要一个工具来 发起HTTP请求,拿到微信返回的数据(openid等)。
而 HttpClient 就是干这件事的工具。
| 发起方 | 对象 | 说明 |
|---|---|---|
| 前端(小程序) | 访问你的服务端接口 | 比如 /user/login |
| 后端(你的Spring项目) | 访问微信官方接口 | 用 HttpClient 调用微信的API |
核心API
- HttpClient:Http客户端对象类型,使用该类型对象可发起Http请求。
- HttpClients:可认为是构建器,可创建HttpClient对象。
- CloseableHttpClient:实现类,实现了HttpClient接口。
- HttpGet:Get方式请求类型。
- HttpPost:Post方式请求类型。
注意:外卖中讲httpclient封装为了工具类,这里不过多赘述。
微信登录流程
- 先在小程序端 使用wx.login() 获得code 授权码
- 小程序端 wx.request 携带code 发送请求到后台
- 后台收到code后, 携带 appid + appSecret + code 使用HttpClient 发送到微信的登入接口服务
- 接口返回一些数据给后台,最重要的是openid 这是微信用户的唯一身份标识
- 后台 自定义登入状态, 生成token,加上openid等数据发送给小程序
- 小程序存储下这些数据,以后发起请求的时候携带token进行身份验证
- 后端收到请求 验证token后在进行业务处理

Controller层(调用service层获取user并返回令牌)
@PostMapping("/login")
public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO){
User user=userService.login(userLoginDTO.getCode());
//jwt
Map<String,Object> claims = new HashMap<>();
claims.put(JwtClaimsConstant.USER_ID,user.getId());
String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(),jwtProperties.getUserTtl(),claims);
log.info("用户登入成功,token为: {}",token);
UserLoginVO userLoginVO = UserLoginVO.builder()
.id(user.getId())
.openid(user.getOpenid())
.token(token)
.build();
return Result.success(userLoginVO);
}
Service
public static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";
@Override
public User login(String code) {
//拿到openid 是微信用户的唯一标识
String openId = getOpenId(code);
if(openId==null) throw new LoginFailedException(MessageConstant.LOGIN_FAILED);
//需要判定当前用户是否为新用户,新用户才需要插入数据库
User user = userMapper.getByOpenid(openId);
if(user==null){
user = User.builder()
.openid(openId)
.createTime(LocalDateTime.now())
.build();
userMapper.insert(user);
}
return user;
}
private String getOpenId(String code) {
Map<String,String> map = new HashMap<>();
map.put("appid",weChatProperties.getAppid());
map.put("secret",weChatProperties.getSecret());
map.put("js_code",code);
map.put("grant_type","authorization_code");
String json = HttpClientUtil.doGet(WX_LOGIN,map);
return JSON.parseObject(json).getString("openid");
}
拦截器
@Component
@Slf4j
public class JwtTokenUserInterceptor implements HandlerInterceptor {
@Autowired
private JwtProperties jwtProperties;
/**
* 校验jwt
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判断当前拦截到的是Controller的方法还是其他资源
if (!(handler instanceof HandlerMethod)) {
//当前拦截到的不是动态方法,直接放行
return true;
}
//1、从请求头中获取令牌
String token = request.getHeader(jwtProperties.getUserTokenName());
//2、校验令牌
try {
log.info("jwt校验:{}", token);
Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
log.info("当前用户id:{}", userId);
//Done 存放当前用户ID到ThreadLocal中
BaseContext.setCurrentId(userId);
//3、通过,放行
return true;
} catch (Exception ex) {
//4、不通过,响应401状态码
response.setStatus(401);
return false;
}
}
}
更多推荐
所有评论(0)