我正在开发VCL应用程序,并且必须使用其REST API集成Twilio:
https://www.twilio.com/docs/usage/your-request-to-twilio
这是我的代码:
pair<bool, String> SMSTwilio::SendMessage(TComponent* Owner,
String ToNumber, String FromNumber, String Message)
{
if(Message.Length() > MESSAGE_LIMIT) {
ShowMessage("Message must have " + IntToStr(MESSAGE_LIMIT) +
" or fewer characters. Cannot send message with " +
IntToStr(Message.Length()) + "characters.");
}
AccountSID = "AC2d48*****************0deb52";
AuthToken = "9e28ec***************c0126e";
Message = "Hi";
FromNumber = "+1740****95";
ToNumber = "+9*****791";
String URI = "https://api.twilio.com/2010-04-01/Accounts/"
+ AccountSID +
"/Messages";
TStringList* params = new TStringList();
params->Add("From=" + FromNumber);
params->Add("To=" + ToNumber);
params->Add("Body=" + Message);
TIdHTTP* HTTP = new TIdHTTP(Owner);
HTTP->Request->Connection = "Keep-Alive";
HTTP->Request->ContentType = "application/x-www-form-urlencoded";
HTTP->Request->BasicAuthentication = true;
HTTP->Request->Username = AccountSID;
HTTP->Request->Password = AuthToken;
TIdSSLIOHandlerSocketOpenSSL* Handler = new TIdSSLIOHandlerSocketOpenSSL(Owner);
Handler->SSLOptions->Method = sslvTLSv1;
HTTP->IOHandler = Handler;
bool isSuccess = false;
String Result = "";
__try {
try {
HTTP->ReadTimeout = 5000;
HTTP->ConnectTimeout = 5000;
Result = HTTP->Post(URI, params);
isSuccess = true;
} catch(Exception &e) {
isSuccess = false;
Result = e.Message;
}
}
__finally {
delete HTTP;
delete params;
}
return make_pair(isSuccess, Result);
}
我收到EIdHTTPProtocolException
引发的"HTTP/1.1 400 BAD REQUEST"
和消息Result = HTTP->Post(URI, params);
。
答案 0 :(得分:0)
根据Twilio的Message Resource文档,您正在发布到.../Messages
,但需要发布到.../Messages.json
(请注意末尾的.json
)
创建消息资源
POST
https://api.twilio.com/2010-04-01/Accounts/{AccountSid}/Messages.json
要发送新的外发消息,请对此消息列表资源URI 进行HTTP POST。
尽管说的不是错误,但您的代码还有其他一些问题:
您的Owner
参数是不必要的。由于您是在同一函数中创建和销毁TIdHTTP
对象,因此根本不需要为其分配Owner
。并且,将那个TIdHTTP
对象分配为TIdSSLIOHandlerSocketOpenSSL
对象的所有者,而不是某些未知的外部所有者,会更有用。
如果Message
太长而无法发送,则不会向呼叫者返回错误。
如果发生某些不良情况(为什么不使用C ++智能指针而不是try..finally
呢?),您不能充分保护对象免于泄漏。
您的catch()
应该通过 const 引用捕获Exception
对象。
您不需要Request->Connection = "Keep-Alive"
,因为Post()
完成后您将关闭连接,实际上您并不是在使用保持活动状态。
您应该使用SSLOptions->SSLVersions
属性而不是SSLOptions->Method
属性。这样一来,您就可以启用sslvTLSv1_1
和sslvTLSv1_2
,因为当今许多服务器都在逐步淘汰TLS 1.0,因此您应该为此而做准备。
话虽如此,请尝试以下类似操作:
#include <utility>
#include <memory>
std::pair<bool, String> SMSTwilio::SendMessage(
String ToNumber, String FromNumber, String Message)
{
if (Message.Length() > MESSAGE_LIMIT) {
String msg = Format(_D("Message must have %d or fewer characters. Cannot send message with %d characters."), ARRAYOFCONST(( MESSAGE_LIMIT, Message.Length() )) );
//ShowMessage(msg);
return std::make_pair(false, msg);
}
String AccountSID = _D("AC2d48*****************0deb52");
String AuthToken = _D("9e28ec***************c0126e");
//Message = _D("Hi");
//FromNumber = _D("+1740****95");
//ToNumber = _D("+9*****791");
String URI = Format(_D("https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json"), ARRAYOFCONST(( AccountSID )) );
std::unique_ptr<TStringList> params(new TStringList); // or std::auto_ptr prior to C++11
params->Add(_D("From=") + FromNumber);
params->Add(_D("To=") + ToNumber);
params->Add(_D("Body=") + Message);
std::unique_ptr<TIdHTTP> HTTP(new TIdHTTP(nullptr)); // or std::auto_ptr prior to C++11
HTTP->ReadTimeout = 5000;
HTTP->ConnectTimeout = 5000;
//HTTP->Request->Connection = _D("Keep-Alive");
HTTP->Request->ContentType = _D("application/x-www-form-urlencoded");
HTTP->Request->BasicAuthentication = true;
HTTP->Request->Username = AccountSID;
HTTP->Request->Password = AuthToken;
TIdSSLIOHandlerSocketOpenSSL* Handler = new TIdSSLIOHandlerSocketOpenSSL(HTTP.get());
Handler->SSLOptions->SSLVersions = TIdSSLVersions() << sslvTLSv1 << sslvTLSv1_1 << sslvTLSv1_2;
HTTP->IOHandler = Handler;
bool isSuccess = false;
String Result;
try {
Result = HTTP->Post(URI, params);
isSuccess = true;
}
catch (const Exception &e) {
isSuccess = false;
Result = e.Message;
}
return std::make_pair(isSuccess, Result);
}