首页 > 编程语言 >java多渠道消息推送-(微信公众号、钉钉、邮箱、系统内部、短信等)

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

时间:2024-04-17 17:57:28浏览次数:27  
标签:yj java String 微信 new import message 推送 com

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  定义实现类

 package com.yj.notice.service.impl;
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.2  配置参数

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

6. 腾讯短信发送实现类

6.1  定义实现类

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.2  配置参数

# 消息推送相关
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");
    }
}

 

 

 

 

 

标签:yj,java,String,微信,new,import,message,推送,com
From: https://www.cnblogs.com/dduo/p/18140862

相关文章

  • tomcat启动指定java版本
    linux上已经配置jdk1.8为全局变量,但是tomcat运行需要指定jdk11。那么我们在不影响全局JAVA_HOME变量的时候,需直接指定JAVA_HOME即可。[rootapache-tomcat-8.5.87]#java-versionjavaversion"1.8.0_211"Java(TM)SERuntimeEnvironment(build1.8.0_211-b12)JavaHotSpo......
  • SQL语法错误-java.sql.SQLSyntaxErrorException: You have an error in your SQL synt
    频繁爆出这样的错误:java.sql.SQLSyntaxErrorException:YouhaveanerrorinyourSQLsyntax;checkthemanualthatcorrespondstoyourMySQLserverversionfortherightsyntaxtousenear''atline1查阅了许多资料后,我怀疑报错可能与字段名不小心用了关键字有关......
  • java使用监听统计网站信息,并获取session中对应的ip
    用javalistener统计在线人数,并获取session中对应的ip在web.xml中添加。注意放到<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>spring监听器之后,否则会报错<listener><listener-class>com.......
  • java多线程 读取list--动态读取list
    java多线程读取list--动态读取list的案例 本次介绍,我使用的是synchronized同步代码块的关键字来读取list,在写java多线程时,一定要注意synchronized关键字的有效范围。ps:如果synchronized关键字的代码块范围太大,可能会导致优先获取到cpu资源的第一个线程在满足条件的情......
  • java多线程 读取变量同步安全的案例
    本次介绍,我使用的是synchronized同步代码块的关键字来读取list,在写java多线程时,一定要注意synchronized关键字的有效范围。ps:如果synchronized关键字的代码块范围太大,可能会导致优先获取到cpu资源的第一个线程在满足条件的情况下一直无法跳循环,从而使得其他线程无法给获......
  • Java登陆第四十三天——Pinia
    到目前一共学习了两种传参方式。 1.组件传参 2.路由传参这两种传参方式并不好用,所以出现了PiniaPinia平替了Vuex,而且比它更优秀。Pinia是Vue衍生的生态系统之一,所以,在使用它前需要导入依赖。npmipinia简单地说,Pinia就是共享数据。各个.vue组件可以利用Pinia更好的完成......
  • KMP算法 Java实现
    Problem:28.找出字符串中第一个匹配项的下标目录解题方法思路构建next数组回溯查找复杂度Code解题方法构建next串回溯查找next串,最后下标思路通过最大前缀后缀能找到下一次未查找到后要回溯的位置构建next数组无论如何第一个数的下一次回溯位置肯定是0,因此next[......
  • 2.JAVA入门 了解JAVA 配置环境
    Java入门Java特性和优势简单性:Java语言设计简洁,易于学习和使用。它摒弃了许多复杂的特性和语法,使得编程变得更加直观和容易上手。面向对象:Java是一种纯粹的面向对象编程语言,所有的代码都以类和对象的形式组织。这种面向对象的特性使得代码更加模块化、可重用性更高,并且更容易......
  • day14_我的Java学习笔记 (常用API、Lambda、常见算法)
    1.常用API1.1Date类【案例】:计算出当前时间往后走1小时121秒之后的时间是多少。1.2SimpleDateFormat【练习】:秒杀活动1.3Calendar2.JDK8新增日期类2.1概述、LocalTime/LocalDate/LocalDateTime2.2Ins......
  • IDEA2023版本创建Spring项目只能勾选17和21却无法使用Java8的完美解决方案
    参考:https://www.jb51.net/program/308256k4b.htm方案一:替换创建项目的源我们只知道IDEA页面创建Spring项目,其实是访问springinitializr去创建项目。故我们可以通过阿里云国服去间接创建Spring项目。将https://start.spring.io/或者http://start.springboot.io/替换为https://......