问题
Anybody know how can integrate google+ in a flex mobile application. While i tried to authenticate with google+ getting an error like text="Error #2032: Stream Error. URL: https://accounts.google.com/o/oauth2/auth?response%5Ftype=code&redirect%5Furi=urn%3Aietf%3Awg%3Aoauth%3A2%2E0%3Aoob&client%5Fid ..." errorID=2032]. URL: https://accounts.google.com/o/oauth2/auth.
回答1:
It's your lucky day, because I know how to do it :-)
The doc is Using OAuth 2.0 for Installed Applications and you get the access token from the web page title.
Below is my View and a screenshot of my app and the Google+ API console:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
viewActivate="openSWV(event)"
viewDeactivate="closeSWV(event)"
title="Getting data...">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import flash.media.StageWebView;
private static const APP_ID:String = 'XXXXXXXXX.apps.googleusercontent.com';
private static const APP_SECRET:String = 'XXXXXXXXXXXXXXXXXXX';
private static const APP_URL:String = 'urn:ietf:wg:oauth:2.0:oob';
private static const AUTH_URL:String = 'https://accounts.google.com/o/oauth2/auth?';
private var _swv:StageWebView = new StageWebView();
private function openSWV(event:ViewNavigatorEvent):void {
_swv.addEventListener(Event.COMPLETE, extractAccessToken);
_swv.addEventListener(LocationChangeEvent.LOCATION_CHANGE, extractAccessToken);
_swv.addEventListener(IOErrorEvent.IO_ERROR, closeSWV);
_swv.addEventListener(ErrorEvent.ERROR, closeSWV);
stage.addEventListener(Event.RESIZE, resizeSWV);
_swv.stage = stage;
resizeSWV();
var reqVars:URLVariables = new URLVariables();
reqVars.client_id = APP_ID;
reqVars.response_type = 'code';
reqVars.redirect_uri = APP_URL;
reqVars.state = getTimer();
reqVars.scope = 'https://www.googleapis.com/auth/userinfo.profile';
_swv.loadURL(AUTH_URL + reqVars);
}
private function closeSWV(event:Event=null):void {
stage.removeEventListener(Event.RESIZE, resizeSWV);
if (! _swv)
return;
_swv.removeEventListener(Event.COMPLETE, extractAccessToken);
_swv.removeEventListener(LocationChangeEvent.LOCATION_CHANGE, extractAccessToken);
_swv.removeEventListener(IOErrorEvent.IO_ERROR, closeSWV);
_swv.removeEventListener(ErrorEvent.ERROR, closeSWV);
_swv.dispose();
_swv = null;
}
private function resizeSWV(event:Event=null):void {
if (! _swv)
return;
// align to the right-bottom corner
_swv.viewPort = new Rectangle(stage.stageWidth - width, stage.stageHeight - height, width, height);
}
private function extractAccessToken(event:Event):void {
trace('title: ' + _swv.title);
trace('location: ' + _swv.location);
var code:String = getValue('code=', _swv.title);
if (code) {
trace('code=' + code);
closeSWV();
var reqVars:URLVariables = new URLVariables();
reqVars.code = code;
reqVars.grant_type = 'authorization_code';
reqVars.client_id = APP_ID;
reqVars.client_secret = APP_SECRET;
reqVars.redirect_uri = APP_URL;
var req:URLRequest = new URLRequest('https://accounts.google.com/o/oauth2/token');
req.method = URLRequestMethod.POST;
req.data = reqVars;
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, handleComplete);
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleError);
loader.addEventListener(IOErrorEvent.IO_ERROR, handleError);
loader.load(req);
}
}
private function handleError(event:ErrorEvent):void {
var loader:URLLoader = URLLoader(event.target);
trace(event.text);
trace(loader.data);
}
private function handleComplete(event:Event):void {
var obj:Object;
var loader:URLLoader = URLLoader(event.target);
trace(loader.data);
try {
obj = JSON.decode(loader.data);
} catch(e:Error) {
trace('Invalid JSON: ' + loader.data);
return;
}
trace('access_token=' + obj.access_token);
var req:URLRequest = new URLRequest('https://www.googleapis.com/oauth2/v1/userinfo?access_token=' + obj.access_token);
var loader2:URLLoader = new URLLoader();
loader2.addEventListener(Event.COMPLETE, handleComplete2);
loader2.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleError);
loader2.addEventListener(IOErrorEvent.IO_ERROR, handleError);
loader2.load(req);
}
private function handleComplete2(event:Event):void {
var obj:Object;
var loader:URLLoader = URLLoader(event.target);
trace(loader.data);
try {
obj = JSON.decode(loader.data);
} catch(e:Error) {
trace('Invalid JSON: ' + loader.data);
return;
}
var info:Object = {
ID: obj.id,
FIRST: obj.given_name,
LAST: obj.family_name,
FEMALE: (obj.gender != 'male'),
AVATAR: obj.picture
};
_userid.text = 'id: ' + info['ID'];
_first.text = 'first: ' + info['FIRST'];
_last.text = 'last: ' + info['LAST'];
_female.text = 'female: ' + info['FEMALE'];
_avatar.text = 'avatar: ' + info['AVATAR'];
_img.source = info['AVATAR'];
title = 'Your data';
_busy.visible = false;
_busy.includeInLayout = false;
_group.visible = true;
}
private function getValue(key:String, str:String):String {
const pattern:RegExp = /[-_a-zA-Z0-9\/.]+/;
var index:int = str.indexOf(key);
if (index > -1) {
var matches:Array = str.substring(index + key.length).match(pattern);
if (matches.length > 0)
return matches[0];
}
return null;
}
]]>
</fx:Script>
<s:BusyIndicator id="_busy"/>
<s:VGroup id="_group" visible="false">
<s:Button id="_play" label="Start game"/>
<s:Label id="_token"/>
<s:Label id="_userid"/>
<s:Label id="_first"/>
<s:Label id="_last"/>
<s:Label id="_female"/>
<s:Label id="_avatar"/>
<s:Image id="_img"/>
</s:VGroup>
</s:View>
来源:https://stackoverflow.com/questions/10717919/how-to-integrate-google-in-a-flex-mobile-application