溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Springboot如何實(shí)現(xiàn)微信小程序登錄

發(fā)布時(shí)間:2022-02-25 15:14:48 來源:億速云 閱讀:295 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要介紹Springboot如何實(shí)現(xiàn)微信小程序登錄,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

前端

.wxml

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

JS部分

bindGetUserInfo(e) {
    let that = this
    let token = wx.getStorageSync('token'); //token其實(shí)就是后臺(tái)調(diào)用微信登錄接口返回的openid,每個(gè)用戶在同一個(gè)小程序內(nèi)是唯一的。
    wx.showLoading({
      title: '加載中', //提示框,加載中的樣式
    })
    if (token) {
      //如果已經(jīng)有token,說明用戶已經(jīng)登錄,跳轉(zhuǎn)到指定頁(yè)面
      wx.switchTab({
        url: ''
      })
    } else {
      //用戶還未登錄,申請(qǐng)用戶授權(quán)
      wx.getUserProfile({
        desc: '用于完善會(huì)員資料', // 聲明獲取用戶個(gè)人信息后的用途,后續(xù)會(huì)展示在彈窗中,請(qǐng)謹(jǐn)慎填寫
        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每次登錄都是隨機(jī)的,所以不需要進(jìn)行存儲(chǔ)
                params.avatarUrl = res.userInfo.avatarUrl; //用戶頭像
                params.nickName = res.userInfo.nickName; //用戶微信名
                params.gender = res.userInfo.gender; //用戶性別 0為未知,1為男,2為女
                //還有有用戶微信設(shè)置的地址信息,個(gè)人認(rèn)為沒啥用,所以沒處理
                wx.request({
                  url: '', //后臺(tái)接口
                  data: params,
                  method: 'POST',
                  header: {
                    'Content-Type': 'application/json',
                    'X-Nideshop-Token': wx.getStorageSync('token')
                  },
                  success: function (res) { //URL為你后臺(tái)的接口
                    console.log(res)
                    if (res.data.code === 200) {
                      //存儲(chǔ)用戶信息
                      wx.setStorageSync('userInfo', res.data.userInfo);
                      wx.setStorageSync('token', res.data.userInfo.openId);
                      wx.switchTab({
                        url: '' //跳轉(zhuǎn)到指定頁(yè)面
                      })
                      wx.hideLoading() //關(guān)閉提示框
                    } else {
                      //輸出錯(cuò)誤信息
                    }
                  }
                })
              }
            })
          } else {
            //用戶按了拒絕按鈕
            wx.showModal({
              title: '警告通知',
              content: '您點(diǎn)擊了拒絕授權(quán),將無法正常顯示個(gè)人信息,點(diǎn)擊確定重新獲取授權(quán)。',
              success: function (res) {
                //用戶拒絕登錄后的處理
              }
            });
          }
        }
      })
    }
  },

前臺(tái)的部分都在這了,詳細(xì)的解釋都寫在注釋里了,如果多處使用登錄、或者校驗(yàn)用戶是否登錄,建議進(jìn)行封裝,方便調(diào)用。

后臺(tái)

后臺(tái)部分我使用的是springboot框架,為了方便新手學(xué)習(xí),我會(huì)將整個(gè)模塊貼在后面,包括jar包。

首先給大家看一下項(xiàng)目目錄結(jié)構(gòu)

Springboot如何實(shí)現(xiàn)微信小程序登錄

POM.XML

jar包的內(nèi)容并不復(fù)雜,我相信各位應(yīng)該都沒啥問題哈哈哈哈哈

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <!--數(shù)據(jù)庫(kù)-->
        <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啟動(dòng)器-->
        <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ù)庫(kù)部分
  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"/>  <!--開啟二級(jí)緩存-->
    </settings>
</configuration>

工具類 WeChatUtil

這個(gè)工具類是我網(wǎng)上找的一個(gè)比較簡(jiǎn)單的工具類,因?yàn)槲⑿诺卿浗涌诜祷氐膮?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方法的請(qǐng)求
     *
     * @param url  發(fā)送請(qǐng)求的 URL
     * @param json 請(qǐng)求參數(shù),請(qǐng)求參數(shù)應(yīng)該是 json 的形式。
     * @return 所代表遠(yuǎn)程資源的響應(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è)置通用的請(qǐng)求屬性
            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請(qǐng)求必須設(shè)置如下兩行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 獲取URLConnection對(duì)象對(duì)應(yīng)的輸出流
            out = new PrintWriter(conn.getOutputStream());
            // 發(fā)送請(qǐng)求參數(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 請(qǐng)求出現(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;
    }

}

接下來就是項(xiàng)目的主題代碼了,因?yàn)橹皇亲鲆粋€(gè)簡(jiǎn)單的demo,所以內(nèi)容并不復(fù)雜,但是不管是學(xué)習(xí)還是普通的小項(xiàng)目都是沒有問題的,可以放心使用

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);
    }
}

實(shí)體類 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ù)庫(kù)
    private String openId; //微信登錄接口返回的參數(shù)之一,就是token
    private String nickName;  //微信名
    private String avatarUrl;  //頭像
    private String gender;  //性別 0 未知  1 男   2 女
    private Date firstLoginTime;  //第一次登錄時(shí)間
    private Date lastLoginTime;  //最后一次登錄時(shí)間
}

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 {
                        //首次登錄,存儲(chǔ)用戶信息
                        userService.insertUser(userVo);
                    }
                    object.put("code",200);
                    object.put("msg","登錄成功!");
                    object.put("userInfo",userVo);
                    return object;
                }else {
                    object.put("code",400);
                    object.put("msg","未知錯(cuò)誤,請(qǐng)重試!");
                    return object;
                }
            }
        }
    }

啟動(dòng)類 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ù)庫(kù)的部分應(yīng)該就不用分享了吧,相信大家根據(jù)實(shí)體類能自己建出來。

以上是“Springboot如何實(shí)現(xiàn)微信小程序登錄”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI