diff --git a/src/Voice/Bxml/Connect.php b/src/Voice/Bxml/Connect.php
new file mode 100644
index 0000000..1cd34e9
--- /dev/null
+++ b/src/Voice/Bxml/Connect.php
@@ -0,0 +1,54 @@
+endpoints = $endpoints;
+ }
+
+ /**
+ * Add an Endpoint to the Connect verb
+ *
+ * @param Endpoint $endpoint
+ * @return $this
+ */
+ public function addEndpoint(Endpoint $endpoint): Connect {
+ $this->endpoints[] = $endpoint;
+ return $this;
+ }
+
+ /**
+ * Converts the Connect verb into a DOMElement
+ *
+ * @param DOMDocument $doc
+ * @return DOMElement
+ */
+ public function toBxml(DOMDocument $doc): DOMElement {
+ $element = $doc->createElement("Connect");
+ foreach ($this->endpoints as $endpoint) {
+ $element->appendChild($endpoint->toBxml($doc));
+ }
+ return $element;
+ }
+}
diff --git a/src/Voice/Bxml/Endpoint.php b/src/Voice/Bxml/Endpoint.php
new file mode 100644
index 0000000..445dff2
--- /dev/null
+++ b/src/Voice/Bxml/Endpoint.php
@@ -0,0 +1,41 @@
+id = $id;
+ }
+
+ /**
+ * Converts the Endpoint verb into a DOMElement
+ *
+ * @param DOMDocument $doc
+ * @return DOMElement
+ */
+ public function toBxml(DOMDocument $doc): DOMElement {
+ $element = $doc->createElement("Endpoint");
+ $element->setAttribute("id", $this->id);
+ return $element;
+ }
+}
diff --git a/src/Voice/Controllers/APIController.php b/src/Voice/Controllers/APIController.php
index 82a7461..3af06fd 100644
--- a/src/Voice/Controllers/APIController.php
+++ b/src/Voice/Controllers/APIController.php
@@ -929,7 +929,7 @@ public function getDownloadCallRecording(
) {
//prepare query string for API call
- $_queryBuilder =
+ $_queryBuilder =
'/api/v2/accounts/{accountId}/calls/{callId}/recordings/{recordingId}/media';
//process optional query parameters
@@ -1040,7 +1040,7 @@ public function deleteRecordingMedia(
) {
//prepare query string for API call
- $_queryBuilder =
+ $_queryBuilder =
'/api/v2/accounts/{accountId}/calls/{callId}/recordings/{recordingId}/media';
//process optional query parameters
@@ -1149,7 +1149,7 @@ public function getCallTranscription(
) {
//prepare query string for API call
- $_queryBuilder =
+ $_queryBuilder =
'/api/v2/accounts/{accountId}/calls/{callId}/recordings/{recordingId}/transcription';
//process optional query parameters
@@ -1266,7 +1266,7 @@ public function createTranscribeCallRecording(
) {
//prepare query string for API call
- $_queryBuilder =
+ $_queryBuilder =
'/api/v2/accounts/{accountId}/calls/{callId}/recordings/{recordingId}/transcription';
//process optional query parameters
@@ -1386,7 +1386,7 @@ public function deleteCallTranscription(
) {
//prepare query string for API call
- $_queryBuilder =
+ $_queryBuilder =
'/api/v2/accounts/{accountId}/calls/{callId}/recordings/{recordingId}/transcription';
//process optional query parameters
@@ -1952,7 +1952,7 @@ public function getConferenceMember(
) {
//prepare query string for API call
- $_queryBuilder =
+ $_queryBuilder =
'/api/v2/accounts/{accountId}/conferences/{conferenceId}/members/{memberId}';
//process optional query parameters
@@ -2179,7 +2179,7 @@ public function getConferenceRecording(
) {
//prepare query string for API call
- $_queryBuilder =
+ $_queryBuilder =
'/api/v2/accounts/{accountId}/conferences/{conferenceId}/recordings/{recordingId}';
//process optional query parameters
@@ -2294,7 +2294,7 @@ public function getDownloadConferenceRecording(
) {
//prepare query string for API call
- $_queryBuilder =
+ $_queryBuilder =
'/api/v2/accounts/{accountId}/conferences/{conferenceId}/recordings/{recordingId}/media';
//process optional query parameters
@@ -2514,4 +2514,204 @@ public function getQueryCallRecordings(
);
return new ApiResponse($response->code, $response->headers, $deserializedResponse);
}
+
+ /**
+ * Creates a BRTC endpoint.
+ *
+ * @param string $accountId
+ * @param Models\CreateEndpointRequest $body
+ * @return ApiResponse response from the API call
+ * @throws APIException Thrown if API call fails
+ */
+ public function createEndpoint(
+ string $accountId,
+ Models\CreateEndpointRequest $body
+ ) {
+ $_queryBuilder = '/accounts/{accountId}/endpoints';
+ $_queryBuilder = APIHelper::appendUrlWithTemplateParameters($_queryBuilder, array(
+ 'accountId' => $accountId,
+ ));
+ $_queryUrl = APIHelper::cleanUrl($this->config->getBaseUri(Servers::PHONENUMBERLOOKUPDEFAULT) . $_queryBuilder);
+ $_headers = array(
+ 'user-agent' => BaseController::USER_AGENT,
+ 'Accept' => 'application/json',
+ 'content-type' => 'application/json; charset=utf-8'
+ );
+ $_bodyJson = Request\Body::Json($body);
+ $this->configureAuth($_headers, 'voice');
+ $_httpRequest = new HttpRequest(HttpMethod::POST, $_headers, $_queryUrl);
+ if ($this->getHttpCallBack() != null) {
+ $this->getHttpCallBack()->callOnBeforeRequest($_httpRequest);
+ }
+ Request::timeout($this->config->getTimeout());
+ $response = Request::post($_queryUrl, $_headers, $_bodyJson);
+ $_httpResponse = new HttpResponse($response->code, $response->headers, $response->raw_body);
+ $_httpContext = new HttpContext($_httpRequest, $_httpResponse);
+ if ($this->getHttpCallBack() != null) {
+ $this->getHttpCallBack()->callOnAfterRequest($_httpContext);
+ }
+ $this->validateResponse($_httpResponse, $_httpContext);
+ $mapper = $this->getJsonMapper();
+ $deserializedResponse = $mapper->mapClass($response->body, 'BandwidthLib\\Voice\\Models\\CreateEndpointResponse');
+ return new ApiResponse($response->code, $response->headers, $deserializedResponse);
+ }
+
+ /**
+ * Lists BRTC endpoints for an account.
+ *
+ * @param string $accountId
+ * @param array $queryParams Optional filter/pagination params
+ * @return ApiResponse response from the API call
+ * @throws APIException Thrown if API call fails
+ */
+ public function listEndpoints(
+ string $accountId,
+ array $queryParams = []
+ ) {
+ $_queryBuilder = '/accounts/{accountId}/endpoints';
+ $_queryBuilder = APIHelper::appendUrlWithTemplateParameters($_queryBuilder, array(
+ 'accountId' => $accountId,
+ ));
+ if (!empty($queryParams)) {
+ $_queryBuilder = APIHelper::appendUrlWithQueryParameters($_queryBuilder, $queryParams);
+ }
+ $_queryUrl = APIHelper::cleanUrl($this->config->getBaseUri(Servers::PHONENUMBERLOOKUPDEFAULT) . $_queryBuilder);
+ $_headers = array(
+ 'user-agent' => BaseController::USER_AGENT,
+ 'Accept' => 'application/json'
+ );
+ $this->configureAuth($_headers, 'voice');
+ $_httpRequest = new HttpRequest(HttpMethod::GET, $_headers, $_queryUrl);
+ if ($this->getHttpCallBack() != null) {
+ $this->getHttpCallBack()->callOnBeforeRequest($_httpRequest);
+ }
+ Request::timeout($this->config->getTimeout());
+ $response = Request::get($_queryUrl, $_headers);
+ $_httpResponse = new HttpResponse($response->code, $response->headers, $response->raw_body);
+ $_httpContext = new HttpContext($_httpRequest, $_httpResponse);
+ if ($this->getHttpCallBack() != null) {
+ $this->getHttpCallBack()->callOnAfterRequest($_httpContext);
+ }
+ $this->validateResponse($_httpResponse, $_httpContext);
+ $mapper = $this->getJsonMapper();
+ $deserializedResponse = $mapper->mapClassArray($response->body, 'BandwidthLib\\Voice\\Models\\Endpoint');
+ return new ApiResponse($response->code, $response->headers, $deserializedResponse);
+ }
+
+ /**
+ * Gets details for a specific BRTC endpoint.
+ *
+ * @param string $accountId
+ * @param string $endpointId
+ * @return ApiResponse response from the API call
+ * @throws APIException Thrown if API call fails
+ */
+ public function getEndpoint(
+ string $accountId,
+ string $endpointId
+ ) {
+ $_queryBuilder = '/accounts/{accountId}/endpoints/{endpointId}';
+ $_queryBuilder = APIHelper::appendUrlWithTemplateParameters($_queryBuilder, array(
+ 'accountId' => $accountId,
+ 'endpointId' => $endpointId,
+ ));
+ $_queryUrl = APIHelper::cleanUrl($this->config->getBaseUri(Servers::PHONENUMBERLOOKUPDEFAULT) . $_queryBuilder);
+ $_headers = array(
+ 'user-agent' => BaseController::USER_AGENT,
+ 'Accept' => 'application/json'
+ );
+ $this->configureAuth($_headers, 'voice');
+ $_httpRequest = new HttpRequest(HttpMethod::GET, $_headers, $_queryUrl);
+ if ($this->getHttpCallBack() != null) {
+ $this->getHttpCallBack()->callOnBeforeRequest($_httpRequest);
+ }
+ Request::timeout($this->config->getTimeout());
+ $response = Request::get($_queryUrl, $_headers);
+ $_httpResponse = new HttpResponse($response->code, $response->headers, $response->raw_body);
+ $_httpContext = new HttpContext($_httpRequest, $_httpResponse);
+ if ($this->getHttpCallBack() != null) {
+ $this->getHttpCallBack()->callOnAfterRequest($_httpContext);
+ }
+ $this->validateResponse($_httpResponse, $_httpContext);
+ $mapper = $this->getJsonMapper();
+ $deserializedResponse = $mapper->mapClass($response->body, 'BandwidthLib\\Voice\\Models\\Endpoint');
+ return new ApiResponse($response->code, $response->headers, $deserializedResponse);
+ }
+
+ /**
+ * Deletes a BRTC endpoint.
+ *
+ * @param string $accountId
+ * @param string $endpointId
+ * @return ApiResponse response from the API call
+ * @throws APIException Thrown if API call fails
+ */
+ public function deleteEndpoint(
+ string $accountId,
+ string $endpointId
+ ) {
+ $_queryBuilder = '/accounts/{accountId}/endpoints/{endpointId}';
+ $_queryBuilder = APIHelper::appendUrlWithTemplateParameters($_queryBuilder, array(
+ 'accountId' => $accountId,
+ 'endpointId' => $endpointId,
+ ));
+ $_queryUrl = APIHelper::cleanUrl($this->config->getBaseUri(Servers::PHONENUMBERLOOKUPDEFAULT) . $_queryBuilder);
+ $_headers = array(
+ 'user-agent' => BaseController::USER_AGENT
+ );
+ $this->configureAuth($_headers, 'voice');
+ $_httpRequest = new HttpRequest(HttpMethod::DELETE, $_headers, $_queryUrl);
+ if ($this->getHttpCallBack() != null) {
+ $this->getHttpCallBack()->callOnBeforeRequest($_httpRequest);
+ }
+ Request::timeout($this->config->getTimeout());
+ $response = Request::delete($_queryUrl, $_headers);
+ $_httpResponse = new HttpResponse($response->code, $response->headers, $response->raw_body);
+ $_httpContext = new HttpContext($_httpRequest, $_httpResponse);
+ if ($this->getHttpCallBack() != null) {
+ $this->getHttpCallBack()->callOnAfterRequest($_httpContext);
+ }
+ $this->validateResponse($_httpResponse, $_httpContext);
+ return new ApiResponse($response->code, $response->headers, null);
+ }
+
+ /**
+ * Updates the BXML for a BRTC endpoint.
+ *
+ * @param string $accountId
+ * @param string $endpointId
+ * @param string $body Valid BXML string
+ * @return ApiResponse response from the API call
+ * @throws APIException Thrown if API call fails
+ */
+ public function updateEndpointBxml(
+ string $accountId,
+ string $endpointId,
+ string $body
+ ) {
+ $_queryBuilder = '/accounts/{accountId}/endpoints/{endpointId}/bxml';
+ $_queryBuilder = APIHelper::appendUrlWithTemplateParameters($_queryBuilder, array(
+ 'accountId' => $accountId,
+ 'endpointId' => $endpointId,
+ ));
+ $_queryUrl = APIHelper::cleanUrl($this->config->getBaseUri(Servers::PHONENUMBERLOOKUPDEFAULT) . $_queryBuilder);
+ $_headers = array(
+ 'user-agent' => BaseController::USER_AGENT,
+ 'content-type' => 'application/xml; charset=utf-8'
+ );
+ $this->configureAuth($_headers, 'voice');
+ $_httpRequest = new HttpRequest(HttpMethod::PUT, $_headers, $_queryUrl);
+ if ($this->getHttpCallBack() != null) {
+ $this->getHttpCallBack()->callOnBeforeRequest($_httpRequest);
+ }
+ Request::timeout($this->config->getTimeout());
+ $response = Request::put($_queryUrl, $_headers, $body);
+ $_httpResponse = new HttpResponse($response->code, $response->headers, $response->raw_body);
+ $_httpContext = new HttpContext($_httpRequest, $_httpResponse);
+ if ($this->getHttpCallBack() != null) {
+ $this->getHttpCallBack()->callOnAfterRequest($_httpContext);
+ }
+ $this->validateResponse($_httpResponse, $_httpContext);
+ return new ApiResponse($response->code, $response->headers, null);
+ }
}
diff --git a/src/Voice/Models/CreateEndpointRequest.php b/src/Voice/Models/CreateEndpointRequest.php
new file mode 100644
index 0000000..26a5caa
--- /dev/null
+++ b/src/Voice/Models/CreateEndpointRequest.php
@@ -0,0 +1,34 @@
+type = $type;
+ $this->direction = $direction;
+ $this->eventCallbackUrl = $eventCallbackUrl;
+ $this->eventFallbackUrl = $eventFallbackUrl;
+ $this->tag = $tag;
+ $this->connectionMetadata = $connectionMetadata;
+ }
+}
diff --git a/src/Voice/Models/CreateEndpointResponse.php b/src/Voice/Models/CreateEndpointResponse.php
new file mode 100644
index 0000000..eae422a
--- /dev/null
+++ b/src/Voice/Models/CreateEndpointResponse.php
@@ -0,0 +1,40 @@
+endpointId = $endpointId;
+ $this->type = $type;
+ $this->status = $status;
+ $this->createdTime = $createdTime;
+ $this->updatedTime = $updatedTime;
+ $this->tag = $tag;
+ $this->devices = $devices;
+ $this->token = $token;
+ }
+}
diff --git a/src/Voice/Models/Device.php b/src/Voice/Models/Device.php
new file mode 100644
index 0000000..5ae0687
--- /dev/null
+++ b/src/Voice/Models/Device.php
@@ -0,0 +1,31 @@
+id = $id;
+ $this->status = $status;
+ $this->type = $type;
+ $this->createdTime = $createdTime;
+ $this->updatedTime = $updatedTime;
+ }
+}
diff --git a/src/Voice/Models/Endpoint.php b/src/Voice/Models/Endpoint.php
new file mode 100644
index 0000000..f6b1a92
--- /dev/null
+++ b/src/Voice/Models/Endpoint.php
@@ -0,0 +1,46 @@
+id = $id;
+ $this->type = $type;
+ $this->status = $status;
+ $this->direction = $direction;
+ $this->eventCallbackUrl = $eventCallbackUrl;
+ $this->eventFallbackUrl = $eventFallbackUrl;
+ $this->tag = $tag;
+ $this->devices = $devices;
+ $this->createdTime = $createdTime;
+ $this->updatedTime = $updatedTime;
+ }
+}
diff --git a/src/Voice/Models/EndpointEvent.php b/src/Voice/Models/EndpointEvent.php
new file mode 100644
index 0000000..2360f74
--- /dev/null
+++ b/src/Voice/Models/EndpointEvent.php
@@ -0,0 +1,34 @@
+eventType = $eventType;
+ $this->endpointId = $endpointId;
+ $this->timestamp = $timestamp;
+ $this->status = $status;
+ $this->reason = $reason;
+ $this->details = $details;
+ }
+}
diff --git a/src/Voice/Models/Enums.php b/src/Voice/Models/Enums.php
new file mode 100644
index 0000000..0060c21
--- /dev/null
+++ b/src/Voice/Models/Enums.php
@@ -0,0 +1,38 @@
+message = $message;
+ $this->code = $code;
+ $this->details = $details;
+ }
+}
diff --git a/src/Voice/Models/Page.php b/src/Voice/Models/Page.php
new file mode 100644
index 0000000..b400d2e
--- /dev/null
+++ b/src/Voice/Models/Page.php
@@ -0,0 +1,28 @@
+page = $page;
+ $this->size = $size;
+ $this->total = $total;
+ $this->totalPages = $totalPages;
+ }
+}
diff --git a/src/Voice/VoiceClient.php b/src/Voice/VoiceClient.php
index 089b842..c79a0bd 100644
--- a/src/Voice/VoiceClient.php
+++ b/src/Voice/VoiceClient.php
@@ -34,4 +34,5 @@ public function getClient()
}
return $this->client;
}
+
}
diff --git a/tests/ApiTest.php b/tests/ApiTest.php
index 44c9bc9..26a0515 100644
--- a/tests/ApiTest.php
+++ b/tests/ApiTest.php
@@ -14,7 +14,7 @@ final class ApiTest extends TestCase
{
protected static $bandwidthClient;
protected static $messagingMFAClient;
-
+ protected static $endpointClient;
public static function setUpBeforeClass(): void {
$config = new BandwidthLib\Configuration(
array(
@@ -37,6 +37,14 @@ public static function setUpBeforeClass(): void {
)
);
self::$messagingMFAClient = new BandwidthLib\BandwidthClient($messagingMFAConfig);
+
+ $endpointConfig = new BandwidthLib\Configuration(
+ array(
+ 'clientId' => getenv("BW_CLIENT_ID"),
+ 'clientSecret' => getenv("BW_CLIENT_SECRET"),
+ )
+ );
+ self::$endpointClient = new BandwidthLib\BandwidthClient($endpointConfig);
}
public function testCreateMessage() {
@@ -72,7 +80,7 @@ public function testUploadDownloadMedia() {
$mediaId = "text-media-id-" . uniqid() . ".txt";
$content = "Hello world";
$contentType = 'text/plain';
-
+
//media upload
self::$messagingMFAClient->getMessaging()->getClient()->uploadMedia(getenv("BW_ACCOUNT_ID"), $mediaId, $content, $contentType);
@@ -130,7 +138,7 @@ public function testCreateCallWithAmdAndGetCallState() {
//get phone call information
// $response = self::$bandwidthClient->getVoice()->getClient()->getCall(getenv("BW_ACCOUNT_ID"), $callId);
- // if (($response->getStatus() == 404) ) {
+ // if (($response->getStatus() == 404) ) {
// $this->assertTrue(is_a($response->getResult()->enqueuedTime, 'DateTime'));
// }
}
@@ -230,7 +238,7 @@ public function testAsyncTnLookup() {
$this->assertIsString($statusResponse->getResult()->data->results[0]->countryCodeA3);
$this->assertIsArray($statusResponse->getResult()->errors);
}
-
+
public function testSyncTnLookup() {
$body = new BandwidthLib\PhoneNumberLookup\Models\CreateLookupRequest();
$body->phoneNumbers = [getenv("USER_NUMBER")];
@@ -251,4 +259,218 @@ public function testSyncTnLookup() {
$this->assertIsString($response->getResult()->data->results[0]->countryCodeA3);
$this->assertIsArray($response->getResult()->errors);
}
+
+ public function testCreateListGetDeleteEndpoint() {
+ $accountId = getenv("BW_ACCOUNT_ID");
+ $voiceClient = self::$endpointClient->getVoice()->getClient();
+
+ // Create endpoint
+ $createReq = new BandwidthLib\Voice\Models\CreateEndpointRequest(
+ 'WEBRTC',
+ 'INBOUND',
+ getenv("BASE_CALLBACK_URL") . "/brtc/events",
+ null,
+ 'php-sdk-test',
+ ["meta" => "data"]
+ );
+ try {
+ $createResp = $voiceClient->createEndpoint($accountId, $createReq)->getResult();
+ } catch (BandwidthLib\APIException $e) {
+ $this->fail('createEndpoint failed with HTTP ' . $e->getCode() . ': ' . $e->getContext()->getResponse()->getRawBody());
+ }
+ $this->assertNotNull($createResp->endpointId);
+ $this->assertEquals('WEBRTC', $createResp->type);
+
+ // List endpoints
+ $endpoints = $voiceClient->listEndpoints($accountId)->getResult();
+ $this->assertIsArray($endpoints);
+ $ids = array_map(fn($ep) => $ep->id, $endpoints);
+ $this->assertContains($createResp->endpointId, $ids, 'Created endpoint should be in list');
+
+ // Get endpoint
+ $endpoint = $voiceClient->getEndpoint($accountId, $createResp->endpointId)->getResult();
+ $this->assertEquals($createResp->endpointId, $endpoint->id);
+ $this->assertEquals('WEBRTC', $endpoint->type);
+
+ // Update endpoint BXML
+ // TODO: This endpoint currently is not implemented, commenting out until it is
+ // $bxml = 'Test BRTC';
+ // $voiceClient->updateEndpointBxml($accountId, $createResp->endpointId, $bxml);
+
+ // Delete endpoint
+ $deleteResp = $voiceClient->deleteEndpoint($accountId, $createResp->endpointId);
+ $this->assertEquals(204, $deleteResp->getStatusCode());
+ }
+
+ public function testCreateEndpointResponseFields() {
+ $accountId = getenv("BW_ACCOUNT_ID");
+ $voiceClient = self::$endpointClient->getVoice()->getClient();
+
+ $createReq = new BandwidthLib\Voice\Models\CreateEndpointRequest(
+ 'WEBRTC',
+ 'INBOUND',
+ getenv("BASE_CALLBACK_URL") . "/brtc/events",
+ getenv("BASE_CALLBACK_URL") . "/brtc/fallback",
+ 'php-sdk-fields-test'
+ );
+ try {
+ $createResp = $voiceClient->createEndpoint($accountId, $createReq)->getResult();
+ } catch (BandwidthLib\APIException $e) {
+ $this->fail('createEndpoint failed with HTTP ' . $e->getCode() . ': ' . $e->getContext()->getResponse()->getRawBody());
+ }
+
+ $this->assertNotNull($createResp->endpointId);
+ $this->assertIsString($createResp->endpointId);
+ $this->assertEquals('WEBRTC', $createResp->type);
+ $this->assertNotNull($createResp->status);
+ $this->assertNotNull($createResp->createdTime);
+ $this->assertNotNull($createResp->updatedTime);
+ $this->assertEquals('php-sdk-fields-test', $createResp->tag);
+
+ // Cleanup
+ $voiceClient->deleteEndpoint($accountId, $createResp->endpointId);
+ }
+
+ public function testGetEndpointFields() {
+ $accountId = getenv("BW_ACCOUNT_ID");
+ $voiceClient = self::$endpointClient->getVoice()->getClient();
+
+ $createReq = new BandwidthLib\Voice\Models\CreateEndpointRequest(
+ 'WEBRTC',
+ 'INBOUND',
+ getenv("BASE_CALLBACK_URL") . "/brtc/events",
+ null,
+ 'php-sdk-get-test'
+ );
+ try {
+ $endpointId = $voiceClient->createEndpoint($accountId, $createReq)->getResult()->endpointId;
+ } catch (BandwidthLib\APIException $e) {
+ $this->fail('createEndpoint failed with HTTP ' . $e->getCode() . ': ' . $e->getContext()->getResponse()->getRawBody());
+ }
+
+ $endpoint = $voiceClient->getEndpoint($accountId, $endpointId)->getResult();
+ $this->assertInstanceOf(BandwidthLib\Voice\Models\Endpoint::class, $endpoint);
+ $this->assertEquals($endpointId, $endpoint->id);
+ $this->assertEquals('WEBRTC', $endpoint->type);
+ $this->assertNotNull($endpoint->status);
+ $this->assertNotNull($endpoint->direction);
+ $this->assertNotNull($endpoint->createdTime);
+ $this->assertNotNull($endpoint->updatedTime);
+ $this->assertEquals('php-sdk-get-test', $endpoint->tag);
+
+ // Cleanup
+ $voiceClient->deleteEndpoint($accountId, $endpointId);
+ }
+
+ public function testListEndpointsContainsCreated() {
+ $accountId = getenv("BW_ACCOUNT_ID");
+ $voiceClient = self::$endpointClient->getVoice()->getClient();
+
+ $createReq = new BandwidthLib\Voice\Models\CreateEndpointRequest(
+ 'WEBRTC',
+ 'INBOUND',
+ getenv("BASE_CALLBACK_URL") . "/brtc/events",
+ null,
+ 'php-sdk-list-test'
+ );
+ try {
+ $endpointId = $voiceClient->createEndpoint($accountId, $createReq)->getResult()->endpointId;
+ } catch (BandwidthLib\APIException $e) {
+ $this->fail('createEndpoint failed with HTTP ' . $e->getCode() . ': ' . $e->getContext()->getResponse()->getRawBody());
+ }
+
+ $endpoints = $voiceClient->listEndpoints($accountId)->getResult();
+ $this->assertIsArray($endpoints);
+ $this->assertNotEmpty($endpoints);
+
+ $ids = array_map(fn($ep) => $ep->id, $endpoints);
+ $this->assertContains($endpointId, $ids, 'Newly created endpoint should appear in list');
+
+ // Cleanup
+ $voiceClient->deleteEndpoint($accountId, $endpointId);
+ }
+
+ public function testListEndpointsEachItemIsEndpointInstance() {
+ $accountId = getenv("BW_ACCOUNT_ID");
+ $voiceClient = self::$endpointClient->getVoice()->getClient();
+
+ $createReq = new BandwidthLib\Voice\Models\CreateEndpointRequest(
+ 'WEBRTC',
+ 'INBOUND',
+ getenv("BASE_CALLBACK_URL") . "/brtc/events"
+ );
+ try {
+ $endpointId = $voiceClient->createEndpoint($accountId, $createReq)->getResult()->endpointId;
+ } catch (BandwidthLib\APIException $e) {
+ $this->fail('createEndpoint failed with HTTP ' . $e->getCode() . ': ' . $e->getContext()->getResponse()->getRawBody());
+ }
+
+ $endpoints = $voiceClient->listEndpoints($accountId)->getResult();
+ foreach ($endpoints as $ep) {
+ $this->assertInstanceOf(BandwidthLib\Voice\Models\Endpoint::class, $ep);
+ $this->assertNotNull($ep->id);
+ $this->assertNotNull($ep->type);
+ $this->assertNotNull($ep->status);
+ }
+
+ // Cleanup
+ $voiceClient->deleteEndpoint($accountId, $endpointId);
+ }
+
+ public function testCreateMultipleEndpointsAndDeleteAll() {
+ $accountId = getenv("BW_ACCOUNT_ID");
+ $voiceClient = self::$endpointClient->getVoice()->getClient();
+
+ $createdIds = [];
+ for ($i = 0; $i < 3; $i++) {
+ $createReq = new BandwidthLib\Voice\Models\CreateEndpointRequest(
+ 'WEBRTC',
+ 'INBOUND',
+ getenv("BASE_CALLBACK_URL") . "/brtc/events",
+ null,
+ "php-sdk-multi-{$i}"
+ );
+ try {
+ $endpointId = $voiceClient->createEndpoint($accountId, $createReq)->getResult()->endpointId;
+ } catch (BandwidthLib\APIException $e) {
+ $this->fail('createEndpoint failed with HTTP ' . $e->getCode() . ': ' . $e->getContext()->getResponse()->getRawBody());
+ }
+ $this->assertNotNull($endpointId);
+ $createdIds[] = $endpointId;
+ }
+
+ $this->assertCount(3, $createdIds);
+
+ // Delete all created endpoints
+ foreach ($createdIds as $id) {
+ $deleteResp = $voiceClient->deleteEndpoint($accountId, $id);
+ $this->assertEquals(204, $deleteResp->getStatusCode());
+ }
+ }
+
+ public function testDeleteEndpointRemovedFromList() {
+ $accountId = getenv("BW_ACCOUNT_ID");
+ $voiceClient = self::$endpointClient->getVoice()->getClient();
+
+ $createReq = new BandwidthLib\Voice\Models\CreateEndpointRequest(
+ 'WEBRTC',
+ 'INBOUND',
+ getenv("BASE_CALLBACK_URL") . "/brtc/events",
+ null,
+ 'php-sdk-delete-check'
+ );
+ try {
+ $endpointId = $voiceClient->createEndpoint($accountId, $createReq)->getResult()->endpointId;
+ } catch (BandwidthLib\APIException $e) {
+ $this->fail('createEndpoint failed with HTTP ' . $e->getCode() . ': ' . $e->getContext()->getResponse()->getRawBody());
+ }
+
+ // Delete it
+ $voiceClient->deleteEndpoint($accountId, $endpointId);
+
+ // Should no longer appear in list
+ $endpoints = $voiceClient->listEndpoints($accountId)->getResult();
+ $ids = array_map(fn($ep) => $ep->id, $endpoints);
+ $this->assertNotContains($endpointId, $ids, 'Deleted endpoint should not appear in list');
+ }
}
diff --git a/tests/BxmlTest.php b/tests/BxmlTest.php
index 44bdb2f..e9f1b85 100644
--- a/tests/BxmlTest.php
+++ b/tests/BxmlTest.php
@@ -540,4 +540,18 @@ public function testStopTranscription() {
$responseXml = $response->toBxml();
$this->assertEquals($expectedXml, $responseXml);
}
+
+ public function testConnectAndEndpoint() {
+ $endpoint1 = new BandwidthLib\Voice\Bxml\Endpoint("endpoint-123");
+ $endpoint2 = new BandwidthLib\Voice\Bxml\Endpoint("endpoint-456");
+ $connect = new BandwidthLib\Voice\Bxml\Connect([
+ $endpoint1,
+ $endpoint2
+ ]);
+ $response = new BandwidthLib\Voice\Bxml\Response();
+ $response->addVerb($connect);
+ $expectedXml = '';
+ $responseXml = $response->toBxml();
+ $this->assertEquals($expectedXml, $responseXml);
+ }
}