使用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/*.xml
spring:
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: 123456
wxMini:
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; /** * 微信小程序工具类 */ @Slf4j public 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
@Repository
public 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;
@Service
public 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;
@SpringBootApplication
public 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);
}
}
数据库的部分应该就不用分享了吧,相信大家根据实体类能自己建出来,好啦,至此微信小程序的登录功能就完成啦,希望能对大家有所帮助。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
免责声明:本站发布的内容(图片、视频和文字)以原创、来自互联网转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系QQ:712375056 进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
Copyright © 2009-2021 56dr.com. All Rights Reserved. 特网科技 特网云 版权所有 珠海市特网科技有限公司 粤ICP备16109289号
域名注册服务机构:阿里云计算有限公司(万网) 域名服务机构:烟台帝思普网络科技有限公司(DNSPod) CDN服务:阿里云计算有限公司 中国互联网举报中心 增值电信业务经营许可证B2
建议您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流浏览器浏览本网站