Sinch::sendRequestToCheckStatusOfSMS()   A
last analyzed

Complexity

Conditions 5
Paths 3

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 9.2248
c 0
b 0
f 0
cc 5
nc 3
nop 1
1
<?php
2
/*
3
 * This file is part of the FreshSinchBundle
4
 *
5
 * (c) Artem Henvald <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
declare(strict_types=1);
12
13
namespace Fresh\SinchBundle\Service;
14
15
use Fresh\SinchBundle\Event\SinchEvents;
16
use Fresh\SinchBundle\Event\SmsEvent;
17
use Fresh\SinchBundle\Exception\SinchException;
18
use Fresh\SinchBundle\Helper\SinchSmsStatus;
19
use GuzzleHttp\Client;
20
use GuzzleHttp\Exception\ClientException;
21
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
22
use Symfony\Component\HttpFoundation\Response;
23
24
/**
25
 * Sinch Service.
26
 *
27
 * @author Artem Henvald <[email protected]>
28
 */
29
class Sinch
30
{
31
    public const URL_FOR_SENDING_SMS = '/v1/sms/';
32
33
    public const URL_FOR_CHECKING_SMS_STATUS = '/v1/message/status/';
34
35
    /** @var Client */
36
    private $guzzleHTTPClient;
37
38
    /** @var EventDispatcherInterface */
39
    private $dispatcher;
40
41
    /** @var string */
42
    private $host;
43
44
    /** @var string */
45
    private $key;
46
47
    /** @var string */
48
    private $secret;
49
50
    /** @var string */
51
    private $from;
52
53
    /**
54
     * @param EventDispatcherInterface $dispatcher
55
     * @param string                   $host
56
     * @param string                   $key
57
     * @param string                   $secret
58
     * @param string|null              $from
59
     */
60
    public function __construct(EventDispatcherInterface $dispatcher, $host, $key, $secret, $from = null)
61
    {
62
        $this->dispatcher = $dispatcher;
63
        $this->host = $host;
64
        $this->key = $key;
65
        $this->secret = $secret;
66
        $this->from = $from;
67
68
        $this->guzzleHTTPClient = new Client([
69
            'base_uri' => \rtrim($this->host, '/'),
70
        ]);
71
    }
72
73
    /**
74
     * @param string      $phoneNumber
75
     * @param string      $messageText
76
     * @param string|null $from
77
     *
78
     * @return int Message ID
79
     *
80
     * @throws SinchException
81
     */
82
    public function sendSMS(string $phoneNumber, string $messageText, ?string $from = null): ?int
83
    {
84
        // @todo validate phone number
85
86
        $body = [
87
            'auth' => [$this->key, $this->secret],
88
            'headers' => ['X-Timestamp' => (new \DateTime('now'))->format('c')], // ISO 8601 date format
89
            'json' => ['message' => $messageText],
90
        ];
91
92
        if (null !== $from) {
93
            $body['json']['from'] = $from;
94
        } elseif (null !== $this->from) {
95
            $from = $this->from;
96
            $body['json']['from'] = $from;
97
        }
98
99
        try {
100
            $smsEvent = new SmsEvent($phoneNumber, $messageText, $from);
101
102
            $this->dispatcher->dispatch(SinchEvents::PRE_SMS_SEND, $smsEvent);
103
            $response = $this->guzzleHTTPClient->post(self::URL_FOR_SENDING_SMS.$phoneNumber, $body);
104
            $this->dispatcher->dispatch(SinchEvents::POST_SMS_SEND, $smsEvent);
105
        } catch (ClientException $e) {
106
            throw SinchExceptionResolver::createAppropriateSinchException($e);
107
        }
108
109
        $messageId = null;
110
111
        if (Response::HTTP_OK === $response->getStatusCode() && $response->hasHeader('Content-Type')
112
            && 'application/json; charset=utf-8' === $response->getHeaderLine('Content-Type')
113
        ) {
114
            $content = $response->getBody()->getContents();
115
            $content = \json_decode($content, true);
116
117
            if (isset($content['messageId']) && \array_key_exists('messageId', $content)) {
118
                $messageId = $content['messageId'];
119
            }
120
        }
121
122
        return $messageId;
123
    }
124
125
    /**
126
     * @param int $messageId
127
     *
128
     * @return string
129
     */
130
    public function getStatusOfSMS(int $messageId): string
131
    {
132
        $response = $this->sendRequestToCheckStatusOfSMS($messageId);
133
        $result = '';
134
135
        if (isset($response['status']) && \array_key_exists('status', $response)) {
136
            $result = $response['status'];
137
        }
138
139
        return $result;
140
    }
141
142
    /**
143
     * @param int $messageId
144
     *
145
     * @return bool
146
     */
147
    public function smsIsSentSuccessfully(int $messageId): bool
148
    {
149
        $response = $this->sendRequestToCheckStatusOfSMS($messageId);
150
151
        $result = false;
152
        if (isset($response['status']) && SinchSmsStatus::SUCCESSFUL === $response['status']) {
153
            $result = true;
154
        }
155
156
        return $result;
157
    }
158
159
    /**
160
     * @param int $messageId
161
     *
162
     * @return bool
163
     */
164
    public function smsIsPending(int $messageId): bool
165
    {
166
        $response = $this->sendRequestToCheckStatusOfSMS($messageId);
167
168
        $result = false;
169
        if (isset($response['status']) && SinchSmsStatus::PENDING === $response['status']) {
170
            $result = true;
171
        }
172
173
        return $result;
174
    }
175
176
    /**
177
     * @param int $messageId
178
     *
179
     * @return bool
180
     */
181
    public function smsIsFaulted(int $messageId): bool
182
    {
183
        $response = $this->sendRequestToCheckStatusOfSMS($messageId);
184
185
        $result = false;
186
        if (isset($response['status']) && SinchSmsStatus::FAULTED === $response['status']) {
187
            $result = true;
188
        }
189
190
        return $result;
191
    }
192
193
    /**
194
     * @param int $messageId
195
     *
196
     * @return bool
197
     */
198
    public function smsInUnknownStatus(int $messageId): bool
199
    {
200
        $response = $this->sendRequestToCheckStatusOfSMS($messageId);
201
202
        $result = false;
203
        if (isset($response['status']) && SinchSmsStatus::UNKNOWN === $response['status']) {
204
            $result = true;
205
        }
206
207
        return $result;
208
    }
209
210
    /**
211
     * @param int $messageId
212
     *
213
     * @return array|null
214
     */
215
    private function sendRequestToCheckStatusOfSMS(int $messageId): ?array
216
    {
217
        $body = [
218
            'auth' => [$this->key, $this->secret],
219
            'headers' => ['X-Timestamp' => (new \DateTime('now'))->format('c')],
220
        ];
221
222
        try {
223
            $response = $this->guzzleHTTPClient->get(self::URL_FOR_CHECKING_SMS_STATUS.$messageId, $body);
224
        } catch (ClientException $e) {
225
            throw SinchExceptionResolver::createAppropriateSinchException($e);
226
        }
227
228
        $result = null;
229
230
        if (Response::HTTP_OK === $response->getStatusCode() && $response->hasHeader('Content-Type')
231
            && 'application/json; charset=utf-8' === $response->getHeaderLine('Content-Type')
232
        ) {
233
            $content = $response->getBody()->getContents();
234
            $result = \json_decode($content, true);
235
        }
236
237
        return $result;
238
    }
239
}
240