微信公众号(事件回调&生成带参数二维码&扫码关注事件&消息模板推送)java版

微信公众号(事件回调&生成带参数二维码&扫码关注事件&消息模板推送)java版

 1.业务处理(全部业务)

    import com.alibaba.fastjson.JSONObject;
    import org.springframework.util.StringUtils;
    import org.springframework.web.bind.annotation.*;
    import javax.servlet.http.HttpServletRequest;
    import java.util.HashMap;
    import java.util.Map;
     
     
    @RestController
    @RequestMapping("/wxPublic")
    public class WxPublic {
     
        private static final String APPID = "****公众号配置****";
        private static final String APPSECRET = "****公众号配置****";
        private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
        private static final String TICKET_URL = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=ACCESSTOKEN";
        private static final String CODE_URL = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET";
        private static final String TEMPLATE_ID = "****公众号配置****";
     
     
        /***
         * 微信服务器触发get请求用于检测签名
         * @return
         */
        @GetMapping("/receiveWx")
        @ResponseBody
        public String handleWxCheckSignature(HttpServletRequest request) {
            return request.getParameter("echostr");
        }
     
        /**
         * 微信公众号回调事件
         *
         * @param wxServiceMsgDto
         * @return
         */
        @PostMapping(value = "receiveWx")
        public String checkWxToken(@RequestBody(required = false) WxServiceMsgDto wxServiceMsgDto) {
            System.out.println("所有事件" + wxServiceMsgDto);
            //处理带参数请求
            if (null != wxServiceMsgDto &&
                !StringUtils.isEmpty(wxServiceMsgDto.getMsgType()) &&
                !StringUtils.isEmpty(wxServiceMsgDto.getEvent()) &&
                !StringUtils.isEmpty(wxServiceMsgDto.getEventKey())&& !wxServiceMsgDto.getEventKey().equals("null") &&
                (wxServiceMsgDto.getEventKey().equals("subscribe") || wxServiceMsgDto.getEvent().equals("SCAN"))
            ) {
                //发送消息
                try {
                    String token = getToken();
                    SendWeChatMsg(token, wxServiceMsgDto.getFromUserName());
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("消息发送失败");
                }
     
                //关注
                if(wxServiceMsgDto.getEvent().equals("subscribe")){
                    System.out.println("关注: " + wxServiceMsgDto.getFromUserName());
                    if(wxServiceMsgDto.getEventKey().contains("FenXiangMa")){
                        System.out.println("优惠券领取");
                    }
                }
     
                //扫码
                if(wxServiceMsgDto.getEvent().equals("SCAN")){
                    System.out.println("扫码: " + wxServiceMsgDto.getFromUserName());
                    if(wxServiceMsgDto.getEventKey().contains("YaoQingMa")){
                        System.out.println("新用户邀请");
                    }
                }
     
                System.out.println("参数: " + wxServiceMsgDto.getEventKey());
            }
            return "";
        }
     
        /**
         * 获取token
         *
         * @return token
         */
        public static String getToken() {
            // 授予形式
            String grant_type = "client_credential";
            //应用ID
            String appid = APPID;
            //密钥
            String secret = APPSECRET;
            // 接口地址拼接参数
            String getTokenApi = "https://api.weixin.qq.com/cgi-bin/token?grant_type=" + grant_type + "&appid=" + appid + "&secret=" + secret;
            String tokenJsonStr = HttpUtil.doGetPost(getTokenApi, "GET", null);
            JSONObject tokenJson = JSONObject.parseObject(tokenJsonStr);
            String token = tokenJson.get("access_token").toString();
            return token;
        }
     
        /***
         * 发送消息
         *
         * @param token
         */
        public static void SendWeChatMsg(String token, String fromUserName) {
            // 接口地址
            String sendMsgApi = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + token;
     
            //封装消息
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("touser", fromUserName);
            params.put("template_id", TEMPLATE_ID);
     
            Map<String, Object> tempdata = new HashMap<>();
            Map<String, Object> first = new HashMap<>();
            first.put("value", "测试");
            tempdata.put("first", first);
     
            Map<String, Object> keyword1 = new HashMap<>();
            keyword1.put("value", "满五十减一百");
            tempdata.put("keyword1", keyword1);
     
            Map<String, Object> keyword2 = new HashMap<>();
            keyword2.put("value", "试试");
            tempdata.put("keyword2", keyword2);
     
            Map<String, Object> keyword3 = new HashMap<>();
            keyword3.put("value", "无");
            tempdata.put("keyword3", keyword3);
     
            Map<String, Object> keyword4 = new HashMap<>();
            keyword4.put("value", "无");
            tempdata.put("keyword4", keyword4);
     
            Map<String, Object> keyword5 = new HashMap<>();
            keyword5.put("value", "请及时查看");
            tempdata.put("keyword5", keyword5);
     
            params.put("data", tempdata);
            String post = HttpUtil.doGetPost(sendMsgApi, "POST", params);
            System.out.println("消息发送成功: " + post);
        }
     
        /**
         * 获取公众号二维码Url
         *
         * @return 返回拿到的access_token及有效期
         */
        public static String getCodeUrl(String info) {
            String codeUrl = null;
            String access_token = null;
            String ticket = null;
            try {
                //获取AccessToken
                try {
                    String url = ACCESS_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);//将URL中的两个参数替换掉
                    Map<String, Object> tokenMap = HttpUtil.doGet(url);
                    access_token = String.valueOf(tokenMap.get("access_token"));
                    System.out.println("access_token: " + tokenMap);
                } catch (Exception e) {
                    System.out.println("获取access_token发生错误");
                    e.printStackTrace();
                    return null;
                }
     
                //获取Ticket接口
                try {
                    String url = TICKET_URL.replace("ACCESSTOKEN", access_token);
                    String data = "{\"expire_seconds\": 2592000, \"action_name\": \"QR_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"" + info + "\"}}}";
                    Map<String, Object> ticketMap = HttpUtil.doPost(url, data, 5000);
                    ticket = String.valueOf(ticketMap.get("ticket"));
                    System.out.println("ticket: " + ticket);
                } catch (Exception e) {
                    System.out.println("获取access_token发生错误");
                    e.printStackTrace();
                    return null;
                }
     
            } catch (Exception e) {
                System.out.println("获取公众号二维码Url发生错误");
                e.printStackTrace();
                return null;
            }
            codeUrl = CODE_URL.replace("TICKET", ticket);
            System.out.println("二维码地址(30天过期): " + codeUrl);
            return codeUrl;
        }
     
        public static void main(String[] args) {
            getCodeUrl("参数一");
            getCodeUrl("参数二");
        }
    }

2.引用封装

    import com.alibaba.fastjson.JSON;
    import com.google.gson.Gson;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
     
    import java.io.*;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.HashMap;
    import java.util.Map;
     
    /**
     * http工具类
     */
    public class HttpUtil {
     
        private static final Logger logger = LoggerFactory.getLogger(HttpUtil.class);
     
        private static final Gson gson = new Gson();
     
     
        /**
         * get方法
         *
         * @param url
         * @return
         */
        public static Map<String, Object> doGet(String url) {
            Map<String, Object> map = new HashMap<>();
            CloseableHttpClient httpClient = HttpClients.createDefault();
     
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000) //连接超时
                    .setConnectionRequestTimeout(5000)//请求超时
                    .setSocketTimeout(5000)
                    .setRedirectsEnabled(true)  //允许自动重定向
                    .build();
            HttpGet httpGet = new HttpGet(url);
            httpGet.setConfig(requestConfig);
     
            try {
                HttpResponse httpResponse = httpClient.execute(httpGet);
                if (httpResponse.getStatusLine().getStatusCode() == 200) {
     
                    String jsonResult = EntityUtils.toString(httpResponse.getEntity());
                    map = gson.fromJson(jsonResult, map.getClass());
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    httpClient.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return map;
        }
     
     
        /**
         * 封装post
         *
         * @return
         */
        public static Map<String, Object> doPost(String url, String data, int timeout) {
            Map<String, Object> map = new HashMap<>();
            CloseableHttpClient httpClient = HttpClients.createDefault();
            //超时设置
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(timeout) //连接超时
                    .setConnectionRequestTimeout(timeout)//请求超时
                    .setSocketTimeout(timeout)
                    .setRedirectsEnabled(true)  //允许自动重定向
                    .build();
            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(requestConfig);
            httpPost.addHeader("Content-Type", "text/html; chartset=UTF-8");
     
            if (data != null && data instanceof String) { //使用字符串传参
                StringEntity stringEntity = new StringEntity(data, "UTF-8");
                httpPost.setEntity(stringEntity);
            }
     
            try {
                CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
                HttpEntity httpEntity = httpResponse.getEntity();
                if (httpResponse.getStatusLine().getStatusCode() == 200) {
                    String result = EntityUtils.toString(httpEntity);
                    map = gson.fromJson(result, map.getClass());
                    return map;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    httpClient.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
     
        /**
         * 调用接口 post
         * @param apiPath
         */
        public static String doGetPost(String apiPath, String type, Map<String, Object> paramMap){
            OutputStreamWriter out = null;
            InputStream is = null;
            String result = null;
            try{
                URL url = new URL(apiPath);// 创建连接
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setDoOutput(true);
                connection.setDoInput(true);
                connection.setUseCaches(false);
                connection.setInstanceFollowRedirects(true);
                connection.setRequestMethod(type) ; // 设置请求方式
                connection.setRequestProperty("Accept", "application/json"); // 设置接收数据的格式
                connection.setRequestProperty("Content-Type", "application/json"); // 设置发送数据的格式
                connection.connect();
                if(type.equals("POST")){
                    out = new OutputStreamWriter(connection.getOutputStream(), "UTF-8"); // utf-8编码
                    out.append(JSON.toJSONString(paramMap));
                    out.flush();
                    out.close();
                }
                // 读取响应
                is = connection.getInputStream();
                int length = (int) connection.getContentLength();// 获取长度
                if (length != -1) {
                    byte[] data = new byte[length];
                    byte[] temp = new byte[512];
                    int readLen = 0;
                    int destPos = 0;
                    while ((readLen = is.read(temp)) > 0) {
                        System.arraycopy(temp, 0, data, destPos, readLen);
                        destPos += readLen;
                    }
                    result = new String(data, "UTF-8"); // utf-8编码
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return  result;
        }
     
    }

    import lombok.Data;
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
     
    /**
     * 公众号返回参数封装
     */
    @XmlRootElement(name = "xml")
    @XmlAccessorType(XmlAccessType.FIELD)
    @Data
    public class WxServiceMsgDto {
     
        @XmlElement(name = "Event")
        private String event;
     
        @XmlElement(name = "Content")
        private String content;
     
        @XmlElement(name = "MsgType")
        private String msgType;
     
        @XmlElement(name = "ToUserName")
        private String toUserName;
     
        @XmlElement(name = "EventKey")
        private String eventKey;
     
        @XmlElement(name="CreateTime")
        private String createTime;
     
        /**
         * fromUserName为关注人的openId
         **/
        @XmlElement(name = "FromUserName")
        private String fromUserName;
     
    }

欢迎关注哦~
————————————————
版权声明:本文为优快云博主「佛係老李」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:`https://blog.csdn.net/qq_37176273/article/details/124289442`
### Java 实现微信公众号关注事件回调 为了实现微信公众号关注事件回调,在Java中需要创建一个HTTP服务器来接收来自微信服务器的消息推送。当有新的用户关注公众号时,微信服务器会向预先设置好的URL发送POST请求,其中包括XML格式的数据包。 #### 创建Servlet监听器 首先定义一个`WeChatEventServlet`类继承自`HttpServlet`用于处理HTTP POST请求: ```java import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class WeChatEventServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置响应编方式 response.setContentType(&quot;text/html;charset=utf-8&quot;); try { // 解析并处理接收到的信息 String message = parseRequest(request); if (message != null &amp;&amp; !&quot;&quot;.equals(message.trim())) { // 对不同类型的消息做不同处理 processMessage(message); // 返回成功状态给微信服务器 response.getWriter().write(&quot;success&quot;); } } catch (Exception e) { e.printStackTrace(); } } private String parseRequest(HttpServletRequest request) throws Exception { // 这里可以使用第三方库如dom4j解析xml数据流 // 或者手动读取输入流转换成字符串再进一步分析 StringBuilder sb = new StringBuilder(); BufferedReader reader = request.getReader(); String line; while ((line = reader.readLine()) != null){ sb.append(line); } return sb.toString(); } private void processMessage(String xmlContent) { // 使用正则表达式或其他方法提取所需字段 // 判断是否为订阅事件,并执行相应操作 // ... } } ``` 此段代展示了如何搭建基本的服务端逻辑框架[^1]。 #### 配置web.xml文件 为了让Tomcat容器识别上述servlet,还需要在项目的WEB-INF目录下的`web.xml`文件内注册这个servlet及其映射路径: ```xml &lt;servlet&gt; &lt;servlet-name&gt;WeChatEvent&lt;/servlet-name&gt; &lt;servlet-class&gt;com.example.WeChatEventServlet&lt;/servlet-class&gt; &lt;/servlet&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;WeChatEvent&lt;/servlet-name&gt; &lt;url-pattern&gt;/wechat/event&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; ``` 这一步骤确保了外部可以通过特定URL访问到我们编写的servlet程序[^3]。 #### XML消息体结构 对于具体的业务需求来说,比如处理用户的关注行为,则需特别注意传入的XML文档中的某些标签值。例如,当发生subscribe(订阅)类型的事件时,可以从&lt;ToUserName&gt;, &lt;FromUserName&gt;, 和&lt;EventKey&gt;等节点获取必要的信息来进行后续的操作[^2]。 ```xml &lt;xml&gt; &lt;ToUserName&gt;&lt;![CDATA[toUser]]&gt;&lt;/ToUserName&gt; &lt;FromUserName&gt;&lt;![CDATA[fromUser]]&gt;&lt;/FromUserName&gt; &lt;CreateTime&gt;123456789&lt;/CreateTime&gt; &lt;MsgType&gt;&lt;![CDATA[event]]&gt;&lt;/MsgType&gt; &lt;Event&gt;&lt;![CDATA[subscribe]]&gt;&lt;/Event&gt; &lt;!-- 如果是带参数二维码关注后的事件 --&gt; &lt;!--&lt;EventKey&gt;&lt;![CDATA[qrscene_123123]]&gt;&lt;/EventKey&gt;--&gt; &lt;/xml&gt; ``` 以上就是基于Java技术栈完成微信公众平台关注事件回调接口的主要步骤和技术要点介绍。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农汉子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值