or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-services.mdindex.mdmaterial-management.mdmenu-management.mdmessage-handling.mdservice-management.mdshopping-guide.mdtemplate-messaging.mduser-management.md

message-handling.mddocs/

0

# Message Handling

1

2

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

3

4

## Message Router

5

6

```java { .api }

7

class WxMpMessageRouter {

8

// Rule creation and configuration

9

WxMpMessageRouterRule rule();

10

11

// Message routing

12

WxMpXmlOutMessage route(WxMpXmlMessage message);

13

WxMpXmlOutMessage route(WxMpXmlMessage message, Map<String, Object> context);

14

WxMpXmlOutMessage route(WxMpXmlMessage message, Map<String, Object> context,

15

WxMpService wxMpService, WxSessionManager sessionManager);

16

}

17

18

class WxMpMessageRouterRule {

19

// Message type matching

20

WxMpMessageRouterRule msgType(String msgType);

21

WxMpMessageRouterRule event(String event);

22

WxMpMessageRouterRule eventKey(String eventKey);

23

WxMpMessageRouterRule eventKeyRegex(String regex);

24

WxMpMessageRouterRule content(String content);

25

WxMpMessageRouterRule rContent(String regexContent);

26

27

// User matching

28

WxMpMessageRouterRule fromUser(String fromUser);

29

30

// Custom matching

31

WxMpMessageRouterRule matcher(WxMpMessageMatcher matcher);

32

33

// Handler assignment

34

WxMpMessageRouterRule handler(WxMpMessageHandler handler);

35

WxMpMessageRouterRule handler(WxMpMessageHandler handler, WxMpMessageHandler... handlers);

36

37

// Processing configuration

38

WxMpMessageRouterRule async(boolean async);

39

WxMpMessageRouterRule interceptor(WxMpMessageInterceptor interceptor);

40

WxMpMessageRouterRule interceptor(WxMpMessageInterceptor interceptor, WxMpMessageInterceptor... interceptors);

41

42

// Rule completion

43

WxMpMessageRouter end();

44

}

45

```

46

47

## Message Handler Interface

48

49

```java { .api }

50

interface WxMpMessageHandler {

51

WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,

52

Map<String, Object> context,

53

WxMpService wxMpService,

54

WxSessionManager sessionManager) throws WxErrorException;

55

}

56

57

interface WxMpMessageInterceptor {

58

boolean intercept(WxMpXmlMessage wxMessage,

59

Map<String, Object> context,

60

WxMpService wxMpService,

61

WxSessionManager sessionManager) throws WxErrorException;

62

}

63

64

interface WxMpMessageMatcher {

65

boolean match(WxMpXmlMessage message);

66

}

67

```

68

69

## Incoming Message Model

70

71

```java { .api }

72

class WxMpXmlMessage implements Serializable {

73

// Basic message fields

74

private String toUser;

75

private String fromUser;

76

private Long createTime;

77

private String msgType;

78

private Long msgId;

79

80

// Text message

81

private String content;

82

83

// Image message

84

private String picUrl;

85

private String mediaId;

86

87

// Voice message

88

private String format;

89

private String recognition;

90

91

// Video message

92

private String thumbMediaId;

93

94

// Location message

95

private String locationX;

96

private String locationY;

97

private String scale;

98

private String label;

99

100

// Link message

101

private String title;

102

private String description;

103

private String url;

104

105

// Event message

106

private String event;

107

private String eventKey;

108

private String ticket;

109

private String latitude;

110

private String longitude;

111

private String precision;

112

113

// Menu events

114

private Long menuId;

115

116

// Scan events

117

private String scanCodeInfo;

118

private String scanType;

119

private String scanResult;

120

121

// Photo events

122

private String sendPicsInfo;

123

private Integer count;

124

private List<SendPicsInfo.Item> picList;

125

126

// Location events

127

private String sendLocationInfo;

128

private String locationName;

129

private String address;

130

131

// All fields map for extensibility

132

private Map<String, Object> allFieldsMap;

133

134

// Static factory methods

135

public static WxMpXmlMessage fromXml(String xml);

136

public static WxMpXmlMessage fromXml(InputStream is);

137

public static WxMpXmlMessage fromEncryptedXml(String xml, WxMpConfigStorage config, String timestamp, String nonce, String msgSignature);

138

public static WxMpXmlMessage fromEncryptedXml(InputStream is, WxMpConfigStorage config, String timestamp, String nonce, String msgSignature);

139

140

// Getters and setters for all fields

141

public String getToUser();

142

public void setToUser(String toUser);

143

public String getFromUser();

144

public void setFromUser(String fromUser);

145

public Long getCreateTime();

146

public void setCreateTime(Long createTime);

147

public String getMsgType();

148

public void setMsgType(String msgType);

149

public String getContent();

150

public void setContent(String content);

151

public Long getMsgId();

152

public void setMsgId(Long msgId);

153

public String getPicUrl();

154

public void setPicUrl(String picUrl);

155

public String getMediaId();

156

public void setMediaId(String mediaId);

157

public String getFormat();

158

public void setFormat(String format);

159

public String getThumbMediaId();

160

public void setThumbMediaId(String thumbMediaId);

161

public String getLocationX();

162

public void setLocationX(String locationX);

163

public String getLocationY();

164

public void setLocationY(String locationY);

165

public String getScale();

166

public void setScale(String scale);

167

public String getLabel();

168

public void setLabel(String label);

169

public String getTitle();

170

public void setTitle(String title);

171

public String getDescription();

172

public void setDescription(String description);

173

public String getUrl();

174

public void setUrl(String url);

175

public String getEvent();

176

public void setEvent(String event);

177

public String getEventKey();

178

public void setEventKey(String eventKey);

179

public String getTicket();

180

public void setTicket(String ticket);

181

public String getLatitude();

182

public void setLatitude(String latitude);

183

public String getLongitude();

184

public void setLongitude(String longitude);

185

public String getPrecision();

186

public void setPrecision(String precision);

187

public String getRecognition();

188

public void setRecognition(String recognition);

189

}

190

```

191

192

## Outgoing Message Models

193

194

```java { .api }

195

abstract class WxMpXmlOutMessage {

196

protected String toUserName;

197

protected String fromUserName;

198

protected Long createTime;

199

protected String msgType;

200

201

// Abstract methods

202

public abstract String toXml();

203

204

// Common methods

205

public String getToUserName();

206

public void setToUserName(String toUserName);

207

public String getFromUserName();

208

public void setFromUserName(String fromUserName);

209

public Long getCreateTime();

210

public void setCreateTime(Long createTime);

211

public String getMsgType();

212

public void setMsgType(String msgType);

213

}

214

215

class WxMpXmlOutTextMessage extends WxMpXmlOutMessage {

216

private String content;

217

218

public String getContent();

219

public void setContent(String content);

220

}

221

222

class WxMpXmlOutImageMessage extends WxMpXmlOutMessage {

223

private String mediaId;

224

225

public String getMediaId();

226

public void setMediaId(String mediaId);

227

}

228

229

class WxMpXmlOutVoiceMessage extends WxMpXmlOutMessage {

230

private String mediaId;

231

232

public String getMediaId();

233

public void setMediaId(String mediaId);

234

}

235

236

class WxMpXmlOutVideoMessage extends WxMpXmlOutMessage {

237

private String mediaId;

238

private String title;

239

private String description;

240

241

public String getMediaId();

242

public void setMediaId(String mediaId);

243

public String getTitle();

244

public void setTitle(String title);

245

public String getDescription();

246

public void setDescription(String description);

247

}

248

249

class WxMpXmlOutMusicMessage extends WxMpXmlOutMessage {

250

private String title;

251

private String description;

252

private String musicUrl;

253

private String hqMusicUrl;

254

private String thumbMediaId;

255

256

public String getTitle();

257

public void setTitle(String title);

258

public String getDescription();

259

public void setDescription(String description);

260

public String getMusicUrl();

261

public void setMusicUrl(String musicUrl);

262

public String getHqMusicUrl();

263

public void setHqMusicUrl(String hqMusicUrl);

264

public String getThumbMediaId();

265

public void setThumbMediaId(String thumbMediaId);

266

}

267

268

class WxMpXmlOutNewsMessage extends WxMpXmlOutMessage {

269

private List<WxMpXmlOutNewsMessage.Item> articles;

270

271

public List<Item> getArticles();

272

public void setArticles(List<Item> articles);

273

public void addArticle(Item item);

274

275

public static class Item {

276

private String title;

277

private String description;

278

private String picUrl;

279

private String url;

280

281

public String getTitle();

282

public void setTitle(String title);

283

public String getDescription();

284

public void setDescription(String description);

285

public String getPicUrl();

286

public void setPicUrl(String picUrl);

287

public String getUrl();

288

public void setUrl(String url);

289

}

290

}

291

```

292

293

## Message Builders

294

295

```java { .api }

296

class TextBuilder {

297

public static WxMpXmlOutTextMessage build(String content, WxMpXmlMessage wxMessage);

298

}

299

300

class ImageBuilder {

301

public static WxMpXmlOutImageMessage build(String mediaId, WxMpXmlMessage wxMessage);

302

}

303

304

class VoiceBuilder {

305

public static WxMpXmlOutVoiceMessage build(String mediaId, WxMpXmlMessage wxMessage);

306

}

307

308

class VideoBuilder {

309

public static WxMpXmlOutVideoMessage build(String mediaId, String title, String description, WxMpXmlMessage wxMessage);

310

}

311

312

class MusicBuilder {

313

public static WxMpXmlOutMusicMessage build(String title, String description,

314

String musicUrl, String hqMusicUrl,

315

String thumbMediaId, WxMpXmlMessage wxMessage);

316

}

317

318

class NewsBuilder {

319

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

320

}

321

```

322

323

## Message Constants

324

325

```java { .api }

326

// Message types from WxConsts

327

public static final String XmlMsgType = "MsgType";

328

public static final String TEXT = "text";

329

public static final String IMAGE = "image";

330

public static final String VOICE = "voice";

331

public static final String VIDEO = "video";

332

public static final String SHORTVIDEO = "shortvideo";

333

public static final String LOCATION = "location";

334

public static final String LINK = "link";

335

public static final String EVENT = "event";

336

public static final String MUSIC = "music";

337

public static final String NEWS = "news";

338

public static final String TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service";

339

public static final String DEVICE_TEXT = "device_text";

340

public static final String DEVICE_EVENT = "device_event";

341

public static final String DEVICE_STATUS = "device_status";

342

public static final String HARDWARE = "hardware";

343

344

// Event types

345

public static final String Event = "Event";

346

public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";

347

public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";

348

public static final String EVENT_TYPE_SCAN = "SCAN";

349

public static final String EVENT_TYPE_LOCATION = "LOCATION";

350

public static final String EVENT_TYPE_CLICK = "CLICK";

351

public static final String EVENT_TYPE_VIEW = "VIEW";

352

public static final String EVENT_TYPE_MASSSENDJOBFINISH = "MASSSENDJOBFINISH";

353

public static final String EVENT_TYPE_TEMPLATESENDJOBFINISH = "TEMPLATESENDJOBFINISH";

354

public static final String EVENT_TYPE_SCANCODE_PUSH = "scancode_push";

355

public static final String EVENT_TYPE_SCANCODE_WAITMSG = "scancode_waitmsg";

356

public static final String EVENT_TYPE_PIC_SYSPHOTO = "pic_sysphoto";

357

public static final String EVENT_TYPE_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";

358

public static final String EVENT_TYPE_PIC_WEIXIN = "pic_weixin";

359

public static final String EVENT_TYPE_LOCATION_SELECT = "location_select";

360

```

361

362

## Usage Examples

363

364

### Basic Message Router Setup

365

366

```java

367

import me.chanjar.weixin.mp.api.WxMpMessageRouter;

368

import me.chanjar.weixin.mp.api.WxMpMessageHandler;

369

import me.chanjar.weixin.common.api.WxConsts;

370

371

// Create message router

372

WxMpMessageRouter router = new WxMpMessageRouter(wxService);

373

374

// Handle text messages

375

router.rule()

376

.msgType(WxConsts.XmlMsgType.TEXT)

377

.handler(new TextMessageHandler())

378

.end();

379

380

// Handle subscribe events

381

router.rule()

382

.msgType(WxConsts.XmlMsgType.EVENT)

383

.event(WxConsts.EventType.SUBSCRIBE)

384

.handler(new SubscribeHandler())

385

.end();

386

387

// Handle menu click events

388

router.rule()

389

.msgType(WxConsts.XmlMsgType.EVENT)

390

.event(WxConsts.EventType.CLICK)

391

.eventKey("MENU_KEY_HELP")

392

.handler(new HelpMenuHandler())

393

.end();

394

395

// Route incoming message

396

WxMpXmlOutMessage response = router.route(incomingMessage);

397

```

398

399

### Custom Message Handlers

400

401

```java

402

public class TextMessageHandler implements WxMpMessageHandler {

403

@Override

404

public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,

405

Map<String, Object> context,

406

WxMpService wxMpService,

407

WxSessionManager sessionManager) throws WxErrorException {

408

409

String content = wxMessage.getContent();

410

411

if ("help".equalsIgnoreCase(content)) {

412

return TextBuilder.build("Help information here", wxMessage);

413

} else if (content.startsWith("weather")) {

414

// Handle weather query

415

String weatherInfo = getWeatherInfo(content);

416

return TextBuilder.build(weatherInfo, wxMessage);

417

} else {

418

return TextBuilder.build("Echo: " + content, wxMessage);

419

}

420

}

421

422

private String getWeatherInfo(String query) {

423

// Weather service implementation

424

return "Weather information for " + query;

425

}

426

}

427

428

public class SubscribeHandler implements WxMpMessageHandler {

429

@Override

430

public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,

431

Map<String, Object> context,

432

WxMpService wxMpService,

433

WxSessionManager sessionManager) throws WxErrorException {

434

435

// Welcome new subscriber

436

String welcomeMessage = "Welcome to our WeChat Official Account! " +

437

"Send 'help' for available commands.";

438

439

return TextBuilder.build(welcomeMessage, wxMessage);

440

}

441

}

442

```

443

444

### Advanced Router Configuration

445

446

```java

447

// Complex routing with multiple conditions

448

router.rule()

449

.msgType(WxConsts.XmlMsgType.TEXT)

450

.rContent("(?i)^(hi|hello|hey).*") // Case-insensitive greeting regex

451

.handler(new GreetingHandler())

452

.end();

453

454

// Handle different users differently

455

router.rule()

456

.msgType(WxConsts.XmlMsgType.TEXT)

457

.fromUser("admin_openid")

458

.handler(new AdminHandler())

459

.end();

460

461

// Custom matcher

462

router.rule()

463

.matcher(message -> {

464

// Custom logic for complex conditions

465

return message.getContent() != null &&

466

message.getContent().contains("urgent");

467

})

468

.handler(new UrgentMessageHandler())

469

.async(true) // Handle asynchronously

470

.end();

471

472

// Interceptor for logging

473

router.rule()

474

.msgType(WxConsts.XmlMsgType.TEXT)

475

.interceptor((wxMessage, context, wxMpService, sessionManager) -> {

476

System.out.println("Processing message from: " + wxMessage.getFromUser());

477

return true; // Continue processing

478

})

479

.handler(new LoggedTextHandler())

480

.end();

481

```

482

483

### Rich Message Responses

484

485

```java

486

public class MenuHandler implements WxMpMessageHandler {

487

@Override

488

public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,

489

Map<String, Object> context,

490

WxMpService wxMpService,

491

WxSessionManager sessionManager) throws WxErrorException {

492

493

String eventKey = wxMessage.getEventKey();

494

495

switch (eventKey) {

496

case "MENU_NEWS":

497

return buildNewsMessage(wxMessage);

498

case "MENU_IMAGE":

499

return buildImageMessage(wxMessage);

500

case "MENU_VOICE":

501

return buildVoiceMessage(wxMessage);

502

default:

503

return TextBuilder.build("Unknown menu option", wxMessage);

504

}

505

}

506

507

private WxMpXmlOutNewsMessage buildNewsMessage(WxMpXmlMessage wxMessage) {

508

List<WxMpXmlOutNewsMessage.Item> articles = new ArrayList<>();

509

510

WxMpXmlOutNewsMessage.Item item1 = new WxMpXmlOutNewsMessage.Item();

511

item1.setTitle("Latest News");

512

item1.setDescription("Check out our latest updates");

513

item1.setPicUrl("https://example.com/image1.jpg");

514

item1.setUrl("https://example.com/news/1");

515

articles.add(item1);

516

517

WxMpXmlOutNewsMessage.Item item2 = new WxMpXmlOutNewsMessage.Item();

518

item2.setTitle("Product Updates");

519

item2.setDescription("New features available now");

520

item2.setPicUrl("https://example.com/image2.jpg");

521

item2.setUrl("https://example.com/news/2");

522

articles.add(item2);

523

524

return NewsBuilder.build(articles, wxMessage);

525

}

526

527

private WxMpXmlOutImageMessage buildImageMessage(WxMpXmlMessage wxMessage) {

528

return ImageBuilder.build("media_id_123", wxMessage);

529

}

530

531

private WxMpXmlOutVoiceMessage buildVoiceMessage(WxMpXmlMessage wxMessage) {

532

return VoiceBuilder.build("voice_media_id_456", wxMessage);

533

}

534

}

535

```

536

537

### Event Handling

538

539

```java

540

// QR code scan events

541

router.rule()

542

.msgType(WxConsts.XmlMsgType.EVENT)

543

.event(WxConsts.EventType.SCAN)

544

.handler(new QrScanHandler())

545

.end();

546

547

// Location events

548

router.rule()

549

.msgType(WxConsts.XmlMsgType.EVENT)

550

.event(WxConsts.EventType.LOCATION)

551

.handler(new LocationHandler())

552

.end();

553

554

public class QrScanHandler implements WxMpMessageHandler {

555

@Override

556

public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,

557

Map<String, Object> context,

558

WxMpService wxMpService,

559

WxSessionManager sessionManager) throws WxErrorException {

560

561

String eventKey = wxMessage.getEventKey();

562

String ticket = wxMessage.getTicket();

563

564

// Process QR code scan

565

String response = processQrScan(eventKey, ticket, wxMessage.getFromUser());

566

567

return TextBuilder.build(response, wxMessage);

568

}

569

570

private String processQrScan(String eventKey, String ticket, String fromUser) {

571

// QR code processing logic

572

return "QR code scanned: " + eventKey;

573

}

574

}

575

```

576

577

### Message Parsing

578

579

```java

580

// Parse incoming XML message

581

String xmlData = "..."; // Received from WeChat

582

WxMpXmlMessage message = WxMpXmlMessage.fromXml(xmlData);

583

584

// Parse encrypted message

585

WxMpXmlMessage encryptedMessage = WxMpXmlMessage.fromEncryptedXml(

586

xmlData, config, timestamp, nonce, msgSignature);

587

588

// Access message data

589

System.out.println("Message type: " + message.getMsgType());

590

System.out.println("From user: " + message.getFromUser());

591

System.out.println("Content: " + message.getContent());

592

```

593

594

### Session Management

595

596

```java

597

public class StatefulHandler implements WxMpMessageHandler {

598

@Override

599

public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,

600

Map<String, Object> context,

601

WxMpService wxMpService,

602

WxSessionManager sessionManager) throws WxErrorException {

603

604

String fromUser = wxMessage.getFromUser();

605

WxSession session = sessionManager.getSession(fromUser);

606

607

// Get session attribute

608

String state = (String) session.getAttribute("conversation_state");

609

610

if ("waiting_for_name".equals(state)) {

611

// Process name input

612

String name = wxMessage.getContent();

613

session.setAttribute("user_name", name);

614

session.setAttribute("conversation_state", "waiting_for_age");

615

616

return TextBuilder.build("Thanks " + name + "! What's your age?", wxMessage);

617

} else if ("waiting_for_age".equals(state)) {

618

// Process age input

619

String age = wxMessage.getContent();

620

String name = (String) session.getAttribute("user_name");

621

622

session.removeAttribute("conversation_state");

623

624

return TextBuilder.build(

625

"Nice to meet you, " + name + " (" + age + " years old)!",

626

wxMessage

627

);

628

} else {

629

// Start conversation

630

session.setAttribute("conversation_state", "waiting_for_name");

631

return TextBuilder.build("What's your name?", wxMessage);

632

}

633

}

634

}

635

```

636

637

## Error Handling

638

639

```java

640

public class SafeMessageHandler implements WxMpMessageHandler {

641

@Override

642

public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,

643

Map<String, Object> context,

644

WxMpService wxMpService,

645

WxSessionManager sessionManager) throws WxErrorException {

646

try {

647

// Message processing logic

648

return processMessage(wxMessage, wxMpService);

649

} catch (Exception e) {

650

// Log error

651

System.err.println("Error processing message: " + e.getMessage());

652

653

// Return safe fallback response

654

return TextBuilder.build(

655

"Sorry, there was an error processing your message. Please try again later.",

656

wxMessage

657

);

658

}

659

}

660

661

private WxMpXmlOutMessage processMessage(WxMpXmlMessage wxMessage, WxMpService wxMpService) {

662

// Actual processing logic

663

return TextBuilder.build("Processed successfully", wxMessage);

664

}

665

}

666

```