JAVA微信公众号网页开发 —— 用户授权获取openid和用户微信信息

官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

 

HttpClientUtil.java

package com.test;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
 
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
 
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
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.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
 
 
 
public class HttpClientUtil {
 
    private static class SingletonHolder{
        private final static  HttpClientUtil INSTANCE=new HttpClientUtil();
    }
 
    private HttpClientUtil(){}
 
    public static HttpClientUtil getInstance(){
        return SingletonHolder.INSTANCE;
    }
 
    public  String get(String url){
        CharsetHandler handler = new CharsetHandler("UTF-8");
        CloseableHttpClient client = null;
        try {
            HttpGet httpget = new HttpGet(new URI(url));
            HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
            client= httpClientBuilder.build();
            client = (CloseableHttpClient) wrapClient(client);
            return client.execute(httpget, handler);
        } catch (Exception e) {
            //e.printStackTrace();
            return "";
        }finally {
            try {
                if(client!=null){
                    client.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
 
    public static String post(String url, String params,String contentType)
    {
 
        //创建HttpClientBuilder
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        //HttpClient
        CloseableHttpClient client = httpClientBuilder.build();
        client = (CloseableHttpClient) wrapClient(client);
 
 
        HttpPost post = new HttpPost(url);
        CloseableHttpResponse res = null;
        try
        {
            StringEntity s = new StringEntity(params,"UTF-8");
            if(StringUtils.isBlank(contentType)){
                s.setContentType("application/json");
            }
            s.setContentType(contentType);
            s.setContentEncoding("utf-8");
            post.setEntity(s);
            res = client.execute(post);
            HttpEntity entity = res.getEntity();
            return EntityUtils.toString(entity, "utf-8");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        } finally {
            try {
                res.close();
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "";
    }
 
    public static String post(String urlStr,String xmlInfo) {
        String line1 = "";
        try {
            URL url = new URL(urlStr);
            URLConnection con = url.openConnection();
            con.setDoOutput(true);
            //con.setRequestProperty("Pragma:", "no-cache");
            con.setRequestProperty("Cache-Control", "no-cache");
            con.setRequestProperty("Content-Type", "text/xml");
 
            OutputStreamWriter out = new OutputStreamWriter(con
                    .getOutputStream());
            out.write(new String(xmlInfo.getBytes("utf-8")));
            out.flush();
            out.close();
            BufferedReader br = new BufferedReader(new InputStreamReader(con
                    .getInputStream()));
            String line = "";
            for (line = br.readLine(); line != null; line = br.readLine()) {
                line1+=line;
            }
            return new String(line1.getBytes(),"utf-8");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
 
    private class CharsetHandler implements ResponseHandler<String> {
        private String charset;
 
        public CharsetHandler(String charset) {
            this.charset = charset;
        }
 
        public String handleResponse(HttpResponse response)
                throws ClientProtocolException, IOException {
            StatusLine statusLine = response.getStatusLine();
            if (statusLine.getStatusCode() >= 300) {
                throw new HttpResponseException(statusLine.getStatusCode(),
                        statusLine.getReasonPhrase());
            }
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                if (!StringUtils.isBlank(charset)) {
                    return EntityUtils.toString(entity, charset);
                } else {
                    return EntityUtils.toString(entity);
                }
            } else {
                return null;
            }
        }
    }
 
    private static  HttpClient wrapClient(HttpClient base) {
        try {
            SSLContext ctx = SSLContext.getInstance("TLSv1");
            X509TrustManager tm = new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] xcs,
                                               String string) throws CertificateException {
                }
 
                public void checkServerTrusted(X509Certificate[] xcs,
                                               String string) throws CertificateException {
                }
 
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };
            ctx.init(null, new TrustManager[] { tm }, null);
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(ctx, new String[] { "TLSv1" }, null,
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
            return httpclient;
 
        } catch (Exception ex) {
            return null;
        }
    }
 
}

 

 

 

 

 

(注:获取到的code只能使用一次,每次请求都要重新获取一次code,因此以下方法,如果用户重新刷新了页面,就会报错,建议把使用过的code放在缓存中,每次请求接口前判断code是否已经使用,如果使用了就重新获取code去请求接口) 

 

MessageAct.java  控制器类

 

import com.redis.RedisService;
import org.apache.commons.lang.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;

@Controller
public class MessageAct {

    private String appid="公众号的APP_ID";

    private String secret="公众号的APP_SECRET";

    /**
     * redis注入,这里可以根据自己的来
     */
    @Autowired
    private RedisService redisService;

    /**
     * 微信登录
     *
     * @param code
     * @param redirectUrl 返回用户的登录地址
     * @param request
     * @param response
     * @param model
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/weixinLogin")
    public String weixinLogin(String code, String redirectUrl, HttpServletRequest request, HttpServletResponse response, ModelMap model) throws IOException {
        String redirect_uri = "redirectUrl是授权登录后要进行跳转的链接";

    //-----在这里判断code是否已经存在于缓存中,如果存在,说明code已经使用过,需要重新获取code------
        Object o = redisService.get(code);
        if (StringUtils.isNotBlank(code) && o!=null) {
            //用过了
            code = "";
        }
        //获取code
        if (StringUtils.isBlank(code)) {
            try {
                PrintWriter out = response.getWriter();
                out.println("<script>window.location.href='" + getCodeUrl(redirect_uri) + "'</script>");
                out.flush();
                out.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return null;
        }
        String[] s = getOpenId(code);
        String openId = s[0];
        String accessToken = s[1];
        //获取用户信息
        String[] userInfo = getUserInfo(openId, accessToken);
        System.out.println("手机登录openId=================================>" + openId);
        
        //查询用户是否存在,openId 作为查询条件
        User user = userMng.findById(openId); 
        if (user != null) {
            //用户已经存在

        } else {
            //用户不存在,进行注册操作
        }
        return "redirect:" + redirectUrl;
    }


    /**
     * 获取用户授权 得到openId,accessToken
     *
     * @param code
     * @return
     */
    public String[] getOpenId(String code) {
        String tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?grant_type=authorization_code";
        tokenUrl = tokenUrl + "&appid=" + appid + "&secret=" + secret + "&code=" + code;
        JSONObject json = null;
        try {
            json = new JSONObject(HttpClientUtil.getInstance().get(tokenUrl));

            //------------在这里把使用过的code存入到缓存中,我这里使用的是redis--------
            redisService.set(code,"");


        } catch (JSONException e2) {
            e2.printStackTrace();
        }
        String openId = "";
        String accessToken = "";
        String[] s = new String[2];
        if (json != null) {
            try {
                openId = json.getString("openid");
                accessToken = json.getString("access_token");
                s[0] = openId;
                s[1] = accessToken;
            } catch (JSONException e) {
                String errcode = null;
                try {
                    errcode = json.getString("errcode");
                    System.out.println("errcode================>手机登录 获取用户授权失败" + errcode);
                } catch (JSONException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return s;
    }


    /**
     * 获取用户信息 拉取用户信息(需scope为 snsapi_userinfo)
     * 只有在用户将公众号绑定到微信开放平台帐号后,可以获取unionid
     *
     * @param
     * @param
     * @return
     */
    public String[] getUserInfo(String openid, String accessToken) {
        String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?lang=zh_CN";
        userInfoUrl = userInfoUrl + "&access_token=" + accessToken + "&openid=" + openid;
        JSONObject json = null;
        try {
            json = new JSONObject(HttpClientUtil.getInstance().get(userInfoUrl));
        } catch (JSONException e2) {
            e2.printStackTrace();
        }
        String nickname = ""; //用户昵称
        String sex = "";  //用户的性别
        String province = ""; //用户个人资料填写的省份
        String city = "";  //普通用户个人资料填写的城市
        String country = ""; //国家,如中国为CN
        String headimgurl = ""; //用户头像,
        String unionid = ""; //
        String[] s = new String[6];
        if (json != null) {
            try {
                nickname = json.getString("nickname");
                sex = json.getString("sex");
                province = json.getString("province");
                city = json.getString("city");
                country = json.getString("country");
                headimgurl = json.getString("headimgurl");
                s[0] = nickname;
                s[1] = sex;
                s[2] = province;
                s[3] = city;
                s[4] = country;
                s[5] = headimgurl;
            } catch (JSONException e) {
                String errcode = null;
                try {
                    errcode = json.getString("errcode");
                    System.out.println("errcode================>获取用户信息失败" + errcode);
                } catch (JSONException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return s;
    }

    /**
     * 获取code请求地址
     *
     * @param redirect_uri  回调地址  这个回调地址需要在微信公众号后台也进行配置 不然会显示"redirect_uri域名还是与后台配置不一致"
     * @param
     * @return
     */
    public String getCodeUrl(String redirect_uri) {
        redirect_uri= URLEncoder.encode(redirect_uri);   //使用 urlEncode 对链接进行处理
        String codeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize";
        codeUrl = codeUrl + "?appid=" + appid + "&redirect_uri=" + redirect_uri
                + "&response_type=code&scope=snsapi_userinfo&state=jetcms#wechat_redirect";

        return codeUrl;
    }
}

 

posted @ 2019-03-16 16:04  yvioo  阅读(10103)  评论(0编辑  收藏  举报