公众号绑定和关注事件

This commit is contained in:
wanggeng888 2021-04-28 21:18:00 +08:00
parent 2b7d5f3121
commit 9d7b8407d9
20 changed files with 721 additions and 32 deletions

View File

@ -24,6 +24,7 @@ public class OfficialAccountProperties {
private String appId;
private String appSecret;
private String grantType;
private String configToken;
public Boolean getApiCrossOrigin() {
return apiCrossOrigin;
@ -80,4 +81,12 @@ public class OfficialAccountProperties {
public void setGrantType(String grantType) {
this.grantType = grantType;
}
public String getConfigToken() {
return configToken == null ? "" : configToken;
}
public void setConfigToken(String configToken) {
this.configToken = configToken;
}
}

View File

@ -0,0 +1,113 @@
package ink.wgink.module.wechat.controller.official.account;
import ink.wgink.common.base.DefaultBaseController;
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.result.OfficialAccountEventResult;
import ink.wgink.module.wechat.service.official.account.IOfficialAccountCheckService;
import ink.wgink.module.wechat.service.official.account.IOfficialAccountUserService;
import ink.wgink.util.xml.XMLUtil;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.CompletableFuture;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: OfficialAccountWechatController
* @Description: 微信公众号
* @Author: wanggeng
* @Date: 2021/4/28 3:15 下午
* @Version: 1.0
*/
@Api(tags = ISystemConstant.API_TAGS_WECHAT_PREFIX + "微信公众号")
@RestController
@RequestMapping(ISystemConstant.WECHAT_PREFIX + "/official/account")
public class OfficialAccountWechatController extends DefaultBaseController {
@Autowired
private IOfficialAccountCheckService officialAccountCheckService;
@Autowired
private IOfficialAccountUserService officialAccountUserService;
@RequestMapping("event")
public void event(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 处理认证
if (StringUtils.equalsIgnoreCase(HttpMethod.GET.toString(), request.getMethod())) {
officialAccountCheckService.checkSignature(request, response);
return;
}
// 处理事件
if (StringUtils.equalsIgnoreCase(HttpMethod.POST.toString(), request.getMethod())) {
AsyncContext asyncContext = request.startAsync();
CompletableFuture.runAsync(() -> {
handleMsgType(asyncContext, request, response);
});
return;
}
}
/**
* 处理消息类型
*
* @param asyncContext
* @param request
* @param response
*/
private void handleMsgType(AsyncContext asyncContext, HttpServletRequest request, HttpServletResponse response) {
OfficialAccountEventResult officialAccountEventResult = getEventResult(request);
if (officialAccountEventResult == null) {
throw new ParamsException("事件错误");
}
if (StringUtils.equalsIgnoreCase(XmlMsgTypeEnum.EVENT.getValue(), officialAccountEventResult.getMsgType())) {
handleEvent(officialAccountEventResult, asyncContext, request, response);
}
}
// 处理事件
private void handleEvent(OfficialAccountEventResult officialAccountEventResult, AsyncContext asyncContext, HttpServletRequest request, HttpServletResponse response) {
if (StringUtils.equalsIgnoreCase(XmlEventTypeEnum.SUBSCRIBE.getType(), officialAccountEventResult.getEvent())) {
OfficialAccountUserPO officialAccountUserPO = new OfficialAccountUserPO();
officialAccountUserPO.setOpenId(officialAccountEventResult.getFromUserName());
officialAccountUserService.save(officialAccountUserPO);
} else if(StringUtils.equalsIgnoreCase(XmlEventTypeEnum.UNSUBSCRIBE.getType(), officialAccountEventResult.getEvent())) {
officialAccountUserService.updateStatus(officialAccountEventResult.getFromUserName(), XmlEventTypeEnum.UNSUBSCRIBE);
}
}
/**
* 事件结果
*
* @param request
* @return
*/
private OfficialAccountEventResult getEventResult(HttpServletRequest request) {
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(request.getInputStream()))) {
StringBuilder content = new StringBuilder();
for (String line; (line = bufferedReader.readLine()) != null; ) {
content.append(line);
}
return XMLUtil.xml2SampleBean(content.toString(), OfficialAccountEventResult.class);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
return null;
}
}

View File

@ -0,0 +1,94 @@
package ink.wgink.module.wechat.dao.official.account;
import ink.wgink.exceptions.RemoveException;
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 org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: IAccountOfficialUserDao
* @Description: 公众号用户
* @Author: wanggeng
* @Date: 2021/4/28 6:42 下午
* @Version: 1.0
*/
@Repository
public interface IOfficialAccountUserDao {
/**
* 建表
*
* @throws UpdateException
*/
void createTable() throws UpdateException;
/**
* 新增
*
* @param params
* @throws SaveException
*/
void save(Map<String, Object> params) throws SaveException;
/**
* 修改
*
* @param params
* @throws UpdateException
*/
void update(Map<String, Object> params) throws UpdateException;
/**
* 删除
*
* @param params
* @throws RemoveException
*/
void remove(Map<String, Object> params) throws RemoveException;
/**
* 详情
*
* @param params
* @return
* @throws SearchException
*/
OfficialAccountUserDTO get(Map<String, Object> params) throws SearchException;
/**
* 详情
*
* @param params
* @return
* @throws SearchException
*/
OfficialAccountUserPO getPO(Map<String, Object> params) throws SearchException;
/**
* 列表
*
* @param params
* @return
* @throws SearchException
*/
List<OfficialAccountUserDTO> list(Map<String, Object> params) throws SearchException;
/**
* 列表
*
* @param params
* @return
* @throws SearchException
*/
List<OfficialAccountUserPO> listPO(Map<String, Object> params) throws SearchException;
}

View File

@ -17,6 +17,7 @@ public enum ErrorMsgEnum {
ERROR_40001(40001, "AppSecret错误或者AppSecret不属于这个公众号请开发者确认AppSecret的正确性"),
ERROR_40002(40002, "请确保grant_type字段值为client_credential"),
ERROR_40164(40164, "调用接口的IP地址不在白名单中请在接口IP白名单中进行设置。小程序及小游戏调用不要求IP地址在白名单内。"),
ERROR_41002(41002, "appid为空"),
ERROR_89503(89503, "此IP调用需要管理员确认,请联系管理员"),
ERROR_89501(89501, "此IP正在等待管理员确认,请联系管理员"),
ERROR_89506(89506, "24小时内该IP被管理员拒绝调用两次24小时内不可再使用该IP调用"),

View File

@ -0,0 +1,34 @@
package ink.wgink.module.wechat.enums;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: EventTypeEnum
* @Description: 事件类型
* @Author: wanggeng
* @Date: 2021/4/28 6:19 下午
* @Version: 1.0
*/
public enum XmlEventTypeEnum {
SUBSCRIBE("subscribe", "订阅"),
UNSUBSCRIBE("unsubscribe", "取消订阅");
private String type;
private String describe;
XmlEventTypeEnum(String type, String describe) {
this.type = type;
this.describe = describe;
}
public String getType() {
return type == null ? "" : type;
}
public String getDescribe() {
return describe == null ? "" : describe;
}
}

View File

@ -0,0 +1,26 @@
package ink.wgink.module.wechat.enums;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: XMLMsgTypeEnum
* @Description: xml消息类型
* @Author: wanggeng
* @Date: 2021/4/28 6:20 下午
* @Version: 1.0
*/
public enum XmlMsgTypeEnum {
EVENT("event");
private String value;
XmlMsgTypeEnum(String value) {
this.value = value;
}
public String getValue() {
return value == null ? "" : value;
}
}

View File

@ -1,7 +1,7 @@
package ink.wgink.module.wechat.official.account.manager;
package ink.wgink.module.wechat.manager;
import ink.wgink.module.wechat.official.account.pojo.OfficialAccountAccessToken;
import ink.wgink.module.wechat.official.account.request.AccessTokenRestTemplate;
import ink.wgink.module.wechat.pojo.OfficialAccountAccessToken;
import ink.wgink.module.wechat.request.AccessTokenRestTemplate;
import ink.wgink.properties.wechat.official.account.OfficialAccountProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -43,7 +43,7 @@ public class OfficialAccountAccessTokenManager {
}
LOG.debug("刷新公众号 AccessToken 开始");
AccessTokenRestTemplate accessTokenRestTemplate = new AccessTokenRestTemplate(officialAccountProperties);
accessTokenRestTemplate.post(officialAccountProperties.getAccessTokenUrl());
accessTokenRestTemplate.get(accessTokenRestTemplate.getAccessTokenUrl());
LOG.debug("accessToken: {}", this.officialAccountAccessToken);
LOG.debug("刷新公众号 AccessToken 结束");
}

View File

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

View File

@ -0,0 +1,14 @@
package ink.wgink.module.wechat.pojo.dtos.official.account;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: OfficialAccountUserDTO
* @Description: 公众号用户
* @Author: wanggeng
* @Date: 2021/4/28 6:46 下午
* @Version: 1.0
*/
public class OfficialAccountUserDTO {
}

View File

@ -0,0 +1,60 @@
package ink.wgink.module.wechat.pojo.pos.official.account;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: OfficialAccountUserVO
* @Description: 公众号用户
* @Author: wanggeng
* @Date: 2021/4/28 6:10 下午
* @Version: 1.0
*/
public class OfficialAccountUserVO {
private String appId;
private String openId;
private String userId;
private String userCode;
private Integer isInitAccount;
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 String getUserCode() {
return userCode == null ? "" : userCode;
}
public void setUserCode(String userCode) {
this.userCode = userCode;
}
public Integer getIsInitAccount() {
return isInitAccount == null ? 0 : isInitAccount;
}
public void setIsInitAccount(Integer isInitAccount) {
this.isInitAccount = isInitAccount;
}
}

View File

@ -0,0 +1,69 @@
package ink.wgink.module.wechat.pojo.vos.official.account;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: OfficialAccountUserPO
* @Description: 公众号用户
* @Author: wanggeng
* @Date: 2021/4/28 6:13 下午
* @Version: 1.0
*/
public class OfficialAccountUserPO {
private String appId;
private String openId;
private String userId;
private String userCode;
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 String getUserCode() {
return userCode == null ? "" : userCode;
}
public void setUserCode(String userCode) {
this.userCode = userCode;
}
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

@ -1,13 +1,15 @@
package ink.wgink.module.wechat.official.account.request;
package ink.wgink.module.wechat.request;
import ink.wgink.module.wechat.enums.ErrorMsgEnum;
import ink.wgink.module.wechat.official.account.manager.OfficialAccountAccessTokenManager;
import ink.wgink.module.wechat.official.account.pojo.OfficialAccountAccessToken;
import ink.wgink.module.wechat.official.account.result.AccessTokenResult;
import ink.wgink.module.wechat.manager.OfficialAccountAccessTokenManager;
import ink.wgink.module.wechat.pojo.OfficialAccountAccessToken;
import ink.wgink.module.wechat.result.AccessTokenResult;
import ink.wgink.properties.wechat.official.account.OfficialAccountProperties;
import ink.wgink.util.request.AbstractRestTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import java.util.HashMap;
@ -24,7 +26,7 @@ import java.util.concurrent.TimeUnit;
* @Date: 2021/4/28 5:31 上午
* @Version: 1.0
*/
public class AccessTokenRestTemplate extends AbstractRestTemplate<AccessTokenResult, Map<String, Object>> {
public class AccessTokenRestTemplate extends AbstractRestTemplate<AccessTokenResult, MultiValueMap> {
private static final Logger LOG = LoggerFactory.getLogger(AccessTokenRestTemplate.class);
private OfficialAccountProperties officialAccountProperties;
@ -33,12 +35,12 @@ public class AccessTokenRestTemplate extends AbstractRestTemplate<AccessTokenRes
}
@Override
public Map<String, Object> postBody() {
Map<String, Object> params = new HashMap<>(6);
params.put("grant_type", officialAccountProperties.getGrantType());
params.put("appid", officialAccountProperties.getAppId());
params.put("secret", officialAccountProperties.getAppSecret());
return params;
public MultiValueMap postBody() {
MultiValueMap multiValueMap = new LinkedMultiValueMap<>();
multiValueMap.add("grant_type", officialAccountProperties.getGrantType());
multiValueMap.add("appid", officialAccountProperties.getAppId());
multiValueMap.add("secret", officialAccountProperties.getAppSecret());
return multiValueMap;
}
@Override
@ -62,7 +64,7 @@ public class AccessTokenRestTemplate extends AbstractRestTemplate<AccessTokenRes
} catch (InterruptedException e) {
LOG.error(e.getMessage(), e);
}
this.post(officialAccountProperties.getAccessTokenUrl());
this.get(getAccessTokenUrl());
return;
}
LOG.error(ErrorMsgEnum.getErrMsg(result.getErrcode()));
@ -73,4 +75,17 @@ public class AccessTokenRestTemplate extends AbstractRestTemplate<AccessTokenRes
LOG.error(error.getMessage(), error);
}
/**
* access_token路径
*
* @return
*/
public String getAccessTokenUrl() {
return String.format("%s?grant_type=%s&appid=%s&secret=%s",
officialAccountProperties.getAccessTokenUrl(),
officialAccountProperties.getGrantType(),
officialAccountProperties.getAppId(),
officialAccountProperties.getAppSecret());
}
}

View File

@ -1,4 +1,4 @@
package ink.wgink.module.wechat.official.account.result;
package ink.wgink.module.wechat.result;
import ink.wgink.module.wechat.result.BaseWechatResult;

View File

@ -1,4 +1,4 @@
package ink.wgink.module.wechat.official.account.pojo;
package ink.wgink.module.wechat.result;
/**
* When you feel like quitting. Think about why you started
@ -10,13 +10,14 @@ package ink.wgink.module.wechat.official.account.pojo;
* @Date: 2021/4/28 11:20 上午
* @Version: 1.0
*/
public class OfficialAccountEvent {
public class OfficialAccountEventResult {
private String toUserName;
private String fromUserName;
private String createTime;
private String msgType;
private String event;
private String eventKey;
public String getToUserName() {
return toUserName == null ? "" : toUserName;
@ -58,6 +59,14 @@ public class OfficialAccountEvent {
this.event = event;
}
public String getEventKey() {
return eventKey == null ? "" : eventKey;
}
public void setEventKey(String eventKey) {
this.eventKey = eventKey;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
@ -71,6 +80,8 @@ public class OfficialAccountEvent {
.append(msgType).append('\"');
sb.append(",\"event\":\"")
.append(event).append('\"');
sb.append(",\"eventKey\":\"")
.append(eventKey).append('\"');
sb.append('}');
return sb.toString();
}

View File

@ -0,0 +1,25 @@
package ink.wgink.module.wechat.service.official.account;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: IOfficialAccountBindService
* @Description: 公众号绑定
* @Author: wanggeng
* @Date: 2021/4/28 3:19 下午
* @Version: 1.0
*/
public interface IOfficialAccountCheckService {
/**
* 校验签名
*
* @param request
* @param response
*/
void checkSignature(HttpServletRequest request, HttpServletResponse response) throws IOException;
}

View File

@ -0,0 +1,32 @@
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;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: IOfficialAccountUserService
* @Description: 公众号用户
* @Author: wanggeng
* @Date: 2021/4/28 6:15 下午
* @Version: 1.0
*/
public interface IOfficialAccountUserService {
/**
* 新增用户
*
* @param officialAccountUserPO
*/
void save(OfficialAccountUserPO officialAccountUserPO);
/**
* 修改状态
*
* @param fromUserName
* @param unsubscribe
*/
void updateStatus(String fromUserName, XmlEventTypeEnum unsubscribe);
}

View File

@ -0,0 +1,82 @@
package ink.wgink.module.wechat.service.official.account.impl;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.exceptions.ParamsException;
import ink.wgink.module.wechat.service.official.account.IOfficialAccountCheckService;
import ink.wgink.properties.wechat.official.account.OfficialAccountProperties;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
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;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: OfficialAccountBindServiceImpl
* @Description: 公众号绑定
* @Author: wanggeng
* @Date: 2021/4/28 3:20 下午
* @Version: 1.0
*/
@Service
public class OfficialAccountCheckServiceImpl extends DefaultBaseService implements IOfficialAccountCheckService {
@Autowired
private OfficialAccountProperties officialAccountProperties;
@Override
public void checkSignature(HttpServletRequest request, HttpServletResponse response) throws IOException {
String signatureParameter = request.getParameter("signature");
String timestampParameter = request.getParameter("timestamp");
String nonceParameter = request.getParameter("nonce");
String echostrParameter = request.getParameter("echostr");
boolean isWechatConfig = !org.springframework.util.StringUtils.isEmpty(signatureParameter)
&& !org.springframework.util.StringUtils.isEmpty(timestampParameter)
&& !org.springframework.util.StringUtils.isEmpty(nonceParameter)
&& !StringUtils.isEmpty(echostrParameter);
if (!isWechatConfig) {
throw new ParamsException("参数缺失");
}
if (!isWechatOfficialAccountConfigRequest(signatureParameter, timestampParameter, nonceParameter, echostrParameter)) {
throw new ParamsException("非公众号账号配置请求");
}
PrintWriter writer = response.getWriter();
writer.write(echostrParameter);
writer.flush();
writer.close();
}
/**
* @param signature
* @param timestamp
* @param nonce
* @param echostr
* @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 -> {
newSignature.append(str);
});
if (!StringUtils.equals(signature, DigestUtils.sha1Hex(newSignature.toString()))) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,36 @@
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.service.official.account.IOfficialAccountUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: OfficialAccountUserServiceImpl
* @Description: 公众号用户
* @Author: wanggeng
* @Date: 2021/4/28 6:15 下午
* @Version: 1.0
*/
@Service
public class OfficialAccountUserServiceImpl extends DefaultBaseService implements IOfficialAccountUserService {
@Autowired
private IOfficialAccountUserDao officialAccountUserDao;
@Override
public void save(OfficialAccountUserPO officialAccountUserPO) {
}
@Override
public void updateStatus(String fromUserName, XmlEventTypeEnum unsubscribe) {
}
}

View File

@ -1,23 +1,15 @@
package ink.wgink.module.wechat.startup;
import ink.wgink.module.wechat.official.account.manager.OfficialAccountAccessTokenManager;
import ink.wgink.module.wechat.official.account.pojo.OfficialAccountEvent;
import ink.wgink.module.wechat.manager.OfficialAccountAccessTokenManager;
import ink.wgink.properties.wechat.official.account.OfficialAccountProperties;
import ink.wgink.util.xml.XMLUtil;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
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.io.ByteArrayInputStream;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
/**
* When you feel like quitting. Think about why you started
@ -37,9 +29,10 @@ public class WechatStartUp implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
new Thread(() -> refreshOfficialAccountAccessToken()).start();
}
@Scheduled(cron = "0 0/5 * * * ? *")
@Scheduled(cron = "0 0/5 * * * ?")
public void refreshOfficialAccountAccessToken() {
OfficialAccountAccessTokenManager.getInstance().refreshAccessToken(officialAccountProperties);
}

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 IF NOT EXISTS `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>