我正在试图弄清楚如何使用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
答案 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.Username
和TIdHTTP.Request.Password
属性。
其他提示:
TIdHTTP.Create(nil)
可缩短为TIdHTTP.Create
您的代码也会泄漏内存,因为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;