1. 程式人生 > >微信授權APP第三方登陸(Android)

微信授權APP第三方登陸(Android)

前幾天負責的程式說是要加入第三方登陸的功能,雖然現在有服務商集成了第三方登陸,但是平時所用的也就微信和QQ,就自己看文件寫了,其中也遇到了一些問題,然後我把我做這個的流程貼出來,並附上對應的Demo,執行Demo前請將Android的SDK以及依賴包的版本升級到最新。

1:首先如果要使用微信的第三方登陸功能,必須要有微信官方認證的微信開放平臺開發者賬號,這個需要300一年,當然,還有很多其他很好的功能。

2:對你要接入第三方登陸的應用進行申請,申請通過之後,可以獲取到關鍵的AppID和AppSecret,申請的時候有兩個地方要注意,這裡寫圖片描述

應用包名是指在你的AndroidManifest檔案下的package中的內容,

這裡寫圖片描述

應用簽名工具在微信開放平臺中資源下載中的Android資源下下載,之後在你的手機上執行,輸入你的應用包名即可得到。

3:下面就是正式開始操作程式碼,將微信的開發工具包匯入你專案的libs目錄中。 
這裡寫圖片描述

4:在AndroidManifest.xm新增許可權支援,程式碼如下。

    <uses-permission         android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission
android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  • 1
  • 2
  • 3
  • 4
  • 5

5:將你的應用程式註冊到微信,只有這樣你的程式啟動後,微信才能響應你的程式,我是在重寫Application的類中註冊的,程式碼如下:

public class
App extends Application {
public static final String WX_APPID = "wxb53411a37963b886"; public static final String WX_APPSecret = "d72be30f31c81dcc507d8c08c0d700f8"; private IWXAPI api; @Override public void onCreate() { super.onCreate(); api = WXAPIFactory.createWXAPI(this, WX_APPID, true); api.registerApp(WX_APPID); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

6:在你的程式包下新建一個名為wxapi的包,並在下面新建一個名為WXEntryActivity的類,並實現IWXAPIEventHandler介面。其中微信傳送給第三方應用的請求將會回撥onReq方法,第三方應用傳送到微信的請求的響應結果將回調nResp方法。在成功響應微信登陸請求後我會發送一個廣播,並存儲獲得的code。code是獲取access_token所必需的,具體可以參考微信的文件。程式碼如下:

public class WXEntryActivity extends AppCompatActivity implements IWXAPIEventHandler {

    private IWXAPI api;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        api = WXAPIFactory.createWXAPI(this, App.WX_APPID, false);
        //將你收到的intent和實現IWXAPIEventHandler介面的物件傳遞給handleIntent方法
        api.handleIntent(getIntent(), this);
    }

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

    @Override
    public void onReq(BaseReq baseReq) {

    }

    @Override
    public void onResp(BaseResp baseResp) {
        String result = "";
        switch (baseResp.errCode) {
            case BaseResp.ErrCode.ERR_OK:
                String code = ((SendAuth.Resp) baseResp).code;
                SharedPreferences WxSp = getApplicationContext().getSharedPreferences(PrefParams.spName, Context.MODE_PRIVATE);
                SharedPreferences.Editor WxSpEditor = WxSp.edit();
                WxSpEditor.putString(PrefParams.CODE,code);
                WxSpEditor.apply();
                Intent intent = new Intent();
                intent.setAction("authlogin");
                WXEntryActivity.this.sendBroadcast(intent);
                finish();
                break;
            case BaseResp.ErrCode.ERR_USER_CANCEL:
                result = "傳送取消";
                Toast.makeText(this, result, Toast.LENGTH_LONG).show();
                finish();
                break;
            case BaseResp.ErrCode.ERR_AUTH_DENIED:
                result = "傳送被拒絕";
                Toast.makeText(this, result, Toast.LENGTH_LONG).show();
                finish();
                break;
            default:
                result = "傳送返回";
                Toast.makeText(this, result, Toast.LENGTH_LONG).show();

                finish();
                break;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

然後還需要在AndroidManifest中隊新新增的類進行註冊,並將exported屬性設定為true(表示該Activity可以被其它程式呼叫)。

7:微信授權流程如下:這是官網上看的 
這裡寫圖片描述 
按照流程來,請求code,程式碼如下:

private void weChatAuth() {
        if (api == null) {
            api = WXAPIFactory.createWXAPI(getActivity(), App.WX_APPID, true);
        }
        SendAuth.Req req = new SendAuth.Req();
        req.scope = "snsapi_userinfo";
        req.state = "wx_login_duzun";
        api.sendReq(req);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

執行該操作之後會拉起微信開啟授權登陸頁面,然後你操作的結果會返回到我們第六步建立的WXEntryActivity類中,若同意請求則可以獲取到code執行接下來的操作。

8:通過code獲取access_token,按下面的請求可以獲取access_token

這裡的APPID和SECRET就是我們申請應用時獲得的。 
正確返回如下:

{ “access_token”:”ACCESS_TOKEN”, “expires_in”:7200, 
“refresh_token”:”REFRESH_TOKEN”, “openid”:”OPENID”, “scope”:”SCOPE”, 
“unionid”:”o6_bmasdasdsad6_2sgVt7hMZOPfL” }

我是這樣實現的

public void getAccessToken(){

        SharedPreferences WX_Sp = getApplicationContext().getSharedPreferences(PrefParams.spName, Context.MODE_PRIVATE);
        String code = WX_Sp.getString(PrefParams.CODE, "");
         final SharedPreferences.Editor WX_SpEditor = WX_Sp.edit();

        String url  = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
                + App.WX_APPID
                + "&secret="
                + App.WX_APPSecret
                + "&code="
                + code
                + "&grant_type=authorization_code";
        Utils.log("獲取access_token的地址"+url);
        HttpUtil.sendHttpRequest(url, new HttpCallBackListener() {
            @Override
            public void onFinish(String response) {
                try {
                    JSONObject jsonObject = new JSONObject(response);
                    String access_token = jsonObject.getString("access_token");
                    Utils.log("---------access_token---------"+access_token);
                    String openid = jsonObject.getString("openid");
                    Utils.log("---------open_id---------"+openid);
                    String refresh_token = jsonObject.getString("refresh_token");
                    if (!access_token.equals("")) {
                        WX_SpEditor.putString(PrefParams.ACCESS_TOKEN, access_token);
                        WX_SpEditor.apply();
                    }
                    if (!refresh_token.equals("")) {
                        WX_SpEditor.putString(PrefParams.REFRESH_TOKEN, refresh_token);
                        WX_SpEditor.apply();
                    }
                    if (!openid.equals("")) {
                        WX_SpEditor.putString(PrefParams.WXOPENID, openid);
                        WX_SpEditor.apply();
                        ThirdLoginWeChat(access_token, openid);

                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
            @Override
            public void onError(Exception e) {
                Utils.showToast(LoginActivity.this, "通過code獲取資料沒有成功");
            }
        });
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

因為只是登陸而已,所以我沒有請求refresh_token,也很簡單,獲取到access_token之後按照要求請求就可以了,

9:最後一步就是獲取你需要的第三方登陸的使用者個人資訊了 
請求說明

“` 
private void ThirdLoginWeChat(String access_token, String openid) {

    String url  = "https://api.weixin.qq.com/sns/userinfo?access_token="
            + access_token
            + "&openid="
            + openid;

    HttpUtil.sendHttpRequest(url, new HttpCallBackListener() {
        @Override
        public void onFinish(String response) {
            try {
                JSONObject jsonObject = new JSONObject(response);
                Utils.log(jsonObject.toString()+"-------獲取個人資訊---");
                String nickName = jsonObject.getString("nickname");
                String sex = jsonObject.getString("sex");
                String province = jsonObject.getString("province");
                String city = jsonObject.getString("city");
                String country = jsonObject.getString("country");
                String headimgurl = jsonObject.getString("headimgurl");
                String privilege = jsonObject.getString("privilege");
                String unionid = jsonObject.getString("unionid");


            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onError(Exception e) {

        }
    });
}```
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

更詳細的Demo裡面都有,有什麼不清楚的地方可以留言,當然鑑於我個人的初級水平,錯誤的地方希望加以斧正。感謝~

demo演示圖片:

這裡寫圖片描述 
這裡寫圖片描述 
這裡寫圖片描述