Bulk delivery confirmation of incoming messages
Delivery confirmation of incoming SMS (replies)
If you want to receive DLR entries to your application, just set up url address on BulkGate Portal (see picture below). Delivery confirmations are sent to the url address via HTTP POST method. Format (Content-Type) of the sent data is application/json. See the table of parameters.

Delivery confirmation: Parameters
| PARAMETER NAME | VALUE | MANDATORY |
|---|---|---|
| status | See the table with delivery confirmation status | Yes |
| smsID | Unique smsID of a message | No |
| to | Phone number of the recipient in international format without the "+" (e.g. 420777777777) | No |
| price | Price of SMS in credits | No |
| channel | Channel used to deliver message | No |
| date | Sending and receiving time (CET timezone), e.g.: 1812141317;1812141318 (14th December 2018, 13:17 and 14th December 2018, 13:18) | No |
| from | Only if status=10, SenderID of incoming SMS in international format | No |
| message | Only if status=10, Text of incoming SMS in UTF-8 encoding | No |
Example of the request
POST example.php HTTP/1.1
Host: portal.bulkgate.com
Content-Type: application/json
Cache-Control: no-cache
[
{
"status":"1",
"smsID":"3t2563af3ff285",
"price":"0.71",
"date":"1904111007;1904111011"
},
{
"status":"2",
"smsID":"2t2563af3ff285",
"price":"0.71",
"date":"1904111007;1904111011"
},
{
"status":"10",
"from":"420777777777",
"text":"answer text",
}
]
Delivery confirmation: Status
| STATUS | DESCRIPTION |
|---|---|
| 1 | SMS successfully delivered |
| 2 | SMS buffered on SMSC. SMS will be delivered later. Recipient is unavailable. |
| 3 | SMS not delivered. Unknown/unavailable recipient. |
| 10 | Incoming SMS or SMS answer (contact us for more information) |
| 13 | Message seen (Viber only) |
Script implementation example
<?php declare(strict_types=1);
class Delivery
{
const STATUS_LIST = [
0 => 'unknown',
1 => 'delivered',
2 => 'unavailable',
3 => 'not_delivered'
];
public function __construct()
{
try
{
foreach ($this->loadInput() as $key => $row)
{
if($row['type'] === 'answer')
{
$this->inbox($row['from'], $row['message']);
}
else
{
$this->delivery($row['smsID'], $row['status'], $row['price'], $row['send_time'], $row['delivery_time']);
}
}
}
catch (\Exception $e)
{
$this->log($e->getMessage(), 'error');
exit(1);
}
exit(0);
}
public function inbox(string $from, string $message): void
{
$this->log(sprintf('From: [%s] Message: [%s]', $from, $message), 'inbox');
}
public function delivery(string $sms_id, string $status, float $price, \DateTime $send_time, \DateTime $delivery_time): void
{
$this->log(sprintf('Message ID [%s] is in the status [%s], Price: [%f], Time of sending: [%s], Delivery time: [%s]', $sms_id, $status, $price, $send_time->format('c'), $delivery_time->format('c')), 'delivery');
}
private function log(string $message, string $type): void
{
$message = '['.date('Y-m-d H-i-s').'] ' . $message . PHP_EOL;
echo $message;
file_put_contents(__DIR__."/$type.log", $message,FILE_APPEND);
}
private function loadInput(): iterable
{
$json = file_get_contents("php://input");
if($json && is_string($json))
{
$data = json_decode($json, true, 512, JSON_BIGINT_AS_STRING);
if ($error = json_last_error())
{
throw new \Exception(json_last_error_msg());
}
if(is_array($data))
{
foreach($data as $key => $row)
{
if((int) ($row['status'] ?? 0) === 10)
{
yield $key => [
'type' => 'answer',
'from' => $row['from'] ?? '',
'message' => $row['message'] ?? ''
];
}
else
{
[$send_time, $delivery_time] = array_pad(explode(';', $row['date'] ?? '0;0'), 2, 0);
yield $key => [
'type' => 'dlr',
'smsID' => $row['smsID'] ?? '',
'status' => self::STATUS_LIST[(int) ($row['status'] ?? 0)] ?? 'unknown',
'price' => (float) $row['price'] ?? 0.0,
'send_time' => new \DateTime('@'.(string) (int) $send_time),
'delivery_time' => new \DateTime('@'.(string) (int) $delivery_time),
];
}
}
}
else
{
throw new \Exception('Invalid input');
}
}
else
{
throw new \Exception('Invalid input');
}
}
};
new \Delivery();