TwilioSMS.php 4.89 KB
Newer Older
Juliper committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
<?php namespace SimpleSoftwareIO\SMS\Drivers;

/**
 * Simple-SMS
 * Simple-SMS is a package made for Laravel to send/receive (polling/pushing) text messages.
 *
 * @link http://www.simplesoftware.io
 * @author SimpleSoftware support@simplesoftware.io
 *
 */

use SimpleSoftwareIO\SMS\OutgoingMessage;
use Services_Twilio;

class TwilioSMS extends AbstractSMS implements DriverInterface
{
    /**
     * The Twilio SDK
     *
     * @var Services_Twilio
     */
    protected $twilio;

    /**
     * Holds the Twilio auth token.
     *
     * @var string
     */
    protected $authToken;

    /**
     * Holds the request URL to verify a Twilio push.
     *
     * @var string
     */
    protected $url;

    /**
     * Determines if requests should be checked to be authentic.
     *
     * @var boolean
     */
    protected $verify;

    /**
     * Constructs the TwilioSMS object.
     *
     * @param Services_Twilio $twilio
     * @param $authToken
     * @param $url
     * @param bool $verify
     */
    public function __construct(Services_Twilio $twilio, $authToken, $url, $verify = false)
    {
        $this->twilio = $twilio;
        $this->authToken = $authToken;
        $this->url = $url;
        $this->verify = $verify;
    }

    /**
     * Sends a SMS message.
     *
     * @param \SimpleSoftwareIO\SMS\OutgoingMessage $message
     * @return void
     */
    public function send(OutgoingMessage $message)
    {
        $from = $message->getFrom();
        $composeMessage = $message->composeMessage();

        foreach ($message->getTo() as $to) {
            $this->twilio->account->messages->create([
                'To' => $to,
                'From' => $from,
                'Body' => $composeMessage,
                'MediaUrl' => $message->getAttachImages(),
            ]);
        }
    }

    /**
     * Processing the raw information from a request and inputs it into the IncomingMessage object.
     *
     * @param $raw
     * @return void
     */
    protected function processReceive($raw)
    {
        $incomingMessage = $this->createIncomingMessage();
        $incomingMessage->setRaw($raw);
        $incomingMessage->setMessage($raw->body);
        $incomingMessage->setFrom($raw->from);
        $incomingMessage->setId($raw->sid);
        $incomingMessage->setTo($raw->to);
    }

    /**
     * Checks the server for messages and returns their results.
     *
     * @param array $options
     * @return array
     */
    public function checkMessages(array $options = [])
    {
        $start = array_key_exists('start', $options) ? $options['start'] : 0;
        $end = array_key_exists('end', $options) ? $options['end'] : 25;

        $rawMessages = $this->twilio->account->messages->getIterator($start, $end, $options);
        $incomingMessages = [];

        foreach ($rawMessages as $rawMessage) {
            $incomingMessage = $this->createIncomingMessage();
            $this->processReceive($incomingMessage, $rawMessage);
            $incomingMessages[] = $incomingMessage;
        }

        return $incomingMessages;
    }

    /**
     * Gets a single message by it's ID.
     *
     * @param string|int $messageId
     * @return \SimpleSoftwareIO\SMS\IncomingMessage
     */
    public function getMessage($messageId)
    {
        $rawMessage = $this->twilio->account->messages->get($messageId);
        $incomingMessage = $this->createIncomingMessage();
        $this->processReceive($incomingMessage, $rawMessage);
        return $incomingMessage;
    }

    /**
     * Receives an incoming message via REST call.
     *
     * @param mixed $raw
     * @return \SimpleSoftwareIO\SMS\IncomingMessage
     */
    public function receive($raw)
    {
        if ($this->verify) {
            $this->validateRequest();
        }

        $incomingMessage = $this->createIncomingMessage();
        $incomingMessage->setRaw($raw->get());
        $incomingMessage->setMessage($raw->get('Body'));
        $incomingMessage->setFrom($raw->get('From'));
        $incomingMessage->setId($raw->get('MessageSid'));
        $incomingMessage->setTo($raw->get('To'));

        return $incomingMessage;
    }

    /**
     * Checks if a message is authentic from Twilio.
     *
     * @throws \InvalidArgumentException
     * @return void
     */
    protected function validateRequest()
    {
        //Twilio requires that all POST data be sorted alpha to validate.
        $data = $_POST;
        ksort($data);

        // append the data array to the url string, with no delimiters
        $url = $this->url;
        foreach ($data as $key => $value) {
            $url = $url . $key . $value;
        }

        //Encode the request string
        $hmac = hash_hmac("sha1", $url, $this->authToken, true);

        //Verify it against the given Twilio key
        if (base64_encode($hmac) != $_SERVER["HTTP_X_TWILIO_SIGNATURE"]) {
            throw new \InvalidArgumentException('This request was not able to verify it came from Twilio.');
        }
    }
}