2016-01-10 53 views
1

我想弄清楚如何使用Delphi 10 Seattle和Indy發送POST請求到Plivo或Twilio發送短信。當我使用Twilio的努力這個代碼,我得到的回報未授權的消息(請注意,我已經節錄我的用戶名和驗證碼):使用Delphi的Twilio或Plivo SMS

procedure TSendTextForm.TwilioSendSms(FromNumber, ToNumber, Sms: string; Var Response: TStrings); 

var 
    apiurl, apiversion, accountsid, authtoken, 
    url: string; 
    aParams, aResponse: TStringStream; 
    mHTTP : TidHttp; 

begin 

    mHTTP := TIdHTTP.Create(nil); 

    apiurl := 'api.twilio.com'; 
    apiversion := '2010-04-01'; 
    accountsid := 'AC2f7cda1e6a4e74376***************:2b521b60208af4c*****************'; 
    url := Format('https://%s/%s/Accounts/%s/SMS/Messages/', [apiurl, apiversion, accountsid]); 
    aParams := TStringStream.Create ; 
try 
    aParams.WriteString('&From=' + FromNumber); 
    aParams.WriteString('&To=' + ToNumber); 
    aParams.WriteString('&Body=' + Sms); 
    aResponse := TStringStream.Create; 
try 
    mHTTP.Post(url, aParams, aResponse); 
finally 
    Response.Text := aResponse.DataString; 
end; 
finally 
    aParams.Free; 
end; 
end; 

我有Plivo類似的代碼。這兩家公司都沒有任何德爾福支持。任何人都可以告訴我我在上面丟失的東西嗎?非常感謝。在https://www.twilio.com/docs/api/rest

麥克風

+0

我不會推薦使用Plivo。他們沒有妥善地爲我們提供大量的短信,所以我們多次聯繫他們的支持,等了幾個星期,沒有任何事情......他們只是把我們的錢拿走了沒有投遞的短信,並沒有採取任何措施來解決問題。 –

回答

1

的REST API文檔說基本身份驗證使用:

HTTP requests to the REST API are protected with HTTP Basic authentication.

TIdHTTP已經內置了對基本身份驗證的支持。只需將TIdHTTP.Request.BasicAuthentication屬性設置爲true,並根據需要設置IdHTTP.Request.UsernameTIdHTTP.Request.Password屬性。

其他提示:

  • TIdHTTP.Create(nil)可縮短至TIdHTTP.Create
  • VAR修改爲響應可以改變以常量

你的代碼也出現內存泄漏,因爲印組件未被釋放。

+1

'TIdHTTP.Post()'還內置了對'application/x-www-form-urlencoded'格式的名稱 - 值對的支持。你應該發佈'TStringList'而不是'TStringStream'。這不僅設置了'TIdHTTP.Request.ContentType'(你不這樣做),但是特別重要的是保留字符(如空白)得到正確編碼,特別是在'Sms'值中。 –

3

Twilio佈道者取得了Twillio部件在這裏。

除了通過上述@mjn提出的基本認證的建議,也有你的樣品中的其他兩個問題,我相信會引起你的問題:

首先,在上面的代碼示例,您的網址將是錯誤的,因爲accountsid變量將sid和auth令牌連接在一起。

accountsid := 'AC2f7cda1e6a4e74376***************:2b521b60208af4c*****************'; 

雖然你要做到這一點,才能使用基本身份驗證,您希望驗證令牌作爲URL的一部分。當您創建url屬性,你只想把SID到URL作爲這樣的參數:

/Accounts/ACXXXXXXX/

其次,我也建議不要使用/SMS資源作爲其棄用。而是使用/Messages這是新的且具有更多的功能:

/Accounts/ACXXXXXXX/Messages

0

這很有趣,但我只是要發佈約plivo同樣的問題。我一直在試圖讓twilio和plivo工作。我確實設法最終讓Twilio工作。另一方面,Plivo不會使用相同的代碼,即使它們實際上是相同的。

我在delphi中使用了REST函數。以下代碼用於twilio和plivo。

procedure TForm1.FormCreate(Sender: TObject); 
begin 
     // TypeCo 
     // = T = Twilio 
     // = P = Plivo 

     TypeCo := 'T'; 


     if TypeCo='T' then // Twillio 
     begin 
      AccountSid := 'ACd27xxxxxxxxxxxxxxxxxxxxxxb106e38'; // x's were replaced to hide ID 
      AuthToken := '24fxxxxxxxxxxxxxxxxxxxxxxxxf08ed'; // x's were replaced to hide Token 
      BaseURL := 'https://api.twilio.com'; 
      Resource := '/2010-04-01/Accounts/'+accountSid+'/Messages'; 
     end 
     else if TypeCO='P' then // Plivo 
     begin 
      AccountSid := 'MANTxxxxxxxxxxxxxXYM'; 
      AuthToken := 'ZDg0OxxxxxxxxxxxxxxxxxxxxxxxxxxxxjM5Njhh'; 
      BaseURL := 'https://api.plivo.com'; 
      Resource := '/v1/Account/'+accountSid+'/Message/'; 
     end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
     RESTClient := TRESTClient.Create(BaseURL); 
     try 
      RESTRequest := TRESTRequest.Create(RESTClient); 
      try 
       RESTResponse := TRESTResponse.Create(RESTClient); 
       try 
        HTTPBasicAuthenticator := THTTPBasicAuthenticator.Create('AC', 'c1234'); 

        try 
         RESTRequest.ResetToDefaults; 

         RESTClient.BaseURL := BaseURL; 
         RESTRequest.Resource := Resource; 
         HTTPBasicAuthenticator.UserName := AccountSid; 
         HTTPBasicAuthenticator.Password := AuthToken; 
         RESTClient.Authenticator := HTTPBasicAuthenticator; 
         RESTRequest.Client := RESTClient; 
         RESTRequest.Response := RESTResponse; 

         // Tried this to fix plivo error with no luck! 
         // RESTClient.Params.AddHeader('Content-Type', 'application/json'); 

         // "From" number is the send # setup in the twilio or plivo account. The "To" number is a verified number in your twilio or plivo account 

         if TypeCo='T' then // Twilio 
          SendSMS('+1602xxxxx55','+1602xxxxxx7', 'This is a test text from Twilio') // x's were replaced to hide telephone numbers 
         else if TypeCo='P' then // Plivo 
          SendSMS('1602xxxxx66','1602xxxxxx7', 'This is a test text from Plivo'); // x's were replaced to hide telephone numbers 

        finally 
         HTTPBasicAuthenticator.Free; 
        end; 
       finally 
        RESTResponse.Free; 
       end; 
      finally 
        RESTRequest.Free; 
      end; 
     finally 
       RESTClient.Free; 
     end; 

end; 


function TForm1.SendSMS(aFrom, aTo, aText: string): boolean; 
begin 
    result := True; 
    RESTRequest.ResetToDefaults; 

    RESTClient.BaseURL := BaseURL; 
    RESTRequest.Resource := Resource; 
    if TypeCo='T' then // Twilio 
    begin 
     RESTRequest.Params.AddUrlSegment('AccountSid', accountSid); 
     RESTRequest.Params.AddItem('From', aFrom); 
     RESTRequest.Params.AddItem('To', aTo); 
     RESTRequest.Params.AddItem('Body', aText); 
    end 
    else if TypeCo='P' then // Plivo 
    begin 
     RESTRequest.Params.AddUrlSegment('AccountSid', accountSid); 
     RESTRequest.Params.AddItem('src', aFrom); 
     RESTRequest.Params.AddItem('dst', aTo); 
     RESTRequest.Params.AddItem('text', aText); 
    end; 


    RESTRequest.Method := rmPOST; 
    RESTRequest.Execute; 

    // Show Success or Error Message 
    ErrorMsg.Clear; 
    ErrorMsg.Lines.Text := RESTResponse.Content; 

end; 

如上所述,上面的代碼適用於Twilio。但是,對於Plivo,我收到以下錯誤:

{ 
    "api_id": "b124d512-b8b6-11e5-9861-22000ac69cc8", 
    "error": "use 'application/json' Content-Type and raw POST with json data" 
} 

我一直在試圖確定如何解決此問題。我接觸Plivo支持和我收到以下響應:

The error "use 'application/json' Content-Type and raw POST with json data" is generated when the Header "Content-Type" is not set the value "application/json" 
Please add the Header Content-Type under Items in the Request Tab and set the Description as application/json. 

我試圖按鈕過程中添加的代碼:

RESTClient.Params.AddHeader('Content-Type', 'application/json'); 

但它仍然給出了同樣的錯誤。我認爲這個代碼非常接近爲Plivo工作。我是REST函數的新手,所以我不知道還有什麼可以嘗試的。我曾嘗試將「應用程序/ json」分配給幾乎所有可以接受它的東西,但仍然會得到相同的錯誤。希望別人能夠了解Plivo的工作原理。

+0

[this SO post](http://stackoverflow.com/a/25047430/4731823),你可以嘗試:var aParam:TRESTRequestParameter; 開始 RestReq.Method:= rmPOST; aParam:= RestReq.Params.AddItem(); aParam.Value:= TJSONObject.ParseJSONValue('{'src':aFrom,'dst':aTo,'text':aText}'); aParam.ContentType:= ctAPPLICATION_JSON; RestClient.Execute(); 結束;' – CharlieC

0

最後,我能夠讓Twilio和Plivo發送短信。藉助Delphi REST調試器和本主題中的註釋,我終於弄清楚了。謝謝!在SendSMS函數(對於Plivo)中,我不得不添加每個參數,而是使用RESTRequest.AddBody()添加「application/json」的「Content-Type」頭並在主體中添加參數爲RAW。還有一點需要注意的是,我最初是在Delphi XE5中測試它,它會繼續給我在之前的文章中提到的同樣的錯誤。當我在Delphi XE7中嘗試它時,它終於運行了!這應該在德爾福10西雅圖工作,但還沒有測試過!

這是工作演示。在表單上,​​你需要有以下組件:

Button1: TButton; 
RESTClient: TRESTClient; 
RESTRequest: TRESTRequest; 
RESTResponse: TRESTResponse; 
HTTPBasicAuthenticator: THTTPBasicAuthenticator; 
ResponseMsg: TMemo; 

在OnCreate,從「T」或「P」取決於你要測試的公司改變TypeCo。然後運行它!

這是代碼。請注意,我隱瞞了AccountSid,AuthToken和電話號碼字段的隱私。

procedure TForm1.FormCreate(Sender: TObject); 
begin 
     // TypeCo 
     // = T = Twilio 
     // = P = Plivo 

     TypeCo := 'P'; 

     if TypeCo='T' then // Twilio 
     begin 
      AccountSid := 'ACd2*************************06e38'; 
      AuthToken := '24f63************************8ed'; 
      BaseURL := 'https://api.twilio.com'; 
      Resource := '/2010-04-01/Accounts/'+accountSid+'/Messages'; 
     end 
     else if TypeCO='P' then // Plivo 
     begin 
      AccountSid := 'MAN*************IXYM'; 
      AuthToken := 'ZDg0*******************************5Njhh'; 
      BaseURL := 'https://api.plivo.com'; 
      Resource := '/v1/Account/'+accountSid+'/Message/'; 
     end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var i:integer; 
begin 
    RESTClient.ResetToDefaults; 
    RESTRequest.ResetToDefaults; 
    ResponseMsg.Clear; 

    RESTClient.BaseURL := BaseURL; 
    RESTRequest.Resource := Resource; 
    HTTPBasicAuthenticator.UserName := AccountSid; 
    HTTPBasicAuthenticator.Password := AuthToken; 
    RESTClient.Authenticator := HTTPBasicAuthenticator; 
    RESTRequest.Client := RESTClient; 
    RESTRequest.Response := RESTResponse; 

    // Here is where you can loop through your messages for different recipients. 
    // I use the same "To" phone number in this test 
    for i := 1 to 3 do 
    begin 
      if TypeCo='T' then // Twilio 
       SendSMS('+1602******0','+1602******7', Format('This is test #%s using Twilio. Sent at %s',[inttostr(i),TimeToStr(Time)])) 
      else if TypeCo='P' then // Plivo 
       SendSMS('1662******2','1602******7', Format('This is test #%s using Plivo. Sent at %s',[inttostr(i),TimeToStr(Time)])); 

      // Show Success or Error Message 
      ResponseMsg.Lines.Add(RESTResponse.Content); 
      ResponseMsg.Lines.Add(''); 
      ResponseMsg.Refresh; 

    end; 
end; 


function TForm1.SendSMS(aFrom, aTo, aText: string):Boolean; 
begin 
    result := False; 
    RESTRequest.Params.Clear; 
    RESTRequest.ClearBody; 


    RESTClient.BaseURL := BaseURL; 
    RESTRequest.Resource := Resource; 
    if TypeCo='T' then // Twilio 
    begin 
      RESTRequest.Params.AddUrlSegment('AccountSid', accountSid); 
      RESTRequest.Params.AddItem('From', aFrom); 
      RESTRequest.Params.AddItem('To', aTo); 
      RESTRequest.Params.AddItem('Body', aText); 
    end 
    else if TypeCo='P' then // Plivo 
    begin 
      // NOTE: The following Header line needs to be commented out for Delphi Seattle 10 Update 1 (or probably newer) to work. The first original Delphi 10 Seattle version would not work at all for Plivo. In this case the following error would occur: "REST request failed: Error adding header: (87) The parameter is incorrect". This was due to the HTTPBasicAuthenticator username and password character lengths adding up to greater than 56. 
      RESTRequest.Params.AddItem('Content-Type', 'application/json', pkHTTPHEADER, [], ctAPPLICATION_JSON); 
     // RESTRequest.Params.AddItem('body', '', pkRequestBody, [], ctAPPLICATION_JSON); // Thought maybe I needed this code, but works without it. 
      RESTRequest.AddBody(Format('{"src":"%s","dst":"%s","text":"%s"}',[aFrom,aTo,aText]),ctAPPLICATION_JSON); 
    end; 

    RESTRequest.Method := rmPOST; 
    RESTRequest.Execute; 
    result := True; 
end; 
+0

非常感謝,羅恩!這正是我需要的!我對REST沒有任何經驗,這對我來說是一個很好的學習經驗。你很樂意花時間。你的例子完美地工作。 –

+0

我決定在Delphi 10 Seattle(原始的第一個版本)中測試它,它會給出以下錯誤: –

+0

REST請求失敗:錯誤添加標頭:(87)參數不正確。這是由於HTTPBasicAuthenticator中用戶名和密碼的字符長度總和超過了56。 UHGG!然後,我刪除了SendSMS函數中的application/json標題行,並再次運行。不知道Delphi的不同版本會發生什麼,但希望它不會因版本的不同而不斷變化。我編輯了答案並在標題行中添加了評論。 Mic牧師,請務必檢查這個答案。 –