SpringCloud 微信小程序授权登录 获取openId SessionKey【SpringCloud系列13】

SpringCloud 大型系列课程正在制作中,欢迎大家关注与提意见。

自我提升方法推荐:神奇的早起
早上 5:00 -5:20 起床刷牙
5:30-6:00 晨练(跑步、跳绳、骑自行车、打球等等)
6:00 - 6:30 英语晨读
6:30-7:00 文学晨读
7:20 早饭

本文章是系列文章中的一篇

本文章实现的是微信小程序授权登录。
在这里插入图片描述
实现微信小程序用户登录的方案有三种,本文章实现的是第一种。

  • 方案一 只获取用户对应的openId,来创建标记用户
  • 方案二 获取用户对应的openId与微信绑定的手机来,来创建标记用户
  • 方案三 获取微信用户的基本信息,来创建标记用户。
1 创建微信模块的服务

在微服务体系中,创建 wx-service 服务,用来实现获取微信用户的基本信息、微信支付相关。
在这里插入图片描述
配置文件 application.yml 中主要配置了连接数据库以及mybatis的相关信息,当然也可以保存在 nacos 中

server:
  port: 9701

spring:
  datasource:
    url: jdbc:mysql://mysql:3306/spring_cloud?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8&useSSL=false
    username: testadmin
    password: qwert.12345
    driver-class-name: com.mysql.jdbc.Driver
  feign:
    client:
      config:
        default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
          loggerLevel: FULL # 日志级别四种NONE、BASIC、HEADERS、FULL
    httpclient:
      enabled: true # 开启feign对HttpClient的支持
      max-connections: 200 # 最大的连接数
      max-connections-per-route: 50 # 每个路径的最大连接数

mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
#mybatis
mybatis-plus:
  mapper-locations: classpath*:**/sqlmap/*.xml
  typeAliasesPackage: com.biglead.wx.pojo
  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: false
    call-setters-on-nulls: true
    log-impl : org.apache.ibatis.logging.stdout.StdOutImpl

然后 pom.xml 中添加核心依赖如下:

    <!--        微信相关-->
    <!--weixin-java-common-->
    <dependency>
        <groupId>com.github.binarywang</groupId>
        <artifactId>weixin-java-common</artifactId>
    </dependency>
    <!--weixin-java-miniapp-->
    <dependency>
        <groupId>com.github.binarywang</groupId>
        <artifactId>weixin-java-miniapp</artifactId>
    </dependency>
    <!--weixin-java-mp-->
    <dependency>
        <groupId>com.github.binarywang</groupId>
        <artifactId>weixin-java-mp</artifactId>
    </dependency>
    <!--weixin-java-open-->
    <dependency>
        <groupId>com.github.binarywang</groupId>
        <artifactId>weixin-java-open</artifactId>
    </dependency>

2 数据库配置小程序的基本信息

本项目的设计理念是中台服务架构,是支持多个小程序来共用的,所以这里采用数据库来保存小程序的基本信息,然后在调用登录相关的认证时,根据不同的小程序,来查询不同的配置。

CREATE TABLE `tb_wx_app` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `app_id` varchar(100) DEFAULT NULL COMMENT '微信小程序的appid',
  `secret` varchar(100) DEFAULT NULL COMMENT '微信小程序的Secret',
  `token` varchar(255) DEFAULT NULL COMMENT '微信小程序消息服务器配置的token',
  `aes_key` varchar(100) DEFAULT NULL COMMENT '微信小程序消息服务器配置的EncodingAESKey',
  `msg_data_format` varchar(10) DEFAULT NULL,
  `mini_name` varchar(30) DEFAULT NULL COMMENT '小程序的名称',
  `app_type` varchar(30) DEFAULT 'mini' COMMENT '类型: mini 默认小程序;h5,app',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

然后把测试小程序的基本信息添加到数据库中
在这里插入图片描述
在 wx-service 服务中创建对应的数据模型

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_wx_app")
public class WxAppInfo implements Serializable {
    private Long id;
    //微信小程序的appid
    private  String appId;
    private  String secret;//微信小程序的Secret
    private  String token;// #微信小程序消息服务器配置的token
    private  String aesKey;// #微信小程序消息服务器配置的EncodingAESKey
    private  String msgDataFormat;//JSON
    private String appType;
}

当然可以将这个类放到公共库中,也可能其他服务会使用到,然后创建对应的 Mapper

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.biglead.wx.pojo.WxAppInfo;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface WxAppInfoMapper extends BaseMapper<WxAppInfo> {
    

}

然后创建对应的 WxAppInfoService

import com.baomidou.mybatisplus.extension.service.IService;
import com.biglead.wx.pojo.WxAppInfo;

public interface WxAppInfoService extends IService<WxAppInfo> {

    /**查询小程序详情*/
    WxAppInfo queryByAppId(String appId);
}

对应的实现类 WxAppInfoServiceImpl

@Service
@Slf4j
public class WxAppInfoServiceImpl extends ServiceImpl<WxAppInfoMapper, WxAppInfo> implements WxAppInfoService {
    @Override
    public WxAppInfo queryByAppId(String appId) {
        WxAppInfo orderInfo = this.getOne(new LambdaQueryWrapper<WxAppInfo>().eq(WxAppInfo::getAppId, appId));
        if (orderInfo == null) {
            throw new RuntimeException("未查询到小程序");
        }
        return orderInfo;
    }

3 根据code来获取openId

首先是定义的 Controller

/**
 * 微信用户相关杢
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/wx")
public class WxUserController {
    @Autowired
    private WxAppLoginService wxAppLoginService;
    
    @ApiOperation(value = "小程序用户登录-只有code")
    @PostMapping("/login_by_code")
    public Map<String,Object> loginMaByCode( @RequestBody MiniLoginRequest loginDTO){
        return wxAppLoginService.loginByCode(loginDTO);
    }
}

MiniLoginRequest 是基本的请求体,定义如下:

import lombok.Data;
@Data
public class MiniLoginCodeRequest {
    //用户登录凭证
    String code;
    //登录的小程序
    String appId;
}

WxAppLoginService 是具体的实现逻辑,定义如下

public interface WxAppLoginService {
    /**根据code 来获取 openId*/
    Map<String, Object> loginByCode(MiniLoginCodeRequest loginDTO);
}

实现类 WxAppLoginServiceImpl 定义如下:

@Service
@Slf4j
public class WxAppLoginServiceImpl implements WxAppLoginService {

    //查询数据库小程序配置
    @Autowired
    private WxAppInfoService wxAppInfoService;
   @Override
    public Map<String, Object> loginByCode(MiniLoginCodeRequest loginDTO) {

        //根据AppId,获取基本配置,构建 WxMaService
        final WxMaService wxService = getWxMaService(loginDTO.getAppId());

        // 获取微信用户session
        WxMaJscode2SessionResult session = null;
        try {
            session = wxService.getUserService().getSessionInfo(loginDTO.getCode());
        } catch (WxErrorException e) {
            Map<String, Object> map = new HashMap<>();
            map.put("message", e.getMessage());
            map.put("code", 400);
            return map;
        }
        if (null == session) {
            Map<String, Object> map = new HashMap<>();
            map.put("message", "获取session失败");
            map.put("code", 400);
            return map;

        }
        String openid = session.getOpenid();
        String sessionKey = session.getSessionKey();
        log.info("微信登录 openid {}  sessionKey {}", openid, sessionKey);

        Map<String, Object> map = new HashMap<>();
        map.put("openId", openid);
        map.put("sessionKey", sessionKey);
        map.put("code", 200);
        return map;
    }

    private WxMaService getWxMaService(String appId) {
        //查询数据库小程序的配置
        WxAppInfo wxAppInfo = wxAppInfoService.queryByAppId(appId);
        String appSecret = wxAppInfo.getSecret();

        WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
        config.setAppid(appId);
        config.setSecret(appSecret);
        config.setMsgDataFormat("JSON");
        WxMaService wxMaService = new WxMaServiceImpl();
        wxMaService.setWxMaConfig(config);
        return wxMaService;
    }
}

这样对应的微信用户的openId 与 sessionKey 就查询成功了,然后再根据这里的 openId 来查询用户服务中是否有用户,没有则创建,代码量过多,大家可以查看本项目的源码,这里的服务调用关系如下:

在这里插入图片描述

4 微信小程序对应的实现

wxml文件中定义的按钮

<view>
  <view style='width:100%;padding-left:30rpx;font-size: 30rpx;margin-top:50rpx;'>
    <button type="primary" bindtap="doLogin">微信一键登录</button>
  </view>
</view>

对应的 js 核心实现

/** 用户信息 */
  doLogin: function (callback = () => {}) {
    let that = this;
    wx.login({
      success: function (loginRes) {
        if (loginRes) {
          that.requestSessionFunction(loginRes);
        } else {
          wx.showToast({
            title: '授权失败',
            icon: 'error',
            duration: 2000
           })
        }
      }
    });
  },
  //业务后台获取信息
  requestSessionFunction(loginRes) {
    let that = this;
    wx.request({
      url: api.AuthLoginBySessionKey,
      method: "post",
      header: {
        'appId': 'wx27c83f987452ccec'
      },
      data: {
        code: loginRes.code,
      },
      success: function (res) {
        console.log('login success');
        console.log("res:", res)
        wx.setStorageSync('token', res.data.data.access_token);
        wx.setStorageSync('userInfo', res.data.data);
        console.log("access_token=" + res.data.data.access_token);
        wx.navigateBack();
      },
      fail: function (error) {
        //调用服务端登录接口失败
        console.log(error);
        wx.navigateBack();
      }
    });
  },

效果预览
在这里插入图片描述

本项目 SpringCloud 源码 https://gitee.com/android.long/spring-cloud-biglead/tree/master/biglead-api-11-admin
本项目 管理后台web 源码https://gitee.com/android.long/spring-cloud-biglead/tree/master/mall-admin-web-master
本项目 小程序 源码https://gitee.com/android.long/spring-cloud-biglead/tree/master/mall-app-web-master
如果有兴趣可以关注一下公众号 biglead ,每周都会有 java、Flutter、小程序、js 、英语相关的内容分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

早起的年轻人

创作源于分享

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值