java WeChat public number development case
- 2020-05-17 05:39:09
- OfStack
WeChat public account development 1 is generally targeted at enterprises and organizations, and individual 1 can only apply for subscription Numbers, and the calling interface is limited, we will briefly describe the steps to access the public number:
1. First of all, you need 1 mailbox to register on the WeChat public account platform;
The way to register is subscription number, public number, small program and enterprise number, we can only choose the subscription number here
2. After registration, we log on to the public account platform --
>
- development
>
Basic configuration, URL and token need to be filled here. URL is the interface of the server we use.
3. If the Java Web server program is compiled and deployed on the server and can be run, the online interface debugging can be conducted on the WeChat public number:
1) select the appropriate interface
2) the system will generate the parameter table of the interface, and you can directly fill in the corresponding parameter values in the text box (the red asterisk represents the required field).
3) click the check question button to get the corresponding debugging information
eg: steps to get access_token:
1) interface type: basic support
2) interface list: get access_token interface /token
3) fill in the corresponding parameters: grant_type, appid, secret
4) click to check the problem
5) the result and the prompt will be returned if the validation is successful. The result is 200 ok, and the prompt is Request successful, which means the validation is successful
What we verify more here is message interface debugging: text messages, picture messages, voice messages, video messages, etc
4, the interface does not understand the place, can enter the development --
>
Developer tools --
>
Developer documentation is queried
5, interface rights: subscription number mainly has basic support, receive messages and web services inside 1 some interfaces
Let's focus on how subscription Numbers receive messages:
1. You need to apply for a personal WeChat subscription number
2. url server and server-side code deployment (tencent cloud or aliyun server can be used)
1) class AccountsServlet. java, verify message processing from WeChat server and WeChat server
package cn.jon.wechat.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.jon.wechat.service.AccountsService;
import cn.jon.wechat.utils.SignUtil;
public class AccountsServlet extends HttpServlet {
public AccountsServlet() {
super();
}
public void destroy() {
super.destroy();
// Put your code here
}
/**
* The confirmation request came from the WeChat server
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println(" Interface testing started!! ");
// WeChat encrypted signature
String signature = request.getParameter("signature");
// The time stamp
String timestamp = request.getParameter("timestamp");
// The random number
String nonce = request.getParameter("nonce");
// Random string
String echostr = request.getParameter("echostr");
PrintWriter out = response.getWriter();
// Through the check signature The request is validated and returned as is if the validation is successful echostr , means the access is successful, otherwise the access fails
if(SignUtil.checkSignature(signature,timestamp,nonce)){
out.print(echostr);
}
out.close();
out = null;
// response.encodeRedirectURL("success.jsp");
}
/**
* Process messages from the WeChat server
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Message acceptance, processing, and response
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
// The core business type is invoked to accept and process the message
String respMessage = AccountsService.processRequest(request);
// The response message
PrintWriter out = response.getWriter();
out.print(respMessage);
out.close();
}
public void init() throws ServletException {
// Put your code here
}
}
2) SignUtil. java class, request calibration tool class, token needs to be corresponding to token1 in WeChat
package cn.jon.wechat.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* Request validation utility class
* @author jon
*/
public class SignUtil {
// With WeChat configuration in Token1 to
private static String token = "";
public static boolean checkSignature(String signature, String timestamp,
String nonce) {
String[] arra = new String[]{token,timestamp,nonce};
// will signature,timestamp,nonce It's an array for lexicographical sort
Arrays.sort(arra);
StringBuilder sb = new StringBuilder();
for(int i=0;i<arra.length;i++){
sb.append(arra[i]);
}
MessageDigest md = null;
String stnStr = null;
try {
md = MessageDigest.getInstance("SHA-1");
byte[] digest = md.digest(sb.toString().getBytes());
stnStr = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Free memory
sb = null;
// will sha1 The encrypted string and signature By contrast, identify that the request is from WeChat
return stnStr!=null?stnStr.equals(signature.toUpperCase()):false;
}
/**
* Converts a byte array to 106 Base string
* @param digestArra
* @return
*/
private static String byteToStr(byte[] digestArra) {
// TODO Auto-generated method stub
String digestStr = "";
for(int i=0;i<digestArra.length;i++){
digestStr += byteToHexStr(digestArra[i]);
}
return digestStr;
}
/**
* Converts the byte to 106 Base string
*/
private static String byteToHexStr(byte dByte) {
// TODO Auto-generated method stub
char[] Digit = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char[] tmpArr = new char[2];
tmpArr[0] = Digit[(dByte>>>4)&0X0F];
tmpArr[1] = Digit[dByte&0X0F];
String s = new String(tmpArr);
return s;
}
public static void main(String[] args) {
/*byte dByte = 'A';
System.out.println(byteToHexStr(dByte));*/
Map<String,String> map = new ConcurrentHashMap<String, String>();
map.put("4", "zhangsan");
map.put("100", "lisi");
Set set = map.keySet();
Iterator iter = set.iterator();
while(iter.hasNext()){
// String keyV = (String) iter.next();
String key =(String)iter.next();
System.out.println(map.get(key));
// System.out.println(map.get(iter.next()));
}
/*for(int i=0;i<map.size();i++){
}*/
}
}
3) AccountsService.java service class, which mainly deals with the request and response of messages, and when users follow your public account, they can set the default push messages
package cn.jon.wechat.service;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import cn.jon.wechat.message.req.ImageMessage;
import cn.jon.wechat.message.req.LinkMessage;
import cn.jon.wechat.message.req.LocationMessage;
import cn.jon.wechat.message.req.VideoMessage;
import cn.jon.wechat.message.req.VoiceMessage;
import cn.jon.wechat.message.resp.TextMessage;
import cn.jon.wechat.utils.MessageUtil;
/**
* Decoupling, which separates the control layer from the business logic layer, mainly deals with requests and responses
* @author jon
*/
public class AccountsService {
public static String processRequest(HttpServletRequest request) {
String respMessage = null;
// The text message content returned by default
String respContent = " Request handling exception, please try later! ";
try {
//xml Request parsing
Map<String,String> requestMap = MessageUtil.pareXml(request);
// Sender account ( open_id )
String fromUserName = requestMap.get("FromUserName");
// The public accounts
String toUserName = requestMap.get("ToUserName");
// Message type
String msgType = requestMap.get("MsgType");
// Reply to this text message by default
TextMessage defaultTextMessage = new TextMessage();
defaultTextMessage.setToUserName(fromUserName);
defaultTextMessage.setFromUserName(toUserName);
defaultTextMessage.setCreateTime(new Date().getTime());
defaultTextMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_TEXT);
defaultTextMessage.setFuncFlag(0);
// Due to the href Attribute values must be caused by double quotation marks, which conflict with the double quotation marks of the string itself, so escape
defaultTextMessage.setContent(" Welcome to visit <a href=\"http://blog.csdn.net/j086924\">jon The blog </a>!");
// defaultTextMessage.setContent(getMainMenu());
// Converts the text message object to xml string
respMessage = MessageUtil.textMessageToXml(defaultTextMessage);
// A text message
if(msgType.equals(MessageUtil.MESSSAGE_TYPE_TEXT)){
//respContent = "Hi, You are sending a text message! ";
// Reply text message
TextMessage textMessage = new TextMessage();
// textMessage.setToUserName(toUserName);
// textMessage.setFromUserName(fromUserName);
// It is important to note that otherwise the message cannot be returned to the user
textMessage.setToUserName(fromUserName);
textMessage.setFromUserName(toUserName);
textMessage.setCreateTime(new Date().getTime());
textMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_TEXT);
textMessage.setFuncFlag(0);
respContent = "Hi , your message is: "+requestMap.get("Content");
textMessage.setContent(respContent);
respMessage = MessageUtil.textMessageToXml(textMessage);
}
// Picture message
else if(msgType.equals(MessageUtil.MESSSAGE_TYPE_IMAGE)){
ImageMessage imageMessage=new ImageMessage();
imageMessage.setToUserName(fromUserName);
imageMessage.setFromUserName(toUserName);
imageMessage.setCreateTime(new Date().getTime());
imageMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_IMAGE);
//respContent=requestMap.get("PicUrl");
imageMessage.setPicUrl("http://img24.pplive.cn//2013//07//24//12103112092_230X306.jpg");
respMessage = MessageUtil.imageMessageToXml(imageMessage);
}
// The geographical position
else if(msgType.equals(MessageUtil.MESSSAGE_TYPE_LOCATION)){
LocationMessage locationMessage=new LocationMessage();
locationMessage.setToUserName(fromUserName);
locationMessage.setFromUserName(toUserName);
locationMessage.setCreateTime(new Date().getTime());
locationMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_LOCATION);
locationMessage.setLocation_X(requestMap.get("Location_X"));
locationMessage.setLocation_Y(requestMap.get("Location_Y"));
locationMessage.setScale(requestMap.get("Scale"));
locationMessage.setLabel(requestMap.get("Label"));
respMessage = MessageUtil.locationMessageToXml(locationMessage);
}
// Video message
else if(msgType.equals(MessageUtil.MESSSAGE_TYPE_VIDEO)){
VideoMessage videoMessage=new VideoMessage();
videoMessage.setToUserName(fromUserName);
videoMessage.setFromUserName(toUserName);
videoMessage.setCreateTime(new Date().getTime());
videoMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_VIDEO);
videoMessage.setMediaId(requestMap.get("MediaId"));
videoMessage.setThumbMediaId(requestMap.get("ThumbMediaId"));
respMessage = MessageUtil.videoMessageToXml(videoMessage);
}
// Links to news
else if(msgType.equals(MessageUtil.MESSSAGE_TYPE_LINK)){
LinkMessage linkMessage=new LinkMessage();
linkMessage.setToUserName(fromUserName);
linkMessage.setFromUserName(toUserName);
linkMessage.setCreateTime(new Date().getTime());
linkMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_LINK);
linkMessage.setTitle(requestMap.get("Title"));
linkMessage.setDescription(requestMap.get("Description"));
linkMessage.setUrl(requestMap.get("Url"));
respMessage = MessageUtil.linkMessageToXml(linkMessage);
}
// Voice message
else if(msgType.equals(MessageUtil.MESSSAGE_TYPE_VOICE)){
VoiceMessage voiceMessage=new VoiceMessage();
voiceMessage.setToUserName(fromUserName);
voiceMessage.setFromUserName(toUserName);
voiceMessage.setCreateTime(new Date().getTime());
voiceMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_VOICE);
voiceMessage.setMediaId(requestMap.get("MediaId"));
voiceMessage.setFormat(requestMap.get("Format"));
respMessage = MessageUtil.voiceMessageToXml(voiceMessage);
}
// Event push
else if(msgType.equals(MessageUtil.MESSSAGE_TYPE_EVENT)){
// The event type
String eventType = requestMap.get("Event");
// To subscribe to
if(eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)){
respContent = " Thanks for your attention! ";
}
// unsubscribe
else if(eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)){
//
System.out.println(" unsubscribe ");
}
else if(eventType.equals(MessageUtil.EVENT_TYPE_CLICK)){
// Custom menu message handling
System.out.println(" Custom menu message handling ");
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return respMessage;
}
public static String getMainMenu()
{
StringBuffer buffer =new StringBuffer();
buffer.append(" A: hello, I am jon, Please reply to the digital selection service :").append("\n");
buffer.append("1 , my blog ").append("\n");
buffer.append("2 , Songs on demand ").append("\n");
buffer.append("3 , Classic game ").append("\n");
buffer.append("4 Chatting and playing CARDS ").append("\n\n");
buffer.append(" reply "+"0"+" Show help menu ");
return buffer.toString();
}
}
4) MessageUtil.java help class, including the definition of constants and xml message transformation and processing
package cn.jon.wechat.utils;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import cn.jon.wechat.message.req.ImageMessage;
import cn.jon.wechat.message.req.LinkMessage;
import cn.jon.wechat.message.req.LocationMessage;
import cn.jon.wechat.message.req.VideoMessage;
import cn.jon.wechat.message.req.VoiceMessage;
import cn.jon.wechat.message.resp.Article;
import cn.jon.wechat.message.resp.MusicMessage;
import cn.jon.wechat.message.resp.NewsMessage;
import cn.jon.wechat.message.resp.TextMessage;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
/**
* Processing classes for various messages
* @author jon
*/
public class MessageUtil {
/**
* Text type
*/
public static final String MESSSAGE_TYPE_TEXT = "text";
/**
* Music type
*/
public static final String MESSSAGE_TYPE_MUSIC = "music";
/**
* Graphic type
*/
public static final String MESSSAGE_TYPE_NEWS = "news";
/**
* Video type
*/
public static final String MESSSAGE_TYPE_VIDEO = "video";
/**
* Image type
*/
public static final String MESSSAGE_TYPE_IMAGE = "image";
/**
* Link type
*/
public static final String MESSSAGE_TYPE_LINK = "link";
/**
* Geographic location type
*/
public static final String MESSSAGE_TYPE_LOCATION = "location";
/**
* Audio type
*/
public static final String MESSSAGE_TYPE_VOICE = "voice";
/**
* Push type
*/
public static final String MESSSAGE_TYPE_EVENT = "event";
/**
* Event type: subscribe (subscription)
*/
public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";
/**
* Event type: unsubscribe (unsubscribe)
*/
public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
/**
* Event type: click (custom menu click event)
*/
public static final String EVENT_TYPE_CLICK= "CLICK";
/**
* Parse the request from WeChat XML
*/
@SuppressWarnings("unchecked")
public static Map<String,String> pareXml(HttpServletRequest request) throws Exception {
// Store the parsed results in HashMap In the
Map<String,String> reqMap = new HashMap<String, String>();
// from request Gets the input stream in
InputStream inputStream = request.getInputStream();
// Read input stream
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
// get xml The root element
Element root = document.getRootElement();
// Gets all the child nodes of the root element
List<Element> elementList = root.elements();
// Traverses all the child nodes to get the information class
for(Element elem:elementList){
reqMap.put(elem.getName(),elem.getText());
}
// Release resources
inputStream.close();
inputStream = null;
return reqMap;
}
/**
* The response message is transformed into xml return
* Text object to xml
*/
public static String textMessageToXml(TextMessage textMessage) {
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
/**
* The speech object is converted into xml
*
*/
public static String voiceMessageToXml(VoiceMessage voiceMessage) {
xstream.alias("xml", voiceMessage.getClass());
return xstream.toXML(voiceMessage);
}
/**
* The video object is converted to xml
*
*/
public static String videoMessageToXml(VideoMessage videoMessage) {
xstream.alias("xml", videoMessage.getClass());
return xstream.toXML(videoMessage);
}
/**
* The conversion of music objects into xml
*
*/
public static String musicMessageToXml(MusicMessage musicMessage) {
xstream.alias("xml", musicMessage.getClass());
return xstream.toXML(musicMessage);
}
/**
* Text object into xml
*
*/
public static String newsMessageToXml(NewsMessage newsMessage) {
xstream.alias("xml", newsMessage.getClass());
xstream.alias("item", new Article().getClass());
return xstream.toXML(newsMessage);
}
/**
* The image object is converted to xml
*
*/
public static String imageMessageToXml(ImageMessage imageMessage)
{
xstream.alias("xml",imageMessage.getClass());
return xstream.toXML(imageMessage);
}
/**
* Link object to xml
*
*/
public static String linkMessageToXml(LinkMessage linkMessage)
{
xstream.alias("xml",linkMessage.getClass());
return xstream.toXML(linkMessage);
}
/**
* The geographical location object is converted to xml
*
*/
public static String locationMessageToXml(LocationMessage locationMessage)
{
xstream.alias("xml",locationMessage.getClass());
return xstream.toXML(locationMessage);
}
/**
* expand xstream , so as to support CDATA block
*
*/
private static XStream xstream = new XStream(new XppDriver(){
public HierarchicalStreamWriter createWriter(Writer out){
return new PrettyPrintWriter(out){
// For all the xml The conversion of nodes is increased CDATA tag
boolean cdata = true;
@SuppressWarnings("unchecked")
public void startNode(String name,Class clazz){
super.startNode(name,clazz);
}
protected void writeText(QuickWriter writer,String text){
if(cdata){
writer.write("<![CDATA[");
writer.write(text);
writer.write("]]>");
}else{
writer.write(text);
}
}
};
}
});
}
5), BaseMessage.java message base class (including: developer WeChat ID, user account, creation time, message type, message ID variable), text, video, picture messages will inherit this base class, on this basis to expand their own variables, can be defined according to the developer document in a variety of message properties
package cn.jon.wechat.message.req;
/**
* The message the base class (general user - The public)
* @author jon
*/
public class BaseMessage {
// Developer WeChat ID
private String ToUserName;
// Sender account ( 1 a openId )
private String FromUserName;
// Message creation time (integer)
private long CreateTime;
// Message type ( text/image/location/link... )
private String MsgType;
// The message id 64 An integer
private String MsgId;
public BaseMessage() {
super();
// TODO Auto-generated constructor stub
}
public BaseMessage(String toUserName, String fromUserName, long createTime,
String msgType, String msgId) {
super();
ToUserName = toUserName;
FromUserName = fromUserName;
CreateTime = createTime;
MsgType = msgType;
MsgId = msgId;
}
public String getToUserName() {
return ToUserName;
}
public void setToUserName(String toUserName) {
ToUserName = toUserName;
}
public String getFromUserName() {
return FromUserName;
}
public void setFromUserName(String fromUserName) {
FromUserName = fromUserName;
}
public long getCreateTime() {
return CreateTime;
}
public void setCreateTime(long createTime) {
CreateTime = createTime;
}
public String getMsgType() {
return MsgType;
}
public void setMsgType(String msgType) {
MsgType = msgType;
}
public String getMsgId() {
return MsgId;
}
public void setMsgId(String msgId) {
MsgId = msgId;
}
}
6) TextMessage.java text message, inherited from the base class 5, extends the content properties
package cn.jon.wechat.message.req;
/**
* A text message
* @author jon
*/
public class TextMessage extends BaseMessage{
// The message content
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
7) ImageMessage.java picture message
package cn.jon.wechat.message.req;
/**
* Picture message
* @author jon
*/
public class ImageMessage extends BaseMessage{
// Image links
private String PicUrl;
public String getPicUrl() {
return PicUrl;
}
public void setPicUrl(String picUrl) {
PicUrl = picUrl;
}
}
8) VideoMessage.java video message
package cn.jon.wechat.message.req;
public class VideoMessage extends BaseMessage {
private String mediaId;
private String thumbMediaId;
public String getMediaId() {
return mediaId;
}
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}
public String getThumbMediaId() {
return thumbMediaId;
}
public void setThumbMediaId(String thumbMediaId) {
this.thumbMediaId = thumbMediaId;
}
}
Other message classes can be completed by themselves according to the developer documentation. In addition, the developer can also apply for a public platform test account to test the relevant content of the development.
This article has been sorted into "Android WeChat development tutorial summary", "java WeChat development tutorial summary" welcome to learn to read.