CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-github-binarywang--weixin-java-mp

Comprehensive Java SDK for WeChat Official Account development with complete API coverage for user management, messaging, materials, menus, and WeChat platform features.

Pending
Overview
Eval results
Files

message-handling.mddocs/

Message Handling

Complete message processing framework including routing, handling, and response building for WeChat Official Account messaging.

Message Router

class WxMpMessageRouter {
  // Rule creation and configuration
  WxMpMessageRouterRule rule();
  
  // Message routing
  WxMpXmlOutMessage route(WxMpXmlMessage message);
  WxMpXmlOutMessage route(WxMpXmlMessage message, Map<String, Object> context);
  WxMpXmlOutMessage route(WxMpXmlMessage message, Map<String, Object> context, 
                         WxMpService wxMpService, WxSessionManager sessionManager);
}

class WxMpMessageRouterRule {
  // Message type matching
  WxMpMessageRouterRule msgType(String msgType);
  WxMpMessageRouterRule event(String event);
  WxMpMessageRouterRule eventKey(String eventKey);
  WxMpMessageRouterRule eventKeyRegex(String regex);
  WxMpMessageRouterRule content(String content);
  WxMpMessageRouterRule rContent(String regexContent);
  
  // User matching
  WxMpMessageRouterRule fromUser(String fromUser);
  
  // Custom matching
  WxMpMessageRouterRule matcher(WxMpMessageMatcher matcher);
  
  // Handler assignment
  WxMpMessageRouterRule handler(WxMpMessageHandler handler);
  WxMpMessageRouterRule handler(WxMpMessageHandler handler, WxMpMessageHandler... handlers);
  
  // Processing configuration
  WxMpMessageRouterRule async(boolean async);
  WxMpMessageRouterRule interceptor(WxMpMessageInterceptor interceptor);
  WxMpMessageRouterRule interceptor(WxMpMessageInterceptor interceptor, WxMpMessageInterceptor... interceptors);
  
  // Rule completion
  WxMpMessageRouter end();
}

Message Handler Interface

interface WxMpMessageHandler {
  WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, 
                          Map<String, Object> context,
                          WxMpService wxMpService, 
                          WxSessionManager sessionManager) throws WxErrorException;
}

interface WxMpMessageInterceptor {
  boolean intercept(WxMpXmlMessage wxMessage,
                   Map<String, Object> context,
                   WxMpService wxMpService,
                   WxSessionManager sessionManager) throws WxErrorException;
}

interface WxMpMessageMatcher {
  boolean match(WxMpXmlMessage message);
}

Incoming Message Model

class WxMpXmlMessage implements Serializable {
  // Basic message fields
  private String toUser;
  private String fromUser;
  private Long createTime;
  private String msgType;
  private Long msgId;
  
  // Text message
  private String content;
  
  // Image message
  private String picUrl;
  private String mediaId;
  
  // Voice message
  private String format;
  private String recognition;
  
  // Video message
  private String thumbMediaId;
  
  // Location message
  private String locationX;
  private String locationY;
  private String scale;
  private String label;
  
  // Link message
  private String title;
  private String description;
  private String url;
  
  // Event message
  private String event;
  private String eventKey;
  private String ticket;
  private String latitude;
  private String longitude;
  private String precision;
  
  // Menu events
  private Long menuId;
  
  // Scan events
  private String scanCodeInfo;
  private String scanType;
  private String scanResult;
  
  // Photo events
  private String sendPicsInfo;
  private Integer count;
  private List<SendPicsInfo.Item> picList;
  
  // Location events
  private String sendLocationInfo;
  private String locationName;
  private String address;
  
  // All fields map for extensibility
  private Map<String, Object> allFieldsMap;
  
  // Static factory methods
  public static WxMpXmlMessage fromXml(String xml);
  public static WxMpXmlMessage fromXml(InputStream is);
  public static WxMpXmlMessage fromEncryptedXml(String xml, WxMpConfigStorage config, String timestamp, String nonce, String msgSignature);
  public static WxMpXmlMessage fromEncryptedXml(InputStream is, WxMpConfigStorage config, String timestamp, String nonce, String msgSignature);
  
  // Getters and setters for all fields
  public String getToUser();
  public void setToUser(String toUser);
  public String getFromUser();
  public void setFromUser(String fromUser);
  public Long getCreateTime();
  public void setCreateTime(Long createTime);
  public String getMsgType();
  public void setMsgType(String msgType);
  public String getContent();
  public void setContent(String content);
  public Long getMsgId();
  public void setMsgId(Long msgId);
  public String getPicUrl();
  public void setPicUrl(String picUrl);
  public String getMediaId();
  public void setMediaId(String mediaId);
  public String getFormat();
  public void setFormat(String format);
  public String getThumbMediaId();
  public void setThumbMediaId(String thumbMediaId);
  public String getLocationX();
  public void setLocationX(String locationX);
  public String getLocationY();
  public void setLocationY(String locationY);
  public String getScale();
  public void setScale(String scale);
  public String getLabel();
  public void setLabel(String label);
  public String getTitle();
  public void setTitle(String title);
  public String getDescription();
  public void setDescription(String description);
  public String getUrl();
  public void setUrl(String url);
  public String getEvent();
  public void setEvent(String event);
  public String getEventKey();
  public void setEventKey(String eventKey);
  public String getTicket();
  public void setTicket(String ticket);
  public String getLatitude();
  public void setLatitude(String latitude);
  public String getLongitude();
  public void setLongitude(String longitude);
  public String getPrecision();
  public void setPrecision(String precision);
  public String getRecognition();
  public void setRecognition(String recognition);
}

Outgoing Message Models

abstract class WxMpXmlOutMessage {
  protected String toUserName;
  protected String fromUserName;
  protected Long createTime;
  protected String msgType;
  
  // Abstract methods
  public abstract String toXml();
  
  // Common methods
  public String getToUserName();
  public void setToUserName(String toUserName);
  public String getFromUserName();
  public void setFromUserName(String fromUserName);
  public Long getCreateTime();
  public void setCreateTime(Long createTime);
  public String getMsgType();
  public void setMsgType(String msgType);
}

class WxMpXmlOutTextMessage extends WxMpXmlOutMessage {
  private String content;
  
  public String getContent();
  public void setContent(String content);
}

class WxMpXmlOutImageMessage extends WxMpXmlOutMessage {
  private String mediaId;
  
  public String getMediaId();
  public void setMediaId(String mediaId);
}

class WxMpXmlOutVoiceMessage extends WxMpXmlOutMessage {
  private String mediaId;
  
  public String getMediaId();
  public void setMediaId(String mediaId);
}

class WxMpXmlOutVideoMessage extends WxMpXmlOutMessage {
  private String mediaId;
  private String title;
  private String description;
  
  public String getMediaId();
  public void setMediaId(String mediaId);
  public String getTitle();
  public void setTitle(String title);
  public String getDescription();
  public void setDescription(String description);
}

class WxMpXmlOutMusicMessage extends WxMpXmlOutMessage {
  private String title;
  private String description;
  private String musicUrl;
  private String hqMusicUrl;
  private String thumbMediaId;
  
  public String getTitle();
  public void setTitle(String title);
  public String getDescription();
  public void setDescription(String description);
  public String getMusicUrl();
  public void setMusicUrl(String musicUrl);
  public String getHqMusicUrl();
  public void setHqMusicUrl(String hqMusicUrl);
  public String getThumbMediaId();
  public void setThumbMediaId(String thumbMediaId);
}

class WxMpXmlOutNewsMessage extends WxMpXmlOutMessage {
  private List<WxMpXmlOutNewsMessage.Item> articles;
  
  public List<Item> getArticles();
  public void setArticles(List<Item> articles);
  public void addArticle(Item item);
  
  public static class Item {
    private String title;
    private String description;
    private String picUrl;
    private String url;
    
    public String getTitle();
    public void setTitle(String title);
    public String getDescription();
    public void setDescription(String description);
    public String getPicUrl();
    public void setPicUrl(String picUrl);
    public String getUrl();
    public void setUrl(String url);
  }
}

Message Builders

class TextBuilder {
  public static WxMpXmlOutTextMessage build(String content, WxMpXmlMessage wxMessage);
}

class ImageBuilder {
  public static WxMpXmlOutImageMessage build(String mediaId, WxMpXmlMessage wxMessage);
}

class VoiceBuilder {
  public static WxMpXmlOutVoiceMessage build(String mediaId, WxMpXmlMessage wxMessage);
}

class VideoBuilder {
  public static WxMpXmlOutVideoMessage build(String mediaId, String title, String description, WxMpXmlMessage wxMessage);
}

class MusicBuilder {
  public static WxMpXmlOutMusicMessage build(String title, String description, 
                                           String musicUrl, String hqMusicUrl, 
                                           String thumbMediaId, WxMpXmlMessage wxMessage);
}

class NewsBuilder {
  public static WxMpXmlOutNewsMessage build(List<WxMpXmlOutNewsMessage.Item> articles, WxMpXmlMessage wxMessage);
}

Message Constants

// Message types from WxConsts
public static final String XmlMsgType = "MsgType";
public static final String TEXT = "text";
public static final String IMAGE = "image";
public static final String VOICE = "voice";
public static final String VIDEO = "video";
public static final String SHORTVIDEO = "shortvideo";
public static final String LOCATION = "location";
public static final String LINK = "link";
public static final String EVENT = "event";
public static final String MUSIC = "music";
public static final String NEWS = "news";
public static final String TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service";
public static final String DEVICE_TEXT = "device_text";
public static final String DEVICE_EVENT = "device_event";
public static final String DEVICE_STATUS = "device_status";
public static final String HARDWARE = "hardware";

// Event types
public static final String Event = "Event";
public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";
public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
public static final String EVENT_TYPE_SCAN = "SCAN";
public static final String EVENT_TYPE_LOCATION = "LOCATION";
public static final String EVENT_TYPE_CLICK = "CLICK";
public static final String EVENT_TYPE_VIEW = "VIEW";
public static final String EVENT_TYPE_MASSSENDJOBFINISH = "MASSSENDJOBFINISH";
public static final String EVENT_TYPE_TEMPLATESENDJOBFINISH = "TEMPLATESENDJOBFINISH";
public static final String EVENT_TYPE_SCANCODE_PUSH = "scancode_push";
public static final String EVENT_TYPE_SCANCODE_WAITMSG = "scancode_waitmsg";
public static final String EVENT_TYPE_PIC_SYSPHOTO = "pic_sysphoto";
public static final String EVENT_TYPE_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";
public static final String EVENT_TYPE_PIC_WEIXIN = "pic_weixin";
public static final String EVENT_TYPE_LOCATION_SELECT = "location_select";

Usage Examples

Basic Message Router Setup

import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.common.api.WxConsts;

// Create message router
WxMpMessageRouter router = new WxMpMessageRouter(wxService);

// Handle text messages
router.rule()
    .msgType(WxConsts.XmlMsgType.TEXT)
    .handler(new TextMessageHandler())
    .end();

// Handle subscribe events
router.rule()
    .msgType(WxConsts.XmlMsgType.EVENT)
    .event(WxConsts.EventType.SUBSCRIBE)
    .handler(new SubscribeHandler())
    .end();

// Handle menu click events
router.rule()
    .msgType(WxConsts.XmlMsgType.EVENT)
    .event(WxConsts.EventType.CLICK)
    .eventKey("MENU_KEY_HELP")
    .handler(new HelpMenuHandler())
    .end();

// Route incoming message
WxMpXmlOutMessage response = router.route(incomingMessage);

Custom Message Handlers

public class TextMessageHandler implements WxMpMessageHandler {
    @Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                                   Map<String, Object> context,
                                   WxMpService wxMpService,
                                   WxSessionManager sessionManager) throws WxErrorException {
        
        String content = wxMessage.getContent();
        
        if ("help".equalsIgnoreCase(content)) {
            return TextBuilder.build("Help information here", wxMessage);
        } else if (content.startsWith("weather")) {
            // Handle weather query
            String weatherInfo = getWeatherInfo(content);
            return TextBuilder.build(weatherInfo, wxMessage);
        } else {
            return TextBuilder.build("Echo: " + content, wxMessage);
        }
    }
    
    private String getWeatherInfo(String query) {
        // Weather service implementation
        return "Weather information for " + query;
    }
}

public class SubscribeHandler implements WxMpMessageHandler {
    @Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                                   Map<String, Object> context,
                                   WxMpService wxMpService,
                                   WxSessionManager sessionManager) throws WxErrorException {
        
        // Welcome new subscriber
        String welcomeMessage = "Welcome to our WeChat Official Account! " +
                               "Send 'help' for available commands.";
        
        return TextBuilder.build(welcomeMessage, wxMessage);
    }
}

Advanced Router Configuration

// Complex routing with multiple conditions
router.rule()
    .msgType(WxConsts.XmlMsgType.TEXT)
    .rContent("(?i)^(hi|hello|hey).*")  // Case-insensitive greeting regex
    .handler(new GreetingHandler())
    .end();

// Handle different users differently
router.rule()
    .msgType(WxConsts.XmlMsgType.TEXT)
    .fromUser("admin_openid")
    .handler(new AdminHandler())
    .end();

// Custom matcher
router.rule()
    .matcher(message -> {
        // Custom logic for complex conditions
        return message.getContent() != null && 
               message.getContent().contains("urgent");
    })
    .handler(new UrgentMessageHandler())
    .async(true)  // Handle asynchronously
    .end();

// Interceptor for logging
router.rule()
    .msgType(WxConsts.XmlMsgType.TEXT)
    .interceptor((wxMessage, context, wxMpService, sessionManager) -> {
        System.out.println("Processing message from: " + wxMessage.getFromUser());
        return true; // Continue processing
    })
    .handler(new LoggedTextHandler())
    .end();

Rich Message Responses

public class MenuHandler implements WxMpMessageHandler {
    @Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                                   Map<String, Object> context,
                                   WxMpService wxMpService,
                                   WxSessionManager sessionManager) throws WxErrorException {
        
        String eventKey = wxMessage.getEventKey();
        
        switch (eventKey) {
            case "MENU_NEWS":
                return buildNewsMessage(wxMessage);
            case "MENU_IMAGE":
                return buildImageMessage(wxMessage);
            case "MENU_VOICE":
                return buildVoiceMessage(wxMessage);
            default:
                return TextBuilder.build("Unknown menu option", wxMessage);
        }
    }
    
    private WxMpXmlOutNewsMessage buildNewsMessage(WxMpXmlMessage wxMessage) {
        List<WxMpXmlOutNewsMessage.Item> articles = new ArrayList<>();
        
        WxMpXmlOutNewsMessage.Item item1 = new WxMpXmlOutNewsMessage.Item();
        item1.setTitle("Latest News");
        item1.setDescription("Check out our latest updates");
        item1.setPicUrl("https://example.com/image1.jpg");
        item1.setUrl("https://example.com/news/1");
        articles.add(item1);
        
        WxMpXmlOutNewsMessage.Item item2 = new WxMpXmlOutNewsMessage.Item();
        item2.setTitle("Product Updates");
        item2.setDescription("New features available now");
        item2.setPicUrl("https://example.com/image2.jpg");
        item2.setUrl("https://example.com/news/2");
        articles.add(item2);
        
        return NewsBuilder.build(articles, wxMessage);
    }
    
    private WxMpXmlOutImageMessage buildImageMessage(WxMpXmlMessage wxMessage) {
        return ImageBuilder.build("media_id_123", wxMessage);
    }
    
    private WxMpXmlOutVoiceMessage buildVoiceMessage(WxMpXmlMessage wxMessage) {
        return VoiceBuilder.build("voice_media_id_456", wxMessage);
    }
}

Event Handling

// QR code scan events
router.rule()
    .msgType(WxConsts.XmlMsgType.EVENT)
    .event(WxConsts.EventType.SCAN)
    .handler(new QrScanHandler())
    .end();

// Location events
router.rule()
    .msgType(WxConsts.XmlMsgType.EVENT)
    .event(WxConsts.EventType.LOCATION)
    .handler(new LocationHandler())
    .end();

public class QrScanHandler implements WxMpMessageHandler {
    @Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                                   Map<String, Object> context,
                                   WxMpService wxMpService,
                                   WxSessionManager sessionManager) throws WxErrorException {
        
        String eventKey = wxMessage.getEventKey();
        String ticket = wxMessage.getTicket();
        
        // Process QR code scan
        String response = processQrScan(eventKey, ticket, wxMessage.getFromUser());
        
        return TextBuilder.build(response, wxMessage);
    }
    
    private String processQrScan(String eventKey, String ticket, String fromUser) {
        // QR code processing logic
        return "QR code scanned: " + eventKey;
    }
}

Message Parsing

// Parse incoming XML message
String xmlData = "..."; // Received from WeChat
WxMpXmlMessage message = WxMpXmlMessage.fromXml(xmlData);

// Parse encrypted message
WxMpXmlMessage encryptedMessage = WxMpXmlMessage.fromEncryptedXml(
    xmlData, config, timestamp, nonce, msgSignature);

// Access message data
System.out.println("Message type: " + message.getMsgType());
System.out.println("From user: " + message.getFromUser());
System.out.println("Content: " + message.getContent());

Session Management

public class StatefulHandler implements WxMpMessageHandler {
    @Override  
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                                   Map<String, Object> context,
                                   WxMpService wxMpService,
                                   WxSessionManager sessionManager) throws WxErrorException {
        
        String fromUser = wxMessage.getFromUser();
        WxSession session = sessionManager.getSession(fromUser);
        
        // Get session attribute
        String state = (String) session.getAttribute("conversation_state");
        
        if ("waiting_for_name".equals(state)) {
            // Process name input
            String name = wxMessage.getContent();
            session.setAttribute("user_name", name);
            session.setAttribute("conversation_state", "waiting_for_age");
            
            return TextBuilder.build("Thanks " + name + "! What's your age?", wxMessage);
        } else if ("waiting_for_age".equals(state)) {
            // Process age input
            String age = wxMessage.getContent();
            String name = (String) session.getAttribute("user_name");
            
            session.removeAttribute("conversation_state");
            
            return TextBuilder.build(
                "Nice to meet you, " + name + " (" + age + " years old)!", 
                wxMessage
            );
        } else {
            // Start conversation
            session.setAttribute("conversation_state", "waiting_for_name");
            return TextBuilder.build("What's your name?", wxMessage);
        }
    }
}

Error Handling

public class SafeMessageHandler implements WxMpMessageHandler {
    @Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                                   Map<String, Object> context,
                                   WxMpService wxMpService,
                                   WxSessionManager sessionManager) throws WxErrorException {
        try {
            // Message processing logic
            return processMessage(wxMessage, wxMpService);
        } catch (Exception e) {
            // Log error
            System.err.println("Error processing message: " + e.getMessage());
            
            // Return safe fallback response
            return TextBuilder.build(
                "Sorry, there was an error processing your message. Please try again later.",
                wxMessage
            );
        }
    }
    
    private WxMpXmlOutMessage processMessage(WxMpXmlMessage wxMessage, WxMpService wxMpService) {
        // Actual processing logic
        return TextBuilder.build("Processed successfully", wxMessage);
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-com-github-binarywang--weixin-java-mp

docs

advanced-services.md

index.md

material-management.md

menu-management.md

message-handling.md

service-management.md

shopping-guide.md

template-messaging.md

user-management.md

tile.json