2013-07-08 106 views
0

是否有一個針對Delphi的實現,它連接到twitter新的API 1.1,並在twitter上執行操作?twitter api 1.1和oauth delphi實現

他們也刪除了所有的xml支持,所以需要有json操作。

從Twitter網站的解釋:

首先,我們需要設置一個印的連接,如so

POST /oauth2/token HTTP/1.1 
Host: api.twitter.com 
User-Agent: My Twitter App v1.0.23 
Authorization: Basic eHZ6MWV2RlM0d0VFUFRHRUZQSEJvZzpMOHFxOVBaeVJn 
        NmllS0dFS2hab2xHQzB2SldMdzhpRUo4OERSZHlPZw== 
Content-Type: application/x-www-form-urlencoded;charset=UTF-8 
Content-Length: 29 
Accept-Encoding: gzip 

grant_type=client_credentials 

然後我們可以使用印地獲得Twitter的迴應:

HTTP/1.1 200 OK 
Status: 200 OK 
Content-Type: application/json; charset=utf-8 
... 
Content-Encoding: gzip 
Content-Length: 140 

{"token_type":"bearer","access_token":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAAAAAAAAAAAA%3DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"} 

這看起來很簡單,但是我們需要使用ssl,它不會強制使用wireshark進行調試。

代碼我使用:

Uses EncdDecd; 
Const 
    Consumer_Key = 'xvz1evFS4wEEPTGEFPHBog'; 
    Consumer_Secret = 'L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg'; 
    Host = 'api.twitter.com/'; 
    Request_token_URL = 'https://api.twitter.com/oauth/request_token'; 
    Twitter_Content_Type = 'application/x-www-form-urlencoded;charset=UTF-8'; 
var 
    Response:TStream; 
    twittersite:TIdHttp;// assume on Form 
    Trace:TMemo; //assume on Form 
    IdSSLIOHandlerSocketOpenSSL1:TIdSSLIOHandlerSocketOpenSSL;//assume on Form 
function EncodeBase64String(s: string): string; 
var 
sIn:TSTringSTream; 
begin 
    sIn := TStringStream.create(s); 
    result := String (EncodeBase64(Sin.Memory, sIn.Size)); 
    sin.Free; 
end; 
begin 
    Response:= TMemoryStream.Create; 
    try 
    //Headers 
    twittersite.Request.Host := Host; 
    twitterSite.Request.UserAgent := 'Fucy Town 1.0'; 
    twitterSite.Request.CustomHeaders.Add('Authorization=Basic '+EncodeBase64String(Consumer_Key+':'+Consumer_Secret)); 
    twitterSite.Request.ContentType := Twitter_Content_Type; 
    twitterSite.Request.CustomHeaders.Add('grant_type=client_credentials'); 
    //SSL 
    twitterSite.IOHandler := IdSSLIOHandlerSocketOpenSSL1; 
    TwitterSite.Post(Request_token_URL,response); 

    Trace.Lines.LoadFromStream(Response); 
    finally 
    FreeAndNil(Response); 
    end; 
end; 

這個結果在401未經授權的。

可以做些什麼來解決這個問題,並得到200好嗎?

回答

0

DUMP

unit twitter; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, IdIntercept, IdLogBase, IdLogDebug, IdIOHandler, IdIOHandlerSocket, 
    IdIOHandlerStack, IdSSL, IdSSLOpenSSL, IdBaseComponent, IdComponent, 
    IdTCPConnection, IdTCPClient, IdHTTP, StdCtrls, IdCoder, IdCoder3to4, 
    IdCoderMIME; 
const 
//https://dev.twitter.com/docs/auth/application-only-auth 
    URL = 'https://api.twitter.com/oauth2/token'; 
    key = 'xvz1evFS4wEEPTGEFPHBog'; //this is example, replace with yours. 
    secret = 'L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg';//this is example, replace with yours. 
type 
    TForm5 = class(TForm) 
    Button1: TButton; 
    Memo1: TMemo; 
    IdHTTP1: TIdHTTP; 
    IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL; 
    IdLogDebug1: TIdLogDebug; 
    IdEncoderMIME1: TIdEncoderMIME; 
    procedure IdLogDebug1Receive(ASender: TIdConnectionIntercept; 
     var ABuffer: TBytes); 
    procedure IdLogDebug1Send(ASender: TIdConnectionIntercept; 
     var ABuffer: TBytes); 
    procedure Button1Click(Sender: TObject); 
    private 
    parameters:TStringList; 
    ringBear:string; 
    keySecretBase64:string; 
    procedure initConnection; 
    function getRingBear(input:TStringstream):string; 
    function requestRingBear:TStringStream; //bearer token 
    procedure requestTwits; 
    function logoff:TStringStream; 
    public 
    { Public declarations } 
    end; 

var 
    Form5: TForm5; 

implementation 

{$R *.dfm} 

uses IdGlobal, superobject; 

procedure TForm5.initConnection; 
begin 
    with IdSSLIOHandlerSocketOpenSSL1 do begin 
     SSLOptions.Method := sslvSSLv3; 
     SSLOptions.Mode := sslmUnassigned; 
     SSLOptions.VerifyMode := []; 
     SSLOptions.VerifyDepth := 2; 
    end; 
    with IdHTTP1 do begin 
     IOHandler := IdSSLIOHandlerSocketOpenSSL1; 
     ReadTimeout := 0; 
     AllowCookies := True; 
     ProxyParams.BasicAuthentication := False; 
     ProxyParams.ProxyPort := 0; 
     Request.ContentLength := -1; 
     Request.ContentRangeEnd := 0; 
     Request.ContentRangeStart := 0; 
     Request.ContentType := 'application/x-www-form-urlencoded'; 
     Request.Accept := 'text/html, */*'; 

     Request.BasicAuthentication := False; 
     Request.UserAgent := 'Mozilla/3.0 (compatible; Indy Library)'; 
     HTTPOptions := [hoForceEncodeParams]; 
    end; 
    IdHTTP1.Intercept := IdLogDebug1; 
    parameters.Clear; 
    IdHTTP1.Request.CustomHeaders.Clear; 

end; 
function TForm5.logoff:TStringStream; 
begin 
    result := TStringStream.Create; 
    idhttp1.Request.CustomHeaders.AddValue('Authorization','Basic '+keySecretBase64); 
    parameters.Add('access_token='+ringBear); 
    IdHTTP1.Post('https://api.twitter.com/oauth2/invalidate_token',parameters,result); 
    keySecretBase64:=''; 
    ringBear := ''; 
end; //the caller needs to free the stream 

function TForm5.requestRingBear:TStringStream; 
begin 
    result := TStringStream.create; 
    keySecretBase64 := TIdEncoderMIME.EncodeString(key+ ':' + secret, IndyTextEncoding_UTF8); 
    parameters.Add('grant_type=client_credentials'); 
    Memo1.Lines.Add('secret and key ' + keySecretBase64); 
    IdHTTP1.Request.CustomHeaders.AddValue('Authorization','Basic '+keySecretBase64); 
    IdHTTP1.post(URL,parameters,result); 
end;//the caller needs to free the stream 

procedure TForm5.requestTwits; 
begin 
    IdHTTP1.Request.CustomHeaders.AddValue('Authorization','Bearer ' + ringBear); 
    memo1.lines.add('twits response : ' + 
    IdHTTP1.Get('https://api.twitter.com/1.1/statuses/user_timeline.json?count=100&screen_name=twitterapi')); 

end; 

procedure TForm5.Button1Click(Sender: TObject); 

var 
    json:ISuperObject; 
    stream:TStringStream; 

begin 
    stream:=TStringStream.Create; 
    parameters:=TStringList.Create; 
    try 
    cursor := crHourGlass; 
    initConnection; 
// return this: {"access_token":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAAAAAAAAAAAA%3DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","token_type":"bearer"} 
    ringBear := getRingBear(requestRingBear);//the caller needs to free the stream 
    initConnection; 
    requestTwits; 
    initConnection; 
    logoff;//the caller needs to free the stream 
    finally 
    cursor := crDefault; 
    memo1.Lines.Add('stream reposne' +stream.DataString); 
    stream.Free; 
    parameters.Free; 
    end; 
end; 

function TForm5.getRingBear(input: TStringstream): string; 
var 
    json : ISuperObject; 
begin 
    json := TSuperObject.ParseStream(input,true); 
    result := json.S['access_token']; 
    input.Free; 
end; 

procedure TForm5.IdLogDebug1Receive(ASender: TIdConnectionIntercept; 
    var ABuffer: TBytes); 
var 
    i: Integer; 
    s: String; 
begin 
    s := ''; 

    for i := Low(ABuffer) to High(ABuffer) do 
    s := s + chr(ABuffer[i]); 

    Memo1.Lines.Add('Recived: '+s); 
end; 
procedure TForm5.IdLogDebug1Send(ASender: TIdConnectionIntercept; 
    var ABuffer: TBytes); 
var 
    i: Integer; 
    s: String; 
begin 
    s := ''; 

    for i := Low(ABuffer) to High(ABuffer) do 
    s := s + chr(ABuffer[i]); 

    Memo1.Lines.Add('SEND: '+s); 
end; 

end. 

DFM需要包含:

object Form5: TForm5 
    Left = 0 
    Top = 0 
    Caption = 'Form5' 
    ClientHeight = 546 
    ClientWidth = 605 
    Color = clBtnFace 
    Font.Charset = DEFAULT_CHARSET 
    Font.Color = clWindowText 
    Font.Height = -11 
    Font.Name = 'Tahoma' 
    Font.Style = [] 
    OldCreateOrder = False 
    DesignSize = (
    605 
    546) 
    PixelsPerInch = 96 
    TextHeight = 13 
    object Button1: TButton 
    Left = 288 
    Top = 513 
    Width = 75 
    Height = 25 
    Caption = 'Button1' 
    TabOrder = 0 
    OnClick = Button1Click 
    end 
    object Memo1: TMemo 
    Left = 8 
    Top = 8 
    Width = 589 
    Height = 499 
    Anchors = [akLeft, akTop, akRight, akBottom] 
    Lines.Strings = (
     'Memo1') 
    ScrollBars = ssVertical 
    TabOrder = 1 
    end 
    object IdHTTP1: TIdHTTP 
    Intercept = IdLogDebug1 
    IOHandler = IdSSLIOHandlerSocketOpenSSL1 
    AllowCookies = True 
    ProxyParams.BasicAuthentication = False 
    ProxyParams.ProxyPort = 0 
    Request.ContentLength = -1 
    Request.Accept = 'text/html, */*' 
    Request.BasicAuthentication = False 
    Request.UserAgent = 'Mozilla/3.0 (compatible; Indy Library)' 
    HTTPOptions = [hoForceEncodeParams] 
    Left = 280 
    Top = 136 
    end 
    object IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL 
    Intercept = IdLogDebug1 
    MaxLineAction = maException 
    Port = 0 
    DefaultPort = 0 
    SSLOptions.Mode = sslmUnassigned 
    SSLOptions.VerifyMode = [] 
    SSLOptions.VerifyDepth = 0 
    Left = 296 
    Top = 48 
    end 
    object IdLogDebug1: TIdLogDebug 
    OnReceive = IdLogDebug1Receive 
    OnSend = IdLogDebug1Send 
    Left = 136 
    Top = 192 
    end 
    object IdEncoderMIME1: TIdEncoderMIME 
    FillChar = '=' 
    Left = 424 
    Top = 256 
    end 
end 

備註:

你必須在Twitter的註冊申請。

你需要twitter的密鑰和祕密。

這是應用程序API提到的here 用pin碼實現用戶oauth是複雜的另一個數量級,並且需要用戶活動來輸入pin碼。如果您需要更多關於here的信息,其中包含詳細解釋here以及非常好的圖表。代碼不完整,dfm丟失。 dropbox oauth上有一個完整的例子,但我目前無法找到它。

delphi xe5有一個oauth客戶端,隨delphi自帶,應該讓你的生活更輕鬆。

註銷不起作用。

和ringBear是參考barney stinson ring bear在他的婚禮,而不是拿戒指,因爲Twitter的把它叫做熊(我想從燈塔同意,沒有婚禮)

的想法很簡單。請求ringBear,然後請求twits然後註銷。

+0

爲什麼地球上你正在使用'TStringStream'作爲你的函數的結果。 – RepeatUntil

+0

在這個例子中,我沒有使用結果。但是,在調試時更容易調試字符串流,並且您可以看到結果,調試器無需寫入文件或showmessage。 – none

+0

我知道,完成它之後免費它呢? – RepeatUntil