企微群机器人推送文本+Excel

该代码示例展示了如何使用Java构建一个企业微信群机器人,将学生、教师信息整理成Excel表格,并通过群机器人定时发送到指定群组,同时支持@特定用户。主要涉及内容包括数据转换、Excel文件操作以及企业微信API的调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

例如,企微群定时推送:内容+表格

群机器人:学校基本信息:

[一个记录学校基本信息的excel表]

 excel表简单类似:

准备肯定先企微群创建一个机器人,获取到群webhook备用;

简易步骤比较简单,先分别获取老师、学生、职工的list信息->再把列表转化为excel表->推送消息

 一、推送工具类;(isNotBank之类的判空方法,可以自行重写)


import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author yrl
 * @date 2023/7/5 15:29
 */
@Slf4j
public class WxPushUtil {

    /**
     * 企业微信机器人api地址与key;webhook 截取
     */
    private final static String WECHAT_API_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/";
    private final static String WECHAT_API_KEY = "xxxxx-xxx-xxx-xxxxxxxxxxxxxxxxx";


    /**
     * 学生列表数据转化为 excel
     *
     * @param wb       Workbook
     * @param student  学生
     * @param dest     首栏提示 默认可空
     * @param pageName 底部分页表名称
     */
    public static boolean studentFileBuild(HSSFWorkbook wb, List<student> student, String dest, String pageName) {
        //
        if (student == null || student.size() < 0) {
            return false;
        }
        //表头字段,与对象一致
        String[] titleArray = new String[]{"学生姓名", "年龄", "性别", "班级"};
        String[] fieldArray = new String[]{"studentName", "age", "sex", "class"};
        List<Map<String, Object>> list = new ArrayList<>();

        for (Student s : student) {
            //转成map
            Map<String, Object> map = BeanUtils.beanToMap(s);
            list.add(map);
        }

        if (list.size() > 0) {
            //数据组合 到HSSFWorkbook
            ExcelUtil.buildExcel(list, wb, pageName, titleArray, fieldArray, dest);
            return true;
        }
        return false;
    }

    /**
     * 老师 数据转化为excel构建
     *
     * @param wb       Workbook
     * @param teacher  老师
     * @param dest     首栏提示 默认可空
     * @param pageName 底部分页表名称
     */
    public static boolean teacherFileBuild(HSSFWorkbook wb, List<Teacher> teacher, String dest, String pageName) {
        //
        if (teacher == null || teacher.size() < 0) {
            return false;
        }
        //表头字段,与对象一致
        String[] titleArray = new String[]{"工号", "姓名", "性别", "职位"};
        String[] fieldArray = new String[]{"number", "name", "sex", "lev"};
        List<Map<String, Object>> list = new ArrayList<>();

        for (Teacher s : teacher) {
            //转成map
            Map<String, Object> map = BeanUtils.beanToMap(s);
            list.add(map);
        }

        if (list.size() > 0) {
            //数据组合 到HSSFWorkbook
            ExcelUtil.buildExcel(list, wb, pageName, titleArray, fieldArray, dest);
            return true;
        }
        return false;
    }

    /**
     * 发送文件消息,需要先将文件上传到企业微信临时素材,再根据获取的media_id调用群机器人
     *
     * @param file      需要发送的文件
     * @param text      发送附件的同时需要发送文字内容
     * @param phoneList 需要@的群成员手机号
     */
    public static void sendFileMsg(File file, String text, List<String> phoneList) {
        // 构造RequestBody对象,用来携带要提交的数据;需要指定MediaType,用于描述请求/响应 body 的内容类型
        MediaType contentType = MediaType.parse("application/form-data; boundary");
        RequestBody body = RequestBody.create(contentType, file);
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", file.getName(), body)
                .build();

        try {
            //获取推送的群id,如果多个,推送多个
            // 上传到临时素材
            String mediaUrl = WECHAT_API_URL + "upload_media?type=file&key=" + WECHAT_API_KEY;
            log.debug("将文件{}上传到临时素材:{}", file.getName(), mediaUrl);
            String respMsg = okHttp(requestBody, mediaUrl);
            log.debug("将文件{}上传到临时素材:{}, {}", file.getName(), mediaUrl, respMsg);

            // 获取临时素材id
            JSONObject result = JSONUtil.parseObj(respMsg);
            String mediaId = result.getStr("media_id");

            if (U.isNotBlank(text)) {
                JSONObject textJson = new JSONObject();
                textJson.set("content", text);
                JSONObject reqBody = new JSONObject();
                //先推文本
                reqBody.set("msgtype", "text");
                reqBody.set("text", textJson);
                //"mentioned_mobile_list":["13800001111","@all"]
                if (A.isNotEmpty(phoneList)) {
                    System.out.println("推送的手机号:" + phoneList);
                    reqBody.set("mentioned_mobile_list", phoneList);
                }

                // 调用群机器人发送消息
                callWeChatBot(reqBody.toString(), WECHAT_API_KEY);
            }

            JSONObject fileJson = new JSONObject();
            fileJson.set("media_id", mediaId);
            JSONObject reqBody = new JSONObject();
            //再推文件
            reqBody.set("msgtype", "file");
            reqBody.set("file", fileJson);
            reqBody.set("safe", 0);

            // 再调用群机器人发送文件消息
            callWeChatBot(reqBody.toString(), WECHAT_API_KEY);
        } catch (Exception e) {
            log.error("文件推送异常:{}", file.getName(), e);
        }
    }


    /**
     * @param body 携带需要提交的数据(后续迁移)
     * @param url  请求地址
     * @throws Exception 异常
     */
    private static String okHttp(RequestBody body, String url) throws Exception {
        // 构造和配置OkHttpClient
        OkHttpClient client = new OkHttpClient.Builder()
                // 设置连接超时时间
                .connectTimeout(10, TimeUnit.SECONDS)
                // 设置读取超时时间
                .readTimeout(20, TimeUnit.SECONDS)
                .build();

        // 构造Request对象
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                // 响应消息不缓存
                .addHeader("cache-control", "no-cache")
                .build();

        // 构建Call对象,通过Call对象的execute()方法提交异步请求
        Response response = client.newCall(request).execute();

        // 请求结果处理
        assert response.body() != null;
        byte[] datas = response.body().bytes();
        return new String(datas);
    }

    /**
     * 调用群机器人
     *
     * @param reqBody 接口请求参数
     * @throws Exception 异常
     */
    private static void callWeChatBot(String reqBody, String key) throws Exception {
        log.debug("调用群机器人:{}", reqBody);
        // 构造RequestBody对象,用来携带要提交的数据;需要指定MediaType,用于描述请求/响应 body 的内容类型
        okhttp3.MediaType contentType = okhttp3.MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(contentType, reqBody);

        String botUrl = WECHAT_API_URL + "send?key=" + key;
        // 调用群机器人
        String respMsg = okHttp(body, botUrl);
        JSONObject result = JSONUtil.parseObj(respMsg);

        if ("0".equals(result.getStr("errcode"))) {
            log.debug("调用群机器人发送消息成功, reqBody: {}, respMsg : {}", reqBody, respMsg);
        } else {
            log.error("调用群机器人发送消息失败, reqBody: {}, respMsg : {}", reqBody, respMsg);
        }
    }
}

二、EXCEL工具类(list转化等)有些方法可能用不到


import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * Excel工具类
 */
public class ExcelUtil<T> {

    public Class<T> clazz;

    public ExcelUtil(Class<T> clazz) {
        this.clazz = clazz;
    }


    /**
     * 读取Excel内容转为List
     */
    public List<T> importExcel(MultipartFile file) throws Exception {
        return importExcel(StringUtils.EMPTY, file);
    }


    /**
     * 读取Excel内容转为List
     */
    public List<T> importExcel(String sheetName, MultipartFile file) throws Exception {
        U.assertException(U.isBlank(file), "上传的文件为空");
        //获取文件名
        String fileName = file.getOriginalFilename();
        U.assertException(!(fileName.endsWith(".xls") || fileName.endsWith(".xlsx")), "请选择Excel文件上传");
        //
        List<T> list = new ArrayList<>();
        Workbook workbook = WorkbookFactory.create(file.getInputStream());
        Sheet sheet;
        if (StringUtils.isNotEmpty(sheetName)) {
            // 如果指定sheet名,则取指定sheet中的内容.
            sheet = workbook.getSheet(sheetName);
        } else {
            // 如果传入的sheet名不存在则默认指向第1个sheet.
            sheet = workbook.getSheetAt(0);
        }
        if (sheet == null) {
            throw new IOException("文件sheet不存在");
        }
        //获取数据
        int rows = sheet.getLastRowNum();
        if (rows == 0) {
            U.assertException("当前工作簿没数据");
        }
        //行号从0开始,所以需要+1
        rows = rows + 1;
        // 默认序号
        int serialNum = 0;
        // 有数据时才处理 得到类的所有field.
        Field[] allFields = clazz.getDeclaredFields();
        //用于校验是否存在某些字段
        Map<String, Field> fieldNameMap = new HashMap<>();
        // 定义一个map用于存放列的序号和field.
        Map<Integer, Field> fieldsMap = new HashMap<>();
        for (Field field : allFields) {
            // 设置类的私有字段属性可访问.
            field.setAccessible(true);
            fieldsMap.put(++serialNum, field);
            fieldNameMap.put(field.getName(), field);
        }
        //
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(DateFormatType.YYYY_MM_DD_HH_MM_SS.getValue());
        DateTimeFormatter df = DateTimeFormatter.ofPattern(DateFormatType.YYYY_MM_DD.getValue());
        SimpleDateFormat sdf = new SimpleDateFormat(DateFormatType.YYYY_MM_DD_HH_MM_SS.getValue());
        //
        Row row = null;
        Cell cell = null;
        try {
            // 从第2行开始取数据,默认第一行是表头.
            for (int i = 1; i < rows; i++) {
                row = sheet.getRow(i);
                if (row == null) {
                    continue;
                }
                T entity = clazz.newInstance();
                for (int j = 0; j < serialNum; j++) {
                    cell = row.getCell(j);
                    if (cell == null) {
                        continue;
                    }

                    // 从map中得到对应列的field.
                    Field field = fieldsMap.get(j + 1);
                    // 取得类型,并根据对象类型设置值.
                    Class<?> fieldType = field.getType();

                    String c;
                    //excel数字精度问题:如果是数字类型,转化
                    if (cell.getCellTypeEnum().equals(CellType.NUMERIC) && fieldType != Date.class) {
                        NumberFormat numberFormat = NumberFormat.getNumberInstance();
                        double d = cell.getNumericCellValue();
                        // 关键在这里!
                        c = numberFormat.format(d);
                    } else {
                        // 先设置Cell的类型,然后就可以把纯数字作为String类型读进来了(这里数字类型 c可能存在精度问题)
                        cell.setCellType(CellType.STRING);
                        c = cell.getStringCellValue();
                    }

                    if (StringUtils.isEmpty(c)) {
                        continue;
                    }
                    if (String.class == fieldType) {
                        field.set(entity, c);
                    } else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {
                        field.set(entity, Integer.parseInt(c));
                    } else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {
                        field.set(entity, Long.valueOf(c));
                    } else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {
                        field.set(entity, Float.valueOf(c));
                    } else if ((Short.TYPE == fieldType) || (Short.class == fieldType)) {
                        field.set(entity, Short.valueOf(c));
                    } else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {
                        field.set(entity, Double.valueOf(c));
                    } else if (Character.TYPE == fieldType) {
                        if (c.length() > 0) {
                            field.set(entity, c.charAt(0));
                        }
                    } else if (Date.class == fieldType) {
                        if (cell.getCellTypeEnum() == CellType.NUMERIC) {
                            cell.setCellValue(sdf.format(cell.getNumericCellValue()));
                            c = sdf.format(cell.getNumericCellValue());
                        } else {
                            c = cell.getStringCellValue();
                        }
                    } else if (BigDecimal.class == fieldType) {
                        try {
                            field.set(entity, NumberUtil.toBigDecimal(c));
                        } catch (Exception ex) {
                            U.assertException("数值类型转换失败,请检查单元格值是否符合规范");
                        }
                    } else if (LocalDateTime.class == fieldType) {
                        field.set(entity, LocalDateTime.parse(excelDoubleToDate(c, DateFormatType.YYYY_MM_DD_HH_MM_SS), dtf));
                    } else if (LocalDate.class == fieldType) {
                        field.set(entity, LocalDate.parse(excelDoubleToDate(c, DateFormatType.YYYY_MM_DD), df));
                    }
                }
                if (BeanUtil.isNotEmpty(entity)) {
                    //判断是否有行号字段,有的话赋值
                    if (fieldNameMap.containsKey("rowNum")) {
                        //记录一下行数
                        fieldNameMap.get("rowNum").set(entity, row.getRowNum() + 1);
                    }
                    list.add(entity);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            U.assertException(StrUtil.format("解析第{}行,第{}列时出错,错误原因:{}",
                    row == null ? "null" : row.getRowNum() + 1,
                    cell == null ? "null" : cell.getColumnIndex() + 1,
                    ex.getMessage()));
        }
        return list;
    }

    //解析Excel日期格式
    public static String excelDoubleToDate(String strDate, DateFormatType dateFormatType) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(dateFormatType.getValue());
            Date tDate = doubleToDate(Double.parseDouble(strDate));
            return sdf.format(tDate);
        } catch (Exception e) {
            //e.printStackTrace();
            return strDate;
        }
    }

    //解析Excel日期格式
    public static Date doubleToDate(Double dVal) {
        Date tDate = new Date();
        long localOffset = tDate.getTimezoneOffset() * 60000; //系统时区偏移 1900/1/1 到 1970/1/1 的 25569 天
        tDate.setTime((long) ((dVal - 25569) * 24 * 3600 * 1000 + localOffset));
        return tDate;
    }


    /**
     * 常规字体-微软雅黑-12号
     */
    public static HSSFFont getFont(HSSFWorkbook wb) {
        HSSFFont font = wb.createFont();
        font.setFontHeightInPoints((short) 12);//设置字体大小
        font.setFontName("微软雅黑");
        return font;
    }

    /**
     * 白色字体-微软雅黑-12号
     */
    public static HSSFFont getWhiteFont(HSSFWorkbook wb) {
        HSSFFont font = wb.createFont();
        font.setFontHeightInPoints((short) 12);//设置字体大小
        font.setFontName("微软雅黑");
        font.setColor(HSSFColor.HSSFColorPredefined.WHITE.getIndex());
        font.setBold(true);
        return font;
    }

    /**
     * 标题字体-微软雅黑-12号-加粗
     */
    public static HSSFFont getTitleFont(HSSFWorkbook wb) {
        HSSFFont font = getFont(wb);
        font.setBold(true);
        return font;
    }

    /**
     * 常规字体-微软雅黑-12号-红色
     */
    public static HSSFFont getRedFont(HSSFWorkbook wb) {
        HSSFFont font = getFont(wb);
        font.setColor(Font.COLOR_RED);
        return font;
    }

    /**
     * 单元格样式-自动换行-全边框-左右垂直居中
     */
    public static CellStyle getCellStyle(HSSFWorkbook wb, HSSFFont font) {
        CellStyle style = wb.createCellStyle();//新建样式对象
        style.setWrapText(true);//设置自动换行
        style.setAlignment(HorizontalAlignment.CENTER);//居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);//居中
        style.setBorderBottom(BorderStyle.THIN);//下边框
        style.setBorderLeft(BorderStyle.THIN);//左边框
        style.setBorderRight(BorderStyle.THIN);//右边框
        style.setBorderTop(BorderStyle.THIN);//上边框
        style.setFont(font);
        return style;
    }

    /**
     * 单元格样式-自动换行-全边框-左右垂直居中-背景颜色
     */
    public static CellStyle getCellStyle(HSSFWorkbook wb, HSSFFont font, short bg) {
        CellStyle style = getCellStyle(wb, font);
        //设置背景色
        style.setFillForegroundColor(bg);
        //设置填充样式
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        return style;
    }


    /**
     * 设置下拉框(注意单元格内的字符不能超过255)
     *
     * @param sheet    指定sheet页
     * @param values   下拉框的值
     * @param firstRow 起始行号
     * @param lastRow  起始行号
     * @param firstCol 起始列号
     * @param lastCol  终止列号
     */
    public static void setDropDownBox(HSSFSheet sheet, String[] values, Integer firstRow, Integer lastRow, Integer firstCol, Integer lastCol) {
        // 加载下拉列表内容
        DVConstraint constraint = DVConstraint.createExplicitListConstraint(values);
        // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
        CellRangeAddressList regions = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol);
        // 数据有效性对象
        HSSFDataValidation data_validation_list = new HSSFDataValidation(regions, constraint);
        sheet.addValidationData(data_validation_list);
    }


    /**
     * sheet合并, 合并后删除数据源sheet
     *
     * @param workbook
     * @param sourceSheet 数据源
     * @param targetSheet 合并到
     * @return
     * @throws IOException
     */
    public static void mergeSheet(XSSFWorkbook workbook, int sourceSheet, int targetSheet) throws IOException {
        final XSSFSheet target = workbook.getSheetAt(targetSheet);
        final XSSFSheet source = workbook.getSheetAt(sourceSheet);
        int lastRowNum = target.getLastRowNum();

        final List<CellRangeAddress> mergedRegions = source.getMergedRegions();

        //处理合并后的mergedRegion
        for (CellRangeAddress mergedRegion : mergedRegions) {
            mergedRegion.setFirstRow(mergedRegion.getFirstRow() + lastRowNum + 1);
            mergedRegion.setLastRow(mergedRegion.getLastRow() + lastRowNum + 1);

        }

        //逐行复制
        for (int i = 0; i <= source.getLastRowNum(); i++) {
            final XSSFRow row = source.getRow(i);
            if (row == null) {
                target.createRow(++lastRowNum);
                continue;
            }
            final Iterator<Cell> cellIterator = row.cellIterator();
            final XSSFRow s1Row = target.createRow(++lastRowNum);
            while (cellIterator.hasNext()) {
                final Cell next = cellIterator.next();
                final CellStyle cellStyle = next.getCellStyle();
                final XSSFCell cell = s1Row.createCell(next.getColumnIndex());
                final CellType cellType = next.getCellType();
                cell.setCellStyle(cellStyle);

                switch (cellType) {
                    case STRING:
                        cell.setCellValue(next.getStringCellValue());
                        break;
                    case FORMULA:
                        cell.setCellFormula(next.getCellFormula());
                        continue;
                    case NUMERIC:
                        cell.setCellValue(next.getNumericCellValue());
                        break;
                    case BOOLEAN:
                        cell.setCellValue(next.getBooleanCellValue());
                }
                cell.setCellType(cellType);
            }
        }

        for (CellRangeAddress mergedRegion : mergedRegions) {
            target.addMergedRegion(mergedRegion);
        }
        //移除sourceSheet
        workbook.removeSheetAt(sourceSheet);
    }

    public static void buildExcel(List<Map<String, Object>> list, HSSFWorkbook wb, String sheetName, String[] titleArray, String[] fieldArray, String dest) {

        HSSFSheet sheet = wb.createSheet(sheetName);
        //样式
        //设置默认行高、列宽
        sheet.setDefaultRowHeight((short) 500);
        sheet.setDefaultColumnWidth(30);
        //字体
        HSSFFont font = getFont(wb);
        //标题字体
        HSSFFont titleFont = getWhiteFont(wb);
        titleFont.setColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
        //标题样式
        CellStyle titleStyle = getCellStyle(wb, titleFont, IndexedColors.GREY_25_PERCENT.getIndex());
        //基础样式
        CellStyle style = getCellStyle(wb, font);
        style.setAlignment(HorizontalAlignment.LEFT);

        int firstRowNum = 0;
        if (StringUtils.isNotBlank(dest)) {
            HSSFFont destFont = getRedFont(wb);
            CellStyle destStyle = getCellStyle(wb, destFont);
            destStyle.setAlignment(HorizontalAlignment.LEFT);
            Row rowDest = sheet.createRow(firstRowNum);
            Cell bigDetailTitleCell = rowDest.createCell(0);
            bigDetailTitleCell.setCellStyle(destStyle);
            bigDetailTitleCell.setCellValue(dest);
            sheet.addMergedRegion(new CellRangeAddress(firstRowNum, firstRowNum, 0, fieldArray.length - 1));

            firstRowNum++;
        }

        //第一行,标题
        Row row0 = sheet.createRow(firstRowNum);
        for (int i = 0; i < titleArray.length; i++) {
            Cell cell = row0.createCell(i);
            cell.setCellStyle(titleStyle);
            cell.setCellValue(titleArray[i]);
        }
        //第2行开始填充数据
        for (int i = 0; i < list.size(); i++) {
            //从第2行开始
            Row row = sheet.createRow(i + 1 + firstRowNum);
            for (int j = 0; j < fieldArray.length; j++) {
                Cell cell = row.createCell(j);
                cell.setCellStyle(style);
                cell.setCellValue(MapUtil.getStr(list.get(i), fieldArray[j], StringUtils.EMPTY));
            }
        }
    }
}

 三、实际业务方法

  /**allInfo 所有信息 包括学生、老师、职工的数据List;phoneList 就是需要@的手机号**/
public void receiptDuePaymentReminderPushMsg(AllInfo allInfo, List<String> phoneList) {
       //创建一个HSSFWorkbook 
        HSSFWorkbook wb = new HSSFWorkbook();
        // 是否有数据需要构建excel推送
        boolean flag0 = studentFileBuild(wb, allInfo.getStudentList(), "", "学生信息");
        boolean flag1 = teacherFileBuild(wb, allInfo.getTeacherList(), "", "老师信息");
        //TODO 职工可自行补充
        boolean flag2 = zhigongFileBuild(wb, allInfo.getZhigongList(), "", "职工信息");


        //只要有一个通过就要发送
        if (!flag0 && !flag1 && !flag2) {
            log.debug("没有需要提醒的数据");
            return;
        }

         //文件名
        String fileName = LocalDate.now() + "学校信息汇总.xlsx";
        File file = new File(fileName);
        try {
            // 上传文件
            wb.write(file);

            // 推送消息:
            String text = "【学校通知】\n请查收学校信息汇总表。";
            //发送文本消息+excel文件到群
            WxPushUtil.sendFileMsg(file, text, phoneList);
        } catch (Exception e) {
            log.error("发送异常", e);
        } finally {
            if (file.exists()) {
                boolean deleteFlag = file.delete();
                log.debug("wxPushMsg delete tmp file: {}", fileName);
            }
        }

    }

 

<think>好的,我现在需要帮用户了解企业微信机器人的主要功能和Webhook的使用方法。首先,我得回忆一下之前提供的引用内容。引用[1]提到了企业微信机器人通过Webhook发送实时报错预警,还提到了配置说明,包括保护Webhook地址的重要性,移除和重新创建机器人的方法,以及自定义消息的开发需求。引用[2]则是一个Python代码示例,展示了如何通过Webhook发送消息,其中包含URL结构和密钥的使用。 用户的问题主要有两部分:主要功能和Webhook的用法。我需要先整理企业微信机器人的主要功能,比如消息推送、自定义格式、安全设置等。然后,关于Webhook的使用方法,需要分步骤说明,比如创建机器人、获取Webhook地址、发送消息的格式(比如文本、Markdown、图片等),以及注意事项比如安全防护和频率限制。 可能需要注意用户提到的“普通推送消息配置”和“自定义推送消息”的区别,这里需要明确说明。同时,引用中的代码示例可能帮助用户理解如何实际操作,所以应该包含一个简单的Python例子,展示如何发送文本消息,并提醒替换密钥。 还需要检查是否有遗漏的功能或步骤,比如是否支持文件类型或其他高级功能,但根据提供的引用,可能主要围绕基本消息类型展开。此外,安全方面需要强调保护Webhook地址,避免泄露,以及移除机器人的方法。 最后,生成相关问题时要覆盖用户可能进一步想知道的内容,比如安全措施、消息类型、错误处理、集成方式等。确保回答结构清晰,分点列出,代码示例正确,并且引用标记正确放置。</think>### 企业微信机器人 Webhook 功能介绍及使用方法 #### 一、主要功能 1. **实时消息推送** 企业微信机器人通过 Webhook 地址可向指定群聊推送文本、Markdown、图片、文件等类型的消息,常用于系统告警、监控通知、任务提醒等场景[^1]。 2. **自定义消息格式** 支持通过 JSON 数据格式自定义消息内容,例如高亮关键信息、添加跳转链接或卡片式交互内容[^1][^2]。 3. **安全控制** 每个机器人对应唯一的 Webhook 地址,需妥善保管以防止滥用。若地址泄露,可通过移除并重新创建机器人解决。 #### 二、Webhook 使用方法 **步骤 1:创建机器人** - 在企业微信群聊中点击右上角「添加机器人」,设置名称后生成唯一的 Webhook 地址,格式为: $$ \text{https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=密钥} $$ **步骤 2:发送消息** 通过 HTTP POST 请求向 Webhook 地址发送 JSON 数据。以下为 Python 示例代码: ```python import requests import json webhook_url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的密钥" headers = {"Content-Type": "application/json"} # 发送文本消息 data = { "msgtype": "text", "text": {"content": "服务器 CPU 使用率超过 90%!请及时处理!"} } response = requests.post(webhook_url, headers=headers, data=json.dumps(data)) print(response.text) # 返回结果校验 ``` **支持的消息类型** | 类型 | 说明 | JSON 关键字段 | |------------|--------------------------|-------------------------| | 文本 | 纯文本,可@群成员 | `text.content` | | Markdown | 支持表格、代码块等格式 | `markdown.content` | | 图片 | 需先上传获取媒体文件 ID | `image.media_id` | | 文件 | 通过临时接口上传文件 | `file.media_id` | **步骤 3:安全配置** - 限制消息频率(默认每分钟最多 20 条) - 敏感操作建议在服务端封装 API,避免前端暴露密钥。 #### 三、典型应用场景 1. **系统监控报警**:推送服务器异常、数据库告警等。 2. **自动化任务通知**:如定时脚本执行结果反馈。 3. **协同办公提醒**:项目进度更新、会议提醒等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值