java多渠道消息推送-(微信公众号、钉钉、邮箱、系统内部、短信等)

1. 消息对象定义

1.1  通用消息对象定义

package com.yj.notice.message;
import com.yj.commons.tools.utils.DateUtils;
import com.yj.commons.tools.utils.StringUtil;
import com.yj.notice.costant.NoticeMethodEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;/**
 * @author : dyg
 * @className : SmsMessageDTO
 * @description : SMS短信平台 实体类
 * @date : 2023/8/30 10:35
 */
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class NoticeMessage implements Serializable {
    private static final long serialVersionUID = 5081758462088563857L;
 /**
 * 消息类型
   **/
private String messageType;
/** * 通知消息类型 */ protected NoticeMethodEnum noticeMethod; /** * 接收者-手机号码 */ protected String receiverPhone; protected String receiverId; /** * 接收者-用户名 */ protected String receiverUserName; /** * 消息内容 */ protected String content; /** * 消息内容 */ protected String title; /** * 消息时间 */ protected String time; /** * 发送结果 */ protected String result; /** * 错误信息 */ protected String error; public String wrapperMessage() { StringBuilder sub = new StringBuilder(); String time = StringUtil.isEmpty(this.getTime()) ? format(new Date(),"yyyy-MM-dd HH:mm:ss") : this.getTime(); sub.append("消息标题: ").append(this.getTitle()).append("\n" ) .append("消息内容: ").append(this.getContent()).append("\n") .append("消息时间: ").append(time).append("\n" ); return sub.toString(); }

  public static String format(Date date, String pattern) {
  if (date != null) {
   SimpleDateFormat df = new SimpleDateFormat(pattern);
   return df.format(date);
  }
   return null;
  }
}

1.2  告警消息对象定义

package com.yj.notice.message;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;

/**
 * @author : dyg
 * @className : AlarmMessage
 * @description : 告警信息
 * @date : 2023/9/5 11:19
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AlarmMessage extends NoticeMessage implements Serializable  {
    private static final long serialVersionUID = -8390792683552907827L;
    /**
     * 告警级别
     */
    protected String level;
    /**
     * 告警类型
     */
    protected String type;
    /**
     * 告警备注
     */
    protected String remark;

    public String wrapperMessage() {
        if(StringUtil.isEmpty(this.getTime()) && StringUtil.isEmpty(this.getLevel()) && StringUtil.isEmpty(this.getType())&& StringUtil.isEmpty(this.getRemark())) {
            return this.getContent();
        }
        StringBuilder sub = new StringBuilder();
        sub.append("告警时间:  ").append(this.getTime()).append("\n")
                .append("告警级别: ").append(this.getLevel()).append("\n")
                .append("告警类别: ").append(this.getType()).append("\n")
                .append("告警消息: ").append(this.getContent()).append("\n")
                .append("备注信息: ").append(this.getRemark());
        return sub.toString();
    }
}

1.3  邮件消息对象定义

package com.yj.notice.message;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.File;
import java.io.Serializable;
/**
 * @author : dyg
 * @className : MailMessage
 * @description : 描述说明该类的功能
 * @date : 2023/9/5 14:33
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MailMessage  extends AlarmMessage implements Serializable {
    private static final long serialVersionUID = 4370431527898082801L;
    /**
     * 附件
     */
    private File attachFile;
    /**
     * html内容
     */
    private String html;
}

1.4  消息发送类型枚举定义

package com.yj.notice.costant;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 通知方式
 *
 * @author changXT
 * @date 2022-8-10
 **/
@AllArgsConstructor
@Getter
public enum NoticeMethodEnum {
    WECHAT("微信", "WECHAT"),
    EMAIL("邮件", "EMAIL"),
    TENCENT_SMS("腾讯短信", "TENCENT_SMS"),
    IN_MSG("站内消息", "IN_MSG"),
    DINGTALK("钉钉", "DINGTALK");
    private String cnName;
    private String name;
public static NoticeMethodEnum getEnum(String name) { for (NoticeMethodEnum noticeMethodEnum : NoticeMethodEnum.values()) { if (name.equals(noticeMethodEnum.name())) { return noticeMethodEnum; } } return null; } }

2. 消息发送接口定义

2.1  消息发送接口定义

package com.yj.notice.service;

import com.yj.notice.MessageSenderManager;
import com.yj.notice.message.NoticeMessage;
import org.springframework.beans.factory.InitializingBean;

/**
 * @author : dyg
 * @className : MessageService
 * @description : 消息发送
 * @date : 2023/8/30 10:34
 */
public interface MessageService<T extends NoticeMessage>  extends InitializingBean {
    /**
     * 发送消息
     * @param message
     * @return
     */
    String send(NoticeMessage message);

    /**
     * 获取发送方法
     *
     * @return 发送方法
     */
    String getNoticeMethod();

    @Override
    default void afterPropertiesSet() {
        MessageSenderManager.registrySender(getNoticeMethod(), this);
    }
}

2.2  消息发送收集器定义

package com.yj.notice;
import com.yj.notice.message.NoticeMessage;
import com.yj.notice.costant.NoticeMethodEnum;
import com.yj.notice.service.MessageService;
import org.springframework.stereotype.Component;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 消息发送者管理器
 *
 * @author donglanlan
 * @date 2021/7/22 2:33 下午
 **/
@Component
public class MessageSenderManager {
    private static final ConcurrentHashMap<String, MessageService<? extends NoticeMessage>> SENDER_MAP =
            new ConcurrentHashMap<>();

    public static void registrySender(String sendMethod, MessageService<? extends NoticeMessage> messageSender) {
        SENDER_MAP.put(sendMethod, messageSender);
    }

    public  MessageService getMessageSender(NoticeMessage messsage) {
        if (messsage.getNoticeMethod() == null) {
            throw new RuntimeException("没有指定消息的发送方式!");
        }
        return getMessageSender(messsage.getNoticeMethod());
    }

    public  MessageService getMessageSender(NoticeMethodEnum methodEnum) {
        return SENDER_MAP.get(methodEnum.getName());
    }
}

3. 微信公众号消息发送实现类

3.1 实现类定义

package com.yj.notice.service.impl;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.yj.commons.tools.utils.DateUtils;
import com.yj.commons.tools.utils.JsonUtil;
import com.yj.commons.tools.utils.StringUtil;
import com.yj.notice.message.NoticeMessage;
import com.yj.notice.costant.NoticeMethodEnum;
import com.yj.notice.message.AlarmMessage;
import com.yj.notice.service.MessageService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.*;

import static com.yj.commons.tools.utils.DateUtils.DATE_TIME_PATTERN;

/**
 * @author : dyg
 * @className : WxMessageServiceImpl
 * @description : 描述说明该类的功能
 * @date : 2023/9/5 9:35
 */
@Service("WechatMessageService")
@Slf4j
@Data
public class WechatMessageServiceImpl implements MessageService {
    /**
     * 账号app_id
     */
    @Value(value = "${notice.wechat.bk_app_id}")
    private String bkAppKey;
    /**
     * 账户密钥
     */
    @Value(value = "${notice.wechat.bk_app_secret}")
    private String bkAppSecret;
    /**
     * 告警消息模板id
     */
    @Value(value = "${notice.wechat.alarm_template_id}")
    private String alarmTemplateId;
    /**
     * 普通消息模板id
     */
    @Value(value = "${notice.wechat.common_template_id}")
    private String commonTemplateId;
    /**
     * 获取token
     * "+ appId +"&secret=" + appIdSecret
     */
    @Value(value = "${notice.wechat.token_uri}")
    private String tokenUri;
    /**
     * + accessToken;
     */
    @Value(value = "${notice.wechat.user_list_uri}")
    private String userListUri;
    /**
     * + accessToken;
     */
    @Value(value = "${notice.wechat.send_message_uri}")
    private String sendMessageUri;

    @Autowired
    RestTemplate restTemplate;

    /**
     * 用户token
     */
    private String enterpriseToken = null;
    private Long tokenFreshTimeSt = 0L;

    @Override
    public String send(NoticeMessage message) {
        String result = null;
        try {
            result = this.sendMessage(message);
        }catch (Exception e){
            log.error(e.getMessage());
            result = e.getMessage()+ " " + e;
        }
        if (com.yj.cmp.commons.util.StringUtil.isNotEmpty(result)) {
            log.error(result);
        } else {
            result = "发送成功";
        }
        return result;
    }

    @Override
    public String getNoticeMethod() {
        return NoticeMethodEnum.WECHAT.getName();
    }

    /**
     * 获取或者刷新token
     */
    private void getOrRefreshToken() {
        try {
            String requestUrl = this.tokenUri + this.bkAppKey +"&secret=" + this.bkAppSecret;
            String res = HttpUtil.get(requestUrl);
            JSONObject jsonObject = JSONObject.parseObject(res);
            String accessToken = jsonObject.getString("access_token");
            this.enterpriseToken = accessToken;
            this.tokenFreshTimeSt = System.currentTimeMillis()/1000;
        } catch (Exception e) {
            log.error("---获取token出现异常{} {} ",e.getMessage(),e);
        }
    }

    /**
     * 获取用户列表openid
     */
    public void getUserList(){
        RestTemplate restTemplate = new RestTemplate();
        String requestUrl = this.userListUri+ this.enterpriseToken;
        ResponseEntity<String> response = restTemplate.postForEntity(requestUrl, null, String.class);
        log.info("结果是: {}",response.getBody());
        com.alibaba.fastjson.JSONObject result = com.alibaba.fastjson.JSONObject.parseObject(response.getBody());
        com.alibaba.fastjson.JSONArray openIdJsonArray = result.getJSONObject("data").getJSONArray("openid");
        Iterator iterator = openIdJsonArray.iterator();
        if (iterator.hasNext()){
            log.debug("用户openid:"+iterator.next());
        }
    }

    @Data
    public class WeChatTemplateMsg {
        /**
         * 消息
         */
        private String value;
        /**
         * 消息颜色
         */
        private String color;

        public WeChatTemplateMsg(String value) {
            this.value = value;
            this.color = "#173177";
        }

        public WeChatTemplateMsg(String value, String color) {
            this.value = value;
            this.color = color;
        }
    }

    /**
     * 获取用户id
     * @param alarmMessage
     * @return
     */
    private JSONObject getWechatUserId(NoticeMessage alarmMessage){
        JSONObject result = new JSONObject();
        String openId = alarmMessage.getReceiverId();
        if(StringUtil.isEmpty(openId)){
            // todo 根据手机号码获取微信id --对应数据估计得手动维护
            String receiverPhone = alarmMessage.getReceiverPhone();
            if(StringUtil.isEmpty(receiverPhone)){
                result.put("message","消息接收者手机号码+微信id都为空,消息无法发送");
            }
            openId = getWechatUserId(receiverPhone);
        }
        result.put("userId",openId);
        return result;
    }

    /**
     * 发送消息
     * @param noticeMessage
     * @return
     */
    public String sendMessage(NoticeMessage noticeMessage){
        String result = null;
        // 模板参数
        Map<String, WeChatTemplateMsg> sendMag = new HashMap<String, WeChatTemplateMsg>();
        // openId代表一个唯一微信用户,即微信消息的接收人
        JSONObject wechatUserId = getWechatUserId(noticeMessage);
        String openId = null;
        if(wechatUserId.containsKey("message")){
            String message = wechatUserId.getString("message");
            log.error(message);
            return message;
        }else{
            Object userId = wechatUserId.get("userId");
            if(Objects.isNull(userId)){
                String message = "未能根据手机号码"+noticeMessage.getReceiverPhone()+"成功获取用户的微信id";
                return message;
            }
            openId = wechatUserId.getString("userId");
        }
        // 公众号的模板id(也有相应的接口可以查询到)
        validateToken();
        String requestUrl = this.sendMessageUri + this.enterpriseToken;
        //拼接base参数
        Map<String, Object> sendBody = new HashMap<>();
        sendBody.put("touser", openId);
        sendBody.put("data", sendMag);

        if(noticeMessage instanceof AlarmMessage){
            AlarmMessage alarmMessage = (AlarmMessage)noticeMessage;
            sendMag.put("message", new WeChatTemplateMsg(alarmMessage.getContent()));
            sendMag.put("time",new WeChatTemplateMsg(alarmMessage.getTime()));
            sendMag.put("level",new WeChatTemplateMsg(alarmMessage.getLevel(),"#FF69B4" ));
            sendMag.put("type",new WeChatTemplateMsg(alarmMessage.getType() ,"#173177"));
            sendMag.put("remark",new WeChatTemplateMsg(alarmMessage.getRemark(),"#173177"));
            sendBody.put("template_id", this.alarmTemplateId);
        }else{
            sendMag.put("content", new WeChatTemplateMsg(noticeMessage.getContent()));
            sendMag.put("title",new WeChatTemplateMsg(noticeMessage.getTitle()));
            String time = StringUtil.isEmpty(noticeMessage.getTime()) ? DateUtils.format(new Date(),DATE_TIME_PATTERN) : noticeMessage.getTime();
            sendMag.put("time",new WeChatTemplateMsg(time,"#FF69B4"));
            sendBody.put("template_id", this.commonTemplateId);
        }

        try {
            // 1.创建httpclient对象
            CloseableHttpClient client = HttpClients.createDefault();
            // 2.创建post对象
            HttpPost post = new HttpPost(requestUrl);
            StringEntity postingString = new StringEntity(JsonUtil.entityToString(sendBody), "utf-8");
            post.setEntity(postingString);
            // 3.执行post方法:得到结果
            CloseableHttpResponse response = client.execute(post);
            // 4.处理结果
            //  1.得到状态码
            int statusCode = response.getStatusLine().getStatusCode();
            log.info("----http code : {}", statusCode);
            if (statusCode == 200) {
                //  2.得到实体内容
                org.apache.http.HttpEntity entity = response.getEntity();
                String content = EntityUtils.toString(entity, "utf-8");
                JSONObject jsonObject = JsonUtil.StringToEntity(content, JSONObject.class);
                String messageCode = jsonObject.getString("errcode");
                String msgId = jsonObject.getString("msgid");
                result = "messageCode : " + messageCode + ", msgId: " +msgId;
            }
            //  5.关闭连接
            client.close();
        } catch (IOException e) {
            log.error("------exception : {} {} ",e.getMessage(),e);
        }
        return result;
    }

    /**
     * 根据手机号码获取用户id
     * @param receiverPhone
     * @return
     */
    private String getWechatUserId(String receiverPhone) {
        String userId = null;
        return userId;
    }

    /**
     * 验证并刷新token
     */
    private void validateToken() {
        if (com.yj.cmp.commons.util.StringUtil.isEmpty(this.enterpriseToken)) {
            this.getOrRefreshToken();
        }
        Long now = System.currentTimeMillis()/1000;
        if(this.tokenFreshTimeSt == 0L){
            this.getOrRefreshToken();
        }else{
            Long diff = (now - tokenFreshTimeSt)/60;
            if(diff > 600){
                // 超过十分钟重新获取一下
                this.getOrRefreshToken();
            }
        }
    }
}

3.2 配置参数

# 消息推送相关
notice:
  # 微信消息相关
  wechat:
    bk_app_id: xxx
    bk_app_secret: xxx
    alarm_template_id: xxx
    common_template_id: xxxxxh
    token_uri: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=
    user_list_uri: https://api.weixin.qq.com/cgi-bin/user/get?access_token=
    send_message_uri: https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=

3.3 消息模板

 

4. 钉钉群消息发送实现类

4.1 引入依赖

   <!-- 钉钉对接机器人 -->
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>dingtalk</artifactId>
            <version>1.5.24</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>alibaba-dingtalk-service-sdk</artifactId>
            <version>2.0.0</version>
        </dependency>

  

4.2 实现类定义

package com.yj.notice.service.impl;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.yj.cmp.commons.util.StringUtil;
import com.yj.commons.tools.utils.JsonUtil;
import com.yj.notice.message.AlarmMessage;
import com.yj.notice.message.NoticeMessage;
import com.yj.notice.costant.NoticeMethodEnum;
import com.yj.notice.service.MessageService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.aliyun.dingtalkrobot_1_0.Client;
import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTOHeaders;
import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTORequest;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.Common;
import com.aliyun.teautil.models.RuntimeOptions;
import com.dingtalk.api.request.OapiV2UserGetbymobileRequest;
import com.dingtalk.api.response.OapiV2UserGetbymobileResponse;
import java.util.Arrays;
import java.util.Map;

/**
 * @author : dyg
 * @className : DingMessageServiceImpl
 * @description : 钉钉消息发送
 * @date : 2023/9/4 17:14
 */
@Service("DingTalkMessageService")
@Slf4j
@Data
public class DingTalkMessageServiceImpl implements MessageService {

    @Value(value = "${notice.dingtalk.token_url}")
    private String tokenUrl;

    @Value(value = "${notice.dingtalk.get_user_by_phone_url}")
    private String getUserByPhoneUrl;

    @Value(value = "${notice.dingtalk.bk_app_key}")
    private String bkAppKey;

    @Value(value = "${notice.dingtalk.bk_app_secret}")
    private String bkAppSecret;

    /**
     * token 数据
     */
    private String enterpriseToken = "";

    /**
     * 获取/刷新token时间戳
     */
    private Long tokenFreshTimeSt = 0L;

    @Override
    public String send(NoticeMessage message) {
        String result = null;
        try {
            String receiverId = message.getReceiverId();
            if (StringUtil.isNotEmpty(receiverId)) {
                // 用户id不为空根据id发送
                result = this.sendDingTalkNotify(receiverId, message);
            } else {
                // 否则根据手机号码查询用户
                String receiverPhone = message.getReceiverPhone();
                if (StringUtil.isNotEmpty(receiverPhone)) {
                    receiverId = this.getDingdingUserIdByPhone(receiverPhone);
                    if (StringUtil.isNotEmpty(receiverId)) {
                        result = this.sendDingTalkNotify(receiverId, message);
                    } else {
                        result = "根据接收者用户手机号码获取的用户id都为空,无法完成消息发送需求";
                    }
                } else {
                    result = "接收者用户id和手机号码都为空,无法完成消息发送需求";
                }
            }
        }catch (Exception e){
            log.error(e.getMessage());
            result = e.getMessage()+ " " + e;
        }
        if (StringUtil.isNotEmpty(result)) {
            log.error(result);
        } else {
            result = "发送成功";
        }
        return result;
    }

    @Override
    public String getNoticeMethod() {
        return NoticeMethodEnum.DINGTALK.getName();
    }

    /**
     * 使用 Token 初始化账号Client
     *
     * @return Client
     * @throws Exception
     */
    private  Client createClient() throws Exception {
        Config config = new Config();
        config.protocol = "https";
        config.regionId = "central";
        return new Client(config);
    }

    /**
     * 获取token,每两小时失效
     */
    private void getOrRefreshToken() {
        try {
            DingTalkClient client = new DefaultDingTalkClient(this.tokenUrl);
            OapiGettokenRequest req = new OapiGettokenRequest();
            req.setAppkey(this.bkAppKey);
            req.setAppsecret(this.bkAppSecret);
            req.setHttpMethod("GET");
            OapiGettokenResponse rsp = client.execute(req);
            log.info("token:" + rsp.getBody());
            Map json = JsonUtil.StringToEntity(rsp.getBody(), Map.class);
            this.enterpriseToken = json.get("access_token").toString();
            this.tokenFreshTimeSt = System.currentTimeMillis()/1000;
        } catch (Exception e) {
            log.error("---获取token出现异常{} {} ",e.getMessage(),e);
        }
    }

    /**
     * 根据手机号码获取钉钉用户id
     * -- 备注: 必须将用户拉入组织/群中之后才可以根据手机号码获取用户
     * @param phone 用户手机号
     * @return void
     */
    private String getDingdingUserIdByPhone(String phone) {
        try {
            if (StringUtil.isEmpty(this.enterpriseToken)) {
                this.getOrRefreshToken();
            }
            DingTalkClient client = new DefaultDingTalkClient(getUserByPhoneUrl);
            OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();
            req.setMobile(phone);
            OapiV2UserGetbymobileResponse rsp = client.execute(req, this.enterpriseToken);
            if (rsp != null) {
                OapiV2UserGetbymobileResponse.UserGetByMobileResponse result = rsp.getResult();
                return result == null ? null : result.getUserid();
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 发送钉钉消息
     * @param dingUserId 钉钉用户id
     * @param message    发送消息
     * @return void
     */
    public String  sendDingTalkNotify(String dingUserId, NoticeMessage message) throws Exception {
        String result = null;
        validateToken();

        Client client = createClient();
        BatchSendOTOHeaders batchSendOTOHeaders = new BatchSendOTOHeaders();
        batchSendOTOHeaders.xAcsDingtalkAccessToken = this.enterpriseToken;
        String content = null;
        if(message instanceof AlarmMessage){
            AlarmMessage alarmMessage = (AlarmMessage)message;
            content = alarmMessage.wrapperMessage();
        }else{
            content = message.wrapperMessage();
        }
        String finalContent = "{\"content\": \"" + content + "\"}";
        BatchSendOTORequest batchSendOTORequest = new BatchSendOTORequest()
                .setRobotCode(this.bkAppKey)//机器人appkey
                .setUserIds(Arrays.asList(dingUserId))
                .setMsgKey("officialTextMsg")
                .setMsgParam(finalContent);
        try {
            client.batchSendOTOWithOptions(batchSendOTORequest, batchSendOTOHeaders, new RuntimeOptions());
        } catch (TeaException err) {
            if (!Common.empty(err.code) && !Common.empty(err.message))
                // err 中含有 code 和 message 属性,可帮助开发定位问题
                log.error(err.code + ":" + err.message);
        } catch (Exception e) {
            TeaException err = new TeaException(e.getMessage(), e);
            if (!Common.empty(err.code) && !Common.empty(err.message))
                // err中含有code和message 属性,可帮助开发定位问题
                log.error(err.code + ":" + err.message);
            result = err.code + ":" + err.message;
        }
        return result;
    }

    /**
     * 验证并刷新token
     */
    private void validateToken() {
        if (StringUtil.isEmpty(this.enterpriseToken)) {
            this.getOrRefreshToken();
        }
        Long now = System.currentTimeMillis()/1000;
        if(this.tokenFreshTimeSt == 0L){
            this.getOrRefreshToken();
        }else{
            Long diff = (now - tokenFreshTimeSt)/60;
            if(diff > 600){
                // 超过十分钟重新获取一下
                this.getOrRefreshToken();
            }
        }
    }
}

4.3 配置参数

# 消息推送相关
notice:
  # 钉钉消息相关
  dingtalk:
    bk_app_key: xxx
    bk_app_secret: xxxx
    token_url: https://oapi.dingtalk.com/gettoken
    get_user_by_phone_url: https://oapi.dingtalk.com/topapi/v2/user/getbymobile

4.4  创建应用获取appKey+appSecret

1. 使用钉钉账户作为管理员创建一个组织/群

 

2. 登录钉钉后台管理页面,工作台--->应用管理--->创建应用(委托服务商开发), 创建一个H5微应用

 

3. 登录钉钉后台管理页面,工作台--->应用管理--->点击应用, 查看 凭证与基础信息 获取配置文件中所需要的appKey/appSecret

4. 为当前应用创建机器人,工作台--->应用管理--->点击应用-->添加应用能力--->机器人添加

 

5. 为应用申请相应的权限,例如根据手机号码获取用户,企业内机器人发送消息权限

6. 将当前应用发布 ,当添加完毕机器人+权限之后,当前应用显示 开发中,如下图所示,需要在版本与管理中创建一个发布版本(只有发布成功之后才可以使用)

 

7. 将需要接收消息的钉钉用户拉入群组

5. 邮件发送实现类

5.1  引入依赖

 <!--对接邮件发送-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

5.2  定义实现类import com.yj.commons.tools.utils.JsonUtil;

import com.yj.commons.tools.utils.StringUtil;
import com.yj.notice.message.MailMessage;
import com.yj.notice.message.NoticeMessage;
import com.yj.notice.costant.NoticeMethodEnum;
import com.yj.notice.service.MessageService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import javax.mail.internet.MimeMessage;
import java.io.File;

/**
 * @author : dyg
 * @className : MailMessageServiceImpl
 * @description : 邮件发送器
 * @date : 2023/9/5 14:31
 */
@Service("MailMessageService")
@Slf4j
@Data
public class MailMessageServiceImpl  implements MessageService {
    @Value("${spring.mail.username}")
    private String from;

    @Autowired
    private JavaMailSender mailSender;

    @Override
    public String getNoticeMethod() {
        return NoticeMethodEnum.EMAIL.getName();
    }

/** * 发送邮件 * @param message * @return */ @Override public String send(NoticeMessage message) { String result = null; try{ if(message instanceof MailMessage){ MailMessage mailMessage = (MailMessage)message; File attachFile = mailMessage.getAttachFile(); String html = mailMessage.getHtml(); if(null != attachFile){ // 带附件的邮件 result = sendAttachFileMail(mailMessage,attachFile); }else{ if(StringUtil.isNotEmpty(html)){ // html内容的邮件 result = sendHtmlMail(mailMessage,html); }else{ // 普通邮件 result = sendSimpleMail(mailMessage); } } } if(StringUtil.isNotEmpty(result)){ log.error("发送邮件: {} 发生错误: {}", JsonUtil.entityToString(message),result); } }catch (Exception e){ log.error(e.getMessage()); result = e.getMessage(); } return result; } /** * 带附件的邮件发送 * @param mailMessage * @param attachFile * @return */ private String sendAttachFileMail(MailMessage mailMessage,File attachFile) { String result = null; try { MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper messageHelper = new MimeMessageHelper(message, true); //邮件发送人 messageHelper.setFrom(from); //邮件接收人 messageHelper.setTo(mailMessage.getReceiverId()); //邮件主题 message.setSubject(mailMessage.getTitle()); //邮件内容 messageHelper.setText(mailMessage.wrapperMessage()); //添加附件 messageHelper.addAttachment(attachFile.getName(), attachFile); //发送 mailSender.send(message); }catch(Exception e) { log.error("发送附件邮件报错: {} {}",e.getMessage(),e); result = e.getMessage(); } return result; } /** * html内容的邮件发送 * @param mailMessage * @param html * @return */ private String sendHtmlMail(MailMessage mailMessage, String html) { String result = null; try { MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper messageHelper = new MimeMessageHelper(message, true); //邮件发送人 messageHelper.setFrom(from); //邮件接收人 messageHelper.setTo(mailMessage.getReceiverId()); //邮件主题 message.setSubject(mailMessage.getTitle()); //邮件内容 messageHelper.setText(html,true); //发送 mailSender.send(message); }catch(Exception e) { log.error("发送html内容邮件报错: {} {}",e.getMessage(),e); result = e.getMessage(); } return result; } /** * 普通邮件发送 * @param mailMessage * @return */ private String sendSimpleMail(MailMessage mailMessage) { String result = null; try { SimpleMailMessage message = new SimpleMailMessage(); message.setFrom(from); message.setTo(mailMessage.getReceiverId()); message.setCc(from); message.setSubject(mailMessage.getTitle()); message.setText(mailMessage.wrapperMessage()); mailSender.send(message); }catch(Exception e) { log.error("发送普通邮件报错: {} {}",e.getMessage(),e); result = e.getMessage(); } return result; } }

5.3  配置参数

spring:
  # 邮件相关
  mail:
    host: smtp.qq.com
    port: 465
    username: xxx@qq.com
    password: xxx
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true

6. 腾讯短信发送实现类

6.1  引入依赖

<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<!-- go to https://search.maven.org/search?q=tencentcloud-sdk-java and get the latest version. -->
<!-- 请到https://search.maven.org/search?q=tencentcloud-sdk-java查询所有版本,最新版本如下 -->
<version>3.1.1000</version>
</dependency>

6.2  定义实现类

package com.yj.notice.service.impl;

import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.yj.cmp.commons.json.JsonUtil;
import com.yj.notice.costant.NoticeMethodEnum;
import com.yj.notice.message.NoticeMessage;
import com.yj.notice.service.MessageService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * @author : dyg
 * @className : TencentMessageServiceImpl
 * @description : 描述说明该类的功能
 * @date : 2024/4/16 10:10
 */
@Service("TencentMessageService")
@Slf4j
@Data
public class TencentMessageServiceImpl implements MessageService {
    /**
     * 短信发送API
     */
    private final String SMS_API = "sms.tencentcloudapi.com";
    private final String SMS_ACTION = "SendSms";
    private final String SMS_VERSION = "2021-01-11";
    private final String SMS_REGION= "ap-beijing";
    /**
     * 短信客户端
     */
    private SmsClient smsClient;

    /**
     * 短信发送AppId
     */
    @Value(value = "${notice.tencent.appId}")
    private String smsSdkAppId;
    /**
     * 短信发送模板Id
     */
    @Value(value = "${notice.tencent.templateId}")
    private String smsTemplateId ;
    /**
     * 腾讯云认证信息
     */
    @Value(value = "${notice.tencent.secretId}")
    private String secretId ;
    @Value(value = "${notice.tencent.secretKey}")
    private String secretKey ;

    /**
     * 获取客户端
     * @return
     */
    public SmsClient getSmsClient() {
        synchronized (this){
            if(null == smsClient){
                Credential credential = new Credential(secretId,secretKey);
                // 实例化一个http选项,可选的,没有特殊需求可以跳过
                HttpProfile httpProfile = new HttpProfile();
                // 推荐使用北极星,相关指引可访问如下链接
                // https://git.woa.com/tencentcloud-internal/tencentcloud-sdk-java#%E5%8C%97%E6%9E%81%E6%98%9F
                httpProfile.setEndpoint(SMS_API);
                // 实例化一个client选项,可选的,没有特殊需求可以跳过
                ClientProfile clientProfile = new ClientProfile();
                clientProfile.setHttpProfile(httpProfile);
                // 实例化要请求产品的client对象,clientProfile是可选的
                smsClient = new SmsClient(credential,SMS_REGION,clientProfile);
            }
        }
        return smsClient;
    }

    
    @Override
    public String send(NoticeMessage message) {
        String result = null;
        SendSmsRequest sendSmsRequest = new SendSmsRequest();
        sendSmsRequest.setSmsSdkAppId(smsSdkAppId);
        sendSmsRequest.setPhoneNumberSet(new String[]{message.getReceiverPhone()});
        sendSmsRequest.setSignName("腾讯云");
        sendSmsRequest.setTemplateId(smsTemplateId);
        sendSmsRequest.setTemplateParamSet(new String[]{message.getTitle(),message.getContent(),message.getTime()});
        try {
            SendSmsResponse sendSmsResponse = smsClient.SendSms(sendSmsRequest);
            result = "发送腾讯短信平台结果: "+ JsonUtil.objectToJson(sendSmsResponse);
        } catch (TencentCloudSDKException e) {
            log.error(e.getMessage(),e);
            result ="发送腾讯短信平台失败: "+ e.getMessage()+ " " + e;
        }
        return result;
    }

    @Override
    public String getNoticeMethod() {
        return NoticeMethodEnum.TENCENT_SMS.getName();
    }
}

6.3  配置参数

# 消息推送相关
notice:
  # 腾讯短信配置
  tencent:
    appId: xx
    templateId: xx
    secretId: xx
    secretKey: xx

7. 系统内部消息发送实现类

7.1  系统内部消息表定义

-- 系统用户-站内消息表
DROP TABLE IF EXISTS `system_user_message`;
create table `system_user_message` (
    `id` int(16) NOT NULL AUTO_INCREMENT,
    `message_type` varchar(200)  COMMENT '消息类型 public-公告 private-个人消息 ticket-工单消息',
    `source_msg_id` int(16) COMMENT '消息id' ,
    `title` varchar(200)  COMMENT '标题',
    `content` text  COMMENT '内容',
    `receiver_id` varchar(200)  COMMENT '接收者id 用户id',
    `send_time` datetime NOT NULL default NOW() COMMENT '发送时间',
    `bus_type` varchar(200)  COMMENT '业务类型',
    `is_read` int(1) default 0 COMMENT '是否已读 0-no 1-yes',
    `read_time` datetime COMMENT '读取时间',
    `properties` varchar(1000) comment '其他数据',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '系统用户-站内消息表';

6.2  系统内部消息实体定义

package com.yj.notice.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.yj.notice.costant.MessageSource;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Date;

/**
 * @author : dyg
 * @className : SystemMessage
 * @description : 内部通知消息
 * @date : 2023/9/7 10:04
 */
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
@TableName("system_user_message")
public class SystemUserMessage implements Serializable {
    private static final long serialVersionUID = 228169618996650529L;

    @TableId(type = IdType.AUTO)
    private Integer id;
    /**
     * 消息类型
     * {@link  MessageSource}
     */
    @TableField("message_type")
    private String messageType;
    /**
     * 源头消息id
     * public-公告  yg_alarm-云管告警  cloud_alarm-插件告警 使用到
     * {@link  MessageSource}
     */
    @TableField("source_msg_id")
    private Integer sourceMsgId;

    /**
     * 消息标题
     */
    @TableField("title")
    private String title;
    /**
     *消息内容
     */
    @TableField("content")
    private String content;
    /**
     * 接收者id
     */
    @TableField("receiver_id")
    private String receiverId;
    /**
     * 发送时间
     */
    @TableField("send_time")
    private Date sendTime;
    /**
     * 消息业务类型
     */
    @TableField("bus_type")
    private String busType;
    /**
     * 是否已读
     * 0-no  1-yes
     */
    @TableField("is_read")
    private Integer isRead;
    /**
     * 读取时间
     */
    @TableField("read_time")
    private Date readTime;

    @TableField("properties")
    private String properties;
}

7.3 实现类定义

package com.yj.notice.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yj.cmp.bss.constant.RoleGroup;
import com.yj.cmp.bss.entity.APIPermission;
import com.yj.cmp.bss.entity.Audit;
import com.yj.cmp.bss.entity.Request;
import com.yj.cmp.bss.entity.User;
import com.yj.cmp.bss.service.RequestService;
import com.yj.cmp.bss.service.UserService;
import com.yj.cmp.commons.constant.BssConstant;
import com.yj.commons.security.user.SecurityUser;
import com.yj.commons.security.user.UserDetail;
import com.yj.commons.tools.page.PageData;
import com.yj.commons.tools.utils.Result;
import com.yj.commons.tools.utils.StringUtil;
import com.yj.helper.user.UserHelper;
import com.yj.notice.costant.MessageSource;
import com.yj.notice.costant.NoticeMethodEnum;
import com.yj.notice.dao.SystemUserMessageDao;
import com.yj.notice.entity.SystemUserMessage;
import com.yj.notice.entity.PublicSystemNotice;
import com.yj.notice.message.NoticeMessage;
import com.yj.notice.service.MessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : dyg
 * @className : NoticeInnerMessageServiceImpl
 * @description : 描述说明该类的功能
 * @date : 2023/9/7 10:42
 */
@Service
@Slf4j
public class SystemUserMessageServiceImpl extends ServiceImpl<SystemUserMessageDao, SystemUserMessage> implements MessageService {
    @Override
    public String send(NoticeMessage message) {
        SystemUserMessage build = SystemUserMessage.builder().messageType(message.getMessageType())
                .title(message.getTitle())
                .content(message.getContent())
                .receiverId(message.getReceiverId())
                .sendTime(new Date())
                .busType(message.getMessageType())
                .isRead(0)
                .build();
        this.save(build);
        return "success";
    }

    @Override
    public String getNoticeMethod() {
        return NoticeMethodEnum.IN_MSG.getName();
    }
}

8. 消息推送测试

8.1  钉钉推送测试

package com.yj.notice.demo;
import com.aliyun.dingtalkrobot_1_0.Client;
import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTOHeaders;
import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTORequest;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.Common;
import com.aliyun.teautil.models.RuntimeOptions;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.*;
import com.dingtalk.api.response.*;
import com.taobao.api.ApiException;
import com.yj.commons.tools.utils.JsonUtil;
import com.yj.commons.tools.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Slf4j
public class DingTalkMessageSend {

    // 企业凭证,两小时一更新
    private static String enterpriseToken = "";
    // 应用凭证
    private static String appkey = "xxxx";
    private static String appsecret = "xxxx";

    // 获取token,每两小时失效
    public static void getToken() {
        try {
            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
            OapiGettokenRequest req = new OapiGettokenRequest();
            req.setAppkey(appkey);
            req.setAppsecret(appsecret);
            req.setHttpMethod("GET");
            OapiGettokenResponse rsp = client.execute(req);
            log.info("token:" + rsp.getBody());
            Map json = JsonUtil.StringToEntity(rsp.getBody(), Map.class);
            enterpriseToken = json.get("access_token").toString();
        } catch (ApiException e) {
            e.printStackTrace();
        }
    }


    /**
     * 使用 Token 初始化账号Client
     *
     * @return Client
     * @throws Exception
     */
    private static Client createClient() throws Exception {
        Config config = new Config();
        config.protocol = "https";
        config.regionId = "central";
        return new Client(config);
    }

    /**
     * 发送钉钉消息
     *
     * @param dingUserId 钉钉用户id
     * @param content    发送消息内容
     * @return void
     */
    public static void createDingNotify(String dingUserId, String content) throws Exception {
        if (StringUtil.isEmpty(enterpriseToken)) {
            getToken();
        }
        Client client = createClient();
        BatchSendOTOHeaders batchSendOTOHeaders = new BatchSendOTOHeaders();
        batchSendOTOHeaders.xAcsDingtalkAccessToken = enterpriseToken;
        content =  "{\"content\": \"" + content + "\"}";
        BatchSendOTORequest batchSendOTORequest = new BatchSendOTORequest()
                .setRobotCode(appkey)//机器人appkey
                .setUserIds(Arrays.asList(dingUserId))
                .setMsgKey("officialTextMsg")
                .setMsgParam(content);
        try {
            client.batchSendOTOWithOptions(batchSendOTORequest, batchSendOTOHeaders, new RuntimeOptions());
        } catch (TeaException err) {
            if (!Common.empty(err.code) && !Common.empty(err.message))
                // err 中含有 code 和 message 属性,可帮助开发定位问题
                log.error(err.code + ":" + err.message);
            // 企业凭证enterpriseToken不合法导致出错时获取新企业凭证并重试
            if (err.code.equals("InvalidAuthentication")) {
                getToken();
            }
        } catch (Exception e) {
            TeaException err = new TeaException(e.getMessage(), e);
            if (!Common.empty(err.code) && !Common.empty(err.message))
                // err中含有code和message 属性,可帮助开发定位问题
                log.error(err.code + ":" + err.message);
        }
    }

    /**
     * 发送钉钉消息
     *
     * @param phone 用户手机号
     * @return void
     */
    public static String getDingdingUserIdByPhone(String phone) {
        try {
            if (StringUtil.isEmpty(enterpriseToken)) {
                getToken();
            }
            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile");
            OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();
            req.setMobile(phone);
            OapiV2UserGetbymobileResponse rsp = client.execute(req, enterpriseToken);
            if (rsp != null) {
                OapiV2UserGetbymobileResponse.UserGetByMobileResponse result = rsp.getResult();
                return result == null ? null : result.getUserid();
            }
        } catch (ApiException e) {
            log.error(e.getErrMsg(), e);
        }
        return null;
    }
    /**
     * 获取组内用户列表
     *
     * @return void
     */
    public static void getUserList( ) {
        try {
            if (StringUtil.isEmpty(enterpriseToken)) {
                getToken();
            }
            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/listid");
            OapiUserListRequest req = new OapiUserListRequest();
            OapiUserListResponse rsp = client.execute(req, enterpriseToken);
            if (rsp != null) {
                List<OapiUserListResponse.Userlist> userlist = rsp.getUserlist();
                userlist.stream().forEach(System.out::println);
            }
        } catch (ApiException e) {
            log.error(e.getErrMsg(), e);
        }
    }
    /**
     * 获取组内用户列表
     *
     * @return void
     */
    public static void getDepartmentList( ) {
        try {
            if (StringUtil.isEmpty(enterpriseToken)) {
                getToken();
            }
            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsub");
            OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest();

            OapiV2DepartmentListsubResponse rsp = client.execute(req, enterpriseToken);
            if (rsp != null) {
                List<OapiV2DepartmentListsubResponse.DeptBaseResponse> result = rsp.getResult();
                result.stream().forEach(System.out::println);
            }
        } catch (ApiException e) {
            log.error(e.getErrMsg(), e);
        }
    }


    public static void main(String[] args) throws Exception{
        String dingdingUserIdByPhone = getDingdingUserIdByPhone("17352253381");
        System.out.println(dingdingUserIdByPhone);
        createDingNotify(dingdingUserIdByPhone,"告警时间:  2023-09-05 16:33:36\n告警级别: 中级\n告警类别: 虚拟机\n告警消息: 虚拟机告警信息\n备注: 虚拟机告警信息");
        getDepartmentList();
        getUserList();
    }
}

8.2  微信推送测试

package com.yj.notice.demo;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.yj.commons.tools.utils.DateUtils;
import com.yj.commons.tools.utils.JsonUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import static com.yj.commons.tools.utils.DateUtils.DATE_TIME_PATTERN;

/**
 * @author : dyg
 * @className : WechatMessageSend
 * @description : 描述说明该类的功能
 * @date : 2023/9/5 10:01
 */
@Slf4j
public class WechatMessageSend {

    @Data
    public static  class WeChatTemplateMsg implements Serializable {
        /**
         * 消息
         */
        private String value;
        /**
         * 消息颜色
         */
        private String color;

        public WeChatTemplateMsg(String value) {
            this.value = value;
            this.color = "#173177";
        }

        public WeChatTemplateMsg(String value, String color) {
            this.value = value;
            this.color = color;
        }
    }
    public static String  getAccessToken(){
        String appId = "xxxx";
        String appIdSecret = "xxxx";
        String requestUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ appId +"&secret=" + appIdSecret;
        String res = HttpUtil.get(requestUrl);
        JSONObject jsonObject = JSONObject.parseObject(res);
        String accessToken = jsonObject.getString("access_token");
        log.info("accessToken:{}", accessToken);
        return accessToken;
    }

    public static void getUserList(){
        RestTemplate restTemplate = new RestTemplate();
        String accessToken = getAccessToken();
        String requestUrl =  "https://api.weixin.qq.com/cgi-bin/user/get?access_token="+ accessToken;
        ResponseEntity<String> response = restTemplate.postForEntity(requestUrl, null, String.class);
        log.info("结果是: {}",response.getBody());
        JSONObject result = JSONObject.parseObject(response.getBody());
        com.alibaba.fastjson.JSONArray openIdJsonArray = result.getJSONObject("data").getJSONArray("openid");
        Iterator iterator = openIdJsonArray.iterator();
        if (iterator.hasNext()){
            String userId = iterator.next().toString();
            log.debug("用户openid:"+userId);
            String userDetailUri = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="+accessToken+"&openid="+userId+"&lang=zh_CN";
            ResponseEntity<String> response2 = restTemplate.postForEntity(userDetailUri, null, String.class);
            log.info("结果是: {}",response2.getBody());
            JSONObject result2 = JSONObject.parseObject(response2.getBody());
            log.info("用户详细信息: {}",result2.toJSONString());
        }
    }
    public static void sendMessage(String type){
        // 模板参数
        Map<String, WeChatTemplateMsg> sendMag = new HashMap<String, WeChatTemplateMsg>();

        // openId代表一个唯一微信用户,即微信消息的接收人
        String openId = "okUjK6P908Zwjc8BOSdinAO8iG5o";
        // 公众号的模板id(也有相应的接口可以查询到)
        String alarmTemplateId = "mfriJWNssZYtIbpfzxH-4FlxgK4ZQ0ID_xNvEO0xDOY";
        String commonTemplateId = "q7bSOYPPDHn-Lz_vTShzsbU4WzKX3lH9nxuasnngj8A";
        // 微信的基础accessToken
        String accessToken = getAccessToken();
        String requestUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;

        //消息主题显示相关map
        //根据自己的模板定义内容和颜色

        //拼接base参数
        Map<String, Object> sendBody = new HashMap<>();
        sendBody.put("touser", openId);               // openId
//        sendBody.put("url", "https://www.baidu.com");  //跳转网页url
        sendBody.put("data", sendMag);                   // 模板参数
        if("alarm".equals(type)){
            sendMag.put("message", new WeChatTemplateMsg("虚拟机-102.23.26.36 CPU使用占比超过80%"));
            sendMag.put("time",new WeChatTemplateMsg(DateUtils.format(new Date(),DATE_TIME_PATTERN),"#173177"));
            sendMag.put("level",new WeChatTemplateMsg("中等","#FF69B4" ));
            sendMag.put("type",new WeChatTemplateMsg("虚拟机CPU" ,"#173177"));
            sendMag.put("remark",new WeChatTemplateMsg("虚拟机CPU使用触发告警","#173177"));
            sendBody.put("template_id", alarmTemplateId);      // 模板Id
        }else{
            sendMag.put("content", new WeChatTemplateMsg("根据兰州市气象局发布的最新天气预警信息,未来8-24小时内,城关区、七里河区、西固区、安宁区、榆中县、皋兰县大部将有依次明显的降水活动,并伴有短时5-6级大风,请注意及时关注最新天气情况!"));
            sendMag.put("title",new WeChatTemplateMsg("暴雨蓝色预警"));
            sendMag.put("time",new WeChatTemplateMsg(DateUtils.format(new Date(),DATE_TIME_PATTERN),"#FF69B4"));
            sendBody.put("template_id", commonTemplateId);      // 模板Id
        }
     

        try {
            // 1.创建httpclient对象
            CloseableHttpClient client = HttpClients.createDefault();
            // 2.创建post对象
            HttpPost post = new HttpPost(requestUrl);
            StringEntity postingString = new StringEntity(JsonUtil.entityToString(sendBody), "utf-8");
            post.setEntity(postingString);
            // 3.执行post方法:得到结果
            CloseableHttpResponse response = client.execute(post);
            // 4.处理结果
            //  1.得到状态码
            int statusCode = response.getStatusLine().getStatusCode();
            log.info("----http code : {}", statusCode);
            if (statusCode == 200) {
                //  2.得到实体内容
                org.apache.http.HttpEntity entity = response.getEntity();
                String content = EntityUtils.toString(entity, "utf-8");
                System.out.println(content);
            }
            //  5.关闭连接
            client.close();
        } catch (IOException e) {
            log.error("------exception : {} {} ",e.getMessage(),e);
        }
    }

    public static void main(String[] args) {
//        getAccessToken();
//        getUserList();
        sendMessage("a");
    }
}

 

 

 

 

 

posted @ 2024-04-17 17:43  521pingguo1314  阅读(16)  评论(0编辑  收藏  举报