Spring Boot实现微信小程序登录

使用Spring Boot完成微信小程序登录

由于微信最近的版本更新,wx.getUserInfo()的这个接口即将失效,将用wx.getUserProfile()替换,所以近期我也对自己的登录进行更新,并且为了巩固学习到的知识,我自己做了一个小demo,在此分享给大家,希望能对大家有所帮助。废话不多说,直接上代码。

前端

.wxml

<button class="r" bindtap="bindGetUserInfo">同意</button>

JS部分

bindGetUserInfo(e) {    let that = this    let token = wx.getStorageSync('token'); //token其实就是后台调用微信登录接口返回的openid,每个用户在同一个小程序内是唯一的。    wx.showLoading({      title: '加载中', //提示框,加载中的样式    })    if (token) {      //如果已经有token,说明用户已经登录,跳转到指定页面      wx.switchTab({        url: ''      })    } else {      //用户还未登录,申请用户授权      wx.getUserProfile({        desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写        success: (res) => {          that.setData({            userInfo: res.userInfo, //保存用户信息          })          if (res.errMsg == "getUserProfile:ok") {            let code = null            wx.login({              success: function (e) {                code = e.code                let params = {};                params.code = code; //用户code  注:用户的code每次登录都是随机的,所以不需要进行存储                params.avatarUrl = res.userInfo.avatarUrl; //用户头像                params.nickName = res.userInfo.nickName; //用户微信名                params.gender = res.userInfo.gender; //用户性别 0为未知,1为男,2为女                //还有有用户微信设置的地址信息,个人认为没啥用,所以没处理                wx.request({                  url: '', //后台接口                  data: params,                  method: 'POST',                  header: {                    'Content-Type': 'application/json',                    'X-Nideshop-Token': wx.getStorageSync('token')                  },                  success: function (res) { //URL为你后台的接口                    console.log(res)                    if (res.data.code === 200) {                      //存储用户信息                      wx.setStorageSync('userInfo', res.data.userInfo);                      wx.setStorageSync('token', res.data.userInfo.openId);                      wx.switchTab({                        url: '' //跳转到指定页面                      })                      wx.hideLoading() //关闭提示框                    } else {                      //输出错误信息                    }                  }                })              }            })          } else {            //用户按了拒绝按钮            wx.showModal({              title: '警告通知',              content: '您点击了拒绝授权,将无法正常显示个人信息,点击确定重新获取授权。',              success: function (res) {                //用户拒绝登录后的处理              }            });          }        }      })    }  },

前台的部分都在这了,详细的解释都写在注释里了,如果多处使用登录、或者校验用户是否登录,建议进行封装,方便调用。

后台

后台部分我使用的是springboot框架,为了方便新手学习,我会将整个模块贴在后面,包括jar包。

首先给大家看一下项目目录结构

POM.XML

jar包的内容并不复杂,我相信各位应该都没啥问题哈哈哈哈哈

<dependency>            <groupId>com.alibaba</groupId>            <artifactId>fastjson</artifactId>            <version>1.2.47</version>        </dependency>        <!--数据库-->        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <version>8.0.23</version>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>            <version>2.4.4</version>        </dependency>        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>druid</artifactId>            <version>1.1.10</version>        </dependency>        <!--SpringBoot启动器-->        <dependency>            <groupId>org.mybatis.spring.boot</groupId>            <artifactId>mybatis-spring-boot-starter</artifactId>            <version>2.1.4</version>        </dependency>        <dependency>            <groupId>log4j</groupId>            <artifactId>log4j</artifactId>            <version>1.2.17</version>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <version>1.16.18</version></dependency>

配置类 application.yml

配置类的内容也不复杂,在此就不作解释啦

mybatis:  type-aliases-package: com.cxb.pojo  config-location: classpath:mybatis/mybatis-config.xml  mapper-locations: classpath:mybatis/mapper/*.xmlspring:  application:    name: item    #数据库部分  datasource:    type: com.alibaba.druid.pool.DruidDataSource    driver-class-name: com.mysql.cj.jdbc.Driver    url: jdbc:mysql:///item?useUnicode=treu&charactEncoding=utf-8    username: root    password: 123456wxMini:  appId:   #小程序的appid,在哪获取如果不知道的话可以百度哟  secret:   #小程序密匙

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"        "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration>    <settings>        <setting name="cacheEnabled" value="true"/>  <!--开启二级缓存-->    </settings></configuration>

工具类 WeChatUtil

这个工具类是我网上找的一个比较简单的工具类,因为微信登录接口返回的参数是加密的,所以需要解密

package com.cxb.utils;import com.alibaba.fastjson.JSONObject;import lombok.extern.slf4j.Slf4j;import javax.net.ssl.HttpsURLConnection;import java.io.*;import java.net.URL;import java.net.URLConnection;import java.nio.charset.StandardCharsets;/** * 微信小程序工具类 */@Slf4jpublic class WeChatUtil {    public static String httpRequest(String requestUrl, String requestMethod, String output) {        try {            URL url = new URL(requestUrl);            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();            connection.setDoOutput(true);            connection.setDoInput(true);            connection.setUseCaches(false);            connection.setRequestMethod(requestMethod);            if (null != output) {                OutputStream outputStream = connection.getOutputStream();                outputStream.write(output.getBytes(StandardCharsets.UTF_8));                outputStream.close();            }            // 从输入流读取返回内容            InputStream inputStream = connection.getInputStream();            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);            String str;            StringBuilder buffer = new StringBuilder();            while ((str = bufferedReader.readLine()) != null) {                buffer.append(str);            }            bufferedReader.close();            inputStreamReader.close();            inputStream.close();            connection.disconnect();            return buffer.toString();        } catch (Exception e) {            e.printStackTrace();        }        return "";    }    /**     * 向指定 URL 发送POST方法的请求     *     * @param url  发送请求的 URL     * @param json 请求参数,请求参数应该是 json 的形式。     * @return 所代表远程资源的响应结果     */    public static String httpPost(String url, JSONObject json) {        PrintWriter out = null;        BufferedReader in = null;        String result = "";        try {            URL realUrl = new URL(url);            // 打开和URL之间的连接            URLConnection conn = realUrl.openConnection();            // 设置通用的请求属性            conn.setRequestProperty("accept", "*/*");            conn.setRequestProperty("connection", "Keep-Alive");            conn.setRequestProperty("user-agent",                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");            // 发送POST请求必须设置如下两行            conn.setDoOutput(true);            conn.setDoInput(true);            // 获取URLConnection对象对应的输出流            out = new PrintWriter(conn.getOutputStream());            // 发送请求参数            out.print(json);            // flush输出流的缓冲            out.flush();            // 定义BufferedReader输入流来读取URL的响应            in = new BufferedReader(                    new InputStreamReader(conn.getInputStream()));            String line;            while ((line = in.readLine()) != null) {                result=result.concat(line);            }        } catch (Exception e) {            System.out.println("发送 POST 请求出现异常!" + e);            e.printStackTrace();        }        //使用finally块来关闭输出流、输入流        finally {            try {                if (out != null) {                    out.close();                }                if (in != null) {                    in.close();                }            } catch (IOException ex) {                ex.printStackTrace();            }        }        return result;    }}

接下来就是项目的主题代码了,因为只是做一个简单的demo,所以内容并不复杂,但是不管是学习还是普通的小项目都是没有问题的,可以放心使用

Dao层 UserDao

package com.cxb.dao;import com.cxb.pojo.User;import org.apache.ibatis.annotations.Mapper;import org.springframework.stereotype.Repository;@Mapper@Repositorypublic interface UserDao {    User queryById(String openId);    void insertUser(User user);    void updateUser(User user);}

service层 UserService

package com.cxb.service;import com.cxb.dao.UserDao;import com.cxb.pojo.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class UserService implements UserDao {    @Autowired    private UserDao userDao;    @Override    public User queryById(String openId) {        return userDao.queryById(openId);    }    @Override    public void insertUser(User user) {        userDao.insertUser(user);    }    @Override    public void updateUser(User user) {        userDao.updateUser(user);    }}

实体类 User

package com.cxb.pojo;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import lombok.experimental.Accessors;import java.io.Serializable;import java.util.Date;@Data@NoArgsConstructor@Accessors(chain = true)public class User implements Serializable {    private Long id;  //id    private String code;  //只是为了能接收参数,不需要存入数据库    private String openId; //微信登录接口返回的参数之一,就是token    private String nickName;  //微信名    private String avatarUrl;  //头像    private String gender;  //性别 0 未知  1 男   2 女    private Date firstLoginTime;  //第一次登录时间    private Date lastLoginTime;  //最后一次登录时间}

SQL部分 UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper        PUBLIC "-//mybatis.org//DTD Mapepr 3.0//EN"        "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.cxb.dao.UserDao">    <select id="queryById" resultType="User">        select * from user where open_id = #{openId}    </select>    <insert id="insertUser" parameterType="User">        insert into user (                        open_id,                        nick_name,                        avatar_url,                        gender,                        first_login_time,                        last_login_time        )        values(               #{openId},               #{nickName},               #{avatarUrl},               #{gender},               #{firstLoginTime},               #{lastLoginTime}              )    </insert>    <update id="updateUser" parameterType="User">        update user        <set>        <if test="nickName != null">`nick_name` = #{nickName},</if>        <if test="avatarUrl != null">`avatar_url` = #{avatarUrl},</if>        <if test="gender != null">`gender` = #{gender},</if>        <if test="lastLoginTime != null">`last_login_time` = #{lastLoginTime}</if>        </set>        where id = #{id}    </update>    </mapper>

控制器 UserController

package com.cxb.controller;import com.alibaba.fastjson.JSONObject;import com.cxb.pojo.User;import com.cxb.service.UserService;import com.cxb.utils.WeChatUtil;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.*;import java.util.Date;@Controller@RequestMapping(value = "/user")public class UserController {    @Value("${wxMini.appId}")    public String appId;    @Value("${wxMini.secret}")    public String secret;    @Autowired    private UserService userService;    @RequestMapping(value = "/login",method = RequestMethod.POST)    @ResponseBody    public JSONObject login(@RequestBody User user){        String code = user.getCode();        JSONObject object=new JSONObject();        if(code == "" || "".equals(code)){            object.put("code",300);            object.put("msg","code不能为空!");            return object;        }        else {            //微信接口服务,通过调用微信接口服务中jscode2session接口获取到openid和session_key            String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code";            String str = WeChatUtil.httpRequest(url, "GET", null); //调用工具类解密            JSONObject jsonObject=JSONObject.parseObject(str);            String openid = (String) jsonObject.get("openid");                if(openid != null && !"".equals(openid)){                    //登录成功                    User userVo=new User();                    userVo.setNickName(user.getNickName());                    userVo.setAvatarUrl(user.getAvatarUrl());                    userVo.setOpenId(openid);                    userVo.setGender(user.getGender());                    userVo.setFirstLoginTime(new Date(System.currentTimeMillis()));                    userVo.setLastLoginTime(new Date(System.currentTimeMillis()));                    User us = userService.queryById(openid);                    if(us != null) {                        //不是首次登录,更新用户信息                        userVo.setId(us.getId());                        userService.updateUser(userVo);                    }                    else {                        //首次登录,存储用户信息                        userService.insertUser(userVo);                    }                    object.put("code",200);                    object.put("msg","登录成功!");                    object.put("userInfo",userVo);                    return object;                }else {                    object.put("code",400);                    object.put("msg","未知错误,请重试!");                    return object;                }            }        }    }

启动类 item

package com.cxb;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Bean;import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;@SpringBootApplicationpublic class item {    //读取配置文件信息    @Bean     public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {        PropertySourcesPlaceholderConfigurer c = new PropertySourcesPlaceholderConfigurer();        c.setIgnoreUnresolvablePlaceholders(true);        return c;    }    public static void main(String[] args) {        SpringApplication.run(item.class,args);    }}

数据库的部分应该就不用分享了吧,相信大家根据实体类能自己建出来,好啦,至此微信小程序的登录功能就完成啦,希望能对大家有所帮助。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

若不给自己设限,则人生中就没有限制你发挥的藩篱。

Spring Boot实现微信小程序登录

相关文章:

你感兴趣的文章:

标签云: