当前位置:首页|资讯

Java微信公众号开发视频学习笔记

作者:从零开始的007发布时间:2024-09-08

视频地址https://www.bilibili.com/video/BV1Av4y1V77b

第一步:开通内网穿透

网站https://natapp.cn/

使用步骤页面https://natapp.cn/article/natapp_newbie

1.注册账号

2.购买免费/付费隧道(付费优惠码B9D625E4)

微信公众号开发,隧道协议选web

3.启动本地web项目,确保http://127.0.0.1可以访问

注意项目端口号,微信公众号限定http://必须使用80端口,https://必须使用443端口。

4.下载本地版本的natapp客户端。

例如我的是win10,64位,下载解压得到natapp.exe。

5.在同文件夹下新建配置文件config.ini,内容如下,修改authtoken为你的隧道的authtoken:

[default]

authtoken=123           #对应一条隧道的authtoken

clienttoken=          #对应客户端的clienttoken,将会忽略authtoken,若无请留空,

log=none            #log 日志文件,可指定本地文件, none=不做记录,stdout=直接屏幕输出 ,默认为none

loglevel=ERROR         #日志等级 DEBUG, INFO, WARNING, ERROR 默认为 DEBUG

http_proxy=           #代理设置 如 http://10.123.10.10:3128 非代理上网用户请务必留空

6.点击natapp.exe运行(这个必须上面都完成了再执行)

打开的界面找到Forwarding http://x79ada.natappfree.cc -> 127.0.0.1:80

访问http://x79ada.natappfree.cc看是否成功

第二步:开通微信公众号测试账号

公众号-开发者工具-公众平台测试账号-开通:获得appID和appsecret

第三步:java代码

maven依赖:

<dependency>
  <groupId>org.dom4j</groupId>
  <artifactId>dom4j</artifactId>
  <version>2.1.3</version>
</dependency>
<dependency>
  <groupId>com.thoughtworks.xstream</groupId>
  <artifactId>xstream</artifactId>
  <version>1.4.11.1</version>
</dependency>
     <dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>1.2.72</version>
</dependency>

Controller类

package com.wxTest.controller;

import com.alibaba.fastjson.JSONObject;

import com.wxTest.vo.TextMessage;

import com.thoughtworks.xstream.XStream;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;

import org.dom4j.Document;

import org.dom4j.Element;

import org.dom4j.io.SAXReader;

import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletInputStream;

import javax.servlet.http.HttpServletRequest;

import java.io.*;

import java.net.HttpURLConnection;

import java.net.URL;

import java.security.MessageDigest;

import java.util.*;

@Slf4j

@RestController

@RequestMapping("/")

public class WxController {

    @GetMapping("/")

    public String test(String signature,String timestamp,String nonce,String echostr) {

//        signature微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。

//        timestamp时间戳

//        nonce随机数

//        echostr 随机字符串

        log.info("signature="+signature);

        log.info("timestamp="+timestamp);

        log.info("nonce="+nonce);

        log.info("echostr="+echostr);

        if(StringUtils.isEmpty(signature)||StringUtils.isEmpty(timestamp)||StringUtils.isEmpty(nonce)||StringUtils.isEmpty(echostr)){

            return null;

        }

        String token="123";//微信接口配置信息配置的Token

        List<String> list = Arrays.asList(token, timestamp, nonce);

        Collections.sort(list);

        StringBuilder stringBuilder = new StringBuilder();

        for(String s:list){

            stringBuilder.append(s);

        }

        try {

            MessageDigest instance = MessageDigest.getInstance("sha1");

            //sha1加密

            byte[] digest = instance.digest(stringBuilder.toString().getBytes());

            StringBuilder sum = new StringBuilder();

            for(byte b:digest){

                sum.append(Integer.toHexString((b>>4)&15));

                sum.append(Integer.toHexString(b&15));

            }

            log.info("sum="+sum);

            if(signature.equals(sum.toString())){

                return echostr;

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

        return null;

    }

    @PostMapping("/")

    public String receiveMsg(HttpServletRequest request){

        HashMap<String, String> map = new HashMap<>();

        try {

            ServletInputStream inputStream = request.getInputStream();

            SAXReader reader = new SAXReader();

            Document document = reader.read(inputStream);

            Element root = document.getRootElement();

            List<Element> elements = root.elements();

            for(Element e:elements){

                map.put(e.getName(),e.getStringValue());

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

        log.info(map.toString());

        StringBuilder xml=new StringBuilder();

        xml.append("<xml><ToUserName><![CDATA[");

        xml.append(map.get("FromUserName"));

        xml.append("]]></ToUserName><FromUserName><![CDATA[");

        xml.append(map.get("ToUserName"));

        xml.append("]]></FromUserName><CreateTime>");

        xml.append(new Date().getTime());

        xml.append("</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[");

        if("image".equals(map.get("MsgType"))){

            xml.append("收到用户图片:"+map.get("PicUrl"));

        }else{

            xml.append("收到用户消息:"+map.get("Content"));

        }

        xml.append("]]></Content></xml>");

        return getReplyMessage(map);

    }

    public static String getReplyMessage(HashMap<String, String> map) {

        TextMessage textMessage = new TextMessage();

        textMessage.setToUserName(map.get("FromUserName"));

        textMessage.setFromUserName(map.get("ToUserName"));

        textMessage.setMsgType("text");

        if("image".equals(map.get("MsgType"))){

            textMessage.setContent("收到用户图片:"+map.get("PicUrl"));

        }else{

            textMessage.setContent("收到用户消息:"+map.get("Content"));

        }

        textMessage.setCreateTime(System.currentTimeMillis()/1000);

        XStream xStream=new XStream();

        xStream.processAnnotations(TextMessage.class);

        return xStream.toXML(textMessage);

    }

    public static String doGet(String href) {

        try {

            // 创建URL对象

            URL url = new URL(href);

            // 创建HttpURLConnection对象

            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();

            // 设置请求方法为GET

            httpConn.setRequestMethod("GET");

            int responseCode = httpConn.getResponseCode();

            if (responseCode == HttpURLConnection.HTTP_OK) {

                // 读取响应体内容  

                InputStream inputStream = httpConn.getInputStream();

                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

                StringBuilder response = new StringBuilder();

                String line;

                while ((line = reader.readLine()) != null) {

                    response.append(line);

                }

                reader.close();

                inputStream.close();

                return response.toString();

            } else {

                System.out.println("GET请求失败,状态码:" + responseCode);

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

        return null;

    }

    public static String doPost(String href,String jsonInputString) {

        try {

            System.out.println("href:"+href);

            System.out.println("请求参数:"+jsonInputString);

            // 创建URL对象

            URL url = new URL(href);

            // 创建HttpURLConnection对象

            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();

            // 设置请求方法为GET

            httpConn.setRequestMethod("POST");

            // 设置请求头

            httpConn.setRequestProperty("Content-Type", "application/json; utf-8");

            httpConn.setRequestProperty("Accept", "application/json");

            // 设置是否向httpUrlConnection输出,因为这个是post请求,所以肯定会有输出,设置为true,

            // 设置是否使用缓存

            httpConn.setUseCaches(false);

            // 允许写入数据

            httpConn.setAllowUserInteraction(false);

            // 设置连接超时时间

            httpConn.setConnectTimeout(10000);

            // 设置读取超时时间

            httpConn.setReadTimeout(10000);

            // 发送POST请求必须设置如下两行

            httpConn.setDoOutput(true);

            httpConn.setDoInput(true);

            // 获取输出流

            OutputStream os = httpConn.getOutputStream();

            byte[] input = jsonInputString.getBytes("utf-8");

            os.write(input, 0, input.length);

            // 读取响应

            BufferedReader br = new BufferedReader(new InputStreamReader(httpConn.getInputStream(), "utf-8"));

            StringBuilder response = new StringBuilder();

            String responseLine = null;

            while ((responseLine = br.readLine()) != null) {

                response.append(responseLine.trim());

            }

            // 关闭连接

            httpConn.disconnect();

            br.close();

            os.close();

            return response.toString();

        } catch (Exception e) {

            e.printStackTrace();

        }

        return null;

    }

    public static void main(String[] args) {

        //获取 Access token

        String appid="你的公众号appid";

        String secret="你的公众号secret";

        String tokenStr = doGet("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+secret);

        System.out.println(tokenStr);

        JSONObject jsonObject = JSONObject.parseObject(tokenStr);

        String access_token = jsonObject.getString("access_token");

        //更新公众号菜单

        List<Map<String,Object>> button=new ArrayList<>();

        List<Map<String,Object>> sub_button=new ArrayList<>();

        Map m=new HashMap();

        m.put("type","click");

        m.put("name","今日歌曲");

        m.put("key","V1001_TODAY_MUSIC");

        button.add(m);

        m=new HashMap();

        m.put("type","view");

        m.put("name","搜搜");

        m.put("url","http://www.soso.com/");

        sub_button.add(m);

        m=new HashMap();

        m.put("type","view");

        m.put("name","百度");

        m.put("url","http://www.baidu.com/");

        sub_button.add(m);

        m=new HashMap();

        m.put("type","click");

        m.put("name","赞一个");

        m.put("key","V1001_GOOD");

        sub_button.add(m);

        m=new HashMap();

        m.put("name","菜单");

        m.put("sub_button",sub_button);

        button.add(m);

        String url="https://api.weixin.qq.com/cgi-bin/menu/create?access_token="+access_token;

        JSONObject json =new JSONObject();

        json.put("button",button);

        String resultMenu = doPost(url, json.toJSONString());

        System.out.println("菜单更新结果:"+resultMenu);

    }

}

TextMessage实体类

package com.wxTest.vo;

import com.thoughtworks.xstream.annotations.XStreamAlias;

@XStreamAlias("xml")

public class TextMessage {

//    <ToUserName><![CDATA[toUser]]></ToUserName>

//  <FromUserName><![CDATA[fromUser]]></FromUserName>

//  <CreateTime>12345678</CreateTime>

//  <MsgType><![CDATA[text]]></MsgType>

//  <Content><![CDATA[你好]]></Content>

    @XStreamAlias("ToUserName")

    private String toUserName;

    @XStreamAlias("FromUserName")

    private String fromUserName;

    @XStreamAlias("CreateTime")

    private Long createTime;

    @XStreamAlias("MsgType")

    private String msgType;

    @XStreamAlias("Content")

    private String content;

     //自己补充get和set方法,或引用lombok插件

}

第四步 接口联调与测试

1.公众号-开发者工具-公众平台测试账号-接口配置信息

点击提交看是否成功,项目是否打印日志

2.用微信关注测试微信公众号,发送文字和图片看是否有返回结果

3.执行WxController的main方法看公众号是否出现菜单



Copyright © 2024 aigcdaily.cn  北京智识时代科技有限公司  版权所有  京ICP备2023006237号-1