1

Delphi 10 Seattle と Indy を使用して POST リクエストを Plivo または Twilio に送信して SMS メッセージを送信する方法を見つけようとしています。このコードを Twilio の取り組みに使用すると、Unauthorized メッセージが返されます (ユーザー名と認証コードを編集したことに注意してください)。

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 による Basic Auth の提案に加えて、サンプルには他に 2 つの問題があり、問題を引き起こすと思われます。

accountsidまず、上記のコード例では、変数が sid と認証トークンの両方を連結して いるため、URL が間違っています。

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

基本認証を使用するためにこれを行う必要がありますが認証トークンを URL の一部として使用する必要はありません。プロパティを作成するときは、次urlのように SID をパラメータとして URL に挿入します。

/Accounts/ACXXXXXXX/

/SMS第二に、非推奨としてリソースを使用しないこともお勧めします。代わりに/Messages、より新しく、より多くの機能を備えたものを使用します。

/Accounts/ACXXXXXXX/Messages

于 2016-01-11T00:29:23.787 に答える
1

The REST API docs on https://www.twilio.com/docs/api/rest say that basic auth is used:

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

TIdHTTP has built-in support for Basic authentication. Simply set the TIdHTTP.Request.BasicAuthentication property to true, and set IdHTTP.Request.Username and TIdHTTP.Request.Password properties as needed.

Other hints:

  • TIdHTTP.Create(nil) can be shortened to TIdHTTP.Create
  • the var modifier for Response can be changed to const

Your code also leaks memory because the Indy component is not freed.

于 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

Delphi 10 シアトルには、TRestClient を使用する REST コンポーネントがいくつかあります。

TMS は、TMS Cloud Pack http://www.tmssoftware.com/site/cloudpack.aspで Twillio のコンポーネントを作成しました。

于 2016-01-10T17:28:30.740 に答える
0

最終的に、Twilio と Plivo の両方で SMS メッセージを送信できるようになりました。Delphi REST Debugger とこのスレッドに寄せられたコメントの助けを借りて、私はついにそれを理解することができました。ありがとうございました!SendSMS 関数 (Plivo 用) では、各パラメーターを追加する代わりに、「application/json」の「Content-Type」ヘッダーを追加し、RESTRequest.AddBody() を使用して本文にパラメーターを RAW として追加する必要がありました。もう 1 つ注意してください。私はもともと Delphi XE5 でこれをテストしていましたが、以前の投稿で述べたのと同じエラーが引き続き発生します。Delphi XE7 で試してみたところ、ついに動きました!!! これは Delphi 10 シアトルでも動作するはずですが、まだテストしていません!

これが動作デモです。フォームには、次のコンポーネントが必要です。

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 に答える