Made to Order Software Corporation Logo

PHP eFax: Main Page

PHP eFax Documentation
Introduction
How do I get my own copy of this product?
Requirements
Sending a Fax
Parsing the fax disposition
Receiving an inbound fax request
Security considerations
Handling eFax failures
Error Handling
Changes between versions
Copyright (c) 2007-2017 Made to Order Software Corp.

Introduction

Welcome to the PHP eFax documentation.

What is eFax? eFax is a company that let's you send and receive faxes via the Internet (see http://www.efax.com). The faxes can be sent to a standard paper fax or to a virtual fax machine (i.e. to your eFax account.) There are two interfaces:

(1) an email interface used to send and receive documents from a set of standard email addresses.

(2) a secure HTTPS API called eFax Developer or business eFax. It can be used in a totally automated way to send and receive faxes via a web interface using the standard HTTPS protocol for communication.

At Made to Order Software, we use eFax for Order Made! Our easy to use ordering system for restaurants. https://secure.m2osw.com/resto/system/list.php

To use the eFax class, create an eFax object and either set the parameter to send a fax, or parse the disposition message. That's it! The rest of the work is handled internally by the class.

Warning
IMPORTANT NOTE:
The secure HTTPS API requires YOU to have a secure website with a valid certificate to accept eFax disposition and inbound fax messages. YOUR certificate must be validated by an entity such as godaddy.com or verysign.com (there are hundreds of companies offering certificates now a day.) Without a valid certificate, dispositions from eFax Developer will NOT work. This is beyond what we can do for you with the PHP eFax library.
Of course, if you do not want to use dispositions or receive inbound messages the certificate is not required, but you will not benefit from as many features as you could otherwise make use of.
Back to Summary

How do I get my own copy of this product?

The source code for this class is available for sale on our http://www.m2osw.com website.

Click on Products at the top, search for PHP eFax, and add it to your cart. Then simply go through our checkout process. A few seconds after we receive your payment, you will gain access to the download area where you will be able to download the PHP eFax package.

If you already purchased a license then you have an account with us and you can simply go back to your account and download a new copy of the library. If you forgot your password, then use the request new password form to be sent a link to your email address. That link will let you enter a new password for your account. The license is permanent so you do not have to re-purchase a new license to re-download a copy of the library.

Back to Summary

Requirements

Up to version 1.5, the class requires the availability of HttpRequest. Below are information on how to install HttpRequest on your server.

Since version 1.6, HttpRequest is optional. You may instead use the accompanying http_request class. To do so, create the eFax object passing false as the optional parameter.

$efax = new eFax(false);
...
$efax->send(); // at this point the http_request class is loaded
Note
The default is to make use o the PEAR HttpRequest class as before. This is so our existing customers do not get a big surprise in the event they upgrade (they do not have to since there is no real code changes that require existing servers that work to make use of the new version.)

Installing the HttpRequest library on Microsoft Windows

Warning
For new installation, we recommend that you use new eFax(false) when creating an eFax object instead of using the HttpRequest class from PEAR.

For a Microsoft Windows system, you can find pre-compiled versions of the HttpRequest module, called php_http.dll at the following URL:

http://pecl4win.php.net/list.php

Please, make sure that the version is correct for your system. The home page for the PECL code for Windows is at PECL4WIN.

A good tutorial for IIS and even Unix users on how to install HttpRequest can be found on IIS Aid.

Installing the HttpRequest library on Debian systems

Warning
For new installation, we recommend that you use new eFax(false) when creating an eFax object instead of using the HttpRequest class from PEAR.

If it is not already installed on your Debian system (this also works under Ubuntu) use the following commands to retrieve and recompile a version on your system:

sudo apt-get install php-pear
sudo apt-get install php5-dev
sudo pecl install pecl_http

Then edit your /etc/php/apache2/php.ini file and add the following line at the end:

extension=http.so

Installing the HttpRequest library on Fedora systems

Warning
For new installation, we recommend that you use new eFax(false) when creating an eFax object instead of using the HttpRequest class from PEAR.

For Fedora, RedHat and other RPM based systems, use yum instead of apt-get. The pecl command is the same.

sudo yum install php-xml
sudo yum install php-devel
sudo pecl install pecl_http
sudo yum install php-pear-HTTP-Request

The php-xml is to get the DOMDocument support.

Once the HTTP Request module installed, add the following at the end of your /etc/php.ini file:

extension=http.so
Back to Summary

Sending a Fax

The following code shows how you create an eFax object, initializes it to send a fax and finally eFax::send() the fax.

The parameters are only examples. You will need to set the parameters to what you need for your specific needs.

$efax = new eFax(false); // use 'true' to use the PEAR HttpRequest class (not recommended)
// mandatory parameters
$efax->set_account_id("9169881450");
$efax->set_user_name("made_to_order_software");
$efax->set_user_password("TopSecret");
$efax->add_file("txt", "This is the content of my text file");
$efax->add_recipient("Alexis Wilke", "Made to Order Software", "9169881450");
// Though this is mandatory, the constructor sets the default that
// you should not need to modify.
// mandatory if set_duplicated_id(false);
$efax->set_fax_id("Fax #123456");
// mandatory if set_disposition_method("EMAIL");
$efax->add_disposition_email("Alexis Wilke", "alexis@m2osw.com");
// mandatory if set_disposition_method("POST");
$efax->set_disposition_url("https://secure.m2osw.com/fax-disposition.php");
// optional flags
$efax->set_disposition_language("en");
$efax->set_disposition_level(eFax::RESPOND_ERROR | eFax::RESPOND_SUCCESS);
$efax->set_disposition_method("POST");
$efax->set_duplicate_id(false);
$efax->set_fax_header(" @DATE @TIME Made to Order Software Corporation");
$efax->set_priority("HIGH");
$efax->set_resolution("STANDARD");
$efax->set_self_busy(true);
// ready to send the fax
$result = $efax->send($efax->message());
if($result)
{
... // handle success
}
else
{
... // handle failure
}
See also
eFax::set_account_id() eFax::add_disposition_email() eFax::set_disposition_url() eFax::set_disposition_language() eFax::set_disposition_level() eFax::set_disposition_method() eFax::set_duplicate_id() eFax::set_fax_header() eFax::set_fax_id() eFax::add_file() eFax::set_outbound_url() eFax::set_priority() eFax::add_recipient() eFax::set_resolution() eFax::set_self_busy() eFax::set_user_name() eFax::set_user_password() eFax::send()
Back to Summary

Parsing the fax disposition

Whenever you receive the fax disposition message from eFax, call the eFax::parse_disposition() function with the XML data included in the message. Then you can use different get functions to retrieve the resulting information.

The disposition is sent by eFax once the fax was successfully sent or a failure was discovered. It is sent to your server using the disposition URL you specified when sending the fax to the eFax server. In our example it is set using the eFax::set_disposition_url() function as follow:

$efax->set_disposition_url("https://secure.m2osw.com/fax-disposition.php");

The following is an example of fax-disposition.php code:

// Get the XML message
$xml = stripslashes($_POST["xml"]);
$efax = new eFax(false);
// the parser checks the validity of the user name and password
$efax->set_user_name("made_to_order_software");
$efax->set_user_password("TopSecret");
// parse the XML message
if($efax->parse_disposition($xml))
{
// get the results and do something with it
// \c eFax::get_result_fax_id() returns the identifier that you sent to
// eFax using the \c eFax::set_fax_id() function; very useful to know
// which fax is being disposed of
$my_var = $efax->get_result_fax_id();
$my_var = $efax->get_result_docid();
$my_var = $efax->get_result_fax_number();
$my_var = $efax->get_result_completion_date();
$my_var = $efax->get_result_fax_status();
$my_var = $efax->get_result_csid();
$my_var = $efax->get_result_duration();
$my_var = $efax->get_result_pages();
$my_var = $efax->get_result_retries();
// now tell eFax that we accepted the disposition
echo "Post Successful\n";
}
else
{
... // handle error case
}
See also
eFax::get_result_fax_id() eFax::get_result_docid() eFax::get_result_fax_number() eFax::get_result_completion_date() eFax::get_result_fax_status() eFax::get_result_csid() eFax::get_result_duration() eFax::get_result_pages() eFax::get_result_retries() eFax::parse_disposition() eFax::set_user_name() eFax::set_user_password()
Back to Summary

Receiving an inbound fax request

Whenever you receive a fax from a sender, eFax Developer posts a notification to a URL you specify in your eFax Developer account. This HTTP POST message includes an XML file that PHP eFax can parse for you. See the eFax::parse_inbound_message() function for additional information.

Warning
Remember that you MUST have a valid certificate to receive notifications from eFax. Otherwise the connection from eFax fails since they do not accept to connect to a non-secure server.

After the call to the parse function you can use different get functions to retrieve the inbound fax information.

Inbound requests are sent to the URL you define in your eFax Developer account. At that URL, you must have a PHP file that includes what follows:

Warning
The user name and password for the inbound eFax processing are defined in the inbound settings screen. These can be made the same as the outbound user name and password, although I would suggest you use a different user name and a different password to increase your security level.
... -- some initialization code such as require_once('efax.php');
// Get the XML message
$xml = stripslashes($_POST["xml"]);
$efax = new eFax(false);
// the parser checks the validity of the user name and password
// (setup in Inbound Settings of your eFax developer account;
// will be empty strings by default which fails with PHP eFax)
$efax->set_user_name("made_to_order_software");
$efax->set_user_password("TopSecret");
// parse the XML message
if($efax->parse_inbound_message($xml))
{
// get the results and do something with it
// InboundPostRequest/RequestControl/RequestDate
$my_var = $efax->get_result_request_date();
// InboundPostRequest/RequestControl/RequestType
$my_var = $efax->get_result_request_type();
// InboundPostRequest/FaxControl/AccountID
$my_var = $efax->get_result_fax_id();
// InboundPostRequest/FaxControl/ANI
$my_var = $efax->get_result_fax_number();
// InboundPostRequest/FaxControl/CSID
$my_var = $efax->get_result_csid();
// InboundPostRequest/FaxControl/DateReceived
$my_var = $efax->get_result_completion_date();
// InboundPostRequest/FaxControl/FaxName
$my_var = $efax->get_result_fax_name();
// InboundPostRequest/FaxControl/MCFID
$my_var = $efax->get_result_docid();
// InboundPostRequest/FaxControl/PageCount
$my_var = $efax->get_result_pages();
// InboundPostRequest/FaxControl/Status
$my_var = $efax->get_result_fax_status();
// InboundPostRequest/FaxControl/UserFieldControl/*
* $my_var = $efax->get_result_user_fields();
* // InboundPostRequest/FaxControl/BarcodeControl/*
* $my_var = $efax->get_result_barcodes();
* // InboundPostRequest/FaxControl/FileContents
* // or
* // InboundPostRequest/FaxControl/PageContentControl/*
* $my_var = $efax->get_result_files();
* }
* else
* {
* ... // handle error case
* }
*
See also
eFax::get_result_barcodes() eFax::get_result_completion_date() eFax::get_result_csid() eFax::get_result_docid() eFax::get_result_fax_id() eFax::get_result_fax_name() eFax::get_result_fax_number() eFax::get_result_fax_status() eFax::get_result_files() eFax::get_result_pages() eFax::get_result_request_date() eFax::get_result_request_type() eFax::get_result_user_fields() eFax::parse_inbound_message() eFax::set_user_name() eFax::set_user_password()
Back to Summary

Security considerations

In eFax, there are several built in security features.

The main feature is that it only works with an SSL connection. This clearly means secure! The only drawback is that you need a valid certificate in order to send and receive faxes with your system.

The second feature is the login and password. These are passed in the XML data. The one drawback with these is that they are written in clear in the XML data. In other words, anyone can read them if they somehow intercept your message (but remember, on the Internet the message is encrypted and thus no one can read the login and password.)

Warning
Do not save the XML in clear on your hard drive unless you know for sure that it is safe. If you want to save it for storage or archival, think about removing the login and password first.

Similarly, whenever you create an XML file to be sent to eFax Developer, you need to incorporate the login and password in clear in that XML document. So watch out and consider saving that information in a protected place on your hard disk. A place only accessible to the part of your application dealing with the sending and receiving of faxes.

Another less obvious security feature is the use of the XML format. That ensures a strong structure preventing many invalid requests. For instance, for inbound messages, we check a certain number of entries that need to be valid for the request to be accepted as an eFax Developer request. This part is handled by the eFax class so you do not have to worry about it.

Handling eFax failures

Whenever you receive an eFax failure such as "Your request failed due to invalid data" you need to check out your eFax object setup and the data that you are sending. I suggest you try sending documents that you trust are correct (was created with genuine tools.) If those fail too, then there is another problem. Note that at first you probably want to try sending a text file. These are the easiest to test with. Only make sure your lines are about 80 characters wide because eFax does not reformat your documents.

The debugging is somewhat difficult because eFax Developer does not give you much info about what goes right and what goes wrong. Note, however, that they keep a copy of the outbound response on their server. So if somehow you do not get that response, you can at least see what they were going to tell you.

The main reason why you would not receive the response is because you did not specify a URL with the HTTPS scheme (secure). Or because your certificate cannot be verified by eFax Developer. In most cases, if you can verify your certificate with your browser and it does not give you an error, then eFax Developer will have no problem with it.

Note that some eFax errors will not happen. For instance, the "Account identifier argument was not passed" error is prevented by the eFax class, which checks that you specified the identifier before it forwards the XML packet to the eFax Developer server.

Other failures are possible. For instance, the fax number may not be valid.

Internally, the eFax class automatically retries sending your document up to 5 times when an error occurs. In most cases, this is used when the connection to the eFax server fails (times out.) If after 5 times it cannot connect and send the fax to the eFax Developer server, then it returns with false. In this case, you will NOT get any other error from eFax Developer since they do not even know you wanted to contact them. Failure to connect happen often at times when they receive a large number of faxes simultaneously. It is frequent that you have to try to connect a second or third time. It never happened to us that the communication would not happen with 5 attempts. For this reason, the count is hard coded in the send() function. Feel free to increase it if you get that problem once in a while.

Note
Since version 1.6, when you use new eFax(false) the http_request detects errors that it reports with a different exception. This allows the system to avoid waiting a long time when a fatal error happens. You may want to catch errors of type http_request_exception to make sure that your software does not just fail on those errors. In most cases those will happen at time of development and if something goes wrong.

Error Handling

Most functions throw an eFaxException when an error occurs.

Exceptions are raised if some parameter was not yet defined and you try to create the message to send a fax and when calling the eFax::send() function.

Also, exceptions are raised if the user name or password were not defined before calling the eFax::parse_disposition() or eFax::parse_inbound_message().

Similarly, exceptions are raised if calling one of the get functions before eFax::parse_disposition() or eFax::parse_inbound_message() were called.

Notice that calling eFax::set_fax_id() does NOT set the fax identifier of the disposition. In other words, calling eFax::get_result_fax_id() after eFax::set_fax_id() without calling eFax::parse_disposition() or eFax::parse_inbound_message() still generates an exception.

Although it should not be necessary, since no exceptions should ever occur when the eFax class is properly used, it is possible to catch the eFaxException in this way:

try {
... // deal with eFax object
}
catch(eFaxException $e)
{
... // handle exception
}

When using the new http_request class

Note that the new http_request class may throw the http_request_exception. If raised, these exceptions will reach your software. Some are like the eFaxException: they only happen when a parameter is invalid and fixing your code will fix the problem. Others would happen in the event an invalid reply was sent by the eFax server. So neither should be raised, although to strengthen your code you probably want to catch these exceptions, just in case. These will only happen when you call the eFax::send() function so you may just protect that one call:

try {
$efax->send(); // deal with eFax object
}
{
... // handle exception
}

When using the PEAR HttpRequest library

Note that the HttpRequest also throws some exceptions. Please read the HttpRequest reference manual for more information.

http://www.php.net/manual/en/class.httprequest.php

According to the documentation of the send() function the following exceptions may be raised by the library:

HttpRuntimeException,
HttpRequestException,
HttpMalformedHeaderException,
HttpEncodingException

Note that the eFax::send() function already catches the HttpInvalidParamException so you will never get that one from the outside of the eFax class.

try {
$efax->send(); // deal with eFax object
}
catch(HttpRequestException $e)
{
... // handle exception
}
Back to Summary

Changes between versions

The following shows what changes between versions. In general, what is listed is what will affect you in some way.

Changes in 1.10

  • Changed the protocol used by default to connect from "tls://" to "ssl://" as it seems that most systems now work that way, try with the other protocol afterward if the first failed

Changes in 1.9

  • Enhanced the set_fax_id() documentation to clearly spefify that the identifier needs to be unique (i.e. you cannot hard code a value and test with the same identifier over and over again.)
  • Updated the efax.doxy file with a newer version of doxygen.

Changes in 1.8

  • Changed the connection to make use of TLS instead of SSL. The http_request object forcibly used SSLv3 which is now banned.

Changes in 1.7

  • Clean up the response which includes invalid characters and can prevent the LoadXML() from working right.
  • Fixed the test in the transmission_control_tags() of the duplicate_id parameter; if false then we must have the fax_id.
  • Added support for the disposition language offered by eFax.
  • Added support for the new file types. Also changed the case support, you can now pass the type with any case. It will be forced to lowercase before sending to the eFax server.

Changes in 1.6

  • Added a new class called http_request that we can use instead of the PEAR HttpRequest class. This means you do not have to install PEAR at all and you can still use PHP eFax.
  • Applied a fix to the response parser, we now trim the response first and then check that it does start with "<?xml" before parsing it as XML.
  • Added a test to check the send() operation of the PHP 5.x version of PHP eFax. This requires an SSL aware server where the fax-server.php code can be installed and run. It is expected to run with Apache2.
  • Updated the documentation.

Changes in 1.5

  • Some clean up work. The code is the same as in version 1.4.

Changes in 1.4

  • Added options to the HttpRequest so SSL v3 is forced. Without it and a newer system (such as Intrepid, Ubuntu 8.10) you could get an error saying that the request was invalid because it was empty.
  • Added an option so redirects are followed (up to 3 of them)
  • Fixed a few small bugs found as we wrote a new test. You are unlikely to have been affected by any of those bugs.
  • Enhanced the documentation.
  • Include a separate file to support PHP 4.4.0+

Changes in 1.3

  • Added the "Post Successful" message from within the parse_inbound_message() function. It is sent only if the login and password are accepted and the control information is valid (proper control date).
  • Added a version definition in the package so your code can check for the version if need be. (PHP_EFAX_VERSION)

Changes in 1.2

  • Fixed the set_user_password() function that would checked $user_name instead of $user_password.
  • Enhanced the documentation for Fedora users.
  • Added more comments about the need for a valid HTTPS certificate.

Changes in 1.1

  • Added support for inbound faxes with the addition of the eFax::parse_inbound_message() function and some eFax::get_result...() functions. Updated the documentation accordingly.
  • Added the eFaxBarcode class to support reading barcodes from received faxes.
  • Fixed the completion date computation. The previous version was affected by your timezone. Now, it properly returns a UTC time.
  • Fixed the eFax::set_account_id() function so invalid characters are automatically removed. Added eFax::set_raw_account_id() just in case you need to setup an account identifier with what is supposed to be viewed as otherwise invalid characters.
  • Fixed some of the existing documentation to clarify a few points.
  • eFax::get_result_recipient_csid() was renamed eFax::get_result_csid() since it is now used for the notifications of sent faxes and the received faxes. In the later case we are the recipient and thus calling the CSID the recipient was not correct.
  • eFax::get_result_pages_sent() was renamed eFax::get_result_pages() since it is now used for the notifications of sent faxes and the received faxes. In the later case, it would need to be "pages received" otherwise.
Back to Summary

Copyright (c) 2007-2017 Made to Order Software Corp.

All Rights Reserved.

This software and its associated documentation contains
proprietary, confidential and trade secret information
of Made to Order Software Corp. and except as provided by
written agreement with Made to Order Software Corp.

a) no part may be disclosed, distributed, reproduced,
   transmitted, transcribed, stored in a retrieval system,
   adapted or translated in any form or by any means
   electronic, mechanical, magnetic, optical, chemical,
   manual or otherwise,

and

b) the recipient is not entitled to discover through reverse
   engineering or reverse compiling or other such techniques
   or processes the trade secrets contained therein or in the
   documentation.
Back to Summary