Java微信公众获取用户信息

Java微信公众获取用户信息踩的坑记录一下

1、测试号

地址:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index

记得修改为自己的域名:例子 example.test.com

接下来就是干货,上Java代码

@RequestMapping(value = "/wxLogin", method = RequestMethod.GET)
public String wxLogin() throws ParseException {
    // 这个url的域名必须要进行再公众号中进行注册验证,这个地址是成功后的回调地址
    String backUrl = "http://xxx.xxx.xxx/wx/callBack";
    // 第一步:用户同意授权,获取code
    String getCodeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WXAuthUtil.APPID
            + "&redirect_uri=" + URLEncoder.encode(backUrl)
            + "&response_type=code"
            + "&scope=snsapi_userinfo"
            + "&state=STATE#wechat_redirect";

    logger.info("获取code, getCodeUrl=" + getCodeUrl);
    // response.sendRedirect(url);
    return "redirect:" + getCodeUrl;// 必须重定向,否则不能成功
}
   @GetMapping(value = "/callBack")
    public String callBack(Model model) throws ServletException, IOException {

        String code = request.getParameter("code");
        // 第二步:通过code换取网页授权access_token
        String getTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + WXAuthUtil.APPID + "&secret="
                + WXAuthUtil.APPSECRET + "&code=" + code + "&grant_type=authorization_code";
        logger.info("获取token,getTokenUrl=" + getTokenUrl);
        JSONObject getTokenJson = WXAuthUtil.doGetJson(getTokenUrl);
        /*
         * { "access_token":"ACCESS_TOKEN", "expires_in":7200,
         * "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" }
         */
        logger.info("获取token,getTokenJson=" + getTokenJson.toJSONString());

        String openid = getTokenJson.getString("openid");
        String access_token = getTokenJson.getString("access_token");
        String refresh_token = getTokenJson.getString("refresh_token");

        // 第五步验证access_token是否失效;展示都不需要
        String vlidTokenUrl = "https://api.weixin.qq.com/sns/auth?access_token=" + access_token + "&openid=" + openid;
        logger.info("验证token,vlidTokenUrl=" + vlidTokenUrl);
        JSONObject validTokenJson = WXAuthUtil.doGetJson(vlidTokenUrl);
        logger.info("验证token,validTokenJson=" + validTokenJson.toJSONString());
        if (!"0".equals(validTokenJson.getString("errcode"))) {
            // 第三步:刷新access_token(如果需要)-----暂时没有使用,参考文档https://mp.weixin.qq.com/wiki,
            String refreshTokenUrl = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + openid
                    + "&grant_type=refresh_token&refresh_token=" + refresh_token;
            logger.info("刷新token,refreshTokenUrl=" + refreshTokenUrl);
            JSONObject refreshTokenJson = WXAuthUtil.doGetJson(refreshTokenUrl);
            /*
             * { "access_token":"ACCESS_TOKEN", "expires_in":7200,
             * "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" }
             */
            logger.info("刷新token,refreshTokenJson=" + refreshTokenJson.toJSONString());
            access_token = refreshTokenJson.getString("access_token");
        }

        // 第四步:拉取用户信息(需scope为 snsapi_userinfo)
        String getUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid=" + openid
                + "&lang=zh_CN";
        logger.info("获取用户信息,getUserInfoUrl=" + getUserInfoUrl.toString());
        JSONObject getUserInfoJson = WXAuthUtil.doGetJson(getUserInfoUrl);
        /*
         * { "openid":" OPENID", " nickname": NICKNAME, "sex":"1", "province":"PROVINCE"
         * "city":"CITY", "country":"COUNTRY", "headimgurl":
         * "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
         * "privilege":[ "PRIVILEGE1" "PRIVILEGE2" ], "unionid":
         * "o6_bmasdasdsad6_2sgVt7hMZOPfL" }
         */
        logger.info("获取用户信息,getUserInfoJson=" + getUserInfoJson.toString());
        /*
         * end 获取微信用户基本信息
         */
        // 获取到用户信息后就可以进行重定向,走自己的业务逻辑了。。。。。。
        // 缓存 + 1
        redisService.incr(ArtKey.isNum,"" + "1");

        // 取缓存
        String numStr = redisService.get(ArtKey.isNum, "" + "1", String.class);

        model.addAttribute("name",getUserInfoJson.get("nickname"));
        model.addAttribute("count",numStr);

        // 回调到页面
        return "index";
    }
}
public static final String APPID = "XXX";
//    public static final String APPID = "XXX";

    public static final String APPSECRET = "XXX";
//    public static final String APPSECRET = "XXX";

    // 与接口配置信息中的Token要一致
    private static String token = "XXX";

    public static JSONObject doGetJson(String url) throws ClientProtocolException, IOException {
        JSONObject jsonObject = null;
        DefaultHttpClient client = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(url);
        HttpResponse response = client.execute(httpGet);
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            // 把返回的结果转换为JSON对象
            String result = EntityUtils.toString(entity, "UTF-8");
            jsonObject = JSON.parseObject(result);
        }
        return jsonObject;
    }

到这儿呢,第一个测试就能跑通了。

接下来,跑第二个测试

URL:(验证微信数字签名的接口)

Token:自己设置

@Slf4j
@RestController
@RequestMapping("/wechat")
public class WechatController {

    /**
     * 微信公众号签名认证接口
     * @Title: test
     * @Description: TODO
     * @param: @param signature
     * @param: @param timestamp
     * @param: @param nonce
     * @param: @param echostr
     * @param: @return
     * @return: String
     * @throws
     */
    @RequestMapping("/wxToken")
    public String test(String signature,String timestamp,String nonce,String echostr) {

        // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
        if (signature != null && WXAuthUtil.checkSignature(signature, timestamp, nonce)) {
            return echostr;
        }
        return null;
    }
}
/**
 * 验证签名
 *
 * @param signature
 * @param timestamp
 * @param nonce
 * @return
 */
public static boolean checkSignature(String signature, String timestamp, String nonce) {
    String[] arr = new String[] { token, timestamp, nonce };
    // 将token、timestamp、nonce三个参数进行字典序排序
    // Arrays.sort(arr);
    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;
}

/**
 * 将字节数组转换为十六进制字符串
 *
 * @param byteArray
 * @return
 */
private static String byteToStr(byte[] byteArray) {
    String strDigest = "";
    for (int i = 0; i < byteArray.length; i++) {
        strDigest += byteToHexStr(byteArray[i]);
    }
    return strDigest;
}

/**
 * 将字节转换为十六进制字符串
 *
 * @param mByte
 * @return
 */
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;
}

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;
            }
        }
    }
}

第二个测试跑通了

,接下来就是公众号上的配置了。

参考:

https://www.zhongjianghua.com/att1tude/10205-2020-04.html

https://blog.csdn.net/qq_36654629/article/details/91877299

https://www.kanzhun.com/jiaocheng/534258.html

 


版权声明:本文为zy1104560031原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。