微信公众号开发

时间:2022-12-23 00:02:04

微信公众号开发大体步骤如下:

  1. 申请公众号
  2. 购买阿里云ESC 实例
  3. 配置公众号开发者工具
  4. 搭建本地服务框架SSM
  5. 编码
  6. 部署阿里云服务器
  7. 测试

申请公众号

事物的发展顶峰必然由盛转衰、是公众号已经火了很久了,至于什么时候死,拭目以待吧。

微信申请公众号分为服务号与订阅号、*机关、企业属于服务号、个人或其他组织属于订阅号,服务号一般需要相关材料证明,并且申请费300RMB /年,订阅号一般不要什么材料(只需要个人身份证正反面照片)、也不用交费,当然订阅号功能比服务号功能少!这里我暂且申请订阅号。

申请完后就可以直接登陆进入后台管理页面

微信公众号开发

点击右上角公众号名称如图:

微信公众号开发

可以看到公众号基本详情。

购买阿里云ESC 实例

为什么 购买阿里云?因为微信公众号回调接口连接的是公网、普通用户ip 基本都是私网、故申请域名,服务器!这里说明一下、目前国内服务器供应商相对较好是阿里云、国外亚马逊、二者区别:国内网速相对国内用户比较好、加个也相对贵点、国外的价格便宜、但对于大陆用户网速较慢。我个人买的是阿里云服务器:

微信公众号开发

最重要的是购买域名、然后备案、备案这个比较麻烦,不出意外的话一个月时间就能备案成功、这里我的域名备案已经成功。

配置公众号开发者工具

点击左立列表菜单 找到“开发者工具”点击去配置公众号开发选项:

微信公众号开发

这里Appid 、AppSecret 在代码里配置,服务器配置是微信公众号服务器回调你本地服务器接口、其中url 是你服务器提供回调接口、token 令牌随便写、同时在代码里也是保持一样,EncodingAESKey 消息加密密钥、随机生成、代码里也需要配置一样,消息加解密方式,有三种:明文、兼容、私密模式、这里是兼容模式。

公众号这已经设置好后、保存并启动配置。

搭建本地服务框架SSM

  • 开发工具:
MyEclipse 2015 state 2.0  + Tomcat 8.0 + MYSQL 5.7 + JDK 1.7
  • 搭建Spring + Spring MVC + MyBatis 项目

  • 微信公众号开发

  • 初始化公众号配置信息 web.xml:
  • 微信公众号开发
  • Servlet class 如下:
package com.cn.hnust.controller;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.cn.hnust.biz.TokenThread;
import com.cn.hnust.biz.TokenThread.AccessTokenCallBack;
import com.cn.hnust.resp.AccessToken;
import com.cn.hnust.util.FileUtil;
import com.cn.hnust.util.L;
@WebServlet(name = "AccessTokenServlet")
public class AccessTokenServlet extends HttpServlet implements AccessTokenCallBack{
    private static final long serialVersionUID = -7811255688733771828L;
    public AccessTokenServlet() {

    }

    @Override
    public void init() throws ServletException {
        //获取servlet初始参数appid和appsecret
        TokenThread.appId = getInitParameter("appid");  
        TokenThread.appSecret = getInitParameter("appsecret");
        new Thread(new TokenThread(this)).start(); //启动进程
// new Thread(new MenuThread()).start();
        super.init();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        L.i("doGet", "is running");
        super.doGet(req, resp);
    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        L.i("doPost", "is running");
        super.doPost(req, resp);
    }

    @Override
    public void callBack(AccessToken accessToken) {
            FileUtil.writerLog(FileUtil.PATH,accessToken.getAccessToken());
    }

}
  • TokenThread class 如下:
package com.cn.hnust.biz;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cn.hnust.resp.AccessToken;
import com.cn.hnust.util.Config;
import com.cn.hnust.util.L;

public class TokenThread implements Runnable {
    public static String appId = "";
    public static String appSecret = "";
    public static AccessToken accessToken = null;
    private AccessTokenCallBack callback;



    public TokenThread(AccessTokenCallBack callback) {
        this.callback = callback;
    }

    @Override
    public void run() {
        while (true) {

            accessToken = this.getAccessToken();
            if (null != accessToken) {
                L.i("token", accessToken.getAccessToken());
                L.i("time", accessToken.getExpiresin()+"");
                callback.callBack(accessToken);
                    try {
                        Thread.sleep(7000 * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }// 获取到access_token 休眠7000秒
            }else{
                    try {
                        Thread.sleep(1000*3);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } //获取的access_token为空 休眠3秒
            }
        }

    }

    private AccessToken getAccessToken() {
        NetWorkHelper workHelper = new NetWorkHelper();
        String Url = String.format(Config.access_token_url,this.appId,this.appSecret);
        String result = workHelper.getHttpsResponse(Url, "");
        JSONObject json = JSON.parseObject(result);
        AccessToken token = new AccessToken();
        token.setAccessToken(json.getString("access_token"));
        token.setExpiresin(json.getInteger("expires_in"));
        return token;

    }

    public interface AccessTokenCallBack {
        public void callBack(AccessToken accessToken);
    }

}
  • NetWorkHelper class 如下:
package com.cn.hnust.biz;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class NetWorkHelper {

    public NetWorkHelper() {
        // TODO Auto-generated constructor stub
    }

    public String getMessage(String ur) {

        try {
            URL url = new URL(ur);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5 * 1000);
            conn.setRequestMethod("GET");
            InputStream inStream = conn.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "GBK"));
            String line = "";
            StringBuffer buffer = new StringBuffer();
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
            //System.out.println("result=" + buffer.toString());
            conn.disconnect();
            return buffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return "error";
        }
    }


     public void postMessage(String sender, String content, String ur) {
            // String path = "http://192.168.1.106:8009/messageApi";

            try {
                Map<String, String> requestParams = new HashMap<String, String>();
                requestParams.put("sender", "12");
                //requestParams.put("content", "中国");
                StringBuilder params = new StringBuilder();
                for (Map.Entry<String, String> entry : requestParams.entrySet()) {
                    params.append(entry.getKey());
                    params.append("=");
                    params.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
                    params.append("&");
                }
                if (params.length() > 0)
                    params.deleteCharAt(params.length() - 1);
                byte[] data = params.toString().getBytes();
                URL url = new URL(ur);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setConnectTimeout(5000);
                conn.setRequestMethod("POST");
                conn.setRequestProperty("Content-Type",
                        "application/x-www-form-urlencoded");
                conn.setRequestProperty("Content-Length",
                        String.valueOf(data.length));
                // POST方式,其实就是浏览器把数据写给服务器
                conn.setDoOutput(true); // 设置可输出流
                // OutputStream os = conn.getOutputStream(); // 获取输出流
                DataOutputStream outStream = new DataOutputStream(
                        conn.getOutputStream());
                outStream.write(data); // 将数据写给服务器
                int code = conn.getResponseCode();
                if (code == 200) {
                    InputStream is = conn.getInputStream();
                    // return StreamTools.streamToString(is);
                } else {
                    // return "网络访问失败";
                }
            } catch (Exception e) {
                e.printStackTrace();
                // return 网络访问失败;
            }
        }


     public String getURLResponse(String urlString) {
            HttpURLConnection conn = null; //连接对象
            InputStream is = null;
            String resultData = "";
            try {
                URL url = new URL(urlString); //URL对象
                conn = (HttpURLConnection) url.openConnection(); //使用URL打开一个链接
                conn.setDoInput(true); //允许输入流,即允许下载

                //在android中必须将此项设置为false
                conn.setDoOutput(false); //允许输出流,即允许上传
                conn.setUseCaches(false); //不使用缓冲
                conn.setRequestMethod("GET"); //使用get请求
                is = conn.getInputStream();   //获取输入流,此时才真正建立链接
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader bufferReader = new BufferedReader(isr);
                String inputLine = "";
                while ((inputLine = bufferReader.readLine()) != null) {
                    resultData += inputLine + "\n";
                }
                System.out.println(resultData);

            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                System.out.println("MalformedURLException:" + e.getMessage());
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                System.out.println("IOException:" + e.getMessage());
            } finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if (conn != null) {
                    conn.disconnect();
                }
            }

            return resultData;
        }


     /** * 下载文件 * @param hsUrl * @return */
    public String DownLoadHttpsFile(String hsUrl,String fileName,String ur) {
        URL url;
        InputStream is = null;
        String filePath = ur+fileName;
        try {
            url = new URL(hsUrl);
            HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
            TrustManager[] tm = {xtm};

            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, tm, null);

            con.setSSLSocketFactory(ctx.getSocketFactory());
            con.setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String arg0, SSLSession arg1) {
                    return true;
                }
            });


            con.setDoInput(true); //允许输入流,即允许下载

            //在android中必须将此项设置为false
            con.setDoOutput(false); //允许输出流,即允许上传
            con.setUseCaches(false); //不使用缓冲
            con.setRequestMethod("GET"); //使用get请求
            is = con.getInputStream();   //获取输入流,此时才真正建立链接

            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while( (len=is.read(buffer)) != -1 ){
                outStream.write(buffer, 0, len);
            }
            is.close();
            byte[] fileBytes = outStream.toByteArray();

            File file = new File(filePath);
            FileOutputStream fops = new FileOutputStream(file);
            fops.write(fileBytes);
            fops.flush();
            fops.close();
           /* Certificate[] certs = con.getServerCertificates(); for (Certificate cert : certs) { X509Certificate xcert = (X509Certificate) cert; }*/

        } catch (Exception e) {
            e.printStackTrace();
        }
        return filePath;
    }


    /** * HTTPS协议的POST请求 * @param hsUrl 请求地址 * @param json 请求数据 * @return */
    public String postHttpsResponse(String hsUrl,String json) {
        URL url;
        InputStream is = null;
        String resultData = "";
        try {
            url = new URL(hsUrl);
            HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
            TrustManager[] tm = {xtm};

            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, tm, null);

            con.setSSLSocketFactory(ctx.getSocketFactory());
            con.setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String arg0, SSLSession arg1) {
                    return true;
                }
            });


            con.setDoInput(true); //允许输入流,即允许下载

            //在android中必须将此项设置为false
            con.setDoOutput(true); //允许输出流,即允许上传
            con.setUseCaches(false); //不使用缓冲
            con.setRequestMethod("POST"); //使用post请求

            //表单数据
            if (null != json) {
                OutputStream outputStream = con.getOutputStream();
                outputStream.write(json.getBytes("UTF-8"));
                outputStream.close();
            }


            is = con.getInputStream();   //获取输入流,此时才真正建立链接
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader bufferReader = new BufferedReader(isr);
            String inputLine = "";
            while ((inputLine = bufferReader.readLine()) != null) {
                resultData += inputLine + "\n";
            }
            System.out.println(resultData);
            Certificate[] certs = con.getServerCertificates();

            for (Certificate cert : certs) {
                X509Certificate xcert = (X509Certificate) cert;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultData;
    }



    public String getHttpsResponse(String hsUrl, String requestMethod) {
        URL url;
        InputStream is = null;
        String resultData = "";
        try {
            url = new URL(hsUrl);
            HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
            TrustManager[] tm = { xtm };
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, tm, null);
            con.setSSLSocketFactory(ctx.getSocketFactory());
            con.setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String arg0, SSLSession arg1) {
                    return true;
                }

            });
            con.setDoInput(true); // 允许输入流,即允许下载
            // 在android中必须将此项设置为false
            con.setDoOutput(false); // 允许输出流,即允许上传
            con.setUseCaches(false); // 不使用缓冲
            if (null != requestMethod && !requestMethod.equals("")) {
                con.setRequestMethod(requestMethod); // 使用指定的方式
            } else {
                con.setRequestMethod("GET"); // 使用get请求
            }
            is = con.getInputStream(); // 获取输入流,此时才真正建立链接
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader bufferReader = new BufferedReader(isr);
            String inputLine = "";
            while ((inputLine = bufferReader.readLine()) != null) {
                resultData += inputLine + "\n";
            }
            Certificate[] certs = con.getServerCertificates();
            int certNum = 1;
            for (Certificate cert : certs) {
                X509Certificate xcert = (X509Certificate) cert;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultData;
    }

    private X509TrustManager xtm = new X509TrustManager() {

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            // TODO Auto-generated method stub

        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            // TODO Auto-generated method stub

        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }

    };

}
  • 微信公众号服务器回调接口类如下:
package com.cn.hnust.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.cn.hnust.biz.MessageHandler;
import com.cn.hnust.biz.ProcessReqest;
import com.cn.hnust.pojo.WxMessage;
import com.cn.hnust.service.IWechatService;
import com.cn.hnust.service.IWxService;
import com.cn.hnust.util.L;
import com.cn.hnust.util.SignUtil;

@Controller
@RequestMapping("/wx")
public class WechatController extends BaseController{
    private static final String TIMESTAMP = "timestamp";

    private static final String ECHOSTR = "echostr";

    private static final String NONCE = "nonce";

    private static final String SIGNATURE = "signature";


    @Resource
    private IWechatService wechatService;
    @Resource
    private IWxService<WxMessage> messageService;



    @RequestMapping("/req")
    public void registerWxAPI(HttpServletRequest request,HttpServletResponse response) {
        String reqMethod = request.getMethod();
        if (reqMethod.equals("GET")) {
            // 微信加密签名
            String signature = request.getParameter(SIGNATURE);
            // 时间戳

            String timestamp = request.getParameter(TIMESTAMP);
            // 随机数
            String nonce = request.getParameter(NONCE);
            // 随机字符串
            String echostr = request.getParameter(ECHOSTR);

            logger.info("===============微信公众号对接开始===============!");
            boolean valid = wechatService.checkcalidata(signature, timestamp,
                    nonce);
            if (valid) {
                PrintWriter out = null;
                try {
                    out = response.getWriter();
                    // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
                    if (SignUtil.checkSignature(signature, timestamp, nonce)) {
                        out.print(echostr);
                        out.flush();
                        logger.info("微信公众号对接成功!");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.info("微信公众号对接出现异常!");
                } finally {
                    out.close();
                    out = null;
                }
            }
        } else if (reqMethod.equals("POST")) {
            response.setContentType("text/html;charset=utf-8"); //设置输出编码格式
            String result = "";
            Map map;
            try {
                map = MessageHandler.parseXml(request);
                System.out.println("开始构造消息");
                result = MessageHandler.buildXml(map,messageService);
                if (result.equals(""))
                    result = "未正确响应";
            } catch (Exception e) {
                e.printStackTrace();
                L.i("发生异常:", e.getMessage());
            }
            try {
                response.getWriter().println(result);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @RequestMapping("chat")
    public void chat(HttpServletRequest request, HttpServletResponse response) {
        // 微信加密签名
        String signature = request.getParameter(SIGNATURE);
        // 时间戳
        String timestamp = request.getParameter(TIMESTAMP);
        // 随机数
        String nonce = request.getParameter(NONCE);

        logger.info("===============微信公众号应答开始===============!");
        boolean valid = wechatService.checkcalidata(signature, timestamp,nonce);
        if (valid) {
            PrintWriter out = null;
            try {
                out = response.getWriter();
                // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
                if (SignUtil.checkSignature(signature, timestamp, nonce)) {
                    // 调用核心业务类接收消息、处理消息
                    String respMessage = null;
                    try {
                        respMessage = ProcessReqest.process(request, response);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    out.print(respMessage);
                    out.flush();
                    logger.info("微信公众号对接成功!");
                }
            } catch (IOException e) {
                e.printStackTrace();
                logger.info("微信公众号对接出现异常!");
            } finally {
                out.close();
                out = null;
            }
        }
    }


}
  • SignUtil class 如下:
package com.cn.hnust.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SignUtil {
    // 与接口配置信息中的Token要一致
    private static final String token = "xxxxxxxx";
    private static final String EncodingAESKey = "xxxxxxxxxxxxxxxxxxxxxxxx";

    public static boolean checkSignature(String signature, String timestamp,String nonce) {
        // 从请求中(也就是微信服务器传过来的)拿到的token, timestamp, nonce
        String[] arr = new String[] { token, timestamp, nonce };
        // 将token、timestamp、nonce三个参数进行字典序排序
        sort(arr);
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
        }
        MessageDigest md = null;
        String tmpStr = null;

        try {
            md = MessageDigest.getInstance("SHA-1");
            // 将三个参数字符串拼接成一个字符串进行sha1加密
            byte[] digest = md.digest(content.toString().getBytes());
            // 将字节数组转成字符串
            tmpStr = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        content = null;
        // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信
        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
    }

    // 用于字典排序
    public static void sort(String a[]) {
        for (int i = 0; i < a.length - 1; i++) {
            for (int j = i + 1; j < a.length; j++) {
                if (a[j].compareTo(a[i]) < 0) {
                    String temp = a[i];
                    a[i] = a[j];
                    a[j] = temp;
                }
            }
        }
    }


    // 将加密后的字节数组变成字符串
    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    private static String byteToHexStr(byte mByte) {
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
                'B', 'C', 'D', 'E', 'F' };
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];

        String s = new String(tempArr);
        return s;
    }

}
  • 业务处理类 MessageHandler 如下:
package com.cn.hnust.biz;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.cn.hnust.pojo.EventType;
import com.cn.hnust.pojo.GeneralMessage;
import com.cn.hnust.pojo.MessageType;
import com.cn.hnust.pojo.MusicMessage;
import com.cn.hnust.pojo.NewsItem;
import com.cn.hnust.pojo.PictureMessage;
import com.cn.hnust.pojo.WxMessage;
import com.cn.hnust.service.IWxService;
import com.cn.hnust.util.L;

public class MessageHandler {

     public static Map parseXml(HttpServletRequest request) throws Exception {
            // 将解析结果存储在HashMap中
            Map map = new HashMap();
            // 从request中取得输入流
            InputStream inputStream = request.getInputStream();
            /* * 读取request的body内容 此方法会导致流读取问题 Premature end of file. Nested exception: * Premature end of file String requestBody = * inputStream2String(inputStream); System.out.println(requestBody); */
            // 读取输入流
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            // 得到xml根元素
            Element root = document.getRootElement();
            // 得到根元素的所有子节点
            List<Element> elementList = root.elements();
            // 遍历所有子节点
            for (Element e : elementList) {
                L.i(e.getName(), e.getText());
                map.put(e.getName(), e.getText());
            }
            // 释放资源
            inputStream.close();
            inputStream = null;
            return map;
        }

     private static String inputStream2String(InputStream is) throws IOException {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int i = -1;
            while ((i = is.read()) != -1) {
                baos.write(i);
            }
            return baos.toString();
        }


     // 根据消息类型 构造返回消息
        public static String buildXml(Map map,IWxService<WxMessage> messageService) {
            String result = "";
            String msgType = map.get("MsgType").toString();
            MessageType messageEnumType = MessageType.valueOf(MessageType.class,
                    msgType.toUpperCase());
            switch (messageEnumType) {
                case TEXT:
                    result = handleTextMessage(map,messageService);
                    break;
                case IMAGE:
                    result = handleImageMessage(map,messageService);
                    break;
                case VOICE:
                    result = handleVoiceMessage(map,messageService);
                    break;
                case VIDEO:
                    result = handleVideoMessage(map,messageService);
                    break;
                case SHORTVIDEO:
                    result = handleSmallVideoMessage(map,messageService);
                    break;
                case LOCATION:
                    result = handleLocationMessage(map,messageService);
                    break;
                case LINK:
                    result = handleLinkMessage(map,messageService);
                    break;
                case EVENT:
                    String eventType = map.get("Event").toString();
                    System.out.println("eventType:" + eventType);
                    EventType eventEnumType = EventType.valueOf(EventType.class, eventType.toUpperCase());
                    switch(eventEnumType){
                    case CLICK:
                        result = handleGetMessageEvent(map,messageService);
                        break;
                    case VIEW:
                        result = handleLinkEvent();
                        break;
                    case SCANCODE_PUSH:
                        result = handleScanPushEvent();
                        break;
                    case SCANCODE_WAITMSG:
                        result = handleScanWaitMsgEvent();
                        break;
                    case PIC_SYSPHOTO:
                        result = handlePicSystemEvent();
                        break;
                    case PIC_PHOTO_OR_ALBUM:
                        result = handlePicPhotoAlbumEvent();
                        break;
                    case PIC_WEIXIN:
                        result = handlePicWeiXinEvent();
                        break;
                    case LOCATION_SELECT:
                        result = handleLocationSelectionEvent();
                        break;

                    default:
                        break;
                    }
                    break;
                default:
                    break;
            }
            return result;
        }


        private static String handleLocationSelectionEvent() {
        // TODO Auto-generated method stub
        return null;
    }

        private static String handlePicWeiXinEvent() {
            // TODO Auto-generated method stub
            return null;
        }

        private static String handlePicPhotoAlbumEvent() {
        // TODO Auto-generated method stub
        return null;
    }

        private static String handlePicSystemEvent() {
        // TODO Auto-generated method stub
        return null;
    }

        private static String handleScanWaitMsgEvent() {
            // TODO Auto-generated method stub
            return null;
        }

        private static String handleScanPushEvent() {
            // TODO Auto-generated method stub
            return null;
        }

        private static String handleLinkEvent() {
            // TODO Auto-generated method stub
            return null;
        }

        private static String handleGetMessageEvent(Map map, IWxService<WxMessage> messageService) {
            String xml = "";
            xml = buildTextMessage(map,messageService, "你点击了天气预报");
            return xml;
        }



        private static String handleTextMessage(Map map, IWxService<WxMessage> messageService) {
            String xml = "";
            String fromUserName = map.get("FromUserName").toString();
            // 开发者微信号
            String toUserName = map.get("ToUserName").toString();
            // 消息内容
            String content = map.get("Content").toString();
            GeneralMessage msg = new GeneralMessage();
            msg.Sender = toUserName;
            msg.Receiver = fromUserName;
            msg.CreateTime = getUtcTime();
            switch (content) {
                case "文本":
                    xml = buildTextMessage(map,messageService, "这是一条文本消息");
                    break;
                case "图片":
                    xml = buildPicture(map,messageService);
                    break;
                case "音乐":
                    xml = buildMusic(map,messageService);
                    break;
                case "图文":
                    xml = buildNewsMessage(map,messageService);
                    break;
                default:
                    xml = String
                            .format("<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%s]]></Content></xml>",
                                    msg.Receiver, msg.Sender, msg.CreateTime,
                                    "请回复如下关键词:\n文本\n图片\n语音\n视频\n音乐\n图文");
                    break;
            }
            return xml;
        }

        private static String getUtcTime() {
            Date dt = new Date();// 如果不需要格式,可直接用dt,dt就是当前系统时间
            DateFormat df = new SimpleDateFormat("yyyyMMddhhmm");// 设置显示格式
            String nowTime = "";
            nowTime = df.format(dt);
            long dd = (long) 0;
            try {
                dd = df.parse(nowTime).getTime();
            } catch (Exception e) {

            }
            return String.valueOf(dd);
        }

        /** * 构造文本消息 * * @param map * @param messageService * @param content * @return */
        private static String buildTextMessage(Map map, IWxService<WxMessage> messageService, String content) {
            String fromUserName = map.get("FromUserName").toString();
            // 开发者微信号
            String toUserName = map.get("ToUserName").toString();
            WxMessage wm = new WxMessage();
            wm.setMsgid(new Date().getTime());
            wm.setContent(content);
            wm.setCreatetime(getUtcTime());
            wm.setTousername(toUserName);
            wm.setFromusername(fromUserName);
            wm.setMsgtype("text");
            messageService.save(wm);

            return String.format("<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%s]]></Content></xml>",
                    fromUserName, toUserName, getUtcTime(), content);
        }


        /** * 构造图片消息 * * @param map * @param messageService * @return */
        private static String buildPicture(Map map, IWxService<WxMessage> messageService) {
            String fromUserName = map.get("FromUserName").toString();
            String toUserName = map.get("ToUserName").toString();
            String tempMediaId = "58fFYMRjJv0V94qZJ1EeGSKRQB4CbboVBC7FAILlxxZ2AzMnVVUeiOOenxgkzv9g";

            WxMessage wm = new WxMessage();
            wm.setMsgid(new Date().getTime());
            wm.setFromusername(fromUserName);
            wm.setTousername(toUserName);
            wm.setMediaid(tempMediaId);
            wm.setMsgtype("image");
            wm.setCreatetime(getUtcTime());
            messageService.save(wm);

            return String.format("<xml>\n" +
                    "<ToUserName><![CDATA[%s]]></ToUserName>\n" +
                    "<FromUserName><![CDATA[%s]]></FromUserName>\n" +
                    "<CreateTime>%s</CreateTime>\n" +
                    "<MsgType><![CDATA[image]]></MsgType>\n" +
                    "<Image>\n" +
                    "<MediaId><![CDATA[%s]]></MediaId>\n" +
                    "</Image>\n" +
                    "</xml>", fromUserName, toUserName, getUtcTime(), tempMediaId);
        }



        /** * 构造音乐消息 * * @param map * @param messageService * @return */
        private static String buildMusic(Map map, IWxService<WxMessage> messageService) {
            MusicMessage msg = new MusicMessage();
            String fromUserName = map.get("FromUserName").toString();
            String toUserName = map.get("ToUserName").toString();


            msg.Sender = toUserName;
            msg.Receiver = fromUserName;
            msg.CreateTime = getUtcTime();
            msg.Title = "蓝莲花";
            msg.Description = "蓝莲花-许巍";
            msg.MusicURL = "http://7te94m.com1.z0.glb.clouddn.com/lanlianhua.mp3";
            msg.HQMusicUrl = "http://7te94m.com1.z0.glb.clouddn.com/lanlianhua.mp3";
            msg.ThumbMediaId = "kpNqTAk7tZ6NHhlHlEBhgUhfxjPBADbK79EfwF1RlOKAFcuKYC0eenD-ja-nTHg9";

            WxMessage wm = new WxMessage();
            wm.setMsgid(new Date().getTime());
            wm.setFromusername(fromUserName);
            wm.setTousername(toUserName);
            wm.setCreatetime(getUtcTime());
            wm.setDescription(msg.Description);
            wm.setTitle(msg.Title);
            wm.setThumbmediaid(msg.ThumbMediaId);
            wm.setUrl(msg.HQMusicUrl);
            wm.setMsgtype("music");
            messageService.save(wm);
            return String
                    .format("<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[music]]></MsgType><Music><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><MusicUrl><![CDATA[%s]]></MusicUrl><HQMusicUrl><![CDATA[%s]]></HQMusicUrl><ThumbMediaId><![CDATA[%s]]></ThumbMediaId></Music></xml>",
                            msg.Receiver, msg.Sender, getUtcTime(), msg.Title,
                            msg.Description, msg.MusicURL, msg.HQMusicUrl,
                            msg.ThumbMediaId);
        }


        /** * 构造图文消息 * * @param map * @param messageService * @return */
        private static String buildNewsMessage(Map map, IWxService<WxMessage> messageService) {
            String fromUserName = map.get("FromUserName").toString();
            String toUserName = map.get("ToUserName").toString();

            NewsItem item = new NewsItem();
            item.Title = "iOS 9.1现2大故障 iPhone基本功能遭殃";
            item.Description = "凤凰科技讯 11月9日消息,据中关村在线报道,iOS 9.1 是个颇为稳定的版本,至少初初推出时的印象是这样,现在推出接近两星期,一些颇为严重的问题开始浮现。其中两大问题,正在困扰为数不少的用户。";
            item.PicUrl = "https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png";
            item.Url = "http://tech.ifeng.com/a/20151109/41503466_0.shtml";
            String itemContent1 = buildSingleItem(item);

            NewsItem item2 = new NewsItem();
            item2.Title = "刚毕业就月薪过万的程序员 创业大街上的得意与迷茫";
            item2.Description = "DoNews11月9日消息(编辑 陈艳曲)第一次见到刚毕业的程序员小李时,正逢他在创业大街上谋到了一份工作,五位数的薪资让他更加坚信,毕业前在技术学校报一个ios开发培训班是一个多么正确的决定";
            item2.PicUrl = "http://photocdn.sohu.com/20151108/mp40396008_1446997429715_4_th_fv23.jpeg";
            item2.Url = "http://tech.hexun.com/2015-11-09/180434346.html";
            String itemContent2 = buildSingleItem(item2);

            WxMessage wm = new WxMessage();
            wm.setMsgid(new Date().getTime());
            wm.setFromusername(fromUserName);
            wm.setTousername(toUserName);
            wm.setTitle(item.Title);
            wm.setCreatetime(getUtcTime());
            wm.setDescription(item.Description);
            wm.setPicurl(item.PicUrl);
            wm.setUrl(item.Url);
            wm.setMsgtype("news");

            messageService.save(wm);
            String content = String.format("<xml>\n" +
                    "<ToUserName><![CDATA[%s]]></ToUserName>\n" +
                    "<FromUserName><![CDATA[%s]]></FromUserName>\n" +
                    "<CreateTime>%s</CreateTime>\n" +
                    "<MsgType><![CDATA[news]]></MsgType>\n" +
                    "<ArticleCount>%s</ArticleCount>\n" +
                    "<Articles>\n" + "%s" +
                    "</Articles>\n" +
                    "</xml> ", fromUserName, toUserName, getUtcTime(), 2, itemContent1 + itemContent2);
            return content;

        }


        /** * 生成图文消息的一条记录 * * @param item * @return */
        private static String buildSingleItem(NewsItem item) {
            String itemContent = String.format("<item>\n" +
                    "<Title><![CDATA[%s]]></Title> \n" +
                    "<Description><![CDATA[%s]]></Description>\n" +
                    "<PicUrl><![CDATA[%s]]></PicUrl>\n" +
                    "<Url><![CDATA[%s]]></Url>\n" +
                    "</item>", item.Title, item.Description, item.PicUrl, item.Url);
            return itemContent;
        }



        /** * 接收到图片消息后处理 * * @param map * @param messageService * @return */
        private static String handleImageMessage(Map map, IWxService<WxMessage> messageService) {
            String picUrl = map.get("PicUrl").toString();
            String mediaId = map.get("MediaId").toString();
            System.out.print("picUrl:"+picUrl);
            System.out.print("mediaId:" + mediaId);
            String result = String.format("已收到您发来的图片,图片Url为:%s\n图片素材Id为:%s",picUrl,mediaId);
            return buildTextMessage(map,messageService,result);
        }

        private static String handleVoiceMessage(Map map, IWxService<WxMessage> messageService){
            String format = map.get("Format").toString();
            String mediaId = map.get("MediaId").toString();
            System.out.print("format:"+format);
            System.out.print("mediaId:" + mediaId);
            String result = String.format("已收到您发来的语音,语音格式为:%s\n语音素材Id为:%s",format,mediaId);
            return buildTextMessage(map,messageService,result);
        }
        private static String handleVideoMessage(Map map, IWxService<WxMessage> messageService){
            String thumbMediaId = map.get("ThumbMediaId").toString();
            String mediaId = map.get("MediaId").toString();
            System.out.print("thumbMediaId:"+thumbMediaId);
            System.out.print("mediaId:" + mediaId);
            String result = String.format("已收到您发来的视频,视频中的素材ID为:%s\n视频Id为:%s",thumbMediaId,mediaId);
            return buildTextMessage(map,messageService,result);
        }
        private static String handleSmallVideoMessage(Map map, IWxService<WxMessage> messageService){
            String thumbMediaId = map.get("ThumbMediaId").toString();
            String mediaId = map.get("MediaId").toString();
            System.out.print("thumbMediaId:"+thumbMediaId);
            System.out.print("mediaId:" + mediaId);
            String result = String.format("已收到您发来的小视频,小视频中素材ID为:%s,\n小视频Id为:%s",thumbMediaId,mediaId);
            return buildTextMessage(map,messageService,result);
        }
        private static String handleLocationMessage(Map map, IWxService<WxMessage> messageService){
            String latitude = map.get("Location_X").toString();  //纬度
            String longitude = map.get("Location_Y").toString();  //经度
            String label = map.get("Label").toString();  //地理位置精度
            String result = String.format("纬度:%s\n经度:%s\n地理位置:%s",latitude,longitude,label);
            return buildTextMessage(map,messageService,result);
        }
        private static String handleLinkMessage(Map map, IWxService<WxMessage> messageService){
            String title = map.get("Title").toString();
            String description = map.get("Description").toString();
            String url = map.get("Url").toString();
            String result = String.format("已收到您发来的链接,链接标题为:%s,\n描述为:%s\n,链接地址为:%s",title,description,url);
            return buildTextMessage(map,messageService,result);
        }


}

至此,基本代码完成。

部署阿里云服务器

主要是把tomcat web app 目录下storm 部署阿里云服务器上,重启tomcat 即可!

测试

关注公众号,随便输入如图:

微信公众号开发

微信公众号开发

微信公众号开发

进入微信后台:

微信公众号开发

进入我自己写的页面:

微信公众号开发

微信公众号开发

微信公众号开发

至此 ,公众号讲解到此为止。