RingCentral’s Fax API and PHP — Part 2
In my previous article, here, I touched on having the RingCentral Fax API send uploaded PDF files out as fax documents. This was done with the PHP SDK. In this article, I wanted to explore managing faxes more deeply as there are a few other aspects to fax management beyond simply sending them out. So I expanded my app to provide a list of received faxes, display individual faxes, and then have the option to forward a selected fax to another number.
Let’s start by looking at the web interface. In Figure 1 you see that I have added a “List Faxes” button to the bottom of the form.
When that new button is clicked we connect to the API within our API credentials and retrieve all the faxes that the account has received in a given date range. If a date range is not provided then the most recent 24-hour period is used. I will point out the setting of these options in the code display later in the article.
As this list is displayed I add links to each line, giving me the options to view or forward the fax. When the “View” link is clicked, the internal fax identifier is used to connect to the RingCentral message store through an API endpoint. The message store is where RingCentral messages are kept, including SMS, Fax, voicemail, and Pager message types. When accessing the message store, it is a best practice to specify what type of message you are looking for in order to keep the volume of data at a manageable size.
The selected fax is then downloaded to the PHP server in PDF format and displayed within an iframe HTML tag. I have added some navigation buttons to the pages as well to ease the movement around the app. This is shown in Figure 3.
You can then click “Return to List” if you want to re-display the list of faxes or click the “Home” button to go back to the initial landing page for this app.
From the list of faxes, you can also forward a fax to another recipient if you want. Clicking the “Forward” link of a particular fax will bring up a page like Figure 4.
This is similar to The view page except that I added an entry field at the top to accept a phone/fax number to forward the selected fax to. Again, at the bottom, I have added helpful navigation buttons.
Now let’s look at the PHP code and the API endpoints that we employed to make this all happen.
Listing faxes
The first new feature that we added was to list any existing received faxes. The code for this is shown below in Listing 1. My PHP file is named list_faxes.php.
<?php $faxes = get_faxes();
foreach ($faxes as $fax) { ?>
<tr class="CustomTable">
<td class="left_col">
<?php foreach ($fax as $key => $value) {
if ($key == "Id") { ?>
<a class="links" href="view_fax.php?id=<?= $value ?>">View</a>
<a class="links" href="forward_fax.php?id=<?= $value ?>">Forward</a>
<?php }
echo "<strong>" . $key . ": </strong>" ;
echo $value . " ";
} ?>
</td>
</tr>
<?php } ?>
Listing 1 — PHP code displaying existing faxes
Here I am calling my custom function called get_faxes() and storing the result into the $faxes variable. Then I loop through the list with a foreach construct adding my “View” and “Forward” links to the display at the same time. What is returned into the $faxes variable is a structured array that allows me to build the output sequentially.
Let’s look at the get_fax function to see the details of what’s going on there. See Listing 2.
function get_faxes () {
$controller = ringcentral_sdk();
$platform = $controller['platform'];
$dateTime = new DateTime('now', new DateTimeZone('AST'));
$fromDate = $startDateTime = $dateTime->modify('-4 days')->format('Y-m-d\TH:i:s.v\Z');
$queryParams = array(
'availability' => array('Alive',),
//'conversationId' => '<ENTER VALUE>',
'dateFrom' => $fromDate,
// format: 2016–03–10T18:07:52.534Z
//'dateTo' => '<ENTER VALUE>',
'direction' => array('Inbound'),
//'distinctConversations' => true,
'messageType' => array('Fax',),
//'readStatus' => array( ),
//'page' => 000,
//'perPage' => 000,
//'phoneNumber' => '<ENTER VALUE>'
);
$fax_list = array();
$i = 1;
try {
$endpoint = "/restapi/v1.0/account/~/extension/~/message-store";
$resp = $platform->get($endpoint, $queryParams);
// echo_spaces("fax object", $resp->json());
foreach ($resp->json()->records as $value) {
$fax_list[$i]["Id"] = $value->id;
$fax_list[$i]["Created"] = date('F j, Y, g:i a', strtotime($value->creationTime));
$fax_list[$i]["Pages"] = $value->faxPageCount;
$fax_list[$i]["From"] = $value->from->phoneNumber;
$fax_list[$i]["Sender"] = $value->from->name;
$i++;
}
} catch (\RingCentral\SDK\Http\ApiException $e) {
// Getting error messages using PHP native interface
$fax_list[$i]["error"] = $e->getMessage();
}
return $fax_list;
}
Listing 2 — The get_faxes() function.
In the first 2 lines of code, I am making my connection to the SDK and getting back the platform controller or response object. Then I set my ‘from’ date based on the server's internal clock and subtract 4 days from that time stamp to create the starting time to search for my on-hand faxes. I set up a parameters array next called $queryParams to limit what the API returns to me from the message store. I want all ‘Alive’ faxes — meaning that I don’t want any deleted or archived ones. I want the time frame that I set with my ‘from’ date, the ‘to’ date, if not set, will default to the current date and time. I want only inbound faxes, and I only want messageTypes of ‘Fax’es.
Next, I set 2 variables to help me with crafting the data when it comes back from the API call. $fax_list is an array where I will store my data and $i is an internal counter I use to identify what row of the response array I want to manage during my foreach loop.
Then, I set my endpoint value pointing to the message-store of RingCentral’s API platform and I call the get method on my $platform instance of the SDK passing in the endpoint and the parameters that were previously set. I store the ‘answer’ to that SDK call in my $resp response object and then I can ‘walk’ through it with my foreach statement building my $fax_list array as I go along. Just before my call to foreach, I have a commented line of code that would output the entire response object to the web screen if I want to see all of it and maybe redesign my $fax_list array.
This is all done within a try / catch construct so that I can capture any errors and output them for debugging purposes if ever required. When my $fax_list array is done being created, I simply return it to the line of code that called this function. This creates the list of faxes that are connected to the account whose API credentials are provided to the SDK.
Viewing Faxes
The next part of this app that was added was the option to view a received fax. This is triggered when the ‘View’ link is clicked on the list of existing faxes. Here is the section of code that gets called when that link is activated. It starts approximately on line 31 of the view_fax.php file.
<?php $filename = view_fax($_GET['id']); ?>
<tr class="CustomTable">
<td class="CustomTableFullCol">
<div id="pdf-container">
<! - Embed the PDF using iframe →
<iframe src="<?php echo $filename; ?>" width="100%" height="100%" style="border: none;"></iframe>
</div>
</td>
</tr>
Listing 3 — Calling the view_fax() function.
The first thing to notice here is that I am picking up the ‘id’ number from the $_GET array. This is set in the line of code in list_faxes.php where I create the ‘View’ link in the previous section.
<a class=”links” href=”view_fax.php?id=<?= $value ?>”>View</a>
I am creating the link, setting a query string for id, and assigning it the $value from the multi-dimensional array that contains the list of faxes from the RingCentral message store. Then in the same line of code, I am sending that id number to the view_fax() function and storing the result in a variable called $filename.
A few lines later I just echo the $filename to the browser within an <iframe> tag coupling. There is more to see within the view_fax() function, listed here:
function view_fax ($faxId) {
$controller = ringcentral_sdk();
$platform = $controller['platform'];
$resp = $platform->get("/account/~/extension/~/message-store/$faxId");
$object = $resp->json();
if (isset($object->attachments)) {
$fileName = $object->id . "_fax.";
$fileName .= substr($object->attachments[0]->contentType, -3);
try {
$res = $platform->get($object->attachments[0]->uri);
file_put_contents($fileName, $res->raw());
} catch (\RingCentral\SDK\Http\ApiException $e) {
echo_spaces("Object error", $e->getMessage());
}
}
return $fileName;
}
Listing 4 — view_fax function retrieving specific id from message store
Again, here we connect to the SDK and get the $platform variable loaded with the connection information that we require. Then I call the get method passing in the endpoint string directly with the $faxId value that was handed to the function. The next line turns the response object into JSON format so that we can more easily access the returned information.
After the formatting of the data, we see if the returned object contains any attachment information — this is where the fax-specific data is stored. Then, if that is positive, we start to build a filename that we can use to save the file information to and then hand it back to the calling code. Once we have the filename constructed we ‘get’ the $object->attachments[0]->uri and then store the fax contents to the $filename we created. Upon returning from this function we use the filename in the <iframe> tags as already noted.
Forwarding Faxes
The last part of this app that was added was the option to forward a received fax to another recipient. Here we start with the same process of displaying the selected fax with the view_fax() function with the addition of requesting a phone/fax number for use in forwarding the selection. The code is located in the forward_fax.php code file. It is almost identical except for what happens when the “Send Forward” button is clicked.
NOTE: In this sample app I don’t have any code validation in place to validate phone number formats or if there is even a forwarding phone number provided.
The line of code that triggers the forwarding process is here:
if (send_forward_fax ($_POST['to_fax_number'], $_GET['id']) == false) {
It is located at about line 74 of the forward_fax.php file. Here I get the id from the query string and the <form> posted ‘to fax number’ and send them both to the send_forward_fax() function. The code for this function follows.
function send_forward_fax ($to_fax_number, $faxid) {
$controller = ringcentral_sdk();
$platform = $controller['platform'];
$sdk = $controller['SDK'];
$filename = view_fax($faxid) ;
try {
$bodyParams = $sdk->createMultipartBuilder()
->setBody(array(
'to' => array(array('phoneNumber' => $to_fax_number)),
'faxResolution' => "High",
// 'coverIndex' => 0,
'coverPageText' => "This is a forwarded fax",
))
->add(fopen($filename, 'r'))
->request('/restapi/v1.0/account/~/extension/~/fax');
$response = $platform->sendRequest($bodyParams);
} catch (\RingCentral\SDK\Http\ApiException $e) {
$response = false ;
}
return $response;
}
Listing 5 — send_forward_fax function
Once again I make a connection to the SDK with my account credentials and then I call the view_fax function to get the filename for the PDF that is stored on my app’s server. I then create a new fax object with the createMultipartBuilder() method call. The first option to set here is the number that you are sending the fax to.
There are a few additional options to also consider here when forwarding a fax. You can simply forward the existing content as it was received by setting the ‘coverIndex’ value to 0. This creates a new fax without a cover sheet. It is currently commented out in our example. Or you can send the content with an additional cover sheet and add in your own text to denote that you are in fact forwarding on a fax document. If you don’t intend on sending a new cover page then simply comment out the ‘coverPageText’ option and activate the ‘coverIndex = 0’ option.
We then finish creating our new fax by ‘add’ing the filename and the endpoint values finishing the request with a call to the ‘sendRequest’ method and handing it the parameters we just established. If the process fails we return a false value otherwise we return the response object itself.
Final thoughts
As you may realize there is a lot more that can be done within this app that I have created and there are also a lot more functions that can be done with the fax API. There is an option, for example, to have different cover page styles added to your faxes. And we can of course delete the faxes from our message store as well, but we did not cover that portion of the API here. My code is on GitHub here if you want to take it and expand it, please feel free.
If you want to learn more about the RingCentral Fax API you can start here. I hope you enjoyed this article and found it useful as an example of what is possible with this API.