At work, we’re currently doing a FULL rebuild of our customer portal. Part of the requirements of the system are that our staff must only be logging into one place. At present they have to be logged into the portal AND WHMCS. So in v2, we have to basically rebuild 90% of the WHMCS admin interface into our portal, and use the WHMCS API for manipulating data stored in WHMCS. (We’re also adding a MongoDB caching layer for read access, and then using hooks in WHMCS to update the cache whenever data is modified).
We found a few ‘holes’ (read: missing functionality) in the WHMCS API, so had to see about adding an API to sit alongside WHMCS. We did ask WHMCS how to go about writing custom API functions to use within the WHMCS API framework, but they came back saying this was not possible. A fair bit of Googling around, and I managed to find a blog post detailing how to write custom API functions for WHMCS. With a bit of work, we now have a nice basis for writing WHMCS API modules. The first one I built for testing was for pulling Invoice PDF’s, which is not currently available in the WHMCS API.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
<?PHP // We don't want someone getting crafy and calling this manually without using the WHMCS API authentications if (!defined("WHMCS")) { die("This file cannot be accessed directly"); } // Borrowed from http://bobcares.com/blog/extend-whmcs-create-your-own-whmcs-api-functions/ function buildParams($vars) { $param = array( 'action' => array(), 'params' => array() ); // Is cmd set? If so we're being used as Local API if (isset($vars['cmd'])) { $param['action'] = $vars['cmd']; $param['params'] = (object) $vars['apivalues1']; $param['adminuser'] = $vars['adminuser']; } else { // Nope, then we're in remote API mode.. // Fix for WHMCS > 7.x if (!isset($vars['_POST']) && isset($vars['_POSTbackup'])) { $vars['_POST'] = $vars['_POSTbackup']; } $param['action'] = $vars['_POST']['action']; // Just cleaning up a bit, so these don't go into the params sub array.. unset($vars['_POST']['username']); unset($vars['_POST']['password']); unset($vars['_POST']['action']); $param['params'] = (object) $vars['_POST']; } return (object) $param; } try { // Get the arguments $vars = get_defined_vars(); $postFields = buildParams($vars); // Include the WHMCS invoicefunctions if (!function_exists('pdfInvoice')) { require_once('invoicefunctions.php'); } // And build an invoice PDF for the given invoiceID - Note, if this invoice ID is invalid, it will return a blank PDF.. $pdfdata = pdfInvoice($postFields->params->invoiceid); // Base64 encode it so it doesn't break the xml or json return $doc = base64_encode($pdfdata); // And return. WHMCS takes care of the json/xml encoding $apiresults = array( "result" => "success", "pdf" => $doc, "message" => "Success Message" ); } catch (Exception $e) { // Return with an error! $apiresults = array( "result" => "error", "message" => $e->getMessage() ); } |
And Voila, a simple WHMCS call such as:
1 2 |
$postfields["action"] = "saugetinvoicepdf"; $postfields["invoiceid"] = "16"; |
Returned Variables
1 2 3 4 5 6 |
<whmcsapi> <action>saugetinvoicepdf</action> <result>success</result> <pdf>......BASE64DATA......</pdf> <message>Success Message</message> </whmcsapi> |
Then it’s a simple matter to go base64_decode($jsondata->pdf) (assuming you used json format and had done a json_decode() on the returned data…), and you have the binary data for the PDF, ready to save to disk, or pass back out to the user via HTTP.
AWESOME!!! THANK YOU!!!`
Hi, use your code but Im getting this error:
Fatal error: Cannot redeclare getinvoicestatuscolour() in /xyxxxxxx/includes/invoicefunctions.php on line 6291459
Can you help me please, how to solve it?
It may be that invoicefunctions is being included with the API functions automatically these days. Try changing the require line to look like this instead:
if (!function_exists(‘getinvoicestatuscolour’)) {
require(‘invoicefunctions.php’);
}
Hi Damien, I’m getting “No input file specified.”
When I browse /includes/api.php this is returned, and also my curl_exec says the same.
Any clues?
Noobery. Thanks. Move along nothing to see here.
Lol no problems mate 🙂
Sorry to bump an old thread guys,
I am beside myself that this functionality isn’t included in WHMCS by default, but I guess that’s how it is.
I know I only need certain parts of the code because I’m only going to be using it in remote API mode. I’m going to be running it on the fly when someone logs into their “My Account” portal on my own page. So I don’t need to cache the page, but I suppose I could launch a popup with the PDF file rendered inside if a customer was to click on the show invoice button.
I’m a bit confused with the way that you pass the params,etc ?
Was the API still a CURL API when this was written??
What would I have to change to get it to work with v 7.3
Any help is greatly appreciated.
I’m glad i’ve found someone who took the time to write the script so that this vital functionality is now available.
Thanks.
Hey Gianpaolo,
I’m just working on upgrading our work WHMCS from 6.1.x to 7.7 now, and this API code is working with the _POSTbackup modification which Andrew suggested (now included in the main post) 🙂
I’m not sure what you mean by ‘still a CURL API when this was written?’ as the access method for the API hasn’t changed at all that I can see, unless you’ve changed over from username/password to apitoken. But that’s a whole different kettle of fish, which I’ll look at in a few weeks. As it is, the existing API authentication works perfectly.
We have ~70 custom API calls in our WHMCS install, and I have been dreading the upgrade, but it was actually fairly simple 🙂
for versions 7+ use _POSTbackup
and use username and password instead of API secret and API key as they require access control now
Hey Andrew,
Is it still working in WHMCS 7.4 using these changes? Finally looking at our WHMCS 7 upgrade at work in the next few weeks, have been dreading if we have to break our custom API calls (> 50 of them) out into another container, separate from WHMCS..
Yes it is working, we had it working with 7.4. Had to scramble the upload script due to GDPR requirements.
Beautiful, that fixes it in 7.x, have updated the main post 🙂