微信登录接口

该文描述了一个使用微信授权进行本地认证服务的过程,包括定义接口、通过授权码获取令牌、获取用户信息、存储用户数据到本地数据库以及处理重定向以实现自动登录。在服务层,主要涉及了请求微信接口获取用户信息和事务管理确保数据一致性。
摘要由CSDN通过智能技术生成

1.流程图

 本地认证服务需要:

  •  定义接口,接受微信下发的授权码
  • 受到授权码以后,调用微信的接口申请令牌
  • 接受到令牌以后,申请获得用户的信息
  • 获取用户信息以后将信息存储到本地的数据库
  • 重定向到浏览器登录界面,自动登录

注意:由于微信属于外网服务,所以要添加穿透器。

2.定义接口

2.1定义controller              

调用service去查询用户的信息

package com.xuecheng.auth.controller;

import com.xuecheng.ucenter.model.po.XcUser;
import com.xuecheng.ucenter.service.impl.WxAuthServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;

/**
 * @author YCL
 * @version 1.0
 * @description 微信登录接口
 * @date 2023-02-28 7:54
 */
@Slf4j
@Controller
public class WxLoginController {

    @Autowired
    WxAuthServiceImpl wxAuthService;

    @PostMapping("/wxLogin")
    public String wxLogin(String code, String state) {
        //拿授权码申请令牌。查询用户
        XcUser xcUser = wxAuthService.wxAuth(code);
        if(xcUser == null){
            //重定向到错误页面
            return "redirect:http://www.xuecheng-plus.com/error.html";
        }
        String username = xcUser.getName();
        return "redirect:http://www.xuecheng-plus.com/sign.html?username="+username+"&authType=wx";
    }
}

2.2定义service

       1.拿着授权码去请求微信获取令牌

//请求微信获取令牌
    /**
     * 微信接口响应结果
     * {
     * "access_token":"ACCESS_TOKEN",
     * "expires_in":7200,
     * "refresh_token":"REFRESH_TOKEN",
     * "openid":"OPENID",
     * "scope":"SCOPE",
     * "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
     * }
     */

    private Map<String, String> getAccss_token(String code){
        String appid = "appid";
        String serect = "serect";
        String url_template = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
        String url = String.format(url_template, appid, serect, code);
        //请求微信获取令牌
        ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST,
                null, String.class);
        //得到相应串
        String body = exchange.getBody();
        Map map = JSON.parseObject(body, Map.class);
        return map;
    }

          2.携带令牌去查询用户信息

//携带令牌查询用户信息
    //http请求方式: GET
    //https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
    /**
     {
     "openid":"OPENID",
     "nickname":"NICKNAME",
     "sex":1,
     "province":"PROVINCE",
     "city":"CITY",
     "country":"COUNTRY",
     "headimgurl": "https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
     "privilege":[
     "PRIVILEGE1",
     "PRIVILEGE2"
     ],
     "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"

     }
     */
    private Map<String,String> getUserInfo(String access_token, String open_id){
        String url_template = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s";
        String url = String.format(url_template, access_token, open_id);
        ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
        String body = exchange.getBody();
        //结果转换成map
        Map map = JSON.parseObject(body, Map.class);
        return map;

    }

        3. 写入数据,将数据写入到本地数据库中

        

 @Transactional
    public XcUser addWxUser(Map userInfo_map){
        //先去除unionid
        String unionid = (String) userInfo_map.get("unionid");
        XcUser xcUser = xcUserMapper.selectOne(new LambdaQueryWrapper<XcUser>().
                eq(XcUser::getWxUnionid, unionid));
        if (xcUser != null){
            return xcUser;
        }

        xcUser = new XcUser();
        String id = UUID.randomUUID().toString();
        xcUser.setId(id);
        xcUser.setWxUnionid(unionid);
        //记录从微信得到的昵称
        xcUser.setNickname(userInfo_map.get("nickname").toString());
        xcUser.setUserpic(userInfo_map.get("headimgurl").toString());
        xcUser.setName(userInfo_map.get("nickname").toString());
        xcUser.setUsername(unionid);
        xcUser.setPassword(unionid);
        xcUser.setUtype("101001");//学生类型
        xcUser.setStatus("1");//用户状态
        xcUser.setCreateTime(LocalDateTime.now());
        xcUserMapper.insert(xcUser);
        XcUserRole xcUserRole = new XcUserRole();
        xcUserRole.setId(UUID.randomUUID().toString());
        xcUserRole.setUserId(id);
        xcUserRole.setRoleId("17");//学生角色
        userRoleMapper.insert(xcUserRole);
        return xcUser;
    }

                  

        4.重写execute方法,查询本地数据库中的数据

    /***
    * @description 微信认证方法
    * @param authParamsDto
    * @return
    * @author
    * @date
    */
    @Override
    public XcUserExt execute(AuthParamsDto authParamsDto) {
        String username = authParamsDto.getUsername();
        XcUser xcUser = xcUserMapper.selectOne(new LambdaQueryWrapper<XcUser>()
                .eq(XcUser::getName, username
        ));
        if(xcUser == null){
            throw new RuntimeException("微信授权过程的用户不存在");
        }
        XcUserExt xcUserExt = new XcUserExt();
        BeanUtils.copyProperties(xcUser,xcUserExt);
        return xcUserExt;
    }

        5.授权方法的调用函数

        注意调用存储到本地数据库的代码的时候,由于数据库方法加了@Transactional,所以是事务,而调用函数本身并不是事务控制,所以要在service中注入自己为代理,防止事务失效,注入自己的代码如下:(关于事务的详细解释在spring专栏中)

    @Autowired
    WxAuthServiceImpl agent;
public XcUser wxAuth(String code){
        //拿着授权码code申请令牌,查询用户
        Map<String, String> accss_token = getAccss_token(code);
        //拿着令牌查询用户信息
        String access_token = accss_token.get("access_token");
        String openid = accss_token.get("openid");
        Map<String, String> userInfo = getUserInfo(access_token, openid);
        //添加用户到数据库
        XcUser xcUser = agent.addWxUser(userInfo);
        return xcUser;
    }

2.3 service完整代码

package com.xuecheng.ucenter.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xuecheng.ucenter.mapper.XcUserMapper;
import com.xuecheng.ucenter.mapper.XcUserRoleMapper;
import com.xuecheng.ucenter.model.dto.AuthParamsDto;
import com.xuecheng.ucenter.model.dto.XcUserExt;
import com.xuecheng.ucenter.model.po.XcUser;
import com.xuecheng.ucenter.model.po.XcUserRole;
import com.xuecheng.ucenter.service.AuthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.UUID;

/**
 * @author YCL
 * @version 1.0
 * @description 微信登录认证
 * @date 2023-02-28 7:42
 */
@Service("wx_authservice")
@Slf4j
public class WxAuthServiceImpl implements AuthService {

    @Autowired
    XcUserMapper xcUserMapper;

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    XcUserRoleMapper userRoleMapper;

    @Autowired
    WxAuthServiceImpl agent;

    public XcUser wxAuth(String code){
        //拿着授权码code申请令牌,查询用户
        Map<String, String> accss_token = getAccss_token(code);
        //拿着令牌查询用户信息
        String access_token = accss_token.get("access_token");
        String openid = accss_token.get("openid");
        Map<String, String> userInfo = getUserInfo(access_token, openid);
        //添加用户到数据库
        XcUser xcUser = agent.addWxUser(userInfo);
        return xcUser;
    }

    /***
    * @description 微信认证方法
    * @param authParamsDto
    * @return
    * @author
    * @date
    */
    @Override
    public XcUserExt execute(AuthParamsDto authParamsDto) {
        String username = authParamsDto.getUsername();
        XcUser xcUser = xcUserMapper.selectOne(new LambdaQueryWrapper<XcUser>()
                .eq(XcUser::getName, username
        ));
        if(xcUser == null){
            throw new RuntimeException("微信授权过程的用户不存在");
        }
        XcUserExt xcUserExt = new XcUserExt();
        BeanUtils.copyProperties(xcUser,xcUserExt);
        return xcUserExt;
    }

    //请求微信获取令牌
    /**
     * 微信接口响应结果
     * {
     * "access_token":"ACCESS_TOKEN",
     * "expires_in":7200,
     * "refresh_token":"REFRESH_TOKEN",
     * "openid":"OPENID",
     * "scope":"SCOPE",
     * "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
     * }
     */

    private Map<String, String> getAccss_token(String code){
        String appid = "appid";
        String serect = "serect";
        String url_template = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
        String url = String.format(url_template, appid, serect, code);
        //请求微信获取令牌
        ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST,
                null, String.class);
        //得到相应串
        String body = exchange.getBody();
        Map map = JSON.parseObject(body, Map.class);
        return map;
    }

    //携带令牌查询用户信息
    //http请求方式: GET
    //https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
    /**
     {
     "openid":"OPENID",
     "nickname":"NICKNAME",
     "sex":1,
     "province":"PROVINCE",
     "city":"CITY",
     "country":"COUNTRY",
     "headimgurl": "https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
     "privilege":[
     "PRIVILEGE1",
     "PRIVILEGE2"
     ],
     "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"

     }
     */
    private Map<String,String> getUserInfo(String access_token, String open_id){
        String url_template = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s";
        String url = String.format(url_template, access_token, open_id);
        ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
        String body = exchange.getBody();
        //结果转换成map
        Map map = JSON.parseObject(body, Map.class);
        return map;

    }

    @Transactional
    public XcUser addWxUser(Map userInfo_map){
        //先去除unionid
        String unionid = (String) userInfo_map.get("unionid");
        XcUser xcUser = xcUserMapper.selectOne(new LambdaQueryWrapper<XcUser>().
                eq(XcUser::getWxUnionid, unionid));
        if (xcUser != null){
            return xcUser;
        }

        xcUser = new XcUser();
        String id = UUID.randomUUID().toString();
        xcUser.setId(id);
        xcUser.setWxUnionid(unionid);
        //记录从微信得到的昵称
        xcUser.setNickname(userInfo_map.get("nickname").toString());
        xcUser.setUserpic(userInfo_map.get("headimgurl").toString());
        xcUser.setName(userInfo_map.get("nickname").toString());
        xcUser.setUsername(unionid);
        xcUser.setPassword(unionid);
        xcUser.setUtype("101001");//学生类型
        xcUser.setStatus("1");//用户状态
        xcUser.setCreateTime(LocalDateTime.now());
        xcUserMapper.insert(xcUser);
        XcUserRole xcUserRole = new XcUserRole();
        xcUserRole.setId(UUID.randomUUID().toString());
        xcUserRole.setUserId(id);
        xcUserRole.setRoleId("17");//学生角色
        userRoleMapper.insert(xcUserRole);
        return xcUser;
    }

}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值