小程序的登陆流程,我们见这张图就好
下面我将根据这个流程,以实战代码讲解,请耐心阅读。
后端配置准备
引入小程序maven,其余springboot那些依赖我就不讲了。
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>4.1.0</version>
</dependency>
yml配置小程序信息:
wx:
miniapp:
configs:
- appid: #微信小程序的appid
secret: #微信小程序的Secret
token: #微信小程序消息服务器配置的token
aesKey: #微信小程序消息服务器配置的EncodingAESKey
msgDataFormat: JSON
新增小程序配置类WxMaConfiguration:
@Configuration
@EnableConfigurationProperties(WxMaProperties.class)
public class WxMaConfiguration {
@Autowired
WxMaProperties properties;
public static final Map<String, WxMaService> serviceList = Maps.newHashMap();
public WxMaService getService(String appId) {
if (serviceList.containsKey(appId)) {
return serviceList.get(appId);
}
throw new RuntimeException("appId不存在");
}
@PostConstruct
public void init() {
List<WxMaProperties.Config> configs = this.properties.getConfigs();
if (CollectionUtils.isEmpty(configs)) {
throw new WxRuntimeException("请添加wx.miniapp 小程序信息配置!");
}
for (WxMaProperties.Config cfg : configs) {
WxMaService maService = new WxMaServiceImpl();
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
config.setAppid(cfg.getAppid());
config.setSecret(cfg.getSecret());
config.setToken(cfg.getToken());
config.setAesKey(cfg.getAesKey());
config.setMsgDataFormat(cfg.getMsgDataFormat());
maService.setWxMaConfig(config);
serviceList.put(cfg.getAppid(), maService);
}
}
}
属性文件WxMaProperties:
@Data
@ConfigurationProperties(prefix = "wx.miniapp")
public class WxMaProperties {
private List<Config> configs;
@Data
public static class Config {
/**
* 设置微信小程序的appid
*/
private String appid;
/**
* 设置微信小程序的Secret
*/
private String secret;
/**
* 设置微信小程序消息服务器配置的token
*/
private String token;
/**
* 设置微信小程序消息服务器配置的EncodingAESKey
*/
private String aesKey;
/**
* 消息格式,XML或者JSON
*/
private String msgDataFormat;
}
}
到此基础配置信息就搞好了,我们还要准备两张表,一张是存储授权信息,一张是用户信息。
CREATE TABLE `user_info` (
`user_id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`username` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '用户名',
`password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '密码',
`mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '电话',
`email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '邮箱',
`nick_name` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '昵称',
`sex` smallint DEFAULT '0' COMMENT '性别. 0:未知;1:男;2:女',
`avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '头像',
`logout_time` timestamp NULL DEFAULT NULL COMMENT '最近登出时间',
`creator` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '创建人',
`create_time` timestamp NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '更新人',
`update_time` timestamp NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`user_id`) USING BTREE
) ENGINE=InnoDB COMMENT='用户信息';
CREATE TABLE `user_oauth` (
`id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`user_id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '用户ID',
`openid` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`valid_status` smallint DEFAULT '1' COMMENT '有效状态. 1:有效;0:无效',
`creator` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`create_time` timestamp NULL DEFAULT NULL COMMENT '创建时间',
`updater` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`update_time` timestamp NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC COMMENT='授权信息';
用户表的字段根据你业务需要扩展。
前后端逻辑实现
- 前端发起wx登录获取code
uni.login({
provider: 'weixin',
success: function(loginRes) {
// 前端获取到微信登录临时码,传至后台
let code = loginRes.code
// 调用后台接口根据code获取openid
wxLogin(code).then((wxRes) => {
resolve(wxRes)
})
},
})
2.前端调用后台login接口 ,传参:appId和code
// 请求后台微信小程序登录
export const wxLogin = (code) => {
return new Promise((resolve) => {
let inviterUserId = getCurQuery('inviterUserId')
console.debug(`调用微信小程序登录. inviterUserId=${inviterUserId || ''}`)
post(`/core/user/login?loginType=WXMP`, {
appid: config.appId,
code: code
}).then((res) => {
console.log(res);
if ('success' == res.status) {
console.debug('微信小程序登录成功')
}
})
})
}
调用成功后,后端会返回openid 和 token信息,token是为了保持登录的。前端存储到本地,下次就直接登录成功。
3. 后端login接口
public V login(LoginDTO dto) {
String appid = (String) dto.getAppid();
String code = (String) dto.getCode();
if (StringUtils.isEmpty(appid) || StringUtils.isEmpty(code)) {
return V.err("参数异常");
}
// 获取服务
WxMaService service = wxMaConfiguration.getService(appid);
WxMaJscode2SessionResult session = null;
try {
// 获取登录信息
session = service.getUserService().getSessionInfo(code);
} catch (WxErrorException e) {
throw new RuntimeException("登录异常");
}
String openid = session.getOpenid();
// 查询数据库信息
UserOauth oauth = userOauthMapper.selectOne(new LambdaQueryWrapper<UserOauth>().eq(UserOauth::getValidStatus, 1)
.eq(UserOauth::getLoginType, dto.getTyper()).eq(UserOauth::getOpenid, openid).last("limit 1"));
if (oauth == null) {
// 插入用户信息
UserInfo user = new UserInfo();
user.setUserId(IdUtil.getSnowflakeNextIdStr());// 主键
user.setUsername("默认昵称_"+IdUtil.getSnowflakeNextIdStr());
user.setNickName("默认昵称_"+IdUtil.getSnowflakeNextIdStr());
userInfoMapper.insert(user) ;
// 插入授权信息
oauth = new UserOauth();
oauth.setId(IdUtil.getSnowflakeNextIdStr());
oauth.setUserId(user.getUserId());
oauth.setLoginType(dto.getTyper());
oauth.setOpenid(openid);
oauth.setValidStatus(1);
// 插入数据库
userOauthMapper.insert(oauth);
}
// token登录
StpUtil.login(oauth.getUserId());
SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
Map<String,Object> ret = new HashMap<>();
ret.put("tokenInfo" , tokenInfo) ;
ret.put("openid" , openid) ;
return V.success(ret);
}
后端接口其实很简单,如果是第一次授权,openid在授权表中是没有的,就 插入授权信息,同时新增用户,然后在生成token(至于用什么框架生成自己选),然后将openid和token返回给前端。
用户评论