├── .gitignore
├── README.md
├── composer.json
├── composer.lock
├── examples
├── include.php
├── index.php
└── webhook.php
└── lib
├── Api.php
├── ApiException.php
├── Client.php
├── Response
├── Balance.php
├── DirectNumber.php
├── IncomingCallsStatistics.php
├── NumberLookup.php
├── PbxInfo.php
├── PbxInternal.php
├── PbxRecordRequest.php
├── PbxRecording.php
├── PbxRedirection.php
├── PbxStatistics.php
├── PbxStatus.php
├── Price.php
├── Redirection.php
├── RequestCallback.php
├── Response.php
├── Sip.php
├── SipCaller.php
├── SipRedirection.php
├── SipRedirectionStatus.php
├── SipStatus.php
├── Sms.php
├── SpeechRecognition.php
├── Statistics.php
├── Tariff.php
├── Timezone.php
├── WebrtcKey.php
└── Zcrm.php
└── Webhook
├── AbstractNotify.php
├── NotifyAnswer.php
├── NotifyEnd.php
├── NotifyInternal.php
├── NotifyIvr.php
├── NotifyOutEnd.php
├── NotifyOutStart.php
├── NotifyRecord.php
├── NotifyStart.php
├── Request.php
└── WaitDtmf.php
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | composer.phar
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Zadarma API - User class
2 | An official PHP class for work with Zadarma API.
3 |
4 | Allows to work with all API methods (including VoIP, PBX, CallBack etc).
5 |
6 | ## Requirements:
7 | - PHP >= 5.5.0
8 | - cURL
9 | - TLS v1.2
10 |
11 | ## How to use?
12 | An official documentation on Zadarma API is [here](https://zadarma.com/support/api/).
13 |
14 | Keys for authorization are in [personal account](https://my.zadarma.com/api/).
15 |
16 | ## Installation
17 | ### Via Сomposer
18 | ```sh
19 | composer require "zadarma/user-api-v1"
20 | ```
21 | or just add this line to your `composer.json` file:
22 | ```json
23 | "zadarma/user-api-v1"
24 | ```
25 |
26 | ### Via Git
27 | ```sh
28 | git clone git@github.com:zadarma/user-api-v1.git
29 | ```
30 |
31 | ### \Zadarma_API\Api call code example
32 | ```php
33 | getSipStatus('YOURSIP');
38 | echo $result->sip.' status: '.($result->is_online ? 'online' : 'offline');
39 | } catch (\Zadarma_API\ApiException $e) {
40 | echo 'Error: '.$e->getMessage();
41 | }
42 |
43 | ```
44 | All other examples you can see in the "[example file](https://github.com/zadarma/user-api-v1/tree/master/examples/index.php)".
45 |
46 | ### \Zadarma_API\Client call code example
47 | ```php
48 | 'YOURSIP',
54 | 'status' => 'on'
55 | );
56 |
57 | $zd = new \Zadarma_API\Client(YOUR_KEY, YOUR_SECRET);
58 | /*
59 | $zd->call('METHOD', 'PARAMS_ARRAY', 'REQUEST_TYPE', 'FORMAT', 'IS_AUTH');
60 | where:
61 | - METHOD - a method API, started from /v1/ and ended by '/';
62 | - PARAMS_ARRAY - an array of parameters to a method;
63 | - REQUEST_TYPE: GET (default), POST, PUT, DELETE;
64 | - FORMAT: json (default), xml;
65 | - IS_AUTH: true (default), false - is method under authentication or not.
66 | */
67 | $answer = $zd->call('/v1/sip/redirection/', $params, 'put');
68 |
69 | $answerObject = json_decode($answer);
70 |
71 | if ($answerObject->status == 'success') {
72 | echo 'Redirection on your SIP "' . $answerObject->sip . " has been changed to " . $answerObject->current_status . ".";
73 | } else {
74 | $answerObject->message;
75 | }
76 | ```
77 |
78 | All other examples you can see in the "[examples](https://github.com/zadarma/user-api-v1/tree/master/examples)" folder.
79 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "zadarma/user-api-v1",
3 | "description": "PHP class for Zadarma API",
4 | "keywords": [
5 | "zadarma",
6 | "api",
7 | "sip",
8 | "pbx",
9 | "free calls"
10 | ],
11 | "type": "library",
12 | "license": "MIT",
13 | "homepage": "https://github.com/zadarma/user-api-v1",
14 | "authors": [
15 | {
16 | "name": "Zadarma",
17 | "email": "github@zadarma.com"
18 | }
19 | ],
20 | "autoload": {
21 | "psr-4": {
22 | "Zadarma_API\\": "lib/"
23 | }
24 | },
25 | "require": {
26 | "php": ">=5.5.0",
27 | "ext-curl": "*"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "1269935064f18102c95cac4638286466",
8 | "packages": [],
9 | "packages-dev": [],
10 | "aliases": [],
11 | "minimum-stability": "stable",
12 | "stability-flags": [],
13 | "prefer-stable": false,
14 | "prefer-lowest": false,
15 | "platform": {
16 | "php": ">=5.5.0",
17 | "ext-curl": "*"
18 | },
19 | "platform-dev": []
20 | }
21 |
--------------------------------------------------------------------------------
/examples/include.php:
--------------------------------------------------------------------------------
1 | getBalance();
20 | $result = $api->getPrice($destinationEmail, $sourceNumber);
21 | $result = $api->getTimezone();
22 | $result = $api->getTariff();
23 |
24 |
25 | // pbx methods
26 | $result = $api->getPbxInternal();
27 | $result = $api->getPbxStatus($pbx);
28 | $result = $api->getPbxInfo($pbx);
29 | $result = $api->getPbxRecord($callId, null);
30 | $result = $api->getPbxRedirection($pbx);
31 |
32 | $result = $api->setPbxPhoneRedirection($pbx, $destinationNumber, false, true);
33 | $result = $api->setPbxVoicemailRedirection($pbx, $destinationEmail, true, Api::PBX_REDIRECTION_OWN_GREETING);
34 | $result = $api->setPbxRedirectionOff($pbx);
35 |
36 |
37 | // sip methods
38 | $result = $api->getSip();
39 | $result = $api->getSipStatus($sip);
40 | $result = $api->getSipRedirection($sip);
41 |
42 | $result = $api->setSipCallerId($sip, $sourceNumber);
43 | $result = $api->setSipRedirectionNumber($sip, $destinationNumber);
44 | $result = $api->setSipRedirectionStatus($sip, false);
45 |
46 |
47 | // statistic methods
48 | $result = $api->getStatistics();
49 | $result = $api->getPbxStatistics();
50 | $result = $api->getDirectNumbers();
51 |
52 | // zcrm methods
53 | $result = $api->zcrmRequest('/users' );
54 |
55 | // other methods
56 | $result = $api->requestCallback($pbx, $destinationNumber);
57 |
58 | $result = $api->numberLookup($destinationNumber);
59 | $result = $api->numberLookupMultiple([$sourceNumber, $destinationNumber]);
60 |
61 | $result = $api->sendSms($destinationNumber, 'text', $sourceNumber);
62 |
63 | $result = $api->startSpeechRecognition($callId);
64 | $result = $api->getSpeechRecognitionResult($callId);
65 | $result = $api->getWebrtcKey($sip);
66 |
--------------------------------------------------------------------------------
/examples/webhook.php:
--------------------------------------------------------------------------------
1 | 'xxxxxxxxxxxxxxxx',
26 | 1 => [
27 | 'file' => 'xxxxxxxxxxxxxxxx',
28 | 1 => [
29 | 'file' => 'xxxxxxxxxxxxxxxx',
30 | 1 => [
31 | 'file' => 'xxxxxxxxxxxxxxxx',
32 | ],
33 | ],
34 | 2 => [
35 | 'file' => 'xxxxxxxxxxxxxxxx',
36 | ],
37 | ],
38 | 2 => [
39 | 'file' => 'xxxxxxxxxxxxxxxx',
40 | ],
41 | ];
42 |
43 | /**
44 | * The system dictates the last 3 digits of the caller's number and exits.
45 | */
46 | public static function example1()
47 | {
48 | /** @var NotifyStart $notify */
49 | $notify = self::getEvent([AbstractNotify::EVENT_START, AbstractNotify::EVENT_IVR]);
50 | if (!$notify) {
51 | return;
52 | }
53 | $request = new Request();
54 | if ($notify->event == AbstractNotify::EVENT_START) {
55 | $request->setIvrSayDigits(mb_substr($notify->caller_id, -3), 'en');
56 | } else {
57 | $request->setHangup();
58 | }
59 | $request->send();
60 | }
61 |
62 | /**
63 | * Enter the date of birth through dtmf and the system will say how many days are left.
64 | */
65 | public static function example2()
66 | {
67 | $request = new Request();
68 | $notify = self::getEvent([AbstractNotify::EVENT_START, AbstractNotify::EVENT_IVR]);
69 | if ($notify->event == AbstractNotify::EVENT_START) {
70 | /** @var NotifyStart $notify */
71 | $request
72 | ->setIvrPlay(self::INFO_FILE_ID)
73 | ->setWaitDtmf(7, 1, 4, self::DTMF_NAME_2, 'hangup')
74 | ->send();
75 | } elseif ($notify->event == AbstractNotify::EVENT_IVR) {
76 | /** @var NotifyIvr $notify */
77 | if (!$notify->wait_dtmf
78 | || $notify->wait_dtmf->name != self::DTMF_NAME_2
79 | || $notify->wait_dtmf->default_behaviour
80 | ) {
81 | $request
82 | ->setHangup()
83 | ->send();
84 | } else {
85 |
86 | if (mb_strlen($notify->wait_dtmf->digits) == 4) {
87 | $month = mb_substr($notify->wait_dtmf->digits, 0, 2);
88 | $day = mb_substr($notify->wait_dtmf->digits, 2);
89 | if ($month > 0 && $month <= 12 && $day > 0 && $day <= date('t', mktime(0, 0, 0, $month))) {
90 | $birth = (new DateTime())->setDate(date('Y'), $month, $day);
91 | $diff = (new DateTime())->diff($birth)->format('%r%a');
92 | if ($diff < 0) {
93 | $diff += (date('L') ? 366 : 365);
94 | }
95 |
96 | $request
97 | ->setIvrSayNumber($diff, 'en')
98 | ->send();
99 | return;
100 | }
101 | }
102 |
103 | $request
104 | ->setIvrPlay(self::WRONG_INPUT_FILE_ID)
105 | ->setWaitDtmf(7, 1, 4, self::DTMF_NAME_2, 'hangup')
106 | ->send();
107 | }
108 | }
109 | }
110 |
111 | /**
112 | * Implementation of multi-level menu.
113 | * Enter '1' or '2' to go to the next menu, '4' to return to the level above, '5' for hangup.
114 | */
115 | public static function example3()
116 | {
117 | $request = new Request();
118 | /** @var NotifyIvr $notify */
119 |
120 | if ($notify = self::getEvent([AbstractNotify::EVENT_START])) {
121 | $request
122 | ->setIvrPlay(self::$menu['file'])
123 | ->setWaitDtmf(5, 1, 1, self::DTMF_NAME_3, 'hangup')
124 | ->send();
125 | return;
126 | }
127 |
128 | $notify = self::getEvent([AbstractNotify::EVENT_IVR]);
129 | if (!empty($notify->wait_dtmf->digits) && mb_strpos($notify->wait_dtmf->name, self::DTMF_NAME_3) === 0) {
130 | $menu = mb_substr($notify->wait_dtmf->name, mb_strlen(self::DTMF_NAME_3));
131 |
132 | switch ($notify->wait_dtmf->digits){
133 | case 1:
134 | case 2:
135 | case 3:
136 | $menu .= $notify->wait_dtmf->digits;
137 | break;
138 |
139 | case 4:
140 | if ($menu) {
141 | $menu = mb_substr($menu, 0, mb_strlen($menu) - 1);
142 | }
143 | break;
144 |
145 | case 5:
146 | default:
147 | $request->setHangup()->send();
148 | return;
149 | }
150 |
151 | list($menu, $file) = self::getMenuFile($menu);
152 | $request
153 | ->setIvrPlay($file)
154 | ->setWaitDtmf(5, 1, 1, self::DTMF_NAME_3.$menu, 'hangup')
155 | ->send();
156 | }
157 | }
158 |
159 | private static function getEvent($allowedTypes)
160 | {
161 | if (self::$api === null) {
162 | self::$api = new Api(KEY, SECRET, true);
163 | }
164 | return self::$api->getWebhookEvent($allowedTypes);
165 | }
166 |
167 | private static function getMenuFile($menuDigits)
168 | {
169 | $menuDigits = (string)$menuDigits;
170 | $menuDigitsResult = '';
171 | $menu = self::$menu;
172 | while ($menuDigits) {
173 | $currentDigit = mb_substr($menuDigits, 0, 1);
174 | $menuDigits = mb_substr($menuDigits, 1);
175 | if (isset($menu[$currentDigit])) {
176 | $menu = $menu[$currentDigit];
177 | $menuDigitsResult .= $currentDigit;
178 | } else {
179 | break;
180 | }
181 | }
182 | return [$menuDigitsResult, $menu['file']];
183 | }
184 | }
185 |
186 | WebhookExample::example1();
--------------------------------------------------------------------------------
/lib/Api.php:
--------------------------------------------------------------------------------
1 | request('info/balance');
61 | return new Balance($data);
62 | }
63 |
64 | /**
65 | * Return call rate in the user's current price plan.
66 | *
67 | * @param string $number
68 | * @param null|string $callerId
69 | * @return Price
70 | * @throws ApiException
71 | */
72 | public function getPrice($number, $callerId = null)
73 | {
74 | $params = ['number' => self::filterNumber($number)];
75 | if ($callerId) {
76 | $params['caller_id'] = self::filterNumber($number);
77 | }
78 | $data = $this->request('info/price', $params);
79 | return new Price($data['info']);
80 | }
81 |
82 | /**
83 | * Return user's timezone.
84 | *
85 | * @return Timezone
86 | * @throws ApiException
87 | */
88 | public function getTimezone()
89 | {
90 | $data = $this->request('info/timezone');
91 | return new Timezone($data);
92 | }
93 |
94 | /**
95 | * Return information about the user's current price plan.
96 | *
97 | * @return Tariff
98 | * @throws ApiException
99 | */
100 | public function getTariff()
101 | {
102 | $data = $this->request('tariff');
103 | return new Tariff($data['info']);
104 | }
105 |
106 | /**
107 | * Request a callback.
108 | * @see https://zadarma.com/en/services/calls/callback/
109 | *
110 | * @param string from Your phone/SIP number, the PBX extension number or the PBX scenario,
111 | * to which the CallBack is made.
112 | * @param string to The phone or SIP number that is being called.
113 | * @param null|string sip SIP user's number or the PBX extension number,
114 | * which is used to make the call.
115 | * @param null|string predicted If this flag is specified the request is predicted
116 | * (the system calls the “to” number, and only connects it to your SIP, or your phone number,
117 | * if the call is successful.);
118 | * @return RequestCallback
119 | * @throws ApiException
120 | */
121 | public function requestCallback($from, $to, $sip = null, $predicted = null)
122 | {
123 | $params = [
124 | 'from' => $from,
125 | 'to' => self::filterNumber($to),
126 | ];
127 | $params = $params + self::filterParams([
128 | 'sip' => is_null($sip) ? null : self::filterNumber($sip),
129 | 'predicted' => $predicted,
130 | ]);
131 | $data = $this->request('request/callback', $params);
132 | return new RequestCallback($data);
133 | }
134 |
135 | /**
136 | * Return the list of user's SIP-numbers.
137 | *
138 | * @return array
139 | * @throws ApiException
140 | */
141 | public function getSip()
142 | {
143 | $data = $this->request('sip');
144 | unset($data['status']);
145 | if (is_array($data['sips']) && $data['sips']) {
146 | foreach ($data['sips'] as &$sipData) {
147 | $sipData = new Sip($sipData);
148 | }
149 | }
150 | return $data;
151 | }
152 |
153 | /**
154 | * Return the user's SIP number online status.
155 | *
156 | * @param $sipId
157 | * @return SipStatus
158 | * @throws ApiException
159 | */
160 | public function getSipStatus($sipId)
161 | {
162 | $data = $this->request('sip/' . self::filterNumber($sipId) . '/status');
163 | return new SipStatus($data);
164 | }
165 |
166 | /**
167 | * Return the current call forwarding based on the user's SIP numbers.
168 | *
169 | * @param null|integer $sipId Selection of the specific SIP ID.
170 | * @return Redirection[]
171 | * @throws ApiException
172 | */
173 | public function getSipRedirection($sipId = null)
174 | {
175 | $params = $sipId ? ['id' => self::filterNumber($sipId)] : [];
176 | $data = $this->request('sip/redirection', $params);
177 | return self::arrayToResultObj($data['info'], Response\Redirection::class);
178 | }
179 |
180 | /**
181 | * Return information about the user's phone numbers.
182 | * @return DirectNumber[]
183 | * @throws ApiException
184 | */
185 | public function getDirectNumbers()
186 | {
187 | $data = $this->request('direct_numbers');
188 | return self::arrayToResultObj($data['info'], DirectNumber::class);
189 | }
190 |
191 | /**
192 | * Return online status of the PBX extension number.
193 | * @return PbxInternal
194 | * @throws ApiException
195 | */
196 | public function getPbxInternal()
197 | {
198 | $data = $this->request('pbx/internal');
199 | return new PbxInternal($data);
200 | }
201 |
202 | /**
203 | * Return online status of the PBX extension number.
204 | * @param $pbxId
205 | * @return PbxStatus
206 | * @throws ApiException
207 | */
208 | public function getPbxStatus($pbxId)
209 | {
210 | $data = $this->request('pbx/internal/' . self::filterNumber($pbxId) . '/status');
211 | return new PbxStatus($data);
212 | }
213 |
214 | /**
215 | * Return information about the PBX extension number.
216 | * @param $pbxId
217 | * @return PbxInfo
218 | * @throws ApiException
219 | */
220 | public function getPbxInfo($pbxId)
221 | {
222 | $data = $this->request('pbx/internal/' . self::filterNumber($pbxId) . '/info');
223 | return new PbxInfo($data);
224 | }
225 |
226 | /**
227 | * Return call recording file request.
228 | * @param string|null $callId Unique call ID, it is specified in the name of the file with the call
229 | * recording (unique for every recording)
230 | * @param string|null $pbxCallId Permanent ID of the external call to the PBX
231 | * @param integer|null $lifetime The link's lifetime in seconds (minimum - 180, maximum - 5184000, default - 1800)
232 | * @return PbxRecordRequest
233 | * @throws ApiException
234 | */
235 | public function getPbxRecord($callId, $pbxCallId, $lifetime = null)
236 | {
237 | $params = array_filter([
238 | 'call_id' => $callId,
239 | 'pbx_call_id' => $pbxCallId,
240 | ]);
241 | if (!$params) {
242 | throw new ApiException('callId or pbxCallId required');
243 | }
244 | if ($lifetime) {
245 | $params['lifetime'] = $lifetime;
246 | }
247 | $data = $this->request('pbx/record/request', $params);
248 | return new PbxRecordRequest($data);
249 | }
250 |
251 | /**
252 | * Return call forwarding parameters on the PBX extension number.
253 | * @param integer $pbxNumber PBX extension number
254 | * @return PbxRedirection
255 | * @throws ApiException
256 | */
257 | public function getPbxRedirection($pbxNumber)
258 | {
259 | $data = $this->request('pbx/redirection', ['pbx_number' => self::filterNumber($pbxNumber)]);
260 | return new PbxRedirection($data);
261 | }
262 |
263 | /**
264 | * Return overall statistics.
265 | * Maximum period of getting statistics is - 1 month. If the limit in the request is exceeded, the time period
266 | * automatically decreases to 30 days. If the start date is not specified, the start of the current month will be
267 | * selected. If the end date is not specified, the current date and time will be selected.
268 | *
269 | * @param string|null $start The start date of the statistics display (format - y-m-d H:i:s)
270 | * @param string|null $end The end date of the statistics display (format - y-m-d H:i:s)
271 | * @param integer|null $sip Filter based on a specific SIP number
272 | * @param bool|null $costOnly Display only the amount of funds spent during a specific period
273 | * @param string|null $type Request type: overall (is not specified in the request), toll and ru495
274 | * @param integer|null $skip Number of lines to be skipped in the sample. The output begins from skip +1 line.
275 | * @param integer|null $limit The limit on the number of input lines
276 | * (the maximum value is 1000, the default value is 1000)
277 | * @return Statistics
278 | * @throws ApiException
279 | */
280 | public function getStatistics(
281 | $start = null,
282 | $end = null,
283 | $sip = null,
284 | $costOnly = null,
285 | $type = null,
286 | $skip = null,
287 | $limit = null
288 | ) {
289 | $params = [
290 | 'start' => $start,
291 | 'end' => $end,
292 | 'sip' => is_null($sip) ? null : self::filterNumber($sip),
293 | 'cost_only' => $costOnly,
294 | 'type' => $type,
295 | 'skip' => $skip,
296 | 'limit' => $limit,
297 | ];
298 | $data = $this->request('statistics', self::filterParams($params));
299 | return new Statistics($data);
300 | }
301 |
302 | /**
303 | * Return PBX statistics.
304 | * @see Api::getStatistics() For $start, $end, $skip, $limit parameters details.
305 | *
306 | * @param string|null $start
307 | * @param string|null $end
308 | * @param true|bool $newFormat Format of the statistics result.
309 | * @param integer|null $skip
310 | * @param integer|null $limit
311 | * @param string|null $callType IN_CALLS for incoming calls, OUT_CALLS for outgoing, null for both
312 | * @return PbxStatistics
313 | * @throws ApiException
314 | */
315 | public function getPbxStatistics(
316 | $start = null,
317 | $end = null,
318 | $newFormat = true,
319 | $callType = null,
320 | $skip = null,
321 | $limit = null
322 | ) {
323 | $params = [
324 | 'start' => $start,
325 | 'end' => $end,
326 | 'version' => $newFormat ? 2 : 1,
327 | 'skip' => $skip,
328 | 'limit' => $limit,
329 | 'call_type' => $callType,
330 | ];
331 | $data = $this->request('statistics/pbx', self::filterParams($params));
332 | return new PbxStatistics($data);
333 | }
334 |
335 | /**
336 | * Return CallBack widget statistics.
337 | * @see Api::getStatistics() For $start and $end parameters details.
338 | *
339 | * @param string|null $start
340 | * @param string|null $end
341 | * @param string|null $widget_id
342 | * @return PbxStatistics
343 | * @throws ApiException
344 | */
345 | public function getCallbackWidgetStatistics($start = null, $end = null, $widget_id = null)
346 | {
347 | $params = [
348 | 'start' => $start,
349 | 'end' => $end,
350 | 'widget_id' => $widget_id,
351 | ];
352 | $data = $this->request('statistics/callback_widget', self::filterParams($params));
353 | return new PbxStatistics($data);
354 | }
355 |
356 | /**
357 | * Return overall incoming calls statistics.
358 | * Maximum period of getting statistics is - 1 month. If the limit in the request is exceeded, the time period
359 | * automatically decreases to 30 days. If the start date is not specified, the start of the current month will be
360 | * selected. If the end date is not specified, the current date and time will be selected.
361 | *
362 | * @param string|null $start The start date of the statistics display (format - y-m-d H:i:s)
363 | * @param string|null $end The end date of the statistics display (format - y-m-d H:i:s)
364 | * @param integer|null $sip Filter based on a specific SIP number
365 | * @param integer|null $skip Number of lines to be skipped in the sample. The output begins from skip +1 line.
366 | * @param integer|null $limit The limit on the number of input lines
367 | * (the maximum value is 1000, the default value is 1000)
368 | * @return IncomingCallsStatistics
369 | * @throws ApiException
370 | */
371 | public function getIncomingCallStatistics($start = null, $end = null, $sip = null, $skip = null, $limit = null)
372 | {
373 | $params = [
374 | 'start' => $start,
375 | 'end' => $end,
376 | 'sip' => is_null($sip) ? null : self::filterNumber($sip),
377 | 'skip' => $skip,
378 | 'limit' => $limit,
379 | ];
380 | $data = $this->request('statistics/incoming-calls', self::filterParams($params));
381 | return new IncomingCallsStatistics($data);
382 | }
383 |
384 | /**
385 | * Changing of the CallerID.
386 | * @param integer id The SIP ID, which needs the CallerID to be changed;
387 | * @param string number The new (changed) phone number, in international format
388 | * (from the list of confirmed or purchased phone numbers).
389 | * @return SipCaller
390 | * @throws ApiException
391 | */
392 | public function setSipCallerId($sipId, $number)
393 | {
394 | $params = [
395 | 'id' => self::filterNumber($sipId),
396 | 'number' => self::filterNumber($number)
397 | ];
398 | $data = $this->request('sip/callerid', $params, 'put');
399 | return new SipCaller($data);
400 | }
401 |
402 |
403 | /**
404 | * Call forwarding switch on/off based on the SIP number.
405 | * @param integer $sipId
406 | * @param bool $statusOn True for 'on' and false for 'off' status.
407 | * @return SipRedirectionStatus
408 | * @throws ApiException
409 | */
410 | public function setSipRedirectionStatus($sipId, $statusOn)
411 | {
412 | $params = [
413 | 'id' => self::filterNumber($sipId),
414 | 'status' => $statusOn ? 'on' : 'off',
415 | ];
416 | $data = $this->request('sip/redirection', $params, 'put');
417 | return new SipRedirectionStatus($data);
418 | }
419 |
420 | /**
421 | * Changing of the call forwarding parameters.
422 | * @param integer $sipId
423 | * @param string $number phone number
424 | * @return SipRedirection
425 | * @throws ApiException
426 | */
427 | public function setSipRedirectionNumber($sipId, $number)
428 | {
429 | $params = [
430 | 'id' => self::filterNumber($sipId),
431 | 'type' => 'phone',
432 | 'number' => self::filterNumber($number),
433 | ];
434 | $data = $this->request('sip/redirection', $params, 'put');
435 | return new SipRedirection($data);
436 | }
437 |
438 | /**
439 | * Enabling of the call recording on the PBX extension number.
440 | * @param integer $sipId
441 | * @param string $status One of the values: "on" - switch on, "off" - switch off, "on_email" - enable the option to
442 | * send the recordings to the email address only, "off_email" - disable the option to send the recordings to the
443 | * email address only, "on_store" - enable the option to save the recordings to the cloud, "off_store" - disable the
444 | * option to save the recordings to the cloud.
445 | * @param string|null $email (optional) change the email address, where the call recordings will be sent.
446 | * You can specify up to 3 email addresses, separated by comma.
447 | * @param string|null $speechRecognition (optional) change the speech recognition settings: "all" - recognize all,
448 | * "optional" - recognize selectively in statistics, "off" - disable.
449 | * @return PbxRecording
450 | * @throws ApiException
451 | */
452 | public function setPbxRecording($sipId, $status, $email = null, $speechRecognition = null)
453 | {
454 | if (!in_array($status, ['on', 'off', 'on_email', 'off_email', 'on_store', 'off_store'])) {
455 | throw new \BadFunctionCallException('Wrong status parameter');
456 | }
457 | $params = [
458 | 'id' => self::filterNumber($sipId),
459 | 'status' => $status
460 | ];
461 | if ($email) {
462 | $params['email'] = $email;
463 | }
464 | if ($speechRecognition && !in_array($status, ['off', 'off_store'])) {
465 | if (!in_array($speechRecognition, ['all', 'optional', 'off'])) {
466 | throw new \BadFunctionCallException('Wrong speechRecognition parameter');
467 | }
468 | $params['speech_recognition'] = $speechRecognition;
469 | }
470 | $data = $this->request('pbx/internal/recording', $params, 'put');
471 | return new PbxRecording($data);
472 | }
473 |
474 | /**
475 | * Sending the SMS messages.
476 | *
477 | * @param string|array $to Phone number(s), where to send the SMS message (array of numbers can be specified);
478 | * @param string $message Message (standard text limit applies; the text will be separated into several SMS messages,
479 | * if the limit is exceeded);
480 | * @param string $callerId Phone number, from which the SMS messages is sent (can be sent only from list of user's
481 | * confirmed phone numbers).
482 | * @return Sms
483 | * @throws ApiException
484 | */
485 | public function sendSms($to, $message, $callerId = null)
486 | {
487 | $to = array_map([self::class, 'filterNumber'], is_array($to) ? $to : [$to]);
488 | $params = [
489 | 'number' => implode(',', $to),
490 | 'message' => $message,
491 | ];
492 | if ($callerId) {
493 | $params['caller_id'] = $callerId;
494 | }
495 | $data = $this->request('sms/send', $params, 'post');
496 | return new Sms($data);
497 | }
498 |
499 | /**
500 | * Number lookup for one phone number.
501 | * @param string $number Phone number.
502 | * @return NumberLookup
503 | * @throws ApiException
504 | */
505 | public function numberLookup($number)
506 | {
507 | $data = $this->request('info/number_lookup', ['numbers' => self::filterNumber($number)], 'post');
508 | return new NumberLookup($data['info']);
509 | }
510 |
511 | /**
512 | * Number lookup for multiple phone numbers.
513 | * @param string[] $numbers Phone number.
514 | * @throws ApiException
515 | */
516 | public function numberLookupMultiple($numbers)
517 | {
518 | $numbers = array_filter(array_map('\Zadarma_API\Api::filterNumber', $numbers));
519 | $this->request('info/number_lookup', ['numbers' => $numbers], 'post');
520 | }
521 |
522 | /**
523 | * Turn off call forwarding parameters on the PBX extension number.
524 | * @param integer $pbxNumber PBX extension number.
525 | * @return PbxRedirection
526 | * @throws ApiException
527 | */
528 | public function setPbxRedirectionOff($pbxNumber)
529 | {
530 | $params = [
531 | 'pbx_number' => self::filterNumber($pbxNumber),
532 | 'status' => 'off',
533 | ];
534 | $data = $this->request('pbx/redirection', $params, 'post');
535 | return new PbxRedirection($data);
536 | }
537 |
538 | /**
539 | * Turn on and setup call forwarding to phone on the PBX extension number.
540 | * @param integer $pbxNumber PBX extension number.
541 | * @param string $destination Phone number.
542 | * @param bool $always Always forward calls or only if there is no answer.
543 | * @param bool $setCallerId Setting up your CallerID during the call forwarding.
544 | * @return PbxRedirection
545 | * @throws ApiException
546 | */
547 | public function setPbxPhoneRedirection($pbxNumber, $destination, $always, $setCallerId)
548 | {
549 | $params = [
550 | 'pbx_number' => self::filterNumber($pbxNumber),
551 | 'type' => 'phone',
552 | 'condition' => $always ? 'always' : 'noanswer',
553 | 'destination' => self::filterNumber($destination),
554 | 'set_caller_id' => $setCallerId ? 'on' : 'off',
555 | ];
556 |
557 | $data = $this->request('pbx/redirection', $params, 'post');
558 | return new PbxRedirection($data);
559 | }
560 |
561 | /**
562 | * Turn on and setup call forwarding to voicemail on the PBX extension number.
563 | * @param integer $pbxNumber PBX extension number.
564 | * @param string $destination Email address.
565 | * @param bool $always Always forward calls or only if there is no answer.
566 | * @param string $greeting Notifications about call forwarding, possible values:
567 | * Api::PBX_REDIRECTION_NO_GREETING, Api::PBX_REDIRECTION_STANDART_GREETING, Api::PBX_REDIRECTION_OWN_GREETING.
568 | * @param string $greetingFile Path to file with notification in mp3 format or wav below 5 MB.
569 | * Specified only when greeting = own.
570 | * @return PbxRedirection
571 | * @throws ApiException
572 | */
573 | public function setPbxVoicemailRedirection($pbxNumber, $destination, $always, $greeting, $greetingFile = null)
574 | {
575 | if (!filter_var($destination, FILTER_VALIDATE_EMAIL)) {
576 | throw new \BadFunctionCallException('Wrong email parameter');
577 | }
578 | $allowedRedirections = [
579 | self::PBX_REDIRECTION_NO_GREETING,
580 | self::PBX_REDIRECTION_OWN_GREETING,
581 | self::PBX_REDIRECTION_STANDART_GREETING
582 | ];
583 | if (!in_array($greeting, $allowedRedirections)) {
584 | throw new \BadFunctionCallException('Wrong voicemailGreeting parameter');
585 | }
586 | $params = [
587 | 'pbx_number' => self::filterNumber($pbxNumber),
588 | 'type' => 'voicemail',
589 | 'condition' => $always ? 'always' : 'noanswer',
590 | 'destination' => $destination,
591 | 'voicemail_greeting' => $greeting,
592 | ];
593 | if ($greeting == self::PBX_REDIRECTION_OWN_GREETING) {
594 | if (
595 | !$greetingFile
596 | || !file_exists($greetingFile)
597 | || !in_array(pathinfo($greetingFile, PATHINFO_EXTENSION), ['wav', 'mp3'])
598 | ) {
599 | throw new \BadFunctionCallException('Greeting file does not exist or has wrong extension.');
600 | }
601 | $params['greeting_file'] = curl_file_create($greetingFile);
602 | }
603 | $data = $this->request('pbx/redirection', $params, 'post');
604 | return new PbxRedirection($data);
605 | }
606 |
607 | /**
608 | * Start speech recognition.
609 | * @param string $callId Unique call ID, it is specified in the name of the file with the call
610 | * recording (unique for every recording)
611 | * @param null|string $lang recognition language (not required)
612 | * @return bool
613 | * @throws ApiException
614 | */
615 | public function startSpeechRecognition($callId, $lang = null)
616 | {
617 | $params = [
618 | 'call_id' => $callId,
619 | ];
620 | if ($lang) {
621 | $params['lang'] = $lang;
622 | }
623 | $data = $this->request('speech_recognition', $params, 'put');
624 | return $data['status'] == 'success';
625 | }
626 |
627 | /**
628 | * Obtaining recognition results.
629 | * @param string $callId Unique call ID, it is specified in the name of the file with the call
630 | * recording (unique for every recording)
631 | * @param null|string $lang recognition language (not required)
632 | * @param bool $returnWords return words or phrases
633 | * @param bool $returnAlternatives return alternative results
634 | * @return SpeechRecognition
635 | * @throws ApiException
636 | */
637 | public function getSpeechRecognitionResult($callId, $lang = null, $returnWords = false, $returnAlternatives = false)
638 | {
639 | $params = [
640 | 'call_id' => $callId,
641 | 'return' => $returnWords ? 'words' : 'phrases',
642 | 'alternatives' => (int)$returnAlternatives,
643 | ];
644 | if ($lang) {
645 | $params['lang'] = $lang;
646 | }
647 | $data = $this->request('speech_recognition', $params, 'get');
648 | return new SpeechRecognition($data);
649 | }
650 |
651 | /**
652 | * Return notify object populated from postData, depending on 'event' field.
653 | * If cannot match event to object, return null.
654 | * Perform signature test, before populating data.
655 | * Throw SignatureException in case of signature test failure.
656 | * @param array|null $eventFilter array of allowed events. If not specified, return all events.
657 | * Example: [AbstractNotify::EVENT_START, AbstractNotify::EVENT_IVR]
658 | * @param array|null $postData Data for model populating. If null, $_POST values used.
659 | * @param null $signature
660 | * @return null|NotifyStart
661 | */
662 | public function getWebhookEvent($eventFilter = null, $postData = null, $signature = null)
663 | {
664 | if ($postData === null) {
665 | $postData = $_POST;
666 | }
667 | if (empty($postData['event']) || ($eventFilter && !in_array($postData['event'], $eventFilter))) {
668 | return null;
669 | }
670 |
671 | if ($signature === null) {
672 | $headers = getallheaders();
673 | if (empty($headers['Signature'])) {
674 | return null;
675 | } else {
676 | $signature = $headers['Signature'];
677 | }
678 | }
679 |
680 | switch ($postData['event']) {
681 | case AbstractNotify::EVENT_START:
682 | $notify = new NotifyStart($postData);
683 | break;
684 |
685 | case AbstractNotify::EVENT_IVR:
686 | $notify = new NotifyIvr($postData);
687 | break;
688 |
689 | case AbstractNotify::EVENT_INTERNAL:
690 | $notify = new NotifyInternal($postData);
691 | break;
692 |
693 | case AbstractNotify::EVENT_ANSWER:
694 | $notify = new NotifyAnswer($postData);
695 | break;
696 |
697 | case AbstractNotify::EVENT_END:
698 | $notify = new NotifyEnd($postData);
699 | break;
700 |
701 | case AbstractNotify::EVENT_OUT_START:
702 | $notify = new NotifyOutStart($postData);
703 | break;
704 |
705 | case AbstractNotify::EVENT_OUT_END:
706 | $notify = new NotifyOutEnd($postData);
707 | break;
708 |
709 | case AbstractNotify::EVENT_RECORD:
710 | $notify = new NotifyRecord($postData);
711 | break;
712 |
713 | default:
714 | return null;
715 | }
716 |
717 | if ($signature != $this->encodeSignature($notify->getSignatureString())) {
718 | return null;
719 | }
720 |
721 | return $notify;
722 | }
723 |
724 | /**
725 | * @param $method
726 | * @param array $params
727 | * @param string $requestType
728 | * @return Zcrm
729 | * @throws ApiException
730 | */
731 | public function zcrmRequest($method, $params = [], $requestType = 'get')
732 | {
733 | $result = $this->call('/' . self::VERSION . '/zcrm' . $method, $params, $requestType);
734 |
735 | $result = json_decode($result, true);
736 | if ((!empty($result['status']) && $result['status'] == 'error') || $this->getHttpCode() >= 400) {
737 | throw new ApiException(isset($result['data']) ? $result['data'] : '', $this->getHttpCode());
738 | }
739 | if ($result === null) {
740 | throw new ApiException('Wrong response', $this->getHttpCode());
741 | }
742 |
743 | return new Zcrm($result);
744 | }
745 |
746 | /**
747 | * Get a key for a webrtc widget.
748 | * @param string $sipLogin SIP login or login of PBX extension number
749 | * @return WebrtcKey
750 | * @throws ApiException
751 | */
752 | public function getWebrtcKey($sipLogin)
753 | {
754 | return new WebrtcKey($this->request('webrtc/get_key', ['sip' => $sipLogin]));
755 | }
756 |
757 | /**
758 | * Make request to api with error checking.
759 | *
760 | * @param $method
761 | * @param array $params
762 | * @param string $requestType
763 | * @return array
764 | * @throws ApiException
765 | */
766 | public function request($method, $params = [], $requestType = 'get')
767 | {
768 | $result = $this->call('/' . self::VERSION . '/' . $method . '/', $params, $requestType);
769 |
770 | $result = json_decode($result, true);
771 | if ((!empty($result['status']) && $result['status'] == 'error') || $this->getHttpCode() >= 400) {
772 | throw new ApiException($result['message'], $this->getHttpCode());
773 | }
774 | if ($result === null) {
775 | throw new ApiException('Wrong response', $this->getHttpCode());
776 | }
777 | return $result;
778 | }
779 |
780 | /**
781 | * Filter from non-digit symbols.
782 | *
783 | * @param string $number
784 | * @return string
785 | * @throws ApiException
786 | */
787 | protected static function filterNumber($number)
788 | {
789 | $number = preg_replace('/\D/', '', $number);
790 | if (!$number) {
791 | throw new ApiException('Wrong number format.');
792 | }
793 | return $number;
794 | }
795 |
796 | /**
797 | * Remove null value items from params.
798 | * @param $params
799 | * @return mixed
800 | */
801 | protected static function filterParams($params)
802 | {
803 | foreach ($params as $k => $v) {
804 | if (is_null($v)) {
805 | unset($params[$k]);
806 | }
807 | }
808 | return $params;
809 | }
810 |
811 | /**
812 | * Convert items of array to object of given class name.
813 | *
814 | * @param array $array
815 | * @param string $resultClassName
816 | * @return array
817 | */
818 | protected static function arrayToResultObj($array, $resultClassName)
819 | {
820 | foreach ($array as &$item) {
821 | $item = new $resultClassName($item);
822 | }
823 | return $array;
824 | }
825 | }
826 |
--------------------------------------------------------------------------------
/lib/ApiException.php:
--------------------------------------------------------------------------------
1 | responseBody = $message;
15 | $message = isset($message['error']) ? $message['error'] : '';
16 | }
17 |
18 | parent::__construct($message, $code, $previous);
19 | }
20 |
21 | public function getResponseBody() {
22 | return $this->responseBody;
23 | }
24 | }
--------------------------------------------------------------------------------
/lib/Client.php:
--------------------------------------------------------------------------------
1 | url = $isSandbox ? static::SANDBOX_URL : static::PROD_URL;
26 | $this->key = $key;
27 | $this->secret = $secret;
28 | }
29 |
30 | /**
31 | * @param $method - API method, including version number
32 | * @param array $params - Query params
33 | * @param string $requestType - (get|post|put|delete)
34 | * @param string $format - (json|xml)
35 | *
36 | * @return mixed
37 | * @throws Exception
38 | *
39 | */
40 | public function call($method, $params = [], $requestType = 'get', $format = 'json')
41 | {
42 | if (!is_array($params)) {
43 | throw new ApiException('Query params must be an array.');
44 | }
45 |
46 | $type = strtoupper($requestType);
47 | if (!in_array($type, ['GET', 'POST', 'PUT', 'DELETE'])) {
48 | $type = 'GET';
49 | }
50 | $params['format'] = $format;
51 |
52 | $options = [
53 | CURLOPT_URL => $this->url . $method,
54 | CURLOPT_CUSTOMREQUEST => $type,
55 | CURLOPT_CONNECTTIMEOUT => 10,
56 | CURLOPT_RETURNTRANSFER => true,
57 | CURLOPT_SSL_VERIFYPEER => false,
58 | CURLOPT_SSL_VERIFYHOST => false,
59 | CURLOPT_HEADERFUNCTION => [$this, 'parseHeaders'],
60 | CURLOPT_HTTPHEADER => $this->getAuthHeader($method, $params),
61 | ];
62 |
63 | $ch = curl_init();
64 |
65 | if ($type == 'GET') {
66 | $options[CURLOPT_URL] = $this->url . $method . '?' . $this->httpBuildQuery($params);
67 | } else {
68 | $options[CURLOPT_POST] = true;
69 | if (array_filter($params, 'is_object')) {
70 | $options[CURLOPT_POSTFIELDS] = $params;
71 | } else {
72 | $options[CURLOPT_POSTFIELDS] = $this->httpBuildQuery($params);
73 | }
74 | }
75 |
76 | curl_setopt_array($ch, $options);
77 |
78 | $response = curl_exec($ch);
79 | $error = curl_error($ch);
80 |
81 | $this->httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
82 |
83 | curl_close($ch);
84 |
85 | if ($error) {
86 | throw new ApiException($error);
87 | }
88 |
89 | return $response;
90 | }
91 |
92 | /**
93 | * @return int
94 | */
95 | public function getHttpCode()
96 | {
97 | return $this->httpCode;
98 | }
99 |
100 | /**
101 | * @return array
102 | */
103 | public function getLimits()
104 | {
105 | return $this->limits;
106 | }
107 |
108 | /**
109 | * @param $signatureString
110 | * @return string
111 | */
112 | public function encodeSignature($signatureString)
113 | {
114 | return base64_encode(hash_hmac('sha1', $signatureString, $this->secret));
115 | }
116 |
117 | /**
118 | * @param $method
119 | * @param $params
120 | *
121 | * @return array
122 | */
123 | private function getAuthHeader($method, $params)
124 | {
125 | $params = array_filter($params, function ($a) {
126 | return !is_object($a);
127 | });
128 | ksort($params);
129 | $paramsString = $this->httpBuildQuery($params);
130 | $signature = $this->encodeSignature($method . $paramsString . md5($paramsString));
131 |
132 | return ['Authorization: ' . $this->key . ':' . $signature];
133 | }
134 |
135 | /**
136 | * @param $curl
137 | * @param $line
138 | *
139 | * @return int
140 | */
141 | private function parseHeaders($curl, $line)
142 | {
143 | if (preg_match('/^X-RateLimit-([a-z]+):\s([0-9]+)/i', $line, $match)) {
144 | $this->limits[$match[1]] = (int)$match[2];
145 | }
146 |
147 | return strlen($line);
148 | }
149 |
150 | /**
151 | * Build HTTP query
152 | *
153 | * @param array $params
154 | *
155 | * @return string
156 | */
157 | private function httpBuildQuery($params = [])
158 | {
159 | return http_build_query($params, '', '&', PHP_QUERY_RFC1738);
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/lib/Response/Balance.php:
--------------------------------------------------------------------------------
1 |
20 | * callstart – the call start time;
21 | * clid – CallerID
22 | * destination – the call destination;
23 | * disposition – the call status:
24 | * 'answered' – conversation,
25 | * 'busy' – busy,
26 | * 'cancel' - cancelled,
27 | * 'no answer' - no answer,
28 | * 'failed' - failed,
29 | * 'no money' - no funds, the limit has been exceeded,
30 | * 'unallocated number' - the phone number does not exist,
31 | * 'no limit' - the limit has been exceeded,
32 | * 'no day limit' - the day limit has been exceeded,
33 | * 'line limit' - the line limit has been exceeded,
34 | * 'no money, no limit' - the limit has been exceeded;
35 | * seconds – the amount of seconds;
36 | * is_recorded – (true, false) recorded or no conversations;
37 | * pbx_call_id – permanent ID of the external call to the PBX (does not alter with the scenario changes,
38 | * voice menu, etc., it is displayed in the statistics and notifications);
39 | * @var array
40 | */
41 | public $stats;
42 | }
--------------------------------------------------------------------------------
/lib/Response/PbxStatus.php:
--------------------------------------------------------------------------------
1 | toArray() + ['sandbox' => null]);
10 | foreach ($values as $k => $v) {
11 | $this->$k = $v;
12 | }
13 | }
14 |
15 | public function toArray() {
16 | return get_object_vars($this);
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/lib/Response/Sip.php:
--------------------------------------------------------------------------------
1 |
16 | * sip – SIP-number;
17 | * callstart – the call start time;
18 | * description – description of call destination;
19 | * disposition – the call status:
20 | * 'answered' – conversation,
21 | * 'busy' – busy,
22 | * 'cancel' - cancelled,
23 | * 'no answer' - no answer,
24 | * 'failed' - failed,
25 | * 'no money' - no funds, the limit has been exceeded,
26 | * 'unallocated number' - the phone number does not exist,
27 | * 'no limit' - the limit has been exceeded,
28 | * 'no day limit' - the day limit has been exceeded,
29 | * 'line limit' - the line limit has been exceeded,
30 | * 'no money, no limit' - the limit has been exceeded;
31 | * billseconds – the amount of seconds;
32 | * cost – the cost per minute of calls to this destination;
33 | * billcost – the cost of the paid minutes;
34 | * currency – the cost currency;
35 | * from – which number was used to make a call;
36 | * to – the phone number that was called.
37 | * @var array
38 | */
39 | public $stats;
40 | }
--------------------------------------------------------------------------------
/lib/Response/Tariff.php:
--------------------------------------------------------------------------------
1 | caller_id.$this->destination.$this->call_start;
26 | }
27 | }
--------------------------------------------------------------------------------
/lib/Webhook/NotifyEnd.php:
--------------------------------------------------------------------------------
1 | caller_id.$this->called_did.$this->call_start;
42 | }
43 | }
--------------------------------------------------------------------------------
/lib/Webhook/NotifyInternal.php:
--------------------------------------------------------------------------------
1 | caller_id.$this->called_did.$this->call_start;
26 | }
27 | }
--------------------------------------------------------------------------------
/lib/Webhook/NotifyIvr.php:
--------------------------------------------------------------------------------
1 | wait_dtmf = !empty($this->wait_dtmf) ? new WaitDtmf($this->wait_dtmf) : null;
19 | }
20 | }
--------------------------------------------------------------------------------
/lib/Webhook/NotifyOutEnd.php:
--------------------------------------------------------------------------------
1 | internal.$this->destination.$this->call_start;
42 | }
43 | }
--------------------------------------------------------------------------------
/lib/Webhook/NotifyOutStart.php:
--------------------------------------------------------------------------------
1 | internal.$this->destination.$this->call_start;
23 | }
24 | }
--------------------------------------------------------------------------------
/lib/Webhook/NotifyRecord.php:
--------------------------------------------------------------------------------
1 | pbx_call_id.$this->call_id_with_rec;
16 | }
17 | }
--------------------------------------------------------------------------------
/lib/Webhook/NotifyStart.php:
--------------------------------------------------------------------------------
1 | caller_id.$this->called_did.$this->call_start;
23 | }
24 | }
--------------------------------------------------------------------------------
/lib/Webhook/Request.php:
--------------------------------------------------------------------------------
1 | data['ivr_play'] = $id;
19 | return $this;
20 | }
21 |
22 | public function setIvrSayPopular($number, $language)
23 | {
24 | $this->data['ivr_saypopular'] = (int)$number;
25 | return $this->setLanguage($language);
26 | }
27 |
28 | public function setIvrSayDigits($number, $language)
29 | {
30 | $this->data['ivr_saydigits'] = (int)$number;
31 | return $this->setLanguage($language);
32 | }
33 |
34 | public function setIvrSayNumber($number, $language)
35 | {
36 | $this->data['ivr_saynumber'] = (int)$number;
37 | return $this->setLanguage($language);
38 | }
39 |
40 | public function setWaitDtmf($timeout, $attempts, $maxdigits, $name, $default)
41 | {
42 | $this->data['wait_dtmf'] = [
43 | 'timeout' => (int)$timeout,
44 | 'attempts' => (int)$attempts,
45 | 'maxdigits' => (int)$maxdigits,
46 | 'name' => $name,
47 | 'default' => $default,
48 | ];
49 | return $this;
50 | }
51 |
52 | public function setRedirect($redirect, $returnTimeout, array $extraOptions = [])
53 | {
54 | $this->data['redirect'] = $redirect;
55 | $this->data['return_timeout'] = (int)$returnTimeout;
56 | if (!empty($extraOptions['rewrite_forward_number'])) {
57 | $number = (string)$extraOptions['rewrite_forward_number'];
58 | if (!preg_match('/^(\+*\d{5,})$/', $number)) {
59 | throw new \BadMethodCallException("Wrong 'rewrite_forward_number' extra option value.");
60 | }
61 | $this->data['rewrite_forward_number'] = $number;
62 | }
63 | return $this;
64 | }
65 |
66 | public function setHangup()
67 | {
68 | $this->data['hangup'] = 1;
69 | return $this;
70 | }
71 |
72 | public function setCallerName($name)
73 | {
74 | $this->data['caller_name'] = $name;
75 | return $this;
76 | }
77 |
78 | /**
79 | * @param string $language one of values returned by getSupportedLanguages() method
80 | * @return $this
81 | */
82 | public function setLanguage($language)
83 | {
84 | if (!in_array($language, self::getSupportedLanguages())) {
85 | throw new \BadMethodCallException('Wrong language.');
86 | }
87 | $this->data['language'] = $language;
88 | return $this;
89 | }
90 |
91 | /**
92 | * Validate data prepared for send and return it or sends it and terminate script.
93 | * @param bool $return
94 | * @return string
95 | */
96 | public function send($return = false)
97 | {
98 | $result = json_encode($this->data);
99 | if ($return) {
100 | return $result;
101 | } else {
102 | echo $result;
103 | exit;
104 | }
105 | }
106 | }
--------------------------------------------------------------------------------
/lib/Webhook/WaitDtmf.php:
--------------------------------------------------------------------------------
1 |