• 在线教育项目-day12【微信扫码登录】


    一、准备工作

    1、注册

    2、邮箱激活

    3、完善开发者资料

    4、开发者资质认证

    准备营业执照,1-2个工作日审批、300元

    5、创建网站应用

    提交审核,7个工作日审批

    6、熟悉微信登录流程

    参考文档:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=e547653f995d8f402704d5cb2945177dc8aa4e7e&lang=zh_CN

    二、后端开发

    1.添加配置

    # 微信开放平台 appid
    wx.open.app_id=wxed9954c01bb89b47
    # 微信开放平台 appsecret
    wx.open.app_secret=a7482517235173ddb4083788de60b90e
    # 微信开放平台 重定向url
    wx.open.redirect_url=http://guli.shop/api/ucenter/wx/callback

    2.创建常量类

    创建util包,创建ConstantPropertiesUtil.java常量类
    @Component
    //@PropertySource("classpath:application.properties")
    public class ConstantPropertiesUtil implements InitializingBean {
    
        @Value("${wx.open.app_id}")
        private String appId;
    
        @Value("${wx.open.app_secret}")
        private String appSecret;
    
        @Value("${wx.open.redirect_url}")
        private String redirectUrl;
    
        public static String WX_OPEN_APP_ID;
        public static String WX_OPEN_APP_SECRET;
        public static String WX_OPEN_REDIRECT_URL;
    
        @Override
        public void afterPropertiesSet() throws Exception {
            WX_OPEN_APP_ID = appId;
            WX_OPEN_APP_SECRET = appSecret;
            WX_OPEN_REDIRECT_URL = redirectUrl;
        }
    }

    3.生成二维码

    请求微信提供固定的地址,向地址后面传参数

    用%s当占位符,用String.format方法实现

    package com.dm.educenter.controller;
    
    import com.dm.base.exceptionhandler.onlineEduException;
    import com.dm.educenter.utils.ConstantPropertiesUtil;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    
    @Controller
    @CrossOrigin
    @RequestMapping("/api/ucenter/wx")
    public class WxApiController {
    
        @GetMapping("login")
        public String getWXCode() throws UnsupportedEncodingException {
            //拼接参数
            // 微信开放平台授权baseUrl
            String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
                    "?appid=%s" +
                    "&redirect_uri=%s" +
                    "&response_type=code" +
                    "&scope=snsapi_login" +
                    "&state=%s" +
                    "#wechat_redirect";
            //对url进行一个编码
            String redirect_url=ConstantPropertiesUtil.WX_OPEN_REDIRECT_URL;
            redirect_url=URLEncoder.encode(redirect_url,"UTF-8");
    
            String url = String.format(
                    baseUrl,
                    ConstantPropertiesUtil.WX_OPEN_APP_ID,
                    redirect_url,
                    "dm");
    
            //重定向请求微信地址
            return "redirect:"+url;
        }
    }

     4.返回数据

     

     我们要根据code获取两个值

    1.access_token 访问凭证

    2.openid  每个微信唯一标识

    拿这上面的两个值再去请求一个地址,最终才可以获取扫码人信息

    5、引入依赖

     <dependencies>
            <!--httpclient-->
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
            </dependency>
            <!--commons-io-->
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
            </dependency>
            <!--gson-->
            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
            </dependency>
        </dependencies>

    6、书写代码

    1.引入HttpClientUtils工具类 

    public class HttpClientUtils {
    
        public static final int connTimeout=10000;
        public static final int readTimeout=10000;
        public static final String charset="UTF-8";
        private static HttpClient client = null;
    
        static {
            PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
            cm.setMaxTotal(128);
            cm.setDefaultMaxPerRoute(128);
            client = HttpClients.custom().setConnectionManager(cm).build();
        }
    
        public static String postParameters(String url, String parameterStr) throws ConnectTimeoutException, SocketTimeoutException, Exception{
            return post(url,parameterStr,"application/x-www-form-urlencoded",charset,connTimeout,readTimeout);
        }
    
        public static String postParameters(String url, String parameterStr,String charset, Integer connTimeout, Integer readTimeout) throws ConnectTimeoutException, SocketTimeoutException, Exception{
            return post(url,parameterStr,"application/x-www-form-urlencoded",charset,connTimeout,readTimeout);
        }
    
        public static String postParameters(String url, Map<String, String> params) throws ConnectTimeoutException,
                SocketTimeoutException, Exception {
            return postForm(url, params, null, connTimeout, readTimeout);
        }
    
        public static String postParameters(String url, Map<String, String> params, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,
                SocketTimeoutException, Exception {
            return postForm(url, params, null, connTimeout, readTimeout);
        }
    
        public static String get(String url) throws Exception {
            return get(url, charset, null, null);
        }
    
        public static String get(String url, String charset) throws Exception {
            return get(url, charset, connTimeout, readTimeout);
        }
    
        /**
         * 发送一个 Post 请求, 使用指定的字符集编码.
         *
         * @param url
         * @param body RequestBody
         * @param mimeType 例如 application/xml "application/x-www-form-urlencoded" a=1&b=2&c=3
         * @param charset 编码
         * @param connTimeout 建立链接超时时间,毫秒.
         * @param readTimeout 响应超时时间,毫秒.
         * @return ResponseBody, 使用指定的字符集编码.
         * @throws ConnectTimeoutException 建立链接超时异常
         * @throws SocketTimeoutException  响应超时
         * @throws Exception
         */
        public static String post(String url, String body, String mimeType,String charset, Integer connTimeout, Integer readTimeout)
                throws ConnectTimeoutException, SocketTimeoutException, Exception {
            HttpClient client = null;
            HttpPost post = new HttpPost(url);
            String result = "";
            try {
                if (StringUtils.isNotBlank(body)) {
                    HttpEntity entity = new StringEntity(body, ContentType.create(mimeType, charset));
                    post.setEntity(entity);
                }
                // 设置参数
                Builder customReqConf = RequestConfig.custom();
                if (connTimeout != null) {
                    customReqConf.setConnectTimeout(connTimeout);
                }
                if (readTimeout != null) {
                    customReqConf.setSocketTimeout(readTimeout);
                }
                post.setConfig(customReqConf.build());
    
                HttpResponse res;
                if (url.startsWith("https")) {
                    // 执行 Https 请求.
                    client = createSSLInsecureClient();
                    res = client.execute(post);
                } else {
                    // 执行 Http 请求.
                    client = HttpClientUtils.client;
                    res = client.execute(post);
                }
                result = IOUtils.toString(res.getEntity().getContent(), charset);
            } finally {
                post.releaseConnection();
                if (url.startsWith("https") && client != null&& client instanceof CloseableHttpClient) {
                    ((CloseableHttpClient) client).close();
                }
            }
            return result;
        }
    
    
        /**
         * 提交form表单
         *
         * @param url
         * @param params
         * @param connTimeout
         * @param readTimeout
         * @return
         * @throws ConnectTimeoutException
         * @throws SocketTimeoutException
         * @throws Exception
         */
        public static String postForm(String url, Map<String, String> params, Map<String, String> headers, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,
                SocketTimeoutException, Exception {
    
            HttpClient client = null;
            HttpPost post = new HttpPost(url);
            try {
                if (params != null && !params.isEmpty()) {
                    List<NameValuePair> formParams = new ArrayList<NameValuePair>();
                    Set<Entry<String, String>> entrySet = params.entrySet();
                    for (Entry<String, String> entry : entrySet) {
                        formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                    }
                    UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, Consts.UTF_8);
                    post.setEntity(entity);
                }
    
                if (headers != null && !headers.isEmpty()) {
                    for (Entry<String, String> entry : headers.entrySet()) {
                        post.addHeader(entry.getKey(), entry.getValue());
                    }
                }
                // 设置参数
                Builder customReqConf = RequestConfig.custom();
                if (connTimeout != null) {
                    customReqConf.setConnectTimeout(connTimeout);
                }
                if (readTimeout != null) {
                    customReqConf.setSocketTimeout(readTimeout);
                }
                post.setConfig(customReqConf.build());
                HttpResponse res = null;
                if (url.startsWith("https")) {
                    // 执行 Https 请求.
                    client = createSSLInsecureClient();
                    res = client.execute(post);
                } else {
                    // 执行 Http 请求.
                    client = HttpClientUtils.client;
                    res = client.execute(post);
                }
                return IOUtils.toString(res.getEntity().getContent(), "UTF-8");
            } finally {
                post.releaseConnection();
                if (url.startsWith("https") && client != null
                        && client instanceof CloseableHttpClient) {
                    ((CloseableHttpClient) client).close();
                }
            }
        }
    
    
    
    
        /**
         * 发送一个 GET 请求
         *
         * @param url
         * @param charset
         * @param connTimeout  建立链接超时时间,毫秒.
         * @param readTimeout  响应超时时间,毫秒.
         * @return
         * @throws ConnectTimeoutException   建立链接超时
         * @throws SocketTimeoutException   响应超时
         * @throws Exception
         */
        public static String get(String url, String charset, Integer connTimeout,Integer readTimeout)
                throws ConnectTimeoutException,SocketTimeoutException, Exception {
    
            HttpClient client = null;
            HttpGet get = new HttpGet(url);
            String result = "";
            try {
                // 设置参数
                Builder customReqConf = RequestConfig.custom();
                if (connTimeout != null) {
                    customReqConf.setConnectTimeout(connTimeout);
                }
                if (readTimeout != null) {
                    customReqConf.setSocketTimeout(readTimeout);
                }
                get.setConfig(customReqConf.build());
    
                HttpResponse res = null;
    
                if (url.startsWith("https")) {
                    // 执行 Https 请求.
                    client = createSSLInsecureClient();
                    res = client.execute(get);
                } else {
                    // 执行 Http 请求.
                    client = HttpClientUtils.client;
                    res = client.execute(get);
                }
    
                result = IOUtils.toString(res.getEntity().getContent(), charset);
            } finally {
                get.releaseConnection();
                if (url.startsWith("https") && client != null && client instanceof CloseableHttpClient) {
                    ((CloseableHttpClient) client).close();
                }
            }
            return result;
        }
    
    
        /**
         * 从 response 里获取 charset
         *
         * @param ressponse
         * @return
         */
        @SuppressWarnings("unused")
        private static String getCharsetFromResponse(HttpResponse ressponse) {
            // Content-Type:text/html; charset=GBK
            if (ressponse.getEntity() != null  && ressponse.getEntity().getContentType() != null && ressponse.getEntity().getContentType().getValue() != null) {
                String contentType = ressponse.getEntity().getContentType().getValue();
                if (contentType.contains("charset=")) {
                    return contentType.substring(contentType.indexOf("charset=") + 8);
                }
            }
            return null;
        }
    
    
    
        /**
         * 创建 SSL连接
         * @return
         * @throws GeneralSecurityException
         */
        private static CloseableHttpClient createSSLInsecureClient() throws GeneralSecurityException {
            try {
                SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                    public boolean isTrusted(X509Certificate[] chain,String authType) throws CertificateException {
                        return true;
                    }
                }).build();
    
                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {
    
                    @Override
                    public boolean verify(String arg0, SSLSession arg1) {
                        return true;
                    }
    
                    @Override
                    public void verify(String host, SSLSocket ssl)
                            throws IOException {
                    }
    
                    @Override
                    public void verify(String host, X509Certificate cert)
                            throws SSLException {
                    }
    
                    @Override
                    public void verify(String host, String[] cns,
                                       String[] subjectAlts) throws SSLException {
                    }
    
                });
    
                return HttpClients.custom().setSSLSocketFactory(sslsf).build();
    
            } catch (GeneralSecurityException e) {
                throw e;
            }
        }
    
        public static void main(String[] args) {
            try {
                String str= post("https://localhost:443/ssl/test.shtml","name=12&page=34","application/x-www-form-urlencoded", "UTF-8", 10000, 10000);
                //String str= get("https://localhost:443/ssl/test.shtml?name=12&page=34","GBK");
                /*Map<String,String> map = new HashMap<String,String>();
                map.put("name", "111");
                map.put("page", "222");
                String str= postForm("https://localhost:443/ssl/test.shtml",map,null, 10000, 10000);*/
                System.out.println(str);
            } catch (ConnectTimeoutException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SocketTimeoutException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }
    callback方法
    @GetMapping("callback")
        public String callback(String code, String state) {
            //向认证服务器发送请求换取access_token
            String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
                    "?appid=%s" +
                    "&secret=%s" +
                    "&code=%s" +
                    "&grant_type=authorization_code";
    
            String accessTokenUrl = String.format(baseAccessTokenUrl,
                    ConstantPropertiesUtil.WX_OPEN_APP_ID,
                    ConstantPropertiesUtil.WX_OPEN_APP_SECRET,
                    code);
            String result = null;
            try {
                result = HttpClientUtils.get(accessTokenUrl);
                System.out.println("accessToken=============" + result);
            } catch (Exception e) {
                throw new onlineEduException(20001, "获取access_token失败");
            }
    
            //解析json字符串
            Gson gson = new Gson();
            //更改成map
            HashMap map = gson.fromJson(result, HashMap.class);
            String accessToken = (String) map.get("access_token");
            String openid = (String) map.get("openid");
    
            //查询数据库当前用用户是否曾经使用过微信登录
            UcenterMember member = memberService.getByOpenid(openid);
            if (member == null) {
                System.out.println("新用户注册");
    
                //访问微信的资源服务器,获取用户信息
                String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                        "?access_token=%s" +
                        "&openid=%s";
                String userInfoUrl = String.format(baseUserInfoUrl, accessToken, openid);
                String resultUserInfo = null;
                try {
                    resultUserInfo = HttpClientUtils.get(userInfoUrl);
                    System.out.println("resultUserInfo==========" + resultUserInfo);
                } catch (Exception e) {
                    throw new onlineEduException(20001, "获取用户信息失败");
                }
                //解析json
                HashMap<String, Object> mapUserInfo = gson.fromJson(resultUserInfo, HashMap.class);
                String nickname = (String) mapUserInfo.get("nickname");
                String headimgurl = (String) mapUserInfo.get("headimgurl");
    
                //向数据库中插入一条记录
                member = new UcenterMember();
                member.setNickname(nickname);
                member.setOpenid(openid);
                member.setAvatar(headimgurl);
                memberService.save(member);
            }
            return "redirect:http://localhost:3000";
        }
     getByOpenid方法
    @Override
        public UcenterMember getByOpenid(String openid) {
            QueryWrapper<UcenterMember> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("openid", openid);
    
            UcenterMember member = baseMapper.selectOne(queryWrapper);
            return member;
    
        }
    @Override
    public UcenterMember getByOpenid(String openid) {
    QueryWrapper<UcenterMember> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("openid", openid);

    UcenterMember member = baseMapper.selectOne(queryWrapper);
    return member;

    }
  • 相关阅读:
    .NET中二进制图片的存储与读取
    mantis基本配置及邮件服务器配置
    搜狗浏览器特性页面JS
    从多个textarea中随机选取一个内容
    JS截取字符串substr 和 substring方法的区别
    MySQL递归的替代方案
    Eclipse去掉对JS文件的Validation
    Hadoop学习笔记二
    es随想二
    Hadoop学习笔记一
  • 原文地址:https://www.cnblogs.com/dmzna/p/12861213.html
Copyright © 2020-2023  润新知