php

As an outcome of this guide, you will receive a Delivery Report of a sent SMS using Infobip SMS API and an online free webhook tool. Once configured, for every SMS sent, you will get a delivery notification sent real-time to an endpoint you have specified for that SMS.

This guide assumes that you already know how to send an SMS with Infobip API. For more details, see: How to send SMS with PHP and Infobip.


Prerequisites

Infobip account

• PHP, version 7.2 or greater

• a webhook that will listen to incoming events

Difficulty level

This guide assumes very basic knowledge of Python and basic familiarity with APIs. It is important, however, that you are familiar with the webhook technology and know how to use it for this project.

Summary of the steps

• Send an SMS with the URL to your webhook specified in the payload.
• Set up a webhook.
• Receive a Delivery Report in real time on to the previously provided URL.

Send SMS with a Notify URL

To receive reports about the progress of an SMS and its ultimate delivery status, Infobip will send a webhook with JSON payload to any URL you provide. This is called the notify URL, and it is passed on to the message sent. It can be the same for every message or be set dynamically for each message, depending on your needs.

Using the example of Sending an SMS Message, this is how you can add a Notify URL and receive status reports.

<?php

use InfobipAPISendSMSApi;
use InfobipModel{ SmsDestination, SmsTextualMessage, SmsAdvancedTextualRequest};

$sendSmsApi = new SendSMSApi($client, $configuration);
$destination = (new SmsDestination())->setTo('445555555555');

$message = (new SmsTextualMessage())
    ->setFrom('InfoSMS')
    ->setText('This is a dummy SMS message sent using infobip-api-php-client')
    ->setDestinations([$destination])
    # This is the important bit 👇
    ->setNotifyUrl('https://yourwebsite.com/whatever/you/like');

$request = (new SmsAdvancedTextualRequest())
    ->setMessages([$message]);

try {
    $smsResponse = $sendSmsApi->sendSmsMessage($request);
    var_dump($smsResponse);
} catch (Throwable $apiException) {
    var_dump($apiException);
}

Shortly after the PHP code runs, the URL https://yourwebsite.com/whatever/you/like should receive a webhook that contains JSON looking like this:

{
  "results": [
    {
      "price": {
        "pricePerMessage": 0.0,
        "currency": "EUR"
      },
      "status": {
        "id": 5,
        "groupId": 3,
        "groupName": "DELIVERED",
        "name": "DELIVERED_TO_HANDSET",
        "description": "Message delivered to handset"
      },
      "error": {
        "id": 0,
        "name": "NO_ERROR",
        "description": "No Error",
        "groupId": 0,
        "groupName": "OK",
        "permanent": false
      },
      "messageId": "35107540824763357907",
      "doneAt": "2022-04-27T16:03:33.291+0000",
      "smsCount": 1,
      "sentAt": "2022-04-27T16:03:28.372+0000",
      "to": "445555555555"
    }
  ]
}

Looks like the delivery worked nicely! No errors, and the status does not contain any suggested actions to fix a problem. To learn more about what other possible statuses and error codes you may catch on your webhook, check out Infobip documentation.

Read a webhook

Seeing as the webhook is an HTTP request with a JSON body, it can be read by the code at the notify URL with something like this:

$json = file_get_contents('php://input');
$data = json_decode($json, true);

foreach ($data['results'] as $result) {
  error_log("{$result['messageId']} was done at {$result['doneAt']} with status {$result['status']['groupName']}");
}

If you were to call this file notify-url.php and run php -S localhost:8088 a local server would be able to parse any incoming JSON and output messages to the server logs with error_log(). You would instead want to store the results in the database, or update some of your own records, etc., but that’s all missing a step.

How do we get Infobip to communicate with code running on localhost?

Intercept webhooks for development

If we set the URL to https://<your-server>/webhooks/infobip, then the code would need to be in production before it’s tested, which isn’t ideal. We need to find a way to get traffic coming from Infobip to something we can control.

There are two convenient ways to do that.

• Hook Relay – a freemium-hosted webhook inspection/relay service.
• ngrok – an open-source CLI solution that can proxy HTTP(S) traffic to your local machine.

Intercept webhooks with Hook Relay

  1. Sign up for a free Hook Relay account with GitHub or GitLab, and click “New Hook”.
  2. Name it something like “Infobip SMS Reports” and copy the URL they give you.
  3. Hook Relay will give a long unique URL that can be copied for use as a notify URL.

Once you have this URL, pass it to SmsTextualMessage with the setNotifyUrl(string) method.

$message = (new SmsTextualMessage())
    ->setFrom('InfoSMS')
    ->setText('This is a dummy SMS message sent using infobip-api-php-client')
    ->setDestinations([$destination])
    ->setNotifyUrl('https://api.hookrelay.dev/hooks/<your-unique-hook>');

A few moments after this has run, Hook Relay should let you know it has received a “delivery” for you. It’s subtle, it says “1 new delivery click to refresh” and click on the ID of the delivery, which will contain all the information about the message that was just sent.

{
  "results": [
    {
      "price": {
        "pricePerMessage": 0.0,
        "currency": "EUR"
      },
      "status": {
        "id": 5,
        "groupId": 3,
        "groupName": "DELIVERED",
        "name": "DELIVERED_TO_HANDSET",
        "description": "Message delivered to handset"
      },
      "error": {
        "id": 0,
        "name": "NO_ERROR",
        "description": "No Error",
        "groupId": 0,
        "groupName": "OK",
        "permanent": false
      },
      "messageId": "35770713228903571979",
      "doneAt": "2022-07-13T10:12:22.906+0000",
      "smsCount": 1,
      "sentAt": "2022-07-13T10:12:12.295+0000",
      "to": "447415774432"
    }
  ]
}

The “Copy as cURL” is also pretty useful, because you can use that to simulate the request that came from Infobip, meaning you can write code in your development environment, then use the cURL command to check your code is responding properly.

Intercept webhooks with ngrok

Install ngrok on your development machine, then run a PHP server from the directory where that notify-url.php code is sitting.

php -S localhost:8088

In another CLI session, start up ngrok and point it at that server:

ngrok http http://localhost:8088/

The output should look like this:

Session Status                online
Session Expires               1 hour, 59 minutes
Terms of Service              https://ngrok.com/tos
Version                       3.0.3
Region                        Europe (eu)
Latency                       calculating...
Web Interface                 http://127.0.0.1:4040
Forwarding                    https://972c-46-234-226-56.eu.ngrok.io -> http://localhost:8088/

Taking that forwarding URL, we can append the name of our PHP file:

$message = (new SmsTextualMessage())
    ->setFrom('InfoSMS')
    ->setText('This is a dummy SMS message sent using infobip-api-php-client')
    ->setDestinations([$destination])
    ->setNotifyUrl('https://972c-46-234-226-56.eu.ngrok.io/notify-url.php');

Now when you send a PHP command, you should see this in your php web server logs:

[Wed Apr 27 19:18:51 2022] 35107992905443344689 was done at 2022-04-27T17:18:51.896+0000 with status DELIVERED

This works just as well with Laravel, Slim, Symfony, etc, just put the code into a controller and use the route instead of the filename in the URL.

Protect against webhook spam

If you want to protect your endpoints from spam, you can use our IP addresses to whitelist the traffic from the Infobip platform. Check out the safelist of IP addresses.