SpringCloud 大型系列课程正在制作中,欢迎大家关注与提意见。
自我提升方法推荐:神奇的早起
早上 5:00 -5:20 起床刷牙
5:30-6:00 晨练(跑步、跳绳、骑自行车、打球等等)
6:00 - 6:30 英语晨读
6:30-7:00 文学晨读
7:20 早饭
本文章是系列文章中的一篇
- 1、SpringCloud 项目基础工程搭建 【SpringCloud系列1】
- 2、SpringCloud 集成Nacos注册中心 【SpringCloud系列2】
- 3、SpringCloud Feign远程调用 【SpringCloud系列3】
- 4、SpringCloud Feign远程调用公共类抽取 【SpringCloud系列4】
- 5、SpringCloud 整合Gateway服务网关 【SpringCloud系列5】
- 6、SpringCloud 整合 Spring Security 认证鉴权【SpringCloud系列6】
- SpringCloud网关Gateway认证鉴权【SpringCloud系列7】
- SpringCloud Gateway 通过redis实现限流【SpringCloud系列8】
- SpringCloud Gateway 整合阿里 Sentinel网关流控、熔断、降级【SpringCloud系列9】
- SpringCloud Gateway 整合RSA对请求参数解密、响应结果加密【SpringCloud系列10】
- SpringCloud 业务管理后台 通过FeignClient来调用oauth/token接口【SpringCloud系列11】
- Spring Security OAuth2.0 多点登录与单点登录【SpringCloud系列12】
本文章实现的是微信小程序授权登录。
实现微信小程序用户登录的方案有三种,本文章实现的是第一种。
- 方案一 只获取用户对应的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 、英语相关的内容分享