Comprehensive Java SDK for WeChat Official Account development with complete API coverage for user management, messaging, materials, menus, and WeChat platform features.
—
Send template messages to users with dynamic content for notifications, confirmations, and personalized communications.
interface WxMpTemplateMsgService {
// Template message operations
WxMpTemplateMsgResult sendTemplateMsg(WxMpTemplateMessage templateMessage) throws WxErrorException;
List<WxMpTemplate> getAllPrivateTemplate() throws WxErrorException;
String addTemplate(String shortTemplateId) throws WxErrorException;
boolean delPrivateTemplate(String templateId) throws WxErrorException;
// Industry management
WxMpTemplateIndustry getIndustry() throws WxErrorException;
void setIndustry(WxMpTemplateIndustry industry) throws WxErrorException;
// Subscribe message support (for Mini Programs)
List<WxMpSubscribeMessage> getSubscribeMessages() throws WxErrorException;
}class WxMpTemplateMessage implements Serializable {
private String toUser;
private String templateId;
private String url;
private WxMpTemplateMessage.MiniProgram miniProgram;
private String clientMsgId;
private List<WxMpTemplateData> data;
public String getToUser();
public void setToUser(String toUser);
public String getTemplateId();
public void setTemplateId(String templateId);
public String getUrl();
public void setUrl(String url);
public MiniProgram getMiniProgram();
public void setMiniProgram(MiniProgram miniProgram);
public String getClientMsgId();
public void setClientMsgId(String clientMsgId);
public List<WxMpTemplateData> getData();
public void setData(List<WxMpTemplateData> data);
// Convenience methods
public WxMpTemplateMessage addData(WxMpTemplateData datum);
public WxMpTemplateMessage addData(String name, String value);
public WxMpTemplateMessage addData(String name, String value, String color);
public static class MiniProgram implements Serializable {
private String appid;
private String pagepath;
private Boolean usePath;
public String getAppid();
public void setAppid(String appid);
public String getPagepath();
public void setPagepath(String pagepath);
public Boolean getUsePath();
public void setUsePath(Boolean usePath);
}
}
class WxMpTemplateData implements Serializable {
private String name;
private String value;
private String color;
public WxMpTemplateData();
public WxMpTemplateData(String name, String value);
public WxMpTemplateData(String name, String value, String color);
public String getName();
public void setName(String name);
public String getValue();
public void setValue(String value);
public String getColor();
public void setColor(String color);
}class WxMpTemplateMsgResult implements Serializable {
private String msgId;
public String getMsgId();
public void setMsgId(String msgId);
}class WxMpTemplate implements Serializable {
private String templateId;
private String title;
private String primaryIndustry;
private String deputyIndustry;
private String content;
private String example;
public String getTemplateId();
public void setTemplateId(String templateId);
public String getTitle();
public void setTitle(String title);
public String getPrimaryIndustry();
public void setPrimaryIndustry(String primaryIndustry);
public String getDeputyIndustry();
public void setDeputyIndustry(String deputyIndustry);
public String getContent();
public void setContent(String content);
public String getExample();
public void setExample(String example);
}class WxMpTemplateIndustry implements Serializable {
private String primaryIndustryCode;
private String primaryIndustryName;
private String secondaryIndustryCode;
private String secondaryIndustryName;
public String getPrimaryIndustryCode();
public void setPrimaryIndustryCode(String primaryIndustryCode);
public String getPrimaryIndustryName();
public void setPrimaryIndustryName(String primaryIndustryName);
public String getSecondaryIndustryCode();
public void setSecondaryIndustryCode(String secondaryIndustryCode);
public String getSecondaryIndustryName();
public void setSecondaryIndustryName(String secondaryIndustryName);
}class WxMpSubscribeMessage implements Serializable {
private String priTmplId;
private String title;
private String content;
private String example;
private Integer type;
public String getPriTmplId();
public void setPriTmplId(String priTmplId);
public String getTitle();
public void setTitle(String title);
public String getContent();
public void setContent(String content);
public String getExample();
public void setExample(String example);
public Integer getType();
public void setType(Integer type);
}// Create template message
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
.toUser("user_openid")
.templateId("template_id")
.url("https://www.example.com/details")
.build();
// Add template data
templateMessage.addData("first", "Hello!")
.addData("keyword1", "Order #12345", "#173177")
.addData("keyword2", "Processing", "#FF0000")
.addData("keyword3", "2024-01-15 10:30:00")
.addData("remark", "Thank you for your order!", "#0000FF");
// Send message
WxMpTemplateMsgResult result = wxService.getTemplateMsgService()
.sendTemplateMsg(templateMessage);
System.out.println("Message sent with ID: " + result.getMsgId());// Create template message with mini program link
WxMpTemplateMessage templateMessage = new WxMpTemplateMessage();
templateMessage.setToUser("user_openid");
templateMessage.setTemplateId("template_id");
// Set mini program
WxMpTemplateMessage.MiniProgram miniProgram = new WxMpTemplateMessage.MiniProgram();
miniProgram.setAppid("miniprogram_appid");
miniProgram.setPagepath("pages/order/detail?id=12345");
miniProgram.setUsePath(true);
templateMessage.setMiniProgram(miniProgram);
// Set fallback URL for users without mini program support
templateMessage.setUrl("https://www.example.com/order/12345");
// Add data
List<WxMpTemplateData> dataList = new ArrayList<>();
dataList.add(new WxMpTemplateData("first", "Order Update"));
dataList.add(new WxMpTemplateData("keyword1", "Order #12345"));
dataList.add(new WxMpTemplateData("keyword2", "Shipped"));
dataList.add(new WxMpTemplateData("keyword3", "2024-01-15"));
dataList.add(new WxMpTemplateData("remark", "Your order has been shipped!"));
templateMessage.setData(dataList);
// Send message
WxMpTemplateMsgResult result = wxService.getTemplateMsgService()
.sendTemplateMsg(templateMessage);// Generate unique client message ID for deduplication
String clientMsgId = "client_msg_" + System.currentTimeMillis();
WxMpTemplateMessage templateMessage = new WxMpTemplateMessage();
templateMessage.setToUser("user_openid");
templateMessage.setTemplateId("template_id");
templateMessage.setClientMsgId(clientMsgId); // Prevents duplicate sends
templateMessage.setUrl("https://www.example.com");
// Add data
templateMessage.addData("first", "Payment Confirmation")
.addData("keyword1", "Payment Success")
.addData("keyword2", "$99.99")
.addData("keyword3", "2024-01-15 14:30:00")
.addData("remark", "Payment completed successfully!");
WxMpTemplateMsgResult result = wxService.getTemplateMsgService()
.sendTemplateMsg(templateMessage);// Get all private templates
List<WxMpTemplate> templates = wxService.getTemplateMsgService()
.getAllPrivateTemplate();
System.out.println("Available templates:");
for (WxMpTemplate template : templates) {
System.out.println("ID: " + template.getTemplateId());
System.out.println("Title: " + template.getTitle());
System.out.println("Content: " + template.getContent());
System.out.println("Example: " + template.getExample());
System.out.println("---");
}
// Add new template from template library
String shortTemplateId = "TM00015"; // Template library ID
String templateId = wxService.getTemplateMsgService().addTemplate(shortTemplateId);
System.out.println("Added template with ID: " + templateId);
// Delete private template
boolean deleted = wxService.getTemplateMsgService()
.delPrivateTemplate("template_id_to_delete");
if (deleted) {
System.out.println("Template deleted successfully");
}// Set industry information
WxMpTemplateIndustry industry = new WxMpTemplateIndustry();
industry.setPrimaryIndustryCode("1"); // IT/Internet/Communication/Electronics
industry.setSecondaryIndustryCode("4"); // Internet/E-commerce
wxService.getTemplateMsgService().setIndustry(industry);
// Get current industry
WxMpTemplateIndustry currentIndustry = wxService.getTemplateMsgService().getIndustry();
System.out.println("Primary: " + currentIndustry.getPrimaryIndustryName());
System.out.println("Secondary: " + currentIndustry.getSecondaryIndustryName());public void sendBatchTemplateMessages(List<String> userOpenIds, String templateId) {
for (String openId : userOpenIds) {
try {
WxMpTemplateMessage message = createTemplateMessage(openId, templateId);
WxMpTemplateMsgResult result = wxService.getTemplateMsgService()
.sendTemplateMsg(message);
System.out.println("Sent to " + openId + " - Message ID: " + result.getMsgId());
// Add delay to avoid rate limiting
Thread.sleep(100);
} catch (WxErrorException e) {
System.err.println("Failed to send to " + openId + ": " + e.getMessage());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
private WxMpTemplateMessage createTemplateMessage(String openId, String templateId) {
WxMpTemplateMessage message = new WxMpTemplateMessage();
message.setToUser(openId);
message.setTemplateId(templateId);
message.setUrl("https://www.example.com/user/" + openId);
// Personalized content
message.addData("first", "Dear Customer")
.addData("keyword1", "System Notification")
.addData("keyword2", "Important Update")
.addData("keyword3", new Date().toString())
.addData("remark", "Please check your account for details.");
return message;
}// Handle template message send completion events
public class TemplateMsgEventHandler implements WxMpMessageHandler {
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context,
WxMpService wxMpService,
WxSessionManager sessionManager) throws WxErrorException {
// Template message send status event
if ("TEMPLATESENDJOBFINISH".equals(wxMessage.getEvent())) {
String status = wxMessage.getStatus();
String msgId = wxMessage.getMsgId();
switch (status) {
case "success":
System.out.println("Template message " + msgId + " sent successfully");
break;
case "failed:user block":
System.out.println("Template message " + msgId + " failed: user blocked");
// Handle user block scenario
break;
case "failed:system failed":
System.out.println("Template message " + msgId + " failed: system error");
// Handle system failure
break;
default:
System.out.println("Template message " + msgId + " status: " + status);
}
}
return null; // No response needed for event notifications
}
}
// Register event handler
router.rule()
.msgType(WxConsts.XmlMsgType.EVENT)
.event("TEMPLATESENDJOBFINISH")
.handler(new TemplateMsgEventHandler())
.end();public class TemplateMessageBuilder {
public static WxMpTemplateMessage buildOrderNotification(String openId,
String orderId,
String status,
String amount,
String orderTime) {
return WxMpTemplateMessage.builder()
.toUser(openId)
.templateId("ORDER_NOTIFICATION_TEMPLATE_ID")
.url("https://www.example.com/order/" + orderId)
.build()
.addData("first", "Order Status Update")
.addData("keyword1", "Order #" + orderId)
.addData("keyword2", status)
.addData("keyword3", amount)
.addData("keyword4", orderTime)
.addData("remark", "Thank you for your business!");
}
public static WxMpTemplateMessage buildPaymentNotification(String openId,
String paymentId,
String amount,
String paymentTime) {
return WxMpTemplateMessage.builder()
.toUser(openId)
.templateId("PAYMENT_NOTIFICATION_TEMPLATE_ID")
.url("https://www.example.com/payment/" + paymentId)
.build()
.addData("first", "Payment Confirmation", "#00FF00")
.addData("keyword1", "Payment #" + paymentId)
.addData("keyword2", amount, "#FF0000")
.addData("keyword3", paymentTime)
.addData("remark", "Payment completed successfully!");
}
public static WxMpTemplateMessage buildAppointmentReminder(String openId,
String appointmentId,
String service,
String dateTime,
String location) {
return WxMpTemplateMessage.builder()
.toUser(openId)
.templateId("APPOINTMENT_REMINDER_TEMPLATE_ID")
.url("https://www.example.com/appointment/" + appointmentId)
.build()
.addData("first", "Appointment Reminder")
.addData("keyword1", service)
.addData("keyword2", dateTime, "#FF0000")
.addData("keyword3", location)
.addData("remark", "Please arrive 10 minutes early.");
}
}
// Usage
WxMpTemplateMessage orderMsg = TemplateMessageBuilder.buildOrderNotification(
"user_openid", "12345", "Shipped", "$99.99", "2024-01-15 10:30:00");
wxService.getTemplateMsgService().sendTemplateMsg(orderMsg);public class TemplateMessageSender {
private final WxMpService wxService;
private final int maxRetries = 3;
public TemplateMessageSender(WxMpService wxService) {
this.wxService = wxService;
}
public boolean sendTemplateMessageWithRetry(WxMpTemplateMessage message) {
for (int attempt = 1; attempt <= maxRetries; attempt++) {
try {
WxMpTemplateMsgResult result = wxService.getTemplateMsgService()
.sendTemplateMsg(message);
System.out.println("Message sent successfully: " + result.getMsgId());
return true;
} catch (WxErrorException e) {
int errorCode = e.getError().getErrorCode();
if (shouldRetry(errorCode) && attempt < maxRetries) {
System.out.println("Attempt " + attempt + " failed, retrying...");
try {
Thread.sleep(1000 * attempt); // Exponential backoff
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
return false;
}
} else {
handleTemplateMessageError(e, message);
return false;
}
}
}
return false;
}
private boolean shouldRetry(int errorCode) {
switch (errorCode) {
case -1: // System busy
case 45047: // Template message send frequency limit
case 41028: // Form id invalid or expired
return true;
case 43004: // User not subscribed
case 43101: // User refused to receive messages
return false; // Don't retry for user-related errors
default:
return false;
}
}
private void handleTemplateMessageError(WxErrorException e, WxMpTemplateMessage message) {
int errorCode = e.getError().getErrorCode();
String errorMsg = e.getError().getErrorMsg();
switch (errorCode) {
case 43004:
System.err.println("User not subscribed: " + message.getToUser());
// Log or handle unsubscribed users
break;
case 43101:
System.err.println("User refused messages: " + message.getToUser());
// Add to do-not-send list
break;
case 40037:
System.err.println("Invalid template ID: " + message.getTemplateId());
break;
case 41028:
System.err.println("Form ID invalid: " + message.getClientMsgId());
break;
case 45047:
System.err.println("Send frequency limit exceeded");
break;
default:
System.err.println("Template message error " + errorCode + ": " + errorMsg);
}
}
}Common color codes for template message data:
#173177 - Dark blue (default)#FF0000 - Red (for important/urgent information)#00FF00 - Green (for success/positive information)#0000FF - Blue (for links/actions)#FFA500 - Orange (for warnings)#808080 - Gray (for secondary information)Common industry codes for template message setup:
1 - IT/Internet/Communication/Electronics2 - Finance/Banking/Insurance3 - Real Estate4 - Education5 - Healthcare/Medical6 - Transportation/Logistics7 - Entertainment/Media8 - Government/Public Services40037: Invalid template_id41028: Form_id invalid or expired41029: Form_id used41030: Page unreachable43004: User not subscribed43101: User refused to receive messages45047: Template message send frequency limit exceeded47001: Template message data format error47003: Template message count exceeded daily limitInstall with Tessl CLI
npx tessl i tessl/maven-com-github-binarywang--weixin-java-mp