(3) WeChat development to obtain access_token, openid

First of all, we need to understand the request process of the h5 page

at the first authorization

client request url

WeChat returns a code to the client

When the user clicks to approve the authorization, he takes the code and obtains the access_token and openId. The code is valid for 5 minutes, and the access_token is a globally unique ticket with a validity period of two hours. When it expires, it needs to be re-acquired

openid is a unique identifier of the user in this public service number

access_token is a credential when you go to the WeChat server to request basic user information

Simply put, the client ---- WeChat server ---- third-party server

interaction between the three

 

First, create a new WeChat data storage class WeixinOauth2Token

 

package com.wonder.entity;

/**
 * Created by Guozhijie on 2016/10/27.
 */
public class WeixinOauth2Token {
    // Web page authorization interface call credentials
    private String accessToken;
    // how long the certificate is valid
    private int expiresIn;
    // used to refresh credentials
    private String refreshToken;
    // user ID
    private String openId;
    // user authorization scope
    private String scope;

    public String getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }

    public int getExpiresIn() {
        return expiresIn;
    }

    public void setExpiresIn(int expiresIn) {
        this.expiresIn = expiresIn;
    }

    public String getRefreshToken () {
        return refreshToken;
    }

    public void setRefreshToken(String refreshToken) {
        this.refreshToken = refreshToken;
    }

    public String getOpenId() {
        return openId;
    }

    public void setOpenId(String openId) {
        this.openId = openId;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }
}

 

 

WeChat user information class weixinUserInfo

 

package com.wonder.entity;

/**
 * Created by Guozhijie on 2016/10/27.
 */
public class WeixinUserInfo {
    // user's ID
    private String openId;
    // Follow status (1 means follow, 0 means not follow), you can't get the rest of the information when you don't follow
    private int subscribe;
    // User attention time, timestamp. If the user has followed many times, take the last follow time
    private String subscribeTime;
    // Nick name
    private String nickname;
    // User's gender (1 is male, 2 is female, 0 is unknown)
    private int sex;
    // user's country
    private String country;
    // user's province
    private String province;
    // user's city
    private String city;
    // User's language, Simplified Chinese is zh_CN
    private String language;
    // profile picture
    private String headImgUrl;

    public String getOpenId() {
        return openId;
    }

    public void setOpenId(String openId) {
        this.openId = openId;
    }

    public int getSubscribe() {
        return subscribe;
    }

    public void setSubscribe(int subscribe) {
        this.subscribe = subscribe;
    }

    public String getSubscribeTime() {
        return subscribeTime;
    }

    public void setSubscribeTime(String subscribeTime) {
        this.subscribeTime = subscribeTime;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public int getSex() {
        return sex;
    }

    public void setSex(int sex) {
        this.sex = sex;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) {
        this.language = language;
    }

    public String getHeadImgUrl() {
        return headImgUrl;
    }

    public void setHeadImgUrl(String headImgUrl) {
        this.headImgUrl = headImgUrl;
    }
}

 

 

Server Certificate Passport Class

 

package com.wonder.Util;

import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * Created by Guozhijie on 2016/10/27.
 */
public class MyX509TrustManager implements X509TrustManager {
    // Check client certificate
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    // Check server side certificate
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    // Returns an array of trusted X509 certificates
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

 Request tool class

package com.wonder.Util;

import com.wonder.entity.WeixinOauth2Token;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;
import java.io. *;
import java.net.ConnectException;
import java.net.URL;

/**
 * Created by Guozhijie on 2016/10/27.
 */
public class CommonUtil {

    private static Logger log = LoggerFactory.getLogger(CommonUtil.class);

    // Credential acquisition (GET)
    public final static String token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

    /**
     * Send https request
     *
     * @param requestUrl request address
     * @param requestMethod request method (GET, POST)
     * @param outputStr Submitted data
     * @return JSONObject (get the attribute value of the json object by JSONObject.get(key))
     */
    public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        try {
            // Create an SSLContext object and initialize it with our specified trust manager
            TrustManager[] tm = { new MyX509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // Get the SSLSocketFactory object from the above SSLContext object
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(ssf);

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // Set the request method (GET/POST)
            conn.setRequestMethod(requestMethod);

            // Write data to the output stream when outputStr is not null
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // Note the encoding format
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // Read the return content from the input stream
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }

            // release resources
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            jsonObject = JSONObject.fromObject(buffer.toString());
        } catch (ConnectException ce) {
            log.error("Connection timed out: {}", ce);
        } catch (Exception e) {
            log.error("https request exception: {}", e);
        }
        return jsonObject;
    }

    /**
     * Get interface access credentials
     *
     * @param appid credentials
     * @param appsecret key
     * @return
     */
    public static WeixinOauth2Token getToken(String appid, String appsecret, HttpServletRequest request) {
        WeixinOauth2Token wat = null;
        String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
        requestUrl = requestUrl.replace("APPID", appid);
        requestUrl = requestUrl.replace("SECRET", appsecret);
        requestUrl = requestUrl.replace("CODE", request.getParameter("code"));
        //Initiate a GET request to get the credentials
        JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);

        if (null != jsonObject) {
            try {
                what = new WeixinOauth2Token ();
                wat.setAccessToken(jsonObject.getString("access_token"));
                wat.setExpiresIn(jsonObject.getInt("expires_in"));
                wat.setRefreshToken(jsonObject.getString("refresh_token"));
                wat.setOpenId(jsonObject.getString("openid"));
                wat.setScope(jsonObject.getString("scope"));
            } catch (JSONException e) {
                what = null;
                // Failed to get token
                log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
            }
        }
        return wat;
    }

    /**
     * URL encoding (utf-8)
     *
     * @param source
     * @return
     */
    public static String urlEncodeUTF8(String source) {
        String result = source;
        try {
            result = java.net.URLEncoder.encode(source, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace ();
        }
        return result;
    }

    /**
     * Determine file extension based on content type
     *
     * @param contentType content type
     * @return
     */
    public static String getFileExt(String contentType) {
        String fileExt = "";
        if ("image/jpeg".equals(contentType))
            fileExt = ".jpg";
        else if ("audio/mpeg".equals(contentType))
            fileExt = ".mp3";
        else if ("audio/amr".equals(contentType))
            fileExt = ".amr";
        else if ("video/mp4".equals(contentType))
            fileExt = ".mp4";
        else if ("video/mpeg4".equals(contentType))
            fileExt = ".mp4";
        return fileExt;
    }
}

 

 

Then make an interceptor when accessing

package com.wonder.interceptor;

import com.wonder.Util.CommonUtil;
import com.wonder.entity.WeixinOauth2Token;
import com.wonder.entity.WeixinUserInfo;
import com.wonder.threadLocal.UserIdThreadLocal;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

/**
 * Created by Guozhijie on 2016/10/27.
 */
public class WechatInterceptor  implements HandlerInterceptor {
    public   boolean preHandle(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object handler) throws Exception{
        String uri=httpServletRequest.getRequestURI();
        WeixinUserInfo user=(WeixinUserInfo) httpServletRequest.getSession().getAttribute("user");
        if(user!=null){
            UserIdThreadLocal.setOpenId(Long.parseLong(user.getOpenId()));
            return true;
        }
        else{

            try{
                String code=httpServletRequest.getParameter("code");
                if(StringUtils.isEmpty(code)){
                   httpServletResponse.sendRedirect(getUrl(httpServletRequest));
                    return false;
                }
                else{
                    String appid="wxd1f88b3343475e07";
                    String appSecret="*************";
                    WeixinOauth2Token token= CommonUtil.getToken(appid,appSecret,httpServletRequest);
                    UserIdThreadLocal.setOpenId( Long.parseLong(token.getOpenId()));
                    WeixinUserInfo weixinUserInfo=new WeixinUserInfo();
                    weixinUserInfo.setOpenId(token.getOpenId());
                    httpServletRequest.getSession().setAttribute("user",weixinUserInfo);
                    return true;
                }
            }catch (Exception e){
                e.printStackTrace ();
                httpServletResponse.sendRedirect(getUrl(httpServletRequest));
                return false;
            }

        }

    }

    @Override
    public   void postHandle(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o, org.springframework.web.servlet.ModelAndView modelAndView) throws Exception{}

    @Override
    public void afterCompletion(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception{}


    public String getUrl(HttpServletRequest request)throws UnsupportedEncodingException{
       String requestUrl=request.getRequestURL().toString();
        String redirectUri= URLEncoder.encode(requestUrl,"utf-8");
        String appid="wxd1f88b3343475e07";
        String url="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+appid+"&redirect_uri="+redirectUri+"&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
        return url;
    }
}

 

The function of interception is when the authorization is passed, if the user is the first time, the login method is used, and then the access_token and openid, unionid and unionid are obtained through appId, secret, code and stored in the database.

If you already have this user in the session, access it directly

If the access has no code parameter and no authorization, go to geturl to get the code and go to the authorization page

 

At this point, a question is what is the access situation when you are authorized and access this url for the second time,

In fact, if your Session has expired when you visit for the second time, you can still visit because it is based on your unionid on the WeChat server.

To judge whether you have authorized and then give you a code. At this time, because of the code parameter, I got the openId and went to the database to query and found that this user can be accessed directly.

 

 

It should be noted that scope permissions are divided into two types  

 

Application authorization scope, snsapi_base (do not pop up the authorization page, jump directly, only get the user's openid), snsapi_userinfo (pop up the authorization page, you can get the nickname, gender, location through openid. And, even if you don't pay attention, As long as the user authorizes, the information can also be obtained )

 

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326172870&siteId=291194637