WeChat Mini Program WeChat account login

Table of contents

Background and front-end code sharing ----


wx.getUserProfile

bindgetuserinfo

login process

Mini Program Login | WeChat Open Documentation (qq.com)

The Mini Program can easily obtain the user identity provided by WeChat through the official login capability provided by WeChat, and quickly establish a user system within the Mini Program.

Description Call wx.login(Object object) | WeChat Open Documentation (qq.com) to obtain the temporary login credential code and send it back to the developer server. Call the Mini Program Login | WeChat Open Documentation (qq.com) auth.code2Session interface in exchange for the user 's unique ID OpenID , the user's unique (if the current Mini Program has been bound to the WeChat Open Platform account) and Session key session_key . Afterwards, the developer server can generate a custom login status according to the user ID, which is used to identify the user's identity during the front-end and back-end interactions in the subsequent business logic. Precautions The session key session_key is the key for encrypting and signing user data . The server obtains open data | WeChat open documents (qq.com) . In order to protect the application's own data, the developer server should not send the session key to the applet, nor should it provide this key to the outside world. . Temporary login credential code can only be used once. The appId function shows that the appid is the unique identifier of the WeChat account, which is fixed; if you understand the development of the WeChat official account, you need to pay attention, the appid of the applet and the appid of the official account are inconsistent session_key function description The WeChat client obtains user information through wx.getUserInfo(). The background sometimes needs to obtain the user information of the WeChat client. Therefore, it is necessary to use the secret key session_key to obtain the official document from the WeChat platform. Signature verification and Data encryption and decryption involves the user's session key session_key. The developer should obtain the session key session_key through the wx.login login process in advance and save it on the server. In order not to tamper with the data, the developer should not pass the session_key to the environment outside the server such as the applet client.

Login-Applet

  1. Execute wx.login to log in to get the code of the applet
  2. The server gets the session_key from WeChat according to the code and caches it; at the same time, it generates an access_token and saves it in the applet to maintain the login status;
  3. When the applet requests server user data, first wx.checkSession, if valid, determine the user through access_token, and find session_key; if invalid, execute wx.login to re-login to regenerate access_token, and the server re-obtains session_key;
  4. If the mini program is not used for a long time, the session_key on the server will become invalid, and the session_key can no longer be used to obtain data from WeChat, and the mini program needs to perform the login operation again; the server can only obtain the session_key through the login of the mini program;

wx.checkSession

Check if the login status has expired

wx.login

Call the interface to obtain login credentials (code)

wx.request

Request your own mini program server, and carry code, userInfo information

Backstage

prepare data sheet

DROP TABLE IF EXISTS `wx_user`;
CREATE TABLE `wx_user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名称',
  `password` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',
  `gender` tinyint(3) NOT NULL DEFAULT 0 COMMENT '性别:0 未知, 1男, 1 女',
  `birthday` date NULL DEFAULT NULL COMMENT '生日',
  `last_login_time` datetime(0) NULL DEFAULT NULL COMMENT '最近一次登录时间',
  `last_login_ip` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '最近一次登录IP地址',
  `user_level` tinyint(3) NULL DEFAULT 0 COMMENT '用户层级 0 普通用户,1 VIP用户,2 区域代理用户',
  `nickname` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户昵称或网络名称',
  `mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户手机号码',
  `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户头像图片',
  `weixin_openid` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '微信登录openid',
  `status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '0 可用, 1 禁用, 2 注销',
  `add_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
  `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '逻辑删除',
  `share_user_id` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `user_name`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Compact;

Reverse build tool generates

  • WxUser.java
  • WxUserMapper.java
  • WxUserMapper.xml

Prepare to encapsulate the data passed from the front end

  • UserInfo
package com.zking.ssm.model;

import lombok.Data;

import java.io.Serializable;

/**
 * 封装微信UserInfo用户信息
 */
@Data
public class UserInfo implements Serializable {
   private static final long serialVersionUID = -5813029516433359765L;

   private Integer userId;
   private String nickName;
   private String avatarUrl;
   private String country;
   private String province;
   private String city;
   private String language;
   private Byte gender;
   private String phone;
   private Byte userLevel;// 用户层级 0 普通用户,1 VIP用户,2 区域代理用户
   private String userLevelDesc;// 代理用户描述
   
   private Byte status;//状态
   private String registerDate;//注册日期
   
}
  • WxLoginInfo
package com.zking.ssm.model;

import lombok.Data;

import java.io.Serializable;

/**
 * 封装请求数据
 */
@Data
public class WxLoginInfo implements Serializable {

   private static final long serialVersionUID = -7722430332896313642L;

   private String code;
   private UserInfo userInfo;

}

Mini Program Server Configuration

Import WeChat Mini Program SDK

<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>weixin-java-miniapp</artifactId>
    <version>3.3.0</version>
</dependency>

WxProperties

Encapsulate the data of oa.wx

@Data
@Configuration
@ConfigurationProperties(prefix = "oa.wx")
public class WxProperties {
    /**
     * 设置微信小程序的appId
     */
    private String appId;
    /**
     * 设置微信小程序的Secret
     */
    private String appSecret;
    /**
     * 消息数据格式
     */
    private String msgDataFormat;
}

WxConfig

Register WxMaService

@Configuration
public class WxConfig {
    @Autowired
    private WxProperties properties;
    @Bean
    public WxMaConfig wxMaConfig() {
        WxMaInMemoryConfig config = new WxMaInMemoryConfig();
        config.setAppid(properties.getAppId());
        config.setSecret(properties.getAppSecret());
        config.setMsgDataFormat(properties.getMsgDataFormat());
        return config;
    }
    @Bean
    public WxMaService wxMaService(WxMaConfig maConfig) {
        WxMaService service = new WxMaServiceImpl();
        service.setWxMaConfig(maConfig);
        return service;
    }
}

WxAuthController

@RequestMapping("/wx/auth")
public class WxAuthController {
    @Autowired
    private WxMaService wxService;
     @PostMapping("login_by_weixin")
    public Object loginByWeixin(@RequestBody WxLoginInfo wxLoginInfo, HttpServletRequest request) {
        //客户端需携带code与userInfo信息
        String code = wxLoginInfo.getCode();
        UserInfo userInfo = wxLoginInfo.getUserInfo();
        if (code == null || userInfo == null) {
            return ResponseUtil.badArgument();
        }
        //调用微信sdk获取openId及sessionKey
        String sessionKey = null;
        String openId = null;
        try {
            WxMaJscode2SessionResult result = this.wxService.getUserService().getSessionInfo(code);
            sessionKey = result.getSessionKey();//session id
            openId = result.getOpenid();//用户唯一标识 OpenID
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (sessionKey == null || openId == null) {
            log.error("微信登录,调用官方接口失败:{}", code);
            return ResponseUtil.fail();
        }else{
            log.info("openId={},sessionKey={}",openId,sessionKey);
        }
        //根据openId查询wx_user表
        //如果不存在,初始化wx_user,并保存到数据库中
        //如果存在,更新最后登录时间
        //....
        // token
        UserToken userToken = null;
        try {
            userToken = UserTokenManager.generateToken(user.getId());
        } catch (Exception e) {
            log.error("微信登录失败,生成token失败:{}", user.getId());
            e.printStackTrace();
            return ResponseUtil.fail();
        }
        userToken.setSessionKey(sessionKey);
        log.info("SessionKey={}",UserTokenManager.getSessionKey(user.getId()));
        Map<Object, Object> result = new HashMap<Object, Object>();
        result.put("token", userToken.getToken());
        result.put("tokenExpire", userToken.getExpireTime().toString());
        result.put("userInfo", userInfo);
        //....
        log.info("【请求结束】微信登录,响应结果:{}", JSONObject.toJSONString(result));
        return ResponseUtil.ok(result);
    }

The response data to the client is:

token user Info

Login-Applet

login.js

user.loginByWeixin(res.userInfo).then(res => {
    app.globalData.hasLogin = true;
    wx.navigateBack({
    delta: 1
    })
})

user.js

function loginByWeixin(userInfo) {
  return new Promise(function(resolve, reject) {
    return login().then((res) => {
      //登录远程服务器
      util.request(api.AuthLoginByWeixin, {
        code: res.code,
        userInfo: userInfo
      }, 'POST').then(res => {
        if (res.errno === 0) {
          //存储用户信息
          wx.setStorageSync('userInfo', res.data.userInfo);
          wx.setStorageSync('token', res.data.token);
          resolve(res);
        } else {
          reject(res);
        }
      })

Save userInfo and token data locally

util.js

function request(url, data = {}, method = "GET") {
  return new Promise(function (resolve, reject) {
    wx.request({
      url: url,
      data: data,
      method: method,
      timeout:6000,
      header: {
        'Content-Type': 'application/json',
        'X-OA-Token': wx.getStorageSync('token')
      },
If you use the util.request function, each request will carry 'X-OA-Token': wx.getStorageSync('token'); and the server has saved all tokens, so the server distinguishes each client by token

emoji

Mysql's utf8 encodes a character with a maximum of 3 bytes, but an emoji expression is 4 bytes, so utf8 does not support storing emoji expressions. But utf8mb4, a superset of utf8, can have up to 4 bytes per character, so it can support the storage of emoji expressions.

The configuration file of MySQL in the Linux system is my.cnf.

The configuration file in Windows is my.ini.

[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8mb4
[mysqld]
#设置3306端口
port = 3306
# 设置mysql的安装目录
basedir=D:\\tools\\mysql-5.7.23-winx64
# 设置mysql数据库的数据的存放目录
datadir=D:\\tools\\mysql-5.7.23-winx64\\data
# 允许最大连接数
max_connections=200
# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8mb4
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB

Background and front-end code sharing ----

Background: ssm-oa.rar - Lanzuoyun

Front desk: oa-mini.rar - Lanzuoyun

Guess you like

Origin blog.csdn.net/qq_62898618/article/details/128628006