Spring Cloud 项目集成企业微信应用推送消息

时间:2025-02-23 07:48:52

Spring Cloud 项目集成企业微信应用推送消息


1. 企业微信管理员后台创建应用
1.1 创建应用
  1. 登录企业微信管理后台:https://work.weixin.qq.com/
  2. 进入 应用管理自建应用创建应用
    • 填写应用名称(如“消息推送服务”)。
    • 选择可见范围(指定接收消息的成员或部门)。
  3. 创建完成后,记录以下信息:
    • 企业 ID(CorpId):企业微信后台首页顶部显示。
    • 应用 AgentId:应用详情页中查看。
    • 应用 Secret:应用详情页中点击“查看Secret”获取。
1.2 配置域名与可信IP
  1. 配置回调域名(可选)
    • 进入应用详情页 → 接收消息 → 配置接收消息的服务器URL(需公网可访问)。
  2. 配置可信IP(必填)
    • 进入 我的企业安全与管理可信IP,添加项目部署的服务器公网IP。
    • 确保企业微信API调用来源IP在此白名单中。

2. 项目引入 SDK
2.1 添加依赖

pom.xml 中添加以下依赖:

<dependency>
    <groupId>cn.felord</groupId>
    <artifactId>wecom-sdk</artifactId>
    <version>1.3.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.2 初始化配置
  1. 配置企业微信参数
    application.yml 中配置:

    wecom:
      corp-id: your_corp_id        # 企业ID
      agent-id: your_agent_id      # 应用AgentId
      secret: your_secret          # 应用Secret
    
  2. 配置 Redis 缓存
    application.yml 中配置 Redis:

    spring:
      redis:
        host: localhost
        port: 6379
        password: your_redis_password
        database: 0
    
  3. 创建配置类

    @Configuration
    @ConfigurationProperties(prefix = "wecom")
    public class WeComConfig {
        private String corpId;
        private String agentId;
        private String secret;
        // Getters & Setters
    }
    
2.3 初始化 SDK 并集成缓存
@Configuration
public class WeComSdkConfig {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Bean
    public WeComTokenCacheable weComTokenCacheable() {
        return new RedisWeComTokenCacheable(redisTemplate);
    }

    @Bean
    public WorkWeChatApi workWeChatApi(WeComTokenCacheable tokenCacheable, WeComConfig config) {
        WorkWeChatApi api = new WorkWeChatApi(tokenCacheable);
        api.setCorpId(config.getCorpId());
        api.setAgentId(config.getAgentId());
        api.setSecret(config.getSecret());
        return api;
    }
}

// Redis 缓存实现
public class RedisWeComTokenCacheable implements WeComTokenCacheable {
    private final RedisTemplate<String, String> redisTemplate;

    public RedisWeComTokenCacheable(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public void putToken(String key, String token, long expire) {
        redisTemplate.opsForValue().set(key, token, expire, TimeUnit.SECONDS);
    }

    @Override
    public String getToken(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    @Override
    public void removeToken(String key) {
        redisTemplate.delete(key);
    }
}

3. 编写工具类
3.1 消息推送工具类
@Service
public class WeComMessageService {

    @Autowired
    private WorkWeChatApi workWeChatApi;

    /**
     * 发送文本消息
     * @param toUser 接收人ID(多个用 | 分隔)
     * @param content 消息内容
     */
    public void sendTextMessage(String toUser, String content) {
        TextMessage message = new TextMessage();
        message.setTouser(toUser);
        message.setMsgtype("text");
        message.setAgentid(workWeChatApi.getAgentId());
        message.setText(new TextMessage.Text(content));

        MessageResponse response = workWeChatApi.message().send(message);
        if (response.getErrcode() != 0) {
            throw new RuntimeException("消息发送失败: " + response.getErrmsg());
        }
    }

    /**
     * 发送图文消息
     * @param toUser 接收人ID
     * @param title 标题
     * @param description 描述
     * @param url 跳转链接
     */
    public void sendNewsMessage(String toUser, String title, String description, String url) {
        NewsMessage message = new NewsMessage();
        message.setTouser(toUser);
        message.setMsgtype("news");
        message.setAgentid(workWeChatApi.getAgentId());

        NewsMessage.Article article = new NewsMessage.Article();
        article.setTitle(title);
        article.setDescription(description);
        article.setUrl(url);
        message.setNews(new NewsMessage.News(Collections.singletonList(article)));

        MessageResponse response = workWeChatApi.message().send(message);
        if (response.getErrcode() != 0) {
            throw new RuntimeException("图文消息发送失败: " + response.getErrmsg());
        }
    }
}

4. 使用示例
4.1 控制器调用
@RestController
@RequestMapping("/wecom")
public class WeComController {

    @Autowired
    private WeComMessageService messageService;

    @PostMapping("/send-text")
    public String sendText(@RequestParam String toUser, @RequestParam String content) {
        messageService.sendTextMessage(toUser, content);
        return "文本消息发送成功!";
    }

    @PostMapping("/send-news")
    public String sendNews(@RequestParam String toUser, 
                           @RequestParam String title,
                           @RequestParam String desc,
                           @RequestParam String url) {
        messageService.sendNewsMessage(toUser, title, desc, url);
        return "图文消息发送成功!";
    }
}
4.2 单元测试
@SpringBootTest
public class WeComMessageTest {

    @Autowired
    private WeComMessageService messageService;

    @Test
    void testSendTextMessage() {
        messageService.sendTextMessage("User1|User2", "测试文本消息");
    }

    @Test
    void testSendNewsMessage() {
        messageService.sendNewsMessage("User1", 
            "Spring Cloud集成指南", 
            "点击查看详细文档", 
            "https://your-domain.com/docs");
    }
}

5. 测试与验证
5.1 本地测试
  1. 启动项目,访问 http://localhost:8080/wecom/send-text?toUser=User1&content=Hello
  2. 检查企业微信客户端,目标用户应收到消息。
5.2 生产验证
  1. 部署到服务器后,确保服务器IP已加入企业微信可信IP列表。
  2. 调用API接口,验证消息是否正常推送。
  3. 查看日志,确认无权限或网络错误。

6. 注意事项
  1. Token 缓存:Access Token 有效期为2小时,需缓存避免频繁刷新。
  2. 频率限制:企业微信API调用频率限制为2000次/分钟,需控制发送频率。
  3. 异常处理:捕获 MessageResponse 中的 errcode,处理如 40001(无效Secret)等错误。
  4. 安全加固:敏感配置(如Secret)建议存储于配置中心(如Nacos)或加密处理。

通过以上步骤,可完整实现 Spring Cloud 项目与企业微信应用的消息推送集成。