安卓微信登录

首先到微信官网注册:https://open.weixin.qq.com/cgi-bin/frame?t=home/app_tmpl&lang=zh_CN


这里需要注意一点的是,app的签名。我们在android studio获取签名的格式如下:

MD5: 97:CF:28:B9:D6:8E:E1:2D:CB:78:4F:7B:C6:C6:E4:F8

但官网需要的应用签名必须小写且无符号,所以应该改为:

97cf28b9d68ee12dcb784f7bc6c6e4f8。

微信获取签名的工具:点击下载 


1.首先在项目根目录下建一个

wxapi包以及WXEntryActivity类,包名和类名必须同上。
在manifest配置如下:
        <!--微信登录配置-->
        <activity
            android:name=".wxapi.WXEntryActivity"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:exported="true" />


    </application>



2.在主界面添加如下代码:

    /*微信登录*/
    private void wxLogin() {
        //通过WXAPIFactory工厂获取IWXApI的示例
        IWXAPI api = WXAPIFactory.createWXAPI(this, Constant.APP_ID_WX, true);
        //将应用的appid注册到微信
        api.registerApp(Constant.APP_ID_WX);
        SendAuth.Req req = new SendAuth.Req();
        req.scope = "snsapi_userinfo";
//                req.scope = "snsapi_login";//提示scope参数错误或者没有scope权;限用snsapi_base提示没权限
        req.state = "wechat_sdk_微信登录";
        //用于保持请求和回调的状态,授权请求后原样带回给第三方。
        // 该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验。
        api.sendReq(req);
    }


3.WXEntryActivity详解:

public class WXEntryActivity extends AppCompatActivity implements IWXAPIEventHandler {

    /**
     * 微信登录相关
     */
    private IWXAPI api;
    private String tag = "WXEntryActivity";
    public static String access_token = "access_token";
    public static String openid = "openid";
    public static final String ACTION_GETWX = "com.bs.utown.get_wx_msg";//用于广播的action


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //通过WXAPIFactory工厂获取IWXApI的示例
        api = WXAPIFactory.createWXAPI(this, Constant.APP_ID_WX, true);
        //将应用的appid注册到微信
        api.registerApp(Constant.APP_ID_WX);
        Logs.d("------------------------------------");
        //注意:
        //第三方开发者如果使用透明界面来实现WXEntryActivity,需要判断handleIntent的返回值,如果返回值为false,
        // 则说明入参不合法未被SDK处理,应finish当前透明界面,避免外部通过传递非法参数的Intent导致停留在透明界面,引起用户的疑惑
        try {
            boolean result = api.handleIntent(getIntent(), this);
            if (!result) {
                Logs.i("参数不合法,未被SDK处理,退出");
                finish();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        api.handleIntent(data, this);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        api.handleIntent(intent, this);
        finish();
    }

    @Override
    public void onReq(BaseReq baseReq) {
        Logs.d(tag + "74   baseReq:" + JSON.toJSONString(baseReq));
    }

    @Override
    public void onResp(BaseResp baseResp) {
        Logs.w(tag + "78  " + JSON.toJSONString(baseResp));
        Logs.i(tag + "79  " + baseResp.errStr + "," + baseResp.openId + "," + baseResp.transaction + "," + baseResp.errCode);

        String code = ((SendAuth.Resp) baseResp).code;
        String result = "";
        switch (baseResp.errCode) {
            case BaseResp.ErrCode.ERR_OK:
                result = "发送成功";
/*现在请求获取数据 access_token https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code*/

                OkHttpUtils.get().url("https://api.weixin.qq.com/sns/oauth2/access_token")
                        .addParams("appid", Constant.APP_ID_WX)
                        .addParams("secret", Constant.APP_SECRET_WX)
                        .addParams("code", code)
                        .addParams("grant_type", "authorization_code")
                        .build()
                        .execute(new StringCallback() {
                            @Override
                            public void onError(okhttp3.Call call, Exception e, int id) {
                                Logs.e(tag + "113 请求错误.." + e+"  "+id+" \n "+call);
                            }

                            @Override
                            public void onResponse(String response, int id) {
                                Logs.v(tag + "118 response:" + response);
                                String tokenstr = null, openidstr = null;
                                try {
                                    JSONObject jo = new JSONObject(response);
                                    tokenstr = jo.getString(access_token);
                                    openidstr = jo.getString(openid);
                                    Logs.i(tag + " 116  " + tokenstr + "   " + openidstr);
                                } catch (JSONException e) {
                                    e.printStackTrace();
                                }
                                /*通过广播将access_token和openid返回登录界面*/
                                LocalBroadcastManager.getInstance(WXEntryActivity.this).sendBroadcast(new Intent(ACTION_GETWX).
                                        putExtra(access_token, tokenstr).putExtra(openid, openidstr));
                            }
                        });
                break;
            case BaseResp.ErrCode.ERR_USER_CANCEL:
                result = "发送取消";
                break;
            case BaseResp.ErrCode.ERR_AUTH_DENIED:
                result = "发送被拒绝";
                break;
            case BaseResp.ErrCode.ERR_BAN:
                result = "签名错误";
                break;
            default:
                result = "发送返回";
                break;
        }
        Toast.makeText(WXEntryActivity.this, result, Toast.LENGTH_LONG).show();
        finish();
    }

}

3.1首先来看,如果你的签名无效返回的数据如下:

WXEntryActivity78  {"errCode":-6,"openId":"","type":1}

我们首先来看这个

BaseResp.ErrCode
 
 
int ERR_BAN = -6;签名错误
其他几种错误格式
static int	ERR_AUTH_DENIED
认证被否决
static int	ERR_COMM
一般错误
static int	ERR_OK
正确返回
static int	ERR_SENT_FAILED
发送失败
static int	ERR_UNSUPPORT
不支持错误
static int	ERR_USER_CANCEL
用户取消

3.2SendAuth.Resp详解

我们可以看出继承自baseResp

{
    "code":"0712DRee0kzwiz13fUce0900feRet",
    "country":"CN",
    "errCode":0, 
    "lang":"zh_CN",
    "state":"wechat_sdk_微信登录",
    "type":1,
    "url":"wxb363a9ff53731258://oauth?code=0712DRee0kzwiz13fUce0900fe02DRet&ate=wechat_sdk_%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95"
}
解释: 
errCode:
 //ERR_OK = 0(用户同意) ERR_AUTH_DENIED = -4(用户拒绝授权 ERR_USER_CANCEL = -2(用户取消)
code:用户换取access_token的code,仅在ErrCode为0时有效
state:第三方程序发送时用来标识其请求的唯一性的标志,由第三方程序调用sendReq时传入,由微信终端回传,state字符串长度不能超过1K
lang:微信客户端当前语言
country:微信用户当前国家信息

3.3获取access_tokenopenid

获取的地址:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
参数说明: 
appid:应用唯一标识,在微信开放平台提交应用审核通过后获得 
secret:应用密钥AppSecret,在微信开放平台提交应用审核通过后获得 
code:填写第一步获取的code参数 

grant_type:固定值,写authorization_code

返回结果说明:

{
    "access_token":"hSTsG7nq8e0yEFhOZFT-wAdTsjT9jC0AYvGRiqGwwR6Hko99o_mmYR8KO18kMxeDOz33d9tnBhMzu_NLsIha2HqvTm1OGPL1weBdvXZVFFc",
    "expires_in":7200,
    "refresh_token":"AeN69M27vttqCedxoIOSeY6cxvbt1N584HjEOclUXtNWxRaZWgmtfvn2jWIDX4tq5t-7Btlc1UkEyyFhV7HVIMXe-V6RPjoZdF525vLzev8",
    "openid":"olmt4wfxS21G4VeeVX16_zUhZezY",
    "scope":"snsapi_userinfo",
    "unionid":"o5aWQwAa7niCIXhAIRBOwglIJ7UQ"
}

access_token:接口调用凭证 
expires_in :access_token接口调用凭证超时时间,单位(秒) 
refresh_token 用户刷新access_token 
openid 授权用户唯一标识 
scope 用户授权的作用域,使用逗号(,)分隔

3.4刷新或续期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。

refresh_token拥有较长的有效期(30天),当refresh_token失效的后,需要用户重新授权,所以,请开发者在refresh_token即将过期时(如第29天时),进行定时的自动刷新并保存好它。

请求方法 
使用/sns/oauth2/access_token接口获取到的refresh_token进行以下接口调用:

http请求方式: GET

https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

参数说明 
参数 是否必须 说明 
appid 是 应用唯一标识 
grant_type 是 填refresh_token 
refresh_token 是 填写通过access_token获取到的refresh_token参数


4.接收数据

/*通过广播将access_token和openid返回登录界面*/
LocalBroadcastManager.getInstance(WXEntryActivity.this).sendBroadcast(new Intent(ACTION_GETWX).
        putExtra(access_token, tokenstr).putExtra(openid, openidstr));

我们可以看到我在WXEntryActivity中添加了用接收数据的广播,最主要是通过openid和access_token获取个人信息。

4.1首先在登录的界面添加接收的广播:

   /*创建用于接收数据的广播*/
    private BroadcastReceiver wxReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(WXEntryActivity.ACTION_GETWX)) {
                wx_access_token = intent.getStringExtra(WXEntryActivity.access_token);
                wx_openid = intent.getStringExtra(WXEntryActivity.openid);
                getWxUserInfo();
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        /*注册微信广播*/
        IntentFilter filter = new IntentFilter(WXEntryActivity.ACTION_GETWX);
        LocalBroadcastManager.getInstance(this).registerReceiver(wxReceiver, filter);

4.2请求个人信息的方式如下:

    /*获取WX的用户信息*/
    private void getWxUserInfo() {
        //https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
        OkHttpUtils.get()
                .url("https://api.weixin.qq.com/sns/userinfo")
                .addParams("access_token", wx_access_token)
                .addParams("openid", wx_openid)//openid:授权用户唯一标识
                .build()
                .execute(new StringCallback() {
                    @Override
                    public void onError(okhttp3.Call call, Exception e, int id) {
                        Logs.e(tag + "141获取错误 " + e + "  " + id + "  " + call);
                    }

                    @Override
                    public void onResponse(String response, int id) {
                        Logs.i(tag + "144 " + response + "  " + id);
                        DialogNotileUtil.show(LoginActivity.this, response);
                    }
                });
    }

4.3返回的数据:










































猜你喜欢

转载自blog.csdn.net/xxdw1992/article/details/80619746