diff --git a/jeecg-module-system/jeecg-system-start/src/main/java/org/jeecg/modules/contoller/h5/WxAuthController.java b/jeecg-module-system/jeecg-system-start/src/main/java/org/jeecg/modules/contoller/h5/WxAuthController.java new file mode 100644 index 00000000..e5e5f17c --- /dev/null +++ b/jeecg-module-system/jeecg-system-start/src/main/java/org/jeecg/modules/contoller/h5/WxAuthController.java @@ -0,0 +1,130 @@ +package org.jeecg.modules.contoller.h5; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.bean.WxOAuth2UserInfo; +import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import org.jeecg.common.api.vo.Result; +import org.jeecg.modules.utils.CookieUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Map; +import java.util.TreeMap; +import java.util.UUID; + +/** + * 微信网页授权相关 + */ +@RestController +@RequestMapping("/wxAuth") +@Api(tags = {"微信网页授权"}) +@RequiredArgsConstructor +public class WxAuthController { + Logger logger = LoggerFactory.getLogger(this.getClass()); + @Autowired + private final WxMpService wxMpService; + + /** + * 使用微信授权code换取openid + * + * @param request + * @param response + * @param form + * @return + */ + @PostMapping("/codeToOpenid") + @CrossOrigin + @ApiOperation(value = "网页登录-code换取openid",notes = "scope为snsapi_base") + public Result codeToOpenid(HttpServletRequest request, HttpServletResponse response, + @CookieValue String appid, @RequestBody WxH5OuthrizeForm form) { + try { + this.wxMpService.switchoverTo(appid); + WxOAuth2AccessToken token = wxMpService.getOAuth2Service().getAccessToken(form.getCode()); + String openid = token.getOpenId(); + CookieUtil.setCookie(response, "openid", openid, 365 * 24 * 60 * 60); + String openidToken = MD5Util.getMd5AndSalt(openid); + CookieUtil.setCookie(response, "openidToken", openidToken, 365 * 24 * 60 * 60); + return Result.ok(openid); + } catch (WxErrorException e) { + logger.error("code换取openid失败", e); + return Result.error(e.getError().getErrorMsg()); + } + } + + /** + * 使用微信授权code换取用户信息(需scope为 snsapi_userinfo) + * + * @param request + * @param response + * @param form + * @return + */ + @PostMapping("/codeToUserInfo") + @CrossOrigin + @ApiOperation(value = "网页登录-code换取用户信息",notes = "需scope为 snsapi_userinfo") + public Result codeToUserInfo(HttpServletRequest request, HttpServletResponse response, + @CookieValue String appid, @RequestBody WxH5OuthrizeForm form) { + try { + this.wxMpService.switchoverTo(appid); + WxOAuth2AccessToken token = wxMpService.getOAuth2Service().getAccessToken(form.getCode()); + WxOAuth2UserInfo userInfo = wxMpService.getOAuth2Service().getUserInfo(token,"zh_CN"); + String openid = userInfo.getOpenid(); + CookieUtil.setCookie(response, "openid", openid, 365 * 24 * 60 * 60); + String openidToken = MD5Util.getMd5AndSalt(openid); + CookieUtil.setCookie(response, "openidToken", openidToken, 365 * 24 * 60 * 60); + return Result.ok(new WxUser(userInfo,appid)); + } catch (WxErrorException e) { + logger.error("code换取用户信息失败", e); + return Result.error(e.getError().getErrorMsg()); + } + } + + /** + * 获取微信分享的签名配置 + * 允许跨域(只有微信公众号添加了js安全域名的网站才能加载微信分享,故这里不对域名进行校验) + * + * @param request + * @param response + * @return + */ + @GetMapping("/getShareSignature") + @ApiOperation(value = "获取微信分享的签名配置",notes = "微信公众号添加了js安全域名的网站才能加载微信分享") + public Result getShareSignature(HttpServletRequest request, HttpServletResponse response, @CookieValue String appid) throws WxErrorException { + this.wxMpService.switchoverTo(appid); + // 1.拼接url(当前网页的URL,不包含#及其后面部分) + String wxShareUrl = request.getHeader(Constant.WX_CLIENT_HREF_HEADER); + if (!StringUtils.hasText(wxShareUrl)) { + return Result.error("header中缺少"+Constant.WX_CLIENT_HREF_HEADER+"参数,微信分享加载失败"); + } + wxShareUrl = wxShareUrl.split("#")[0]; + Map wxMap = new TreeMap<>(); + String wxNoncestr = UUID.randomUUID().toString(); + String wxTimestamp = (System.currentTimeMillis() / 1000) + ""; + wxMap.put("noncestr", wxNoncestr); + wxMap.put("timestamp", wxTimestamp); + wxMap.put("jsapi_ticket", wxMpService.getJsapiTicket()); + wxMap.put("url", wxShareUrl); + + // 加密获取signature + StringBuilder wxBaseString = new StringBuilder(); + wxMap.forEach((key, value) -> wxBaseString.append(key).append("=").append(value).append("&")); + String wxSignString = wxBaseString.substring(0, wxBaseString.length() - 1); + // signature + String wxSignature = SHA1Util.sha1(wxSignString); + Map resMap = new TreeMap<>(); + resMap.put("appId", appid); + resMap.put("wxTimestamp", wxTimestamp); + resMap.put("wxNoncestr", wxNoncestr); + resMap.put("wxSignature", wxSignature); + return Result.ok(resMap); + } +} diff --git a/jeecg-module-system/jeecg-system-start/src/main/java/org/jeecg/modules/entity/WxH5OuthrizeForm.java b/jeecg-module-system/jeecg-system-start/src/main/java/org/jeecg/modules/entity/WxH5OuthrizeForm.java new file mode 100644 index 00000000..86f589f7 --- /dev/null +++ b/jeecg-module-system/jeecg-system-start/src/main/java/org/jeecg/modules/entity/WxH5OuthrizeForm.java @@ -0,0 +1,15 @@ +package org.jeecg.modules.entity; + +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +@Data +public class WxH5OuthrizeForm { + @NotEmpty(message = "code不得为空") + private String code; + + @Override + public String toString() { + return Json.toJsonString(this); + } +} diff --git a/jeecg-module-system/jeecg-system-start/src/main/java/org/jeecg/modules/utils/CookieUtil.java b/jeecg-module-system/jeecg-system-start/src/main/java/org/jeecg/modules/utils/CookieUtil.java new file mode 100644 index 00000000..c6c856ff --- /dev/null +++ b/jeecg-module-system/jeecg-system-start/src/main/java/org/jeecg/modules/utils/CookieUtil.java @@ -0,0 +1,64 @@ +package org.jeecg.modules.utils; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Cookie工具类 + */ +public class CookieUtil { + + /** + * 设置cookie + * + * @param maxAge 秒 + */ + public static void setCookie(HttpServletResponse response, String cookieName, String cookieValue, + int maxAge) { + Cookie cookie = new Cookie(cookieName, cookieValue); + maxAge = Math.max(maxAge, 0); + cookie.setMaxAge(maxAge); + cookie.setPath("/"); + response.addCookie(cookie); + } + + public static void clearCookie(HttpServletResponse response, String cookieName, String domain) { + Cookie cookie = new Cookie(cookieName, ""); + cookie.setMaxAge(0); + cookie.setDomain(domain); + cookie.setPath("/"); + response.addCookie(cookie); + } + + public static void refreshCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, + String domain, int maxAge) { + Cookie cookie = getCookie(request, cookieName); + if (cookie != null) { + cookie.setMaxAge(maxAge); + cookie.setDomain(domain); + cookie.setPath("/"); + response.addCookie(cookie); + } + } + + public static String getCookieValue(HttpServletRequest request, String cookieName) { + Cookie cookie = getCookie(request, cookieName); + if (cookie != null) { + return cookie.getValue(); + } + return null; + } + + private static Cookie getCookie(HttpServletRequest request, String cookieName) { + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (int i = 0; i < cookies.length; i++) { + if (cookieName.equals(cookies[i].getName())) { + return cookies[i]; + } + } + } + return null; + } +} diff --git a/pom.xml b/pom.xml index 94176c3e..73430e38 100644 --- a/pom.xml +++ b/pom.xml @@ -77,6 +77,7 @@ 1.2.9 1.5.2 + 4.5.6.B @@ -116,6 +117,11 @@ + + com.github.binarywang + weixin-java-mp + ${weixin-java.version} + org.springframework.boot spring-boot-starter-test