用户openid_获取用户openid - CSDN
精华内容
参与话题
  • 获取微信用户openId

    万次阅读 2014-12-10 16:11:17
    开发框架:struts2(零配置) ...PS:下列获取openid的代码可以在柳峰的《微信公众平台应用开发方法、技巧与案例》的第六章找到。但是书中关于授权域名以及redirect_uri的关联写的不是很详细,在此主

    开发框架:struts2(零配置)

    官方文档下载地址

    https://mp.weixin.qq.com/paymch/readtemplate?t=mp/business/course3_tmpl&lang=zh_CN

    PS:下列获取openid的代码可以在柳峰的《微信公众平台应用开发方法、技巧与案例》的第六章找到。但是书中关于授权域名以及redirect_uri的关联写的不是很详细,在此主要详细介绍了出现问题排错的方向。代码觉得有疑惑的,可以看柳大神的书,或者csdn搜索柳峰找相关博客查看。

    1 首先,我们需要进入我们的服务号,点击左侧栏开发者中心--->修改网页授权获取用户基本信息的值,假设我们对外的ip183.33.212.175tomcat的端口号为8016,这个修改为183.33.212.175:8016


    2 创建WeiXinOauth2Token类。改类具有以下属性:(自行添加getset方法)

    private String accessToken;

    private int expiresIn;

    private String refeshToken;

    private String openId;

    private String scope;

    3 调用微信的授权接口

    https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect


    其中要说明的是,redirect_uri一定是在我们设定网页授权获取用户基本信息的域名下的action,不然微信页面会提示redirect_uri错误(所以,出现该错误,各位应该知道如何排错了)

    官方文档给了下面一段话解释:

    比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html、http://www.qq.com/login.html都可以进行 OAuth2.0 鉴权。但http://pay.qq.com、http://music.qq.com、http://qq.com 无法进行 OAuth2.0 鉴权。

    上面一段话是什么意思呢?

    假设我的授权域名为183.33.212.175:8016,那么。我的redirect_uri需要为http://183.33.212.175:8016/wxweb/config/oauth!execute.action特别注意的是前面的http://必须要有,

    不然就提示找不到页面183.33.212.175:8016/wxweb/config /oauth!execute.action?code=XXXXXXXXXX。(这一点被坑了一天)

    4 然后将redirect_uri进行encode,具体代码如下
    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;
    }
    requestUrl= https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect中的REDIRECT_URI是我们的redirect_uri 进行encode后的值,APPID为你服务号的appid.
    将上面的requestUrl设置为图文链接或者view按钮链接发送给用户。

    5 获取用户openid

    我的redirect_uri对应的action方法为

    public String execute() throws ServletException, IOException{
                    // 将请求、响应的编码均设置为UTF-8(防止中文乱码)
                    HttpServletRequest request = ServletActionContext.getRequest();
                    HttpServletResponse response = ServletActionContext.getResponse();
                    request.setCharacterEncoding("UTF-8");
                    response.setCharacterEncoding("UTF-8");
                    String code = request.getParameter("code");
                    String openId ="";
                    if (!"authdeny".equals(code)) {
                            WeiXinOauth2Token weiXinOauth2Token = AdvancedUtil
                                            .getOauth2AccessToken("wx0953bae287adfeee",
                                                            "8e81dbc44a84a3c290c0cc3759f85421", code);
                            openId = weiXinOauth2Token.getOpenId();
                    }
                    request.getSession().setAttribute("openId", openId);
                    return "index";
    }

    AdvancedUtil的方法如下:
    public static WeiXinOauth2Token getOauth2AccessToken(String appId, String appSecret, String code) {
                    WeiXinOauth2Token wat = new WeiXinOauth2Token();
                    String requestUrl = oauth2Url.replace("APPID", appId).replace("SECRET", appSecret).replace("CODE", code);
                    JSONObject jsonObject = CommonUtil
                                    .httpsRequest(requestUrl, "GET", null);
                    if (null != jsonObject) {
                            try {
                                    wat = new WeiXinOauth2Token();
                                    wat.setAccessToken(jsonObject.getString("access_token"));
                                    wat.setExpiresIn(jsonObject.getInt("expires_in"));
                                    wat.setRefeshToken(jsonObject.getString("refresh_token"));
                                    wat.setOpenId(jsonObject.getString("openid"));
                                    wat.setScope(jsonObject.getString("scope"));
                            } catch (Exception e) {
                                    wat = null;
                                    String errorCode = jsonObject.getString("errcode");
                                    String errorMsg = jsonObject.getString("errmsg");
                                    log.error("获取网页授权凭证失败 errcode{},errMsg", errorCode, errorMsg);
                            }

                    }
                    return wat;
    }
    CommmonUtil相关方法如下
    /**
             * 发送https请求
             *
             * @param requestUrl 请求地址
             * @param requestMethod 请求方式(GET、POST)
             * @param outputStr 提交的数据
             * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
             */
    public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
                    JSONObject jsonObject = null;
                    try {
                            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
                            TrustManager[] tm = { new MyX509TrustManager() };
                            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
                            sslContext.init(null, tm, new java.security.SecureRandom());
                            // 从上述SSLContext对象中得到SSLSocketFactory对象
                            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);
                            // 设置请求方式(GET/POST)
                            conn.setRequestMethod(requestMethod);
                            //conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
                            // 当outputStr不为null时向输出流写数据
                            if (null != outputStr) {
                                    OutputStream outputStream = conn.getOutputStream();
                                    // 注意编码格式
                                    outputStream.write(outputStr.getBytes("UTF-8"));
                                    outputStream.close();
                            }
                            // 从输入流读取返回内容
                            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);
                            }
                            // 释放资源
                            bufferedReader.close();
                            inputStreamReader.close();
                            inputStream.close();
                            inputStream = null;
                            conn.disconnect();
                            jsonObject = JSONObject.fromObject(buffer.toString());
                    } catch (ConnectException ce) {
                            log.error("连接超时:{}", ce);
                    } catch (Exception e) {
                            log.error("https请求异常:{}", e);
                    }
                    return jsonObject;
    }
    测试OK后,会得到用户的openid并正确跳转到oauth_index.jsp页面。

    假设用我们sae的应用,授权域名写为searchinfo.sinaapp.com,其中searchinfo是你的应用名称。那么没有encode前的redirect_uri为:http://searchinfo.sinaapp.com/config/oauth!execute.action。
    需要注意的是,你部署的代码中config/oauth!execute.action方法所在版本必须为你应用的默认版本。检测是否可行,直接访问
    searchinfo.sinaapp.com/config/oauth!execute.action,若报500空指针,说明填写正确。找不到方法请自行修改默认版本,找到对应的执行action即可。

    展开全文
  • 微信h5静默、非静默授权获取用户openId的方法和步骤: 一、openId是什么? openId是用户在当前公众号下的唯一标识(‘身份证’),就是说通过这个openId,就能区分在这个公众号下具体是哪个用户。 二、openId有...

    微信h5静默、非静默授权获取用户openId的方法和步骤:

    一、openId是什么?

    openId是用户在当前公众号下的唯一标识(‘身份证’),就是说通过这个openId,就能区分在这个公众号下具体是哪个用户。

    二、openId有什么用?

    假如用户A在当前公众号下购买了一件商品,用户的下单信息肯定要存储到后台数据库,那根据什么进行存储呢?openId是用户在当前公众号下的唯一标识,通过openId和用户的下单购买信息进行键值对的数据绑定。那么我要查询该用户购买过什么商品,就能够通过openId去查询,并且数据是唯一的,不会和另外的用户数据有冲突。

    拓展:UnionID:一个商家或公司可能会有多个公众号,假如用户A同时都关注了这个公司下面的三个公众号,那么这个用户就会有三个openId(一个公众号就对应一个openID)。如果作为开发者的我们,要对这个用户在这三个公众号下消费的数据进行汇总,我怎么获取到这三份数据(同一用户的)?答案是 UnionId,微信开发者文档:如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为同一用户,对同一个微信开放平台下的不同应用(移动应用、网站应用和公众帐号),unionid是相同的。就是说如果要获取用户在同一公司不同公众号下的数据,后台表结构不但要关联openId,还要关联UnionId。

    三、怎么获取openId?

    (一)登录微信公众平台后台获取公众号的AppId,设置回调地址。

    回调地址设置页面向导:开发>接口权限>网页服务>网页授权>修改。开发的项目需要放到已经解析好服务器域名的服务器下,同时把Mp***.text文件放到服务器根目录下,此时你的服务器必须能联通外网也就是有公网IP,并且80端口是打开的,可以使用阿里云等服务器,默认配置就可以了。

    (二)根据开发需要,静默授权还是非静默授权

       ① 静默授权:snsapi_base,没有弹窗,只能获取用户的openId。

       ②非静默授权:snsapi_userinfo,有弹框弹出需要用户手动点击确认授权。可以获取openId,用户的头像、昵称等

    (三)前端代码,配置的参数要一一对应,获取code,并调用后台接口,把code传给后台

    redirect_uri,这个的意思是:授权完成后再重新回到当前页面(又刷新了一次页面)

    getUrlParam的方法,可以百度下,就是获取页面路径的某个字段所对应的参数。

    如果配置参数一一对应,那么此时已经通过回调地址刷新页面后,你就会看到在地址栏中的code了。

    (四)前端截取地址栏中的code后通过调接口把code传给后台,后台通过code获取openId和用户头像昵称等信息并返回给前端

    为什么,前端不能一起把获取code和获取openId的操作一并做了,还要请求后台,让后台获取openId?

    (五)后台通过 code、AppSecret(公众号平台后台取得)请求微信链接获取openId

    前端具体代码如下,可复制(记得把文中的 window.APPID改为自己公众号的APPID)

    <template>
        <div></div>
    </template>
    
    <script>
    import GetUrlParam from '@/assets/js/util/getUrlParam.js'
    export default {
        name: 'Index',
        data () {
            return {
            }
        },
        created () {
            this.getCode()
        },
        methods: {
            getCode () { // 非静默授权,第一次有弹框
                const code = GetUrlParam('code') // 截取路径中的code,如果没有就去微信授权,如果已经获取到了就直接传code给后台获取openId
                const local = window.location.href
                if (code == null || code === '') {
                    window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' + window.APPID + '&redirect_uri=' + encodeURIComponent(local) + '&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect'
                } else {
                    this.getOpenId(code) //把code传给后台获取用户信息
                }
            },
            getOpenId (code) { // 通过code获取 openId等用户信息,/api/user/wechat/login 为后台接口
                let _this = this
                this.$http.post('/api/user/wechat/login', {code: code}).then((res) => {
                    let datas = res.data
                    if (datas.code === 0 ) {
                        console.log('成功')
                    }
                }).catch((error) => {
                    console.log(error)
                })
            }
        }
    }
    </script>
    
    <style lang="less" scoped>
    
    </style>

    (六)通过openId做用户的数据绑定或查询等操作

        前后端都获取了openId后,就能通过openId做用户数据的绑定和查询了。

    (七)补充说明

       使用上述方法进行的微信授权,在手机端会有两次空白页跳转,时间虽然很短暂,但有些产品经理会觉得这种体验不好(实在很欠揍)。解决方法是:可以把跳转到微信获取code的这段链接拼接好直接复制到  微信公众平台 后台管理系统菜单列表里面。这样点击菜单,在回调页通过截取url中的code,就能直接获取到code了,就避免了多次跳转的情况。

    (八)解决微信授权成功进入项目后,点击手机物理返回键或返回会出现空白页或者报错的情况,空白页是因为授权页就是空白页。可以参考我的另一篇文章:

    解决微信授权成功后点击按返回键出现空白页和报错的问题
    https://blog.csdn.net/qq_35430000/article/details/81505497

    最后:这篇分享来源于我在实际项目中摸索和借鉴其他项目,有不对的地方希望大家多多指出,有不明白的地方可以给我留言.

    卓越的云计算服务提供商,230万+用户正在享受阿里云"稳定,安全,低成本"的产品服务,金牌服务:免费体验,专业快速备案,7x24小时售后,服务器只选阿里云

    展开全文
  • 微信每次的访问 请求 首先经过授权 拿到code换取openid 将openid存入cookie 这以后的所有...2, 第三方页面授权,如何减少从微信服务器获取用户openid的次数以及减少获取用户信息的次数,加速第三方页面的加载速速...

    微信每次的访问 请求 首先经过授权 拿到code换取openid 将openid存入cookie 这以后的所有访问url 全部都从cookie中获取openid 如果没有在获取code换取

    • 可以解决的问题:

    1,如何存储获取用户信息及调用第三方接口所需要的token.
    2, 第三方页面授权,如何减少从微信服务器获取用户openid的次数以及减少获取用户信息的次数,加速第三方页面的加载速速。

    • 处理逻辑:
      首先,说一下我的测试逻辑:
      1,先用一个穿透工具,配置好自己的测试号域名和appid 等信息。
      2,编写一个WxServlet 拦截wx下的请求,经过处理和url拼接需要的参数进行重定向到具体业务目录上。
      3,启动服务,在微信开发者工具或者微信中打开预设好的url(“。。。。/wx/。。。”),进行访问/index。
      4,index是入口地址,可以先从cookie中获取openid,不过这个暂不使用,还是根据传过来的code在进行获取一次,这样保证每次访问都会进行授权验证,拿到授权后再获取openid,存入cookie设置过期时间,这里可以添加和保存用户信息的逻辑等。
      5,点击页面跳转到index1上。这个加了testUtil 这个工具类,首先获取cookie中的openid,如果没有,需要重新通过code获取。(这里也可以做成拦截器等,这里改造老项目就按需处理了)。
      6,通过index1和index2的相互跳转 获取openid都是可以轻松实现,设置时间可以测试,并亲测过安卓和苹果都没问题,页面进行分享后也是可以正常使用的。(主要处理之前openid拼接在url上的尴尬问题)

    微信菜单入口

        /**
         * 微信菜单入口
         */
        @RequestMapping("/index")
        public String index(HttpServletRequest request, HttpServletResponse response)throws Exception {
    //      CookieUtils.deleteCookie(request, response, "userOpenid");
            String cookieValue = CookieUtils.getCookieValue(request, "userOpenid");
            System.out.println("*********c=="+cookieValue);
    
            String code = request.getParameter("code");
            logger.info("--openid为空--,OAuth2.0页面授权CODE====="+ code);
            //1、如果不是微信中打开则返回 
            if (StringUtils.isNotBlank(code)) {
                JSONObject jsonObject = WeiXinUtil.getAuthorizationAccessToken(WeiXinConstant.getAppid(), WeiXinConstant.getAppsecret(),code);
                //保存一小时cookie
                CookieUtils.setCookie(request, response, "userOpenid", jsonObject.getString("openid"), 10, true);
            }else{
                if (StringUtils.isBlank(code)) {
                    return null;
                }
            }
            return "/app/book/student/testIndex";
        }
    

    测试页面1

        @RequestMapping("/index1")
        public String index1(HttpServletRequest request, HttpServletResponse response)throws Exception {
             String testUtil = testUtil(request, response);
             if(StringUtils.isNotBlank(testUtil)){
                 return "redirect:"+testUtil;
             }
             String cookieValue = CookieUtils.getCookieValue(request, "userOpenid");
             if(StringUtils.isBlank(cookieValue)){
                 System.out.println("opneid is null   写入日志   1111&&&&&");
             }else{
                 System.out.println("openid not null   ---开始处理自己的逻辑11111---");
             }
            return "/app/book/student/testIndex1";
        }

    测试页面2

        @RequestMapping("/index2")
        public String index2(HttpServletRequest request, HttpServletResponse response)throws Exception {
            String testUtil = testUtil(request, response);
             if(StringUtils.isNotBlank(testUtil)){
                 return "redirect:"+testUtil;
             }
             String cookieValue = CookieUtils.getCookieValue(request, "userOpenid");
             if(StringUtils.isBlank(cookieValue)){
                 System.out.println("opneid is null   *****写入日志   222");
             }else{
                 System.out.println("openid not null*****开始处理自己的逻辑--2222---");
             }
             return "/app/book/student/testIndex2";
        }

    处理cookie是否存在openid逻辑工具类

    public String testUtil(HttpServletRequest request, HttpServletResponse response)throws Exception {
    
            String cookieValue = CookieUtils.getCookieValue(request, "userOpenid");
            System.out.println("*********cookieValue=="+cookieValue);
            String code = request.getParameter("code");
            System.out.println("*********code=="+code);
            String authorizationUrl = "";
            if(StringUtils.isBlank(cookieValue)){
                 if(StringUtils.isBlank(code)){
                     String uri = request.getRequestURI();
                     String url = "http://" + WeiXinConstant.SERVER_HOST()+uri;
                     authorizationUrl = WeiXinUtil.getAuthorizationCode(WeiXinConstant.getAppid(),url.toString(), WeiXinConstant.SCOPE_SNSAPI_USERINFO);
                     System.out.println("**********Url=="+authorizationUrl);
                 }else{
                     JSONObject jsonObject = WeiXinUtil.getAuthorizationAccessToken(WeiXinConstant.getAppid(), WeiXinConstant.getAppsecret(),code);
                     //保存一小时cookie 3600
                     CookieUtils.setCookie(request, response, "userOpenid", jsonObject.getString("openid"), 20, true);
                 }
             }
            return authorizationUrl;
        }
    

    通过servlet及线程定时获取access_token并使用的文章

    https://blog.csdn.net/alen_en/article/details/80975014

    展开全文
  • 最近,对微信公众号有点兴趣,就自己研究了研究里面的一些内容,发现还挺... 我想,做微信公众号开发的,对于想获取关注了公众号的用户信息,或者说是当前与后台服务器进行交互的当前用户信息,这个功能是很重要...

        最近,对微信公众号有点兴趣,就自己研究了研究里面的一些内容,发现还挺有意思的,而且通过微信公众号可以调用一些比较有意思的接口,就比如百度开发服务平台 点击进入 里面的很有接口,就比较常见的翻译,语音识别,地理位置等等,都挺好的。好了,不多说,进入正题好了。

        我想,做微信公众号开发的,对于想获取关注了公众号的用户信息,或者说是当前与后台服务器进行交互的当前用户信息,这个功能是很重要的吧。因为,通过这个,可以直接获取到当前的用户信息,而不需要,每次都是进行自己输入信息,这个只会让用户感觉到很不适。。。所以,为了解决这个需求,那咱们来研究研究,如何获取微信的个人信息~!

    大家可以关注我的微信公众号:Java菜鸟进阶之路

     (一)思路

    我们来研究一下,要想获取到个人信息,是如何一个流程呢?

    路线图:

    上面,画了一个简单的一个流程图,我想,看着这个应该觉得不难吧。是的,确实思路很简单,但是,,里面的坑也不少。接下来,我对两种情况都进行讲解。

    (二)情况一:通过用户与服务器进行消息交互,来获取用户信息

    思路:针对这种情况的话,比较简单,因为,我们在做用户与服务器进行消息交互的时候,我们可以知道,用户发送的内容是以XML的形式进行发送的,然后服务器,首先接受到XML,然后再把XML转为Map对象,再从Map对象中获取对应的内容即可。那么,发送的XML的字段是个怎么样呢?

    字段信息:

    ToUserName:发送给谁的ID
    FromUserName:发消息方的ID(其实也就是用户的OpenId)
    CreateTime:消息发送时间,时间戳
    MsgType:消息类似,有文本,图片,音频,视频,事件推送等
    Content:发送的内容

    通过这个,我想大家,再结合上面给的流程图,是不是发现了什么呢?是的,这个OpenId,我们已经获取了呀,那是不是可以直接获取到用户信息了呢?。。。。emmmmmm,这样说吧。差不多是可以的,那具体是怎么做呢?紧接着往下看,仔细看我其中的注释

    步骤:

    1:解析发送过来的XML信息格式,将其转为Map格式

    /**
         * XML格式转为map格式
         * @param request
         * @return
         */
        public static Map<String , String> xmlToMap(HttpServletRequest request){
            Map<String ,String> map = new HashMap<String , String>();
            try {
                InputStream inputStream =null;
                inputStream = request.getInputStream();
                SAXReader reader = new SAXReader();
                Document doc = reader.read(inputStream);
                Element rootElement = doc.getRootElement();
                List<Element> elements = rootElement.elements();
                for (Element el:elements) {
                    map.put(el.getName() , el.getText());
                }
                inputStream.close();
                return map ;
            } catch (Exception e) {
                e.printStackTrace();
                return null ;
            }
        }

    备注:记得导入相应的包哦。。比如dom4j还有xsreader。。

    2:获取用户的个人信息

    package com.hnu.scw.utils;
    
    import com.hnu.scw.model.AccessToken;
    import net.sf.json.JSONObject;
    
    /**
     * @author scw
     * @create 2018-01-18 16:42
     * @desc 用于获取微信用户的信息
     **/
    public class WeiXinUserInfoUtils {
        private static final String GET_USERINFO_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
    
        /**
         * 获取微信用户账号的相关信息
         * @param opendID  用户的openId,这个通过当用户进行了消息交互的时候,才有
         * @return
         */
        public static String getUserInfo(String opendID){
            AccessToken accessToken = WeiXinUtils.getAccessToken();
            //获取access_token
            String token = accessToken.getToken();
            String url = GET_USERINFO_URL.replace("ACCESS_TOKEN" , token);
            url = url.replace("OPENID" ,opendID);
            JSONObject jsonObject = WeiXinUtils.doGetStr(url);
            return jsonObject.toString();
        }
    }

    备注:传入的参数就是咱们之前说过的,FromUserName的值,这个应该不用多解释吧。因为,对于传入的XML,我们已经存入了Map中,那么直接从Map取出对应的字段信息就可以了,

    String fromUserName = map.get("FromUserName");

    3:通过上面,我们就得到了具体的用户信息的Json格式了,当然,我上面的方法将Json内容转为了String,我这里只是用于查看是否获取到信息了而已,所以,你们就根据各自的需求进行处理就可以了,该解析的就解析即可。。

    总结:

    上面的这种方法是不是很简单,这个没什么难的,而且这个根据微信公众号的开发手册也可以分析出来。

    缺点:我们发现了,这种方法,只有当用户进行了消息交互,才会有FromUserName(这时候可以等价看成是OpenId),那么我们在实际开发中,肯定遇到了一种情况,就是用户没有进行消息交互,直接点击一个菜单按钮,然后就把用户信息自动显示到了一个页面中,那这样是怎么做,方法是一样吗?不多说,继续看下面~~~~~~~~~

    (三)情况二:通过点击按钮,来直接获取到用户信息

    思路:首先,点击菜单按钮,要先到网页授权的接口去请求(主要是获取Code,这是必须要的一个参数),然后再重定向到我们自己菜单按钮实际想去的URL,然后再获取OpenId,再通过OpenId,获取用户信息。。哇塞,咦,思路挺简单的嘛。。那么,我们开始工作。。

    步骤:

    1:创建菜单

    对于这个自定义菜单的话,不是主要介绍的了,这个如果做过微信公众号开发的,应该都明白吧。所以,我这就贴一点关键代码:

    ViewButton viewButton = new ViewButton();
            viewButton.setName("view菜单");
            viewButton.setType("view");
            //viewButton.setUrl("http://myjava.ngrok.xiaomiqiu.cn/tomainpage");
            viewButton.setUrl("https://open.weixin.qq.com/connect/oauth2/authorize?appid=XXXXXX&redirect_uri=http://myjava.ngrok.xiaomiqiu.cn/tologin/userinfo&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect");

    备注:大家,请注意,这个view菜单的URL,和我们平常的跳转的区别再哪里。。

     

    分析:

    知识点1:

    https://open.weixin.qq.com/connect/oauth2/authorize?appid=XXXX

    这个就是网页授权的接口地址,其中的appid就是我们自己微信公众号申请的时候,给我们的唯一值,这个大家去微信公众号查看即可。

     

    知识点2:

    redirect_uri=http://myjava.ngrok.xiaomiqiu.cn/tologin/userinfo&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect");

    这个就是我们实际想要点击按钮,跳转到的页面,这个就和咱们平常的跳转是一样的,所以一定要记住,要先去授权页面,再重定向回去(主要是为了获取code参数)。

     

    2:配置微信公众号的网页授权域名

    备注:这个是在自己微信公众号的开发管理模块里面的,而且,我这里用的是测试号进行的(当然,如果有企业号这更加好呀。界面也是一样)

    注意点:对添加的回调页面域名:首先,不能加入http://这个,对于平常的链接,我想都有这个,这个是请求协议,但这里千万不能加入;另外,只需要写总的域名地址,不需要精确到最内层。打个比方:

    一般的:

    http://myjava.ngrok.xiaomiqiu.cn/tologin/userinfo

    这里就配置就只需要:(其实就是配置我们的服务器域名即可)

    myjava.ngrok.xiaomiqiu.cn

    3:编写,相应的处理内容(关键代码,请仔细看)

    备注:我用的是SSH(SpringMVC+Spring+Hibernate)框架来进行开发的,当然,用Servlet也可以,用SSM(SpringMVC+Spring+Mybatis)或者用SSH(Struts+Spring+Hibernate)都可以,这个根据自己的需求即可相应的改变呢!!(另外,这个几个框架,我其他的文章都有很详细的介绍了,所以自己看看相应配置即可)

    Controller层代码:

    package com.hnu.scw.controller;
    import com.hnu.scw.bean.WeiXinUser;
    import com.hnu.scw.service.WeiXinUserInfoService;
    import com.hnu.scw.utils.WeiXinUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    import java.util.HashMap;
    import java.util.Map;
    /**
     * @author scw
     * @create 2018-01-18 17:47
     * @desc 获取微信用户的所有信息,这个主要是为了不要用户自己填写个人信息
     **/
    @Controller
    public class WeiXinUserInfoController {
    
        @Autowired
        private WeiXinUserInfoService userService;
    
        /**
         * 进行网页授权,便于获取到用户的绑定的内容
         * @param request
         * @param session
         * @param map
         * @return
         */
        @RequestMapping("/tologin/userinfo")
        public String check(HttpServletRequest request , HttpSession session, Map<String, Object> map) {
            //首先判断一下session中,是否有保存着的当前用户的信息,有的话,就不需要进行重复请求信息
            WeiXinUser  weiXinUser = null ;
            if(session.getAttribute("currentUser") != null){
                weiXinUser = (WeiXinUser) session.getAttribute("currentUser");
            }else {
                /**
                 * 进行获取openId,必须的一个参数,这个是当进行了授权页面的时候,再重定向了我们自己的一个页面的时候,
                 * 会在request页面中,新增这个字段信息,要结合这个ProjectConst.Get_WEIXINPAGE_Code这个常量思考
                 */
                String code = request.getParameter("code");
                try {
                    //得到当前用户的信息(具体信息就看weixinUser这个javabean)
                    weiXinUser = getTheCode(session, code);
                    //将获取到的用户信息,放入到session中
                    session.setAttribute("currentUser", weiXinUser);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            map.put("weiXinUser", weiXinUser);
            return "hello";
        }
    
        /**
         * 获取用户的openId
         * @param session
         * @param code
         * @return 返回封装的微信用户的对象
         */
        private WeiXinUser getTheCode(HttpSession session, String code) {
            Map<String , String>  authInfo = new HashMap<>();
            String openId = "";
            if (code != null)
            {
                // 调用根据用户的code得到需要的授权信息
                authInfo= userService.getAuthInfo(code);
               //获取到openId
                openId = authInfo.get("Openid");
            }
            // 获取基础刷新的接口访问凭证(目前还没明白为什么用authInfo.get("AccessToken");这里面的access_token就不行)
            String accessToken = WeiXinUtils.getAccessToken().getToken();
            //获取到微信用户的信息
            WeiXinUser userinfo = userService.getUserInfo(accessToken ,openId);
    
            return userinfo;
        }
    }

    Service层接口:

    package com.hnu.scw.service;
    import com.hnu.scw.bean.WeiXinUser;
    import java.util.Map;
    /**
     * 用于进行微信用户个人信息的操作接口
     */
    public interface WeiXinUserInfoService {
         /**
          * 获取到微信个人用户的信息
          * @param accessToken
          * @param openId
          * @return
          */
         WeiXinUser getUserInfo(String accessToken, String openId);
    
         /**
          *用于获取网页授权后的信息字段,其中主要是获取openId
          * @param code  授权码
          * @return
          */
         Map<String , String > getAuthInfo(String code);
    
         /**
          * 进行网页授权的认证
          * @param code 授权码
          * @return
          */
         Map<String,String> oauth2GetOpenid(String code);
    }
    

    Service层实现:

     

    package com.hnu.scw.service.imp;
    import com.hnu.scw.bean.WeiXinUser;
    import com.hnu.scw.projectconst.ProjectConst;
    import com.hnu.scw.service.WeiXinUserInfoService;
    import com.hnu.scw.utils.WeiXinUtils;
    import net.sf.json.JSONObject;
    import org.springframework.stereotype.Service;
    import java.util.HashMap;
    import java.util.Map;
    /**
     * @author scw
     * @create 2018-01-18 17:51
     * @desc 用于获取微信用户的信息
     **/
    @Service
    public class WeiXinUserInfoImlp implements WeiXinUserInfoService {
        /**
         * 获取微信用户的信息
         * @param accessToken
         * @param openId
         * @return
         */
        @Override
        public WeiXinUser getUserInfo(String accessToken, String openId) {
            WeiXinUser weixinUserInfo = null;
            // 拼接获取用户信息接口的请求地址
            String requestUrl = ProjectConst.GET_WEIXIN_USER_URL.replace("ACCESS_TOKEN", accessToken).replace(
                    "OPENID", openId);
            // 获取用户信息(返回的是Json格式内容)
            JSONObject jsonObject = WeiXinUtils.doGetStr(requestUrl);
    
            if (null != jsonObject) {
                try {
                    //封装获取到的用户信息
                    weixinUserInfo = new WeiXinUser();
                    // 用户的标识
                    weixinUserInfo.setOpenId(jsonObject.getString("openid"));
                    // 昵称
                    weixinUserInfo.setNickname(jsonObject.getString("nickname"));
                    // 用户的性别(1是男性,2是女性,0是未知)
                    weixinUserInfo.setSex(jsonObject.getInt("sex"));
                    // 用户所在国家
                    weixinUserInfo.setCountry(jsonObject.getString("country"));
                    // 用户所在省份
                    weixinUserInfo.setProvince(jsonObject.getString("province"));
                    // 用户所在城市
                    weixinUserInfo.setCity(jsonObject.getString("city"));
                    // 用户头像
                    weixinUserInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));
                } catch (Exception e) {
                    if (0 == weixinUserInfo.getSubscribe()) {
                        System.out.println("用户并没有关注本公众号");
                    } else {
                        int errorCode = jsonObject.getInt("errcode");
                        String errorMsg = jsonObject.getString("errmsg");
                        System.out.println("由于"+errorCode +"错误码;错误信息为:"+errorMsg+";导致获取用户信息失败");
                    }
                }
            }
            return weixinUserInfo;
        }
    
        /**
         * 进行用户授权,获取到需要的授权字段,比如openId
         * @param code 识别得到用户id必须的一个值
         * 得到网页授权凭证和用户id
         * @return
         */
        @Override
        public Map<String, String> oauth2GetOpenid(String code) {
            //自己的配置appid(公众号进行查阅)
            String appid = ProjectConst.PROJECT_APPID;
            //自己的配置APPSECRET;(公众号进行查阅)
            String appsecret = ProjectConst.PROJECT_APPSECRET;
            //拼接用户授权接口信息
            String requestUrl = ProjectConst.GET_WEBAUTH_URL.replace("APPID", appid).replace("SECRET", appsecret).replace("CODE", code);
            //存储获取到的授权字段信息
            Map<String, String> result = new HashMap<String, String>();
            try {
                JSONObject OpenidJSONO = WeiXinUtils.doGetStr(requestUrl);
                //OpenidJSONO可以得到的内容:access_token expires_in  refresh_token openid scope
                String Openid = String.valueOf(OpenidJSONO.get("openid"));
                String AccessToken = String.valueOf(OpenidJSONO.get("access_token"));
                //用户保存的作用域
                String Scope = String.valueOf(OpenidJSONO.get("scope"));
                String refresh_token = String.valueOf(OpenidJSONO.get("refresh_token"));
                result.put("Openid", Openid);
                result.put("AccessToken", AccessToken);
                result.put("scope", Scope);
                result.put("refresh_token", refresh_token);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    
        /**
         * 获取到微信用户的唯一的OpendID
         * @param code  这是要获取OpendId的必须的一个参数
         * @return
         */
        @Override
        public Map<String , String> getAuthInfo(String code) {
            //进行授权验证,获取到OpenID字段等信息
            Map<String, String> result = oauth2GetOpenid(code);
            // 从这里可以得到用户openid
            String openId = result.get("Openid");
    
            return result;
        }
    }

    4:GET请求接口的代码:

    package com.hnu.scw.utils;
    import com.hnu.scw.menu.BaseButton;
    import com.hnu.scw.menu.ClickButton;
    import com.hnu.scw.menu.CustomeMenu;
    import com.hnu.scw.menu.ViewButton;
    import com.hnu.scw.model.AccessToken;
    import net.sf.json.JSONObject;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.util.EntityUtils;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    
    /**
     * @author scw
     * @create 2018-01-17 14:13
     * @desc 用户获取access_token,众号调用各接口时都需使用access_token
     **/
    public class WeiXinUtils {
        /**
         * Get请求,方便到一个url接口来获取结果
         * @param url
         * @return
         */
        public static JSONObject doGetStr(String url){
            DefaultHttpClient defaultHttpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(url);
            JSONObject jsonObject = null;
            try{
                HttpResponse response = defaultHttpClient.execute(httpGet);
                HttpEntity entity = response.getEntity();
                if(entity != null){
                    String result = EntityUtils.toString(entity, "UTF-8");
                    jsonObject = JSONObject.fromObject(result);
                }
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return jsonObject;
        }

    5:获取Access_Token代码:(这个就是在4中的类中的方法)

    /**
         * 获取access_token
         * @return
         */
        public static AccessToken getAccessToken(){
            AccessToken accessToken = new AccessToken();
            String url = ACCESS_TOKEN_URL.replace("APPID" ,APPID).replace("APPSECRET",APPSECRET);
            JSONObject jsonObject = doGetStr(url);
            if(jsonObject !=null){
                accessToken.setToken(jsonObject.getString("access_token"));
                accessToken.setExpireIn(jsonObject.getInt("expires_in"));
            }
            return accessToken;
        }

    6:Access_Token的实体类

    package com.hnu.scw.model;
    /**
     * @author scw
     * @create 2018-01-17 14:35
     * @desc 封装AccessToken的实体
     **/
    public class AccessToken {
        private String token;
        private int expireIn;
    
        public String getToken() {
            return token;
        }
        public void setToken(String token) {
            this.token = token;
        }
        public int getExpireIn() {
            return expireIn;
        }
        public void setExpireIn(int expireIn) {
            this.expireIn = expireIn;
        }
    }

    7:用户信息的实体类

    package com.hnu.scw.bean;
    /**
     * @author scw
     * @create 2018-01-18 17:11
     * @desc 对于微信用户本身存在的信息的一个javabean,不需要在数据库中进行处理
     **/
    public class WeiXinUser {
        // 用户的标识
        private String openId;
        // 关注状态(1是关注,0是未关注),未关注时获取不到其余信息
        private int subscribe;
        // 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间
        private String subscribeTime;
        // 昵称
        private String nickname;
        // 用户的性别(1是男性,2是女性,0是未知)
        private int sex;
        // 用户所在国家
        private String country;
        // 用户所在省份
        private String province;
        // 用户所在城市
        private String city;
        // 用户的语言,简体中文为zh_CN
        private String language;
        // 用户头像
        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;
        }
    }

    8:一些静态常量的接口地址:

    package com.hnu.scw.projectconst;
    
    /**
     * @author scw
     * @create 2018-01-18 15:31
     * @desc 项目相关的静态量
     **/
    public class ProjectConst {
        /**
         * 用于获取当前与微信公众号交互的用户信息的接口(一般是用第一个接口地址)
         */
        public static final String GET_WEIXIN_USER_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID";
        public final static String GetPageUsersUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
    
        /**
         * 用于进行网页授权验证的接口URL,通过这个才可以得到opendID等字段信息
         */
        public final static String GET_WEBAUTH_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
    
        /**
         * 用于进行当点击按钮的时候,能够在网页授权之后获取到code,再跳转到自己设定的一个URL路径上的接口,这个主要是为了获取之后于
         * 获取openId的接口相结合
         * 注意:参数:toselfURL  表示的是当授权成功后,跳转到的自己设定的页面,所以这个要根据自己的需要进行修改
         */
        public final static String Get_WEIXINPAGE_Code = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=toselfURL&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect";
        /**
         * 获取access_token的URL
         */
        private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    
    }

    9:大功告成。。。。哇塞,完美解决。。

    总结:

    这种方式,相对于上面的话,好处就在于,不需要进行消息交互就可以获取到用户的信息,这样其实更符合我们的业务需求,相对于更加好。但是,第一种情况也是有实用价值的,所以,我们要客观的进行评价和使用~~~~当然,这里面还有很多的可以优化的地方,就是,比如获取Access_Token,我们一般都是弄到本地,因为微信公众号一天请求的次数有限制(2000),所以这可以进行优化哦。。。。其他的根据需求来就可以啦!!!!!!!!

         好了,这个就介绍这个多了,都是经过本人亲自测试通过后的代码,所以,大家可以放心的使用,有问题的话,可以进行留言交流哦。。。

    Github仓库地址:

    https:https://github.com/qq496616246/WeChatCode.git

    git:git@github.com:qq496616246/WeChatCode.git

    彩蛋:

    如果你想利用闲暇零散的学习技术,那么不妨关注我的公众号阅读你想要的文章哦!

    公众号搜索:Java菜鸟进阶之路

    展开全文
  • 微信公众平台 获取用户openid

    千次阅读 2018-08-30 16:06:20
    今天做微信公众号获取用户openid,圆满成功,特此来一发。   第一步:理解逻辑。   1:获取openid的逻辑 获得微信的openid,需要先访问微信提供的一个网址:这个网址名为url1,下面有赋值。 通过这个网址,...
  • 获取用户openid方法

    千次阅读 2019-06-22 11:26:58
    //app.js wx.login({ success: function(res) { var that = this; var header = { ‘content-type’: ‘application/...‘token’: wx.getStorageSync(‘token’) //读取cookie 拿到登录之后异步保存的token值 }; if...
  • 方法一:通过全局Access Token获取用户基本信息 用户关注以及回复消息的时候,均可以获得用户OpenID 然后使用access_token接口,请求获得全局Access Token ...amp;amp;appid=APPID&amp;...secret=APPSE...
  • 微信小程序获取用户openid

    万次阅读 多人点赞 2018-03-26 17:12:53
    1、wx.login(OBJECT) 调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的 会话密钥(session_key)。用户数据的加解密通讯需要依赖会话密钥完成。2、code 换取 ...
  • 包含两个东西,1是实现文档,2是实现demo。 这是java版的,实现原理,通过JS请求自定义controller方法来获取微信用户信息的。
  • 首先需要在微信公众平台申请账号并在微信...设置->公众号设置->功能设置中设置或者在平台下接口权限->网页权限->网页授权中设置授权域名。...redirect_uri=REDIRECT_URI&response_type=code&scope=
  • 如何获取微信用户openid

    千次阅读 2019-04-02 16:54:29
    方法一:通过全局Access Token获取用户基本信息 用户关注以及回复消息的时候,均可以获得用户OpenID 然后使用access_token接口,请求获得全局Access Token ...appid=APPID&secret=APPSECRE...
  • h5怎么获取微信用户openId,h5如何获取微信用户openId

    万次阅读 多人点赞 2016-11-23 09:05:59
    最近公司需要做一个微信公众号,作为一个前端,我首当其冲,首先需要做一个 “微信和系统用户绑定”的功能;主要步骤为: 1.获取微信openid; 2.通过openid获取用户信息;无用户信息需要绑定 3.输入手机并确认...
  • 本文demo下载:wisdomdd.cn在开发微信公众号时,一旦... OpenId相应于用户唯一主键注意: 上面视频中漏掉了一个很重要的点: 网页授权获取用户基本信息需要修改其相应的域名(这个域名也是访问项目的域名) 如果没有相...
  • 在微信公众号中,获取关注用户OPENID。代码是用C#来进行开发的。
  • 借助小程序云开发获取小程序用户openid

    万次阅读 多人点赞 2018-10-11 17:29:11
    我们之前获取用户的openid,如下图官方文档说明,是通过该wx.login先获取临时凭证,然后再用临时凭证去换取用户的openid,这样做无可厚非,但是小程序出了云开发之后,再用这种方法获取用户openid就显得有些麻烦了,...
  • java获取微信用户openid

    千次阅读 2018-07-06 16:20:13
    服务器携带登录凭证code以及小程序的appid和appsecret从微信服务器中获取openid和session_...
  • 小程序用户openid是用户在小程序中的唯一标识符, openid长度官方建议是保存为64位, 但是在小程序支付接口中, 用户的openid是128位, 你可以根据情况处理。 猛击这里, 观看《小程序获取用户的openid》...
  • 微信h5静默、非静默授权获取用户openId的方法和步骤: 一、openId是什么? openId是用户在当前公众号下的唯一标识(‘身份证’),就是说通过这个openId,就能区分在这个公众号下具体是哪个用户。 二、openId有什么用...
  • PHP 获取微信用户openid

    2019-11-19 08:50:46
    //获取小程序传来的code $code = I('code','','htmlspecialchars'); //获取小程序appid和appsecret $sys = M('system')->where(['id'=>1])->...//获取openid $url = "https://api.weix...
  • 微信公众号静默授权获取用户openId开发环境和文档微信微信公众平台接口测试帐号申请微信公众号接入配置微信公众平台接口调试工具自定义菜单(公众号)网页授权文档(非常有必要看一下)前端Vue 开发环境和文档 微信 ...
1 2 3 4 5 ... 20
收藏数 32,167
精华内容 12,866
关键字:

用户openid