隨著技術(shù)的日益增上,手機的性能越來越好,許多app或者軟件小程序?qū)映霾桓F。下面,為大家介紹如何使用Springboot來實現(xiàn)微信小程序的登錄,下面是詳情內(nèi)容,有興趣的小伙伴可以一起來學(xué)習(xí)學(xué)習(xí)。
由于微信最近的版本更新,wx.getUserInfo()的這個接口即將失效,將用wx.getUserProfile()替換,所以近期我也對自己的登錄進行更新,并且為了鞏固學(xué)習(xí)到的知識,我自己做了一個小demo,在此分享給大家,希望能對大家有所幫助。廢話不多說,直接上代碼。
前端
.wxml
<button class="r" bindtap="bindGetUserInfo">同意</button>
JS部分
bindGetUserInfo(e) {
let that = this
let token = wx.getStorageSync('token'); //token其實就是后臺調(diào)用微信登錄接口返回的openid,每個用戶在同一個小程序內(nèi)是唯一的。
wx.showLoading({
title: '加載中', //提示框,加載中的樣式
})
if (token) {
//如果已經(jīng)有token,說明用戶已經(jīng)登錄,跳轉(zhuǎn)到指定頁面
wx.switchTab({
url: ''
})
} else {
//用戶還未登錄,申請用戶授權(quán)
wx.getUserProfile({
desc: '用于完善會員資料', // 聲明獲取用戶個人信息后的用途,后續(xù)會展示在彈窗中,請謹慎填寫
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為女
//還有有用戶微信設(shè)置的地址信息,個人認為沒啥用,所以沒處理
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: '' //跳轉(zhuǎn)到指定頁面
})
wx.hideLoading() //關(guān)閉提示框
} else {
//輸出錯誤信息
}
}
})
}
})
} else {
//用戶按了拒絕按鈕
wx.showModal({
title: '警告通知',
content: '您點擊了拒絕授權(quán),將無法正常顯示個人信息,點擊確定重新獲取授權(quán)。',
success: function (res) {
//用戶拒絕登錄后的處理
}
});
}
}
})
}
},
前臺的部分都在這了,詳細的解釋都寫在注釋里了,如果多處使用登錄、或者校驗用戶是否登錄,建議進行封裝,方便調(diào)用。
后臺
后臺部分我使用的是springboot框架,為了方便新手學(xué)習(xí),我會將整個模塊貼在后面,包括jar包。
首先給大家看一下項目目錄結(jié)構(gòu)
POM.XML
jar包的內(nèi)容并不復(fù)雜,我相信各位應(yīng)該都沒啥問題哈哈哈哈哈
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!--數(shù)據(jù)庫-->
<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
配置類的內(nèi)容也不復(fù)雜,在此就不作解釋啦
mybatis: type-aliases-package: com.cxb.pojo config-location: classpath:mybatis/mybatis-config.xml mapper-locations: classpath:mybatis/mapper/*.xml spring: application: name: item #數(shù)據(jù)庫部分 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
這個工具類是我網(wǎng)上找的一個比較簡單的工具類,因為微信登錄接口返回的參數(shù)是加密的,所以需要解密
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();
}
// 從輸入流讀取返回內(nèi)容
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 發(fā)送POST方法的請求
*
* @param url 發(fā)送請求的 URL
* @param json 請求參數(shù),請求參數(shù)應(yīng)該是 json 的形式。
* @return 所代表遠程資源的響應(yīng)結(jié)果
*/
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();
// 設(shè)置通用的請求屬性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 發(fā)送POST請求必須設(shè)置如下兩行
conn.setDoOutput(true);
conn.setDoInput(true);
// 獲取URLConnection對象對應(yīng)的輸出流
out = new PrintWriter(conn.getOutputStream());
// 發(fā)送請求參數(shù)
out.print(json);
// flush輸出流的緩沖
out.flush();
// 定義BufferedReader輸入流來讀取URL的響應(yīng)
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result=result.concat(line);
}
} catch (Exception e) {
System.out.println("發(fā)送 POST 請求出現(xiàn)異常!" + e);
e.printStackTrace();
}
//使用finally塊來關(guān)閉輸出流、輸入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
}
接下來就是項目的主題代碼了,因為只是做一個簡單的demo,所以內(nèi)容并不復(fù)雜,但是不管是學(xué)習(xí)還是普通的小項目都是沒有問題的,可以放心使用
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; //只是為了能接收參數(shù),不需要存入數(shù)據(jù)庫
private String openId; //微信登錄接口返回的參數(shù)之一,就是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 {
//微信接口服務(wù),通過調(diào)用微信接口服務(wù)中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); //調(diào)用工具類解密
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);
}
}
數(shù)據(jù)庫的部分應(yīng)該就不用分享了吧,相信大家根據(jù)實體類能自己建出來,好啦,至此微信小程序的登錄功能就完成啦,希望能對大家有所幫助。
以上就是關(guān)于使用Spring boot來實現(xiàn)微信小程序登錄功能的詳細代碼過程的文章,如果您想要了解更多關(guān)于Spring boot的內(nèi)容,在這里小編推薦您可以直接搜索Spring boot相關(guān)內(nèi)容,里面有豐富的視頻、教程以及許多相關(guān)Spring boot的文章,供大家選擇學(xué)習(xí)。