目前公司需要在培训管理系统中向企业微信发送通知。通知类型为文本。
现在的项目是maven管理的多模块形式,所以考虑新增一个模块,在模块中对外提供公共方法,调用企业微信weixin-java-cp中提供的方法实现消息发送。该模块打包为jar集成到主项目下,后续如果多项目共用的话考虑增加消息处理服务平台应用,用来处理短信,微信等消息内容。
做模块开发之前,先参考了官方提供的springboot实现的demo,地址如下:
企业微信调用官方demo
附上相关资料:
主动发送消息
官方-企业微信消息类型及格式
属性类用来获取企业微信的配置信息:
get、set使用了lombok
@Getter
@Setter
@ConfigurationProperties(prefix = "wechat.cp")
public class WxCpProperties {
/**
* 设置微信企业号的corpId
*/
private String corpId;
private List<AppConfig> appConfigs;
@Getter
@Setter
public static class AppConfig {
/**
* 设置微信企业应用的AgentId
*/
private Integer agentId;
/**
* 设置微信企业应用的Secret
*/
private String secret;
/**
* 设置微信企业号的token
*/
private String token;
/**
* 设置微信企业号的EncodingAESKey
*/
private String aesKey;
}
@Override
public String toString() {
return JsonUtils.toJson(this);
}
}
@Configuration
@EnableConfigurationProperties(WxCpProperties.class)
public 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 static WxCpService getCpService(Integer agentId)
{
return cpServices.get(agentId);
}
@PostConstruct
public void initServices()
{
cpServices = this.properties.getAppConfigs().stream().map(a -> {
val configStorage = new WxCpInMemoryConfigStorage();
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));
}
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;
}
}
@Service("WxMessageServce")
public class WxMessageServce
{
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private WxCpProperties wxCpProperties;
/***
* 根据指定的用户id发送指定文本消息
* @param content
* @param userId 消息接收者id,企业微信中管理员添加用户时使用的唯一标识,特殊情况:指定为@all,则向关注该企业应用的全部成员发送
* @return WxCpMessageSendResult
* @throws Exception
* @throws ValidateException
*/
public WxCpMessageSendResult sendTextMsg(String content, String userId) throws ValidateException, Exception
{
WxCpMessageSendResult result = null;
AppConfig appConfig = wxCpProperties.getAppConfigs().get(0);
this.logger.debug("发送消息服务器配置:{}", appConfig.toString());
WxCpMessage message = WxCpMessage.TEXT().agentId(appConfig.getAgentId()).toUser(userId).content(content).build();
this.logger.info("发送消息:{}", content);
final WxCpService wxCpService = WxCpConfiguration.getCpService(appConfig.getAgentId());
try
{
result = wxCpService.messageSend(message);
}
catch (WxErrorException e)
{
logger.error("发送消息异常", e);
throw new ValidateException("发送消息失败");
}
return result;
}
/***
* 向指定的多个用户发送消息
* @param content 消息内容,最长不超过2048个字节
* @param userList 成员ID列表(消息接收者,最多支持1000个)。
* @return WxCpMessageSendResult
* @throws Exception
*/
public WxCpMessageSendResult sendTextMsg(String content, List<String> userList) throws ValidateException, Exception
{
if (userList != null && userList.size() > 1000)
{
throw new ValidateException("消息接收者,最多支持1000个");
}
String user = String.join("|", userList);
return sendTextMsg(content, user);
}
/***
* 向超过1000个用户发送消息
* @param content 消息内容,最长不超过2048个字节
* @param userList 成员ID列表(消息接收者)。
* @return
* @throws ValidateException
* @throws Exception
*/
public WxCpMessageSendResult sendTextMsgMoreThanLimit(String content, List<String> userList) throws ValidateException, Exception
{
WxCpMessageSendResult result = new WxCpMessageSendResult();
int max = userList.size() % 1000 > 0 ? userList.size() / 1000 + 1 : userList.size();
StringJoiner invaliduser = new StringJoiner("|");
StringJoiner errMsg = new StringJoiner("|");
for (int i = 0; i < max; i++)
{
WxCpMessageSendResult wxCpMessageSendResult = sendTextMsg(content, userList.subList(1000 * i, max - i == 1 ? userList.size() % 1000 : 999 * i));
if (!StringUtils.isBlank(wxCpMessageSendResult.getInvalidUser()))
invaliduser.add(wxCpMessageSendResult.getInvalidUser());
if (!"0".equals(wxCpMessageSendResult.getErrCode()))
{
result.setErrCode(wxCpMessageSendResult.getErrCode());
}
if (!"ok".equals(wxCpMessageSendResult.getErrMsg()))
{
errMsg.add(wxCpMessageSendResult.getErrMsg());
}
}
result.setErrCode(0);
result.setInvalidUser(invaliduser.toString());
result.setErrMsg(errMsg.length() > 1 ? errMsg.toString() : "ok");
return result;
}
}