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 @@
<#-- -->
+
@footer>