createTable

Business logic adjustment
This commit is contained in:
WenG 2021-04-28 23:01:14 +08:00
parent 9d7b8407d9
commit f5d7c61123
10 changed files with 420 additions and 51 deletions

View File

@ -5,7 +5,7 @@ import ink.wgink.exceptions.ParamsException;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.module.wechat.enums.XmlEventTypeEnum;
import ink.wgink.module.wechat.enums.XmlMsgTypeEnum;
import ink.wgink.module.wechat.pojo.vos.official.account.OfficialAccountUserPO;
import ink.wgink.module.wechat.pojo.vos.official.account.OfficialAccountUserVO;
import ink.wgink.module.wechat.result.OfficialAccountEventResult;
import ink.wgink.module.wechat.service.official.account.IOfficialAccountCheckService;
import ink.wgink.module.wechat.service.official.account.IOfficialAccountUserService;
@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.concurrent.CompletableFuture;
/**
@ -47,7 +48,6 @@ public class OfficialAccountWechatController extends DefaultBaseController {
@RequestMapping("event")
public void event(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 处理认证
if (StringUtils.equalsIgnoreCase(HttpMethod.GET.toString(), request.getMethod())) {
officialAccountCheckService.checkSignature(request, response);
@ -57,7 +57,11 @@ public class OfficialAccountWechatController extends DefaultBaseController {
if (StringUtils.equalsIgnoreCase(HttpMethod.POST.toString(), request.getMethod())) {
AsyncContext asyncContext = request.startAsync();
CompletableFuture.runAsync(() -> {
try {
handleMsgType(asyncContext, request, response);
} catch (IOException e) {
LOG.error(e.getMessage(), e);
}
});
return;
}
@ -70,22 +74,35 @@ public class OfficialAccountWechatController extends DefaultBaseController {
* @param request
* @param response
*/
private void handleMsgType(AsyncContext asyncContext, HttpServletRequest request, HttpServletResponse response) {
private void handleMsgType(AsyncContext asyncContext, HttpServletRequest request, HttpServletResponse response) throws IOException {
OfficialAccountEventResult officialAccountEventResult = getEventResult(request);
// 解析完流之后直接返回防止微信服务器重复请求
PrintWriter writer = response.getWriter();
writer.write("");
writer.flush();
asyncContext.complete();
// 处理消息事件
if (officialAccountEventResult == null) {
throw new ParamsException("事件错误");
}
if (StringUtils.equalsIgnoreCase(XmlMsgTypeEnum.EVENT.getValue(), officialAccountEventResult.getMsgType())) {
handleEvent(officialAccountEventResult, asyncContext, request, response);
}
handleEvent(officialAccountEventResult, request, response);
}
// 处理事件
private void handleEvent(OfficialAccountEventResult officialAccountEventResult, AsyncContext asyncContext, HttpServletRequest request, HttpServletResponse response) {
}
/**
* 处理事件
*
* @param officialAccountEventResult
* @param request
* @param response
*/
private void handleEvent(OfficialAccountEventResult officialAccountEventResult, HttpServletRequest request, HttpServletResponse response) {
if (StringUtils.equalsIgnoreCase(XmlEventTypeEnum.SUBSCRIBE.getType(), officialAccountEventResult.getEvent())) {
OfficialAccountUserPO officialAccountUserPO = new OfficialAccountUserPO();
officialAccountUserPO.setOpenId(officialAccountEventResult.getFromUserName());
officialAccountUserService.save(officialAccountUserPO);
OfficialAccountUserVO officialAccountUserVO = new OfficialAccountUserVO();
officialAccountUserVO.setOpenId(officialAccountEventResult.getFromUserName());
officialAccountUserService.save(officialAccountUserVO);
} else if (StringUtils.equalsIgnoreCase(XmlEventTypeEnum.UNSUBSCRIBE.getType(), officialAccountEventResult.getEvent())) {
officialAccountUserService.updateStatus(officialAccountEventResult.getFromUserName(), XmlEventTypeEnum.UNSUBSCRIBE);
}

View File

@ -5,7 +5,7 @@ import ink.wgink.exceptions.SaveException;
import ink.wgink.exceptions.SearchException;
import ink.wgink.exceptions.UpdateException;
import ink.wgink.module.wechat.pojo.dtos.official.account.OfficialAccountUserDTO;
import ink.wgink.module.wechat.pojo.vos.official.account.OfficialAccountUserPO;
import ink.wgink.module.wechat.pojo.pos.official.account.OfficialAccountUserPO;
import org.springframework.stereotype.Repository;
import java.util.List;

View File

@ -11,4 +11,77 @@ package ink.wgink.module.wechat.pojo.dtos.official.account;
* @Version: 1.0
*/
public class OfficialAccountUserDTO {
private String appId;
private String openId;
private String userId;
private String userCode;
private Integer isInitAccount;
private String gmtCreate;
private String gmtModified;
private String status;
public String getAppId() {
return appId == null ? "" : appId.trim();
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getOpenId() {
return openId == null ? "" : openId.trim();
}
public void setOpenId(String openId) {
this.openId = openId;
}
public String getUserId() {
return userId == null ? "" : userId.trim();
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserCode() {
return userCode == null ? "" : userCode.trim();
}
public void setUserCode(String userCode) {
this.userCode = userCode;
}
public Integer getIsInitAccount() {
return isInitAccount;
}
public void setIsInitAccount(Integer isInitAccount) {
this.isInitAccount = isInitAccount;
}
public String getGmtCreate() {
return gmtCreate == null ? "" : gmtCreate.trim();
}
public void setGmtCreate(String gmtCreate) {
this.gmtCreate = gmtCreate;
}
public String getGmtModified() {
return gmtModified == null ? "" : gmtModified.trim();
}
public void setGmtModified(String gmtModified) {
this.gmtModified = gmtModified;
}
public String getStatus() {
return status == null ? "" : status.trim();
}
public void setStatus(String status) {
this.status = status;
}
}

View File

@ -1,4 +1,4 @@
package ink.wgink.module.wechat.pojo.vos.official.account;
package ink.wgink.module.wechat.pojo.pos.official.account;
/**
* When you feel like quitting. Think about why you started
@ -18,6 +18,8 @@ public class OfficialAccountUserPO {
private String userCode;
private Integer isInitAccount;
private String gmtCreate;
private String gmtModified;
private String status;
public String getAppId() {
return appId == null ? "" : appId;
@ -66,4 +68,20 @@ public class OfficialAccountUserPO {
public void setGmtCreate(String gmtCreate) {
this.gmtCreate = gmtCreate;
}
public String getGmtModified() {
return gmtModified == null ? "" : gmtModified.trim();
}
public void setGmtModified(String gmtModified) {
this.gmtModified = gmtModified;
}
public String getStatus() {
return status == null ? "" : status.trim();
}
public void setStatus(String status) {
this.status = status;
}
}

View File

@ -1,4 +1,4 @@
package ink.wgink.module.wechat.pojo.pos.official.account;
package ink.wgink.module.wechat.pojo.vos.official.account;
/**
* When you feel like quitting. Think about why you started

View File

@ -1,7 +1,14 @@
package ink.wgink.module.wechat.service.official.account;
import ink.wgink.module.wechat.enums.XmlEventTypeEnum;
import ink.wgink.module.wechat.pojo.vos.official.account.OfficialAccountUserPO;
import ink.wgink.module.wechat.pojo.dtos.official.account.OfficialAccountUserDTO;
import ink.wgink.module.wechat.pojo.pos.official.account.OfficialAccountUserPO;
import ink.wgink.module.wechat.pojo.vos.official.account.OfficialAccountUserVO;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.result.SuccessResultList;
import java.util.List;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
@ -18,15 +25,74 @@ public interface IOfficialAccountUserService {
/**
* 新增用户
*
* @param officialAccountUserPO
* @param officialAccountUserVO
*/
void save(OfficialAccountUserPO officialAccountUserPO);
void save(OfficialAccountUserVO officialAccountUserVO);
/**
* 修改状态
*
* @param fromUserName
* @param unsubscribe
* @param openId
* @param xmlEventTypeEnum
*/
void updateStatus(String fromUserName, XmlEventTypeEnum unsubscribe);
void updateStatus(String openId, XmlEventTypeEnum xmlEventTypeEnum);
/**
* 详情
*
* @param params
* @return
*/
OfficialAccountUserDTO get(Map<String, Object> params);
/**
* 详情
*
* @param appId
* @param openId
* @return
*/
OfficialAccountUserDTO get(String appId, String openId);
/**
* 详情
*
* @param params
* @return
*/
OfficialAccountUserPO getPO(Map<String, Object> params);
/**
* 详情
*
* @param appId
* @param openId
* @return
*/
OfficialAccountUserPO getPO(String appId, String openId);
/**
* 列表
*
* @param params
* @return
*/
List<OfficialAccountUserDTO> list(Map<String, Object> params);
/**
* 列表
*
* @param params
* @return
*/
List<OfficialAccountUserPO> listPO(Map<String, Object> params);
/**
* 分页
*
* @param page
* @return
*/
SuccessResultList<List<OfficialAccountUserDTO>> listPage(ListPage page);
}

View File

@ -13,9 +13,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* When you feel like quitting. Think about why you started
@ -63,16 +62,12 @@ public class OfficialAccountCheckServiceImpl extends DefaultBaseService implemen
* @return
*/
private boolean isWechatOfficialAccountConfigRequest(String signature, String timestamp, String nonce, String echostr) {
List<String> sortList = new ArrayList<>();
sortList.add(officialAccountProperties.getConfigToken());
sortList.add(timestamp);
sortList.add(nonce);
Collections.sort(sortList);
StringBuilder newSignature = new StringBuilder();
sortList.forEach(str -> {
Stream.of(officialAccountProperties.getConfigToken(), timestamp, nonce).sorted()
.collect(Collectors.toList())
.forEach(str -> {
newSignature.append(str);
});
if (!StringUtils.equals(signature, DigestUtils.sha1Hex(newSignature.toString()))) {
return false;
}

View File

@ -3,11 +3,22 @@ package ink.wgink.module.wechat.service.official.account.impl;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.module.wechat.dao.official.account.IOfficialAccountUserDao;
import ink.wgink.module.wechat.enums.XmlEventTypeEnum;
import ink.wgink.module.wechat.pojo.vos.official.account.OfficialAccountUserPO;
import ink.wgink.module.wechat.pojo.dtos.official.account.OfficialAccountUserDTO;
import ink.wgink.module.wechat.pojo.pos.official.account.OfficialAccountUserPO;
import ink.wgink.module.wechat.pojo.vos.official.account.OfficialAccountUserVO;
import ink.wgink.module.wechat.service.official.account.IOfficialAccountUserService;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.properties.wechat.official.account.OfficialAccountProperties;
import ink.wgink.util.date.DateUtil;
import ink.wgink.util.map.HashMapUtil;
import ink.wgink.util.string.WStringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
@ -23,14 +34,79 @@ public class OfficialAccountUserServiceImpl extends DefaultBaseService implement
@Autowired
private IOfficialAccountUserDao officialAccountUserDao;
@Autowired
private OfficialAccountProperties officialAccountProperties;
@Override
public void save(OfficialAccountUserPO officialAccountUserPO) {
public void save(OfficialAccountUserVO officialAccountUserVO) {
OfficialAccountUserPO officialAccountUserPO = getPO(officialAccountProperties.getAppId(), officialAccountUserVO.getOpenId());
if (officialAccountUserPO != null) {
updateStatus(officialAccountUserVO.getOpenId(), XmlEventTypeEnum.SUBSCRIBE);
return;
}
String time = DateUtil.getTime();
officialAccountUserVO.setAppId(officialAccountProperties.getAppId());
// 用户码用于绑定账号时使用
officialAccountUserVO.setUserCode(WStringUtil.randomSubStr(String.valueOf(System.currentTimeMillis()), 6));
// 标记为初始化账号
officialAccountUserVO.setIsInitAccount(1);
Map<String, Object> params = HashMapUtil.beanToMap(officialAccountUserVO);
// 标记订阅状态
params.put("status", XmlEventTypeEnum.SUBSCRIBE.getType());
params.put("gmtCreate", time);
params.put("gmtModified", time);
officialAccountUserDao.save(params);
}
@Override
public void updateStatus(String fromUserName, XmlEventTypeEnum unsubscribe) {
public void updateStatus(String openId, XmlEventTypeEnum xmlEventTypeEnum) {
String time = DateUtil.getTime();
Map<String, Object> params = getHashMap(6);
params.put("status", xmlEventTypeEnum.getType());
params.put("gmtModified", time);
params.put("appId", officialAccountProperties.getAppId());
params.put("openId", openId);
officialAccountUserDao.update(params);
}
@Override
public OfficialAccountUserDTO get(Map<String, Object> params) {
return officialAccountUserDao.get(params);
}
@Override
public OfficialAccountUserDTO get(String appId, String openId) {
Map<String, Object> params = getHashMap(4);
params.put("appId", appId);
params.put("openId", openId);
return get(params);
}
@Override
public OfficialAccountUserPO getPO(Map<String, Object> params) {
return officialAccountUserDao.getPO(params);
}
@Override
public OfficialAccountUserPO getPO(String appId, String openId) {
Map<String, Object> params = getHashMap(4);
params.put("appId", appId);
params.put("openId", openId);
return getPO(params);
}
@Override
public List<OfficialAccountUserDTO> list(Map<String, Object> params) {
return officialAccountUserDao.list(params);
}
@Override
public List<OfficialAccountUserPO> listPO(Map<String, Object> params) {
return officialAccountUserDao.listPO(params);
}
@Override
public SuccessResultList<List<OfficialAccountUserDTO>> listPage(ListPage page) {
return null;
}
}

View File

@ -1,16 +1,16 @@
package ink.wgink.module.wechat.startup;
import ink.wgink.module.wechat.dao.official.account.IOfficialAccountUserDao;
import ink.wgink.module.wechat.manager.OfficialAccountAccessTokenManager;
import ink.wgink.properties.wechat.official.account.OfficialAccountProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
@ -23,15 +23,23 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
*/
@Component
public class WechatStartUp implements ApplicationRunner {
private static final Logger LOG = LoggerFactory.getLogger(WechatStartUp.class);
@Autowired
private OfficialAccountProperties officialAccountProperties;
@Autowired
private IOfficialAccountUserDao officialAccountUserDao;
@Override
public void run(ApplicationArguments args) throws Exception {
initTable();
new Thread(() -> refreshOfficialAccountAccessToken()).start();
}
private void initTable() {
LOG.debug("创建 wechat_official_account_user 表");
officialAccountUserDao.createTable();
}
@Scheduled(cron = "0 0/5 * * * ?")
public void refreshOfficialAccountAccessToken() {
OfficialAccountAccessTokenManager.getInstance().refreshAccessToken(officialAccountProperties);

View File

@ -1,26 +1,40 @@
<?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">
<mapper namespace="ink.wgink.module.wechat.dao.official.account.IOfficialAccountUserDao">
<cache flushInterval="3600000"/>
<resultMap id="miniAppUserPO" type="ink.wgink.login.wechat.pojo.pos.user.MiniAppUserPO">
<resultMap id="officialAccountUserPO" type="ink.wgink.module.wechat.pojo.pos.official.account.OfficialAccountUserPO">
<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"/>
<result column="gmt_modified" property="gmtModified"/>
<result column="status" property="status"/>
</resultMap>
<resultMap id="officialAccountUserDTO" type="ink.wgink.module.wechat.pojo.dtos.official.account.OfficialAccountUserDTO">
<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"/>
<result column="status" property="status"/>
</resultMap>
<!-- 建表 -->
<update id="createTable">
CREATE TABLE IF NOT EXISTS `wechat_mini_app_user` (
CREATE TABLE IF NOT EXISTS `wechat_official_account_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',
`user_code` varchar(255) DEFAULT NULL COMMENT '用户码',
`status` varchar(255) DEFAULT NULL COMMENT '订阅状态',
`is_init_account` int(1) DEFAULT '0' COMMENT '是否初始化账户',
`gmt_create` datetime DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `app_id` (`app_id`) USING BTREE,
KEY `open_id` (`open_id`) USING BTREE,
@ -29,32 +43,71 @@
</update>
<!-- 保存 -->
<insert id="save" parameterType="map">
INSERT INTO wechat_mini_app_user(
<insert id="save" parameterType="map" flushCache="true">
INSERT INTO wechat_official_account_user(
app_id,
open_id,
user_id,
user_code,
status,
is_init_account,
gmt_create
gmt_create,
gmt_modified
) VALUES(
#{appId},
#{openId},
#{userId},
#{userCode},
#{status},
#{isInitAccount},
#{gmtCreate}
#{gmtCreate},
#{gmtModified}
)
</insert>
<!-- 删除 -->
<update id="remove" parameterType="map" flushCache="true">
DELETE FROM
wechat_official_account_user
WHERE
app_id = #{appId}
AND
open_ids IN
<foreach collection="openIds" index="index" open="(" separator="," close=")">
#{openIds[${index}]}
</foreach>
</update>
<!-- 修改 -->
<update id="update" parameterType="map" flushCache="true">
UPDATE
wechat_official_account_user
SET
<if test="userId != null">
user_id = #{userId},
</if>
<if test="status != null and status != ''">
status = #{status},
</if>
gmt_modified = #{gmtModified}
WHERE
app_id = #{appId}
AND
open_id = #{openId}
</update>
<!-- 详情 -->
<select id="getPO" parameterType="map" resultMap="miniAppUserPO" useCache="true">
<select id="get" parameterType="map" resultMap="officialAccountUserDTO" useCache="true">
SELECT
app_id,
open_id,
user_id,
status,
is_init_account,
gmt_create
LEFT(gmt_create, 19) gmt_create,
LEFT(gmt_modified, 19) gmt_modified
FROM
wechat_mini_app_user
wechat_official_account_user
<where>
<if test="appId != null and appId != ''">
app_id = #{appId}
@ -70,6 +123,69 @@
</where>
</select>
<!-- 详情 -->
<select id="list" parameterType="map" resultMap="officialAccountUserDTO" useCache="true">
SELECT
app_id,
open_id,
user_id,
status,
is_init_account,
LEFT(gmt_create, 19) gmt_create,
LEFT(gmt_modified, 19) gmt_modified
FROM
wechat_official_account_user
<where>
<if test="status != null and status != ''">
status = #{status}
</if>
</where>
</select>
<!-- 详情 -->
<select id="getPO" parameterType="map" resultMap="officialAccountUserPO" useCache="true">
SELECT
app_id,
open_id,
user_id,
status,
is_init_account,
gmt_create,
gmt_modified
FROM
wechat_official_account_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>
<!-- 详情 -->
<select id="listPO" parameterType="map" resultMap="officialAccountUserPO" useCache="true">
SELECT
app_id,
open_id,
user_id,
status,
is_init_account,
gmt_create,
gmt_modified
FROM
wechat_official_account_user
<where>
<if test="status != null and status != ''">
status = #{status}
</if>
</where>
</select>
</mapper>