1

I'm working on a project that uses Twilio Notify for mass text notifications. I would like to track the status of individual messages, so I added a deliveryCallbackUrl to the notification resource.

$notification = $service->notifications->create([
 "toBinding" => $binding,
 "body" => $message_text,
 "deliveryCallbackUrl" => "https://username:password@mysite/notification_delivery_callback.php"
]);

I can successfully receive the callback payload, but when I attempt to validate the request, it fails.

use Twilio\Rest\Client;
use Twilio\Security\RequestValidator;

$configs = get_configs();

$signature = $_SERVER["HTTP_X_TWILIO_SIGNATURE"];
$request_url = $_SERVER['SCRIPT_URI'];

$validator = new RequestValidator($configs['twilio_auth_token']);
$request = $_REQUEST;

// $is_valid always returns false
$is_valid = $validator->validate($signature, $request_url, $request);

The payload is nested and includes json.

Array(    
  [NotificationSid] => NTxxxxxxxxx   
  [ServiceSid] => ISxxxxxxxxx   
  [Count] => 4    
  [IsFinal] => true   
  [DeliveryState] => Array(         
    [3] => {"status":"SENT","type":"sms","identity":"xxxxxxxxx","sid":"SMxxxxxxxxx"}            
    [2] => {"status":"SENT","type":"sms","identity":"xxxxxxxxx","sid":"SMxxxxxxxxx"}            
    [1] => {"status":"SENT","type":"sms","identity":"xxxxxxxxx","sid":"SMxxxxxxxxx"}           
    [0] => {"status":"SENT","type":"sms","identity":"xxxxxxxxx","sid":"SMxxxxxxxxx"}       
  )    
  [AccountSid] => ACxxxxxxxxx    
  [SequenceId] => 0
)

It seems the DeliveryState array is the issue, as I am able to successfully validate non-nested requests for other webhooks. I've crawled through Twilio help docs, but so far, haven't found anything about how to validate nested requests. I've attempted to flatten the array and escape the json (one or the other, both at the same time), but no luck.

Array(
  ...
  [DeliveryState] => Array(
    [0] => "{\"status\":\"SENT\",\"type\":\"sms\",\"identity\":\"xxxxxxxxx\",\"sid\":\"SMxxxxxxxxx\"}"   
    [1] => "{\"status\":\"SENT\",\"type\":\"sms\",\"identity\":\"xxxxxxxxx\",\"sid\":\"SMxxxxxxxxx\"}"
    [2] => "{\"status\":\"SENT\",\"type\":\"sms\",\"identity\":\"xxxxxxxxx\",\"sid\":\"SMxxxxxxxxx\"}"
    [3] => "{\"status\":\"SENT\",\"type\":\"sms\",\"identity\":\"xxxxxxxxx\",\"sid\":\"SMxxxxxxxxx\"}"
  )
  ...
)
Array(
  ...
  [0] => "{\"status\":\"SENT\",\"type\":\"sms\",\"identity\":\"xxxxxxxxx\",\"sid\":\"SMxxxxxxxxx\"}"   
  [1] => "{\"status\":\"SENT\",\"type\":\"sms\",\"identity\":\"xxxxxxxxx\",\"sid\":\"SMxxxxxxxxx\"}"
  [2] => "{\"status\":\"SENT\",\"type\":\"sms\",\"identity\":\"xxxxxxxxx\",\"sid\":\"SMxxxxxxxxx\"}"
  [3] => "{\"status\":\"SENT\",\"type\":\"sms\",\"identity\":\"xxxxxxxxx\",\"sid\":\"SMxxxxxxxxx\"}"
  ...
)

Does anyone know what the desired format is to validate this properly?

1 Answers1

0

Worked with Twilio Support to solve the issue.

  • There was a bug in the sdk: The PHP library didn't support multi-dimensional arrays in the RequestValidator (twilio/sdk has been fixed and updated to 6.42.1)
  • Format: The validator is looking for a specific format -- need to unnest the DeliveryState array and reformat the keys (order is also important)

Example format that passes validation

(
    [NotificationSid] => NTxxx
    [ServiceSid] => ISxxx
    [Count] => 5
    [IsFinal] => true
    [DeliveryState[0]] => {"status":"SENT","type":"sms","identity":"xxxxxxxxxx","sid":"SMxxx"}
    [DeliveryState[1]] => {"status":"SENT","type":"sms","identity":"xxxxxxxxxx","sid":"SMxxx"}
    [DeliveryState[2]] => {"status":"SENT","type":"sms","identity":"xxxxxxxxxx","sid":"SMxxx"}
    [DeliveryState[3]] => {"status":"SENT","type":"sms","identity":"xxxxxxxxxx","sid":"SMxxx"}
    [DeliveryState[4]] => {"status":"SENT","type":"sms","identity":"xxxxxxxxxx","sid":"SMxxx"}
    [AccountSid] => ACxxx
    [SequenceId] => 0
)