From a02eda534986d3d8565b5ed6308a6f4beb1908cc Mon Sep 17 00:00:00 2001 From: wenc000 <450292408@qq.com> Date: Sat, 9 May 2020 19:32:56 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=BE=AE=E4=BF=A1=E5=85=AC?= =?UTF-8?q?=E4=BC=97=E5=8F=B7=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E5=B0=8F=E7=A8=8B=E5=BA=8F=E8=AE=A4=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wechat/config/WechatFilterConfig.java | 20 ++- .../config/pojo/WechatMiniAppProperties.java | 104 +++++++++++++++ .../pojo/WechatOfficialAccountProperties.java | 37 ++++-- .../WechatMiniAppAuthController.java | 36 ++++++ .../cm/common/wechat/filter/WechatFilter.java | 23 ++-- .../wechat/filter/WechatMiniAppFilter.java | 119 ++++++++++++++++++ .../manager/miniapp/WechatMiniAppManager.java | 27 ++++ .../WechatOfficialAccountManager.java | 3 +- .../wechat/pojo/WechatMiniAppLoginVO.java | 40 ++++++ .../wechat/pojo/WechatMiniAppUserInfo.java | 77 ++++++++++++ .../service/IWechatMiniAppAuthService.java | 28 +++++ .../impl/WechatMiniAppAuthServiceImpl.java | 97 ++++++++++++++ 12 files changed, 578 insertions(+), 33 deletions(-) create mode 100644 cloud-common-wechat/src/main/java/com/cm/common/wechat/config/pojo/WechatMiniAppProperties.java create mode 100644 cloud-common-wechat/src/main/java/com/cm/common/wechat/controller/WechatMiniAppAuthController.java create mode 100644 cloud-common-wechat/src/main/java/com/cm/common/wechat/filter/WechatMiniAppFilter.java create mode 100644 cloud-common-wechat/src/main/java/com/cm/common/wechat/manager/miniapp/WechatMiniAppManager.java create mode 100644 cloud-common-wechat/src/main/java/com/cm/common/wechat/pojo/WechatMiniAppLoginVO.java create mode 100644 cloud-common-wechat/src/main/java/com/cm/common/wechat/pojo/WechatMiniAppUserInfo.java create mode 100644 cloud-common-wechat/src/main/java/com/cm/common/wechat/service/IWechatMiniAppAuthService.java create mode 100644 cloud-common-wechat/src/main/java/com/cm/common/wechat/service/impl/WechatMiniAppAuthServiceImpl.java diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/WechatFilterConfig.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/WechatFilterConfig.java index 657dc49..9f118db 100644 --- a/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/WechatFilterConfig.java +++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/WechatFilterConfig.java @@ -1,7 +1,9 @@ package com.cm.common.wechat.config; +import com.cm.common.constants.ISystemConstant; import com.cm.common.wechat.config.pojo.WechatOfficialAccountProperties; import com.cm.common.wechat.filter.WechatFilter; +import com.cm.common.wechat.filter.WechatMiniAppFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.FilterRegistrationBean; @@ -21,9 +23,6 @@ import org.springframework.context.annotation.Configuration; @Configuration public class WechatFilterConfig { - @Value(value = "${open-platform.wechat.apiCrossOrigin}") - private Boolean apiCrossOrigin; - @Autowired private WechatOfficialAccountProperties wechatOfficialAccountProperties; @@ -31,14 +30,25 @@ public class WechatFilterConfig { public FilterRegistrationBean wechatFilterRegister() { WechatFilter wechatFilter = new WechatFilter(); wechatFilter.setWechatOfficialAccountProperties(wechatOfficialAccountProperties); - wechatFilter.setApiCrossOrigin(apiCrossOrigin); FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(wechatFilter); - filterRegistrationBean.addUrlPatterns("/wechat/*", "/wechatroute/*"); + filterRegistrationBean.addUrlPatterns(ISystemConstant.WECHAT_PREFIX + "/*", ISystemConstant.WECHAT_ROUTE_PREFIX + "/*"); filterRegistrationBean.setName("wechatFilter"); filterRegistrationBean.setOrder(1); return filterRegistrationBean; } + @Bean + public FilterRegistrationBean wechatMiniAppRegister() { + WechatMiniAppFilter wechatMiniAppFilter = new WechatMiniAppFilter(); + + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); + filterRegistrationBean.setFilter(wechatMiniAppFilter); + filterRegistrationBean.addUrlPatterns(ISystemConstant.WECHAT_MINI_APP_PREFIX + "/*"); + filterRegistrationBean.setName("wechatMiniAppFilter"); + filterRegistrationBean.setOrder(1); + return filterRegistrationBean; + } + } diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/pojo/WechatMiniAppProperties.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/pojo/WechatMiniAppProperties.java new file mode 100644 index 0000000..df612f1 --- /dev/null +++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/pojo/WechatMiniAppProperties.java @@ -0,0 +1,104 @@ +package com.cm.common.wechat.config.pojo; + +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 WechatMiniAppProperties { + + private Boolean active; + private String authorizeUrl; + private String bindUserUrl; + private String grantType; + private String appKey; + private String appSecret; + private String configToken; + + 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; + } + + public String getConfigToken() { + return configToken == null ? "" : configToken; + } + + public void setConfigToken(String configToken) { + this.configToken = configToken; + } + + @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(",\"configToken\":\"") + .append(configToken).append('\"'); + sb.append('}'); + return sb.toString(); + } +} diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/pojo/WechatOfficialAccountProperties.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/pojo/WechatOfficialAccountProperties.java index ccce16d..8d85984 100644 --- a/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/pojo/WechatOfficialAccountProperties.java +++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/config/pojo/WechatOfficialAccountProperties.java @@ -18,6 +18,7 @@ import org.springframework.stereotype.Component; @ConfigurationProperties(prefix = "open-platform.wechat.official-account") public class WechatOfficialAccountProperties { + private Boolean apiCrossOrigin; private Boolean activate; private WechatOfficialAccountAuthorizeProperties authorize; private String accessTokenUrl; @@ -27,6 +28,14 @@ public class WechatOfficialAccountProperties { private String grantType; private String configToken; + public Boolean getApiCrossOrigin() { + return apiCrossOrigin; + } + + public void setApiCrossOrigin(Boolean apiCrossOrigin) { + this.apiCrossOrigin = apiCrossOrigin; + } + public Boolean getActivate() { return activate; } @@ -94,22 +103,24 @@ public class WechatOfficialAccountProperties { @Override public String toString() { final StringBuilder sb = new StringBuilder("{"); - sb.append("\"activate\":") + sb.append("\"apiCrossOrigin\":") + .append(apiCrossOrigin); + sb.append(",\"activate\":") .append(activate); sb.append(",\"authorize\":") .append(authorize); - sb.append(",\"accessTokenUrl\":") - .append("\"").append(accessTokenUrl).append("\""); - sb.append(",\"bindUserUrl\":") - .append("\"").append(bindUserUrl).append("\""); - sb.append(",\"appId\":") - .append("\"").append(appId).append("\""); - sb.append(",\"appSecret\":") - .append("\"").append(appSecret).append("\""); - sb.append(",\"grantType\":") - .append("\"").append(grantType).append("\""); - sb.append(",\"configToken\":") - .append("\"").append(configToken).append("\""); + sb.append(",\"accessTokenUrl\":\"") + .append(accessTokenUrl).append('\"'); + sb.append(",\"bindUserUrl\":\"") + .append(bindUserUrl).append('\"'); + sb.append(",\"appId\":\"") + .append(appId).append('\"'); + sb.append(",\"appSecret\":\"") + .append(appSecret).append('\"'); + sb.append(",\"grantType\":\"") + .append(grantType).append('\"'); + sb.append(",\"configToken\":\"") + .append(configToken).append('\"'); sb.append('}'); return sb.toString(); } diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/controller/WechatMiniAppAuthController.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/controller/WechatMiniAppAuthController.java new file mode 100644 index 0000000..868f323 --- /dev/null +++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/controller/WechatMiniAppAuthController.java @@ -0,0 +1,36 @@ +package com.cm.common.wechat.controller; + +import com.cm.common.annotation.CheckRequestBodyAnnotation; +import com.cm.common.constants.ISystemConstant; +import com.cm.common.result.SuccessResultData; +import com.cm.common.wechat.pojo.WechatMiniAppLoginVO; +import com.cm.common.wechat.service.IWechatMiniAppAuthService; +import io.swagger.annotations.Api; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: WechatMiniAppSignController + * @Description: 微信小程序登录 + * @Author: WangGeng + * @Date: 2020/5/9 18:08 + * @Version: 1.0 + **/ +@Api(tags = ISystemConstant.API_TAGS_WECHAT_MINI_APP_PREFIX + "小程序认证") +@RestController +@RequestMapping(ISystemConstant.WECHAT_MINI_APP_PREFIX + "/auth") +public class WechatMiniAppAuthController { + + @Autowired + private IWechatMiniAppAuthService wechatMiniAppAuthService; + + @PostMapping("login") + @CheckRequestBodyAnnotation + public SuccessResultData login(@RequestBody WechatMiniAppLoginVO wechatMiniAppLoginVO) throws Exception { + return wechatMiniAppAuthService.login(wechatMiniAppLoginVO); + } + +} diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/filter/WechatFilter.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/filter/WechatFilter.java index a348ce8..cb80477 100644 --- a/cloud-common-wechat/src/main/java/com/cm/common/wechat/filter/WechatFilter.java +++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/filter/WechatFilter.java @@ -41,29 +41,28 @@ public class WechatFilter implements Filter { private static final Logger LOG = LoggerFactory.getLogger(WechatFilter.class); private WechatOfficialAccountProperties wechatOfficialAccountProperties; - private Boolean apiCrossOrigin; private AntPathMatcher antPathMatcher; - private static final String WECHAT_LOGIN_URL = "/**/wechat/sign/login"; + private static final String WECHAT_LOGIN_URL = String.format("/**%s/sign/login", ISystemConstant.WECHAT_PREFIX); /** * 微信类放行 */ - private static final String WECHAT_RELEASE_URL = "/**/wechatrelease/**"; + private static final String WECHAT_RELEASE_URL = String.format("/**%s%s/**", ISystemConstant.WECHAT_PREFIX, ISystemConstant.RELEASE_SUFFIX); /** * 微信放行 */ - private static final String WECHAT_API_RELEASE_URL = "/**/wechat/**/**release/**"; + private static final String WECHAT_API_RELEASE_URL = String.format("/**%s/**/**%s/**", ISystemConstant.WECHAT_PREFIX, ISystemConstant.RELEASE_SUFFIX); /** * 微信路由放行 */ - private static final String WECHAT_ROUTE_RELEASE_URL = "/**/wechatroute/**/**release/**"; + private static final String WECHAT_ROUTE_RELEASE_URL = String.format("/**%s/**/**%s/**", ISystemConstant.WECHAT_ROUTE_PREFIX, ISystemConstant.RELEASE_SUFFIX); /** * 微信路由静态资源 */ - private static final String WECHAT_ROUTE_STATIC_URL = "/**/wechatroute/static/**"; - private static final String WECHAT_ROUTE_CSS_URL = "/**/wechatroute/css/**"; - private static final String WECHAT_ROUTE_JS_URL = "/**/wechatroute/js/**"; - private static final String WECHAT_ROUTE_IMAGES_URL = "/**/wechatroute/images/**"; + private static final String WECHAT_ROUTE_STATIC_URL = String.format("/**%s/static/**", ISystemConstant.WECHAT_ROUTE_PREFIX); + private static final String WECHAT_ROUTE_CSS_URL = String.format("/**%s/css/**", ISystemConstant.WECHAT_ROUTE_PREFIX); + private static final String WECHAT_ROUTE_JS_URL = String.format("/**%s/js/**", ISystemConstant.WECHAT_ROUTE_PREFIX); + private static final String WECHAT_ROUTE_IMAGES_URL = String.format("/**%s/images/**", ISystemConstant.WECHAT_ROUTE_PREFIX); /** * 上传文件 */ @@ -79,7 +78,7 @@ public class WechatFilter implements Filter { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; - if (apiCrossOrigin != null && apiCrossOrigin) { + if (wechatOfficialAccountProperties.getApiCrossOrigin() != null && wechatOfficialAccountProperties.getApiCrossOrigin()) { response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Credentials", "true"); @@ -228,10 +227,6 @@ public class WechatFilter implements Filter { this.wechatOfficialAccountProperties = wechatOfficialAccountProperties; } - public void setApiCrossOrigin(Boolean apiCrossOrigin) { - this.apiCrossOrigin = apiCrossOrigin; - } - /** * 错误返回 * diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/filter/WechatMiniAppFilter.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/filter/WechatMiniAppFilter.java new file mode 100644 index 0000000..e745b5b --- /dev/null +++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/filter/WechatMiniAppFilter.java @@ -0,0 +1,119 @@ +package com.cm.common.wechat.filter; + +import com.alibaba.fastjson.JSON; +import com.cm.common.constants.ISystemConstant; +import com.cm.common.enums.AppTokenTypeEnum; +import com.cm.common.enums.ErrorResultCodeEnum; +import com.cm.common.exception.TokenException; +import com.cm.common.result.ErrorResult; +import com.cm.common.token.app.AppTokenManager; +import com.cm.common.token.app.entity.AppToken; +import com.cm.common.token.app.entity.AppTokenUser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.StringUtils; + +import javax.servlet.*; +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: MiniProgramFilter + * @Description: 小程序过滤器 + * @Author: WangGeng + * @Date: 2020/5/9 16:06 + * @Version: 1.0 + **/ +public class WechatMiniAppFilter implements Filter { + + private static final Logger LOG = LoggerFactory.getLogger(WechatMiniAppFilter.class); + private AntPathMatcher antPathMatcher; + + private static final String WECHAT_MINI_APP_LOGIN_URL = String.format("/**%s/auth/login", ISystemConstant.WECHAT_MINI_APP_PREFIX); + /** + * 微信类放行 + */ + private static final String WECHAT_MINI_APP_RELEASE_URL = String.format("/**%s%s/**", ISystemConstant.WECHAT_MINI_APP_PREFIX, ISystemConstant.APP_RELEASE_SUFFIX); + /** + * 微信放行 + */ + private static final String WECHAT_API_MINI_APP_RELEASE_URL = String.format("/**%s/**/**%s/**", ISystemConstant.WECHAT_MINI_APP_PREFIX, ISystemConstant.APP_RELEASE_SUFFIX); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + antPathMatcher = new AntPathMatcher(); + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + + String requestUri = request.getRequestURI(); + boolean isLogin = antPathMatcher.match(WECHAT_MINI_APP_LOGIN_URL, requestUri); + if (isLogin) { + + return; + } + + boolean isRelease = antPathMatcher.match(WECHAT_MINI_APP_RELEASE_URL, requestUri) || + antPathMatcher.match(WECHAT_API_MINI_APP_RELEASE_URL, requestUri); + if (isRelease) { + filterChain.doFilter(request, response); + return; + } + + String token = request.getHeader("token"); + if (StringUtils.isEmpty(token)) { + errorResponse(response, "token不能为空"); + return; + } + LOG.debug("校验token"); + try { + checkToken(token); + } catch (TokenException e) { + errorResponse(response, e.getMessage()); + return; + } + filterChain.doFilter(request, response); + } + + @Override + public void destroy() { + + } + + private void checkToken(String token) throws TokenException { + AppTokenManager appTokenManager = AppTokenManager.getInstance(); + LOG.debug("检查token是否存在"); + AppToken appToken = appTokenManager.getToken(token); + if (appToken != null) { + return; + } + LOG.debug("解析token是否合法"); + AppTokenUser appTokenUser = appTokenManager.parseToAppTokenUser(token); + appTokenManager.addToken(token, AppTokenTypeEnum.WECHAT_MINI_APP, appTokenUser); + } + + /** + * 错误返回 + * + * @param response + * @param errorInfo + * @throws IOException + */ + private void errorResponse(HttpServletResponse response, String errorInfo) throws IOException { + response.setStatus(HttpStatus.BAD_REQUEST.value()); + response.setHeader("Content-Type", "application/json;charset=UTF-8"); + ErrorResult result = new ErrorResult(ErrorResultCodeEnum.PARAMS_ERROR.getValue(), errorInfo); + response.getWriter().write(JSON.toJSONString(result)); + } + +} diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/manager/miniapp/WechatMiniAppManager.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/manager/miniapp/WechatMiniAppManager.java new file mode 100644 index 0000000..531c32a --- /dev/null +++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/manager/miniapp/WechatMiniAppManager.java @@ -0,0 +1,27 @@ +package com.cm.common.wechat.manager.miniapp; + +import com.cm.common.wechat.config.pojo.WechatMiniAppProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: WechatMiniAppManager + * @Description: 微信小程序管理 + * @Author: WangGeng + * @Date: 2020/5/9 18:05 + * @Version: 1.0 + **/ +public class WechatMiniAppManager { + + private static final Logger LOG = LoggerFactory.getLogger(WechatMiniAppManager.class); + private WechatMiniAppProperties wechatMiniAppProperties; + + + + public void setWechatMiniAppProperties(WechatMiniAppProperties wechatMiniAppProperties) { + this.wechatMiniAppProperties = wechatMiniAppProperties; + } +} diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/manager/officialaccount/WechatOfficialAccountManager.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/manager/officialaccount/WechatOfficialAccountManager.java index dc3219d..28e41ea 100644 --- a/cloud-common-wechat/src/main/java/com/cm/common/wechat/manager/officialaccount/WechatOfficialAccountManager.java +++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/manager/officialaccount/WechatOfficialAccountManager.java @@ -46,7 +46,8 @@ public class WechatOfficialAccountManager { private String accessToken; private long updateTime = 0L; - private WechatOfficialAccountManager() {} + private WechatOfficialAccountManager() { + } public static WechatOfficialAccountManager getInstance() { return wechatOfficialAccountManager; diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/pojo/WechatMiniAppLoginVO.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/pojo/WechatMiniAppLoginVO.java new file mode 100644 index 0000000..c58846b --- /dev/null +++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/pojo/WechatMiniAppLoginVO.java @@ -0,0 +1,40 @@ +package com.cm.common.wechat.pojo; + +import com.cm.common.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 WechatMiniAppLoginVO { + + @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(); + } +} diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/pojo/WechatMiniAppUserInfo.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/pojo/WechatMiniAppUserInfo.java new file mode 100644 index 0000000..f84c42f --- /dev/null +++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/pojo/WechatMiniAppUserInfo.java @@ -0,0 +1,77 @@ +package com.cm.common.wechat.pojo; + +/** + * 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 WechatMiniAppUserInfo { + + private String openid; + private String session_key; + private String unionid; + private Integer errcode; + private String errmsg; + + 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; + } + + @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).append('\"'); + sb.append(",\"errmsg\":\"") + .append(errmsg).append('\"'); + sb.append('}'); + return sb.toString(); + } +} diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/service/IWechatMiniAppAuthService.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/service/IWechatMiniAppAuthService.java new file mode 100644 index 0000000..bb803b5 --- /dev/null +++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/service/IWechatMiniAppAuthService.java @@ -0,0 +1,28 @@ +package com.cm.common.wechat.service; + +import com.cm.common.exception.SaveException; +import com.cm.common.exception.SearchException; +import com.cm.common.exception.TokenException; +import com.cm.common.result.SuccessResultData; +import com.cm.common.wechat.pojo.WechatMiniAppLoginVO; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: IWechatMiniAppAuthService + * @Description: 小程序认证 + * @Author: WangGeng + * @Date: 2020/5/9 18:16 + * @Version: 1.0 + **/ +public interface IWechatMiniAppAuthService { + /** + * 登录 + * + * @param wechatMiniAppLoginVO + * @return + * @throws TokenException + */ + SuccessResultData login(WechatMiniAppLoginVO wechatMiniAppLoginVO) throws Exception; +} diff --git a/cloud-common-wechat/src/main/java/com/cm/common/wechat/service/impl/WechatMiniAppAuthServiceImpl.java b/cloud-common-wechat/src/main/java/com/cm/common/wechat/service/impl/WechatMiniAppAuthServiceImpl.java new file mode 100644 index 0000000..509067f --- /dev/null +++ b/cloud-common-wechat/src/main/java/com/cm/common/wechat/service/impl/WechatMiniAppAuthServiceImpl.java @@ -0,0 +1,97 @@ +package com.cm.common.wechat.service.impl; + +import com.cm.common.exception.SearchException; +import com.cm.common.exception.WechatAccessTokenForUserException; +import com.cm.common.exception.WechatUserInfoException; +import com.cm.common.exception.base.SystemException; +import com.cm.common.result.SuccessResultData; +import com.cm.common.utils.AesUtil; +import com.cm.common.wechat.config.pojo.WechatMiniAppProperties; +import com.cm.common.wechat.pojo.WechatMiniAppLoginVO; +import com.cm.common.wechat.pojo.WechatMiniAppUserInfo; +import com.cm.common.wechat.pojo.WechatOfficialAccountUserInfo; +import com.cm.common.wechat.service.IWechatMiniAppAuthService; +import org.apache.commons.codec.binary.Base64; +import org.codehaus.jackson.map.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * When you feel like quitting. Think about why you started + * 当你想要放弃的时候,想想当初你为何开始 + * + * @ClassName: WechatMiniAppAuthServiceImpl + * @Description: 小程序认证 + * @Author: WangGeng + * @Date: 2020/5/9 18:16 + * @Version: 1.0 + **/ +@Service +public class WechatMiniAppAuthServiceImpl implements IWechatMiniAppAuthService { + + private static final Logger LOG = LoggerFactory.getLogger(WechatMiniAppAuthServiceImpl.class); + + @Autowired + private WechatMiniAppProperties wechatMiniAppProperties; + + @Override + public SuccessResultData login(WechatMiniAppLoginVO wechatMiniAppLoginVO) throws Exception { + if (wechatMiniAppProperties == null) { + throw new SystemException("未有相关配置"); + } + Map params = new HashMap<>(2); + params.put("appid", wechatMiniAppProperties.getAppKey()); + params.put("secret", wechatMiniAppProperties.getAppSecret()); + params.put("js_code", wechatMiniAppLoginVO.getJsCode()); + params.put("grant_type", wechatMiniAppProperties.getGrantType()); + + StringBuilder url = new StringBuilder(wechatMiniAppProperties.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); + WechatMiniAppUserInfo wechatMiniAppUserInfo = new ObjectMapper().readValue(resultJson, WechatMiniAppUserInfo.class); + if (wechatMiniAppUserInfo == null) { + throw new WechatUserInfoException("获取微信用户信息失败"); + } + if (wechatMiniAppUserInfo.getErrcode() != null && wechatMiniAppUserInfo.getErrcode() != 0) { + throw new WechatAccessTokenForUserException(String.format("获取用户信息失败,错误码:%s,错误信息:%s", wechatMiniAppUserInfo.getErrcode(), wechatMiniAppUserInfo.getErrmsg())); + } + + LOG.debug("绑定用户 | 登录"); + String wechatSignInfo = Base64.encodeBase64String(AesUtil.aesCommonEncoder("WECHAT_SIGN_INFO", new StringBuilder(wechatMiniAppUserInfo.getOpenid()).append("_WenG_").append(wechatMiniAppProperties.getAppKey()).toString()).getBytes("UTF-8")); + String token = getAppToken(wechatSignInfo); + return new SuccessResultData(token); + } + + /** + * 获取token + * + * @param wechatSignInfo + * @return + */ + public String getAppToken(String wechatSignInfo) { + RestTemplate restTemplate = new RestTemplate(); + Map params = new HashMap<>(1); + params.put("signInfo", wechatSignInfo); + HttpEntity> requestBody = new HttpEntity<>(params); + ResponseEntity result = restTemplate.postForEntity(wechatMiniAppProperties.getBindUserUrl(), requestBody, Map.class); + LOG.debug("状态码:{}", result.getStatusCodeValue()); + if (HttpStatus.OK.value() != result.getStatusCodeValue()) { + throw new SearchException("获取Token失败"); + } + Map body = result.getBody(); + return (String) body.get("data"); + } + +}