微信公众号开发-用户信息拉取

概述

如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑。拉取用户信息所需步骤如下:

  1. 引导用户进入授权同意页面同意授权,获取code。
  2. 通过code换取网页授权access_token。
  3. 通过网页授权access_token和openid获取用户基本信息。
    在这里插入图片描述
第一步:用户同意授权
  1. 引导用户使用微信手机端访问规定的url:
    https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
参数说明:
APPID - 微信提供的APPID
REDIRECT_URI - 需要跳转的url,并且需要进行编码
SCOPE - 这里填写snsapi_userinfo,用以获取用户信息
STATE - 状态,重定向时会携带state
第二步:获取code

微信进行重定向时会携带code和state,这个时候我们需要进行获取。

第三步:获取access_token

利用获得到的code获取access_token,代码如下:

  String url = "https://api.weixin.qq.com/sns/oauth2/access_token?";
  Map<String, String> map = new HashMap<>();
  map.put("appid", WxConstant.APP_ID);
  map.put("secret", WxConstant.SECRET);
  map.put("grant_type", "authorization_code");
  map.put("code", code);
  String res = HttpClientUtils.doGet(url, map);
第四步:通过access_token拉取用户信息

再次发出请求,请求用户信息。

String sUrl = "https://api.weixin.qq.com/sns/userinfo?";
Map<String, String> sMap = new HashMap<>();
sMap.put("access_token", obj.getString("access_token"));
sMap.put("openid", obj.getString("openid"));
sMap.put("lang", "zh_CN");
JSONObject u = JSONObject.parseObject(HttpClientUtils.doGet(sUrl, sMap));

完整实现代码

需要引入的jar包和所需的工具类

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.2</version>
</dependency>
<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.1.1</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <version>4.4.6</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
</dependency>

简化了网络请求操作的工具类,使用了Apache的HttpClient。

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.http.NameValuePair;
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.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
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.BasicNameValuePair;
import org.apache.http.util.EntityUtils;


public class HttpClientUtils {

    public static String doGet(String url, Map<String, String> param) {

        // 创建Httpclient对象
        CloseableHttpClient httpclient = HttpClients.createDefault();

        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                for (String key : param.keySet()) {
                    builder.addParameter(key, param.get(key));
                }
            }
            URI uri = builder.build();

            // 创建http GET请求
            HttpGet httpGet = new HttpGet(uri);

            // 执行请求
            response = httpclient.execute(httpGet);
            // 判断返回状态是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }

    public static String doGet(String url) {
        return doGet(url, null);
    }

    public static String doPost(String url, Map<String, String> param) {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            // 创建参数列表
            if (param != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, param.get(key)));
                }
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"utf-8");
                httpPost.setEntity(entity);
            }
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        return resultString;
    }

    public static String doPost(String url) {
        return doPost(url, null);
    }

    public static String doPostJson(String url, String json) {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            // 创建请求内容
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        return resultString;
    }
}

以下是核心代码,顺序依次是Controller->Service->Dao->Entity

import com.lanou.wechat.service.WxService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

@RestController
@RequestMapping("/wx")
public class WxController {

    @Autowired
    private WxService wxService;

    @GetMapping("/redirect")
    public String redirect(String code, String state){
        wxService.getUserInfo(code, state);
        return "数据抓取成功";
    }
}
import com.alibaba.fastjson.JSONObject;
import com.lanou.wechat.Constant.WxConstant;
import com.lanou.wechat.dao.UserInfoDao;
import com.lanou.wechat.entity.UserInfo;
import com.lanou.wechat.utils.HttpClientUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;

@Service
public class WxService {

    @Resource
    private UserInfoDao userInfoDao;

    public void getUserInfo(String code, String state){
        //通过code获取网页授权access_token
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?";
        Map<String, String> map = new HashMap<>();
        map.put("appid", WxConstant.APP_ID);
        map.put("secret", WxConstant.SECRET);
        map.put("grant_type", "authorization_code");
        map.put("code", code);
        String res = HttpClientUtils.doGet(url, map);
        JSONObject obj = JSONObject.parseObject(res);

        //拉取用户信息
        String sUrl = "https://api.weixin.qq.com/sns/userinfo?";
        Map<String, String> sMap = new HashMap<>();
        sMap.put("access_token", obj.getString("access_token"));
        sMap.put("openid", obj.getString("openid"));
        sMap.put("lang", "zh_CN");
        JSONObject u = JSONObject.parseObject(HttpClientUtils.doGet(sUrl, sMap));

        //创建UserInfo对象
        UserInfo info = new UserInfo();
        info.setAccessToken(obj.getString("access_token"));
        info.setRefreshToken(obj.getString("refresh_token"));
        info.setOpenId(u.getString("openid"));
        info.setNickName(u.getString("nickname"));
        info.setSex(u.getString("sex"));
        info.setCountry(u.getString("country"));
        info.setProvince(u.getString("province"));
        info.setCity(u.getString("city"));
        info.setHeadImgUrl(u.getString("headimgurl"));

        //将UserInfo对象写进数据库
        try{
            userInfoDao.insert(info);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
//UserInfoDao
import com.lanou.wechat.entity.UserInfo;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserInfoDao extends BaseDao<UserInfo> {
}

//BaseDao
public interface BaseDao<T> {
   void insert(T t) throws Exception;
}
public class UserInfo {
	
	//省略 getter setter
	private int id;
	private String openId;
	private String nickName;
	private String sex;
	private String province;
	private String city;
	private String country;
	private String headImgUrl;
	private String accessToken;
	private String refreshToken;
	
}

常量定义

public class WxConstant {

    public static final String APP_ID = "你的APP_ID";

    public static final String SECRET = "你的SECRET";

}

所要用到的用户信息插入操作

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lanou.wechat.dao.UserInfoDao">
   
    <insert id="insert" parameterType="com.lanou.wechat.entity.UserInfo">
        insert into tb_userinfo 
        (nickName,gender,headImgUrl,city,province,country,accessToken,refreshToken,openId)
        values 
        (#{nickName}, #{sex}, #{headImgUrl}, #{city}, #{province}, #{country}, #{accessToken}, #{refreshToken}, #{openId})
    </insert>
    
</mapper>

总结

需要注意的是配置文件端口号必须是80,以确保安全。最终将项目打包上传就可以获取到微信用户的信息了。最终获取到的信息如图所示:
  在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值