1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace SimPod\SmsManager; |
6
|
|
|
|
7
|
|
|
use GuzzleHttp\Client; |
8
|
|
|
use GuzzleHttp\Exception\ClientException; |
9
|
|
|
use GuzzleHttp\Exception\ServerException; |
10
|
|
|
use Psr\Http\Message\ResponseInterface; |
11
|
|
|
use SimPod\SmsManager\Exception\SendingFailed; |
12
|
|
|
use function dom_import_simplexml; |
13
|
|
|
|
14
|
|
|
final class ApiSmsManager implements SmsManager |
15
|
|
|
{ |
16
|
|
|
private const XML_BASE_PATH = 'https://xml-api.smsmanager.cz/'; |
17
|
|
|
private const XML_PATH_SEND = 'Send'; |
18
|
|
|
|
19
|
|
|
/** @var string */ |
20
|
|
|
private $apiKey; |
21
|
|
|
|
22
|
|
|
/**@var Client */ |
23
|
|
|
private $xmlClient; |
24
|
|
|
|
25
|
|
|
public function __construct() |
26
|
|
|
{ |
27
|
|
|
$this->xmlClient = new Client( |
28
|
|
|
[ |
29
|
|
|
'base_uri' => self::XML_BASE_PATH, |
30
|
|
|
] |
31
|
|
|
); |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
public function setApiKey(string $apiKey) : void |
35
|
|
|
{ |
36
|
|
|
$this->apiKey = $apiKey; |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @return Response|bool |
41
|
|
|
*/ |
42
|
|
|
public function sendSms(Sms $sms) |
43
|
|
|
{ |
44
|
|
|
$xml = $this->buildXml($sms); |
45
|
|
|
|
46
|
|
|
if ($xml === null) { |
47
|
|
|
return false; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
try { |
51
|
|
|
$response = $this->xmlClient->post( |
52
|
|
|
self::XML_PATH_SEND, |
53
|
|
|
[ |
54
|
|
|
'multipart' => [ |
55
|
|
|
[ |
56
|
|
|
'name' => 'XMLDATA', |
57
|
|
|
'contents' => $xml, |
58
|
|
|
], |
59
|
|
|
], |
60
|
|
|
] |
61
|
|
|
); |
62
|
|
|
|
63
|
|
|
return $this->buildResponseData($response); |
64
|
|
|
} catch (ClientException | ServerException $exception) { |
65
|
|
|
$response = Parser::parseXmlResponseBody($exception->getResponse()); |
66
|
|
|
|
67
|
|
|
throw SendingFailed::forRecipients($sms->getRecipients(), $response); |
68
|
|
|
} |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
private function buildXml(Sms $sms) : ?string |
72
|
|
|
{ |
73
|
|
|
$xml = new \SimpleXMLElement('<RequestDocument/>'); |
74
|
|
|
$requestHeader = $xml->addChild('RequestHeader'); |
75
|
|
|
$requestHeader->addChild('Apikey', $this->apiKey); |
76
|
|
|
$request = $xml |
77
|
|
|
->addChild('RequestList') |
78
|
|
|
->addChild('Request'); |
79
|
|
|
|
80
|
|
|
$request->addAttribute('Type', $sms->getType()->getValue()); |
81
|
|
|
|
82
|
|
|
if ($sms->getSender() !== null) { |
83
|
|
|
$request->addAttribute('Sender', $sms->getSender()); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
if ($sms->getCustomId() !== null) { |
87
|
|
|
$request->addAttribute('CustomID', (string) $sms->getCustomId()); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
$request->addChild('Message', $sms->getMessage())->addAttribute('Type', 'Text'); |
91
|
|
|
|
92
|
|
|
$numberList = $request->addChild('NumbersList'); |
93
|
|
|
|
94
|
|
|
$hasAnyNumber = false; |
95
|
|
|
foreach ($sms->getRecipients() as $recipient) { |
96
|
|
|
Validator::isE164($recipient); |
97
|
|
|
$numberList->addChild('Number', $recipient); |
98
|
|
|
$hasAnyNumber = true; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/* removes <?xml version="1.0"?> */ |
102
|
|
|
$dom = dom_import_simplexml($xml); |
103
|
|
|
$xml = $dom->ownerDocument->saveXML($dom->ownerDocument->documentElement); |
104
|
|
|
|
105
|
|
|
return $hasAnyNumber ? $xml : null; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
private function buildResponseData(ResponseInterface $apiResponse) : Response |
109
|
|
|
{ |
110
|
|
|
$result = new \SimpleXMLElement((string) $apiResponse->getBody()); |
111
|
|
|
|
112
|
|
|
$responseId = (int) $result->Response['ID']; |
113
|
|
|
$responseType = (string) $result->Response['Type']; |
114
|
|
|
|
115
|
|
|
$response = new Response($responseId, $responseType); |
116
|
|
|
|
117
|
|
|
/** @var \SimpleXMLElement $responseRequestList */ |
118
|
|
|
$responseRequestList = $result->ResponseRequestList; |
|
|
|
|
119
|
|
|
|
120
|
|
|
foreach ($responseRequestList->ResponseRequest as $request) { |
121
|
|
|
$responseRequest = new ResponseRequest( |
122
|
|
|
(int) $request->RequestID, |
123
|
|
|
(int) $request->CustomID, |
124
|
|
|
(int) $request['SmsCount'], |
125
|
|
|
(float) $request['SmsPrice'] |
126
|
|
|
); |
127
|
|
|
|
128
|
|
|
/** @var \SimpleXMLElement $responseNumbersList */ |
129
|
|
|
$responseNumbersList = $request->ResponseNumbersList; |
130
|
|
|
foreach ($responseNumbersList->Number as $phoneNumber) { |
131
|
|
|
$responseRequest->addNumber((string) $phoneNumber); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
$response->addResponseRequest($responseRequest); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
return $response; |
138
|
|
|
} |
139
|
|
|
} |
140
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.