1. 程式人生 > >Android:微信授權登入與微信分享全解析

Android:微信授權登入與微信分享全解析

前言

在移動網際網路浪潮中,聯網APP已經把單機拍死在沙灘上,很多公司都希望自家應用能夠有一套帳號系統,可是許多使用者卻並不一定買賬:我憑啥註冊你家應用的帳號?微博,微信,QQ幾乎成了每個人手機中的必裝應用,於是微信,微博,QQ說了:來來來,你們都可以用我家的帳號登入你家應用,只要你遵循OAuth2.0協議標準就行。於是第三方社交帳號登陸成為了許多新興應用的選擇,由於騰訊官方微信開放平臺的線上文件相對最新的SDK有些出入,並且登入相關的文件結構次序有些紊亂,今天就把我的一些經驗記錄在此,對微信開放平臺官方的線上文件進行一定的整理。同時微信分享可以擴大自身APP影響力,於是微信分享功能也是很多開發者需要的功能,一併整理在此,希望能對後來的同道朋友有所幫助。
轉載請註明原作者

xiong_it和原文連線:http://blog.csdn.net/xiong_it/article/details/48317527,謝謝!

微信登入

授權流程說明

微信OAuth2.0授權登入讓微信使用者使用微信身份安全登入第三方應用或網站,在微信使用者授權登入已接入微信OAuth2.0的第三方應用後,第三方可以獲取到使用者的介面呼叫憑證(access_token),通過access_token可以進行微信開放平臺授權關係介面呼叫,從而可實現獲取微信使用者基本開放資訊和幫助使用者實現基礎開放功能等。
微信OAuth2.0授權登入目前支援authorization_code模式,適用於擁有server端的應用授權。該模式整體流程為:
1. 第三方發起微信授權登入請求,微信使用者允許授權第三方應用後,微信會拉起應用或重定向到第三方網站,並且帶上授權臨時票據code引數;
2. 通過code引數加上AppID和AppSecret等,通過API換取access_token;
3. 通過access_token進行介面呼叫,獲取使用者基本資料資源或幫助使用者實現基本操作。
獲取access_token時序圖:
xiong_it微信授權流程

注意:如果開發者需要呼叫登入介面,需要進行進行開發者認證並交300大洋,官方線上文件說無需繳費,其實那已經是過去式了,只是在線文件沒有更新而異。

下面將依次講解微信授權登入流程。所有網路請求均為GET請求。

1、獲取臨時票據code
2、獲取access_token & openid
3、檢查access_token是否有效
4、重新整理或續期access_token
5、獲取微信使用者詳細資訊

獲取臨時票據code

前三條向右的箭頭

{ 
    // 發出授權申請
    Final SendAuth.Req req = new SendAuth.Req();
    req.scope = "snsapi_userinfo"
; req.state = "wechat_sdk_微信登入,分享demo_test"; api.sendReq(req); }

上兩條箭頭向左的流程在程式碼體現出來的就是:

public void onResp(BaseResp resp) ;// 這個回撥介面位於IWXAPIEventHandler中

返回的資料為resp,用作請求登入授權時,它是SendAuth.Resp的例項,攜帶的資料有:

ErrorCode:ERR_OK = 0(使用者同意);ERR_AUTH_DENIED = -4(使用者拒絕授權);ERR_USER_CANCEL = -2(使用者取消)
code:使用者換取access_token的code,僅在ErrCode為0時有效
state:第三方程式傳送時用來標識其請求的唯一性的標誌,由第三方程式呼叫sendReq時傳入,由微信終端回傳,state字串長度不能超過1K
lang:微信客戶端當前語言
country:微信客戶端當前國家

以上資料均以static String形式存在SendAuth.Resp的resp物件中。

注意:當使用微信提供最新的SDK/library時,上面有些資料是不存在,微信開放平臺的文件和API及SDK沒有同步更新。讀者可使用最下方微信登入,分享demo中的筆者使用的jar包構建工程。

獲取access_token & openid

注意:微信的介面連結是使用SSL的安全連結,普通的HttpClient訪問會導致應用崩潰或報錯,詳細方法請下載最下方的微信登入,分享demo程式碼,或者點選下方連結直接搜尋

appid:  應用唯一標識,在微信開放平臺提交應用稽核通過後獲得
secret:應用金鑰AppSecret,在微信開放平臺提交應用稽核通過後獲得
code    :填寫第一步獲取的code引數
grant_type:固定值,填authorization_code

最下方向左的箭頭表示使用code訪問完連結返回的資料,json攜帶的資料有:

access_token:介面呼叫憑證
expires_in:access_token的有效期,一般為7200(秒),也即是兩小時
refresh_token:使用者重新整理access_token
openid:授權使用者唯一標識
scope:使用者授權的作用域,使用逗號(,)分隔

檢查access_token是否有效

{ 
"errcode":0,"errmsg":"ok"
}

失效時的返回資料為:

{ 
"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。
refresh_token擁有較長的有效期(30天),當refresh_token失效的後,需要使用者重新授權。

appid:應用唯一標識
grant_type:固定值,填refresh_token
refresh_token:填寫前面獲取到的refresh_token的值

返回的json資料有:

access_token:介面呼叫憑證
expires_in:access_token介面呼叫憑證超時時間,單位(秒)
refresh_token:使用者重新整理access_token
openid:授權使用者唯一標識
scope:使用者授權的作用域,使用逗號(,)分隔

獲取微信使用者詳細資訊

openid:普通使用者的標識,對當前開發者帳號唯一
nickname:普通使用者暱稱
sex:普通使用者性別,1為男性,2為女性
province:普通使用者個人資料填寫的省份
city:普通使用者個人資料填寫的城市
country:國家,如中國為CN
headimgurl:使用者頭像,最後一個數值代表正方形頭像大小(有0466496132數值可選,0代表640*640正方形頭像),使用者沒有頭像時該項為空
privilege:使用者特權資訊,json陣列,如微信沃卡使用者為(chinaunicom)
unionid:使用者統一標識。針對一個微信開放平臺帳號下的應用,同一使用者的unionid是唯一的。

微信官方建議:
開發者最好儲存unionID資訊,以便以後在不同應用之間進行使用者資訊互通。

微信登入的流程結束了, 至於開發者需要將那些使用者資訊上傳到自家的app伺服器就取決於開發者了。

微信分享

1、微信分享分為微信好友分享,朋友圈分享,當然,還有收藏也是共用分享的介面,無需授權登入即可呼叫分享介面。
2、由於好友分享,朋友圈分享和收藏只是一個引數的區別,所以下面只講好友分享,具體的可以下載最下方的微信登入,分享demo原始碼進行檢視。
3、微信可以分享的內容包括,純文字,圖片,連結,音樂,視訊,app,emoji表情等。

微信分享流程

1、在你的工程裡面新建一個wxapi包,並且新建一個WXEntryActivity,繼承Activity,或其他Activity(這兩步是必須的,微信開發文件中有提到),詳見:
https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=1417751808&token=&lang=zh_CN
2、並在manifest檔案裡面加上exported屬性,設定為true。
這裡寫圖片描述
3、實現一個IWXAPIEventHandler介面。
微信傳送的請求將回調到onReq方法,傳送到微信請求的響應結果將回調到onResp方法
在WXEntryActivity中將接收到的intent及實現了IWXAPIEventHandler介面的物件傳遞給IWXAPI介面的handleIntent方法,示例如下圖:
這裡寫圖片描述
當微信傳送請求到你的應用,將通過IWXAPIEventHandler介面的onReq方法進行回撥,類似的,應用請求微信的響應結果將通過onResp回撥。

注意
如果需要混淆程式碼,為了保證sdk的正常使用,需要在proguard.cfg加上下面兩行配置:

-keep class com.tencent.mm.sdk.** {
*;
}

微信分享詳細程式碼流程是:

IWXAPI api = WXAPIFactory.createWXAPI(this, APP_ID, false);// 傳入申請到的appid,得到一個IWXAPI的例項
api.registerApp(APP_ID);// 將app註冊到微信列表,我不知道這是什麼意思,有知道的請告訴我,謝謝!

// 開始分享純文字到給好友
WXTextObject textObj = new WXTextObject();
textObj.text = text;

// 用WXTextObject物件初始化一個WXMediaMessage物件
WXMediaMessage msg = new WXMediaMessage();
msg.mediaObject = textObj;

// 傳送文字型別的訊息時,title欄位不起作用
// msg.title = "Will be ignored";
msg.title = "分享文字標題";
msg.description = text;

// 構造一個Req
SendMessageToWX.Req req = new SendMessageToWX.Req();
req.transaction = buildTransaction("text"); // transaction欄位用於唯一標識一個請求
req.message = msg;

req.scene = SendMessageToWX.Req.WXSceneTimeline;// 表示傳送場景為朋友圈,這個代表分享到朋友圈
// req.scene = SendMessageToWX.Req.WXSceneSession;//表示傳送場景為好友對話,這個代表分享給好友
// req.scene = SendMessageToWX.Req.WXSceneFavorite;// 表示傳送場景為收藏,這個代表新增到微信收藏
// 呼叫api介面傳送資料到微信 
api.sendReq(req);

上面大致的表現了一個分享純文字給好友的場景,如果需要分享到朋友圈,只需要更改req.scene欄位值。

1、其中IWXAPI.registerAPP(APP_ID)是官方demo中的一行程式碼,表示的是將app註冊到微信列表,我並不知道有什麼用,所謂的微信列表出現在哪兒?該行程式碼刪除後,仍然可以獲取登入授權,實現分享等功能。有知道的請告訴我,謝謝!

2、目前筆者遇到無法分享線上圖片WXImageObject的問題,分享線上圖片時出現分享介面右上角“傳送”按鈕灰色,無法點選的情況,希望分享成功的朋友告訴我,謝謝!問題如下圖
線上圖片無法分享傳送

要分享連結,圖片,音樂,視訊等需要將WXTextObject 物件改成對應的obj物件。詳細請下載文章下方的微信登入,分享demo。

後記

由於微信官方demo中並未提供微信登入的程式碼示例,分享的程式碼很齊全,可是分享線上圖片的程式碼在我這裡卻又問題,所以筆者將自己的一些經驗和遇到的坑總結在這裡,包括了微信第三方登入,微信分享的內容,希望對大家有所幫助。也希望筆者在文中提到的問題有熱心人能夠解答

//1、 註冊到微信列表有什麼用,微信列表在哪兒可以看到
IWXAPI.registerApp(APP_ID);
//2、 我為什麼無法使用以下程式碼分享線上圖片
WXImageObject imgObj = new WXImageObject();
imgObj.imageUrl = imgUrl;// 線上圖片連結

WXMediaMessage msg = new WXMediaMessage();
msg.mediaObject = imgObj;

Bitmap bmp = BitmapFactory.decodeStream(new URL(url).openStream());
Bitmap thumbBmp = Bitmap.createScaledBitmap(bmp, THUMB_SIZE, THUMB_SIZE, true);
bmp.recycle();
msg.thumbData = Util.bmpToByteArray(thumbBmp, true);

SendMessageToWX.Req req = new SendMessageToWX.Req();
req.transaction = buildTransaction("img");
req.message = msg;
req.scene = isTimelineCb.isChecked() ? SendMessageToWX.Req.WXSceneTimeline : SendMessageToWX.Req.WXSceneSession;
api.sendReq(req);

update:20150917
最近有人向我反映生成的apk無法正常執行。在此進行解釋:
demo原始碼生成的apk不可正常執行的原因是:在微信開放平臺新增應用時,包名,應用簽名,app_id是繫結的。你們簽名的apk不起作用,demo程式碼僅供參考交流
demo原始碼下載http://download.csdn.net/detail/xiong_it/9099037

udapte:20160507
感謝6樓評論,指正了兩個筆誤,已修正,如果讀者只想實現分享功能,可以參考筆者的另一篇部落格: Anroid開發:友盟分享SDK v5使用指南(Android Studio)

update:20160711
筆者前段時間更新一篇博文:《微信支付SDK接入指南》。有興趣的可以前往閱讀。