前期准備工作:申請AppId,下載資源包jar、文檔等。
微信授權登錄步驟:
1. 第三方發起微信授權登錄請求,微信用戶允許授權第三方應用后,微信會拉起應用或重定向到第三方網站,並且帶上授權臨時票據code參數;(第1步官方文檔寫得很模糊分散,做微信授權登錄的時候遇到很多問題,現在總結記錄下來)
2. 通過code參數加上AppID和AppSecret等,通過API換取access_token,openid;
3. 通過access_token和openid進行接口調用,獲取用戶基本數據資源或幫助用戶實現基本操作。
注意:
1.想要正常調起微信授權登錄頁面,應用包名和簽名必須是和申請AppId時上傳的應用保持一致,否則無法調起微信授權登錄頁面。Debug簽名是無法調起微信授權登錄頁面的。
2.想要接收微信返回值,也就是響應回調方法,必須做到以下3步操作:
a.新建一個包:應用包名.wxapi(應用包名必須是你申請AppId時應用的包名),在wxapi目錄下新建WXEntryActivity類,該類繼承自Activity,並在manifest文件里面配置WXEntryActivity時,加上exported屬性,設置為true
b.實現IWXAPIEventHandler接口,微信發送的請求將回調到onReq方法,發送到微信請求的響應結果將回調到onResp方法
c.在WXEntryActivity中將接收到的intent及實現了IWXAPIEventHandler接口的對象傳遞給IWXAPI接口的handleIntent方法,示例如下圖
該代碼寫在onCreate方法里,請把AppId替換成你自己的AppId
當微信發送請求到你的應用,將通過IWXAPIEventHandler接口的onReq方法進行回調,類似的,應用請求微信的響應結果將通過onResp回調。
WXEntryActivity無需設置界面,通過onResp(BaseResp resp)拿到返回的resp,resq的類型是com.tencent.mm.sdk.modelmsg.SendAuth$Resp,強轉成SendAuth.Resp,就能通過resq.code拿到code,把code發送給后台服務器,后台通過code就能拿到access_token和oppenid,通過access_token和oppenid就能拿到用戶信息進行注冊登錄了,然后把信息再返回給前端應用,整個授權登錄就OK了。
第一步:請求CODE移動應用微信授權登錄
SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = "wechat_sdk_demo_test";
api.sendReq(req);
注:請求CODE這段代碼寫在點擊微信登錄的Activity(或Fragment或View)里邊。不能寫在WXEntryActivity,否則無法響應WXEntryActivity的回調方法。
第二步和第三步由后台服務器來做,實現用戶注冊登錄再返回給前端應用。這樣就實現了微信授權登錄。
F.A.Q
1. 什么是授權臨時票據(code)?
答:第三方通過code進行獲取access_token的時候需要用到,code的超時時間為10分鍾,一個code只能成功換取一次access_token即失效。code的臨時性和一次保障了微信授權登錄的安全性。第三方可通過使用https和state參數,進一步加強自身授權登錄的安全性。
WXEntryActivity類代碼如下(ConstantApi.APP_ID_WX為APP_ID )
public class WXEntryActivity extends Activity implements IWXAPIEventHandler { private static final String TAG = "WXEntryActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); IWXAPI api = WXAPIFactory.createWXAPI(this, ConstantApi.APP_ID_WX, true); api.handleIntent(getIntent(), this); } @Override public void onReq(BaseReq req) { Log.e(TAG, "onReq..."); } @Override public void onResp(BaseResp resp) { Log.e(TAG, "onResp..."); String code = null; switch (resp.errCode) { case BaseResp.ErrCode.ERR_OK://用戶同意,只有這種情況的時候code是有效的 code = ((SendAuth.Resp) resp).code; break; case BaseResp.ErrCode.ERR_AUTH_DENIED://用戶拒絕授權 break; case BaseResp.ErrCode.ERR_USER_CANCEL://用戶取消 break; default://發送返回 break; } finish(); }