微信公众号-入门的坑

641 阅读4分钟

写自未接触过公众号,也不知道什么是token的搬运工。

一、需求

要求后台管理系统生成带用户标签的二维码,用户扫码后获取参数并为用户打上标签,之后微信根据标签的不同显示不同的菜单

二、技术调研

生成带参数的二维码

  • 首先需要获得access_token,可以根据appid和secret直接调用接口直接获取,但是是新生成的并且是占用了次数,可以从token管理中获取一个未失效的token
  • 根据token调用获取所有标签的接口,获得标签id
  • 根据token调用获得二维码ticket的接口,根据参数设置有效时长和是否有效
  • 根据ticket调用查看二维码接口

搭建微信认证服务器

  • git搜索公众号demo
  • 修改appid、secret、令牌、密钥参数
  • 修改开源项目端口为80,使用https://natapp.cn/内网穿透到本地80端口
  • 将穿透的域名认证服务器的地址填写到公众号服务器地址上
  • 之后就可以愉快的打断点,随意调教

三、结果

流程是没有问题的,能够实现,只不过标签对应的自定义菜单是在第三方维护的,用户扫码后立刻能打上标签,但是并不能立刻显示对应的自定义菜单,好像很5分钟获取一次菜单有关。需求不了了之。

四、上线

  • 后续,两星期之后上线,配置认证服务器之后,每次获取的token都是40001,token失效,清除redis存储的缓存之后,获取的token不到1小时又失效了,查看了官方文档,原本2小时的有效期,根本不靠谱,随后又修改token刷新时间,基本稳定。

四、坑-总结

  • 坑不大,只要看着微信文档就可以知道调什么接口,搜索也很方便,比百度好使。文档整理:

获取用户信息标签文档:mp.weixin.qq.com/wiki?t=reso…

为用户打标签接口文档:mp.weixin.qq.com/wiki?t=reso…

关注获取到参数:mp.weixin.qq.com/wiki?t=reso…

  • token的获取最好由一个服务提供,还需要配置白名单,不可能每个项目都生成token

  • 推荐入门开源项目:github.com/binarywang/… 项目为weixin-java-tools的Demo演示程序,推荐了内网穿透的使用,而且是springboot项目,基本事件的处理。

  • 更加强大的开源项目:github.com/Wechat-Grou… 内容太多,代码优美,学习一下如何构建微信项目。

  • 发起http请求,可以使用apache.http.client、okHttp。贴出apache工具类:若有觉得不怎么好,可自行百度

彻底入门OkHttp使用 blog.csdn.net/u013651026/…

package com.wechat.web.util;

import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
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.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import javax.servlet.ServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
 
public class HttpUtil {
    /**
     *
     * @param url 请求地址
     * @param data 请求数据
     * @return String 响应string
     * @throws Exception 异常
     */
    public static String post(String url, Map<String,String> data) throws Exception{
        HttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);

        if (data != null) {
            List<NameValuePair> nvps = new ArrayList<>();
            data.forEach((key, value) -> {
                nvps.add(new BasicNameValuePair(key, value));
            });
            httpPost.setEntity(new UrlEncodedFormEntity(nvps));
        }
        ResponseHandler<String> responseHandler = getStringResponseHandler();
        return httpClient.execute(httpPost, responseHandler);
    }

    /**
     * @param url  请求地址
     * @param body 请求数据
     * @return responseContent 响应数据
     */
    public static String post(String url, String body) {
        String responseContent = "";
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json");

            StringEntity s = new StringEntity(body, "utf-8");
            s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
            httpPost.setEntity(s);

//            httpPost.setEntity(new StringEntity(body));

            response = httpClient.execute(httpPost);

            HttpEntity entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, Consts.UTF_8);

        } catch (ParseException | IOException e) {
            e.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return responseContent;
    }

    /**
     *
     * @param url 请求地址
     * @throws Exception todo 是否异常
     */
    public static String get(String url) {
        HttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        ResponseHandler<String> responseHandler = getStringResponseHandler();
        try {
            return httpClient.execute(httpGet, responseHandler);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     *     Create a custom response handler
     */
    private static ResponseHandler<String> getStringResponseHandler() {
        return (final HttpResponse response) -> {
            int status = response.getStatusLine().getStatusCode();
            if (status >= 200 && status < 300) {
                HttpEntity entity = response.getEntity();
                return entity != null ? EntityUtils.toString(entity, Consts.UTF_8) : null;
            } else {
                throw new ClientProtocolException("Unexpected response status: " + status);
            }
        };
    }


    /**
     * 获取请求Body
     *
     * @param request ServletRequest
     * @return String
     */
    public static String getBodyString(ServletRequest request) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }

}