├── .gitignore ├── README.md ├── composer.json ├── docs ├── README.md ├── admin.md └── agent.md ├── example ├── admin │ ├── moh_list.php │ └── version.php └── update_fileds.php ├── phpstan.neon.dist ├── phpunit.xml.dist ├── rector.php ├── src ├── Client.php ├── Contracts │ ├── AdminContract.php │ ├── AgentContract.php │ ├── MetaInformationContract.php │ ├── ResponseContract.php │ ├── StringableContract.php │ └── TransporterContract.php ├── Enums │ └── Transporter │ │ ├── ContentType.php │ │ └── Method.php ├── Exceptions │ ├── ErrorException.php │ ├── InvalidArgumentException.php │ ├── InvalidIpException.php │ ├── InvalidUrlException.php │ ├── TransporterException.php │ └── UnserializableResponse.php ├── Factory.php ├── Resources │ ├── Admin.php │ ├── Agent.php │ ├── Concerns │ │ ├── Streamable.php │ │ └── Transportable.php │ └── RemoteAgent.php ├── Responses │ ├── Concerns │ │ ├── ArrayAccessible.php │ │ └── HasMetaInformation.php │ └── StreamResponse.php ├── Transporters │ └── HttpTransporter.php ├── ValueObjects │ ├── ApiKey.php │ ├── BasicAuth.php │ ├── Parameter.php │ ├── ResourceUri.php │ └── Transporter │ │ ├── BaseUri.php │ │ ├── Headers.php │ │ ├── Payload.php │ │ ├── QueryParams.php │ │ └── Response.php └── VicidialApi.php └── tests ├── ClientTest.php ├── FactoryTest.php ├── Fakers ├── FakeGuzzleClient.php ├── FakeGuzzleClientException.php └── FakeHttpTransporter.php ├── Resources └── AgentTest.php ├── TestCase.php └── VicidialAPiTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | composer.lock 3 | .idea/ 4 | test-coverage/ 5 | coverage.xml 6 | .phpunit.result.cache 7 | build 8 | example/.env 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vicidial API PHP WRAPPER 2 | 3 | Beautiful and simple Implementation to integrate Vicidial API 4 | 5 | DISCLAIMER: VICIdial is a registered trademark of the Vicidial Group which i am not related in anyway. 6 | 7 | VICIDIAL is a software suite that is designed to interact with the Asterisk Open-Source PBX Phone system to act as a complete inbound/outbound contact center suite with inbound email support as well. 8 | 9 | http://www.vicidial.org/vicidial.php 10 | 11 | Vicidial has an AGENT API and NON AGENT API, this classes are intended to make it easier to use in PHP 12 | 13 | - http://vicidial.org/docs/NON-AGENT_API.txt 14 | - http://vicidial.org/docs/AGENT_API.txt 15 | 16 | ## Install 17 | Requires PHP 8.1 18 | 19 | `composer require masterfermin02/vicidial-api-wrapper` 20 | 21 | ### For PHP 7.4+ must install this version 22 | 23 | `composer require masterfermin02/vicidial-api-wrapper:1.0.3` 24 | 25 | ## How to use it 26 | Example 1: Update fields on agent screen 27 | ```php 28 | 29 | agent(); 41 | echo $agentApi->updateFields("gabriel", $fields); 42 | } catch (Exception $e) { 43 | echo 'Exception: ', $e->getMessage(), "\n"; 44 | } 45 | 46 | ``` 47 | 48 | Example 2: Hangup Call, Dispo it and Pause Agent 49 | ```php 50 | 51 | agent(); 59 | $agentApi->pause("gabriel", "PAUSE"); 60 | $agentApi->hangup("gabriel"); 61 | $agentApi->dispo("gabriel", ['value' => 'SALE']); 62 | $agentApi->pauseCode("gabriel", "BREAK"); 63 | } catch (Exception $e) { 64 | echo 'Exception: ', $e->getMessage(), "\n"; 65 | } 66 | 67 | ``` 68 | 69 | Example 3: Update fields on agent screen 70 | ```php 71 | agent(); 83 | echo $agentApi->updateFields("gabriel", $fields); 84 | } catch (Exception $e) { 85 | echo 'Exception: ', $e->getMessage(), "\n"; 86 | } 87 | 88 | ``` 89 | 90 | ### Vicidial admin or No agent api 91 | ```php 92 | admin(); 102 | echo $agentApi->mohList([ 103 | 'format' => 'selectframe', 104 | 'comments' => 'fieldname', 105 | 'stage' => 'date' 106 | ]); 107 | } catch (Exception $e) { 108 | echo 'Exception: ', $e->getMessage(), "\n"; 109 | } 110 | ``` 111 | 112 | Url encode 113 | ```php 114 | admin(); 131 | echo $agentApi 132 | ->withUrlEncode(true) 133 | ->addLead($fields); 134 | } catch (Exception $e) { 135 | echo 'Exception: ', $e->getMessage(), "\n"; 136 | } 137 | ``` 138 | 139 | Login remote agent 140 | 141 | ```php 142 | remoteAgent(); 154 | $remoteAgent->active( 155 | getenv('agentId'), 156 | getenv('confExten'), 157 | ); 158 | $remoteAgent->hangUp( 159 | "gabriel", 160 | [ 161 | 'status' => 'SALE', 162 | ] 163 | ] 164 | ); 165 | $remoteAgent->inActive( 166 | getenv('agentId'), 167 | getenv('confExten'), 168 | ); 169 | } catch (Exception $e) { 170 | echo 'Exception: ', $e->getMessage(), "\n"; 171 | } 172 | ``` 173 | 174 | 175 | ### Docs: 176 | - [Agent](https://github.com/masterfermin02/vicidial-api-wrapper/blob/main/docs/agent.md) 177 | - [Admin](https://github.com/masterfermin02/vicidial-api-wrapper/blob/main/docs/admin.md) 178 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "masterfermin02/vicidial-api-wrapper", 3 | "description": "Beautiful and simple Implementation to integrate Vicidial API", 4 | "keywords": [ 5 | "vicidial", 6 | "api", 7 | "wrapper", 8 | "php" 9 | ], 10 | "homepage": "https://github.com/masterfermin02/vicidial-api-wrapper", 11 | "license": "BSD-3-Clause", 12 | "authors": [ 13 | { 14 | "name": "Fermin Perdomo", 15 | "email": "masterfermin02@gmail.com" 16 | } 17 | ], 18 | "require": { 19 | "php": "^8.1", 20 | "graham-campbell/guzzle-factory": "^5.0", 21 | "ext-json": "*", 22 | "php-http/discovery": "^1.19", 23 | "php-http/multipart-stream-builder": "^1.3", 24 | "psr/http-client": "^1.0", 25 | "psr/http-client-implementation": "*", 26 | "psr/http-factory-implementation": "*", 27 | "psr/http-message": "^1.1" 28 | }, 29 | "require-dev": { 30 | "phpunit/phpunit": "~9", 31 | "squizlabs/php_codesniffer": "~3.0", 32 | "vlucas/phpdotenv": "^5.5", 33 | "guzzlehttp/guzzle": "^7.5", 34 | "guzzlehttp/psr7": "^2.6", 35 | "laravel/pint": "^1.13", 36 | "nunomaduro/collision": "^7.10", 37 | "phpstan/phpstan": "^1.10", 38 | "rector/rector": "^0.18.8", 39 | "symfony/var-dumper": "^6.3" 40 | }, 41 | "extra": { 42 | "branch-alias": { 43 | "dev-master": "1.0-dev" 44 | } 45 | }, 46 | "autoload": { 47 | "psr-4": { 48 | "VicidialApi\\": "src/" 49 | }, 50 | "files": [ 51 | "src/VicidialApi.php" 52 | ] 53 | }, 54 | "autoload-dev": { 55 | "psr-4": { 56 | "Test\\": "tests/" 57 | } 58 | }, 59 | "scripts": { 60 | "lint": "pint -v", 61 | "refactor": "rector --debug", 62 | "test:lint": "pint --test -v", 63 | "test:refactor": "rector --dry-run", 64 | "test:types": "phpstan analyse --ansi", 65 | "test:unit": "vendor/bin/phpunit", 66 | "test": [ 67 | "@test:lint", 68 | "@test:refactor", 69 | "@test:types", 70 | "@test:unit" 71 | ] 72 | }, 73 | "config": { 74 | "allow-plugins": { 75 | "php-http/discovery": true 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | ### Docs: 2 | - [Agent](https://github.com/masterfermin02/vicidial-api-wrapper/blob/main/docs/agent.md) 3 | - [Admin](https://github.com/masterfermin02/vicidial-api-wrapper/blob/main/docs/admin.md) 4 | -------------------------------------------------------------------------------- /docs/agent.md: -------------------------------------------------------------------------------- 1 | ### Agent API functions: 2 | - [version](#version) - shows version and build of the API, along with the date/time 3 | - [external_hangup](#external_hangup) - sends command to hangup the current phone call for one specific agent(Hangup Customer) 4 | - [external_status](#external_status) - sends command to set the disposition for one specific agent and move on to next call 5 | - [external_pause](#external_pause) - sends command to pause/resume an agent now if not on a call, or pause after their next call if on call 6 | - [external_dial](#external_dial) - sends command to manually dial a number on the agent's screen 7 | - [preview_dial_action](#preview_dial_action) - sends a SKIP, DIALONLY, ALTDIAL, ADR3DIAL or FINISH when a lead is being previewed or manual alt dial 8 | - [external_add_lead](#external_add_lead) - Adds a lead in the manual dial list of the campaign for logged-in agent 9 | - [change_ingroups](#change_ingroups) - changes the selected in-groups for a logged-in agent 10 | - [update_fields](#update_fields) - changes values for selected data fields in the agent interface 11 | - [set_timer_action](#set_timer_action) - sets timer action for the current call the agent is on 12 | - [st_login_log](#st_login_log) - looks up the vicidial_users.custom_three field and logs event from CRM 13 | - [st_get_agent_active_lead](#st_get_agent_active_lead) - looks up active lead info for an agent and outputs lead information 14 | - [ra_call_control](#ra_call_control) - remote agent call control: hangup/transfer calls being handled by remote agents 15 | - [send_dtmf](#send_dtmf) - sends dtmf signal string to agent's session 16 | - [transfer_conference](#transfer_conference) - sends several commands related to the agent transfer-conf frame 17 | - [park_call](#park_call) - sends command to park customer or grab customer from park or ivr 18 | - [logout](#logout) - logs the agent out of the agent interface 19 | - [recording](#recording) - sends a recording start/stop signal or status of agent recording 20 | - [webserver](#webserver) - display webserver information, very useful for load balanced setups 21 | - [webphone_url ](#webphone_url)- display the webphone url for the current agent's session 22 | - [call_agent](#call_agent) - send a call to connect the agent to their session 23 | - [pause_code](#pause_code) - set a pause code if the agent is paused 24 | - [audio_playback](#audio_playback) - basic play/pause/resume/stop/restart audio in agent session 25 | - [switch_lead](#switch_lead) - for inbound calls, switches lead_id of live inbound call on agent screen 26 | - [calls_in_queue_count](#calls_in_queue_count) - display a count of the calls waiting in queue for the specific agent 27 | - [force_fronter_leave_3way](#force_fronter_leave_3way) - will send a command to fronter agent to leave-3way call that executing agent is on 28 | - [force_fronter_audio_stop](#force_fronter_audio_stop)- will send a command to fronter agent session to stop any audio_playback playing on it 29 | - [vm_message](#vm_message) - set a custom voicemail message to be played when agent clicks the VM button on the agent screen 30 | 31 | 32 | ### Required variables for all API calls: 33 | - user - is the API user 34 | - pass - is the API user password 35 | - agent_user - is the vicidial agent user whose session that you want to affect 36 | - source - description of what originated the API call (maximum 20 characters) default (test) 37 | - hasSSl - Tell the client if use http or https default (true) 38 | 39 | ```php 40 | agent(); 43 | ``` 44 | 45 | #### Example 46 | To hangup the call, disposition it and then pause the agent, do the following in order: 47 | 48 | ```php 49 | agent(); 53 | $agent_user = '1000'; 54 | $vicidialAPI->pause($agent_user, "PAUSE"); 55 | $vicidialAPI->hangup($agent_user); 56 | $vicidialAPI->dispo($agent_user, ['value' => 'SALE']); 57 | $vicidialAPI->pauseCode($agent_user, "BREAK"); 58 | } catch (Exception $e) { 59 | echo 'Exception: ', $e->getMessage(), "\n"; 60 | } 61 | ``` 62 | 63 | Response to calls will return either an ERROR or a SUCCESS along with an explanation. 64 | for example: 65 | ``` 66 | SUCCESS: external_status function set - 6666|A 67 | ERROR: agent_user is not logged in - 6666 68 | ERROR: auth USER DOES NOT HAVE PERMISSION TO USE THIS FUNCTION - 6666|webserver|ADMIN 69 | ``` 70 | 71 | 72 | DETAIL OF EACH FUNCTION: 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- 77 | [↑ Top](#agent-api-functions) 78 | 79 | version 80 | --- 81 | 82 | DESCRIPTION: 83 | shows version and build of the API, along with the date/time 84 | 85 | RESPONSES: 86 | ``` 87 | VERSION: 2.0.5-2|BUILD: 90116-1229|DATE: 2009-01-15 14:59:33|EPOCH: 1222020803 88 | ``` 89 | Code: 90 | ```php 91 | 92 | agent(); 96 | echo $vicidialAPI->version(); // VERSION: 2.0.5-2|BUILD: 90116-1229|DATE: 2009-01-15 14:59:33|EPOCH: 1222020803 97 | } catch (Exception $e) { 98 | echo 'Exception: ', $e->getMessage(), "\n"; 99 | } 100 | 101 | ``` 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- 106 | [↑ Top](#agent-api-functions) 107 | 108 | webserver 109 | --- 110 | 111 | DESCRIPTION: 112 | shows version and build of the API, along with the date/time 113 | 114 | RESPONSES: 115 | ``` 116 | Webserver Data: 117 | set.timezone: America/New_York 118 | abbr.timezone: EDT 119 | dst.timezone: 1 120 | uname: Linux dev-db 2.6.34.8-0.2-default #1 SMP 2011-04-06 18:11:26 +0200 x86_64 121 | host name: dev-db 122 | server name: www.vicidial.org 123 | php version: 5.3.3 124 | apache version: Apache/2.2.15 (Linux/SUSE) 125 | apache processes: 13 126 | system loadavg: 0.06 127 | disk_free_space: 444174315520 128 | date.timezone: America/New_York 129 | max_execution_time: 360 130 | max_input_time: 360 131 | memory_limit: 128M 132 | post_max_size: 48M 133 | upload_max_filesize: 42M 134 | default_socket_timeout: 360 135 | ``` 136 | Code: 137 | ```php 138 | 139 | agent(); 144 | echo $vicidialAPI->webserver(); 145 | } catch (Exception $e) { 146 | echo 'Exception: ', $e->getMessage(), "\n"; 147 | } 148 | 149 | ``` 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- 154 | [↑ Top](#agent-api-functions) 155 | 156 | external_hangup 157 | --- 158 | 159 | DESCRIPTION: 160 | Hangs up the current customer call on the agent screen 161 | 162 | RESPONSES: 163 | ERROR: external_hangup not valid - 1|6666 164 | ERROR: no user found - 6666 165 | ERROR: agent_user is not logged in - 6666 166 | SUCCESS: external_hangup function set - 1|6666 167 | 168 | ```php 169 | 170 | agent(); 174 | echo $vicidialAPI->hangup("agent_name"); 175 | } catch (Exception $e) { 176 | echo 'Exception: ', $e->getMessage(), "\n"; 177 | } 178 | 179 | ``` 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- 184 | [↑ Top](#agent-api-functions) 185 | 186 | external_status 187 | --- 188 | 189 | DESCRIPTION: 190 | Sets the status of the current customer call on the agent dispotion screen 191 | 192 | VALUES: (value) 193 | - value - 194 | Any valid status in the VICIDIAL system will work for this function 195 | - callback_datetime - 196 | YYYY-MM-DD+HH:MM:SS, date and time of scheduled callback. REQUIRED if callback is set and status is flagged as a scheduled callback 197 | - callback_type - 198 | USERONLY or ANYONE, default is ANYONE 199 | - callback_comments - 200 | Optional comments to appear when the callback is called back, must be less than 200 characters in length 201 | - qm_dispo_code - 202 | Option callstatus code used if QM is enabled 203 | callback_type=USERONLY&callback_comments=callback+comments+go+here&qm_dispo_code=1234 204 | 205 | Code: 206 | ```php 207 | 208 | agent(); 212 | echo $vicidialAPI->dispo("agent_user",[ 213 | 'value' => 'A' 214 | ]); 215 | } catch (Exception $e) { 216 | echo 'Exception: ', $e->getMessage(), "\n"; 217 | } 218 | 219 | try { 220 | $vicidialAPI = VicidialApi::create("127.0.0.1", "6666", "123")->agent(); 221 | echo $vicidialAPI->dispo("agent_user",[ 222 | 'value' => 'CALLBK', 223 | 'callback_datetime' => '2012-01-25+12:00:00', 224 | 'callback_type' => 'USERONLY', 225 | 'callback_comments' => 'callback+comments+go+here', 226 | 'qm_dispo_code' => 123 227 | ]); 228 | } catch (Exception $e) { 229 | echo 'Exception: ', $e->getMessage(), "\n"; 230 | } 231 | 232 | ``` 233 | 234 | [↑ Top](#agent-api-functions) 235 | 236 | logout 237 | --- 238 | 239 | DESCRIPTION: 240 | Logs the agent out of the agent interface. If the agent is on a live call, will logout after the live call is dispositioned 241 | 242 | VALUES: (value) 243 | - LOGOUT - Logout the agent session 244 | 245 | RESPONSES: 246 | ``` 247 | ERROR: external_status not valid - A|6666 248 | ERROR: no user found - 6666 249 | ERROR: agent_user is not logged in - 6666 250 | SUCCESS: external_status function set - A|6666 251 | ``` 252 | 253 | Code: 254 | ```php 255 | 256 | agent(); 260 | echo $vicidialAPI->logout("agent_user"); 261 | } catch (Exception $e) { 262 | echo 'Exception: ', $e->getMessage(), "\n"; 263 | } 264 | 265 | ``` 266 | 267 | 268 | -------------------------------------------------------------------------------- 269 | [↑ Top](#agent-api-functions) 270 | 271 | external_pause 272 | --- 273 | 274 | DESCRIPTION: 275 | Pauses or Resumes the agent. If a Pause and the agent is on a live call will pause after the live call is dispositioned 276 | 277 | VALUES: (value) 278 | - PAUSE - Pauses the agent session 279 | - RESUME - Resumes the agent session 280 | 281 | RESPONSES: 282 | ``` 283 | ERROR: external_pause not valid - PAUSE|6666 284 | ERROR: no user found - 6666 285 | ERROR: agent_user is not logged in - 6666 286 | SUCCESS: external_pause function set - PAUSE|1232020456|6666 287 | ``` 288 | 289 | Code: 290 | 291 | ```php 292 | 293 | agent(); 297 | $agent_user = '1000'; 298 | $vicidialAPI->pause($agent_user, "PAUSE"); 299 | } catch (Exception $e) { 300 | echo 'Exception: ', $e->getMessage(), "\n"; 301 | } 302 | 303 | ``` 304 | 305 | -------------------------------------------------------------------------------- 306 | [↑ Top](#agent-api-functions) 307 | 308 | external_dial 309 | --- 310 | 311 | DESCRIPTION: 312 | 313 |

Places a manual dial phone call on the agent screen, you can define whether to search for the lead in the existing database or not and you can define the phone_code and the number to dial. This action will pause the agent after their current call, enter in the information to place the call, and dialing the call on the agent screen.

314 | 315 | VALUES: 316 | ``` 317 | value - 318 | Any valid phone number (7275551212), or "MANUALNEXT" to mimic the Dial Next Number button 319 | lead_id - 320 | Any valid lead_id from the system(either value or lead_id are required) if both are defined, lead_id will override value 321 | phone_code - 322 | Any valid phone country code (1 for USA/Canada, 44 for UK, etc...) 323 | search - 324 | YES - perform a search in the campaign-defined vicidial_list list for this phone number and bring up that lead 325 | NO - do not search, create a new vicidial_list record for the call 326 | preview - 327 | YES - preview the lead in the vicidial screen without dialing 328 | NO - do not preview the lead, place call immediately 329 | focus - 330 | YES - change the focus of the screen to the vicidial.php agent interface, brings up an alert in the browser window 331 | NO - do not change focus 332 | vendor_id - 333 | OPTIONAL, any valid Vendor lead code 334 | dial_prefix - 335 | OPTIONAL, any dial prefix that you want to add to the beginning of the dial string for this call 336 | group_alias - 337 | OPTIONAL, the outbound callerID(from an existing group-alias) that you want to use for this call 338 | vtiger_callback - 339 | OPTIONAL, YES or NO, will lookup the phone number and Vtiger account ID from the provided Event ID 340 | alt_user - 341 | OPTIONAL, instead of agent_user, this is to lookup the agent_user using the vicidial_users.custom_three field 342 | alt_dial - 343 | OPTIONAL, if using lead_id you can set this flag to dial the ALT number or the ADDR3 number or SEARCH a phone_number within the lead 344 | if SEARCH is used and the phone_number is not matched with the lead's phone_number, alt_phone or address3 field 345 | an ERROR will be returned 346 | dial_ingroup - 347 | OPTIONAL, place the call as an in-group outbound calls 348 | outbound_cid - 349 | OPTIONAL, the CallerID to send for this outbound call. NOTE: This will only work if "Outbound Call Any CID" is enabled in System Settings! 350 | ``` 351 | 352 | RESPONSES: 353 | ``` 354 | NOTICE: defined dial_ingroup not found - FAKE_INGROUP 355 | ERROR: external_dial not valid - 7275551212|1|YES|6666 356 | ERROR: no user found - 6666 357 | ERROR: agent_user is not logged in - 6666 358 | ERROR: agent_user is not allowed to place manual dial calls - 6666 359 | ERROR: caller_id_number from group_alias is not valid - 6666|TESTING|123 360 | ERROR: group_alias is not valid - 6666|TESTING 361 | ERROR: outbound_cid is not allowed on this system - 6666|3125551212|DISABLED 362 | ERROR: vtiger callback activity does not exist in vtiger system - 12345 363 | ERROR: phone_number is already in this agents manual dial queue - 6666|7275551211 364 | ERROR: lead_id is not valid - 6666|1234567 365 | ERROR: phone number is not valid - 6666||1234567| 366 | ERROR: phone number lead_id search not found - 6666|7275551212|1234567| 367 | SUCCESS: external_dial function set - 7275551212|6666|1|YES|NO|YES|123456|1232020456|9|TESTING|7275551211| 368 | ``` 369 | 370 | Next dial example: 371 | Code: 372 | ```php 373 | agent(); 377 | $agent_user = '1000'; 378 | $vicidialAPI->dial($agent_user, [ 379 | 'phone_number' => 'MANUALNEXT', 380 | 'phone_code' => '1' 381 | ]); 382 | } catch (Exception $e) { 383 | echo 'Exception: ', $e->getMessage(), "\n"; 384 | } 385 | 386 | ``` 387 | 388 | Manual dial example: 389 | ```php 390 | agent(); 394 | $agent_user = '1000'; 395 | $vicidialAPI->dial($agent_user, [ 396 | 'phone_number' => 7275551212, 397 | 'phone_code' => '1' 398 | ]); 399 | } catch (Exception $e) { 400 | echo 'Exception: ', $e->getMessage(), "\n"; 401 | } 402 | 403 | ``` 404 | 405 | -------------------------------------------------------------------------------- 406 | [↑ Top](#agent-api-functions) 407 | 408 | preview_dial_action 409 | --- 410 | 411 | DESCRIPTION: 412 | sends a SKIP, DIALONLY, ALTDIAL, ADR3DIAL or FINISH when a lead is being previewed or in Manual Alt Dial 413 | 414 | VALUES: 415 | - value - 416 | One of the following actions (SKIP, DIALONLY, ALTDIAL, ADR3DIAL or FINISH) 417 | 418 | RESPONSES: 419 | ``` 420 | ERROR: preview_dial_action not valid - 7275551212|1|YES|6666 421 | ERROR: no user found - 6666 422 | ERROR: agent_user is not logged in - 6666 423 | ERROR: agent_user is not allowed to place manual dial calls - 6666 424 | ERROR: preview dialing not allowed on this campaign - 6666|TESTING|DISABLED 425 | ERROR: preview dial skipping not allowed on this campaign - 6666|TESTING|PREVIEW_ONLY 426 | ERROR: alt number dialing not allowed on this campaign - 6666|TESTING|N 427 | SUCCESS: preview_dial_action function set - DIALONLY|6666|DIALONLY 428 | ``` 429 | 430 | Code: 431 | 432 | ```php 433 | agent(); 438 | $agent_user = '1000'; 439 | $vicidialAPI->previewDial($agent_user, 'SKIP'); 440 | } catch (Exception $e) { 441 | echo 'Exception: ', $e->getMessage(), "\n"; 442 | } 443 | 444 | ``` 445 | 446 | 447 | 448 | 449 | 450 | -------------------------------------------------------------------------------- 451 | [↑ Top](#agent-api-functions) 452 | 453 | external_add_lead 454 | --- 455 | 456 | DESCRIPTION: 457 | 458 | Adds a lead in the manual dial list of the campaign for logged-in agent. A much simplified add lead function compared to the Non-Agent API function 459 | 460 | VALUES: 461 | ``` 462 | dnc_check - 463 | OPTIONAL - Check for number against system DNC 464 | campaign_dnc_check - 465 | OPTIONAL - Check for number against campaign DNC from the agent's campaign 466 | LEAD DATA (must populate at least one) 467 | NOTE: Only fields that are specified in the API call will be modified 468 | address1 469 | address2 470 | address3 471 | alt_phone 472 | city 473 | comments 474 | country_code 475 | date_of_birth 476 | email 477 | first_name 478 | gender 479 | gmt_offset_now 480 | last_name 481 | middle_initial 482 | phone_number 483 | phone_code 484 | postal_code 485 | province 486 | security_phrase 487 | source_id 488 | state 489 | title 490 | vendor_lead_code 491 | rank 492 | owner 493 | ``` 494 | RESPONSES: 495 | ``` 496 | ERROR: external_add_lead not valid - 7275551212|1|6666| 497 | ERROR: no user found - 6666 498 | ERROR: lead insertion failed - 7275551212|TESTCAMP|101|6666 499 | ERROR: add_lead PHONE NUMBER IN DNC - 7275551212|6666 500 | ERROR: add_lead PHONE NUMBER IN CAMPAIGN DNC - 7275551212|TESTCAMP|6666 501 | ERROR: campaign manual dial list undefined - 7275551212|TESTCAMP|6666 502 | ERROR: agent_user is not logged in - 6666 503 | SUCCESS: lead added - 7275551212|TESTCAMP|101|123456|6666 504 | ``` 505 | 506 | Code: 507 | 508 | ```php 509 | agent(); 513 | $agent_user = '1000'; 514 | $vicidialAPI->addLead($agent_user, [ 515 | 'phone_number' => 7275551212, 516 | 'phone_code' => 1, 517 | 'first_name' => 'Bob', 518 | 'last_name' => 'Smith', 519 | 'dnc_check' => 'YES' 520 | ]); 521 | } catch (Exception $e) { 522 | echo 'Exception: ', $e->getMessage(), "\n"; 523 | } 524 | 525 | ``` 526 | 527 | 528 | -------------------------------------------------------------------------------- 529 | [↑ Top](#agent-api-functions) 530 | 531 | change_ingroups 532 | --- 533 | 534 | DESCRIPTION: 535 | 536 | This function will change the selected in-groups for an agent that is logged into a campaign that allows for inbound calls to be handled. Allows the selected in-groups for an agent to be changed while they are logged-in to the ViciDial Agent screen only. Once changed in this way, the agent would need to log out and back in to be able to select in-groups themselves(If Agent Choose In-Groups is enabled for that user). The blended checkbox can also be changed using this function. The API user performing this function must have vicidial_users.change_agent_campaign = 1. 537 | 538 | VALUES: 539 | ``` 540 | value - 541 | CHANGE - will change all in-groups to those defined in ingroup_choices 542 | REMOVE - will only remove the listed in-groups 543 | ADD - will only add the listed in-groups 544 | blended - 545 | YES - set the agent to take outbound auto-dialed calls (not applicable in MANUAL and INBOUND_MAN dial method campaigns) 546 | NO - set the agent to only take inbound calls 547 | ingroup_choices - 548 | OPTIONAL, a space-delimited(use plusses + in the URL) list of in-groups to allow the agent to take calls from, example: " TEST_IN2 SALESLINE TRAINING_IN -" 549 | set_as_default - 550 | OPTIONAL, YES or NO - overwrites the settings for the agent in the user modification screen, default is NO 551 | ``` 552 | 553 | RESPONSES: 554 | ``` 555 | ERROR: change_ingroups not valid - N| TEST_IN SALESLINE - 556 | ERROR: agent_user is not logged in - 6666 557 | ERROR: campaign does not allow inbound calls - 6666 558 | ERROR: user is not allowed to change agent in-groups - 6666|TESTING|123 559 | ERROR: campaign dial_method does not allow outbound autodial - 6666|TESTING 560 | ERROR: ingroup does not exist - FAKE_IN| TEST_IN FAKE_IN SALESLINE - 561 | ERROR: ingroup_choices are required for ADD and REMOVE values - ADD| 562 | SUCCESS: change_ingroups function set - YES| TEST_IN SALESLINE -|6666 563 | ``` 564 | 565 | Code: 566 | 567 | ```php 568 | agent(); 572 | $agent_user = '1000'; 573 | $vicidialAPI->changeIngroups($agent_user, [ 574 | 'value' => 'REMOVE', 575 | 'blended' => 'NO', 576 | 'ingroup_choices' => '+TEST_IN2+TEST_IN4+-' 577 | ]); 578 | } catch (Exception $e) { 579 | echo 'Exception: ', $e->getMessage(), "\n"; 580 | } 581 | 582 | ``` 583 | 584 | -------------------------------------------------------------------------------- 585 | [↑ Top](#agent-api-functions) 586 | 587 | update_fields 588 | --- 589 | 590 | DESCRIPTION: 591 | 592 | Updates the fields that are specified with the values. This will update the data that is on the agent's screen in the customer information section. 593 | 594 | VALUES: 595 | ``` 596 | agent_user - 597 | REQUIRED alphanumeric string for agent user 598 | LEAD DATA (must populate at least one) 599 | NOTE: Only fields that are specified in the API call will be modified 600 | address1 601 | address2 602 | address3 603 | alt_phone 604 | city 605 | comments 606 | country_code 607 | date_of_birth 608 | email 609 | first_name 610 | gender 611 | gmt_offset_now 612 | last_name 613 | middle_initial 614 | phone_number 615 | phone_code 616 | postal_code 617 | province 618 | security_phrase 619 | source_id 620 | state 621 | title 622 | vendor_lead_code 623 | rank 624 | owner 625 | 626 | NOTES: 627 | - most special characters are not allowed, but single quotes are 628 | ``` 629 | 630 | RESPONSES: 631 | ``` 632 | ERROR: update_fields not valid - 6666 633 | ERROR: agent_user is not logged in - 6666 634 | ERROR: user is not allowed to modify lead information - 6666|1234 635 | ERROR: agent_user does not have a lead on their screen - 6666|1234 636 | ERROR: no fields have been defined - 6666 637 | SUCCESS: update_fields lead updated - 6666|1234|87498|vendor_lead_code='1234567',address1='' 638 | ``` 639 | 640 | Code: 641 | 642 | ```php 643 | agent(); 649 | $agent_user = '1000'; 650 | $vicidialAPI->updateFields($agent_user, [ 651 | 'vendor_lead_code' => '1234567', 652 | 'address1' => '' 653 | ]); 654 | } catch (Exception $e) { 655 | echo 'Exception: ', $e->getMessage(), "\n"; 656 | } 657 | 658 | ``` 659 | 660 | 661 | 662 | 663 | 664 | -------------------------------------------------------------------------------- 665 | [↑ Top](#agent-api-functions) 666 | 667 | set_timer_action 668 | --- 669 | 670 | DESCRIPTION: 671 | 672 | Updates the fields that are specified with the values. This will update the data that is on the agent's screen in the customer information section. 673 | 674 | VALUES: 675 | ``` 676 | agent_user - 677 | REQUIRED, alphanumeric string for agent user 678 | value - 679 | REQUIRED, one of these choices: 'NONE','WEBFORM','WEBFORM2','D1_DIAL','D2_DIAL','D3_DIAL','D4_DIAL','D5_DIAL','MESSAGE_ONLY' 680 | notes - 681 | Optional, the message to be displayed with the timer action 682 | rank - 683 | Optional, the number of seconds into the call to display 684 | ``` 685 | 686 | RESPONSES: 687 | ``` 688 | ERROR: set_timer_action not valid - 6666 689 | ERROR: agent_user is not logged in - 6666 690 | ERROR: user is not allowed to modify campaign settings - 6666|1234 691 | SUCCESS: set_timer_action lead updated - 6666|1234|MESSAGE_ONLY|test message|15 692 | ``` 693 | 694 | Code: 695 | 696 | ```php 697 | agent(); 703 | $agent_user = '1000'; 704 | $vicidialAPI->setTimerAction($agent_user, [ 705 | 'value' => 'MESSAGE_ONLY', 706 | 'notes' => 'test+message', 707 | 'rank' => '15' 708 | ]); 709 | } catch (Exception $e) { 710 | echo 'Exception: ', $e->getMessage(), "\n"; 711 | } 712 | 713 | ``` 714 | 715 | 716 | -------------------------------------------------------------------------------- 717 | [↑ Top](#agent-api-functions) 718 | 719 | st_login_log 720 | --- 721 | 722 | DESCRIPTION: 723 | 724 | Looks up the vicidial_users.custom_three field(as "agentId") to associate with a vicidial user ID. If found it will populate the custom_four field with a "teamId" value, then output the vicidial user ID 725 | 726 | VALUES: 727 | ``` 728 | value - 729 | REQUIRED alphanumeric string for CRM AgentID 730 | vendor_id - 731 | REQUIRED alphanumeric string for CRM TeamID 732 | ``` 733 | 734 | RESPONSES: 735 | ``` 736 | ERROR: st_login_log not valid - 6666|207 737 | ERROR: no user found - 6666 738 | SUCCESS: st_login_log user found - 6666 739 | ``` 740 | 741 | Code: 742 | 743 | ```php 744 | agent(); 748 | $agent_user = '1000'; 749 | $vicidialAPI->stLoginLog([ 750 | 'value' => 876543, 751 | 'vendor_id' => 207 752 | ]); 753 | } catch (Exception $e) { 754 | echo 'Exception: ', $e->getMessage(), "\n"; 755 | } 756 | 757 | ``` 758 | 759 | 760 | 761 | 762 | -------------------------------------------------------------------------------- 763 | [↑ Top](#agent-api-functions) 764 | 765 | st_get_agent_active_lead 766 | --- 767 | 768 | DESCRIPTION: 769 | 770 | Looks up the vicidial_users.custom_three field(as "agentId") to associate with a vicidial user ID. If found it will output the active lead_id and phone number, vendor_lead_code, province, security_phrase and source_id fields. 771 | 772 | VALUES: 773 | ``` 774 | value - 775 | REQUIRED alphanumeric string for CRM AgentID 776 | vendor_id - 777 | REQUIRED alphanumeric string for CRM TeamID 778 | ``` 779 | 780 | EXAMPLE URLS: 781 | http://server/agc/api.php?source=test&user=6666&pass=1234&function=st_get_agent_active_lead&value=876543&vendor_id=207 782 | 783 | RESPONSES: 784 | ERROR: st_get_agent_active_lead not valid - 6666|207 785 | ERROR: no user found - 6666 786 | ERROR: user not logged in - 6666 787 | ERROR: no active lead found - 6666 788 | SUCCESS: st_get_agent_active_lead lead found - 6666|7275551212|123456|9987-1234765|SK|WILLIAMS|JUH764AJJJ9 789 | 790 | Code: 791 | 792 | ```php 793 | agent(); 797 | $agent_user = '1000'; 798 | $vicidialAPI->stGetAgentActiveLead([ 799 | 'value' => 876543, 800 | 'vendor_id' => 207 801 | ]); 802 | } catch (Exception $e) { 803 | echo 'Exception: ', $e->getMessage(), "\n"; 804 | } 805 | 806 | ``` 807 | 808 | 809 | -------------------------------------------------------------------------------- 810 | [↑ Top](#agent-api-functions) 811 | 812 | ra_call_control 813 | --- 814 | 815 | DESCRIPTION: 816 | Allows for remote agent call control: hangup/transfer calls being handled by remote agents, also options for recording a disposition and call length 817 | 818 | VALUES: 819 | - value - REQUIRED, The call ID of the call as received as CallerIDname field or a special SIP-header, i.e. Y0315201639000402027 820 | - agent_user - REQUIRED, alphanumeric string for remote agent user 821 | - stage - REQUIRED, one of these choices: 'HANGUP','EXTENSIONTRANSFER','INGROUPTRANSFER' 822 | - ingroup_choices - OPTIONAL, only required if INGROUPTRANSFER stage is used, must be a single active in-group, reserved option of "DEFAULTINGROUP" can be used to send the call to the default in-group for the in-group or campaign that originated the call to the remote agent 823 | - phone_number - OPTIONAL, only required if EXTENSIONTRANSFER stage is used, must be a full number when dialed that will dial through the default context 824 | - status - OPTIONAL, status of the call, maximum of 6 characters, if not set, status will be RAXFER 825 | 826 | ``` 827 | RESPONSES: 828 | ERROR: ra_call_control not valid - Y0315201639000402027|6666|INGROUPTRANSFER 829 | ERROR: no user found - 6666 830 | ERROR: user not logged in - 6666 831 | ERROR: no active call found - Y0315201639000402027 832 | ERROR: phone_number is not valid - 9 833 | ERROR: ingroup is not valid - TESTINGROUP 834 | ERROR: stage is not valid - XYZ 835 | SUCCESS: ra_call_control transferred - 6666|Y0315201639000402027|SALESLINE 836 | SUCCESS: ra_call_control hungup - 6666|Y0315201639000402027|HANGUP 837 | ``` 838 | 839 | Code: 840 | 841 | ```php 842 | agent(); 846 | $agent_user = '1000'; 847 | $vicidialAPI->raCallControl($agent_user, [ 848 | 'stage' => 'INGROUPTRANSFER', 849 | 'ingroup_choices' => 'DEFAULTINGROUP', 850 | 'value' => 'Y0316001655000402028' 851 | ]); 852 | } catch (Exception $e) { 853 | echo 'Exception: ', $e->getMessage(), "\n"; 854 | } 855 | 856 | ``` 857 | 858 | 859 | 860 | -------------------------------------------------------------------------------- 861 | [↑ Top](#agent-api-functions) 862 | 863 | send_dtmf 864 | --- 865 | 866 | DESCRIPTION: 867 | 868 | Sends dtmf signal string to agent's session 869 | 870 | VALUES: (value) 871 | - only valid DTMF characters with these replacements: 872 | - P = # (pound or hash) 873 | - S = * (star) 874 | - Q = (one second of silence) 875 | ``` 876 | RESPONSES: 877 | ERROR: send_dtmf not valid - QQ|6666 878 | ERROR: no user found - 6666 879 | ERROR: agent_user is not logged in - 6666 880 | SUCCESS: send_dtmf function set - QQQQ1234SQQQQQ6654P|6666 881 | ``` 882 | 883 | 884 | Code: 885 | 886 | ```php 887 | agent(); 892 | $agent_user = '1000'; 893 | $vicidialAPI->sendDtmf([ 894 | 'value' => 'QQQQ1234SQQQQQ6654P' 895 | ]); 896 | } catch (Exception $e) { 897 | echo 'Exception: ', $e->getMessage(), "\n"; 898 | } 899 | 900 | ``` 901 | 902 | -------------------------------------------------------------------------------- 903 | [↑ Top](#agent-api-functions) 904 | 905 | park_call 906 | --- 907 | 908 | DESCRIPTION: 909 | sends command to park customer or grab customer out of park 910 | 911 | VALUES: 912 | value - 913 | REQUIRED, choices are below 914 | PARK_CUSTOMER - send customer to the park extension as defined in the campaign the agent is logged into 915 | GRAB_CUSTOMER - grab customer from the park extension and send them to the agent session 916 | PARK_IVR_CUSTOMER - send customer to the park ivr as defined in the campaign the agent is logged into, customer will come back after finishing IVR 917 | GRAB_IVR_CUSTOMER - grab customer from the park ivr and send them to the agent session 918 | 919 | ``` 920 | RESPONSES: 921 | ERROR: park_call not valid - PARK_CUSTOMER|6666 922 | ERROR: no user found - 6666 923 | ERROR: agent_user is not logged in - 6666 924 | ERROR: agent_user does not have a lead on their screen - 6666 925 | SUCCESS: park_call function set - PARK_CUSTOMER|6666 926 | ``` 927 | 928 | Code: 929 | 930 | ```php 931 | agent(); 935 | $agent_user = '1000'; 936 | $vicidialAPI->parkCall($agent_user, [ 937 | 'value' => 'PARK_CUSTOMER' 938 | ]); 939 | $vicidialAPI->parkCall($agent_user, [ 940 | 'value' => 'GRAB_CUSTOMER' 941 | ]); 942 | $vicidialAPI->parkCall($agent_user, [ 943 | 'value' => 'PARK_IVR_CUSTOMER' 944 | ]); 945 | $vicidialAPI->parkCall($agent_user, [ 946 | 'value' => 'GRAB_IVR_CUSTOMER' 947 | ]); 948 | } catch (Exception $e) { 949 | echo 'Exception: ', $e->getMessage(), "\n"; 950 | } 951 | 952 | ``` 953 | 954 | 955 | 956 | -------------------------------------------------------------------------------- 957 | [↑ Top](#agent-api-functions) 958 | 959 | transfer_conference 960 | --- 961 | 962 | DESCRIPTION: 963 | 964 | sends several commands related to the agent transfer-conf frame 965 | 966 | VALUES: 967 | value - 968 | REQUIRED, choices are below 969 | HANGUP_XFER - hangup the third party line 970 | HANGUP_BOTH - hangup customer and third party line 971 | BLIND_TRANSFER - send a call to a defined phone number 972 | LEAVE_VM - blind transfer customer to the campaign-defined voicemail message 973 | LOCAL_CLOSER - send call to another ViciDial agent, must have in-group, optional phone_number field for AGENTDIRECT agent 974 | DIAL_WITH_CUSTOMER - 3-way call with customer on the line 975 | PARK_CUSTOMER_DIAL - send customer to park and place a call to a third party 976 | LEAVE_3WAY_CALL - leave customer and third party in conference and go to the disposition screen 977 | phone_number - 978 | OPTIONAL/REQUIRED, required for any transfer or dial value 979 | ingroup_choices - 980 | OPTIONAL/REQUIRED, required for local_closer and consultative transfers, must be a single active in-group, reserved option of "DEFAULTINGROUP" can be used to select the default in-group for the in-group or campaign that the call originated from 981 | consultative - 982 | OPTIONAL, when you want to do a consultative transfer with your customer and another ViciDial agent, 'YES' and 'NO' are valid options, you can only use this with DIAL_WITH_CUSTOMER or PARK_CUSTOMER_DIAL 983 | dial_override - 984 | OPTIONAL, dials exactly the phone number specified with no campaign-defined phone code or prefix, 'YES' and 'NO' are valid options 985 | group_alias - 986 | OPTIONAL, defines what caller ID number to use when doing DIAL_WITH_CUSTOMER or PARK_CUSTOMER_DIAL 987 | cid_choice - 988 | OPTIONAL, alternate method for caller ID number to use when doing DIAL_WITH_CUSTOMER or PARK_CUSTOMER_DIAL: 'CAMPAIGN','AGENT_PHONE','CUSTOMER','CUSTOM_CID' 989 | ``` 990 | RESPONSES: 991 | ERROR: transfer_conference not valid - QQ|6666 992 | ERROR: value is not valid - XYZFUNCTION|6666 993 | ERROR: no user found - 6666 994 | ERROR: ingroup is not valid - XYZINGROUP 995 | ERROR: agent_user is not logged in - 6666 996 | ERROR: agent_user does not have a live call - 6666 997 | ERROR: caller_id_number from group_alias is not valid - 6666|TESTING|123 998 | ERROR: group_alias is not valid - 6666|TESTING 999 | ERROR: cid_choice is not valid - 6666|TESTING 1000 | SUCCESS: transfer_conference function set - LOCAL_CLOSER|SALESLINE||YES|6666|M2141842580000000044| 1001 | ``` 1002 | 1003 | Code: 1004 | 1005 | ```php 1006 | agent(); 1010 | $agent_user = '1000'; 1011 | $vicidialAPI->transferConference($agent_user, [ 1012 | 'value' => 'HANGUP_XFER' 1013 | ]); 1014 | $vicidialAPI->transferConference($agent_user, [ 1015 | 'value' => 'HANGUP_BOTH' 1016 | ]); 1017 | $vicidialAPI->transferConference($agent_user, [ 1018 | 'value' => 'BLIND_TRANSFER', 1019 | 'phone_number' => 8500 1020 | ]); 1021 | } catch (Exception $e) { 1022 | echo 'Exception: ', $e->getMessage(), "\n"; 1023 | } 1024 | 1025 | ``` 1026 | 1027 | 1028 | -------------------------------------------------------------------------------- 1029 | [↑ Top](#agent-api-functions) 1030 | 1031 | recording 1032 | --- 1033 | DESCRIPTION: 1034 | 1035 | sends a recording start/stop signal or status of agent recording 1036 | 1037 | VALUES: 1038 | value - 1039 | REQUIRED, choices are below 1040 | - START - sends a "start recording" signal to the agent screen 1041 | (you can have multiple recordings going at the same time) 1042 | - STOP - sends a "stop recording" signal to the agent screen 1043 | (this will stop all active recordings onthe agent screen) 1044 | - STATUS - displays results of active recording and agent session information 1045 | (returns: user|recording_id|filename|server|start_time|agent_server|session|agent_status) 1046 | - stage - 1047 | OPTIONAL, value to append to the recording filename, limited to 14 characters, if more it will truncate. Only works with START value 1048 | 1049 | ``` 1050 | RESPONSES: 1051 | ERROR: no user found - 6666 1052 | ERROR: agent_user is not logged in - 6666 1053 | ERROR: stop recording error - 6666|||||192.168.1.5|8600051|PAUSED 1054 | SUCCESS: recording function sent - 6666|STOP||||192.168.1.5|8600051|PAUSED 1055 | SUCCESS: recording function sent - 6666|START||||192.168.1.5|8600051|PAUSED 1056 | SUCCESS: recording function sent - 6666|START_MIDCALL||||192.168.1.5|8600051|PAUSED 1057 | NOTICE: not recording - 6666|||||192.168.1.5|8600051|PAUSED 1058 | NOTICE: recording active - 6666|121242|20120810-012008__6666_|192.168.1.5|2012-08-10 01:20:10|192.168.1.5|8600051|PAUSED 1059 | ``` 1060 | 1061 | Code: 1062 | ```php 1063 | agent(); 1068 | $agent_user = '1000'; 1069 | $vicidialAPI->recording($agent_user, [ 1070 | 'value' => 'START' 1071 | ]); 1072 | $vicidialAPI->recording($agent_user, [ 1073 | 'value' => 'STOP' 1074 | ]); 1075 | $vicidialAPI->recording($agent_user, [ 1076 | 'value' => 'STATUS' 1077 | ]); 1078 | $vicidialAPI->recording($agent_user, [ 1079 | 'value' => 'START', 1080 | 'stage' => '_MIDCALL' 1081 | ]); 1082 | } catch (Exception $e) { 1083 | echo 'Exception: ', $e->getMessage(), "\n"; 1084 | } 1085 | 1086 | ``` 1087 | 1088 | 1089 | 1090 | 1091 | -------------------------------------------------------------------------------- 1092 | [↑ Top](#agent-api-functions) 1093 | 1094 | webphone_url 1095 | --- 1096 | 1097 | DESCRIPTION: 1098 | 1099 | display or launch the webphone url for the current agent's session 1100 | 1101 | VALUES: 1102 | value - 1103 | REQUIRED, choices are below: 1104 | DISPLAY - displays only the URL for the webphone if enabled 1105 | LAUNCH - redirects the url to the webphone url to launch it 1106 | 1107 | 1108 | ``` 1109 | RESPONSES: 1110 | 1111 | ERROR: no user found - 6666 1112 | ERROR: agent_user is not logged in - 6666 1113 | ERROR: webphone_url not valid - 6666|DISPLAY 1114 | ERROR: webphone_url error - webphone url is empty - 6666 1115 | ERROR: webphone_url error - no session data - 6666 1116 | ``` 1117 | 1118 | 1119 | Code: 1120 | 1121 | ```php 1122 | agent(); 1126 | $agent_user = '1000'; 1127 | $vicidialAPI->webphoneUrl($agent_user, 'DISPLAY'); 1128 | $vicidialAPI->webphoneUrl($agent_user, 'LAUNCH'); 1129 | } catch (Exception $e) { 1130 | echo 'Exception: ', $e->getMessage(), "\n"; 1131 | } 1132 | 1133 | ``` 1134 | 1135 | -------------------------------------------------------------------------------- 1136 | [↑ Top](#agent-api-functions) 1137 | 1138 | call_agent 1139 | --- 1140 | 1141 | DESCRIPTION: 1142 | 1143 | send a call to connect the agent to their session 1144 | 1145 | VALUES: 1146 | value - 1147 | REQUIRED, choices are below: 1148 | CALL - places call from the agent session to the agent's phone 1149 | 1150 | NOTES: 1151 | 1152 | this function is not designed to work with on-hook agents 1153 | 1154 | ``` 1155 | RESPONSES: 1156 | ERROR: no user found - 6666 1157 | ERROR: agent_user is not logged in - 6666 1158 | ERROR: call_agent not valid - 6666|CALL 1159 | ERROR: call_agent error - entry is empty - 6666 1160 | ERROR: call_agent error - no session data - 6666 1161 | SUCCESS: call_agent function sent - 6666 1162 | ``` 1163 | 1164 | Code: 1165 | 1166 | ```php 1167 | agent(); 1171 | $agent_user = '1000'; 1172 | $vicidialAPI->callAgent($agent_user,'CALL'); 1173 | } catch (Exception $e) { 1174 | echo 'Exception: ', $e->getMessage(), "\n"; 1175 | } 1176 | ``` 1177 | 1178 | 1179 | 1180 | 1181 | -------------------------------------------------------------------------------- 1182 | [↑ Top](#agent-api-functions) 1183 | 1184 | audio_playback 1185 | --- 1186 | 1187 | DESCRIPTION: 1188 | 1189 | Basic play/stop/pause/resume/restart audio in agent session 1190 | 1191 | NOTE: PAUSE/RESUME/RESTART features only work with Asterisk 1.8 and higher 1192 | (In Asterisk versions earlier than 1.8 you can replicate RESTART using PLAY and dial_override=Y) 1193 | 1194 | VALUES: 1195 | stage - 1196 | REQUIRED, choices are below: 1197 | PLAY - starts playing of new audio file in agent session 1198 | STOP - kills playback of audio in agent session 1199 | PAUSE - pauses playing of audio 1200 | RESUME - resumes playing of audio after pause 1201 | RESTART - restarts playback at beginning of audio 1202 | value - 1203 | REQUIRED for stage of 'PLAY', name of audio file in audio store to play, must NOT have extension 1204 | dial_override - 1205 | OPTIONAL, (Y or N), default is N. Allows you to PLAY without issuing a STOP to a currently playing audio file 1206 | 1207 | ``` 1208 | RESPONSES: 1209 | ERROR: no user found - 6666 1210 | ERROR: agent_user is not logged in - PLAY|6666 1211 | ERROR: audio_playback not valid - ss-noservice|PLAY|6666 1212 | ERROR: audio_playback error - entry is empty - PLAY|6666 1213 | ERROR: audio_playback error - no session data - PLAY|6666 1214 | ERROR: audio_playback error - no audio playing in agent session - 8600051|10.10.10.15|PAUSE|6666 1215 | ERROR: audio_playback error - audio already playing in agent session - 8600051|10.10.10.15|PLAY|6666 1216 | NOTICE: audio_playback previous playback stopped - PLAY|Y|6666 1217 | SUCCESS: audio_playback function sent - ss-noservice|PLAY|6666 1218 | ``` 1219 | 1220 | Code: 1221 | 1222 | ```php 1223 | agent(); 1228 | $agent_user = '1000'; 1229 | $vicidialAPI->audioPlayBack($agent_user,[ 1230 | 'value' => 'ss-noservices', 1231 | 'stage' => 'PLAY' 1232 | ]); 1233 | $vicidialAPI->audioPlayBack($agent_user,[ 1234 | 'stage' => 'STOP' 1235 | ]); 1236 | $vicidialAPI->audioPlayBack($agent_user,[ 1237 | 'stage' => 'RESUME' 1238 | ]); 1239 | $vicidialAPI->audioPlayBack($agent_user,[ 1240 | 'stage' => 'RESTART' 1241 | ]); 1242 | $vicidialAPI->audioPlayBack($agent_user,[ 1243 | 'value' => 'ss-noservices', 1244 | 'stage' => 'PLAY', 1245 | 'dial_override' => 'Y' 1246 | ]); 1247 | } catch (Exception $e) { 1248 | echo 'Exception: ', $e->getMessage(), "\n"; 1249 | } 1250 | ``` 1251 | 1252 | 1253 | -------------------------------------------------------------------------------- 1254 | [↑ Top](#agent-api-functions) 1255 | 1256 | switch_lead 1257 | --- 1258 | 1259 | DESCRIPTION: 1260 | 1261 | For agents on a live inbound call, switches lead_id of live inbound call on agent screen including associated logs. You can define a lead_id or a vendor_lead_code to switch to. Works like the SELECT function of the LEAD SEARCH feature in the agent screen. 1262 | 1263 | VALUES: 1264 | - lead_id - 1265 | Any valid lead_id from the system(either lead_id or vendor_lead_code are required) if both are defined, lead_id will override vendor_lead_code 1266 | - vendor_lead_code - 1267 | OPTIONAL, any valid Vendor lead code 1268 | 1269 | RESPONSES: 1270 | ``` 1271 | ERROR: switch_lead not valid - ||6666 1272 | ERROR: no user found - 6666 1273 | ERROR: agent_user is not logged in - 6666 1274 | ERROR: agent_user does not have a live call - 6666 1275 | ERROR: agent call is not inbound - 6666|V2012367890123456789 1276 | ERROR: campaign not found - 6666|TESTCAMP 1277 | ERROR: campaign does not allow inbound lead search - 6666|TESTCAMP 1278 | ERROR: switch-to lead not found - 6666|12345|123456789 1279 | SUCCESS: switch_lead function set - 6666|12345|1234567890|TESTCAMP|12346 1280 | ``` 1281 | 1282 | Code: 1283 | 1284 | ```php 1285 | agent(); 1290 | $agent_user = '1000'; 1291 | $vicidialAPI->switchLead($agent_user,[ 1292 | 'lead_id' => '12345' 1293 | ]); 1294 | $vicidialAPI->audioPlayBack($agent_user,[ 1295 | 'vendor_lead_code' => '1234567890' 1296 | ]); 1297 | } catch (Exception $e) { 1298 | echo 'Exception: ', $e->getMessage(), "\n"; 1299 | } 1300 | ``` 1301 | 1302 | 1303 | -------------------------------------------------------------------------------- 1304 | [↑ Top](#agent-api-functions) 1305 | 1306 | vm_message 1307 | --- 1308 | 1309 | IMPORTANT NOTES: 1310 | 1311 | - Set the campaign "Answering Machine Message" setting to 'LTTagent' for this to work. 1312 | - There are some other campaign settings that can override this function, so you will want to disable 'AM Message Wildcards' and 'VM Message Groups'. 1313 | 1314 | DESCRIPTION: 1315 | 1316 | Set a custom voicemail message to be played when agent clicks the VM button on the agent screen 1317 | 1318 | VALUES: 1319 | - value - 1320 | REQUIRED, One audio file or multiple audio files(separated by pipes) to play when the call is sent to VM by the agent 1321 | - lead_id - 1322 | OPTIONAL, The lead_id of the call that the agent is currently on, if populated it will validate that is the lead the agent is talking to 1323 | 1324 | EXAMPLE URLS: 1325 | http://server/agc/api.php?source=test&user=6666&pass=1234&agent_user=1000&function=vm_message&value=EXship01|EXship02|EXship03 1326 | http://server/agc/api.php?source=test&user=6666&pass=1234&agent_user=1000&function=vm_message&lead_id=12345&value=appointment_reminder2 1327 | 1328 | RESPONSES: 1329 | 1330 | - ERROR: vm_message not valid - ||6666 1331 | - ERROR: no user found - 6666 1332 | - ERROR: agent_user is not logged in - 6666 1333 | - ERROR: current call does not match lead_id submitted - 6666 1334 | - ERROR: agent_user does not have a live call - 6666 1335 | - SUCCESS: vm_message function set - 6666|12345|EXship01|EXship02|EXship03 1336 | 1337 | Code: 1338 | 1339 | ```php 1340 | agent(); 1346 | $agent_user = '1000'; 1347 | $vicidialAPI->vmMessage($agent_user,[ 1348 | 'value' => 'EXship01|EXship02|EXship03' 1349 | ]); 1350 | $vicidialAPI->vmMessage($agent_user,[ 1351 | 'lead_id' => 12345, 1352 | 'value' => 'appointment_reminder2' 1353 | ]); 1354 | } catch (Exception $e) { 1355 | echo 'Exception: ', $e->getMessage(), "\n"; 1356 | } 1357 | ``` 1358 | 1359 | 1360 | 1361 | -------------------------------------------------------------------------------- 1362 | [↑ Top](#agent-api-functions) 1363 | 1364 | pause_code 1365 | --- 1366 | 1367 | DESCRIPTION: 1368 | 1369 | set a pause code for an agent that is paused 1370 | 1371 | VALUES: 1372 | - value - pause code to set, must be 6 characters or less 1373 | 1374 | NOTES: 1375 | 1376 | this function will not work if the agent is not paused 1377 | 1378 | RESPONSES: 1379 | - ERROR: no user found - 6666 1380 | - ERROR: agent_user is not logged in - 6666 1381 | - ERROR: pause_code not valid - 6666|JUMPING 1382 | - ERROR: pause_code error - agent is not paused - 6666 1383 | - SUCCESS: pause_code function sent - 6666 1384 | 1385 | Code: 1386 | 1387 | ```php 1388 | agent(); 1394 | $agent_user = '1000'; 1395 | $vicidialAPI->pauseCode($agent_user,'BREAK'); 1396 | } catch (Exception $e) { 1397 | echo 'Exception: ', $e->getMessage(), "\n"; 1398 | } 1399 | ``` 1400 | 1401 | 1402 | 1403 | -------------------------------------------------------------------------------- 1404 | [↑ Top](#agent-api-functions) 1405 | 1406 | calls_in_queue_count 1407 | --- 1408 | 1409 | DESCRIPTION: 1410 | 1411 | display a count of the calls waiting in queue for the specific agent 1412 | 1413 | VALUES: 1414 | - value - 1415 | REQUIRED, choices are below: 1416 | DISPLAY - displays number of calls in queue that could be sent to this agent 1417 | 1418 | RESPONSES: 1419 | - ERROR: no user found - 6666 1420 | - ERROR: agent_user is not logged in - 6666 1421 | - SUCCESS: calls_in_queue_count - 0 1422 | 1423 | Code: 1424 | 1425 | ```php 1426 | agent(); 1432 | $agent_user = '1000'; 1433 | $vicidialAPI->callsInQueueCount($agent_user,'DISPLAY'); 1434 | } catch (Exception $e) { 1435 | echo 'Exception: ', $e->getMessage(), "\n"; 1436 | } 1437 | ``` 1438 | 1439 | 1440 | 1441 | 1442 | -------------------------------------------------------------------------------- 1443 | [↑ Top](#agent-api-functions) 1444 | 1445 | force_fronter_leave_3way 1446 | --- 1447 | 1448 | DESCRIPTION: 1449 | 1450 | will send a command to fronter agent to leave-3way call that executing agent is on. Will not execute command for the named 'agent_user', but will look for oldest other user currently on a call with the same lead_id that the named agent_user is on the phone with. 1451 | 1452 | VALUES: 1453 | - value - 1454 | REQUIRED, choices are below: 1455 | - LOCAL_ONLY - looks for fronter only on local cluster 1456 | - LOCAL_AND_CCC - looks on local cluster and remote CCC to send command to (will always check local first) 1457 | - CCC_REMOTE - use this when the closer is not on this cluster 1458 | - lead_id - 1459 | - OPTIONAL, only to be used with CCC_REMOTE value commands 1460 | 1461 | RESPONSES: 1462 | - ERROR: no user found - 6666 1463 | - ERROR: agent_user is not logged in - 6666 1464 | - ERROR: agent_user is not on a phone call - 6666 1465 | - ERROR: no fronter found - 6666 1466 | - SUCCESS: force_fronter_leave_3way SENT - 6667 1467 | - SUCCESS: force_fronter_leave_3way command sent over CCC - test_ccc 1468 | 1469 | Code: 1470 | 1471 | ```php 1472 | agent(); 1476 | $agent_user = '1000'; 1477 | $vicidialAPI->forceFronterLeave3way($agent_user,'LOCAL_ONLY'); 1478 | $vicidialAPI->forceFronterLeave3way($agent_user,'LOCAL_AND_CCC'); 1479 | } catch (Exception $e) { 1480 | echo 'Exception: ', $e->getMessage(), "\n"; 1481 | } 1482 | ``` 1483 | 1484 | -------------------------------------------------------------------------------- 1485 | [↑ Top](#agent-api-functions) 1486 | 1487 | force_fronter_audio_stop 1488 | --- 1489 | 1490 | DESCRIPTION: 1491 | will send a command to fronter agent session to stop any audio_playback playing on it. Will not execute command for the named 'agent_user', but will look for other user session currently on a call with the same lead_id that the named agent_user is on the phone with. 1492 | 1493 | VALUES: 1494 | - value - 1495 | REQUIRED, choices are below: 1496 | - LOCAL_ONLY - looks for fronter only on local cluster 1497 | - LOCAL_AND_CCC - looks on local cluster and remote CCC to send command to (will always check local first) 1498 | - CCC_REMOTE - use this when the closer is not on this cluster 1499 | - lead_id - 1500 | - OPTIONAL, only to be used with CCC_REMOTE value commands 1501 | 1502 | EXAMPLE URLS: 1503 | http://server/agc/api.php?source=test&user=6666&pass=1234&agent_user=1000&function=force_fronter_audio_stop&value=LOCAL_ONLY 1504 | http://server/agc/api.php?source=test&user=6666&pass=1234&agent_user=1000&function=force_fronter_audio_stop&value=LOCAL_AND_CCC 1505 | 1506 | RESPONSES: 1507 | ERROR: force_fronter_audio_stop not valid - LOCAL_AND_CCC|6666 1508 | ERROR: auth USER DOES NOT HAVE PERMISSION TO USE THIS FUNCTION - LOCAL_AND_CCC|6666|force_fronter_audio_stop 1509 | ERROR: no user found - 6666 1510 | ERROR: agent_user is not logged in - 6666 1511 | ERROR: agent_user is not on a phone call - 6666 1512 | ERROR: no fronter session found - |6666|1234 1513 | ERROR: no fronter found - 6666 1514 | ERROR: force_fronter_audio_stop error - no audio playing in other agent session - 8600051|10.0.0.5||6666|1234 1515 | SUCCESS: force_fronter_audio_stop function SENT - LOCAL_AND_CCC||6667|1234 1516 | SUCCESS: force_fronter_audio_stop command sent over CCC - test_ccc 1517 | 1518 | Code: 1519 | 1520 | ```php 1521 | agent(); 1525 | $agent_user = '1000'; 1526 | $vicidialAPI->forceFronterAudioStop($agent_user,'LOCAL_ONLY'); 1527 | $vicidialAPI->forceFronterAudioStop($agent_user,'LOCAL_AND_CCC'); 1528 | } catch (Exception $e) { 1529 | echo 'Exception: ', $e->getMessage(), "\n"; 1530 | } 1531 | ``` 1532 | -------------------------------------------------------------------------------- /example/admin/moh_list.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | load(); 8 | 9 | try { 10 | $agent_api = VicidialApi::create( 11 | getenv('VICIDIAL_ADMIN_URL'), 12 | getenv('VICIDIAL_USER'), 13 | getenv('VICIDIAL_PASS') 14 | )->admin(); 15 | 16 | echo $agent_api->mohList([ 17 | 'format' => 'selectframe', 18 | 'comments' => 'fieldname', 19 | 'stage' => 'date', 20 | ]); 21 | } catch (Exception $e) { 22 | echo 'Exception: ', $e->getMessage(), "\n"; 23 | } 24 | -------------------------------------------------------------------------------- /example/admin/version.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | load(); 8 | 9 | $fields['first_name'] = 'John'; 10 | $fields['last_name'] = 'Doe'; 11 | $fields['address1'] = '123 Fake St'; 12 | 13 | try { 14 | $agent_api = VicidialApi::create( 15 | getenv('VICIDIAL_ADMIN_URL'), 16 | getenv('VICDIAL_USER'), 17 | getenv('VICDIAL_PASS') 18 | )->admin(); 19 | echo $agent_api->version(); 20 | } catch (Exception $e) { 21 | echo 'Exception: ', $e->getMessage(), "\n"; 22 | } 23 | -------------------------------------------------------------------------------- /example/update_fileds.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | load(); 8 | 9 | $fields['first_name'] = 'John'; 10 | $fields['last_name'] = 'Doe'; 11 | $fields['address1'] = '123 Fake St'; 12 | 13 | try { 14 | $agent_api = VicidialApi::create( 15 | getenv('VICIDIAL_ADMIN_URL'), 16 | getenv('VICDIAL_USER'), 17 | getenv('VICDIAL_PASS') 18 | )->agent(); 19 | echo $agent_api->updateFields('gabriel', $fields); 20 | } catch (Exception $e) { 21 | echo 'Exception: ', $e->getMessage(), "\n"; 22 | } 23 | -------------------------------------------------------------------------------- /phpstan.neon.dist: -------------------------------------------------------------------------------- 1 | parameters: 2 | level: max 3 | paths: 4 | - src 5 | excludePaths: 6 | analyse: 7 | - src/Testing 8 | 9 | reportUnmatchedIgnoredErrors: true 10 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 21 | 22 | 23 | tests 24 | 25 | 26 | 27 | 28 | ./src 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /rector.php: -------------------------------------------------------------------------------- 1 | paths([ 11 | __DIR__.'/src', 12 | ]); 13 | 14 | // register a single rule 15 | $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class); 16 | 17 | // define sets of rules 18 | $rectorConfig->sets([ 19 | LevelSetList::UP_TO_PHP_83, 20 | ]); 21 | }; 22 | -------------------------------------------------------------------------------- /src/Client.php: -------------------------------------------------------------------------------- 1 | transporter); 21 | } 22 | 23 | public function admin(): Admin 24 | { 25 | return new Admin($this->transporter); 26 | } 27 | 28 | public function remoteAgent(): RemoteAgent 29 | { 30 | return new RemoteAgent($this->transporter); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Contracts/AdminContract.php: -------------------------------------------------------------------------------- 1 | $options 18 | */ 19 | public function mohList(array $options): string; 20 | 21 | /** 22 | * Get the list of VM. 23 | * 24 | * @param array $options 25 | */ 26 | public function vmList(array $options): string; 27 | 28 | /** 29 | * Get blind monitor information. 30 | * 31 | * @param array $options 32 | */ 33 | public function blindMonitor(array $options): string; 34 | 35 | /** 36 | * Get agent in group information. 37 | * 38 | * @param array $options 39 | */ 40 | public function agentInGroupInfo(array $options): string; 41 | 42 | /** 43 | * Get agent campaigns. 44 | * 45 | * @param array $options 46 | */ 47 | public function agentCampaigns(array $options): string; 48 | 49 | /** 50 | * Get the campaigns list. 51 | * 52 | * @param array $options 53 | */ 54 | public function campaignsList(array $options): string; 55 | 56 | /** 57 | * Get the hopper list. 58 | * 59 | * @param array $options 60 | */ 61 | public function hopperList(array $options): string; 62 | 63 | /** 64 | * Look up recording information. 65 | * 66 | * @param array $options 67 | */ 68 | public function recordingLookup(array $options): string; 69 | 70 | /** 71 | * Export DID log. 72 | * 73 | * @param array $options 74 | */ 75 | public function didLogExport(array $options): string; 76 | 77 | /** 78 | * Get phone number log. 79 | * 80 | * @param array $options 81 | */ 82 | public function phoneNumberLog(array $options): string; 83 | 84 | /** 85 | * Export agent stats. 86 | * 87 | * @param array $options 88 | */ 89 | public function agentStatsExport(array $options): string; 90 | 91 | /** 92 | * Get user group status. 93 | * 94 | * @param array $options 95 | */ 96 | public function userGroupStatus(array $options): string; 97 | 98 | /** 99 | * Get in-group status. 100 | * 101 | * @param array $options 102 | */ 103 | public function inGroupStatus(array $options): string; 104 | 105 | /** 106 | * Get agent status. 107 | * 108 | * @param array $options 109 | */ 110 | public function agentStatus(array $options): string; 111 | 112 | /** 113 | * Get call ID information. 114 | * 115 | * @param array $options 116 | */ 117 | public function callIdInfo(array $options): string; 118 | 119 | /** 120 | * Get lead field information. 121 | * 122 | * @param array $options 123 | */ 124 | public function leadFieldInfo(array $options): string; 125 | 126 | /** 127 | * Search lead status. 128 | * 129 | * @param array $options 130 | */ 131 | public function leadStatusSearch(array $options): string; 132 | 133 | /** 134 | * Get CCC lead information. 135 | * 136 | * @param array $options 137 | */ 138 | public function cccLeadInfo(array $options): string; 139 | 140 | /** 141 | * Get lead callback information. 142 | * 143 | * @param array $options 144 | */ 145 | public function leadCallbackInfo(array $options): string; 146 | 147 | /** 148 | * Update log entry. 149 | * 150 | * @param array $options 151 | */ 152 | public function updateLogEntry(array $options): string; 153 | 154 | /** 155 | * Add lead. 156 | * 157 | * @param array $options 158 | */ 159 | public function addLead(array $options): string; 160 | 161 | /** 162 | * Update lead. 163 | * 164 | * @param array $options 165 | */ 166 | public function updateLead(array $options): string; 167 | 168 | /** 169 | * Add user. 170 | * 171 | * @param array $options 172 | */ 173 | public function addUser(array $options): string; 174 | 175 | /** 176 | * Update user. 177 | * 178 | * @param array $options 179 | */ 180 | public function updateUser(array $options): string; 181 | 182 | /** 183 | * Add group alias. 184 | * 185 | * @param array $options 186 | */ 187 | public function addGroupAlias(array $options): string; 188 | 189 | /** 190 | * Add DNC phone. 191 | * 192 | * @param array $options 193 | */ 194 | public function addDncPhone(array $options): string; 195 | 196 | /** 197 | * Add FPG phone. 198 | * 199 | * @param array $options 200 | */ 201 | public function addFpgPhone(array $options): string; 202 | 203 | /** 204 | * Add phone. 205 | * 206 | * @param array $options 207 | */ 208 | public function addPhone(array $options): string; 209 | 210 | /** 211 | * Update phone. 212 | * 213 | * @param array $options 214 | */ 215 | public function updatePhone(array $options): string; 216 | 217 | /** 218 | * Add phone alias. 219 | * 220 | * @param array $options 221 | */ 222 | public function addPhoneAlias(array $options): string; 223 | 224 | /** 225 | * Update phone alias. 226 | * 227 | * @param array $options 228 | */ 229 | public function updatePhoneAlias(array $options): string; 230 | 231 | /** 232 | * Refresh server. 233 | * 234 | * @param array $options 235 | */ 236 | public function serverRefresh(array $options): string; 237 | 238 | /** 239 | * Add list. 240 | * 241 | * @param array $options 242 | */ 243 | public function addList(array $options): string; 244 | 245 | /** 246 | * Update list. 247 | * 248 | * @param array $options 249 | */ 250 | public function updateList(array $options): string; 251 | 252 | /** 253 | * Get list information. 254 | * 255 | * @param array $options 256 | */ 257 | public function listInfo(array $options): string; 258 | 259 | /** 260 | * Get list custom fields. 261 | * 262 | * @param array $options 263 | */ 264 | public function listCustomFields(array $options): string; 265 | 266 | /** 267 | * Check phone number. 268 | * 269 | * @param array $options 270 | */ 271 | public function checkPhoneNumber(array $options): string; 272 | 273 | /** 274 | * Get logged-in agents. 275 | * 276 | * @param array $options 277 | */ 278 | public function loggedInAgents(array $options): string; 279 | 280 | /** 281 | * Get call status stats. 282 | * 283 | * @param array $options 284 | */ 285 | public function callStatusStats(array $options): string; 286 | 287 | /** 288 | * Get call disposition report. 289 | * 290 | * @param array $options 291 | */ 292 | public function callDispoReport(array $options): string; 293 | 294 | /** 295 | * Update campaign. 296 | * 297 | * @param array $options 298 | */ 299 | public function updateCampaign(array $options): string; 300 | 301 | /** 302 | * Add DID. 303 | * 304 | * @param array $options 305 | */ 306 | public function addDid(array $options): string; 307 | 308 | /** 309 | * Update DID. 310 | * 311 | * @param array $options 312 | */ 313 | public function updateDid(array $options): string; 314 | 315 | /** 316 | * Update CID group entry. 317 | * 318 | * @param array $options 319 | */ 320 | public function updateCidGroupEntry(array $options): string; 321 | 322 | /** 323 | * Copy user. 324 | * 325 | * @param array $options 326 | */ 327 | public function copyUser(array $options): string; 328 | } 329 | -------------------------------------------------------------------------------- /src/Contracts/AgentContract.php: -------------------------------------------------------------------------------- 1 | $options 15 | */ 16 | public function dispo(string $agentUser, array $options): string; 17 | 18 | /** 19 | * Creates the URL for the external_pause method and calls 'call_api_url' to execute it 20 | */ 21 | public function pause(string $agentUser, string $status): string; 22 | 23 | /** 24 | * Creates the URL for the pause_code method and calls 'call_api_url' to execute it 25 | */ 26 | public function pauseCode(string $agentUser, string $code): string; 27 | 28 | /** 29 | * Creates the URL for the webserver method and calls 'call_api_url' to execute it 30 | */ 31 | public function webserver(): string; 32 | 33 | /** 34 | * Creates the URL for the version method and calls 'call_api_url' to execute it 35 | */ 36 | public function version(): string; 37 | 38 | /** 39 | * Creates the URL for the logout method and calls 'call_api_url' to execute it 40 | */ 41 | public function logout(string $agentUser): string; 42 | 43 | /** 44 | * Creates the URL for the external_dial method and calls 'call_api_url' to execute it 45 | * 46 | * @param array $options 47 | */ 48 | public function dial(string $agentUser, array $options): string; 49 | 50 | /** 51 | * Sends a SKIP, DIALONLY, ALTDIAL, ADR3DIAL or FINISH when a lead is being previewed or in Manual Alt Dial 52 | */ 53 | public function previewDial(string $agentUser, string $value): string; 54 | 55 | /** 56 | * Adds a lead in the manual dial list of the campaign for logged-in agent. A much simplified add lead function compared to the Non-Agent API function 57 | * 58 | * @param array $options 59 | */ 60 | public function addLead(string $agentUser, array $options): string; 61 | 62 | /** 63 | * This function will change the selected in-groups for an agent that is logged into a campaign that allows 64 | * for inbound calls to be handled. Allows the selected in-groups for an agent to be changed while they are 65 | * logged-in to the ViciDial Agent screen only. Once changed in this way, the agent would need to log out 66 | * and back in to be able to select in-groups themselves(If Agent Choose In-Groups is enabled for that user). 67 | * The blended checkbox can also be changed using this function. The API user performing this function must 68 | * have vicidial_users.change_agent_campaign = 1. 69 | * 70 | * @param array $options 71 | */ 72 | public function changeInGroups(string $agentUser, array $options): string; 73 | 74 | /** 75 | * Creates the URL for the external_dial method and calls 'call_api_url' to execute it 76 | * 77 | * @param array $fieldsToUpdate 78 | */ 79 | public function updateFields(string $agentUser, array $fieldsToUpdate): string; 80 | 81 | /** 82 | * Updates the fields that are specified with the values. This will update the data 83 | * that is on the agent's screen in the customer information section. 84 | * 85 | * @param array $options 86 | */ 87 | public function setTimerAction(string $agentUser, array $options): string; 88 | 89 | /** 90 | * Looks up the vicidial_users.custom_three field(as "agentId") to associate with a vicidial user ID. 91 | * If found it will populate the custom_four field with a "teamId" value, then output the vicidial user ID 92 | * 93 | * @param array $options 94 | */ 95 | public function stLoginLog(array $options): string; 96 | 97 | /** 98 | * Looks up the vicidial_users.custom_three field(as "agentId") to associate with a vicidial user ID. 99 | * If found it will output the active lead_id and phone number, vendor_lead_code, province, security_phrase and source_id fields. 100 | * 101 | * @param array $options 102 | */ 103 | public function stGetAgentActiveLead(array $options): string; 104 | 105 | /** 106 | * @param array $options 107 | */ 108 | public function raCallControl(string $agent, array $options): string; 109 | 110 | /** 111 | * @param array $options 112 | */ 113 | public function sendDtmf(array $options): string; 114 | 115 | /** 116 | * @param array $options 117 | */ 118 | public function transferConference(string $agent, array $options): string; 119 | 120 | /** 121 | * @param array $options 122 | */ 123 | public function parkCall(string $agent, array $options): string; 124 | 125 | public function callAgent(string $agentUser, string $value): string; 126 | 127 | /** 128 | * @param array $options 129 | */ 130 | public function recording(string $agent, array $options): string; 131 | 132 | public function webPhoneUrl(string $agentUser, string $value): string; 133 | 134 | /** 135 | * @param array $options 136 | */ 137 | public function audioPlayBack(string $agentUser, array $options): string; 138 | 139 | /** 140 | * Creates the URL for the pause_code method and calls 'call_api_url' to execute it 141 | */ 142 | public function switchLead(string $agentUser, string $leadId): string; 143 | 144 | /** 145 | * Set a custom voicemail message to be played when agent clicks the VM button on the agent screen 146 | * 147 | * @param array $options 148 | */ 149 | public function vmMessage(string $agentUser, array $options): string; 150 | 151 | /** 152 | * display a count of the calls waiting in queue for the specific agent 153 | */ 154 | public function callsInQueueCount(string $agentUser, string $status): string; 155 | 156 | public function forceFronterLeave3way(string $agentUser, string $status): string; 157 | 158 | public function forceFronterAudioStop(string $agentUser, string $status): string; 159 | } 160 | -------------------------------------------------------------------------------- /src/Contracts/MetaInformationContract.php: -------------------------------------------------------------------------------- 1 | , value-of> 13 | * 14 | * @internal 15 | */ 16 | interface MetaInformationContract extends ArrayAccess 17 | { 18 | /** 19 | * Returns the array representation of the meta information. 20 | * 21 | * @return TArray 22 | */ 23 | public function toArray(): array; 24 | 25 | /** 26 | * @param key-of $offset 27 | */ 28 | public function offsetExists(mixed $offset): bool; 29 | 30 | /** 31 | * @template TOffsetKey of key-of 32 | * 33 | * @param TOffsetKey $offset 34 | * @return TArray[TOffsetKey] 35 | */ 36 | public function offsetGet(mixed $offset): mixed; 37 | 38 | /** 39 | * @template TOffsetKey of key-of 40 | * 41 | * @param TOffsetKey $offset 42 | * @param TArray[TOffsetKey] $value 43 | */ 44 | public function offsetSet(mixed $offset, mixed $value): never; 45 | 46 | /** 47 | * @template TOffsetKey of key-of 48 | * 49 | * @param TOffsetKey $offset 50 | */ 51 | public function offsetUnset(mixed $offset): never; 52 | } 53 | -------------------------------------------------------------------------------- /src/Contracts/ResponseContract.php: -------------------------------------------------------------------------------- 1 | , value-of> 13 | * 14 | * @internal 15 | */ 16 | interface ResponseContract extends ArrayAccess 17 | { 18 | /** 19 | * Returns the array representation of the Response. 20 | * 21 | * @return TArray 22 | */ 23 | public function toArray(): array; 24 | 25 | /** 26 | * @param key-of $offset 27 | */ 28 | public function offsetExists(mixed $offset): bool; 29 | 30 | /** 31 | * @template TOffsetKey of key-of 32 | * 33 | * @param TOffsetKey $offset 34 | * @return TArray[TOffsetKey] 35 | */ 36 | public function offsetGet(mixed $offset): mixed; 37 | 38 | /** 39 | * @template TOffsetKey of key-of 40 | * 41 | * @param TOffsetKey $offset 42 | * @param TArray[TOffsetKey] $value 43 | */ 44 | public function offsetSet(mixed $offset, mixed $value): never; 45 | 46 | /** 47 | * @template TOffsetKey of key-of 48 | * 49 | * @param TOffsetKey $offset 50 | */ 51 | public function offsetUnset(mixed $offset): never; 52 | } 53 | -------------------------------------------------------------------------------- /src/Contracts/StringableContract.php: -------------------------------------------------------------------------------- 1 | |string> 20 | * 21 | * @throws ErrorException|UnserializableResponse|TransporterException 22 | */ 23 | public function requestObject(Payload $payload): Response; 24 | 25 | /** 26 | * Sends a content request to a server. 27 | * 28 | * @throws ErrorException|TransporterException 29 | */ 30 | public function requestContent(Payload $payload): string; 31 | 32 | /** 33 | * Sends a stream request to a server. 34 | ** 35 | * @throws ErrorException 36 | */ 37 | public function requestStream(Payload $payload): ResponseInterface; 38 | } 39 | -------------------------------------------------------------------------------- /src/Enums/Transporter/ContentType.php: -------------------------------------------------------------------------------- 1 | , type: ?string, code: string|int|null} $contents 13 | */ 14 | public function __construct(private readonly array $contents) 15 | { 16 | $message = ($contents['message'] ?: (string) $this->contents['code']) ?: 'Unknown error'; 17 | 18 | if (is_array($message)) { 19 | $message = implode("\n", $message); 20 | } 21 | 22 | parent::__construct($message); 23 | } 24 | 25 | /** 26 | * Returns the error message. 27 | */ 28 | public function getErrorMessage(): string 29 | { 30 | return $this->getMessage(); 31 | } 32 | 33 | /** 34 | * Returns the error type. 35 | */ 36 | public function getErrorType(): ?string 37 | { 38 | return $this->contents['type']; 39 | } 40 | 41 | /** 42 | * Returns the error code. 43 | */ 44 | public function getErrorCode(): string|int|null 45 | { 46 | return $this->contents['code']; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Exceptions/InvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | getMessage(), 0, $exception); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Exceptions/UnserializableResponse.php: -------------------------------------------------------------------------------- 1 | getMessage(), 0, $exception); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Factory.php: -------------------------------------------------------------------------------- 1 | 47 | */ 48 | private array $headers = []; 49 | 50 | /** 51 | * The query parameters for the requests. 52 | * 53 | * @var array 54 | */ 55 | private array $queryParams = []; 56 | 57 | private ?Closure $streamHandler = null; 58 | 59 | private ?BasicAuth $basicAuth = null; 60 | 61 | /** 62 | * Sets the API key for the requests. 63 | */ 64 | public function withApiKey(string $apiKey): self 65 | { 66 | $this->apiKey = trim($apiKey); 67 | 68 | return $this; 69 | } 70 | 71 | public function withApiUser(string $apiUser): self 72 | { 73 | $this->apiUser = trim($apiUser); 74 | 75 | return $this; 76 | } 77 | 78 | public function withApiPass(string $apiPass): self 79 | { 80 | $this->apiPass = trim($apiPass); 81 | 82 | return $this; 83 | } 84 | 85 | public function withSource(string $source): self 86 | { 87 | $this->source = trim($source); 88 | 89 | return $this; 90 | } 91 | 92 | /** 93 | * Sets the HTTP client for the requests. 94 | * If no client is provided the factory will try to find one using PSR-18 HTTP Client Discovery. 95 | */ 96 | public function withHttpClient(ClientInterface $client): self 97 | { 98 | $this->httpClient = $client; 99 | 100 | return $this; 101 | } 102 | 103 | /** 104 | * Sets the stream handler for the requests. Not required when using Guzzle. 105 | */ 106 | public function withStreamHandler(Closure $streamHandler): self 107 | { 108 | $this->streamHandler = $streamHandler; 109 | 110 | return $this; 111 | } 112 | 113 | /** 114 | * Sets the base URI for the requests. 115 | * If no URI is provided the factory will use the default OpenAI API URI. 116 | */ 117 | public function withBaseUri(string $baseUri): self 118 | { 119 | $this->baseUri = $baseUri; 120 | 121 | return $this; 122 | } 123 | 124 | /** 125 | * Adds a custom HTTP header to the requests. 126 | */ 127 | public function withHttpHeader(string $name, string $value): self 128 | { 129 | $this->headers[$name] = $value; 130 | 131 | return $this; 132 | } 133 | 134 | /** 135 | * Adds a custom query parameter to the request url. 136 | */ 137 | public function withQueryParam(string $name, string $value): self 138 | { 139 | $this->queryParams[$name] = $value; 140 | 141 | return $this; 142 | } 143 | 144 | /** 145 | * Adds a basic auth to the request. 146 | */ 147 | public function withBasicAuth(string $user, string $pass): self 148 | { 149 | $this->basicAuth = new BasicAuth($user, $pass); 150 | 151 | return $this; 152 | } 153 | 154 | /** 155 | * Creates a new Open AI Client. 156 | */ 157 | public function make(): Client 158 | { 159 | $headers = Headers::create(); 160 | 161 | if ($this->apiKey !== null) { 162 | $headers = Headers::withAuthorization(ApiKey::from($this->apiKey)); 163 | } 164 | 165 | if ($this->basicAuth !== null) { 166 | $headers = $headers->withBasicAuthorization($this->basicAuth); 167 | } 168 | 169 | foreach ($this->headers as $name => $value) { 170 | $headers = $headers->withCustomHeader($name, $value); 171 | } 172 | 173 | $baseUri = BaseUri::from($this->baseUri ?: 'localhost'); 174 | 175 | $queryParams = QueryParams::create(); 176 | foreach ($this->queryParams as $name => $value) { 177 | $queryParams = $queryParams->withParam($name, $value); 178 | } 179 | 180 | $queryParams = $queryParams->withParam('source', $this->source); 181 | 182 | if ($this->apiUser !== null && $this->apiPass !== null) { 183 | $queryParams = $queryParams->withParam('user', $this->apiUser); 184 | $queryParams = $queryParams->withParam('pass', $this->apiPass); 185 | } 186 | 187 | $client = $this->httpClient ??= Psr18ClientDiscovery::find(); 188 | 189 | $sendAsync = $this->makeStreamHandler($client); 190 | 191 | $transporter = new HttpTransporter($client, $baseUri, $headers, $queryParams, $sendAsync); 192 | 193 | return new Client($transporter); 194 | } 195 | 196 | /** 197 | * Creates a new stream handler for "stream" requests. 198 | */ 199 | private function makeStreamHandler(ClientInterface $client): Closure 200 | { 201 | if (! is_null($this->streamHandler)) { 202 | return $this->streamHandler; 203 | } 204 | 205 | if ($client instanceof GuzzleClient) { 206 | return fn (RequestInterface $request): ResponseInterface => $client->send($request, ['stream' => true]); 207 | } 208 | 209 | if ($client instanceof Psr18Client) { 210 | return fn (RequestInterface $request): ResponseInterface => $client->sendRequest($request); 211 | } 212 | 213 | return function (RequestInterface $_): never { 214 | throw new Exception('To use stream requests you must provide an stream handler closure via the OpenAI factory.'); 215 | }; 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /src/Resources/Admin.php: -------------------------------------------------------------------------------- 1 | makeApiRequest('version', []); 17 | } 18 | 19 | public function mohList(array $options): string 20 | { 21 | return $this->makeApiRequest('moh_list', $options); 22 | } 23 | 24 | public function vmList(array $options): string 25 | { 26 | return $this->makeApiRequest('vm_list', $options); 27 | } 28 | 29 | public function blindMonitor(array $options): string 30 | { 31 | return $this->makeApiRequest('blind_monitor', $options); 32 | } 33 | 34 | public function agentInGroupInfo(array $options): string 35 | { 36 | return $this->makeApiRequest('agent_ingroup_info', $options); 37 | } 38 | 39 | public function agentCampaigns(array $options): string 40 | { 41 | return $this->makeApiRequest('agent_campaigns', $options); 42 | } 43 | 44 | /** 45 | * Get the campaigns list. 46 | * 47 | * @param array $options 48 | */ 49 | public function campaignsList(array $options): string 50 | { 51 | return $this->makeApiRequest('campaigns_list', $options); 52 | } 53 | 54 | /** 55 | * Get the hopper list. 56 | * 57 | * @param array $options 58 | */ 59 | public function hopperList(array $options): string 60 | { 61 | return $this->makeApiRequest('hopper_list', $options); 62 | } 63 | 64 | /** 65 | * Look up recording information. 66 | * 67 | * @param array $options 68 | */ 69 | public function recordingLookup(array $options): string 70 | { 71 | return $this->makeApiRequest('recording_lookup', $options); 72 | } 73 | 74 | /** 75 | * Export DID log. 76 | * 77 | * @param array $options 78 | */ 79 | public function didLogExport(array $options): string 80 | { 81 | return $this->makeApiRequest('did_log_export', $options); 82 | } 83 | 84 | /** 85 | * Get phone number log. 86 | * 87 | * @param array $options 88 | */ 89 | public function phoneNumberLog(array $options): string 90 | { 91 | return $this->makeApiRequest('phone_number_log', $options); 92 | } 93 | 94 | /** 95 | * Export agent stats. 96 | * 97 | * @param array $options 98 | */ 99 | public function agentStatsExport(array $options): string 100 | { 101 | return $this->makeApiRequest('agent_stats_export', $options); 102 | } 103 | 104 | /** 105 | * Get user group status. 106 | * 107 | * @param array $options 108 | */ 109 | public function userGroupStatus(array $options): string 110 | { 111 | return $this->makeApiRequest('user_group_status', $options); 112 | } 113 | 114 | /** 115 | * Get in-group status. 116 | * 117 | * @param array $options 118 | */ 119 | public function inGroupStatus(array $options): string 120 | { 121 | return $this->makeApiRequest('in_group_status', $options); 122 | } 123 | 124 | /** 125 | * Get agent status. 126 | * 127 | * @param array $options 128 | */ 129 | public function agentStatus(array $options): string 130 | { 131 | return $this->makeApiRequest('agent_status', $options); 132 | } 133 | 134 | /** 135 | * Get call ID information. 136 | * 137 | * @param array $options 138 | */ 139 | public function callIdInfo(array $options): string 140 | { 141 | return $this->makeApiRequest('callid_info', $options); 142 | } 143 | 144 | /** 145 | * Get lead field information. 146 | * 147 | * @param array $options 148 | */ 149 | public function leadFieldInfo(array $options): string 150 | { 151 | return $this->makeApiRequest('lead_field_info', $options); 152 | } 153 | 154 | /** 155 | * Search lead status. 156 | * 157 | * @param array $options 158 | */ 159 | public function leadStatusSearch(array $options): string 160 | { 161 | return $this->makeApiRequest('lead_status_search', $options); 162 | } 163 | 164 | /** 165 | * Get CCC lead information. 166 | * 167 | * @param array $options 168 | */ 169 | public function cccLeadInfo(array $options): string 170 | { 171 | return $this->makeApiRequest('ccc_lead_info', $options); 172 | } 173 | 174 | /** 175 | * Get lead callback information. 176 | * 177 | * @param array $options 178 | */ 179 | public function leadCallbackInfo(array $options): string 180 | { 181 | return $this->makeApiRequest('lead_callback_info', $options); 182 | } 183 | 184 | /** 185 | * Update log entry. 186 | * 187 | * @param array $options 188 | */ 189 | public function updateLogEntry(array $options): string 190 | { 191 | return $this->makeApiRequest('update_log_entry', $options); 192 | } 193 | 194 | /** 195 | * Add lead. 196 | * 197 | * @param array $options 198 | */ 199 | public function addLead(array $options): string 200 | { 201 | return $this->makeApiRequest('add_lead', $options); 202 | } 203 | 204 | /** 205 | * Update lead. 206 | * 207 | * @param array $options 208 | */ 209 | public function updateLead(array $options): string 210 | { 211 | return $this->makeApiRequest('update_lead', $options); 212 | } 213 | 214 | /** 215 | * Add user. 216 | * 217 | * @param array $options 218 | */ 219 | public function addUser(array $options): string 220 | { 221 | return $this->makeApiRequest('add_user', $options); 222 | } 223 | 224 | /** 225 | * Update user. 226 | * 227 | * @param array $options 228 | */ 229 | public function updateUser(array $options): string 230 | { 231 | return $this->makeApiRequest('update_user', $options); 232 | } 233 | 234 | /** 235 | * Add group alias. 236 | * 237 | * @param array $options 238 | */ 239 | public function addGroupAlias(array $options): string 240 | { 241 | return $this->makeApiRequest('add_group_alias', $options); 242 | } 243 | 244 | /** 245 | * Add DNC phone. 246 | * 247 | * @param array $options 248 | */ 249 | public function addDncPhone(array $options): string 250 | { 251 | return $this->makeApiRequest('add_dnc_phone', $options); 252 | } 253 | 254 | /** 255 | * Add FPG phone. 256 | * 257 | * @param array $options 258 | */ 259 | public function addFpgPhone(array $options): string 260 | { 261 | return $this->makeApiRequest('add_fpg_phone', $options); 262 | } 263 | 264 | /** 265 | * Add phone. 266 | * 267 | * @param array $options 268 | */ 269 | public function addPhone(array $options): string 270 | { 271 | return $this->makeApiRequest('add_phone', $options); 272 | } 273 | 274 | /** 275 | * Update phone. 276 | * 277 | * @param array $options 278 | */ 279 | public function updatePhone(array $options): string 280 | { 281 | return $this->makeApiRequest('update_phone', $options); 282 | } 283 | 284 | /** 285 | * Add phone alias. 286 | * 287 | * @param array $options 288 | */ 289 | public function addPhoneAlias(array $options): string 290 | { 291 | return $this->makeApiRequest('add_phone_alias', $options); 292 | } 293 | 294 | /** 295 | * Update phone alias. 296 | * 297 | * @param array $options 298 | */ 299 | public function updatePhoneAlias(array $options): string 300 | { 301 | return $this->makeApiRequest('update_phone_alias', $options); 302 | } 303 | 304 | /** 305 | * Refresh server. 306 | * 307 | * @param array $options 308 | */ 309 | public function serverRefresh(array $options): string 310 | { 311 | return $this->makeApiRequest('server_refresh', $options); 312 | } 313 | 314 | /** 315 | * Add list. 316 | * 317 | * @param array $options 318 | */ 319 | public function addList(array $options): string 320 | { 321 | return $this->makeApiRequest('add_list', $options); 322 | } 323 | 324 | /** 325 | * Update list. 326 | * 327 | * @param array $options 328 | */ 329 | public function updateList(array $options): string 330 | { 331 | return $this->makeApiRequest('update_list', $options); 332 | } 333 | 334 | /** 335 | * Get list information. 336 | * 337 | * @param array $options 338 | */ 339 | public function listInfo(array $options): string 340 | { 341 | return $this->makeApiRequest('list_info', $options); 342 | } 343 | 344 | /** 345 | * Get list custom fields. 346 | * 347 | * @param array $options 348 | */ 349 | public function listCustomFields(array $options): string 350 | { 351 | return $this->makeApiRequest('list_custom_fields', $options); 352 | } 353 | 354 | /** 355 | * Check phone number. 356 | * 357 | * @param array $options 358 | */ 359 | public function checkPhoneNumber(array $options): string 360 | { 361 | return $this->makeApiRequest('check_phone_number', $options); 362 | } 363 | 364 | /** 365 | * Get logged-in agents. 366 | * 367 | * @param array $options 368 | */ 369 | public function loggedInAgents(array $options): string 370 | { 371 | return $this->makeApiRequest('logged_in_agents', $options); 372 | } 373 | 374 | /** 375 | * Get call status stats. 376 | * 377 | * @param array $options 378 | */ 379 | public function callStatusStats(array $options): string 380 | { 381 | return $this->makeApiRequest('call_status_stats', $options); 382 | } 383 | 384 | /** 385 | * Get call disposition report. 386 | * 387 | * @param array $options 388 | */ 389 | public function callDispoReport(array $options): string 390 | { 391 | return $this->makeApiRequest('call_dispo_report', $options); 392 | } 393 | 394 | /** 395 | * Update campaign. 396 | * 397 | * @param array $options 398 | */ 399 | public function updateCampaign(array $options): string 400 | { 401 | return $this->makeApiRequest('update_campaign', $options); 402 | } 403 | 404 | /** 405 | * Add DID. 406 | * 407 | * @param array $options 408 | */ 409 | public function addDid(array $options): string 410 | { 411 | return $this->makeApiRequest('add_did', $options); 412 | } 413 | 414 | /** 415 | * Update DID. 416 | * 417 | * @param array $options 418 | */ 419 | public function updateDid(array $options): string 420 | { 421 | return $this->makeApiRequest('update_did', $options); 422 | } 423 | 424 | /** 425 | * Update CID group entry. 426 | * 427 | * @param array $options 428 | */ 429 | public function updateCidGroupEntry(array $options): string 430 | { 431 | return $this->makeApiRequest('update_cid_group_entry', $options); 432 | } 433 | 434 | public function copyUser(array $options): string 435 | { 436 | return $this->makeApiRequest('copy_user', $options); 437 | } 438 | 439 | /** 440 | * Helper method to make the actual API request. 441 | * 442 | * @param array $options 443 | */ 444 | private function makeApiRequest(string $function, array $options): string 445 | { 446 | $options = array_merge($options, [ 447 | 'function' => $function, 448 | ]); 449 | 450 | $payload = Payload::retrieveWithParameters(self::ADMIN_URL, $options); 451 | 452 | return $this->transporter->requestContent($payload); 453 | } 454 | } 455 | -------------------------------------------------------------------------------- /src/Resources/Agent.php: -------------------------------------------------------------------------------- 1 | urlencode(trim($agentUser)), 24 | 'function' => 'external_hangup', 25 | 'value' => '1', 26 | ]); 27 | 28 | return $this->transporter->requestContent($payload); 29 | } 30 | 31 | /** 32 | * Creates the URL for the external_status method and calls 'call_api_url' to execute it 33 | * 34 | * @param array $options 35 | * 36 | * @throws Exception 37 | */ 38 | public function dispo(string $agentUser, array $options): string 39 | { 40 | $options = $options + [ 41 | 'agent_user' => urlencode(trim($agentUser)), 42 | 'function' => 'external_status', 43 | ]; 44 | 45 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 46 | 47 | return $this->transporter->requestContent($payload); 48 | } 49 | 50 | /** 51 | * Creates the URL for the external_pause method and calls 'call_api_url' to execute it 52 | * 53 | * @throws Exception 54 | */ 55 | public function pause(string $agentUser, string $status): string 56 | { 57 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, [ 58 | 'agent_user' => urlencode(trim($agentUser)), 59 | 'function' => 'external_pause', 60 | 'value' => urlencode(trim($status)), 61 | ]); 62 | 63 | return $this->transporter->requestContent($payload); 64 | } 65 | 66 | /** 67 | * Creates the URL for the pause_code method and calls 'call_api_url' to execute it 68 | * 69 | * @throws Exception 70 | */ 71 | public function pauseCode(string $agentUser, string $code): string 72 | { 73 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, [ 74 | 'agent_user' => urlencode(trim($agentUser)), 75 | 'function' => 'pause_code', 76 | 'value' => $code, 77 | ]); 78 | 79 | return $this->transporter->requestContent($payload); 80 | } 81 | 82 | /** 83 | * Creates the URL for the webserver method and calls 'call_api_url' to execute it 84 | * 85 | * @throws Exception 86 | */ 87 | public function webserver(): string 88 | { 89 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, [ 90 | 'function' => 'webserver', 91 | ]); 92 | 93 | return $this->transporter->requestContent($payload); 94 | } 95 | 96 | /** 97 | * Creates the URL for the version method and calls 'call_api_url' to execute it 98 | * 99 | * @throws Exception 100 | */ 101 | public function version(): string 102 | { 103 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, [ 104 | 'function' => 'version', 105 | ]); 106 | 107 | return $this->transporter->requestContent($payload); 108 | } 109 | 110 | /** 111 | * Creates the URL for the logout method and calls 'call_api_url' to execute it 112 | * 113 | * @throws Exception 114 | */ 115 | public function logout(string $agentUser): string 116 | { 117 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, [ 118 | 'agent_user' => urlencode(trim($agentUser)), 119 | 'function' => 'logout', 120 | 'value' => 'LOGOUT', 121 | ]); 122 | 123 | return $this->transporter->requestContent($payload); 124 | } 125 | 126 | /** 127 | * Creates the URL for the external_dial method and calls 'call_api_url' to execute it 128 | * 129 | * @param array $options 130 | * 131 | * @throws Exception 132 | */ 133 | public function dial(string $agentUser, array $options): string 134 | { 135 | if (! isset($options['phone_number'])) { 136 | throw new Exception('Please provide a valid phone number'); 137 | } 138 | 139 | $options = $options + [ 140 | 'agent_user' => urlencode(trim($agentUser)), 141 | 'function' => 'external_dial', 142 | 'value' => urlencode(trim($options['phone_number'])), 143 | 'phone_code' => urlencode(trim($options['phone_code'] ?? '')), 144 | 'search' => 'YES', 145 | 'preview' => 'NO', 146 | 'focus' => 'YES', 147 | ]; 148 | 149 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 150 | 151 | return $this->transporter->requestContent($payload); 152 | } 153 | 154 | /** 155 | * Sends a SKIP, DIALONLY, ALTDIAL, ADR3DIAL or FINISH when a lead is being previewed or in Manual Alt Dial 156 | * 157 | * @throws Exception 158 | */ 159 | public function previewDial(string $agentUser, string $value): string 160 | { 161 | $options = [ 162 | 'agent_user' => urlencode(trim($agentUser)), 163 | 'function' => 'preview_dial_action', 164 | 'value' => urlencode(trim($value)), 165 | ]; 166 | 167 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 168 | 169 | return $this->transporter->requestContent($payload); 170 | } 171 | 172 | /** 173 | * Adds a lead in the manual dial list of the campaign for logged-in agent. A much simplified add lead function compared to the Non-Agent API function 174 | * 175 | * @param array $options 176 | * 177 | * @throws Exception 178 | */ 179 | public function addLead(string $agentUser, array $options): string 180 | { 181 | $options = $options + [ 182 | 'agent_user' => urlencode(trim($agentUser)), 183 | 'function' => 'external_add_lead', 184 | ]; 185 | 186 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 187 | 188 | return $this->transporter->requestContent($payload); 189 | } 190 | 191 | /** 192 | * This function will change the selected in-groups for an agent that is logged into a campaign that allows 193 | * for inbound calls to be handled. Allows the selected in-groups for an agent to be changed while they are 194 | * logged-in to the ViciDial Agent screen only. Once changed in this way, the agent would need to log out 195 | * and back in to be able to select in-groups themselves(If Agent Choose In-Groups is enabled for that user). 196 | * The blended checkbox can also be changed using this function. The API user performing this function must 197 | * have vicidial_users.change_agent_campaign = 1. 198 | * 199 | * @param array $options 200 | * 201 | * @throws Exception 202 | */ 203 | public function changeInGroups(string $agentUser, array $options): string 204 | { 205 | 206 | $options = $options + [ 207 | 'agent_user' => urlencode(trim($agentUser)), 208 | 'function' => 'change_ingroups', 209 | ]; 210 | 211 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 212 | 213 | return $this->transporter->requestContent($payload); 214 | } 215 | 216 | /** 217 | * Creates the URL for the external_dial method and calls 'call_api_url' to execute it 218 | * 219 | * @param array $fieldsToUpdate 220 | * 221 | * @throws Exception 222 | */ 223 | public function updateFields(string $agentUser, array $fieldsToUpdate): string 224 | { 225 | // According to the API documentation only these fields are allowed to update using this method 226 | $allowedFields = ['address1', 'address2', 'address3', 'rank', 'owner', 'vendor_lead_code', 227 | 'alt_phone', 'city', 'comments', 'country_code', 'date_of_birth', 'email', 'first_name', 228 | 'gender', 'gmt_offset_now', 'last_name', 'middle_initial', 'phone_number', 'phone_code', 229 | 'postal_code', 'province', 'security_phrase', 'source_id', 'state', 'title', 230 | ]; 231 | 232 | // Validate that every single field to update us valid 233 | foreach ($fieldsToUpdate as $key => $value) { 234 | if (! in_array($key, $allowedFields)) { 235 | throw new Exception("$key is not a valid field"); 236 | } 237 | } 238 | 239 | $options = $fieldsToUpdate + [ 240 | 'agent_user' => urlencode(trim($agentUser)), 241 | 'function' => 'update_fields', 242 | ]; 243 | 244 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 245 | 246 | return $this->transporter->requestContent($payload); 247 | } 248 | 249 | /** 250 | * Updates the fields that are specified with the values. This will update the data 251 | * that is on the agent's screen in the customer information section. 252 | * 253 | * @param array $options 254 | * 255 | * @throws Exception 256 | */ 257 | public function setTimerAction(string $agentUser, array $options): string 258 | { 259 | $options = $options + [ 260 | 'agent_user' => urlencode(trim($agentUser)), 261 | 'function' => 'set_timer_action', 262 | ]; 263 | 264 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 265 | 266 | return $this->transporter->requestContent($payload); 267 | } 268 | 269 | /** 270 | * Looks up the vicidial_users.custom_three field(as "agentId") to associate with a vicidial user ID. 271 | * If found it will populate the custom_four field with a "teamId" value, then output the vicidial user ID 272 | * 273 | * @param array $options 274 | * 275 | * @throws Exception 276 | */ 277 | public function stLoginLog(array $options): string 278 | { 279 | $options = $options + [ 280 | 'function' => 'st_login_log', 281 | ]; 282 | 283 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 284 | 285 | return $this->transporter->requestContent($payload); 286 | } 287 | 288 | /** 289 | * Looks up the vicidial_users.custom_three field(as "agentId") to associate with a vicidial user ID. 290 | * If found it will output the active lead_id and phone number, vendor_lead_code, province, security_phrase and source_id fields. 291 | * 292 | * @param array $options 293 | * 294 | * @throws Exception 295 | */ 296 | public function stGetAgentActiveLead(array $options): string 297 | { 298 | $options = $options + [ 299 | 'function' => 'st_get_agent_active_lead', 300 | ]; 301 | 302 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 303 | 304 | return $this->transporter->requestContent($payload); 305 | } 306 | 307 | /** 308 | * @param array $options 309 | * 310 | * @throws Exception 311 | */ 312 | public function raCallControl(string $agent, array $options): string 313 | { 314 | $options['agent_user'] = $agent; 315 | $options = $options + [ 316 | 'function' => 'ra_call_control', 317 | ]; 318 | 319 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 320 | 321 | return $this->transporter->requestContent($payload); 322 | } 323 | 324 | /** 325 | * @param array $options 326 | * 327 | * @throws Exception 328 | */ 329 | public function sendDtmf(array $options): string 330 | { 331 | $options = $options + [ 332 | 'function' => 'send_dtmf', 333 | ]; 334 | 335 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 336 | 337 | return $this->transporter->requestContent($payload); 338 | } 339 | 340 | /** 341 | * @param array $options 342 | * 343 | * @throws Exception 344 | */ 345 | public function transferConference(string $agent, array $options): string 346 | { 347 | $options['agent_user'] = $agent; 348 | $options = $options + [ 349 | 'function' => 'transfer_conference', 350 | ]; 351 | 352 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 353 | 354 | return $this->transporter->requestContent($payload); 355 | } 356 | 357 | /** 358 | * @param array $options 359 | * 360 | * @throws Exception 361 | */ 362 | public function parkCall(string $agent, array $options): string 363 | { 364 | $options['agent_user'] = $agent; 365 | $options = $options + [ 366 | 'function' => 'park_call', 367 | ]; 368 | 369 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 370 | 371 | return $this->transporter->requestContent($payload); 372 | } 373 | 374 | /** 375 | * @throws Exception 376 | */ 377 | public function callAgent(string $agentUser, string $value): string 378 | { 379 | $options = [ 380 | 'function' => 'call_agent', 381 | 'agent_user' => urlencode(trim($agentUser)), 382 | 'value' => $value, 383 | ]; 384 | 385 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 386 | 387 | return $this->transporter->requestContent($payload); 388 | } 389 | 390 | /** 391 | * @param array $options 392 | * 393 | * @throws Exception 394 | */ 395 | public function recording(string $agent, array $options): string 396 | { 397 | $options['agent_user'] = $agent; 398 | $options = $options + [ 399 | 'function' => 'recording', 400 | ]; 401 | 402 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 403 | 404 | return $this->transporter->requestContent($payload); 405 | } 406 | 407 | /** 408 | * @throws Exception 409 | */ 410 | public function webPhoneUrl(string $agentUser, string $value): string 411 | { 412 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, [ 413 | 'agent_user' => urlencode(trim($agentUser)), 414 | 'function' => 'webphone_url', 415 | 'value' => urlencode(trim($value)), 416 | ]); 417 | 418 | return $this->transporter->requestContent($payload); 419 | } 420 | 421 | /** 422 | * @param array $options 423 | * 424 | * @throws Exception 425 | */ 426 | public function audioPlayBack(string $agentUser, array $options): string 427 | { 428 | $options['agent_user'] = $agentUser; 429 | $options = $options + [ 430 | 'function' => 'audio_playback', 431 | ]; 432 | 433 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 434 | 435 | return $this->transporter->requestContent($payload); 436 | } 437 | 438 | /** 439 | * Creates the URL for the pause_code method and calls 'call_api_url' to execute it 440 | * 441 | * @throws Exception 442 | */ 443 | public function switchLead(string $agentUser, string $leadId): string 444 | { 445 | $options = [ 446 | 'agent_user' => urlencode(trim($agentUser)), 447 | 'function' => 'switch_lead', 448 | 'value' => urlencode(trim($leadId)), 449 | ]; 450 | 451 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 452 | 453 | return $this->transporter->requestContent($payload); 454 | } 455 | 456 | /** 457 | * Set a custom voicemail message to be played when agent clicks the VM button on the agent screen 458 | * 459 | * @param array $options 460 | * 461 | * @throws Exception 462 | */ 463 | public function vmMessage(string $agentUser, array $options): string 464 | { 465 | $options['agent_user'] = $agentUser; 466 | $options = $options + [ 467 | 'function' => 'vm_message', 468 | ]; 469 | 470 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 471 | 472 | return $this->transporter->requestContent($payload); 473 | } 474 | 475 | /** 476 | * display a count of the calls waiting in queue for the specific agent 477 | * 478 | * @throws Exception 479 | */ 480 | public function callsInQueueCount(string $agentUser, string $status): string 481 | { 482 | $options = [ 483 | 'agent_user' => urlencode(trim($agentUser)), 484 | 'function' => 'calls_in_queue_count', 485 | 'value' => urlencode(trim($status)), 486 | ]; 487 | 488 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 489 | 490 | return $this->transporter->requestContent($payload); 491 | } 492 | 493 | /** 494 | * @throws Exception 495 | */ 496 | public function forceFronterLeave3way(string $agentUser, string $status): string 497 | { 498 | $options = [ 499 | 'agent_user' => urlencode(trim($agentUser)), 500 | 'function' => 'force_fronter_leave_3way', 501 | 'value' => urlencode(trim($status)), 502 | ]; 503 | 504 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 505 | 506 | return $this->transporter->requestContent($payload); 507 | } 508 | 509 | /** 510 | * @throws Exception 511 | */ 512 | public function forceFronterAudioStop(string $agentUser, string $status): string 513 | { 514 | $options = [ 515 | 'agent_user' => urlencode(trim($agentUser)), 516 | 'function' => 'force_fronter_audio_stop', 517 | 'value' => urlencode(trim($status)), 518 | ]; 519 | 520 | $payload = Payload::retrieveWithParameters(self::AGENT_URL, $options); 521 | 522 | return $this->transporter->requestContent($payload); 523 | } 524 | } 525 | -------------------------------------------------------------------------------- /src/Resources/Concerns/Streamable.php: -------------------------------------------------------------------------------- 1 | $parameters 11 | * 12 | * @throws InvalidArgumentException 13 | */ 14 | private function ensureNotStreamed(array $parameters): void 15 | { 16 | if (! isset($parameters['stream'])) { 17 | return; 18 | } 19 | 20 | if ($parameters['stream'] !== true) { 21 | return; 22 | } 23 | 24 | throw new InvalidArgumentException('Stream option is not supported. Please use the createStreamed() method instead.'); 25 | } 26 | 27 | /** 28 | * Set the stream parameter to true. 29 | * 30 | * @param array $parameters 31 | * @return array 32 | */ 33 | private function setStreamParameter(array $parameters): array 34 | { 35 | $parameters['stream'] = true; 36 | 37 | return $parameters; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Resources/Concerns/Transportable.php: -------------------------------------------------------------------------------- 1 | agent = new Agent($this->transporter); 22 | } 23 | 24 | /** 25 | * @throws ErrorException 26 | * @throws TransporterException 27 | */ 28 | public function active( 29 | string $remoteAgentId, 30 | string $confExten, 31 | int $numberOfLines = 1, 32 | ): string { 33 | $payload = Payload::retrieveWithParameters(self::REMOTE_AGENT_END_POINT, [ 34 | 'status' => 'ACTIVE', 35 | 'ADD' => self::ACTION, 36 | 'remote_agent_id' => $remoteAgentId, 37 | 'number_of_lines' => $numberOfLines, 38 | 'conf_exten' => $confExten, 39 | ]); 40 | 41 | return $this->transporter->requestContent($payload); 42 | } 43 | 44 | /** 45 | * @throws ErrorException 46 | * @throws TransporterException 47 | */ 48 | public function inactive( 49 | string $remoteAgentId, 50 | string $confExten, 51 | int $numberOfLines = 1, 52 | ): string { 53 | $payload = Payload::retrieveWithParameters(self::REMOTE_AGENT_END_POINT, [ 54 | 'status' => 'INACTIVE', 55 | 'ADD' => self::ACTION, 56 | 'remote_agent_id' => $remoteAgentId, 57 | 'number_of_lines' => $numberOfLines, 58 | 'conf_exten' => $confExten, 59 | ]); 60 | 61 | return $this->transporter->requestContent($payload); 62 | } 63 | 64 | /** 65 | * @throws \Exception 66 | */ 67 | public function hangUp(string $agent, array $options): string 68 | { 69 | return $this->agent->raCallControl( 70 | $agent, 71 | $options 72 | ); 73 | } 74 | 75 | public function transfer(string $agent, array $options): string 76 | { 77 | return $this->agent->raCallControl( 78 | $agent, 79 | $options 80 | ); 81 | } 82 | 83 | public function ingroupTransfer(string $agent, array $options): string 84 | { 85 | return $this->agent->raCallControl( 86 | $agent, 87 | $options 88 | ); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/Responses/Concerns/ArrayAccessible.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | trait ArrayAccessible 15 | { 16 | /** 17 | * {@inheritDoc} 18 | */ 19 | public function offsetExists(mixed $offset): bool 20 | { 21 | return array_key_exists($offset, $this->toArray()); 22 | } 23 | 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | public function offsetGet(mixed $offset): mixed 28 | { 29 | return $this->toArray()[$offset]; 30 | } 31 | 32 | /** 33 | * {@inheritDoc} 34 | */ 35 | public function offsetSet(mixed $offset, mixed $value): never 36 | { 37 | throw new BadMethodCallException('Cannot set response attributes.'); 38 | } 39 | 40 | /** 41 | * {@inheritDoc} 42 | */ 43 | public function offsetUnset(mixed $offset): never 44 | { 45 | throw new BadMethodCallException('Cannot unset response attributes.'); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Responses/Concerns/HasMetaInformation.php: -------------------------------------------------------------------------------- 1 | meta; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Responses/StreamResponse.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | final class StreamResponse implements IteratorAggregate 17 | { 18 | /** 19 | * Creates a new Stream Response instance. 20 | * 21 | * @param class-string $responseClass 22 | */ 23 | public function __construct( 24 | private readonly string $responseClass, 25 | private readonly ResponseInterface $response, 26 | ) { 27 | // 28 | } 29 | 30 | /** 31 | * {@inheritDoc} 32 | */ 33 | public function getIterator(): Generator 34 | { 35 | while (! $this->response->getBody()->eof()) { 36 | $line = $this->readLine($this->response->getBody()); 37 | 38 | if (! str_starts_with($line, 'data:')) { 39 | continue; 40 | } 41 | 42 | $data = trim(substr($line, strlen('data:'))); 43 | 44 | if ($data === '[DONE]') { 45 | break; 46 | } 47 | 48 | /** @var array{error?: array{message: string|array, type: string, code: string}} $response */ 49 | $response = json_decode($data, true, 512, JSON_THROW_ON_ERROR); 50 | 51 | if (isset($response['error'])) { 52 | throw new ErrorException($response['error']); 53 | } 54 | 55 | yield $this->responseClass::from($response); 56 | } 57 | } 58 | 59 | /** 60 | * Read a line from the stream. 61 | */ 62 | private function readLine(StreamInterface $stream): string 63 | { 64 | $buffer = ''; 65 | 66 | while (! $stream->eof()) { 67 | if ('' === ($byte = $stream->read(1))) { 68 | return $buffer; 69 | } 70 | $buffer .= $byte; 71 | if ($byte === "\n") { 72 | break; 73 | } 74 | } 75 | 76 | return $buffer; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Transporters/HttpTransporter.php: -------------------------------------------------------------------------------- 1 | toRequest($this->baseUri, $this->headers, $this->queryParams); 42 | 43 | $response = $this->sendRequest(fn (): \Psr\Http\Message\ResponseInterface => $this->client->sendRequest($request)); 44 | 45 | $contents = $response->getBody()->getContents(); 46 | 47 | if (str_contains($response->getHeaderLine('Content-Type'), ContentType::TEXT_PLAIN->value)) { 48 | return Response::from($contents); 49 | } 50 | 51 | $this->throwIfJsonError($response, $contents); 52 | 53 | try { 54 | /** @var array{error?: array{message: string, type: string, code: string}} $data */ 55 | $data = json_decode($contents, true, 512, JSON_THROW_ON_ERROR); 56 | } catch (JsonException $jsonException) { 57 | throw new UnserializableResponse($jsonException); 58 | } 59 | 60 | return Response::from($data); 61 | } 62 | 63 | /** 64 | * {@inheritDoc} 65 | */ 66 | public function requestContent(Payload $payload): string 67 | { 68 | $request = $payload->toRequest($this->baseUri, $this->headers, $this->queryParams); 69 | $response = $this->sendRequest(fn (): \Psr\Http\Message\ResponseInterface => $this->client->sendRequest($request)); 70 | 71 | $contents = $response->getBody()->getContents(); 72 | 73 | $this->throwIfJsonError($response, $contents); 74 | 75 | return $contents; 76 | } 77 | 78 | /** 79 | * {@inheritDoc} 80 | */ 81 | public function requestStream(Payload $payload): ResponseInterface 82 | { 83 | $request = $payload->toRequest($this->baseUri, $this->headers, $this->queryParams); 84 | 85 | $response = $this->sendRequest(fn () => ($this->streamHandler)($request)); 86 | 87 | $this->throwIfJsonError($response, $response); 88 | 89 | return $response; 90 | } 91 | 92 | private function sendRequest(Closure $callable): ResponseInterface 93 | { 94 | try { 95 | return $callable(); 96 | } catch (ClientExceptionInterface $clientException) { 97 | if ($clientException instanceof ClientException) { 98 | $this->throwIfJsonError($clientException->getResponse(), $clientException->getResponse()->getBody()->getContents()); 99 | } 100 | 101 | throw new TransporterException($clientException); 102 | } 103 | } 104 | 105 | private function throwIfJsonError(ResponseInterface $response, string|ResponseInterface $contents): void 106 | { 107 | if ($response->getStatusCode() < 400) { 108 | return; 109 | } 110 | 111 | if (! str_contains($response->getHeaderLine('Content-Type'), ContentType::JSON->value)) { 112 | return; 113 | } 114 | 115 | if ($contents instanceof ResponseInterface) { 116 | $contents = $contents->getBody()->getContents(); 117 | } 118 | 119 | try { 120 | /** @var array{error?: array{message: string|array, type: string, code: string}} $response */ 121 | $response = json_decode($contents, true, 512, JSON_THROW_ON_ERROR); 122 | 123 | if (isset($response['error'])) { 124 | throw new ErrorException($response['error']); 125 | } 126 | } catch (JsonException $jsonException) { 127 | throw new UnserializableResponse($jsonException); 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/ValueObjects/ApiKey.php: -------------------------------------------------------------------------------- 1 | apiKey; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/ValueObjects/BasicAuth.php: -------------------------------------------------------------------------------- 1 | username}:{$this->password}"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/ValueObjects/Parameter.php: -------------------------------------------------------------------------------- 1 | $values 22 | */ 23 | public static function fromArray(array $values): self 24 | { 25 | return new self(implode(',', $values)); 26 | } 27 | 28 | public static function fromObject(object $value): self 29 | { 30 | return new self(json_encode($value, JSON_THROW_ON_ERROR) ?: ''); 31 | } 32 | 33 | public function toString(): string 34 | { 35 | if (is_scalar($this->value) || $this->value === null) { 36 | return strval($this->value); 37 | } 38 | 39 | if (is_object($this->value)) { 40 | return static::fromObject($this->value)->toString(); 41 | } 42 | 43 | if (is_array($this->value)) { 44 | return static::fromArray($this->value)->toString(); 45 | } 46 | 47 | throw new \InvalidArgumentException('Parameter value must be scalar or null'); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/ValueObjects/ResourceUri.php: -------------------------------------------------------------------------------- 1 | uri; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/ValueObjects/Transporter/BaseUri.php: -------------------------------------------------------------------------------- 1 | baseUri, $protocol)) { 37 | return "{$this->baseUri}/"; 38 | } 39 | } 40 | 41 | return "https://{$this->baseUri}/"; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/ValueObjects/Transporter/Headers.php: -------------------------------------------------------------------------------- 1 | $headers 20 | */ 21 | private function __construct(private readonly array $headers) 22 | { 23 | // .. 24 | } 25 | 26 | /** 27 | * Creates a new Headers value object 28 | */ 29 | public static function create(): self 30 | { 31 | return new self([]); 32 | } 33 | 34 | /** 35 | * Creates a new Headers value object with the given API token. 36 | */ 37 | public static function withAuthorization(ApiKey $apiKey): self 38 | { 39 | return new self([ 40 | 'Authorization' => "Bearer {$apiKey->toString()}", 41 | ]); 42 | } 43 | 44 | public static function withBasicAuthorization(BasicAuth $basicAuth): self 45 | { 46 | return new self([ 47 | 'Authorization' => "Basic {$basicAuth->encode()}", 48 | ]); 49 | } 50 | 51 | /** 52 | * Creates a new Headers value object, with the given content type, and the existing headers. 53 | */ 54 | public function withContentType(ContentType $contentType, string $suffix = ''): self 55 | { 56 | return new self([ 57 | ...$this->headers, 58 | 'Content-Type' => $contentType->value.$suffix, 59 | ]); 60 | } 61 | 62 | /** 63 | * Creates a new Headers value object, with the newly added header, and the existing headers. 64 | */ 65 | public function withCustomHeader(string $name, string $value): self 66 | { 67 | return new self([ 68 | ...$this->headers, 69 | $name => $value, 70 | ]); 71 | } 72 | 73 | /** 74 | * @return array $headers 75 | */ 76 | public function toArray(): array 77 | { 78 | return $this->headers; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/ValueObjects/Transporter/Payload.php: -------------------------------------------------------------------------------- 1 | $parameters 25 | */ 26 | private function __construct( 27 | private readonly ContentType $contentType, 28 | private readonly Method $method, 29 | private readonly ResourceUri $uri, 30 | private readonly array $parameters = [], 31 | ) { 32 | // .. 33 | } 34 | 35 | /** 36 | * Creates a new Payload value object from the given parameters. 37 | */ 38 | public static function list(string $resource): self 39 | { 40 | $contentType = ContentType::JSON; 41 | $method = Method::GET; 42 | $uri = ResourceUri::list($resource); 43 | 44 | return new self($contentType, $method, $uri); 45 | } 46 | 47 | /** 48 | * Creates a new Payload value object from the given parameters. 49 | */ 50 | public static function retrieve(string $resource, string $id, string $suffix = ''): self 51 | { 52 | $contentType = ContentType::JSON; 53 | $method = Method::GET; 54 | $uri = ResourceUri::retrieve($resource, $id, $suffix); 55 | 56 | return new self($contentType, $method, $uri); 57 | } 58 | 59 | /** 60 | * Creates a new Payload value object from the given parameters. 61 | */ 62 | public static function retrieveContent(string $resource, string $id): self 63 | { 64 | $contentType = ContentType::JSON; 65 | $method = Method::GET; 66 | $uri = ResourceUri::retrieveContent($resource, $id); 67 | 68 | return new self($contentType, $method, $uri); 69 | } 70 | 71 | /** 72 | * Creates a new Payload value object from the given parameters. 73 | * 74 | * @param array $parameters 75 | */ 76 | public static function create(string $resource, array $parameters): self 77 | { 78 | $contentType = ContentType::JSON; 79 | $method = Method::POST; 80 | $uri = ResourceUri::create($resource); 81 | 82 | return new self($contentType, $method, $uri, $parameters); 83 | } 84 | 85 | /** 86 | * Creates a new Payload value object from the given parameters. 87 | * 88 | * @param array $parameters 89 | */ 90 | public static function retrieveWithParameters(string $resource, array $parameters): self 91 | { 92 | $contentType = ContentType::JSON; 93 | $method = Method::GET; 94 | $uri = ResourceUri::create($resource); 95 | 96 | return new self($contentType, $method, $uri, $parameters); 97 | } 98 | 99 | /** 100 | * Creates a new Payload value object from the given parameters. 101 | * 102 | * @param array $parameters 103 | */ 104 | public static function upload(string $resource, array $parameters): self 105 | { 106 | $contentType = ContentType::MULTIPART; 107 | $method = Method::POST; 108 | $uri = ResourceUri::upload($resource); 109 | 110 | return new self($contentType, $method, $uri, $parameters); 111 | } 112 | 113 | /** 114 | * Creates a new Payload value object from the given parameters. 115 | */ 116 | public static function cancel(string $resource, string $id): self 117 | { 118 | $contentType = ContentType::JSON; 119 | $method = Method::POST; 120 | $uri = ResourceUri::cancel($resource, $id); 121 | 122 | return new self($contentType, $method, $uri); 123 | } 124 | 125 | /** 126 | * Creates a new Payload value object from the given parameters. 127 | */ 128 | public static function delete(string $resource, string $id): self 129 | { 130 | $contentType = ContentType::JSON; 131 | $method = Method::DELETE; 132 | $uri = ResourceUri::delete($resource, $id); 133 | 134 | return new self($contentType, $method, $uri); 135 | } 136 | 137 | /** 138 | * Creates a new Psr 7 Request instance. 139 | */ 140 | public function toRequest(BaseUri $baseUri, Headers $headers, QueryParams $queryParams): RequestInterface 141 | { 142 | $psr17Factory = new Psr17Factory(); 143 | 144 | $body = null; 145 | 146 | $uri = $baseUri->toString().$this->uri->toString(); 147 | 148 | if ($this->method === Method::GET && ! empty($this->parameters)) { 149 | foreach ($this->parameters as $key => $value) { 150 | $queryParams = $queryParams->withParam($key, Parameter::from($value)->toString()); 151 | } 152 | } 153 | 154 | if (! empty($queryParams->toArray())) { 155 | $uri .= '?'.http_build_query($queryParams->toArray()); 156 | } 157 | 158 | $headers = $headers->withContentType($this->contentType); 159 | 160 | if ($this->method === Method::POST) { 161 | if ($this->contentType === ContentType::MULTIPART) { 162 | $streamBuilder = new MultipartStreamBuilder($psr17Factory); 163 | 164 | /** @var array $parameters */ 165 | $parameters = $this->parameters; 166 | 167 | foreach ($parameters as $key => $value) { 168 | if (is_int($value) || is_float($value) || is_bool($value)) { 169 | $value = (string) $value; 170 | } 171 | 172 | $streamBuilder->addResource($key, $value); 173 | } 174 | 175 | $body = $streamBuilder->build(); 176 | 177 | $headers = $headers->withContentType($this->contentType, '; boundary='.$streamBuilder->getBoundary()); 178 | } else { 179 | $body = $psr17Factory->createStream(json_encode($this->parameters, JSON_THROW_ON_ERROR)); 180 | } 181 | } 182 | 183 | $request = $psr17Factory->createRequest($this->method->value, $uri); 184 | 185 | if ($body instanceof StreamInterface) { 186 | $request = $request->withBody($body); 187 | } 188 | 189 | foreach ($headers->toArray() as $name => $value) { 190 | $request = $request->withHeader($name, $value); 191 | } 192 | 193 | return $request; 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /src/ValueObjects/Transporter/QueryParams.php: -------------------------------------------------------------------------------- 1 | $params 16 | */ 17 | private function __construct(private readonly array $params) 18 | { 19 | // .. 20 | } 21 | 22 | /** 23 | * Creates a new Query Params value object 24 | */ 25 | public static function create(): self 26 | { 27 | return new self([]); 28 | } 29 | 30 | /** 31 | * Creates a new Query Params value object, with the newly added param, and the existing params. 32 | */ 33 | public function withParam(string $name, string|int $value): self 34 | { 35 | return new self([ 36 | ...$this->params, 37 | $name => $value, 38 | ]); 39 | } 40 | 41 | /** 42 | * @return array 43 | */ 44 | public function toArray(): array 45 | { 46 | return $this->params; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/ValueObjects/Transporter/Response.php: -------------------------------------------------------------------------------- 1 | 30 | */ 31 | public static function from(array|string $data): self 32 | { 33 | return new self($data); 34 | } 35 | 36 | /** 37 | * Returns the response data. 38 | * 39 | * @return TData 40 | */ 41 | public function data(): array|string 42 | { 43 | return $this->data; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/VicidialApi.php: -------------------------------------------------------------------------------- 1 | withBaseUri($baseUri) 17 | ->withApiUser($apiUser) 18 | ->withApiPass($apiPassword) 19 | ->make(); 20 | } 21 | 22 | public function createWithBasicAuth( 23 | string $baseUri, 24 | string $apiUser, 25 | string $apiPassword, 26 | string $username, 27 | string $password 28 | ): Client { 29 | return self::factory() 30 | ->withBaseUri($baseUri) 31 | ->withApiUser($apiUser) 32 | ->withApiPass($apiPassword) 33 | ->withBasicAuth($username, $password) 34 | ->make(); 35 | } 36 | 37 | /** 38 | * Creates a new factory instance to configure a custom Open AI Client 39 | */ 40 | public static function factory(): Factory 41 | { 42 | return new Factory(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/ClientTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf(Agent::class, $client->agent()); 18 | } 19 | 20 | public function testHasAdmin(): void 21 | { 22 | $client = VicidialApi::create( 23 | 'localhost', 24 | 'testUser', 25 | 'testPassword', 26 | ); 27 | 28 | $this->assertInstanceOf(Admin::class, $client->admin()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/FactoryTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf(Factory::class, $client); 16 | } 17 | 18 | public function testFactoryWithCustomUrl(): void 19 | { 20 | $client = VicidialApi::factory() 21 | ->withBaseUri('http://localhost') 22 | ->withApiUser('testUser') 23 | ->withApiPass('testPassword') 24 | ->make(); 25 | 26 | $this->assertInstanceOf(Client::class, $client); 27 | } 28 | 29 | public function testFactoryWithCustomUrlAndCustomClient(): void 30 | { 31 | $client = VicidialApi::factory() 32 | ->withBaseUri('http://localhost') 33 | ->withApiUser('testUser') 34 | ->withApiPass('testPassword') 35 | ->withHttpClient(new \GuzzleHttp\Client()) 36 | ->make(); 37 | 38 | $this->assertInstanceOf(Client::class, $client); 39 | } 40 | 41 | public function testCustomStreamViaFactory(): void 42 | { 43 | $vicidialApi = VicidialApi::factory() 44 | ->withBaseUri('http://localhost') 45 | ->withApiUser('testUser') 46 | ->withApiPass('testPassword') 47 | ->withHttpClient($client = new \GuzzleHttp\Client()) 48 | ->withStreamHandler(fn (RequestInterface $request): ResponseInterface => $client->send($request, ['stream' => true])) 49 | ->make(); 50 | 51 | $this->assertInstanceOf(Client::class, $vicidialApi); 52 | } 53 | 54 | public function testWithHttpHeaders(): void 55 | { 56 | $client = VicidialApi::factory() 57 | ->withBaseUri('http://localhost') 58 | ->withApiUser('testUser') 59 | ->withApiPass('testPassword') 60 | ->withHttpHeader('X-Test', 'test') 61 | ->make(); 62 | 63 | $this->assertInstanceOf(Client::class, $client); 64 | } 65 | 66 | public function testWithQueryParam(): void 67 | { 68 | $client = VicidialApi::factory() 69 | ->withBaseUri('http://localhost') 70 | ->withApiUser('testUser') 71 | ->withApiPass('testPassword') 72 | ->withQueryParam('test', 'test') 73 | ->make(); 74 | 75 | $this->assertInstanceOf(Client::class, $client); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /tests/Fakers/FakeGuzzleClient.php: -------------------------------------------------------------------------------- 1 | content); 22 | } 23 | 24 | public function requestContent(Payload $payload): string 25 | { 26 | return $this->contentToString(); 27 | } 28 | 29 | public function requestStream(Payload $payload): ResponseInterface 30 | { 31 | $stream = Utils::streamFor($this->contentToString()); 32 | 33 | return new GuzzleResponse(200, [], $stream); // This is a fake response 34 | } 35 | 36 | private function contentToString(): string 37 | { 38 | return is_array($this->content) ? json_encode($this->content) : $this->content; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/Resources/AgentTest.php: -------------------------------------------------------------------------------- 1 | assertEquals('PAUSE', $agent->pauseCode('testuser', '1234')); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf(Client::class, $client); 20 | } 21 | 22 | public function testCreateFactoryCorrectly(): void 23 | { 24 | $client = VicidialApi::factory(); 25 | 26 | $this->assertInstanceOf(Factory::class, $client); 27 | } 28 | 29 | public function testFactoryWithCustomUrl(): void 30 | { 31 | $client = VicidialApi::factory() 32 | ->withBaseUri('http://localhost') 33 | ->withApiUser('testUser') 34 | ->withApiPass('testPassword') 35 | ->make(); 36 | 37 | $this->assertInstanceOf(Client::class, $client); 38 | } 39 | 40 | public function testFactoryWithCustomUrlAndCustomClient(): void 41 | { 42 | $client = VicidialApi::factory() 43 | ->withBaseUri('http://localhost') 44 | ->withApiUser('testUser') 45 | ->withApiPass('testPassword') 46 | ->withHttpClient(new \GuzzleHttp\Client()) 47 | ->make(); 48 | 49 | $this->assertInstanceOf(Client::class, $client); 50 | } 51 | 52 | public function testCustomStreamViaFactory(): void 53 | { 54 | $vicidialApi = VicidialApi::factory() 55 | ->withBaseUri('http://localhost') 56 | ->withApiUser('testUser') 57 | ->withApiPass('testPassword') 58 | ->withHttpClient($client = new \GuzzleHttp\Client()) 59 | ->withStreamHandler(fn (RequestInterface $request): ResponseInterface => $client->send($request, ['stream' => true])) 60 | ->make(); 61 | 62 | $this->assertInstanceOf(Client::class, $vicidialApi); 63 | } 64 | } 65 | --------------------------------------------------------------------------------