From e0532a7028d031326a21409494e863d15e053d43 Mon Sep 17 00:00:00 2001 From: wanggeng888 <450292408@qq.com> Date: Wed, 28 Apr 2021 12:02:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=BE=AE=E4=BF=A1=E6=A8=A1?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- module-wechat/pom.xml | 22 ++++++ .../module/wechat/enums/ErrorMsgEnum.java | 50 ++++++++++++ .../OfficialAccountAccessTokenManager.java | 59 ++++++++++++++ .../pojo/OfficialAccountAccessToken.java | 44 +++++++++++ .../account/pojo/OfficialAccountEvent.java | 77 +++++++++++++++++++ .../request/AccessTokenRestTemplate.java | 76 ++++++++++++++++++ .../account/result/AccessTokenResult.java | 35 +++++++++ .../wechat/result/BaseWechatResult.java | 33 ++++++++ .../module/wechat/startup/WechatStartUp.java | 47 +++++++++++ pom.xml | 1 + 10 files changed, 444 insertions(+) create mode 100644 module-wechat/pom.xml create mode 100644 module-wechat/src/main/java/ink/wgink/module/wechat/enums/ErrorMsgEnum.java create mode 100644 module-wechat/src/main/java/ink/wgink/module/wechat/official/account/manager/OfficialAccountAccessTokenManager.java create mode 100644 module-wechat/src/main/java/ink/wgink/module/wechat/official/account/pojo/OfficialAccountAccessToken.java create mode 100644 module-wechat/src/main/java/ink/wgink/module/wechat/official/account/pojo/OfficialAccountEvent.java create mode 100644 module-wechat/src/main/java/ink/wgink/module/wechat/official/account/request/AccessTokenRestTemplate.java create mode 100644 module-wechat/src/main/java/ink/wgink/module/wechat/official/account/result/AccessTokenResult.java create mode 100644 module-wechat/src/main/java/ink/wgink/module/wechat/result/BaseWechatResult.java create mode 100644 module-wechat/src/main/java/ink/wgink/module/wechat/startup/WechatStartUp.java diff --git a/module-wechat/pom.xml b/module-wechat/pom.xml new file mode 100644 index 00000000..aa0f1b09 --- /dev/null +++ b/module-wechat/pom.xml @@ -0,0 +1,22 @@ + + + + wg-basic + ink.wgink + 1.0-SNAPSHOT + + 4.0.0 + + module-wechat + + + + ink.wgink + common + 1.0-SNAPSHOT + + + + \ No newline at end of file diff --git a/module-wechat/src/main/java/ink/wgink/module/wechat/enums/ErrorMsgEnum.java b/module-wechat/src/main/java/ink/wgink/module/wechat/enums/ErrorMsgEnum.java new file mode 100644 index 00000000..675dd7b7 --- /dev/null +++ b/module-wechat/src/main/java/ink/wgink/module/wechat/enums/ErrorMsgEnum.java @@ -0,0 +1,50 @@ +package ink.wgink.module.wechat.enums; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: ErrorMsgEnums + * @Description: + * @Author: wanggeng + * @Date: 2021/4/28 6:08 上午 + * @Version: 1.0 + */ +public enum ErrorMsgEnum { + + SYSTEM_BUSY(-1, "系统繁忙,此时请开发者稍候再试"), + SUCCESS(0, "请求成功"), + ERROR_40001(40001, "AppSecret错误或者AppSecret不属于这个公众号,请开发者确认AppSecret的正确性"), + ERROR_40002(40002, "请确保grant_type字段值为client_credential"), + ERROR_40164(40164, "调用接口的IP地址不在白名单中,请在接口IP白名单中进行设置。(小程序及小游戏调用不要求IP地址在白名单内。)"), + ERROR_89503(89503, "此IP调用需要管理员确认,请联系管理员"), + ERROR_89501(89501, "此IP正在等待管理员确认,请联系管理员"), + ERROR_89506(89506, "24小时内该IP被管理员拒绝调用两次,24小时内不可再使用该IP调用"), + ERROR_89507(89507, "1小时内该IP被管理员拒绝调用一次,1小时内不可再使用该IP调用"); + + private int errCode; + private String errMsg; + + ErrorMsgEnum(int errCode, String errMsg) { + this.errCode = errCode; + this.errMsg = errMsg; + } + + public int getErrCode() { + return errCode; + } + + public String getErrMsg() { + return errMsg == null ? "" : errMsg; + } + + public static String getErrMsg(int errCode) { + ErrorMsgEnum[] errorMsgEnums = values(); + for (ErrorMsgEnum errorMsgEnum : errorMsgEnums) { + if (errorMsgEnum.errCode == errCode) { + return errorMsgEnum.getErrMsg(); + } + } + return null; + } +} diff --git a/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/manager/OfficialAccountAccessTokenManager.java b/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/manager/OfficialAccountAccessTokenManager.java new file mode 100644 index 00000000..a6653980 --- /dev/null +++ b/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/manager/OfficialAccountAccessTokenManager.java @@ -0,0 +1,59 @@ +package ink.wgink.module.wechat.official.account.manager; + +import ink.wgink.module.wechat.official.account.pojo.OfficialAccountAccessToken; +import ink.wgink.module.wechat.official.account.request.AccessTokenRestTemplate; +import ink.wgink.properties.wechat.official.account.OfficialAccountProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: AccessTokenManager + * @Description: access_token控制器 + * @Author: wanggeng + * @Date: 2021/4/27 5:19 下午 + * @Version: 1.0 + */ +public class OfficialAccountAccessTokenManager { + + private static final Logger LOG = LoggerFactory.getLogger(OfficialAccountAccessTokenManager.class); + /** + * 最大过期毫秒 + */ + private static long MAXIMUM_EXPIRE_MILLISECOND = 5400000; + private static OfficialAccountAccessTokenManager officialAccountAccessTokenManager = AccessTokenManagerFactory.officialAccountAccessTokenManager; + private OfficialAccountAccessToken officialAccountAccessToken; + + private OfficialAccountAccessTokenManager() { + } + + public static OfficialAccountAccessTokenManager getInstance() { + return officialAccountAccessTokenManager; + } + + /** + * 刷新access_token + */ + public void refreshAccessToken(OfficialAccountProperties officialAccountProperties) { + long currentTime = System.currentTimeMillis(); + if (officialAccountAccessToken != null && (currentTime - this.officialAccountAccessToken.getLastUpdated()) < MAXIMUM_EXPIRE_MILLISECOND) { + return; + } + LOG.debug("刷新公众号 AccessToken 开始"); + AccessTokenRestTemplate accessTokenRestTemplate = new AccessTokenRestTemplate(officialAccountProperties); + accessTokenRestTemplate.post(officialAccountProperties.getAccessTokenUrl()); + LOG.debug("accessToken: {}", this.officialAccountAccessToken); + LOG.debug("刷新公众号 AccessToken 结束"); + } + + public void setAccessToken(OfficialAccountAccessToken officialAccountAccessToken) { + this.officialAccountAccessToken = officialAccountAccessToken; + } + + private static class AccessTokenManagerFactory { + public static OfficialAccountAccessTokenManager officialAccountAccessTokenManager = new OfficialAccountAccessTokenManager(); + } + +} diff --git a/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/pojo/OfficialAccountAccessToken.java b/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/pojo/OfficialAccountAccessToken.java new file mode 100644 index 00000000..3b6a3316 --- /dev/null +++ b/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/pojo/OfficialAccountAccessToken.java @@ -0,0 +1,44 @@ +package ink.wgink.module.wechat.official.account.pojo; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: AccessToken + * @Description: + * @Author: wanggeng + * @Date: 2021/4/28 5:29 上午 + * @Version: 1.0 + */ +public class OfficialAccountAccessToken { + + private String accessToken; + private long lastUpdated; + + public String getAccessToken() { + return accessToken == null ? "" : accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public long getLastUpdated() { + return lastUpdated; + } + + public void setLastUpdated(long lastUpdated) { + this.lastUpdated = lastUpdated; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("{"); + sb.append("\"accessToken\":\"") + .append(accessToken).append('\"'); + sb.append(",\"lastUpdated\":") + .append(lastUpdated); + sb.append('}'); + return sb.toString(); + } +} diff --git a/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/pojo/OfficialAccountEvent.java b/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/pojo/OfficialAccountEvent.java new file mode 100644 index 00000000..9a990845 --- /dev/null +++ b/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/pojo/OfficialAccountEvent.java @@ -0,0 +1,77 @@ +package ink.wgink.module.wechat.official.account.pojo; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: AttentionCancel + * @Description: 公众号事件 + * @Author: wanggeng + * @Date: 2021/4/28 11:20 上午 + * @Version: 1.0 + */ +public class OfficialAccountEvent { + + private String toUserName; + private String fromUserName; + private String createTime; + private String msgType; + private String event; + + public String getToUserName() { + return toUserName == null ? "" : toUserName; + } + + public void setToUserName(String toUserName) { + this.toUserName = toUserName; + } + + public String getFromUserName() { + return fromUserName == null ? "" : fromUserName; + } + + public void setFromUserName(String fromUserName) { + this.fromUserName = fromUserName; + } + + public String getCreateTime() { + return createTime == null ? "" : createTime; + } + + public void setCreateTime(String createTime) { + this.createTime = createTime; + } + + public String getMsgType() { + return msgType == null ? "" : msgType; + } + + public void setMsgType(String msgType) { + this.msgType = msgType; + } + + public String getEvent() { + return event == null ? "" : event; + } + + public void setEvent(String event) { + this.event = event; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("{"); + sb.append("\"toUserName\":\"") + .append(toUserName).append('\"'); + sb.append(",\"fromUserName\":\"") + .append(fromUserName).append('\"'); + sb.append(",\"createTime\":\"") + .append(createTime).append('\"'); + sb.append(",\"msgType\":\"") + .append(msgType).append('\"'); + sb.append(",\"event\":\"") + .append(event).append('\"'); + sb.append('}'); + return sb.toString(); + } +} diff --git a/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/request/AccessTokenRestTemplate.java b/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/request/AccessTokenRestTemplate.java new file mode 100644 index 00000000..7304ccfc --- /dev/null +++ b/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/request/AccessTokenRestTemplate.java @@ -0,0 +1,76 @@ +package ink.wgink.module.wechat.official.account.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.properties.wechat.official.account.OfficialAccountProperties; +import ink.wgink.util.request.AbstractRestTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.client.HttpClientErrorException; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: AccessTokenRestTemplate + * @Description: + * @Author: wanggeng + * @Date: 2021/4/28 5:31 上午 + * @Version: 1.0 + */ +public class AccessTokenRestTemplate extends AbstractRestTemplate> { + private static final Logger LOG = LoggerFactory.getLogger(AccessTokenRestTemplate.class); + private OfficialAccountProperties officialAccountProperties; + + public AccessTokenRestTemplate(OfficialAccountProperties officialAccountProperties) { + this.officialAccountProperties = officialAccountProperties; + } + + @Override + public Map postBody() { + Map params = new HashMap<>(6); + params.put("grant_type", officialAccountProperties.getGrantType()); + params.put("appid", officialAccountProperties.getAppId()); + params.put("secret", officialAccountProperties.getAppSecret()); + return params; + } + + @Override + public Class successResultType() { + return AccessTokenResult.class; + } + + @Override + public void success200(AccessTokenResult result) { + if (result.getErrcode() == ErrorMsgEnum.SUCCESS.getErrCode()) { + OfficialAccountAccessToken officialAccountAccessToken = new OfficialAccountAccessToken(); + officialAccountAccessToken.setAccessToken(result.getAccess_token()); + officialAccountAccessToken.setLastUpdated(System.currentTimeMillis()); + OfficialAccountAccessTokenManager.getInstance().setAccessToken(officialAccountAccessToken); + return; + } + if (result.getErrcode() == ErrorMsgEnum.SYSTEM_BUSY.getErrCode()) { + LOG.error("系统繁忙,3s后重试"); + try { + TimeUnit.SECONDS.sleep(3); + } catch (InterruptedException e) { + LOG.error(e.getMessage(), e); + } + this.post(officialAccountProperties.getAccessTokenUrl()); + return; + } + LOG.error(ErrorMsgEnum.getErrMsg(result.getErrcode())); + } + + @Override + public void error400(HttpClientErrorException error) { + LOG.error(error.getMessage(), error); + } + +} diff --git a/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/result/AccessTokenResult.java b/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/result/AccessTokenResult.java new file mode 100644 index 00000000..52d5073d --- /dev/null +++ b/module-wechat/src/main/java/ink/wgink/module/wechat/official/account/result/AccessTokenResult.java @@ -0,0 +1,35 @@ +package ink.wgink.module.wechat.official.account.result; + +import ink.wgink.module.wechat.result.BaseWechatResult; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: AccessTokenResult + * @Description: + * @Author: wanggeng + * @Date: 2021/4/28 6:00 上午 + * @Version: 1.0 + */ +public class AccessTokenResult extends BaseWechatResult { + + private String access_token; + private Long expires_in; + + public String getAccess_token() { + return access_token == null ? "" : access_token; + } + + public void setAccess_token(String access_token) { + this.access_token = access_token; + } + + public Long getExpires_in() { + return expires_in == null ? 0 : expires_in; + } + + public void setExpires_in(Long expires_in) { + this.expires_in = expires_in; + } +} diff --git a/module-wechat/src/main/java/ink/wgink/module/wechat/result/BaseWechatResult.java b/module-wechat/src/main/java/ink/wgink/module/wechat/result/BaseWechatResult.java new file mode 100644 index 00000000..0027b113 --- /dev/null +++ b/module-wechat/src/main/java/ink/wgink/module/wechat/result/BaseWechatResult.java @@ -0,0 +1,33 @@ +package ink.wgink.module.wechat.result; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: BaseWechatResult + * @Description: 微信基础返回类 + * @Author: wanggeng + * @Date: 2021/4/28 5:59 上午 + * @Version: 1.0 + */ +public class BaseWechatResult { + + private Integer errcode; + private String errmsg; + + public Integer getErrcode() { + return errcode == null ? 0 : errcode; + } + + public void setErrcode(Integer errcode) { + this.errcode = errcode; + } + + public String getErrmsg() { + return errmsg == null ? "" : errmsg; + } + + public void setErrmsg(String errmsg) { + this.errmsg = errmsg; + } +} diff --git a/module-wechat/src/main/java/ink/wgink/module/wechat/startup/WechatStartUp.java b/module-wechat/src/main/java/ink/wgink/module/wechat/startup/WechatStartUp.java new file mode 100644 index 00000000..38b79ff8 --- /dev/null +++ b/module-wechat/src/main/java/ink/wgink/module/wechat/startup/WechatStartUp.java @@ -0,0 +1,47 @@ +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.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; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: WechatStartUp + * @Description: 微信启动 + * @Author: wanggeng + * @Date: 2021/4/28 6:40 上午 + * @Version: 1.0 + */ +@Component +public class WechatStartUp implements ApplicationRunner { + @Autowired + private OfficialAccountProperties officialAccountProperties; + + @Override + public void run(ApplicationArguments args) throws Exception { + + } + + @Scheduled(cron = "0 0/5 * * * ? *") + public void refreshOfficialAccountAccessToken() { + OfficialAccountAccessTokenManager.getInstance().refreshAccessToken(officialAccountProperties); + } + +} diff --git a/pom.xml b/pom.xml index 9e5df7a3..aeab9354 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,7 @@ login-wechat basic-properties module-article + module-wechat pom