• 热门专题

应用接入微信登录步步为赢

作者:  发布日期:2016-12-26 20:23:22
  • 接入微信登录:

    1、准备工作

    1.在微信开放平台https://open.weixin.qq.com/注册成为开发者。

    2.在“管理中心”中创建一个移动应用,需“应用名称、简介、及28*28和108*108的PNG图片各一张,且大小不超过300k”,点击下一步,需“应用官网地址,应用签名及包名”等信息,然后即可提交审核。
    说明:
    应用签名:可在微信开发平台的资源中心》》资源下载》》中下载“签名生成工具”,用户获取已经安装到手机的第三方应用的签名。输入应用包名,即可获得该应用的签名值。

    3.提交审核后,在7个工作日内腾讯将给出审核结果。(通常较快,几个小时就可反馈结果)

    2、微信登录接入

    微信登录遵循协议Aouth4.0中的授权码模式,先介绍一下Aouth4.0的流程:

    处理流程

    3、微信登录的官方文档将微信登录分为3个步骤:

    第一步.请求code:

    {
        // send oauth request 
         Final SendAuth.Req req = new SendAuth.Req();
         req.scope = 'snsapi_userinfo';
         req.state = 'wechat_sdk_demo_test';
         api.sendReq(req);
    }
    
    用这段代码向微信开放平台请求授权码code,可拉起微信并打开授权登录页(前提是你安装了微信应用并已登录,未登录的会引导你先登录)下图:
    

    调起微信授权页面

    需要注意的情况:

    1.如果微信授权页不显示,请检查你的APP签名是否和你在腾讯开放平台的APP签名一致,不一致可修改腾讯开放平台中的APP签名,修改后重装微信或清除微信数据后重试。
    
    2.在你的包名相应目录下新建一个wxapi目录,并在该wxapi目录下新增一个WXEntryActivity类,该类继承自Activity(例如应用程序的包名为net.sourceforge,则新的包名为:net.sourceforge.wxapi),此处应注意包名不要弄错,新增类的名字必须为WXEntryActivity。
    

    返回说明

    用户点击授权后,微信客户端会被拉起,跳转至授权界面,用户在该界面点击允许或取消,SDK通过SendAuth的Resp返回数据给调用方。回调WXEntryActivity中的onResp(BaseResp resp)方法,如下:
    
    @Override
    public void onResp(BaseResp resp) {
        int errorCode = resp.errCode;
        switch (errorCode) {
        case BaseResp.ErrCode.ERR_OK:
            //用户同意
            String code = ((SendAuth.Resp) resp).code;
            break;
        case BaseResp.ErrCode.ERR_AUTH_DENIED:
            //用户拒绝
            break;
        case BaseResp.ErrCode.ERR_USER_CANCEL:
            //用户取消
            break;
        default:
            break;
        }
        ToastUtil.showMessageLong(this, resp.errStr);
    }
    

    客户端收到授权码后,向自己的服务器发起登录请求,并附带收到的授权码。

    服务端收到登录请求,向微信开放平台请求获取access_token,微信开放平台返回Json字符串:

    第二步:通过code获取access_token:

    获取第一步的code后,请求以下链接获取access_token:

    private String getAccessToken(String code) {
            String url = 'https://api.weixin.qq.com/sns/oauth4/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code';
            URI uri = URI.create(url);
            HttpClient client = new DefaultHttpClient();
            HttpGet get = new HttpGet(uri);
            HttpResponse response;
        try {
            response = client.execute(get);
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
    
                BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), 'UTF8'));
                StringBuilder sb = new StringBuilder();
    
                for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
                    sb.append(temp);
                }
    
                JSONObject object = new JSONObject(sb.toString().trim());
                accessToken = object.getString('access_token');
                openID = object.getString('openid');
                refreshToken = object.getString('refresh_token');
                expires_in = object.getLong('expires_in');
                return accessToken;
            }
        } catch (Exception e) {
            // TODO Autogenerated catch block
            e.printStackTrace();
        }
        return null;
    }
    

    参数说明

    参数        是否必须        说明 
    appid       是        应用唯一标识,在微信开放平台提交应用审核通过后获得
    
    secret      是      应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
    
    code        是       填写第一步获取的code参数
    
    grant_type  是      填authorization_code回说明**
    

    正确的返回:

    { 
    'access_token':'ACCESS_TOKEN', 
    'expires_in':7200, 
    'refresh_token':'REFRESH_TOKEN',
    'openid':'OPENID', 
    'scope':'SCOPE',
    'unionid':'o6_bmasdasdsad6_2sgVt7hMZOPfL'
    }
    
      参数                              说明
    access_token                    接口调用凭证
    expires_in  access_token        接口调用凭证超时时间,单位(秒)
    refresh_token                   用户刷新access_token
    openid                          授权用户唯一标识
    scope                           用户授权的作用域,使用逗号(,)分隔
    unionid          只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
    

    错误返回样例:

    {'errcode':40029,'errmsg':'invalid code'}
    

    第三步:通过access_token调用接口

    获取access_token后,进行接口调用,有以下前提:

    access_token有效且未超时;
    微信用户已授权给第三方应用帐号相应接口作用域(scope)。
    

    对于接口作用域(scope),能调用的接口有以下:

    授权作用域(scope)             接口                接口说明
    snsapi_base       /sns/oauth4/access_token     通过code换取              access_token、refresh_token和已授权scope
                        /sns/oauth4/refresh_token  刷新或续期access_token使用
                        /sns/auth                  检查access_token有效性
    snsapi_userinfo    /sns/userinfo               获取用户个人信息
    

    其中snsapi_base属于基础接口,若应用已拥有其它scope权限,则默认拥有snsapi_base的权限。使用snsapi_base可以让移动端网页授权绕过跳转授权登录页请求用户授权的动作,直接跳转第三方网页带上授权临时票据(code),但会使得用户已授权作用域(scope)仅为snsapi_base,从而导致无法获取到需要用户授权才允许获得的数据和基础功能。

    以获取用户信息为例:

    private void getUserInfo() {
            if (isAccessTokenIsInvalid() && System.currentTimeMillis() < expires_in) {
                String uri = 'https://api.weixin.qq.com/sns/userinfo?access_token=' + accessToken + '&openid=' + openID;
                HttpClient client = new DefaultHttpClient();
                HttpGet get = new HttpGet(URI.create(uri));
                try {
                    HttpResponse response = client.execute(get);
                    if (response.getStatusLine().getStatusCode() == 200) {
                        BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), 'UTF8'));
                        StringBuilder builder = new StringBuilder();
                        for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
                            builder.append(temp);
                        }
                        JSONObject object = new JSONObject(builder.toString().trim());
                        String nikeName = object.getString('nickname');
                    }
                } catch (Exception e) {
                    // TODO Autogenerated catch block
                    e.printStackTrace();
                }
            }
        }
    

    微信重复登录

    假设用户已经获得授权,则下次登录时只需要验证access_token是否有效,无效则重新获取授权,有效则无需重新获得授权。

    1.用户向自己的服务器请求登录,登录方式为微信登录,附带上次登录返回的的access_token
    
    2.服务器收到用户的登录请求,向微信开放平台发送access_token是否有效的验证请求如下:
    
    private boolean isAccessTokenIsInvalid() {
            String url = 'https://api.weixin.qq.com/sns/auth?access_token=' + accessToken + '&openid=' + openID;
            URI uri = URI.create(url);
            HttpClient client = new DefaultHttpClient();
            HttpGet get = new HttpGet(uri);
            HttpResponse response;
            try {
                response = client.execute(get);
                if (response.getStatusLine().getStatusCode() == 200) {
                    HttpEntity entity = response.getEntity();
                BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), 'UTF8'));
                StringBuilder sb = new StringBuilder();
    
                for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
                    sb.append(temp);
                }
                JSONObject object = new JSONObject(sb.toString().trim());
                int errorCode = object.getInt('errcode');
                if (errorCode == 0) {
                    return true;
                }
            }
        } catch (Exception e) {
            // TODO Autogenerated catch block
            e.printStackTrace();
        }
        return false;
    }
    

    返回说明

    正确的Json返回结果:
        { 
        'errcode':0,'errmsg':'ok'
        }
    
    错误的Json返回示例:
        { 
        'errcode':40003,'errmsg':'invalid openid'
        }
    

    如果access_token有效,服务端将信息返回给客户端,客户端成功登录。

    如果access_token无效,服务端向微信开放平台发送刷新access_token的请求如下:

    access_token是调用授权关系接口的调用凭证,由于access_token有效期(目前为2个小时)较短,当access_token超时后,可以使用refresh_token进行刷新,access_token刷新结果有两种:
    
    1.若access_token已超时,那么进行refresh_token会获取一个新的access_token,新的超时时间; 
    2.若access_token未超时,那么进行refresh_token不会改变access_token,但超时时间会刷新,相当于续期access_token。
    

    刷新token

    private void refreshAccessToken() {
        String uri = 'https://api.weixin.qq.com/sns/oauth4/refresh_token?appid=' + ShareUtil.APP_ID + '&grant_type=refresh_token&refresh_token='
                + refreshToken;
        HttpClient client = new DefaultHttpClient();
        HttpGet get = new HttpGet(URI.create(uri));
        try {
            HttpResponse response = client.execute(get);
            if (response.getStatusLine().getStatusCode() == 200) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), 'UTF8'));
                StringBuilder builder = new StringBuilder();
                for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
                    builder.append(temp);
                }
                JSONObject object = new JSONObject(builder.toString().trim());
                accessToken = object.getString('access_token');
                refreshToken = object.getString('refresh_token');
                openID = object.getString('openid');
                expires_in = object.getLong('expires_in');
            }
        } catch (Exception e) {
            // TODO Autogenerated catch block
            e.printStackTrace();
        }
    }
    

    正确的返回:

    { 
    'access_token':'ACCESS_TOKEN', 
    'expires_in':7200, 
    'refresh_token':'REFRESH_TOKEN', 
    'openid':'OPENID', 
    'scope':'SCOPE' 
    }
    参数                    说明
    access_token       接口调用凭证
    expires_in        access_token接口调用凭证超时时间,单位(秒)
    refresh_token     用户刷新access_token
    openid           授权用户唯一标识
    scope          用户授权的作用域,使用逗号(,)分隔
    

    错误返回样例:

    {
    'errcode':40030,'errmsg':'invalid refresh_token'
    }
    

延伸阅读:

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规