0
# Template Messaging
1
2
Send template messages to users with dynamic content for notifications, confirmations, and personalized communications.
3
4
## Template Message Service Interface
5
6
```java { .api }
7
interface WxMpTemplateMsgService {
8
// Template message operations
9
WxMpTemplateMsgResult sendTemplateMsg(WxMpTemplateMessage templateMessage) throws WxErrorException;
10
List<WxMpTemplate> getAllPrivateTemplate() throws WxErrorException;
11
String addTemplate(String shortTemplateId) throws WxErrorException;
12
boolean delPrivateTemplate(String templateId) throws WxErrorException;
13
14
// Industry management
15
WxMpTemplateIndustry getIndustry() throws WxErrorException;
16
void setIndustry(WxMpTemplateIndustry industry) throws WxErrorException;
17
18
// Subscribe message support (for Mini Programs)
19
List<WxMpSubscribeMessage> getSubscribeMessages() throws WxErrorException;
20
}
21
```
22
23
## Data Models
24
25
### Template Message
26
27
```java { .api }
28
class WxMpTemplateMessage implements Serializable {
29
private String toUser;
30
private String templateId;
31
private String url;
32
private WxMpTemplateMessage.MiniProgram miniProgram;
33
private String clientMsgId;
34
private List<WxMpTemplateData> data;
35
36
public String getToUser();
37
public void setToUser(String toUser);
38
public String getTemplateId();
39
public void setTemplateId(String templateId);
40
public String getUrl();
41
public void setUrl(String url);
42
public MiniProgram getMiniProgram();
43
public void setMiniProgram(MiniProgram miniProgram);
44
public String getClientMsgId();
45
public void setClientMsgId(String clientMsgId);
46
public List<WxMpTemplateData> getData();
47
public void setData(List<WxMpTemplateData> data);
48
49
// Convenience methods
50
public WxMpTemplateMessage addData(WxMpTemplateData datum);
51
public WxMpTemplateMessage addData(String name, String value);
52
public WxMpTemplateMessage addData(String name, String value, String color);
53
54
public static class MiniProgram implements Serializable {
55
private String appid;
56
private String pagepath;
57
private Boolean usePath;
58
59
public String getAppid();
60
public void setAppid(String appid);
61
public String getPagepath();
62
public void setPagepath(String pagepath);
63
public Boolean getUsePath();
64
public void setUsePath(Boolean usePath);
65
}
66
}
67
68
class WxMpTemplateData implements Serializable {
69
private String name;
70
private String value;
71
private String color;
72
73
public WxMpTemplateData();
74
public WxMpTemplateData(String name, String value);
75
public WxMpTemplateData(String name, String value, String color);
76
77
public String getName();
78
public void setName(String name);
79
public String getValue();
80
public void setValue(String value);
81
public String getColor();
82
public void setColor(String color);
83
}
84
```
85
86
### Template Message Result
87
88
```java { .api }
89
class WxMpTemplateMsgResult implements Serializable {
90
private String msgId;
91
92
public String getMsgId();
93
public void setMsgId(String msgId);
94
}
95
```
96
97
### Template Information
98
99
```java { .api }
100
class WxMpTemplate implements Serializable {
101
private String templateId;
102
private String title;
103
private String primaryIndustry;
104
private String deputyIndustry;
105
private String content;
106
private String example;
107
108
public String getTemplateId();
109
public void setTemplateId(String templateId);
110
public String getTitle();
111
public void setTitle(String title);
112
public String getPrimaryIndustry();
113
public void setPrimaryIndustry(String primaryIndustry);
114
public String getDeputyIndustry();
115
public void setDeputyIndustry(String deputyIndustry);
116
public String getContent();
117
public void setContent(String content);
118
public String getExample();
119
public void setExample(String example);
120
}
121
```
122
123
### Industry Information
124
125
```java { .api }
126
class WxMpTemplateIndustry implements Serializable {
127
private String primaryIndustryCode;
128
private String primaryIndustryName;
129
private String secondaryIndustryCode;
130
private String secondaryIndustryName;
131
132
public String getPrimaryIndustryCode();
133
public void setPrimaryIndustryCode(String primaryIndustryCode);
134
public String getPrimaryIndustryName();
135
public void setPrimaryIndustryName(String primaryIndustryName);
136
public String getSecondaryIndustryCode();
137
public void setSecondaryIndustryCode(String secondaryIndustryCode);
138
public String getSecondaryIndustryName();
139
public void setSecondaryIndustryName(String secondaryIndustryName);
140
}
141
```
142
143
### Subscribe Message
144
145
```java { .api }
146
class WxMpSubscribeMessage implements Serializable {
147
private String priTmplId;
148
private String title;
149
private String content;
150
private String example;
151
private Integer type;
152
153
public String getPriTmplId();
154
public void setPriTmplId(String priTmplId);
155
public String getTitle();
156
public void setTitle(String title);
157
public String getContent();
158
public void setContent(String content);
159
public String getExample();
160
public void setExample(String example);
161
public Integer getType();
162
public void setType(Integer type);
163
}
164
```
165
166
## Usage Examples
167
168
### Send Basic Template Message
169
170
```java
171
// Create template message
172
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
173
.toUser("user_openid")
174
.templateId("template_id")
175
.url("https://www.example.com/details")
176
.build();
177
178
// Add template data
179
templateMessage.addData("first", "Hello!")
180
.addData("keyword1", "Order #12345", "#173177")
181
.addData("keyword2", "Processing", "#FF0000")
182
.addData("keyword3", "2024-01-15 10:30:00")
183
.addData("remark", "Thank you for your order!", "#0000FF");
184
185
// Send message
186
WxMpTemplateMsgResult result = wxService.getTemplateMsgService()
187
.sendTemplateMsg(templateMessage);
188
System.out.println("Message sent with ID: " + result.getMsgId());
189
```
190
191
### Send Template Message with Mini Program
192
193
```java
194
// Create template message with mini program link
195
WxMpTemplateMessage templateMessage = new WxMpTemplateMessage();
196
templateMessage.setToUser("user_openid");
197
templateMessage.setTemplateId("template_id");
198
199
// Set mini program
200
WxMpTemplateMessage.MiniProgram miniProgram = new WxMpTemplateMessage.MiniProgram();
201
miniProgram.setAppid("miniprogram_appid");
202
miniProgram.setPagepath("pages/order/detail?id=12345");
203
miniProgram.setUsePath(true);
204
templateMessage.setMiniProgram(miniProgram);
205
206
// Set fallback URL for users without mini program support
207
templateMessage.setUrl("https://www.example.com/order/12345");
208
209
// Add data
210
List<WxMpTemplateData> dataList = new ArrayList<>();
211
dataList.add(new WxMpTemplateData("first", "Order Update"));
212
dataList.add(new WxMpTemplateData("keyword1", "Order #12345"));
213
dataList.add(new WxMpTemplateData("keyword2", "Shipped"));
214
dataList.add(new WxMpTemplateData("keyword3", "2024-01-15"));
215
dataList.add(new WxMpTemplateData("remark", "Your order has been shipped!"));
216
templateMessage.setData(dataList);
217
218
// Send message
219
WxMpTemplateMsgResult result = wxService.getTemplateMsgService()
220
.sendTemplateMsg(templateMessage);
221
```
222
223
### Send Template Message with Client Message ID
224
225
```java
226
// Generate unique client message ID for deduplication
227
String clientMsgId = "client_msg_" + System.currentTimeMillis();
228
229
WxMpTemplateMessage templateMessage = new WxMpTemplateMessage();
230
templateMessage.setToUser("user_openid");
231
templateMessage.setTemplateId("template_id");
232
templateMessage.setClientMsgId(clientMsgId); // Prevents duplicate sends
233
templateMessage.setUrl("https://www.example.com");
234
235
// Add data
236
templateMessage.addData("first", "Payment Confirmation")
237
.addData("keyword1", "Payment Success")
238
.addData("keyword2", "$99.99")
239
.addData("keyword3", "2024-01-15 14:30:00")
240
.addData("remark", "Payment completed successfully!");
241
242
WxMpTemplateMsgResult result = wxService.getTemplateMsgService()
243
.sendTemplateMsg(templateMessage);
244
```
245
246
### Manage Template Library
247
248
```java
249
// Get all private templates
250
List<WxMpTemplate> templates = wxService.getTemplateMsgService()
251
.getAllPrivateTemplate();
252
253
System.out.println("Available templates:");
254
for (WxMpTemplate template : templates) {
255
System.out.println("ID: " + template.getTemplateId());
256
System.out.println("Title: " + template.getTitle());
257
System.out.println("Content: " + template.getContent());
258
System.out.println("Example: " + template.getExample());
259
System.out.println("---");
260
}
261
262
// Add new template from template library
263
String shortTemplateId = "TM00015"; // Template library ID
264
String templateId = wxService.getTemplateMsgService().addTemplate(shortTemplateId);
265
System.out.println("Added template with ID: " + templateId);
266
267
// Delete private template
268
boolean deleted = wxService.getTemplateMsgService()
269
.delPrivateTemplate("template_id_to_delete");
270
if (deleted) {
271
System.out.println("Template deleted successfully");
272
}
273
```
274
275
### Industry Management
276
277
```java
278
// Set industry information
279
WxMpTemplateIndustry industry = new WxMpTemplateIndustry();
280
industry.setPrimaryIndustryCode("1"); // IT/Internet/Communication/Electronics
281
industry.setSecondaryIndustryCode("4"); // Internet/E-commerce
282
wxService.getTemplateMsgService().setIndustry(industry);
283
284
// Get current industry
285
WxMpTemplateIndustry currentIndustry = wxService.getTemplateMsgService().getIndustry();
286
System.out.println("Primary: " + currentIndustry.getPrimaryIndustryName());
287
System.out.println("Secondary: " + currentIndustry.getSecondaryIndustryName());
288
```
289
290
### Batch Template Messages
291
292
```java
293
public void sendBatchTemplateMessages(List<String> userOpenIds, String templateId) {
294
for (String openId : userOpenIds) {
295
try {
296
WxMpTemplateMessage message = createTemplateMessage(openId, templateId);
297
WxMpTemplateMsgResult result = wxService.getTemplateMsgService()
298
.sendTemplateMsg(message);
299
300
System.out.println("Sent to " + openId + " - Message ID: " + result.getMsgId());
301
302
// Add delay to avoid rate limiting
303
Thread.sleep(100);
304
305
} catch (WxErrorException e) {
306
System.err.println("Failed to send to " + openId + ": " + e.getMessage());
307
} catch (InterruptedException e) {
308
Thread.currentThread().interrupt();
309
break;
310
}
311
}
312
}
313
314
private WxMpTemplateMessage createTemplateMessage(String openId, String templateId) {
315
WxMpTemplateMessage message = new WxMpTemplateMessage();
316
message.setToUser(openId);
317
message.setTemplateId(templateId);
318
message.setUrl("https://www.example.com/user/" + openId);
319
320
// Personalized content
321
message.addData("first", "Dear Customer")
322
.addData("keyword1", "System Notification")
323
.addData("keyword2", "Important Update")
324
.addData("keyword3", new Date().toString())
325
.addData("remark", "Please check your account for details.");
326
327
return message;
328
}
329
```
330
331
### Template Message Event Handling
332
333
```java
334
// Handle template message send completion events
335
public class TemplateMsgEventHandler implements WxMpMessageHandler {
336
@Override
337
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
338
Map<String, Object> context,
339
WxMpService wxMpService,
340
WxSessionManager sessionManager) throws WxErrorException {
341
342
// Template message send status event
343
if ("TEMPLATESENDJOBFINISH".equals(wxMessage.getEvent())) {
344
String status = wxMessage.getStatus();
345
String msgId = wxMessage.getMsgId();
346
347
switch (status) {
348
case "success":
349
System.out.println("Template message " + msgId + " sent successfully");
350
break;
351
case "failed:user block":
352
System.out.println("Template message " + msgId + " failed: user blocked");
353
// Handle user block scenario
354
break;
355
case "failed:system failed":
356
System.out.println("Template message " + msgId + " failed: system error");
357
// Handle system failure
358
break;
359
default:
360
System.out.println("Template message " + msgId + " status: " + status);
361
}
362
}
363
364
return null; // No response needed for event notifications
365
}
366
}
367
368
// Register event handler
369
router.rule()
370
.msgType(WxConsts.XmlMsgType.EVENT)
371
.event("TEMPLATESENDJOBFINISH")
372
.handler(new TemplateMsgEventHandler())
373
.end();
374
```
375
376
### Custom Template Message Builder
377
378
```java
379
public class TemplateMessageBuilder {
380
381
public static WxMpTemplateMessage buildOrderNotification(String openId,
382
String orderId,
383
String status,
384
String amount,
385
String orderTime) {
386
return WxMpTemplateMessage.builder()
387
.toUser(openId)
388
.templateId("ORDER_NOTIFICATION_TEMPLATE_ID")
389
.url("https://www.example.com/order/" + orderId)
390
.build()
391
.addData("first", "Order Status Update")
392
.addData("keyword1", "Order #" + orderId)
393
.addData("keyword2", status)
394
.addData("keyword3", amount)
395
.addData("keyword4", orderTime)
396
.addData("remark", "Thank you for your business!");
397
}
398
399
public static WxMpTemplateMessage buildPaymentNotification(String openId,
400
String paymentId,
401
String amount,
402
String paymentTime) {
403
return WxMpTemplateMessage.builder()
404
.toUser(openId)
405
.templateId("PAYMENT_NOTIFICATION_TEMPLATE_ID")
406
.url("https://www.example.com/payment/" + paymentId)
407
.build()
408
.addData("first", "Payment Confirmation", "#00FF00")
409
.addData("keyword1", "Payment #" + paymentId)
410
.addData("keyword2", amount, "#FF0000")
411
.addData("keyword3", paymentTime)
412
.addData("remark", "Payment completed successfully!");
413
}
414
415
public static WxMpTemplateMessage buildAppointmentReminder(String openId,
416
String appointmentId,
417
String service,
418
String dateTime,
419
String location) {
420
return WxMpTemplateMessage.builder()
421
.toUser(openId)
422
.templateId("APPOINTMENT_REMINDER_TEMPLATE_ID")
423
.url("https://www.example.com/appointment/" + appointmentId)
424
.build()
425
.addData("first", "Appointment Reminder")
426
.addData("keyword1", service)
427
.addData("keyword2", dateTime, "#FF0000")
428
.addData("keyword3", location)
429
.addData("remark", "Please arrive 10 minutes early.");
430
}
431
}
432
433
// Usage
434
WxMpTemplateMessage orderMsg = TemplateMessageBuilder.buildOrderNotification(
435
"user_openid", "12345", "Shipped", "$99.99", "2024-01-15 10:30:00");
436
wxService.getTemplateMsgService().sendTemplateMsg(orderMsg);
437
```
438
439
### Error Handling and Retry Logic
440
441
```java
442
public class TemplateMessageSender {
443
private final WxMpService wxService;
444
private final int maxRetries = 3;
445
446
public TemplateMessageSender(WxMpService wxService) {
447
this.wxService = wxService;
448
}
449
450
public boolean sendTemplateMessageWithRetry(WxMpTemplateMessage message) {
451
for (int attempt = 1; attempt <= maxRetries; attempt++) {
452
try {
453
WxMpTemplateMsgResult result = wxService.getTemplateMsgService()
454
.sendTemplateMsg(message);
455
456
System.out.println("Message sent successfully: " + result.getMsgId());
457
return true;
458
459
} catch (WxErrorException e) {
460
int errorCode = e.getError().getErrorCode();
461
462
if (shouldRetry(errorCode) && attempt < maxRetries) {
463
System.out.println("Attempt " + attempt + " failed, retrying...");
464
try {
465
Thread.sleep(1000 * attempt); // Exponential backoff
466
} catch (InterruptedException ie) {
467
Thread.currentThread().interrupt();
468
return false;
469
}
470
} else {
471
handleTemplateMessageError(e, message);
472
return false;
473
}
474
}
475
}
476
return false;
477
}
478
479
private boolean shouldRetry(int errorCode) {
480
switch (errorCode) {
481
case -1: // System busy
482
case 45047: // Template message send frequency limit
483
case 41028: // Form id invalid or expired
484
return true;
485
case 43004: // User not subscribed
486
case 43101: // User refused to receive messages
487
return false; // Don't retry for user-related errors
488
default:
489
return false;
490
}
491
}
492
493
private void handleTemplateMessageError(WxErrorException e, WxMpTemplateMessage message) {
494
int errorCode = e.getError().getErrorCode();
495
String errorMsg = e.getError().getErrorMsg();
496
497
switch (errorCode) {
498
case 43004:
499
System.err.println("User not subscribed: " + message.getToUser());
500
// Log or handle unsubscribed users
501
break;
502
case 43101:
503
System.err.println("User refused messages: " + message.getToUser());
504
// Add to do-not-send list
505
break;
506
case 40037:
507
System.err.println("Invalid template ID: " + message.getTemplateId());
508
break;
509
case 41028:
510
System.err.println("Form ID invalid: " + message.getClientMsgId());
511
break;
512
case 45047:
513
System.err.println("Send frequency limit exceeded");
514
break;
515
default:
516
System.err.println("Template message error " + errorCode + ": " + errorMsg);
517
}
518
}
519
}
520
```
521
522
## Template Message Colors
523
524
Common color codes for template message data:
525
526
- `#173177` - Dark blue (default)
527
- `#FF0000` - Red (for important/urgent information)
528
- `#00FF00` - Green (for success/positive information)
529
- `#0000FF` - Blue (for links/actions)
530
- `#FFA500` - Orange (for warnings)
531
- `#808080` - Gray (for secondary information)
532
533
## Industry Codes
534
535
Common industry codes for template message setup:
536
537
- `1` - IT/Internet/Communication/Electronics
538
- `2` - Finance/Banking/Insurance
539
- `3` - Real Estate
540
- `4` - Education
541
- `5` - Healthcare/Medical
542
- `6` - Transportation/Logistics
543
- `7` - Entertainment/Media
544
- `8` - Government/Public Services
545
546
## Best Practices
547
548
1. **Template Selection**: Choose appropriate templates from the WeChat template library
549
2. **Content Relevance**: Ensure template content matches your business needs
550
3. **Personalization**: Use dynamic data to personalize messages
551
4. **Color Usage**: Use colors strategically to highlight important information
552
5. **URL Links**: Provide meaningful landing pages for template message links
553
6. **Rate Limiting**: Respect WeChat's sending frequency limits
554
7. **User Experience**: Don't overuse template messages to avoid user fatigue
555
8. **Error Handling**: Implement proper error handling and retry logic
556
9. **Mini Program Integration**: Use mini program links for better user experience
557
10. **Analytics**: Track template message performance and user engagement
558
559
## Rate Limits
560
561
- Maximum 100,000 template messages per day for verified accounts
562
- Maximum 1,000 template messages per day for unverified accounts
563
- No more than 4 template messages per user per day
564
- Minimum 12-hour interval between messages to the same user for some template types
565
566
## Common Error Codes
567
568
- `40037`: Invalid template_id
569
- `41028`: Form_id invalid or expired
570
- `41029`: Form_id used
571
- `41030`: Page unreachable
572
- `43004`: User not subscribed
573
- `43101`: User refused to receive messages
574
- `45047`: Template message send frequency limit exceeded
575
- `47001`: Template message data format error
576
- `47003`: Template message count exceeded daily limit