正式开始使用springboot进行微信公众号开发

对公众号还没有一定的了解的,请先阅读此博客 使用springboot进行微信公众号开发的准备!_码上编程的博客-CSDN博客_springboot微信公众号开发   之后再来阅读此博客

此博客将手把手教你从0开始用springboot进行微信公众号的开发。当然了,这里只是介绍初步的使用以及学习方法,详细使用或者更深层次的使用,则详细阅读微信公众号官方文档, 官方文档就是最好的教材!!

官方文档: 微信公众平台开发概述 | 微信开放文档 

本项目的源代码在gitee中,使用git clone https://gitee.com/liu-wenxin/gongzhonghao.git即可下载

1、读取流的方式接受用户消息 

公众号发送对应的消息,详细信息类型请看官方文档

目标结果    可以发现是xml数据包

代码实现

public class WeixinService {
    /**
     * 读取公众号发送过来的消息
     * @param request
     * @return
     * @throws IOException
     */
    public static String getWeixinMessage(HttpServletRequest request) throws IOException {
        ServletInputStream is = request.getInputStream();
        byte[] b=new byte[1024];
        int len;
        StringBuilder sb=new StringBuilder();
        while((len=is.read(b))!=-1){
            sb.append(new String(b,0,len));
        }
        return sb.toString();
    }
}
@RestController
public class TestweixinController {

    @RequestMapping(value="/testWeixin",method = {RequestMethod.POST,RequestMethod.GET})
    public void testWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException {

        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();

        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");

        if(Utils.check(timestamp,nonce,signature)){
            //校验正确并返回echostr,才能正式成为一名公众号开发者,即填写的URL和TOKEN才能生效
            //out.print(echostr);

            //查看用户从公众号发送过来的信息
            String result = WeixinService.getWeixinMessage(request);
            System.out.println(result);
        }else{
            //校验失败
            out.print("---请到公众号执行相应操作---");
        }
        out.flush();
        out.close();
    }
}

2、将读取的xml数据映射成map数据格式

上述方式读取公众号发送过来的信息也没毛病,但是, 当我想要获取某个节点的值就显得不是那么灵活了,并且也不方便,能不能将xml数据映射出map数据,通过操作map方式去操作xml数据

答案是:  可以的!!!

需要导入的依赖:

	<!--解析xml数据-->
		<dependency>
			<groupId>dom4j</groupId>
			<artifactId>dom4j</artifactId>
			<version>1.6.1</version>
		</dependency>

代码实现:

public class WeixinService {
   
    //以Map形式读取公众号的所有消息
    public static Map<String, String> parseRequest(InputStream is) throws IOException {
        //将输入流解析成Map
        Map<String, String> map = new HashMap<>();
        try {
            //读取输入流获取文档对象
            SAXReader reader = new SAXReader();
            Document document = reader.read(is);

            //根据文档对象获取根节点
            Element root = document.getRootElement();
            //获取所有的子节点
            List<Element> elements = root.elements();
            for (Element e : elements) {
                map.put(e.getName(), e.getStringValue());
            }

        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return map;
    }
}
@RestController
public class TestweixinController {

    @RequestMapping(value="/testWeixin",method = {RequestMethod.POST,RequestMethod.GET})
    public void testWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException {

        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();

        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");

        if(Utils.check(timestamp,nonce,signature)){
            //校验正确并返回echostr,才能正式成为一名公众号开发者,即填写的URL和TOKEN才能生效
            //out.print(echostr);

            //查看用户从公众号发送过来的信息
            Map<String, String> requestMap=WeixinService.parseRequest(request.getInputStream());
            System.out.println(requestMap);
        }else{
            //校验失败
            out.print("---请到公众号执行相应操作---");
        }
        out.flush();
        out.close();
    }
}

目标结果:

3、xml的字符串形式发送消息给用户

来而不往非礼也,用户发送信息了,可能焦急的等待公众号的回复!  通过阅读官方文档可得知,返回的数据类型也是xml数据包格式,每种类型都有严格的格式,比如:

回复文本消息

<xml>
  <ToUserName><![CDATA[toUser]]></ToUserName>
  <FromUserName><![CDATA[fromUser]]></FromUserName>
  <CreateTime>12345678</CreateTime>
  <MsgType><![CDATA[text]]></MsgType>
  <Content><![CDATA[你好]]></Content>
</xml>

 回复图片消息

<xml>
  <ToUserName><![CDATA[toUser]]></ToUserName>
  <FromUserName><![CDATA[fromUser]]></FromUserName>
  <CreateTime>12345678</CreateTime>
  <MsgType><![CDATA[image]]></MsgType>
  <Image>
    <MediaId><![CDATA[media_id]]></MediaId>
  </Image>
</xml>

代码实现

public class WeixinService {

    //以Map形式读取公众号的所有消息
    public static Map<String, String> parseRequest(InputStream is) throws IOException {
        //将输入流解析成Map
        Map<String, String> map = new HashMap<>();
        try {
            //读取输入流获取文档对象
            SAXReader reader = new SAXReader();
            Document document = reader.read(is);

            //根据文档对象获取根节点
            Element root = document.getRootElement();
            //获取所有的子节点
            List<Element> elements = root.elements();
            for (Element e : elements) {
                map.put(e.getName(), e.getStringValue());
            }

        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return map;
    }
}

这里有个坑,发送的xml数据不能有空格 ,  还有发送方与接收方的逻辑, 原来的发送方现在要变成接收方,原来的接收方要变成发送方

@RestController
public class TestweixinController {

    @RequestMapping(value="/testWeixin",method = {RequestMethod.POST,RequestMethod.GET})
    public void testWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException {

        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();

        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");

        if(Utils.check(timestamp,nonce,signature)){
            //校验正确并返回echostr,才能正式成为一名公众号开发者,即填写的URL和TOKEN才能生效
            //out.print(echostr);

            //查看用户从公众号发送过来的信息
            Map<String, String> requestMap=WeixinService.parseRequest(request.getInputStream());
            System.out.println(requestMap);

            //返回 收到了!!!给用户
            String respXml="<xml>\n" +
                    "<ToUserName><![CDATA["+requestMap.get("FromUserName")+"]]></ToUserName>\n" +
                    "<FromUserName><![CDATA["+requestMap.get("ToUserName")+"]]></FromUserName>\n" +
                    "<CreateTime>12345678</CreateTime>\n" +
                    "<MsgType><![CDATA[text]]></MsgType>\n" +
                    "<Content><![CDATA["+"收到了!!!"+"]]></Content>\n" +
                    "</xml>\n";

            out.print(respXml);
        }else{
            //校验失败
            out.print("---请到公众号执行相应操作---");
        }
        out.flush();
        out.close();
    }
}

目标结果

4、 将发送的数据解析成xml数据格式,通过操作对象的方式操作xml待返回的数据

上述方式也可以实现发送数据给用户,就是不灵活还有不方便,如果能通过操作对象的方式操作xml数据,那该有多好呀,  答案是可以实现的!!

导入的依赖

 <!--将信息封装成xml数据-->
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.8</version>
        </dependency>
        <dependency>
            <groupId>xmlpull</groupId>
            <artifactId>xmlpull</artifactId>
            <version>1.1.3.1</version>
        </dependency>
        <dependency>
            <groupId>xpp3</groupId>
            <artifactId>xpp3_min</artifactId>
            <version>1.1.4c</version>
        </dependency>

每种消息类型都含有 <ToUserName> <FromUserName> <CreateTime> <MsgType>

BaseMessage.java , 让所有的衍生类继承它,@XStreamAlias("xml")和@XStreamAlias("ToUserName") 解决映射成对象小写的问题

/*
* 所有消息的父类
* */
@Data
@NoArgsConstructor
@XStreamAlias("xml")
public class BaseMessage {
    @XStreamAlias("ToUserName")
    private String toUserName;

    @XStreamAlias("FromUserName")
    private String fromUserName;

    @XStreamAlias("CreateTime")
    private String createTime;

    @XStreamAlias("MsgType")
    private String msgType;

    public BaseMessage(Map<String,String> requestMap){
        this.toUserName= (String) requestMap.get("FromUserName");
        this.fromUserName= (String) requestMap.get("ToUserName");
        this.createTime=System.currentTimeMillis()/1000+"";
    }
}

TextMessage.java

@Data
@XStreamAlias("xml")
public class TextMessage extends BaseMessage {
    @XStreamAlias("Content")
    private String content;

    public TextMessage(Map<String, String> requestMap, String content){
        //调用父类构造方法
        super(requestMap);
        //设置类型为文本类型
        this.setMsgType("text");
        this.content=content;
    }
}

 ImageMessage.java

@Data
@XStreamAlias("xml")
public class ImageMessage extends BaseMessage {
    @XStreamAlias("Image")
    private Image image;

    public ImageMessage(Map<String,String> requestMap,Image image){
        super(requestMap);
        this.setMsgType("image");
        this.image=image;
    }
}

Image.java 

@XStreamAlias("Image")
@AllArgsConstructor
@Data
public class Image {
    @XStreamAlias("MediaId")
    private String mediaId;
}

public class WeixinService {

    //以Map形式读取公众号的所有消息
    public static Map<String, String> parseRequest(InputStream is) throws IOException {
        //将输入流解析成Map
        Map<String, String> map = new HashMap<>();
        try {
            //读取输入流获取文档对象
            SAXReader reader = new SAXReader();
            Document document = reader.read(is);

            //根据文档对象获取根节点
            Element root = document.getRootElement();
            //获取所有的子节点
            List<Element> elements = root.elements();
            for (Element e : elements) {
                map.put(e.getName(), e.getStringValue());
            }

        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return map;
    }

    /*
   *封装公众号返回信息,用于处理所有的事件和消息的回复,返回的是xml数据包
   * */
    public static String getResponse(Map<String, String> requestMap) {
        BaseMessage msg = null;
        //获取用户发送消息的类型
        String msgType = (String) requestMap.get("MsgType");
        switch (msgType) {
            case "text":
                //处理文本类型
                msg = dealTextMessage(requestMap);
                //将图文信息转成xml数据包
                //msg=dealNewsMessage(requestMap);
                //System.out.println("---返回文字类型数据---");
                break;
            case "image":
                //处理图片信息
                msg = dealImageMessage(requestMap);
                break;
            default:
                break;
        }
        if (msg != null) {
            //将信息转成xml数据包
            return beanToXml(msg);
        }
        return null;
    }

    /*
  * 把消息对象转成xml数据
  * */
    private static String beanToXml(BaseMessage msg) {
        XStream stream = new XStream();
        /*
        * 使对应类上的注解生效
        * */
        stream.processAnnotations(BaseMessage.class);
        stream.processAnnotations(TextMessage.class);
        stream.processAnnotations(ImageMessage.class);
        String xml = stream.toXML(msg);
        return xml;
    }

    /*
   * 专门处理文本消息
   * */
    private static BaseMessage dealTextMessage(Map<String, String> requestMap) {
        TextMessage textMessage=new TextMessage(requestMap,"成功获取消息!!!");
       return textMessage;
    }

    /*
  *
  *专门处理回复图片消息 requestMap是从用户从公众号发过来的数据
  * */
    private static BaseMessage dealImageMessage(Map<String, String> requestMap) {
        return null;
    }

}

@RestController
public class TestweixinController {

    @RequestMapping(value="/testWeixin",method = {RequestMethod.POST,RequestMethod.GET})
    public void testWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException {

        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();

        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");

        if(Utils.check(timestamp,nonce,signature)){
            //校验正确并返回echostr,才能正式成为一名公众号开发者,即填写的URL和TOKEN才能生效
            //out.print(echostr);

            //查看用户从公众号发送过来的信息
            Map<String, String> requestMap=WeixinService.parseRequest(request.getInputStream());

            //返回信息给用户
            String resXml = WeixinService.getResponse(requestMap);
            out.print(resXml);
        }else{
            //校验失败
            out.print("---请到公众号执行相应操作---");
        }
        out.flush();
        out.close();
    }
}

目标效果

5、获取access_token

有了access_token才能进行其它操作,比如素材管理、自定义菜单

记得将TOKEN、APPID、APPSECRET改成自己的值

代码部分

public class Utils {

    public static final String TOKEN="aabbccdd";    //TOKEN就是自己填写的
    public static final String APPID="wx18d322f947cdf313";
    public static final String APPSECRET="addf7e78f784c940ce69557cbe58b31b";

    //用于存储access_token
    private static AccessToken at;

    /*
   * 获取accessToken,有效期2小时
   * */
    private static void getToken() {

        String url = " https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "&appid=" + APPID + "&secret=" + APPSECRET;
            URL realUrl = new URL(urlNameString);

            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();

            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("Accept-Charset", "utf-8");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();

            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();

            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream(),"utf-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }

        } catch (Exception e) {
            System.out.println("发送GET请求出现异常!" + e);
            e.printStackTrace();
        }

        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }


        Gson gson = new Gson();
        HashMap hashMap = gson.fromJson(result, HashMap.class);
        String access_token = (String) hashMap.get("access_token");
        Double expires_in = (Double) hashMap.get("expires_in");
        //创建access_token,并存起来
        at = new AccessToken(access_token, expires_in);
    }

    /*
    * 获取access_token的方法    直接HttpRequest.getAccessToken()即可返回access_token值
    * */
    public static String getAccessToken() {
        if (at == null || at.isExpired()) {
            //过期则创建新的access_token
            getToken();
        }
        //返回access_token
        return at.getAccess_token();
    }

    /*
   * 验证签名
   * */
    public static boolean check(String timestamp, String nonce, String signature) {

        //1、将token、timestamp、nonce进行字典排序
        String[] strs = new String[]{TOKEN, timestamp, nonce};
        Arrays.sort(strs);

        //2、将三个参数字符串拼接成一个字符串进行sha1加密
        String str = strs[0] + strs[1] + strs[2];
        String mysignature = sha1(str);

        //返回对比结果
        return mysignature.equalsIgnoreCase(signature);
    }

    /*
     * 加密方法
     * */
    private static String sha1(String src) {

        try {
            //获取一个加密对象
            MessageDigest md = MessageDigest.getInstance("sha1");
            //加密
            byte[] digest = md.digest(src.getBytes());
            char[] chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
            StringBuffer sb = new StringBuffer();
            //处理结果集
            for (byte b : digest) {
                sb.append(chars[(b >> 4) & 15]);
                sb.append(chars[b & 15]);
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }
}
@SpringBootTest
class GongzhonghaoApplicationTests {

	@Test
	void contextLoads() {
        System.out.println("---access_token---\n"+ Utils.getAccessToken());
    }

}

目标结果

6、自定义菜单

无论是点击菜单、二级菜单、视图菜单,都有一个name的属性, 菜单的刷新需要你先取消关注公众号,然后在重新关注才能看到效果

@Data
@AllArgsConstructor
public abstract class AbstractButon {
    private String name;
}

官网要求的菜单类型数据

{
     "button":[
     {	
          "type":"click",
          "name":"今日歌曲",
          "key":"V1001_TODAY_MUSIC"
      },
      {
           "name":"菜单",
           "sub_button":[
           {	
               "type":"view",
               "name":"搜索",
               "url":"http://www.soso.com/"
            },
            {
                 "type":"miniprogram",
                 "name":"wxa",
                 "url":"http://mp.weixin.qq.com",
                 "appid":"wx286b93c14bbf93aa",
                 "pagepath":"pages/lunar/index"
             },
            {
               "type":"click",
               "name":"赞一下我们",
               "key":"V1001_GOOD"
            }]
       }]
 }


@Data
public class Button {
    private List<AbstractButon> button=new ArrayList<>();
}

点击菜单

public class ClickButton extends AbstractButon {
    private String type="click";
    private String key;

    public ClickButton(String name,String key){
        super(name);
        this.key=key;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }
}

二级菜单

public class SubButton extends AbstractButon {
    private List<AbstractButon> sub_button=new ArrayList<>();

    public SubButton(String name){
        super(name);
    }

    public List<AbstractButon> getSub_button() {
        return sub_button;
    }

    public void setSub_button(List<AbstractButon> sub_button) {
        this.sub_button = sub_button;
    }
}

发送post请求的方法:

 /**
     * 发送post请求
     * @param url 地址
     * @param data 参数
     * @return
     */
    public static String post(String url,String data){
        BufferedReader in = null;
        String result="";
        try {
            URL urlObj=new URL(url);
            URLConnection connection=urlObj.openConnection();

            //设置可发送状态
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("Accept-Charset", "utf-8");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

            //获取输出流
            OutputStream os=connection.getOutputStream();
            //写出数据
            os.write(data.getBytes("UTF-8"));
            os.close();

            //获取输入流
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            in.close();
            os.close();
            return result.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

测试

@SpringBootTest
class GongzhonghaoApplicationTests {

	@Test
	void contextLoads() {

        //一级菜单
        Button btn = new Button();
        btn.getButton().add(new ClickButton("一级菜单","1"));

        //二级菜单
        SubButton sb2=new SubButton("二级菜单");
        sb2.getSub_button().add(new ClickButton("1","21"));
        sb2.getSub_button().add(new ClickButton("2","22"));
        btn.getButton().add(sb2);


        Gson gson = new Gson();

        //向指定的url发送post请求,并携带上access_token和菜单数据
        String url="https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
        url=url.replace("ACCESS_TOKEN",Utils.getAccessToken());

        //返回结果集
        String result = Utils.post(url, gson.toJson(btn));
        System.out.println("---result---\n"+result);
    }

}

目标结果

 

 

7、菜单事件

上述菜单虽然有了,但是点击却没有任何响应,这时需要为它添上事件处理!  菜单事件类型有click(点击事件)、view(跳转链接事件)、scancode_push(扫码推事件)、view_miniprogram(跳转小程序事件)等等,详情请看官方文档。

代码部分

public class WeixinService {

    //以Map形式读取公众号的所有消息
    public static Map<String, String> parseRequest(InputStream is) throws IOException {
        //将输入流解析成Map
        Map<String, String> map = new HashMap<>();
        try {
            //读取输入流获取文档对象
            SAXReader reader = new SAXReader();
            Document document = reader.read(is);

            //根据文档对象获取根节点
            Element root = document.getRootElement();
            //获取所有的子节点
            List<Element> elements = root.elements();
            for (Element e : elements) {
                map.put(e.getName(), e.getStringValue());
            }

        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return map;
    }

    /*
   *封装公众号返回信息,用于处理所有的事件和消息的回复,返回的是xml数据包
   * */
    public static String getResponse(Map<String, String> requestMap) {
        BaseMessage msg = null;
        //获取用户发送消息的类型
        String msgType = (String) requestMap.get("MsgType");
        switch (msgType) {
            case "text":
                //处理文本类型
                msg = dealTextMessage(requestMap);
                //将图文信息转成xml数据包
                //msg=dealNewsMessage(requestMap);
                //System.out.println("---返回文字类型数据---");
                break;
            case "image":
                //处理图片信息
                msg = dealImageMessage(requestMap);
                break;
            case "event":
                //处理事件
                msg = dealEvent(requestMap);
                break;
            default:
                break;
        }
        if (msg != null) {
            //将信息转成xml数据包
            return beanToXml(msg);
        }
        return null;
    }

    /**
     * 判断菜单栏事件
     * @param requestMap
     * @return
     */
    private static BaseMessage dealEvent(Map<String, String> requestMap) {
        //判断什么事件
        String event = requestMap.get("Event");
        switch (event){
            case "CLICK":
                //详细处理点击事件
                return dealClick(requestMap);
            default:
                //其它事件
                break;
        }
        return null;
    }

    /**
     * 专门处理点击事件
     * @param requestMap
     * @return
     */
    private static BaseMessage dealClick(Map<String, String> requestMap) {
        //获取创建菜单时填的key值
        String key = requestMap.get("EventKey");
        switch (key){
            case "1":
                //点击一级菜单
                return new TextMessage(requestMap,"点击了一级菜单");
            case "21":
                //点击二级菜单的1
                return new TextMessage(requestMap,"点击二级菜单的1");
            case "22":
                //点击二级菜单的2
                return new TextMessage(requestMap,"点击二级菜单的2");
            default:
                break;
        }
        return null;
    }

    /*
  * 把消息对象转成xml数据
  * */
    private static String beanToXml(BaseMessage msg) {
        XStream stream = new XStream();
        /*
        * 使对应类上的注解生效
        * */
        stream.processAnnotations(BaseMessage.class);
        stream.processAnnotations(TextMessage.class);
        stream.processAnnotations(ImageMessage.class);
        String xml = stream.toXML(msg);
        return xml;
    }

    /*
   * 专门处理文本消息
   * */
    private static BaseMessage dealTextMessage(Map<String, String> requestMap) {
        TextMessage textMessage=new TextMessage(requestMap,"成功获取消息!!!");
       return textMessage;
    }

    /*
  *
  *专门处理回复图片消息 requestMap是从用户从公众号发过来的数据
  * */
    private static BaseMessage dealImageMessage(Map<String, String> requestMap) {
        return null;
    }

}
@RestController
public class TestweixinController {

    @RequestMapping(value="/testWeixin",method = {RequestMethod.POST,RequestMethod.GET})
    public void testWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException {

        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();

        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");

        if(Utils.check(timestamp,nonce,signature)){
            //校验正确并返回echostr,才能正式成为一名公众号开发者,即填写的URL和TOKEN才能生效
            //out.print(echostr);

            //查看用户从公众号发送过来的信息
            Map<String, String> requestMap=WeixinService.parseRequest(request.getInputStream());

            //返回信息给用户
            String resXml = WeixinService.getResponse(requestMap);
            out.print(resXml);
        }else{
            //校验失败
            out.print("---请到公众号执行相应操作---");
        }
        out.flush();
        out.close();
    }
}

目标结果

微信公众号基础开发已经结束了!!!   不要光看,需要多练多看官方文档!!

 本项目的源代码在gitee中,使用git clone https://gitee.com/liu-wenxin/gongzhonghao.git即可下载

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值