diff --git a/austin-common/src/main/java/com/java3y/austin/common/constant/SendAccountConstant.java b/austin-common/src/main/java/com/java3y/austin/common/constant/SendAccountConstant.java index 76c8bcc..38fd4d6 100644 --- a/austin-common/src/main/java/com/java3y/austin/common/constant/SendAccountConstant.java +++ b/austin-common/src/main/java/com/java3y/austin/common/constant/SendAccountConstant.java @@ -45,6 +45,12 @@ public class SendAccountConstant { public static final String WECHAT_OFFICIAL_ACCOUNT_KEY = "officialAccount"; public static final String WECHAT_OFFICIAL__PREFIX = "official_"; + /** + * 微信小程序 应用消息 账号 + */ + public static final String WECHAT_MINI_PROGRAM_ACCOUNT_KEY = "miniProgramAccount"; + public static final String WECHAT_MINI_PROGRAM_PREFIX = "mini_program_"; + /** * 短信 账号 */ diff --git a/austin-common/src/main/java/com/java3y/austin/common/dto/account/WeChatMiniProgramAccount.java b/austin-common/src/main/java/com/java3y/austin/common/dto/account/WeChatMiniProgramAccount.java new file mode 100644 index 0000000..1e8d4e5 --- /dev/null +++ b/austin-common/src/main/java/com/java3y/austin/common/dto/account/WeChatMiniProgramAccount.java @@ -0,0 +1,44 @@ +package com.java3y.austin.common.dto.account; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * + * 小程序订阅消息参数 + *

+ * 参数示例: + * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html + * * @author sunql + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class WeChatMiniProgramAccount { + + /** + * 订阅消息模板ID + */ + private String templateId; + + /** + * 跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版 + */ + private String miniProgramState; + + /** + * 击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。 + */ + private String page; + + /** + * 账号相关 + */ + private String appId; + private String appSecret; + private String grantType; + +} diff --git a/austin-common/src/main/java/com/java3y/austin/common/dto/model/MiniProgramContentModel.java b/austin-common/src/main/java/com/java3y/austin/common/dto/model/MiniProgramContentModel.java index 4601781..5e15ed3 100644 --- a/austin-common/src/main/java/com/java3y/austin/common/dto/model/MiniProgramContentModel.java +++ b/austin-common/src/main/java/com/java3y/austin/common/dto/model/MiniProgramContentModel.java @@ -1,8 +1,22 @@ package com.java3y.austin.common.dto.model; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Map; + /** * @author 3y */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor public class MiniProgramContentModel extends ContentModel { - + /** + * 模板消息发送的数据 + */ + Map map; } diff --git a/austin-handler/pom.xml b/austin-handler/pom.xml index 6fdac1a..7f542c6 100644 --- a/austin-handler/pom.xml +++ b/austin-handler/pom.xml @@ -46,6 +46,11 @@ com.github.binarywang weixin-java-mp + + + com.github.binarywang + weixin-java-miniapp + @@ -54,4 +59,4 @@ - \ No newline at end of file + diff --git a/austin-handler/src/main/java/com/java3y/austin/handler/domain/wechat/WeChatMiniProgramParam.java b/austin-handler/src/main/java/com/java3y/austin/handler/domain/wechat/WeChatMiniProgramParam.java new file mode 100644 index 0000000..54bab4f --- /dev/null +++ b/austin-handler/src/main/java/com/java3y/austin/handler/domain/wechat/WeChatMiniProgramParam.java @@ -0,0 +1,38 @@ +package com.java3y.austin.handler.domain.wechat; + +import lombok.Builder; +import lombok.Data; + +import java.util.Map; +import java.util.Set; + +/** + * @author sunql + * @date 2022年05月06日 15:56 + * + * 小程序参数 + */ +@Data +@Builder +public class WeChatMiniProgramParam { + /** + * 业务Id + */ + private Long messageTemplateId; + + /** + * 发送账号 + */ + private Integer sendAccount; + + /** + * 接收者(用户)的 openid + */ + private Set openIds; + + /** + * 模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } } + */ + private Map data; + +} diff --git a/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/MiniProgramAccountHandler.java b/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/MiniProgramAccountHandler.java new file mode 100644 index 0000000..013fd15 --- /dev/null +++ b/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/MiniProgramAccountHandler.java @@ -0,0 +1,67 @@ +package com.java3y.austin.handler.handler.impl; + +import com.alibaba.fastjson.JSON; +import com.google.common.base.Throwables; +import com.java3y.austin.common.domain.TaskInfo; +import com.java3y.austin.common.dto.model.MiniProgramContentModel; +import com.java3y.austin.common.dto.model.OfficialAccountsContentModel; +import com.java3y.austin.common.enums.ChannelType; +import com.java3y.austin.handler.domain.wechat.WeChatMiniProgramParam; +import com.java3y.austin.handler.domain.wechat.WeChatOfficialParam; +import com.java3y.austin.handler.handler.BaseHandler; +import com.java3y.austin.handler.handler.Handler; +import com.java3y.austin.handler.script.MiniProgramAccountService; +import com.java3y.austin.handler.script.OfficialAccountService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author sunql + * 微信小程序发送订阅消息 + */ +@Component +@Slf4j +public class MiniProgramAccountHandler extends BaseHandler implements Handler { + + @Autowired + private MiniProgramAccountService miniProgramAccountService; + + public MiniProgramAccountHandler() { + channelCode = ChannelType.MINI_PROGRAM.getCode(); + } + + @Override + public boolean handler(TaskInfo taskInfo) { + WeChatMiniProgramParam miniProgramParam = buildMiniProgramParam(taskInfo); + try { + miniProgramAccountService.send(miniProgramParam); + } catch (Exception e) { + log.error("MiniProgramAccountHandler#handler fail:{},params:{}", + Throwables.getStackTraceAsString(e), JSON.toJSONString(taskInfo)); + return false; + } + return true; + } + + /** + * 通过taskInfo构建小程序订阅消息 + * + * @param taskInfo + * @return + */ + private WeChatMiniProgramParam buildMiniProgramParam(TaskInfo taskInfo) { + // 小程序订阅消息可以关联到系统业务,通过接口查询。 + WeChatMiniProgramParam miniProgramParam = WeChatMiniProgramParam.builder() + .openIds(taskInfo.getReceiver()) + .messageTemplateId(taskInfo.getMessageTemplateId()) + .sendAccount(taskInfo.getSendAccount()) + .build(); + + MiniProgramContentModel contentModel = (MiniProgramContentModel) taskInfo.getContentModel(); + miniProgramParam.setData(contentModel.getMap()); + return miniProgramParam; + } + +} + diff --git a/austin-handler/src/main/java/com/java3y/austin/handler/script/MiniProgramAccountService.java b/austin-handler/src/main/java/com/java3y/austin/handler/script/MiniProgramAccountService.java new file mode 100644 index 0000000..7a4b6da --- /dev/null +++ b/austin-handler/src/main/java/com/java3y/austin/handler/script/MiniProgramAccountService.java @@ -0,0 +1,19 @@ +package com.java3y.austin.handler.script; + +import com.java3y.austin.handler.domain.wechat.WeChatMiniProgramParam; + +/** + * @author sunql + */ +public interface MiniProgramAccountService { + + /** + * 发送订阅消息 + * + * @param miniProgramParam 订阅消息参数 + * @return + * @throws Exception + */ + void send(WeChatMiniProgramParam miniProgramParam) throws Exception; + +} diff --git a/austin-handler/src/main/java/com/java3y/austin/handler/script/impl/MiniProgramAccountServiceImpl.java b/austin-handler/src/main/java/com/java3y/austin/handler/script/impl/MiniProgramAccountServiceImpl.java new file mode 100644 index 0000000..c6019bd --- /dev/null +++ b/austin-handler/src/main/java/com/java3y/austin/handler/script/impl/MiniProgramAccountServiceImpl.java @@ -0,0 +1,93 @@ +package com.java3y.austin.handler.script.impl; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.api.WxMaSubscribeService; +import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl; +import cn.binarywang.wx.miniapp.api.impl.WxMaSubscribeServiceImpl; +import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage; +import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl; +import com.java3y.austin.common.constant.SendAccountConstant; +import com.java3y.austin.common.dto.account.WeChatMiniProgramAccount; +import com.java3y.austin.handler.domain.wechat.WeChatMiniProgramParam; +import com.java3y.austin.handler.script.MiniProgramAccountService; +import com.java3y.austin.support.utils.AccountUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author sunql + * @date 2022年05月06日 16:41 + */ +@Service +@Slf4j +public class MiniProgramAccountServiceImpl implements MiniProgramAccountService { + + @Autowired + private AccountUtils accountUtils; + + @Override + public void send(WeChatMiniProgramParam miniProgramParam) throws Exception { + WeChatMiniProgramAccount miniProgramAccount = accountUtils.getAccount(miniProgramParam.getSendAccount(), + SendAccountConstant.WECHAT_MINI_PROGRAM_ACCOUNT_KEY, + SendAccountConstant.WECHAT_MINI_PROGRAM_PREFIX, + WeChatMiniProgramAccount.builder().build()); + + WxMaSubscribeService wxMaSubscribeService = initService(miniProgramAccount); + List subscribeMessageList = assembleReq(miniProgramParam, miniProgramAccount); + for (WxMaSubscribeMessage subscribeMessage : subscribeMessageList) { + wxMaSubscribeService.sendSubscribeMsg(subscribeMessage); + } + } + + /** + * 组装发送模板信息参数 + */ + private List assembleReq(WeChatMiniProgramParam miniProgramParam, WeChatMiniProgramAccount miniProgramAccount) { + Set receiver = miniProgramParam.getOpenIds(); + List messageList = new ArrayList<>(receiver.size()); + + // 构建微信小程序订阅消息 + for (String openId : receiver) { + WxMaSubscribeMessage subscribeMessage = WxMaSubscribeMessage.builder() + .toUser(openId) + .data(getWxMTemplateData(miniProgramParam.getData())) + .miniprogramState(miniProgramAccount.getMiniProgramState()) + .templateId(miniProgramAccount.getTemplateId()) + .page(miniProgramAccount.getPage()) + .build(); + messageList.add(subscribeMessage); + } + return messageList; + } + + /** + * 构建订阅消息参数 + * + * @returnp + */ + private List getWxMTemplateData(Map data) { + List templateDataList = new ArrayList<>(data.size()); + data.forEach((k, v) -> templateDataList.add(new WxMaSubscribeMessage.MsgData(k, v))); + return templateDataList; + } + + /** + * 初始化微信小程序 + * + * @return + */ + private WxMaSubscribeServiceImpl initService(WeChatMiniProgramAccount miniProgramAccount) { + WxMaService wxMaService = new WxMaServiceImpl(); + WxMaDefaultConfigImpl wxMaConfig = new WxMaDefaultConfigImpl(); + wxMaConfig.setAppid(miniProgramAccount.getAppId()); + wxMaConfig.setSecret(miniProgramAccount.getAppSecret()); + wxMaService.setWxMaConfig(wxMaConfig); + return new WxMaSubscribeServiceImpl(wxMaService); + } +} diff --git a/austin-support/src/main/java/com/java3y/austin/support/utils/AccountUtils.java b/austin-support/src/main/java/com/java3y/austin/support/utils/AccountUtils.java index 77a4fc8..fd612a2 100644 --- a/austin-support/src/main/java/com/java3y/austin/support/utils/AccountUtils.java +++ b/austin-support/src/main/java/com/java3y/austin/support/utils/AccountUtils.java @@ -27,6 +27,7 @@ public class AccountUtils { * (key:dingDingRobotAccount) 钉钉自定义机器人参数示例:[{"ding_ding_robot_10":{"secret":"SEC996d8d9d4768aded74114faae924f229229de444475a1c295d64fedf","webhook":"https://oapi.dingtalk.com/robot/send?access_token=8d03b644ffb6534b203d87333367328b0c3003d164715d2c6c6e56"}}] * (key:dingDingWorkNoticeAccount) 钉钉工作消息参数示例:[{"ding_ding_work_notice_10":{"appKey":"dingh6yyyyyyycrlbx","appSecret":"tQpvmkR863333yyyyyHP3QHyyyymy9Ao1yoL1oQX5Nlx_fYLLLlpPJWHvWKbTu","agentId":"152333383622"}}] * (key:officialAccount) 微信服务号模板消息参数示例:[{"official_10":{"appId":"wxecb4693d2eef1ea7","secret":"6240870f4d91701640d769ba20120821","templateId":"JHUk6eE9T5Ts7a5JO3ZQqkBBrZBGn5C9iIiKNDQsk-Q","url":"http://weixin.qq.com/download","miniProgramId":"xiaochengxuappid12345","path":"index?foo=bar"}}] + * (key:miniProgramAccount) 微信服务号模板消息参数示例:[{"mini_program_10":{"appId":"wxecb4693d2eef1ea7","appSecret":"6240870f4d91701640d769ba20120821","templateId":"JHUk6eE9T5Ts7a5JO3ZQqkBBrZBGn5C9iIiKNDQsk-Q","grantType":"client_credential","miniProgramState":"trial","page":"index?foo=bar"}}] */ public T getAccount(Integer sendAccount, String apolloKey, String prefix, T t) { String accountValues = config.getProperty(apolloKey, AustinConstant.APOLLO_DEFAULT_VALUE_JSON_ARRAY); diff --git a/austin-web/src/main/resources/application.properties b/austin-web/src/main/resources/application.properties index 20c1b3c..28bc18d 100644 --- a/austin-web/src/main/resources/application.properties +++ b/austin-web/src/main/resources/application.properties @@ -87,10 +87,3 @@ management.endpoint.metrics.enabled=true management.endpoint.prometheus.enabled=true management.endpoints.web.exposure.include=* management.metrics.export.prometheus.enabled=true - -##################### wx mp config ##################### -##################### TODO not test by 3y,wait to apply for OfficialAccount ##################### -wx.mp.account.appid="appid" -wx.mp.account.secret="secret" -wx.mp.account.token="token" -wx.mp.account.aesKey="aesKey" \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6388c08..68c2ffa 100644 --- a/pom.xml +++ b/pom.xml @@ -160,6 +160,13 @@ ${weixin-java} + + + com.github.binarywang + weixin-java-miniapp + ${weixin-java} + + io.github.lyh200