2016-01-10 52 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牧师,请务必检查这个答案。 –