1

我试图弄清楚如何使用 Delphi 10 Seattle 和 Indy 向 Plivo 或 Twilio 发送 POST 请求以发送 SMS 消息。当我将此代码用于 Twilio 工作时,我收到一条 Unauthorized 消息作为回报(请注意,我已经编辑了我的用户名和 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 支持。谁能告诉我我在这里缺少什么?非常感谢。

麦克风

4

5 回答 5

3

Twilio 布道者在这里。

除了上面@mjn 提出的基本身份验证建议外,您的示例中还有另外两个问题我相信会导致您出现问题:

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

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

虽然您确实希望这样做以使用基本身份验证,但您希望身份验证令牌作为 URL 的一部分。创建url属性时,您只想将 SID 作为参数放入 URL,如下所示:

/Accounts/ACXXXXXXX/

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

/Accounts/ACXXXXXXX/Messages

于 2016-01-11T00:29:23.787 回答
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 组件未释放。

于 2016-01-10T16:30:16.077 回答
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 的工作原理有所了解。

于 2016-01-11T23:08:33.430 回答
0

最后,我能够让 Twilio 和 Plivo 都发送 SMS 消息。借助 Delphi REST Debugger 和此线程中的注释,我终于能够弄明白。谢谢!在 SendSMS 函数(用于 Plivo)中,我不得不添加“application/json”的“Content-Type”标头,并使用 RESTRequest.AddBody() 在正文中添加参数作为 RAW,而不是添加每个参数。还有一点需要注意,我最初是在 Delphi XE5 中测试它,它会继续给我在之前的帖子中提到的相同错误。当我在Delphi XE7中尝试时,它终于成功了!!!这也应该在 Delphi 10 Seattle 中工作,但还没有测试过!

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

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

在 OnCreate 中,根据您要测试的公司将 TypeCo 从“T”或“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;
于 2016-01-13T23:07:39.603 回答
0

在 Delphi 10 Seattle 中,有一些带有 TRESTClient 的 REST 组件

TMS 在他们的 TMS Cloud Pack 中为 Twillio 制作了组件http://www.tmssoftware.com/site/cloudpack.asp

于 2016-01-10T17:28:30.740 回答