1. 程式人生 > >微信移動應用接入開發, Android 授權微信登入獲取openid,unionid等,score引數錯誤或者沒有scope許可權

微信移動應用接入開發, Android 授權微信登入獲取openid,unionid等,score引數錯誤或者沒有scope許可權

    寫這篇文章的原因,就是自己氣不過。專案需求突然要做微信公眾號與App微信分享使用同個使用者體系,接到任務是確認這使用者體系,於是需要確認android app端獲取授權使用者後返回的unionid與微信公眾號授權使用者返回的unionid是否一致。但是,為了獲取這個unionid,讓我捉急了一個下午,因此,寫這篇文章可以為後來的朋友帶來方便。

第一步:請求CODE:

app介面可以設定一個button,在button的onClick()中填寫以下程式碼:

   <pre class="java" name="code">final SendAuth.Req req = new SendAuth.Req();
   req.scope = "snsapi_userinfo";
   req.state = "wxdemo";
   api.sendReq(req);

其中:

scope代表你應用的許可權,下圖展示某個應用的許可權:

    snsapi_base屬於基礎介面,若應用已擁有其它scope許可權,則預設擁有snsapi_base的許可權。使用snsapi_base可以讓移動端網頁授權繞過跳轉授權登入頁請求使用者授權的動作,直接跳轉第三方網頁帶上授權臨時票據(code),但會使得使用者已授權作用域(scope)僅為snsapi_base,從而導致無法獲取到需要使用者授權才允許獲得的資料和基礎功能。     snsapi_userinfo:這個屬性許可權比snsapi_base高,使用此屬性,可以讓移動端網頁授權跳轉授權登入頁請求(本篇文章就是採用這個屬性,所以下面可以看到示例的跳往京東授權登入頁請求)

倘若微訊號還沒申請微信登入功能,那麼將出現錯誤頁面:

若正確:

第二步 獲取code

         微信的回撥都是在WXEntryActivity中的public void onResp(BaseResp resp)函式中得到的,也就是說,我們的code可以在resp中獲取到。

按照微信官方文件:

點選第一步事例中京東商城“確認登入”按鈕按道理說是可以從SendAuthResp獲取到code欄位的:

例如

<span style="font-size:18px;">case BaseResp.ErrCode.ERR_OK:
String code = ((SendAuth.Resp) resp).code;
Break</span>

但是這時,你會發現找不到code這個屬性。也就是說,按照官網說的去獲取是獲取不到code的。那該怎麼獲取呢?下面給你講解超級坑爹的方法;
case BaseResp.ErrCode.ERR_OK:
			result = R.string.errcode_success;
			
			String code = ((SendAuth.Resp) resp).token;

			break;

沒錯,你沒看錯,真正的code放在了屬性為”token”欄位中;

第三步 獲取登入授權後的資訊,包含openidunionid

根據微信官網提到,這個步驟叫通過code獲取access_token,需要用get方式請求

(你的Appid&secret=(你的app secret)&code=(第二步中獲取到的code&grant_type=authorization_code,其中appid 和 app secret就是你在微信開放平臺申請移動應用後,在應用介面可以找到。

上面的連結是https連結,Android app要訪問https需要構造一個新的HttpClient,

以下附上第三步所需用到的程式碼:

// 第三方應用傳送到微信的請求處理後的響應結果,會回撥到該方法


@Override

public void onResp(BaseResp resp) {

int result = 0;



switch (resp.errCode) {

case BaseResp.ErrCode.ERR_OK:

result = R.string.errcode_success;


String code = ((SendAuth.Resp) resp).token;

String url = "https://api.weixin.qq.com/sns/oauth2/access_token" +

"?appid=" + Constants.APP_ID +

"&secret=" +Constants.APP_SECRET +

"&code=" + code +

"&grant_type=authorization_code";


String result1 = new String(httpGet(url));

Log.d("WXEntryActivity", result1);

break;

case BaseResp.ErrCode.ERR_USER_CANCEL:

result = R.string.errcode_cancel;

break;

case BaseResp.ErrCode.ERR_AUTH_DENIED:

result = R.string.errcode_deny;

break;

default:

result = R.string.errcode_unknown;

break;

}


Toast.makeText(this, result, Toast.LENGTH_LONG).show();

}



public static byte[] httpGet(final String url) {

if (url == null || url.length() == 0) {

return null;

}

 

HttpClient httpClient = getNewHttpClient();

HttpGet httpGet = new HttpGet(url);

 

try {

HttpResponse resp = httpClient.execute(httpGet);

if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {

return null;

}

 

return EntityUtils.toByteArray(resp.getEntity());

 

} catch (Exception e) {

e.printStackTrace();

return null;

}

}


private static HttpClient getNewHttpClient() { 

   try { 

       KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 

       trustStore.load(null, null); 

 

       SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore); 

       sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 

 

       HttpParams params = new BasicHttpParams(); 

       HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 

       HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); 

 

       SchemeRegistry registry = new SchemeRegistry(); 

       registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 

       registry.register(new Scheme("https", sf, 443)); 

 

       ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); 

 

       return new DefaultHttpClient(ccm, params); 

   } catch (Exception e) { 

       return new DefaultHttpClient(); 

   } 

}


private static class SSLSocketFactoryEx extends SSLSocketFactory {      

      

    SSLContext sslContext = SSLContext.getInstance("TLS");      

      

    public SSLSocketFactoryEx(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {      

        super(truststore);      

      

        TrustManager tm = new X509TrustManager() {      

      

            public X509Certificate[] getAcceptedIssuers() {      

                return null;      

            }      

      

@Override

public void checkClientTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {

}

 

@Override

public void checkServerTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {

}  

        };      

      

        sslContext.init(null, new TrustManager[] { tm }, null);      

    }      

      

@Override

public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {

return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);

}

 

@Override

public Socket createSocket() throws IOException {

return sslContext.getSocketFactory().createSocket();

} 

}