使用Delphi的Twilio或Plivo SMS

时间:2016-01-10 13:46:30

标签: delphi sms twilio indy plivo

我正在试图弄清楚如何使用Delphi 10 Seattle和Indy向Plivo或Twilio发送POST请求以发送SMS消息。当我将此代码用于Twilio工作时,我收到了一条未经授权的消息(请注意我已经编辑了我的用户名和Auth代码):

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代码。两家公司都没有任何Delphi支持。谁能告诉我上面我缺少的东西?非常感谢。

MIC

5 个答案:

答案 0 :(得分:3)

Twilio传道者在这里。

除了以上@mjn提出的Basic Auth建议外,您的样本中还有另外两个问题,我认为会导致您出现问题:

首先,在上面的代码示例中,您的URL将是错误的,因为accountsid变量将您的sid和auth令牌连接在一起。

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

执行想要执行此操作以使用基本身份验证时,希望将身份验证令牌作为URL的一部分。当您创建url属性时,您只想将SID作为参数放入URL:

/Accounts/ACXXXXXXX/

其次,我还建议不要使用/SMS资源作为其弃用。而是使用更新且具有更多功能的/Messages

/Accounts/ACXXXXXXX/Messages

答案 1 :(得分:1)

https://www.twilio.com/docs/api/rest上的REST API文档说使用了基本身份验证:

  

对REST API的HTTP请求受HTTP Basic保护   认证

TIdHTTP内置支持基本身份验证。只需将TIdHTTP.Request.BasicAuthentication属性设置为true,然后根据需要设置IdHTTP.Request.UsernameTIdHTTP.Request.Password属性。

其他提示:

  • TIdHTTP.Create(nil)可缩短为TIdHTTP.Create
  • Response的 var 修饰符可以更改为 const

您的代码也会泄漏内存,因为Indy组件未被释放。

答案 2 :(得分:0)

在Delphi 10 Seattle中,有一些使用TRestClient的REST组件

TMS在他们的TMS Cloud Pack http://www.tmssoftware.com/site/cloudpack.asp

中为Twillio制作了组件

答案 3 :(得分: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功能的新手,所以我不确定还有什么可以尝试的。我已经尝试将“application / json”分配给几乎所有接受它的东西,但仍然会得到同样的错误。希望其他人能够了解Plivo的工作原理。

答案 4 :(得分:0)

最后,我能够让Twilio和Plivo发送短信。在Delphi REST Debugger的帮助下以及在这个帖子中发表的评论中,我终于能够弄明白了。谢谢!在SendSMS函数(对于Plivo)中,我不得不添加一个" Content-Type"而不是添加每个参数。 " application / json"的标题并使用RESTRequest.AddBody()将参数作为RAW添加到正文中。还有一点需要注意,我最初是在Delphi XE5中对此进行测试,它会继续给我一个早先帖子中提到的相同错误。当我在Delphi XE7中尝试它时,它终于奏效了!这应该也适用于Delphi 10 Seattle,但还没有测试过它!

这是工作演示。在表单上,​​您需要具有以下组件:

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

在OnCreate中,从" T"更改TypeCo;或" P"取决于您要测试的公司。然后运行它!

这是代码。请注意,我屏蔽了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;