I create a conversation with my phone number to opt out of the texting service to test.
Once opted out, I will delete the conversation so my application doesnt try to add the message onto the current Conversation->sid
.
But when I create a conversation it does not throw a Twilio error. Even though it should give me a forbidden error since the recipient number is blacklisted.
Here is my sample code:
//store registered user in DB
public function createConversations(Request $request)
{
//check if forms are inputted properly
$this->validate($request, [
'Friendly_Title' => 'required|unique:conversations|max:100',
'Recipient_Number' => 'required|size:11',
'text_body' => 'required'
]);
//twilio credentials
$sid = config('services.twilio.example_sid');
$token = config('services.twilio.example_token');
$twilio = new Client($sid, $token);
//first check if guest number exists in the db('conversations')
$convo_guest_number = DB::table('example')->where('Recipient_Number', '=', $request->Recipient_Number)->count();
if ($convo_guest_number > 0) {
try {
//get requested channel_id from new conversation
$CH_ID = DB::table('example')->where('Recipient_Number', '=', $request->Recipient_Number)->get('Channel_Id')->first();
//update the updated_at column
DB::table('example')->where('Recipient_Number', '=', $request->Recipient_Number)->update(['updated_at' => now()]);
//create body message
$message = $twilio->conversations->v1->conversations($CH_ID->Channel_Id)
->messages
->create([
"author" => "EXAMPLE AUTHOR", //$participant->sid
"body" => $request->text_body
]
);
//return back with warning message
return back()->with('warning', 'Conversation already exists, added message to existing conversation');
}catch (TwilioException $e) {
return back()->with("warning", "Error: {$e->getMessage()}");
}
} //if new conversatoin
else {
try {
//create new conversation
$conversation = $twilio->conversations->v1->conversations
->create([
"friendlyName" => $request->Friendly_Title
]
);
//store the conversation channel id
$Conversation_SID = $conversation->sid;
//fetch the newly created conversation
$conversation = $twilio->conversations->v1->conversations($Conversation_SID)
->fetch();
//set recipient number and twilio number
//add participant
$user_number = "+". config('services.example.example_phone_number');
$participant_number = "+" . $request->Recipient_Number;
$participant = $twilio->conversations->v1->conversations($conversation->sid)
->participants
->create([
"messagingBindingAddress" => $participant_number,
"messagingBindingProxyAddress" => $user_number
]
);
$participant = $twilio->conversations->v1->conversations($conversation->sid)
->participants
->create([
"identity" => "EXAMPLE AUTHOR"
]
);
// set you as the author of the meessage
$message = $twilio->conversations->v1->conversations($conversation->sid)
->messages
->create([
"author" => "DEMO AUTHOR", //$participant->sid
"body" => $request->text_body . "\r\nReply 'STOP' to unsubscribe."
]
);
//insert into conversations table
DB::table('example')
->insert([
'user_id' => auth()->user()->id,
'Friendly_Title' => $request->Friendly_Title,
'Channel_Id' => $conversation->sid,
'Recipient_Number' => $request->Recipient_Number,
'text_body' => $request->text_body,
'twilio_number' => config('services.twilio.example_phone_number'),
'twilio_author' => 'EXAMPLE AUTHOR',
'NeedsAttention' => false,
'checkedConversation' => false,
'optedOut' => false,
'last_outbound_date' => now(),
'created_at' => now(),
'updated_at' => now()
]);
return back()->with("success", "{$request->Friendly_Title} - was created ");
}catch (TwilioException $e) {
return back()->with("warning", "Error: {$e->getMessage()}");
}
}
}
Do I need to add a try/catch block for each small Twilio task? ALL CREDENTIALS ARE PLACHOLDERS
Twilio developer evangelist here.
Since the Conversations API deals with participants using different methods of sending messages, such as SMS or chat, creating a participant in a conversation doesn't check for opt-out status. It's also possible for a user to opt-out after being added to a conversation.
Similarly, when you send a message to the conversation that message is fanned out to each participant. So the response cannot tell you whether a single message failed to send for whatever reason. The API request will succeed because the message resource on the conversation was created successfully, even if sending individual messages later in the process fails.
The best way to deal with this is to register for delivery webhooks. The onDeliveryUpdated
webhook will fire when the status changes for a message and you will be able to record in your application whether that message was sent or failed for some reason. This will allow you to handle opt-outs and other failures for each participant.