1. 准备工作

首先需要获取微信公众号的开发配置:

  • 公众号AppID和AppSecret

  • 服务器配置Token

  • 服务器IP白名单

2. 使用官方SDK - Weixin-Java-Tools

添加依赖

xml

<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>weixin-java-mp</artifactId>
    <version>4.4.0</version>
</dependency>

配置类

java

@Configuration
public class WeChatMpConfig {
    
    @Value("${wechat.mp.appId}")
    private String appId;
    
    @Value("${wechat.mp.secret}")
    private String secret;
    
    @Value("${wechat.mp.token}")
    private String token;
    
    @Bean
    public WxMpService wxMpService() {
        WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl();
        config.setAppId(appId);
        config.setSecret(secret);
        config.setToken(token);
        
        WxMpService service = new WxMpServiceImpl();
        service.setWxMpConfigStorage(config);
        return service;
    }
}

3. 模板消息推送

java

@Service
public class WeChatMessageService {
    
    @Autowired
    private WxMpService wxMpService;
    
    /**
     * 发送模板消息
     */
    public void sendTemplateMessage(String openId, String templateId, 
                                  Map<String, String> data, String url) {
        try {
            WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                    .toUser(openId)
                    .templateId(templateId)
                    .url(url)
                    .build();
            
            // 添加模板数据
            data.forEach((key, value) -> {
                templateMessage.addData(new WxMpTemplateData(key, value, "#173177"));
            });
            
            // 发送消息
            wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
            
        } catch (WxErrorException e) {
            throw new RuntimeException("微信模板消息发送失败", e);
        }
    }
    
    /**
     * 示例:发送订单通知
     */
    public void sendOrderNotification(String openId, String orderNo, 
                                    String productName, String amount) {
        Map<String, String> data = new HashMap<>();
        data.put("first", "您好,您有新的订单通知");
        data.put("keyword1", orderNo);
        data.put("keyword2", productName);
        data.put("keyword3", amount);
        data.put("remark", "感谢您的购买!");
        
        sendTemplateMessage(openId, "YOUR_TEMPLATE_ID", data, "https://your-domain.com/order/" + orderNo);
    }
}

4. 客服消息推送

java

@Service
public class CustomerServiceMessage {
    
    @Autowired
    private WxMpService wxMpService;
    
    /**
     * 发送文本客服消息
     */
    public void sendTextMessage(String openId, String content) {
        try {
            WxMpKefuMessage message = WxMpKefuMessage.TEXT()
                    .toUser(openId)
                    .content(content)
                    .build();
            
            wxMpService.getKefuService().sendKefuMessage(message);
            
        } catch (WxErrorException e) {
            throw new RuntimeException("客服消息发送失败", e);
        }
    }
    
    /**
     * 发送图文消息
     */
    public void sendNewsMessage(String openId, String title, String description, 
                              String url, String picUrl) {
        try {
            WxMpKefuMessage message = WxMpKefuMessage.NEWS()
                    .toUser(openId)
                    .addArticle(
                        new WxArticle().setTitle(title)
                                      .setDescription(description)
                                      .setUrl(url)
                                      .setPicUrl(picUrl)
                    )
                    .build();
            
            wxMpService.getKefuService().sendKefuMessage(message);
            
        } catch (WxErrorException e) {
            throw new RuntimeException("图文消息发送失败", e);
        }
    }
}

5. 接收消息处理

控制器类

java

@RestController
@RequestMapping("/wechat")
public class WeChatController {
    
    @Autowired
    private WxMpService wxMpService;
    
    /**
     * 微信服务器验证
     */
    @GetMapping(produces = "text/plain;charset=utf-8")
    public String authGet(
            @RequestParam(name = "signature", required = false) String signature,
            @RequestParam(name = "timestamp", required = false) String timestamp,
            @RequestParam(name = "nonce", required = false) String nonce,
            @RequestParam(name = "echostr", required = false) String echostr) {
        
        if (wxMpService.checkSignature(timestamp, nonce, signature)) {
            return echostr;
        }
        
        return "非法请求";
    }
    
    /**
     * 接收用户消息
     */
    @PostMapping(produces = "application/xml; charset=UTF-8")
    public String post(
            @RequestBody String requestBody,
            @RequestParam("signature") String signature,
            @RequestParam("timestamp") String timestamp,
            @RequestParam("nonce") String nonce,
            @RequestParam(name = "encrypt_type", required = false) String encType,
            @RequestParam(name = "msg_signature", required = false) String msgSignature) {
        
        if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
            throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
        }
        
        // 处理消息逻辑
        return processMessage(requestBody);
    }
    
    private String processMessage(String requestBody) {
        try {
            WxMpXmlMessage message = WxMpXmlMessage.fromXml(requestBody);
            String fromUser = message.getFromUser();
            String msgType = message.getMsgType();
            
            // 根据消息类型处理
            switch (msgType) {
                case "text":
                    // 处理文本消息
                    return handleTextMessage(message);
                case "event":
                    // 处理事件消息
                    return handleEventMessage(message);
                default:
                    return "success";
            }
            
        } catch (Exception e) {
            return "error";
        }
    }
    
    private String handleTextMessage(WxMpXmlMessage message) {
        // 自动回复逻辑
        String content = message.getContent();
        String replyContent = "收到您的消息:" + content;
        
        WxMpXmlOutTextMessage response = WxMpXmlOutMessage.TEXT()
                .content(replyContent)
                .fromUser(message.getToUser())
                .toUser(message.getFromUser())
                .build();
        
        return response.toXml();
    }
}

6. 批量消息推送

java

@Service
public class BatchMessageService {
    
    @Autowired
    private WxMpService wxMpService;
    
    /**
     * 批量发送模板消息
     */
    public void batchSendTemplateMessages(List<String> openIds, String templateId, 
                                        Map<String, String> data) {
        for (String openId : openIds) {
            try {
                // 添加延迟,避免触发频率限制
                Thread.sleep(100);
                
                WxMpTemplateMessage message = WxMpTemplateMessage.builder()
                        .toUser(openId)
                        .templateId(templateId)
                        .build();
                
                data.forEach((key, value) -> {
                    message.addData(new WxMpTemplateData(key, value, "#173177"));
                });
                
                wxMpService.getTemplateMsgService().sendTemplateMsg(message);
                
            } catch (Exception e) {
                // 记录失败日志,继续发送下一条
                System.err.println("发送失败 openId: " + openId + ", 错误: " + e.getMessage());
            }
        }
    }
}

7. 配置文件

yaml

# application.yml
wechat:
  mp:
    appId: your_app_id
    secret: your_app_secret
    token: your_token

注意事项

  1. 频率限制:模板消息有发送频率限制,注意控制发送速度

  2. 用户授权:模板消息需要用户授权才能发送

  3. 错误处理:做好异常处理和重试机制

  4. 日志记录:记录发送日志以便排查问题

  5. 测试环境:在测试号上充分测试后再上线

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐