微信登录(简易版)

引子

感觉微信登录刚开始用的时候真的好绕啊,感觉很多东西自己不太能用的清楚,下面是自己的简易版记录,主要为了做个笔记,如果觉得有些出入可以提出,自己也是一个新人啦。

前端

  1. 通过调用 wx.login 接口来进行code的获取,从而得到确定用户唯一身份的openId和会话密钥sessionkey;
  2. 通过获取微信手机号来得到密钥encryptedData以及矢量iv,通过wx.getUserInfo得到用户信息(其实这个得到用户信息没有太大的必要,因为他现在经过修改得到的用户名称和头像都不是微信的了,都是默认的,但我觉得把这个默认的先存进去做我一个默认设定的也行)
<button wx:if="{{!isBindPhone}}" open-type="getPhoneNumber" bindgetphonenumber="onGetPhoneNumber">获取手机号</button>
 import util from '../../utils/util';
  onGetPhoneNumber(e) {
    //授权
    if (e.detail.errMsg == 'getPhoneNumber:fail user deny') {
        wx.showToast({
          title: "必须绑定手机号才可登录",
          icon: 'none'
        })
        return;
    }
    let encryptedData = e.detail.encryptedData;
    let iv = e.detail.iv;
    var that = this;
    wx.getSetting({
        success(e){
            wx.getUserInfo({
                success: function(res) {
                   // console.log(res);
                   //将其数据通过wx.request传到后端,
                   //其中loginByWeixin是自己写的方法名
                    util.loginByWeixin(res.userInfo,encryptedData,iv);
                }
              })
        }
    })

后端

作为一个后端小白,真的是从头开始走的…┭┮﹏┭┮

  1. 依赖
    <!--用的是binarywang的接口-->
    	<dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-miniapp</artifactId>
            <version>4.5.0</version>
        </dependency>
        <!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.2.0</version>
        </dependency>
        <!--序列化,反序列化-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.38</version>
        </dependency>
    
  2. 这里加个微信接口的配置
  • WxConfig
@Configuration
@EnableConfigurationProperties(WxProperties.class)
public class WxConfig {

    @Autowired
    private WxProperties wxProperties;
    public WxConfig(WxProperties wxProperties){
        this.wxProperties=wxProperties;
    }
    @Bean
    public WxMaService wxMaService() {

        List<WxProperties.Config> configs = this.wxProperties.getConfigs();

        if (configs == null) {
            System.out.println("没有微信小程序配置啊");
        }

        WxMaServiceImpl maService = new WxMaServiceImpl();

        Map<String, WxMaDefaultConfigImpl> multiConfigs = configs.stream()
                .map(cof -> {
                    WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
                    config.setAppid(cof.getAppid());
                    config.setSecret(cof.getSecret());
                    config.setToken(cof.getToken());
                    config.setAesKey(cof.getAesKey());
                    config.setMsgDataFormat(cof.getMsgDataFormat());
                    return config;
                })
                .collect(Collectors.toMap(WxMaDefaultConfigImpl::getAppid, Function.identity(), (o, n) -> o));
        maService.setMultiConfigs(multiConfigs);
        return maService;
    }

}

  • WxProperties
@Data
@Configuration
//wechat-setting是在application.yml中配置的名称
@ConfigurationProperties(prefix = "wechat-setting")
public class WxProperties {
   private List<Config> configs;
   @Data
   public static class Config {
       /**
        * 设置微信小程序的appid
        */
       private String appid;

       /**
        * 设置微信小程序的Secret
        */
       private String secret;

       /**
        * 设置微信小程序消息服务器配置的token
        */
       private String token;

       /**
        * 设置微信小程序消息服务器配置的EncodingAESKey
        */
       private String aesKey;

       /**
        * 消息格式,XML或者JSON
        */
       private String msgDataFormat;
   }

}
  • application.yml
# 注意写法
wechat-setting:
 configs:
 - appid: 
   secret: 
  1. jedis 配置
  • RedisConfig
public class RedisConfig {
   @Value("${spring.redis.host}")
   private String ADDR;
   //端口号
   @Value("${spring.redis.port}")
   private  int PORT ;
   //密码
   @Value("${spring.redis.auth}")
   private  String AUTH ;
   //连接的时间,一旦超时就报错
   @Value("${spring.redis.timeout}")
   private  int TIMEOUT ;
   //可用连接实例的最大数目,默认值为8;
   //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
   private  int MAX_ACTIVE = 1024;

   //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值8。
   private  int MAX_IDLE = 200;

   //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
   private  int MAX_WAIT = 10000;

   //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
   private  boolean TEST_ON_BORROW = true;

   private JedisPool pool = null;
//连接池
   @Bean
   public JedisPool getJedisPool()
   {
       try {
           JedisPoolConfig config = new JedisPoolConfig();
           config.setMaxTotal(MAX_ACTIVE);
           config.setMaxIdle(MAX_IDLE);
           config.setMaxWaitMillis(MAX_WAIT);
           config.setTestOnBorrow(TEST_ON_BORROW);
           Integer port = new Integer(PORT);
           //pool = new JedisPool(config, ADDR, port, TIMEOUT);
           pool = new JedisPool(config, ADDR, port, TIMEOUT, AUTH);
           try {
               pool.getResource();
           } catch (JedisConnectionException e) {
               System.out.println("redis没有设置密码");
               pool = new JedisPool(config, ADDR, port, TIMEOUT);
               e.printStackTrace();
           }
           return pool;
       } catch (Exception e) {
           e.printStackTrace();
       }
       return pool;
   }

   /**
    * 返还到连接池
    * @param redis
    */
   public  void returnResource(Jedis redis) {
       if (redis != null) {
           redis.close();
       }
   }

   public  String get(String key) {
       Jedis jedis = null;
       String value = null;
       try {
           jedis = pool.getResource();
           //选择第几个数据库
           jedis.select(0);
           value = jedis.get(key);
       } catch (Exception e) {
           e.printStackTrace();
       } finally {
           returnResource(jedis);
       }
       return value;
   }
   public  String set(String key, String value) {
       Jedis jedis = null;
       try {
//            选择数据库
           jedis = pool.getResource();jedis.select(0);
           return jedis.set(key, value);
       } catch (Exception e) {
           e.printStackTrace();
       } finally {
           returnResource(jedis);
       }
       return "0";
   }
   /**
    *
    * @param key
    * @param value
    * @param seconds 单位:秒
    * @return 成功返回OK 失败和异常返回null
    */
   public  String setex(String key, String value, int seconds) {
       Jedis jedis = null;
       String res = null;
       try {
           jedis = pool.getResource();
           jedis.select(0);
           res = jedis.setex(key, seconds, value);
       } catch (Exception e) {
           e.printStackTrace();
       } finally {
           returnResource(jedis);
       }
       return res;
   }
  • application.yml
sping:
  redis:
  	# 默认
    host: 127.0.0.1
    # 默认
    port: 6379
    timeout: 10000
    # 密码可以自己设定
    auth: 12345
  1. 最后使用
@RestController
@RequestMapping("/wechat")
public class WeChatController {
   private Logger logger = LoggerFactory.getLogger(WeChatController.class);
   @Resource
   private WxMaService wxMaService;
   @Resource
   private IUserService userService;
   @Resource
   private RedisConfig redisConfig;
//    @Resource
//    private ReturnForm returnForm;

//获取openId
   @RequestMapping("/login")
   public Object getSession(@RequestBody WxLoginInfo wxLoginInfo, HttpServletRequest request) {
       //ifcode为空的话则报错给前端
       if (Strings.isNullOrEmpty(wxLoginInfo.getCode())) {
           return Result.fail("code参数错误");
       }
       String code = wxLoginInfo.getCode();
       WxUserInfo userInfo = wxLoginInfo.getUserInfo();
       if(code==null || userInfo == null){
           return Result.fail("code参数错误或userInfo未能获取");
       }
       String sessionKey = null;
       String openId = null;
       String unionId = null;
       try{
           WxMaJscode2SessionResult res = this.wxMaService.getUserService().getSessionInfo(code);
           sessionKey = res.getSessionKey();
           openId = res.getOpenid();
           unionId = res.getUnionid();
           System.out.println("sessionKey: "+sessionKey);
           System.out.println("openId:"+openId);
           System.out.println("unionId:"+unionId);
       }catch(Exception e){
           logger.error("login_by_wechat error:{}",e);
       }
       if(sessionKey==null || openId ==null){
           return Result.fail("sessionKey或openId为空");
       }
       //得到了openId
       User user=new User();
       user.setOpen_id(openId);
       Map<String,Object> data = userService.login(user);
       ReturnForm returnForm=new ReturnForm();
       //则没有该用户,需要创建该用户
       if(data==null){
           //则获取手机号
           WxMaPhoneNumberInfo phoneInfo = wxMaService.getUserService().getPhoneNoInfo(sessionKey, wxLoginInfo.getEncryptedData(), wxLoginInfo.getIv());
           String phoneNumber = phoneInfo.getPhoneNumber();
           user.setTel(phoneNumber);
           user.setAvatar(wxLoginInfo.getUserInfo().getAvatarUrl());
           user.setName(wxLoginInfo.getUserInfo().getNickName());
           userService.createUser(user);
           String key = "user:" + UUID.randomUUID();
           //存入redis
           redisConfig.setObject(key,user);
           returnForm.setToken(key);
           returnForm.setUser(user);
           return Result.success(returnForm,"创建成功");
       }else{
           returnForm.setToken(data.get("token").toString());
           returnForm.setUser((User)data.get("userInfo"));
           return Result.success(returnForm,"查找到相关用户");
       }
   }
  • service
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

   /*
   *   通过前端获取code信息,再通过微信小程序提供的api解读code,得到用户信息和openid等信息
   *   获取用户openid进行查询,是否存在改任
   * */
   @Resource
   private RedisConfig redisConfig;
   @Override
   public Map<String, Object> login(User user) {
       // 根据用户名和密码去查询(openid去查询)
       LambdaQueryWrapper<User> wrapper= new LambdaQueryWrapper<>();
       wrapper.eq(User::getOpen_id,user.getOpen_id());
       User loginUser = this.baseMapper.selectOne(wrapper);
       //如果结果不为空,则生成token,并将用户信息存入redis中
       if(loginUser != null){
           //暂时用UUID,终极方案是jwt
           String key = "user:" + UUID.randomUUID();
           //存入redis
           redisConfig.setex(key,JSON.toJSONString(loginUser),36000);
           //返回数据
           Map<String,Object> data = new HashMap<>();
           data.put("token",key);
           data.put("userInfo",loginUser);
           return data;
       }
       return null;
   }

   /**
    *
    * @param user
    * @return
    * 1 表示手机号为空,
    * 2 表示创建成功
    * 3 表示创建失败
    */
   @Override
   public Boolean createUser(User user){
       return this.saveOrUpdate(user);
   }
}

最后,仅供参考了,
日常打气,加油努力!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值