新增微信登录模块

This commit is contained in:
wanggeng888 2021-04-08 22:53:25 +08:00
parent 9611a5fc54
commit 57e7d5aea7
13 changed files with 715 additions and 0 deletions

22
login-wechat/pom.xml Normal file
View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>wg-basic</artifactId>
<groupId>ink.wgink</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>login-wechat</artifactId>
<dependencies>
<dependency>
<groupId>ink.wgink</groupId>
<artifactId>login-base</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,93 @@
package ink.wgink.login.wechat.config.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: WechatMiniProgramProperties
* @Description: 微信小程序
* @Author: WangGeng
* @Date: 2020/5/9 15:50
* @Version: 1.0
**/
@Configuration
@ConfigurationProperties(prefix = "open-platform.wechat.mini-app")
public class MiniAppProperties {
private Boolean active;
private String authorizeUrl;
private String bindUserUrl;
private String grantType;
private String appKey;
private String appSecret;
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
public String getAuthorizeUrl() {
return authorizeUrl == null ? "" : authorizeUrl;
}
public void setAuthorizeUrl(String authorizeUrl) {
this.authorizeUrl = authorizeUrl;
}
public String getBindUserUrl() {
return bindUserUrl == null ? "" : bindUserUrl;
}
public void setBindUserUrl(String bindUserUrl) {
this.bindUserUrl = bindUserUrl;
}
public String getGrantType() {
return grantType == null ? "" : grantType;
}
public void setGrantType(String grantType) {
this.grantType = grantType;
}
public String getAppKey() {
return appKey == null ? "" : appKey;
}
public void setAppKey(String appKey) {
this.appKey = appKey;
}
public String getAppSecret() {
return appSecret == null ? "" : appSecret;
}
public void setAppSecret(String appSecret) {
this.appSecret = appSecret;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"active\":")
.append(active);
sb.append(",\"authorizeUrl\":\"")
.append(authorizeUrl).append('\"');
sb.append(",\"bindUserUrl\":\"")
.append(bindUserUrl).append('\"');
sb.append(",\"grantType\":\"")
.append(grantType).append('\"');
sb.append(",\"appKey\":\"")
.append(appKey).append('\"');
sb.append(",\"appSecret\":\"")
.append(appSecret).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,39 @@
package ink.wgink.login.wechat.controller.api.sign;
import ink.wgink.annotation.CheckRequestBodyAnnotation;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.login.wechat.pojo.vos.sign.MiniAppLoginVO;
import ink.wgink.login.wechat.service.sign.IMiniAppSignService;
import ink.wgink.pojo.result.SuccessResultData;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: MiniSignWechatController
* @Description: 小程序登录
* @Author: wanggeng
* @Date: 2021/4/8 5:08 下午
* @Version: 1.0
*/
@Api(tags = ISystemConstant.API_TAGS_WECHAT_MINI_APP_PREFIX + "小程序登录")
@RestController
@RequestMapping(ISystemConstant.WECHAT_MINI_APP_PREFIX + "/sign")
public class MiniAppSignController {
@Autowired
private IMiniAppSignService miniAppSignService;
@PostMapping("default")
@CheckRequestBodyAnnotation
public SuccessResultData<String> defaultSign(@RequestBody MiniAppLoginVO miniAppLoginVO) throws Exception {
return new SuccessResultData<>(miniAppSignService.defaultSign(miniAppLoginVO));
}
}

View File

@ -0,0 +1,47 @@
package ink.wgink.login.wechat.dao.user;
import ink.wgink.exceptions.SaveException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.UpdateException;
import ink.wgink.login.wechat.pojo.pos.user.MiniAppUserPO;
import org.springframework.stereotype.Repository;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: IMiniAppUserDao
* @Description: 小程序用户
* @Author: wanggeng
* @Date: 2021/4/8 5:39 下午
* @Version: 1.0
*/
@Repository
public interface IMiniAppUserDao {
/**
* 建表
*
* @throws UpdateException
*/
void createTable() throws UpdateException;
/**
* 新增
*
* @param params
* @throws SaveException
*/
void save(Map<String, Object> params) throws SaveException;
/**
* 详情
*
* @param params
* @return
* @throws SearchException
*/
MiniAppUserPO getPO(Map<String, Object> params) throws SearchException;
}

View File

@ -0,0 +1,88 @@
package ink.wgink.login.wechat.pojo.bos.user;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: WechatMiniAppUserInfo
* @Description: 微信小程序用户信息
* @Author: WangGeng
* @Date: 2020/5/9 18:29
* @Version: 1.0
**/
public class MiniAppUserInfoBO {
private String openid;
private String session_key;
private String unionid;
private Integer errcode;
private String errmsg;
private long updateTime;
public String getOpenid() {
return openid == null ? "" : openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getSession_key() {
return session_key == null ? "" : session_key;
}
public void setSession_key(String session_key) {
this.session_key = session_key;
}
public String getUnionid() {
return unionid == null ? "" : unionid;
}
public void setUnionid(String unionid) {
this.unionid = unionid;
}
public Integer getErrcode() {
return errcode;
}
public void setErrcode(Integer errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg == null ? "" : errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
public long getUpdateTime() {
return updateTime;
}
public void setUpdateTime(long updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"openid\":\"")
.append(openid).append('\"');
sb.append(",\"session_key\":\"")
.append(session_key).append('\"');
sb.append(",\"unionid\":\"")
.append(unionid).append('\"');
sb.append(",\"errcode\":")
.append(errcode);
sb.append(",\"errmsg\":\"")
.append(errmsg).append('\"');
sb.append(",\"updateTime\":")
.append(updateTime);
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,63 @@
package ink.wgink.login.wechat.pojo.pos.user;
import java.io.Serializable;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: MiniAppUserPO
* @Description: 小程序用户
* @Author: wanggeng
* @Date: 2021/4/8 5:49 下午
* @Version: 1.0
*/
public class MiniAppUserPO implements Serializable {
private static final long serialVersionUID = -8186629510739913926L;
private String appId;
private String openId;
private String userId;
private Integer isInitAccount;
private String gmtCreate;
public String getAppId() {
return appId == null ? "" : appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getOpenId() {
return openId == null ? "" : openId;
}
public void setOpenId(String openId) {
this.openId = openId;
}
public String getUserId() {
return userId == null ? "" : userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public Integer getIsInitAccount() {
return isInitAccount == null ? 0 : isInitAccount;
}
public void setIsInitAccount(Integer isInitAccount) {
this.isInitAccount = isInitAccount;
}
public String getGmtCreate() {
return gmtCreate == null ? "" : gmtCreate;
}
public void setGmtCreate(String gmtCreate) {
this.gmtCreate = gmtCreate;
}
}

View File

@ -0,0 +1,40 @@
package ink.wgink.login.wechat.pojo.vos.sign;
import ink.wgink.annotation.CheckEmptyAnnotation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: WechatMiniProgramLoginVO
* @Description: 小程序登录VO
* @Author: WangGeng
* @Date: 2020/5/9 18:12
* @Version: 1.0
**/
@ApiModel
public class MiniAppLoginVO {
@ApiModelProperty(name = "jsCode", value = "临时code")
@CheckEmptyAnnotation(name = "jsCode")
private String jsCode;
public String getJsCode() {
return jsCode == null ? "" : jsCode;
}
public void setJsCode(String jsCode) {
this.jsCode = jsCode;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"jsCode\":\"")
.append(jsCode).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,28 @@
package ink.wgink.login.wechat.service.sign;
import ink.wgink.login.wechat.pojo.vos.sign.MiniAppLoginVO;
import ink.wgink.pojo.result.SuccessResultData;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: IMiniAppSignService
* @Description: 小程序登录
* @Author: wanggeng
* @Date: 2021/4/8 5:14 下午
* @Version: 1.0
*/
public interface IMiniAppSignService {
String WECHAT_RANDOM_USER_PREFIX = "WX_";
/**
* 默认登录
*
* @param miniAppLoginVO
* @return
* @throws Exception
*/
String defaultSign(MiniAppLoginVO miniAppLoginVO) throws Exception;
}

View File

@ -0,0 +1,82 @@
package ink.wgink.login.wechat.service.sign.impl;
import com.alibaba.fastjson.JSONObject;
import ink.wgink.exceptions.PropertiesException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.WechatAccessTokenForUserException;
import ink.wgink.exceptions.WechatUserInfoException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.login.base.service.BaseAppSignService;
import ink.wgink.login.wechat.config.properties.MiniAppProperties;
import ink.wgink.login.wechat.pojo.bos.user.MiniAppUserInfoBO;
import ink.wgink.login.wechat.pojo.vos.sign.MiniAppLoginVO;
import ink.wgink.login.wechat.service.sign.IMiniAppSignService;
import ink.wgink.login.wechat.service.user.IMiniAppUserService;
import ink.wgink.service.user.pojo.pos.UserPO;
import ink.wgink.service.user.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: MiniAppSignServiceImpl
* @Description: 小程序登录
* @Author: wanggeng
* @Date: 2021/4/8 5:14 下午
* @Version: 1.0
*/
@Service
public class MiniAppSignServiceImpl extends BaseAppSignService implements IMiniAppSignService {
@Autowired
private MiniAppProperties miniAppProperties;
@Autowired
private IMiniAppUserService miniAppUserService;
@Autowired
private IUserService userService;
@Override
public String defaultSign(MiniAppLoginVO miniAppLoginVO) throws Exception {
if (miniAppLoginVO == null) {
throw new PropertiesException("未有相关配置");
}
if (miniAppProperties.getActive() == null || !miniAppProperties.getActive()) {
throw new PropertiesException("未激活小程序配置");
}
Map<String, Object> params = new HashMap<>(2);
params.put("appid", miniAppProperties.getAppKey());
params.put("secret", miniAppProperties.getAppSecret());
params.put("js_code", miniAppLoginVO.getJsCode());
params.put("grant_type", miniAppProperties.getGrantType());
StringBuilder url = new StringBuilder(miniAppProperties.getAuthorizeUrl());
url.append("?appid={appid}&secret={secret}&js_code={js_code}&grant_type={grant_type}");
RestTemplate restTemplate = new RestTemplate();
String resultJson = restTemplate.getForObject(url.toString(), String.class, params);
MiniAppUserInfoBO miniAppUserInfoBO = JSONObject.parseObject(resultJson, MiniAppUserInfoBO.class);
if (miniAppUserInfoBO == null) {
throw new WechatUserInfoException("获取微信用户信息失败");
}
if (miniAppUserInfoBO.getErrcode() != null && miniAppUserInfoBO.getErrcode() != 0) {
throw new WechatAccessTokenForUserException(String.format("获取用户信息失败,错误码:%s错误信息%s", miniAppUserInfoBO.getErrcode(), miniAppUserInfoBO.getErrmsg()));
}
LOG.debug("绑定用户");
String userId = miniAppUserService.createAndReturnUserId(miniAppProperties.getAppKey(), miniAppUserInfoBO.getOpenid());
UserPO userPO = userService.getPO(userId);
if (userPO == null) {
throw new SearchException("用户不存在");
}
String isRandomUsername = ISystemConstant.IS_FALSE_INT;
if (userPO.getUserUsername().startsWith(IMiniAppSignService.WECHAT_RANDOM_USER_PREFIX)) {
isRandomUsername = ISystemConstant.IS_TRUE_INT;
}
return getToken(userPO) + "_" + isRandomUsername;
}
}

View File

@ -0,0 +1,54 @@
package ink.wgink.login.wechat.service.user;
import ink.wgink.login.wechat.pojo.pos.user.MiniAppUserPO;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: IMiniAppUserService
* @Description: 小程序用户
* @Author: wanggeng
* @Date: 2021/4/8 5:37 下午
* @Version: 1.0
*/
public interface IMiniAppUserService {
/**
* 创建用户并返回用户ID已经存在的不操作
*
* @param appKey
* @param openId
* @return
* @throws Exception
*/
String createAndReturnUserId(String appKey, String openId) throws Exception;
/**
* 详情
*
* @param params
* @return
*/
MiniAppUserPO getPO(Map<String, Object> params);
/**
* 详情
*
* @param userId
* @return
*/
MiniAppUserPO getPO(String userId);
/**
* 详情
*
* @param appId
* @param openId
* @return
*/
MiniAppUserPO getPO(String appId, String openId);
}

View File

@ -0,0 +1,83 @@
package ink.wgink.login.wechat.service.user.impl;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.login.wechat.dao.user.IMiniAppUserDao;
import ink.wgink.login.wechat.pojo.pos.user.MiniAppUserPO;
import ink.wgink.login.wechat.service.sign.IMiniAppSignService;
import ink.wgink.login.wechat.service.user.IMiniAppUserService;
import ink.wgink.service.user.pojo.pos.UserPO;
import ink.wgink.service.user.pojo.vos.UserVO;
import ink.wgink.service.user.service.IUserService;
import ink.wgink.util.date.DateUtil;
import ink.wgink.util.map.HashMapUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: MiniAppUserServiceImpl
* @Description: 小程序用户
* @Author: wanggeng
* @Date: 2021/4/8 5:38 下午
* @Version: 1.0
*/
@Service
public class MiniAppUserServiceImpl extends DefaultBaseService implements IMiniAppUserService {
@Value("${user.default-password:888888}")
private String defaultPassword;
@Autowired
private IMiniAppUserDao miniAppUserDao;
@Autowired
private IUserService userService;
@Override
public String createAndReturnUserId(String appKey, String openId) {
MiniAppUserPO miniAppUserPO = getPO(appKey, openId);
if (miniAppUserPO != null) {
LOG.debug("已经绑定小程序用户");
return miniAppUserPO.getUserId();
}
UserVO userVO = new UserVO();
userVO.setUserUsername(IMiniAppSignService.WECHAT_RANDOM_USER_PREFIX + openId);
userVO.setUserName("微信" + openId.substring(0, 6));
userVO.setUserPassword(defaultPassword);
userVO.setUserState(0);
userVO.setUserType(2);
String userId = userService.saveAndReturnId(userVO, true);
Map<String, Object> params = getHashMap(6);
params.put("appId", appKey);
params.put("openId", openId);
params.put("userId", userId);
params.put("isInitAccount", 1);
params.put("gmtCreate", DateUtil.getTime());
miniAppUserDao.save(params);
return userId;
}
@Override
public MiniAppUserPO getPO(Map<String, Object> params) {
return miniAppUserDao.getPO(params);
}
@Override
public MiniAppUserPO getPO(String userId) {
Map<String, Object> params = getHashMap(2);
params.put("userId", userId);
return getPO(params);
}
@Override
public MiniAppUserPO getPO(String appId, String openId) {
Map<String, Object> params = getHashMap(4);
params.put("appId", appId);
params.put("openId", openId);
return getPO(params);
}
}

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ink.wgink.login.wechat.dao.user.IMiniAppUserDao">
<cache flushInterval="3600000"/>
<resultMap id="miniAppUserPO" type="ink.wgink.login.wechat.pojo.pos.user.MiniAppUserPO">
<result column="app_id" property="appId"/>
<result column="open_id" property="openId"/>
<result column="user_id" property="userId"/>
<result column="is_init_account" property="isInitAccount"/>
<result column="gmt_create" property="gmtCreate"/>
</resultMap>
<!-- 建表 -->
<update id="createTable">
CREATE TABLE `wechat_mini_app_user` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`app_id` varchar(255) DEFAULT NULL COMMENT 'appid',
`open_id` varchar(255) DEFAULT NULL COMMENT 'openid',
`user_id` varchar(255) DEFAULT NULL COMMENT '用户ID',
`is_init_account` int(1) DEFAULT '0' COMMENT '是否初始化账户',
`gmt_create` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `app_id` (`app_id`) USING BTREE,
KEY `open_id` (`open_id`) USING BTREE,
KEY `user_id` (`user_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='小程序用户';
</update>
<!-- 保存 -->
<insert id="save" parameterType="map">
INSERT INTO wechat_mini_app_user(
app_id,
open_id,
user_id,
is_init_account,
gmt_create
) VALUES(
#{appId},
#{openId},
#{userId},
#{isInitAccount},
#{gmtCreate}
)
</insert>
<!-- 详情 -->
<select id="getPO" parameterType="map" resultMap="miniAppUserPO" useCache="true">
SELECT
app_id,
open_id,
user_id,
is_init_account,
gmt_create
FROM
wechat_mini_app_user
<where>
<if test="appId != null and appId != ''">
app_id = #{appId}
</if>
<if test="openId != '' and openId != ''">
AND
open_id = #{openId}
</if>
<if test="userId != null and userId != ''">
AND
user_id = #{userId}
</if>
</where>
</select>
</mapper>

View File

@ -27,6 +27,7 @@
<module>service-position</module>
<module>login-base</module>
<module>login-app</module>
<module>login-wechat</module>
</modules>
<packaging>pom</packaging>