diff --git a/blog-admin/src/main/resources/templates/config.ftl b/blog-admin/src/main/resources/templates/config.ftl index a5cd8777e756dd8d43bd281680c67c8c5c038922..e26ad901eddf0c7dd982ffc383509a3e0e4442f0 100644 --- a/blog-admin/src/main/resources/templates/config.ftl +++ b/blog-admin/src/main/resources/templates/config.ftl @@ -715,6 +715,18 @@ +
+ +
+ +
+
+
+ +
+ +
+
diff --git a/blog-core/src/main/java/com/zyd/blog/business/enums/ConfigKeyEnum.java b/blog-core/src/main/java/com/zyd/blog/business/enums/ConfigKeyEnum.java index 11b10af20321b8a317290cfbc0cd2812a6fe1c0a..c494044a1319cfb6e5651e9adc944ef275c894ea 100644 --- a/blog-core/src/main/java/com/zyd/blog/business/enums/ConfigKeyEnum.java +++ b/blog-core/src/main/java/com/zyd/blog/business/enums/ConfigKeyEnum.java @@ -250,6 +250,14 @@ public enum ConfigKeyEnum { * 启用 Hitokoto(一言)。一言,随机显示一句话的插件,该插件部分时候加载较慢,如果不需要请自行关闭 */ ENABLE_HITOKOTO("enableHitokoto"), + /** + * 微信公众号appId + */ + WX_GZH_APP_ID("wxGzhAppId"), + /** + * 微信公众号AppSecret + */ + WX_GZH_APP_SECRET("wxGzhAppSecret"), ; private final String key; diff --git a/blog-core/src/main/java/com/zyd/blog/util/GetAccessTokenComponent.java b/blog-core/src/main/java/com/zyd/blog/util/GetAccessTokenComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..b1a571b46014201588f837ba5e409960dcc8aa51 --- /dev/null +++ b/blog-core/src/main/java/com/zyd/blog/util/GetAccessTokenComponent.java @@ -0,0 +1,52 @@ +package com.zyd.blog.util; + +import com.alibaba.fastjson.JSONObject; +import org.apache.http.client.HttpClient; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.BasicResponseHandler; +import org.apache.http.impl.client.DefaultHttpClient; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author: gelin + * @phone:17788767989 + * @Createdate: 2022/8/4 13:58 + */ +@Component +public class GetAccessTokenComponent { + + /** + * 网页授权接口 + */ + public final String AccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET"; + + public Map getAccessToken(String appId, String AppSecret) { + Map result = new HashMap<>(); + + String requestUrl = AccessTokenUrl.replace("APPID", appId).replace("SECRET", AppSecret); + HttpClient client = null; + + try { + client = new DefaultHttpClient(); + HttpGet httpget = new HttpGet(requestUrl); + ResponseHandler responseHandler = new BasicResponseHandler(); + String response = client.execute(httpget, responseHandler); + JSONObject OpenidJSON = JSONObject.parseObject(response); + + String accessToken = String.valueOf(OpenidJSON.get("access_token")); + // 秒 + Integer expiresIn = (Integer) OpenidJSON.get("expires_in"); + + result.put("accessToken", accessToken); + } catch (Exception e) { + e.printStackTrace(); + } finally { + client.getConnectionManager().shutdown(); + } + return result; + } +} diff --git a/blog-core/src/main/java/com/zyd/blog/util/JsApiTicketComponent.java b/blog-core/src/main/java/com/zyd/blog/util/JsApiTicketComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..1e439824b0bb539df0d7c0be35bc1ecb8ed88c2e --- /dev/null +++ b/blog-core/src/main/java/com/zyd/blog/util/JsApiTicketComponent.java @@ -0,0 +1,55 @@ +package com.zyd.blog.util; + +import com.alibaba.fastjson.JSONObject; +import org.apache.http.client.HttpClient; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.BasicResponseHandler; +import org.apache.http.impl.client.DefaultHttpClient; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author: gelin + * @phone:17788767989 + * @Createdate: 2022/8/4 14:00 + */ +@Component +public class JsApiTicketComponent { + + /** + * 网页授权接口 + */ + public final String AccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi"; + + public Map JsapiTicket(String accessToken) { + Map result = new HashMap<>(); + + // 缓存过期,重新生成 + String requestUrl = AccessTokenUrl.replace("ACCESS_TOKEN", accessToken); + HttpClient client = null; + + try { + client = new DefaultHttpClient(); + HttpGet httpget = new HttpGet(requestUrl); + ResponseHandler responseHandler = new BasicResponseHandler(); + String response = client.execute(httpget, responseHandler); + JSONObject openidJSON = JSONObject.parseObject(response); + String errcode = String.valueOf(openidJSON.get("errcode")); + String errmsg = String.valueOf(openidJSON.get("errmsg")); + String ticket = String.valueOf(openidJSON.get("ticket")); + Integer expiresIn = (Integer) openidJSON.get("expires_in"); + + result.put("errcode", errcode); + result.put("errmsg", errmsg); + result.put("ticket", ticket); + } catch (Exception e) { + e.printStackTrace(); + } finally { + client.getConnectionManager().shutdown(); + } + return result; + } +} diff --git a/blog-web/src/main/java/com/zyd/blog/controller/RestApiController.java b/blog-web/src/main/java/com/zyd/blog/controller/RestApiController.java index 6a5c2a1a6d2b3d9c9c07f58bc1b80994ed934f6e..1776eed9e4bba4b3b01e1c73eee0fa08bc6ab4f5 100644 --- a/blog-web/src/main/java/com/zyd/blog/controller/RestApiController.java +++ b/blog-web/src/main/java/com/zyd/blog/controller/RestApiController.java @@ -9,6 +9,7 @@ import com.zyd.blog.business.entity.BizAdBo; import com.zyd.blog.business.entity.Comment; import com.zyd.blog.business.entity.Link; import com.zyd.blog.business.enums.CommentStatusEnum; +import com.zyd.blog.business.enums.ConfigKeyEnum; import com.zyd.blog.business.enums.PlatformEnum; import com.zyd.blog.business.service.*; import com.zyd.blog.business.vo.CommentConditionVO; @@ -16,9 +17,14 @@ import com.zyd.blog.framework.exception.ZhydArticleException; import com.zyd.blog.framework.exception.ZhydCommentException; import com.zyd.blog.framework.exception.ZhydLinkException; import com.zyd.blog.framework.object.ResponseVO; +import com.zyd.blog.framework.property.AppProperties; +import com.zyd.blog.persistence.beans.SysConfig; +import com.zyd.blog.util.GetAccessTokenComponent; +import com.zyd.blog.util.JsApiTicketComponent; import com.zyd.blog.util.RestClientUtil; import com.zyd.blog.util.ResultUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.digest.DigestUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; @@ -26,9 +32,11 @@ import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.net.URLDecoder; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.function.Function; import java.util.stream.Collectors; @@ -56,6 +64,12 @@ public class RestApiController { private SysNoticeService noticeService; @Autowired private BizAdService adService; + @Autowired + private GetAccessTokenComponent getAccessTokenComponent; + @Autowired + private JsApiTicketComponent jsApiTicketComponent; + @Autowired + private SysConfigService sysConfigService; @PostMapping("/autoLink") @BussinessLog(value = "自助申请友链", platform = PlatformEnum.WEB) @@ -188,4 +202,63 @@ public class RestApiController { return ResultUtil.success(res); } + @PostMapping("/jssdkGetSignature") + @BussinessLog(value = "获取jssdk签名", platform = PlatformEnum.WEB, save = false) + public ResponseVO jssdkGetSignature(String url) { + + if (StringUtils.isEmpty(url)) { + return ResultUtil.error("页面地址为空"); + } + + String urlN = ""; + try { + urlN = URLDecoder.decode(url, "UTF-8"); + } catch (Exception e) { + e.printStackTrace(); + } + + SysConfig configId = sysConfigService.getByKey(ConfigKeyEnum.WX_GZH_APP_ID.getKey()); + SysConfig configSecret = sysConfigService.getByKey(ConfigKeyEnum.WX_GZH_APP_SECRET.getKey()); + if (StringUtils.isEmpty(configId) || StringUtils.isEmpty(configSecret)) { + return ResultUtil.error("微信公众号appId、AppSecret未配置"); + } + Map tokenMap = getAccessTokenComponent.getAccessToken(configId.getConfigValue(), configSecret.getConfigValue()); + String accessToken = tokenMap.get("accessToken"); + if (StringUtils.isEmpty(accessToken)) { + log.error("accessToken is null"); + return ResultUtil.error("accessToken is empty"); + } + + Map ticketMap = jsApiTicketComponent.JsapiTicket(accessToken); + String ticket = ticketMap.get("ticket"); + if (StringUtils.isEmpty(ticket)) { + log.error("ticket is null"); + return ResultUtil.error("ticket is empty"); + } + + //随机字符串 + String nonceStr = UUID.randomUUID().toString().replaceAll("-", ""); + //时间戳 微信要求为秒 + Long timestamp = System.currentTimeMillis() / 1000; + //4获取url 根据项目需要获取对应的url地址 + + //5、将参数排序并拼接字符串 此处noncestr不能驼峰大写 按key的ascii顺序 + String str = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "×tamp=" + timestamp + "&url=" + urlN; + + //6、将字符串进行sha1加密 + String signature = DigestUtils.sha1Hex(str); + Map map = new HashMap<>(); + + map.put("appid", configId.getConfigValue()); + map.put("timestamp", timestamp); + map.put("noncestr", nonceStr); + map.put("accessToken", accessToken); + map.put("ticket", ticket); + map.put("signature", signature); + +// log.info("str: {}", str); +// log.info("urlN: {}, map: {}", urlN, JSONUtils.toJSONString(map)); + return ResultUtil.success("jssdkGetSignature获取成功", map); + } + } diff --git a/blog-web/src/main/resources/templates/article.ftl b/blog-web/src/main/resources/templates/article.ftl index 60305258bd994ce18cbae68634c729f9e5703060..e29d078021ff656f9eb41c7e0cc05d6db586f171 100644 --- a/blog-web/src/main/resources/templates/article.ftl +++ b/blog-web/src/main/resources/templates/article.ftl @@ -266,6 +266,7 @@ <#-- --> +