diff --git a/udf-starter-weixin-mp-api/pom.xml b/udf-starter-weixin-mp-api/pom.xml index b8cc400..f49c757 100644 --- a/udf-starter-weixin-mp-api/pom.xml +++ b/udf-starter-weixin-mp-api/pom.xml @@ -23,6 +23,10 @@ org.itkk.udf udf-starter-amqp-rabbitmq + + org.itkk.udf + udf-starter-cache-redis + commons-codec diff --git a/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/Menu.java b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/Menu.java new file mode 100644 index 0000000..6520c2a --- /dev/null +++ b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/Menu.java @@ -0,0 +1,56 @@ +package org.itkk.udf.weixin.mp.api; + +import org.itkk.udf.weixin.mp.api.domain.BaseResult; +import org.itkk.udf.weixin.mp.api.domain.MenuGroup; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +/** + * Menu + */ +@Component +public class Menu { + + /** + * weixinMpApiProperties + */ + @Autowired + private WeixinMpApiProperties weixinMpApiProperties; + + /** + * token + */ + @Autowired + private Token token; + + /** + * externalRestTemplate + */ + @Autowired + @Qualifier("externalRestTemplate") + private RestTemplate externalRestTemplate; + + /** + * 创建菜单 + * + * @param businessCode 业务代码 + * @param menuGroup 菜单组 + * @return BaseResult + */ + public BaseResult create(String businessCode, MenuGroup menuGroup) { + //获得接口地址 + String path = weixinMpApiProperties.getApiPath().get("menu_create"); + //拼接url + StringBuilder url = new StringBuilder(path); + url.append(WeixinMpConsont.appendAccessToken(token.get(businessCode))); + //请求 + BaseResult result = externalRestTemplate.postForEntity(url.toString(), menuGroup, BaseResult.class).getBody(); + //验证 + WeixinMpConsont.checkResult(result); + //返回 + return result; + } + +} diff --git a/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/Token.java b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/Token.java new file mode 100644 index 0000000..90e149d --- /dev/null +++ b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/Token.java @@ -0,0 +1,82 @@ +package org.itkk.udf.weixin.mp.api; + +import org.itkk.udf.weixin.mp.api.domain.AccessToken; +import org.itkk.udf.weixin.mp.api.meta.WeixinMpApiAuthMeta; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.util.concurrent.TimeUnit; + +/** + * Token + */ +@Component +public class Token { + + /** + * DISTRIBUTED_LOCK_KEY_PREFIX + */ + private static final String WEIXIN_MP_TOKEN_KEY_PREFIX = ":WEIXIN_MP_TOKEN:"; + + /** + * weixinMpApiProperties + */ + @Autowired + private WeixinMpApiProperties weixinMpApiProperties; + + /** + * externalRestTemplate + */ + @Autowired + @Qualifier("externalRestTemplate") + private RestTemplate externalRestTemplate; + + /** + * redisTemplate + */ + @Autowired + private RedisTemplate redisTemplate; + + /** + * profiles + */ + @Value("${spring.profiles.active}") + private String profiles; + + /** + * 获取access_token + * + * @param businessCode 业务代码 + * @return AccessToken + */ + protected String get(String businessCode) { + //获得认证相关信息 + WeixinMpApiAuthMeta auth = weixinMpApiProperties.getAuth().get(businessCode); + //生成缓存key + String key = profiles + WEIXIN_MP_TOKEN_KEY_PREFIX + businessCode + ":" + auth.getAppId(); + //检查缓存是否存在,如果存在,则直接返回 + if (redisTemplate.hasKey(key)) { + return (String) redisTemplate.opsForValue().get(key); + } + //获得接口地址 + String path = weixinMpApiProperties.getApiPath().get("token"); + //拼接url + StringBuilder url = new StringBuilder(path); + url.append("?appid=").append(auth.getAppId()).append("&secret=").append(auth.getAppSecret()).append("&grant_type=client_credential"); + //请求 + AccessToken result = externalRestTemplate.getForEntity(url.toString(), AccessToken.class).getBody(); + //验证 + WeixinMpConsont.checkResult(result); + //缓存(新增 & 更新) + final int num200 = 200; + int expiresIn = result.getExpires_in() - num200; + redisTemplate.opsForValue().set(key, result.getAccess_token(), expiresIn, TimeUnit.SECONDS); + //返回 + return result.getAccess_token(); + } + +} diff --git a/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/WeixinMpApiProperties.java b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/WeixinMpApiProperties.java index 1b3727e..b49a801 100644 --- a/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/WeixinMpApiProperties.java +++ b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/WeixinMpApiProperties.java @@ -25,4 +25,9 @@ public class WeixinMpApiProperties { */ private Map snsPath; + /** + * 接口地址 + */ + private Map apiPath; + } diff --git a/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/WeixinMpConsont.java b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/WeixinMpConsont.java index fdd3380..22fe93d 100644 --- a/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/WeixinMpConsont.java +++ b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/WeixinMpConsont.java @@ -25,6 +25,16 @@ public class WeixinMpConsont { } + /** + * 描述 : 构建参数 + * + * @param accessToken 令牌 + * @return 参数 + */ + public static String appendAccessToken(String accessToken) { + return "?access_token=" + accessToken; + } + /** *

* 检查返回值 diff --git a/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/domain/AccessToken.java b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/domain/AccessToken.java new file mode 100644 index 0000000..e7aae53 --- /dev/null +++ b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/domain/AccessToken.java @@ -0,0 +1,27 @@ +package org.itkk.udf.weixin.mp.api.domain; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * AccessToken + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class AccessToken extends BaseResult { + /** + * ID + */ + private static final long serialVersionUID = 1L; + + /** + * 凭证 + */ + private String access_token; //NOSONAR + + /** + * 凭证有效期 + */ + private Integer expires_in; //NOSONAR + +} diff --git a/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/domain/Menu.java b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/domain/Menu.java new file mode 100644 index 0000000..22b8966 --- /dev/null +++ b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/domain/Menu.java @@ -0,0 +1,59 @@ +package org.itkk.udf.weixin.mp.api.domain; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * Menu + */ +@Data +public class Menu implements Serializable { + + /** + * ID + */ + private static final long serialVersionUID = 1L; + + /** + * 二级菜单数组,个数应为1~5个 + */ + private List

sub_button; //NOSONAR + + /** + * 菜单的响应动作类型,view表示网页类型,click表示点击类型,miniprogram表示小程序类型 + */ + private String type; + + /** + * 菜单标题,不超过16个字节,子菜单不超过60个字节 + */ + private String name; + + /** + * 菜单KEY值,用于消息接口推送,不超过128字节(click等点击类型必须) + */ + private String key; + + /** + * 网页链接,用户点击菜单可打开链接,不超过1024字节(view、miniprogram类型必须) + */ + private String url; + + /** + * 调用新增永久素材接口返回的合法media_id(media_id类型和view_limited类型必须) + */ + private String media_id; //NOSONAR + + /** + * 小程序的appid(仅认证公众号可配置) (miniprogram类型必须) + */ + private String appid; + + /** + * 小程序的页面路径 (miniprogram类型必须) + */ + private String pagepath; + +} diff --git a/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/domain/MenuGroup.java b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/domain/MenuGroup.java new file mode 100644 index 0000000..33b43f9 --- /dev/null +++ b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/domain/MenuGroup.java @@ -0,0 +1,24 @@ +package org.itkk.udf.weixin.mp.api.domain; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * MenuGroup + */ +@Data +public class MenuGroup implements Serializable { + + /** + * ID + */ + private static final long serialVersionUID = 1L; + + /** + * 一级菜单数组,个数应为1~3个 + */ + private List button; + +} diff --git a/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/ShaOne.java b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/utils/ShaOne.java similarity index 97% rename from udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/ShaOne.java rename to udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/utils/ShaOne.java index 08f193b..5b809d7 100644 --- a/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/ShaOne.java +++ b/udf-starter-weixin-mp-api/src/main/java/org/itkk/udf/weixin/mp/api/utils/ShaOne.java @@ -4,7 +4,7 @@ * Created by Administrator * Copyright (C) 2016 LLSFW, All rights reserved. */ -package org.itkk.udf.weixin.mp.api; +package org.itkk.udf.weixin.mp.api.utils; import java.io.UnsupportedEncodingException; diff --git a/udf-starter-weixin-mp/src/main/java/org/itkk/udf/weixin/mp/service/WeixinMpCallbackService.java b/udf-starter-weixin-mp/src/main/java/org/itkk/udf/weixin/mp/service/WeixinMpCallbackService.java index 68d9ecc..9d949c2 100644 --- a/udf-starter-weixin-mp/src/main/java/org/itkk/udf/weixin/mp/service/WeixinMpCallbackService.java +++ b/udf-starter-weixin-mp/src/main/java/org/itkk/udf/weixin/mp/service/WeixinMpCallbackService.java @@ -6,6 +6,7 @@ import org.itkk.udf.amqp.rabbitmq.Rabbitmq; import org.itkk.udf.amqp.rabbitmq.RabbitmqMessage; import org.itkk.udf.weixin.mp.api.*; import org.itkk.udf.weixin.mp.api.meta.WeixinMpApiAuthMeta; +import org.itkk.udf.weixin.mp.api.utils.ShaOne; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service;