当前位置:首页 » 《随便一记》 » 正文

JAVA-实现接入企业微信发送消息(最详细代码讲解!)

26 人参与  2022年09月22日 19:22  分类 : 《随便一记》  评论

点击全文阅读


1.通过应用发送消息

2.通过群机器人发送群消息

要清楚几个概念

使用企业微信管理员登录到控制台
企业微信后台管理地址

1.CorpId

这个是每个企业独有的企业ID
在这里插入图片描述

2.agentId 和 secret

agentId 相当于是应用ID,secret就理解成key
可以自己创建个应用,然后绑定到相关部门或者具体到人
在这里插入图片描述
在这里插入图片描述
知道这三个概念后,就可以通过SDK发送企业微信消息了

1.引入依赖

        <dependency>            <groupId>com.github.binarywang</groupId>            <artifactId>weixin-java-cp</artifactId>            <version>3.7.0</version>        </dependency>

2.添加固定写法的代码

2.1.增加config类,自己新增个config包写到里面

在这里插入图片描述

package com.linkyoyo.weatherpredict.config;import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;import org.springframework.stereotype.Component;/** * @author GuoZiXuan * @date 2022/06/13 14:45 */@Data@AllArgsConstructor@NoArgsConstructor@Builder@Componentpublic class AppConfig {    /**     * 设置微信企业应用的AgentId     */    private Integer agentId;    /**     * 设置微信企业应用的Secret     */    private String secret;    /**     * 设置微信企业号的token     */    private String token;    /**     * 设置微信企业号的EncodingAESKey     */    private String aesKey;}
package com.linkyoyo.weatherpredict.config;import com.linkyoyo.weatherpredict.handler.*;import com.google.common.collect.Lists;import com.google.common.collect.Maps;import lombok.val;import me.chanjar.weixin.common.api.WxConsts;import me.chanjar.weixin.cp.api.WxCpService;import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;import me.chanjar.weixin.cp.constant.WxCpConsts;import me.chanjar.weixin.cp.message.WxCpMessageRouter;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.util.List;import java.util.Map;import java.util.stream.Collectors;/** * @author Binary Wang(https://github.com/binarywang) *///@Configuration//@EnableConfigurationProperties(WxCpProperties.class)@Componentpublic class WxCpConfiguration {    private LogHandler logHandler;    private NullHandler nullHandler;    private LocationHandler locationHandler;    private MenuHandler menuHandler;    private MsgHandler msgHandler;    private UnsubscribeHandler unsubscribeHandler;    private SubscribeHandler subscribeHandler;    private WxCpProperties properties;    private static Map<Integer, WxCpMessageRouter> routers = Maps.newHashMap();    private static Map<Integer, WxCpService> cpServices = Maps.newHashMap();    @Autowired    public WxCpConfiguration(LogHandler logHandler, NullHandler nullHandler, LocationHandler locationHandler,                             MenuHandler menuHandler, MsgHandler msgHandler, UnsubscribeHandler unsubscribeHandler,                             SubscribeHandler subscribeHandler, WxCpProperties properties) {        this.logHandler = logHandler;        this.nullHandler = nullHandler;        this.locationHandler = locationHandler;        this.menuHandler = menuHandler;        this.msgHandler = msgHandler;        this.unsubscribeHandler = unsubscribeHandler;        this.subscribeHandler = subscribeHandler;        this.properties = properties;    }    public static Map<Integer, WxCpMessageRouter> getRouters() {        return routers;    }    public WxCpService getCpService(Integer agentId, String secret, String corpId) {        AppConfig appConfig = AppConfig.builder()                .agentId(agentId)                .secret(secret)                .build();        List<AppConfig> list = Lists.newArrayList();        list.add(appConfig);        properties.setAppConfigs(list);        properties.setCorpId(corpId);        cpServices = this.properties.getAppConfigs().stream().map(a -> {            val configStorage = new WxCpDefaultConfigImpl();            configStorage.setCorpId(this.properties.getCorpId());            configStorage.setAgentId(a.getAgentId());            configStorage.setCorpSecret(a.getSecret());            configStorage.setToken(a.getToken());            configStorage.setAesKey(a.getAesKey());            val service = new WxCpServiceImpl();            service.setWxCpConfigStorage(configStorage);            routers.put(a.getAgentId(), this.newRouter(service));            return service;        }).collect(Collectors.toMap(service -> service.getWxCpConfigStorage().getAgentId(), a -> a));        return cpServices.get(agentId);    }    private WxCpMessageRouter newRouter(WxCpService wxCpService) {        final val newRouter = new WxCpMessageRouter(wxCpService);        // 记录所有事件的日志 (异步执行)        newRouter.rule().handler(this.logHandler).next();        // 自定义菜单事件        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)            .event(WxConsts.MenuButtonType.CLICK).handler(this.menuHandler).end();        // 点击菜单链接事件(这里使用了一个空的处理器,可以根据自己需要进行扩展)        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)            .event(WxConsts.MenuButtonType.VIEW).handler(this.nullHandler).end();        // 关注事件        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)            .event(WxConsts.EventType.SUBSCRIBE).handler(this.subscribeHandler)            .end();        // 取消关注事件        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)            .event(WxConsts.EventType.UNSUBSCRIBE)            .handler(this.unsubscribeHandler).end();        // 上报地理位置事件        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)            .event(WxConsts.EventType.LOCATION).handler(this.locationHandler)            .end();        // 接收地理位置消息        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION)            .handler(this.locationHandler).end();        // 扫码事件(这里使用了一个空的处理器,可以根据自己需要进行扩展)        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)            .event(WxConsts.EventType.SCAN).handler(this.nullHandler).end();        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)            .event(WxCpConsts.EventType.CHANGE_CONTACT).handler(new ContactChangeHandler()).end();        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)            .event(WxCpConsts.EventType.ENTER_AGENT).handler(new EnterAgentHandler()).end();        // 默认        newRouter.rule().async(false).handler(this.msgHandler).end();        return newRouter;    }}
package com.linkyoyo.weatherpredict.config;import com.linkyoyo.weatherpredict.util.JsonUtils;import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;import org.springframework.stereotype.Component;import java.util.List;@Data@AllArgsConstructor@NoArgsConstructor@Builder@Componentpublic class WxCpProperties {  /**   * 设置微信企业号的corpId   */  private String corpId;  private List<AppConfig> appConfigs;  @Override  public String toString() {    return JsonUtils.toJson(this);  }}

2.2.增加builder类,自己新增个builder包写到里面

在这里插入图片描述

package com.linkyoyo.weatherpredict.builder;import me.chanjar.weixin.cp.api.WxCpService;import me.chanjar.weixin.cp.bean.WxCpXmlMessage;import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** *  @author Binary Wang(https://github.com/binarywang) */public abstract class AbstractBuilder {  protected final Logger logger = LoggerFactory.getLogger(getClass());  /**   * 创建WxCpXmlOutMessage信息   * @param content   * @param wxMessage   * @param service   * @return   */  public abstract WxCpXmlOutMessage build(String content, WxCpXmlMessage wxMessage, WxCpService service);}
package com.linkyoyo.weatherpredict.builder;import me.chanjar.weixin.cp.api.WxCpService;import me.chanjar.weixin.cp.bean.WxCpXmlMessage;import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;import me.chanjar.weixin.cp.bean.WxCpXmlOutTextMessage;/** *  @author Binary Wang(https://github.com/binarywang) */public class TextBuilder extends AbstractBuilder {  @Override  public WxCpXmlOutMessage build(String content, WxCpXmlMessage wxMessage,                                 WxCpService service) {    WxCpXmlOutTextMessage m = WxCpXmlOutMessage.TEXT().content(content)        .fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName())        .build();    return m;  }}

2.3 增加handle类,放在handler包下

在这里插入图片描述

package com.linkyoyo.weatherpredict.handler;import me.chanjar.weixin.cp.message.WxCpMessageHandler;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * @author Binary Wang(https://github.com/binarywang) */public abstract class AbstractHandler implements WxCpMessageHandler {  protected Logger logger = LoggerFactory.getLogger(getClass());}
package com.linkyoyo.weatherpredict.handler;/** * @author Binary Wang(https://github.com/binarywang) */public abstract class AbstractScanHandler extends AbstractHandler {}
package com.linkyoyo.weatherpredict.handler;import com.linkyoyo.weatherpredict.builder.TextBuilder;import com.linkyoyo.weatherpredict.util.JsonUtils;import me.chanjar.weixin.common.session.WxSessionManager;import me.chanjar.weixin.cp.api.WxCpService;import me.chanjar.weixin.cp.bean.WxCpXmlMessage;import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;import org.springframework.stereotype.Component;import java.util.Map;/** * 通讯录变更事件处理器. * * @author Binary Wang(https://github.com/binarywang) */@Componentpublic class ContactChangeHandler extends AbstractHandler {  @Override  public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,                                  WxSessionManager sessionManager) {    String content = "收到通讯录变更事件,内容:" + JsonUtils.toJson(wxMessage);    this.logger.info(content);    return new TextBuilder().build(content, wxMessage, cpService);  }}
package com.linkyoyo.weatherpredict.handler;import lombok.extern.slf4j.Slf4j;import me.chanjar.weixin.common.error.WxErrorException;import me.chanjar.weixin.common.session.WxSessionManager;import me.chanjar.weixin.cp.api.WxCpService;import me.chanjar.weixin.cp.bean.WxCpXmlMessage;import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;import java.util.Map;/** * <pre> * * Created by Binary Wang on 2018/8/27. * </pre> * * @author <a href="https://github.com/binarywang">Binary Wang</a> */@Slf4jpublic class EnterAgentHandler extends AbstractHandler {    private static final int TEST_AGENT = 1000002;    @Override    public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService wxCpService, WxSessionManager sessionManager) throws WxErrorException {        // do something        return null;    }}
package com.linkyoyo.weatherpredict.handler;import com.linkyoyo.weatherpredict.builder.TextBuilder;import me.chanjar.weixin.common.api.WxConsts;import me.chanjar.weixin.common.session.WxSessionManager;import me.chanjar.weixin.cp.api.WxCpService;import me.chanjar.weixin.cp.bean.WxCpXmlMessage;import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;import org.springframework.stereotype.Component;import java.util.Map;/** * @author Binary Wang(https://github.com/binarywang) */@Componentpublic class LocationHandler extends AbstractHandler {  @Override  public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,                                  WxSessionManager sessionManager) {    if (wxMessage.getMsgType().equals(WxConsts.XmlMsgType.LOCATION)) {      //TODO 接收处理用户发送的地理位置消息      try {        String content = "感谢反馈,您的的地理位置已收到!";        return new TextBuilder().build(content, wxMessage, null);      } catch (Exception e) {        this.logger.error("位置消息接收处理失败", e);        return null;      }    }    //上报地理位置事件    this.logger.info("\n上报地理位置,纬度 : {}\n经度 : {}\n精度 : {}",        wxMessage.getLatitude(), wxMessage.getLongitude(), String.valueOf(wxMessage.getPrecision()));    //TODO  可以将用户地理位置信息保存到本地数据库,以便以后使用    return null;  }}
package com.linkyoyo.weatherpredict.handler;import com.linkyoyo.weatherpredict.util.JsonUtils;import me.chanjar.weixin.common.session.WxSessionManager;import me.chanjar.weixin.cp.api.WxCpService;import me.chanjar.weixin.cp.bean.WxCpXmlMessage;import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;import org.springframework.stereotype.Component;import java.util.Map;/** *  @author Binary Wang(https://github.com/binarywang) */@Componentpublic class LogHandler extends AbstractHandler {  @Override  public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,                                  WxSessionManager sessionManager) {    this.logger.info("\n接收到请求消息,内容:{}", JsonUtils.toJson(wxMessage));    return null;  }}
package com.linkyoyo.weatherpredict.handler;import me.chanjar.weixin.common.api.WxConsts.MenuButtonType;import me.chanjar.weixin.common.session.WxSessionManager;import me.chanjar.weixin.cp.api.WxCpService;import me.chanjar.weixin.cp.bean.WxCpXmlMessage;import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;import org.springframework.stereotype.Component;import java.util.Map;/** * @author Binary Wang(https://github.com/binarywang) */@Componentpublic class MenuHandler extends AbstractHandler {  @Override  public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,                                  WxSessionManager sessionManager) {    String msg = String.format("type:%s, event:%s, key:%s",        wxMessage.getMsgType(), wxMessage.getEvent(),        wxMessage.getEventKey());    if (MenuButtonType.VIEW.equals(wxMessage.getEvent())) {      return null;    }    return WxCpXmlOutMessage.TEXT().content(msg)        .fromUser(wxMessage.getToUserName()).toUser(wxMessage.getFromUserName())        .build();  }}
package com.linkyoyo.weatherpredict.handler;import com.linkyoyo.weatherpredict.builder.TextBuilder;import com.linkyoyo.weatherpredict.util.JsonUtils;import me.chanjar.weixin.common.api.WxConsts;import me.chanjar.weixin.common.session.WxSessionManager;import me.chanjar.weixin.cp.api.WxCpService;import me.chanjar.weixin.cp.bean.WxCpXmlMessage;import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;import org.springframework.stereotype.Component;import java.util.Map;/** * @author Binary Wang(https://github.com/binarywang) */@Componentpublic class MsgHandler extends AbstractHandler {  @Override  public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,                                  WxSessionManager sessionManager) {    if (!wxMessage.getMsgType().equals(WxConsts.XmlMsgType.EVENT)) {      //TODO 可以选择将消息保存到本地    }    //TODO 组装回复消息    String content = "收到信息内容:" + JsonUtils.toJson(wxMessage);    return new TextBuilder().build(content, wxMessage, cpService);  }}
package com.linkyoyo.weatherpredict.handler;import me.chanjar.weixin.common.session.WxSessionManager;import me.chanjar.weixin.cp.api.WxCpService;import me.chanjar.weixin.cp.bean.WxCpXmlMessage;import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;import org.springframework.stereotype.Component;import java.util.Map;/** * @author Binary Wang(https://github.com/binarywang) */@Componentpublic class NullHandler extends AbstractHandler {  @Override  public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,                                  WxSessionManager sessionManager) {    return null;  }}
package com.linkyoyo.weatherpredict.handler;import com.linkyoyo.weatherpredict.builder.TextBuilder;import me.chanjar.weixin.common.error.WxErrorException;import me.chanjar.weixin.common.session.WxSessionManager;import me.chanjar.weixin.cp.api.WxCpService;import me.chanjar.weixin.cp.bean.WxCpUser;import me.chanjar.weixin.cp.bean.WxCpXmlMessage;import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;import org.springframework.stereotype.Component;import java.util.Map;/** * @author Binary Wang(https://github.com/binarywang) */@Componentpublic class SubscribeHandler extends AbstractHandler {  @Override  public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,                                  WxSessionManager sessionManager) throws WxErrorException {    this.logger.info("新关注用户 OPENID: " + wxMessage.getFromUserName());    // 获取微信用户基本信息    WxCpUser userWxInfo = cpService.getUserService().getById(wxMessage.getFromUserName());    if (userWxInfo != null) {      // TODO 可以添加关注用户到本地    }    WxCpXmlOutMessage responseResult = null;    try {      responseResult = handleSpecial(wxMessage);    } catch (Exception e) {      this.logger.error(e.getMessage(), e);    }    if (responseResult != null) {      return responseResult;    }    try {      return new TextBuilder().build("感谢关注", wxMessage, cpService);    } catch (Exception e) {      this.logger.error(e.getMessage(), e);    }    return null;  }  /**   * 处理特殊请求,比如如果是扫码进来的,可以做相应处理   */  private WxCpXmlOutMessage handleSpecial(WxCpXmlMessage wxMessage) {    //TODO    return null;  }}
package com.linkyoyo.weatherpredict.handler;import me.chanjar.weixin.common.session.WxSessionManager;import me.chanjar.weixin.cp.api.WxCpService;import me.chanjar.weixin.cp.bean.WxCpXmlMessage;import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;import org.springframework.stereotype.Component;import java.util.Map;/** * @author Binary Wang(https://github.com/binarywang) */@Componentpublic class UnsubscribeHandler extends AbstractHandler {  @Override  public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, Map<String, Object> context, WxCpService cpService,                                  WxSessionManager sessionManager) {    String openId = wxMessage.getFromUserName();    this.logger.info("取消关注用户 OPENID: " + openId);    // TODO 可以更新本地数据库为取消关注状态    return null;  }}

2.4 增加表及实体类,用于存应用的信息

这里使用的是postresql,字段一样就行,增加该表的原因是,后面发送消息需要传入应用的agentId和secret还有公司Id,所以需要维护起来

CREATE TABLE "public"."tbl_department" (  "id" int4 NOT NULL DEFAULT nextval('tbl_department_id_seq'::regclass),  "agent_id" int4 NOT NULL,  "secret" varchar(255) COLLATE "pg_catalog"."default" NOT NULL,  "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL,  "corp_id" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,  "create_time" timestamp(6),  "update_time" timestamp(6),  CONSTRAINT "tbl_department_pkey" PRIMARY KEY ("id"));ALTER TABLE "public"."tbl_department"   OWNER TO "hzcloud_master";COMMENT ON COLUMN "public"."tbl_department"."agent_id" IS '微信-应用-agentId';COMMENT ON COLUMN "public"."tbl_department"."secret" IS '微信-应用-secret';COMMENT ON COLUMN "public"."tbl_department"."name" IS '微信-应用(部门)-名称';COMMENT ON COLUMN "public"."tbl_department"."corp_id" IS '微信-企业ID';COMMENT ON COLUMN "public"."tbl_department"."create_time" IS '创建时间';COMMENT ON COLUMN "public"."tbl_department"."update_time" IS '修改时间';COMMENT ON TABLE "public"."tbl_department" IS '微信-部门表';
package com.linkyoyo.weatherpredict.entity;import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;import lombok.experimental.Accessors;import org.hibernate.annotations.DynamicInsert;import org.hibernate.annotations.DynamicUpdate;import org.springframework.data.annotation.CreatedDate;import org.springframework.data.annotation.LastModifiedDate;import org.springframework.data.jpa.domain.support.AuditingEntityListener;import javax.persistence.*;import java.time.LocalDateTime;/** * @author ZhangWeiXiang * @date 2021/11/15 14:19 * 微信部门 */@Data@Accessors(chain = true)@NoArgsConstructor@AllArgsConstructor@Builder@DynamicInsert@DynamicUpdate@EntityListeners(AuditingEntityListener.class)@Entity@Table(name = "tbl_department")public class Department {    /**     * 主键     */    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    private Integer id;    /**     * 每个应用都有唯一的agentid     */    @Column(name = "agent_id")    private Integer agentId;    /**     * 独立的访问密钥     */    @Column(name = "secret")    private String secret;    /**     * 应用名称     */    private String name;    /**     * 企业ID     */    @Column(name = "corp_id")    private String corpId;    /**     * 创建时间     */    @CreatedDate    @Column(name = "create_time")    private LocalDateTime createTime;    /**     * 修改时间     */    @LastModifiedDate    @Column(name = "update_time")    private LocalDateTime updateTime;}

2.5 增加工具类

package com.linkyoyo.weatherpredict.util;import com.fasterxml.jackson.annotation.JsonInclude.Include;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.SerializationFeature;/** *  @author Binary Wang(https://github.com/binarywang) */public class JsonUtils {  private static final ObjectMapper JSON = new ObjectMapper();  static {    JSON.setSerializationInclusion(Include.NON_NULL);    JSON.configure(SerializationFeature.INDENT_OUTPUT, Boolean.TRUE);  }  public static String toJson(Object obj) {    try {      return JSON.writeValueAsString(obj);    } catch (JsonProcessingException e) {      e.printStackTrace();    }    return null;  }}


下面就是我自己封装后的写法了,这里主要有两个,发送普通消息和发送文件消息

1.引入hutool工具类的依赖,我后面有用到

     <dependency>            <groupId>cn.hutool</groupId>            <artifactId>hutool-all</artifactId>            <version>4.6.2</version>        </dependency>

2.编写文件转换方法,就是将上传的文件暂存

2.1新增类FileStoreService
package com.linkyoyo.weatherpredict.service;import org.springframework.web.multipart.MultipartFile;import java.io.File;public interface FileStoreService {    File upload(MultipartFile multipartFile);}// A code blockvar foo = 'bar';
2.2编写实现类
package com.linkyoyo.weatherpredict.service.impl;import cn.hutool.core.io.FileUtil;import com.linkyoyo.weatherpredict.exception.BizException;import com.linkyoyo.weatherpredict.properties.LinkyoyoProperties;import com.linkyoyo.weatherpredict.result.CodeMsg;import com.linkyoyo.weatherpredict.service.FileStoreService;import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import org.springframework.web.multipart.MultipartFile;import java.io.File;import java.io.IOException;@Service@Slf4j@Transactional@RequiredArgsConstructorpublic class FileStoreServiceImpl implements FileStoreService {    @Autowired    private LinkyoyoProperties linkyoyoProperties ;    @Override    public File upload(MultipartFile multipartFile) {        String  fileName = multipartFile.getOriginalFilename();        if(!FileUtil.exist(linkyoyoProperties.getPy().getWordPath()+ File.separator+"temporary"))            FileUtil.mkdir(linkyoyoProperties.getPy().getWordPath()+File.separator+"temporary") ;//linkyoyoProperties.getPy().getWordPath()  这个方法就是从我的配置类获取个路径,这个你可以自己设置成自己的本地某个路径就好        String path = linkyoyoProperties.getPy().getWordPath()+File.separator+"temporary"+File.separator;        if(!FileUtil.exist(path))            FileUtil.mkdir(path) ;        File file = FileUtil.touch(new File(path, fileName));        try {            multipartFile.transferTo(file);        } catch (IOException e) {            log.error("文件转存失败 :FileStoreService" + file.getAbsolutePath());            throw new BizException(CodeMsg.FILE_UPLOAD_ERROR.fillArgs("转存失败"));        }        return file;    }}
2.2编写接收类,主要是用于调用企业微信API后,转换为实体类用
package com.linkyoyo.weatherpredict.info;import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;@Data@Builder@AllArgsConstructor@NoArgsConstructorpublic class UserInfo {    private String userid;}

3.!重点来了,编写消息发送工具类

package com.linkyoyo.weatherpredict.util;import cn.hutool.http.HttpUtil;import com.alibaba.fastjson.JSONArray;import com.alibaba.fastjson.JSONObject;import com.linkyoyo.weatherpredict.config.WxCpConfiguration;import com.linkyoyo.weatherpredict.entity.Department;import com.linkyoyo.weatherpredict.exception.BizException;import com.linkyoyo.weatherpredict.info.UserInfo;import com.linkyoyo.weatherpredict.result.CodeMsg;import lombok.extern.slf4j.Slf4j;import me.chanjar.weixin.common.error.WxErrorException;import me.chanjar.weixin.cp.api.WxCpService;import me.chanjar.weixin.cp.bean.WxCpAgent;import me.chanjar.weixin.cp.bean.WxCpDepart;import me.chanjar.weixin.cp.bean.WxCpMessage;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.util.CollectionUtils;import java.io.File;import java.util.List;import java.util.Map;import java.util.stream.Collectors;@Component@Slf4jpublic class WxSendUtils {    @Autowired    private WxCpConfiguration wxCpConfiguration;    public void sendTextMsg(Department department, String msg)  throws Exception{        WxCpService cpService = wxCpConfiguration.getCpService(department.getAgentId(), department.getSecret(), department.getCorpId());        //拿到所有应用的名称和agentId        List<WxCpAgent> list = cpService.getAgentService().list();        if(CollectionUtils.isEmpty(list)){            throw new BizException(CodeMsg.API_CALL_ERROR.fillArgs("该应用不存在!"));        }        //获取到该应用下绑定的所有部门        List<WxCpDepart> wxCpDepartList = cpService.getDepartmentService().list(null);        //对该应用绑定的部门进行消息的发送        wxCpDepartList.forEach(wxCpDepart -> {            WxCpMessage wxCpMessage = WxCpMessage.TEXT()                    .agentId(department.getAgentId()) // 企业号应用ID                    .toParty(wxCpDepart.getId()+"")                    .content(msg)                    .build();            try {                cpService.messageSend(wxCpMessage);            } catch (WxErrorException e) {                log.info("微信告警发送报错: {}", e.getError());            }        });        //对该应用绑定的个人进行消息的发送        List<String> userInfos = getUseInfos(department.getCorpId(), department.getSecret(), department.getAgentId());        userInfos.forEach(userInfo -> {            WxCpMessage wxCpMessage = WxCpMessage.TEXT()                    .agentId(department.getAgentId()) // 企业号应用ID                    .toUser(userInfo)                    .content(msg)                    .build();            try {                cpService.messageSend(wxCpMessage);            } catch (WxErrorException e) {                log.info("微信告警发送报错: {}", e.getError());            }        });    }    public void sendFileMsg(Department department, File file) throws WxErrorException {        //调用资源上传接口并返回资源Id        String mediaId = getMediaId(department.getCorpId(), department.getSecret(), "file", file);        WxCpService cpService = wxCpConfiguration.getCpService(department.getAgentId(), department.getSecret(), department.getCorpId());        //拿到所有应用的名称和agentId        List<WxCpAgent> list = cpService.getAgentService().list();        if(CollectionUtils.isEmpty(list)){            throw new BizException(CodeMsg.API_CALL_ERROR.fillArgs("该应用不存在!"));        }        //获取到该应用下绑定的所有部门        List<WxCpDepart> wxCpDepartList = cpService.getDepartmentService().list(null);        //对该应用绑定的部门进行消息的发送        wxCpDepartList.forEach(wxCpDepart -> {            WxCpMessage wxCpMessage = WxCpMessage.FILE()                    .agentId(department.getAgentId()) // 企业号应用ID                    .toParty(wxCpDepart.getId()+"")                    .mediaId(mediaId)                    .build();            try {                cpService.messageSend(wxCpMessage);            } catch (WxErrorException e) {                log.info("微信告警发送报错: {}", e.getError());            }        });        //对该应用绑定的个人进行消息的发送        List<String> userInfos = getUseInfos(department.getCorpId(), department.getSecret(), department.getAgentId());        userInfos.forEach(userInfo -> {            WxCpMessage wxCpMessage = WxCpMessage.FILE()                    .agentId(department.getAgentId()) // 企业号应用ID                    .toUser(userInfo)                    .mediaId(mediaId)                    .build();            try {                cpService.messageSend(wxCpMessage);            } catch (WxErrorException e) {                log.info("微信告警发送报错: {}", e.getError());            }        });    }    /**     *     * @param corpid 企业ID     * @param corpsecret  Secret     * @param type 媒体文件类型:图片(image)、语音(voice)、视频(video),普通文件(file)     * @param file     * @throws Exception     */    public String getMediaId(String corpid, String corpsecret, String type,File file){        String token = null;        String mediaId = null;        //获取token        try {            String toKenBody = HttpUtil.createGet("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid="+corpid+"&corpsecret="+corpsecret)                    .execute().body();            JSONObject toKenObject = JSONObject.parseObject(toKenBody);            token = toKenObject.get("access_token").toString();        }catch (Exception e){            throw new BizException(CodeMsg.API_CALL_ERROR.fillArgs("企业微信 获取token接口 调用失败"));        }        try {            String body = HttpUtil.createPost("https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token="+token+"&type="+type)                    .form("media",file)                    .execute().body();            JSONObject jsonObject = JSONObject.parseObject(body);            mediaId = jsonObject.get("media_id").toString();        }catch (Exception e){            throw new BizException(CodeMsg.API_CALL_ERROR.fillArgs("企业微信 上传临时素材接口 调用失败"));        }        return mediaId;    }    public List<String> getUseInfos(String corpid, String corpsecret,Integer agentid){        try {            String body = HttpUtil.createGet("https://qyapi.weixin.qq.com/cgi-bin/agent/get?access_token="+getToKen(corpid,corpsecret)+"&agentid="+agentid)                    .execute().body();            JSONObject toKenObject = JSONObject.parseObject(body);            Map<String,Object> userinfo = (Map<String, Object>) toKenObject.get("allow_userinfos");            if(CollectionUtils.isEmpty(userinfo))                return null;            JSONArray user = (JSONArray)userinfo.get("user");            List<UserInfo> userInfos = user.toJavaList(UserInfo.class);            if(CollectionUtils.isEmpty(user))                return null;            return userInfos.stream().map(e->e.getUserid()).collect(Collectors.toList());        }catch (Exception e){            throw new BizException(CodeMsg.API_CALL_ERROR.fillArgs("企业微信 上传临时素材接口 调用失败"));        }    }    public String getToKen(String corpid, String corpsecret){        try {            String toKenBody = HttpUtil.createGet("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid="+corpid+"&corpsecret="+corpsecret)                    .execute().body();            JSONObject toKenObject = JSONObject.parseObject(toKenBody);            return toKenObject.get("access_token").toString();        }catch (Exception e){            throw new BizException(CodeMsg.API_CALL_ERROR.fillArgs("企业微信 获取token接口 调用失败"));        }    }}

代码讲解:普通消息的发送只需要传入四个重要信息,1.公司Id 2.agentId 3.secret 4.消息,而文件消息就有点不一样了,发送的文件必须先调用上传临时文件接口,然后会返回一个mediaId,然后发送文件消息的时候就传这个Id,这样就实现了文件消息的发送。
还有个点就是,应用既可以绑部门,也可以绑个人,所以可以通过方法先获取到该应用下绑定的部门或个人,然后再去往这个部门下的所有人去发消息,或去发个人。

4.编写测试类
package com.linkyoyo.weatherpredict.controller;import com.linkyoyo.weatherpredict.entity.Department;import com.linkyoyo.weatherpredict.result.R;import com.linkyoyo.weatherpredict.service.FileStoreService;import com.linkyoyo.weatherpredict.util.WxSendUtils;import lombok.RequiredArgsConstructor;import me.chanjar.weixin.common.error.WxErrorException;import org.springframework.web.bind.annotation.*;import org.springframework.web.multipart.MultipartFile;@RestController@RequiredArgsConstructor@RequestMapping("/sendWx")public class SendWxController {    private final WxSendUtils wxSendUtils;    private final FileStoreService fileStoreService;    //发送文件消息    @PostMapping(value = "/FileMsg", headers = "Content-Type=multipart/form-data")    public R FileMsg(@RequestPart("file") MultipartFile file) throws WxErrorException {        Department department = new Department();        department.setName("消息推送");        department.setCorpId("***");        department.setAgentId(***);        department.setSecret("***");        wxSendUtils.sendFileMsg(department, fileStoreService.upload(file));        return R.ok();    }    //发送普通文本消息    @PostMapping(value = "/TextMsg")    public R TextMsg(String msg) throws Exception {        Department department = new Department();        department.setName("消息推送");         department.setCorpId("***");        department.setAgentId(***);        department.setSecret("***");        wxSendUtils.sendTextMsg(department, msg);        return R.ok();    }    @PostMapping(value = "/getUse")    public R getUse() throws Exception {        Department department = new Department();        department.setName("消息推送");        department.setCorpId("***");        department.setAgentId(***);        department.setSecret("***");        wxSendUtils.getUseInfos(department.getCorpId(),department.getSecret(),department.getAgentId());        return R.ok();    }}

发送群消息

1.创建群机器人

在这里插入图片描述
在这里插入图片描述
主要就是通过这个地址去发送消息的

相关API地址:https://developer.work.weixin.qq.com/document/path/91770


点击全文阅读


本文链接:http://zhangshiyu.com/post/45035.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1