For anyone looking how to pull an Invoice/Bill as a PDF, not as XML or JSON, from a Xero account via yii2 it is quite simple at the end of the day!
Here’s the gist of it:
/**
* Action: Download Invoice PDF
*
* Retrieves an invoice from Xero using its GUID and streams the PDF
* directly to the browser for inline viewing.
*
* Library:
* calcinai/xero-php
*
* Route Example:
* /controller/download-invoice?xeroInvoiceId={GUID}
*
* Expected Output:
* application/pdf
*
* @param string $xeroInvoiceId Xero invoice unique identifier.
* @return string PDF binary response.
* @throws \yii\web\ServerErrorHttpException
*/
public function actionDownloadInvoice($xeroInvoiceId)
{
$xero = null;
// Get your $xero instance
// *****
if (isset($xero)) {
try {
$invoice = $xero->loadByGUID(
Invoice::class,
$xeroInvoiceId,
['Accept' => 'application/pdf']
);
$pdfContent = $invoice->getPDF();
Yii::$app->response->format = \yii\web\Response::FORMAT_RAW;
Yii::$app->response->headers
->set('Content-Type', 'application/pdf')
->set('Content-Disposition', 'inline; filename="invoice-' . $xeroInvoiceId. '.pdf"');
return $pdfContent;
} catch (\Exception $e) {
throw new \yii\web\ServerErrorHttpException($e->getMessage());
}
}
}
or, an alternate more robust version might look like:
/**
* Action: Download Invoice PDF
*
* Retrieves an invoice from Xero using its GUID and streams the PDF
* directly to the browser for inline viewing.
*
* Library:
* calcinai/xero-php
*
* Route Example:
* /controller/download-invoice?xeroInvoiceId={GUID}
*
* Expected Output:
* application/pdf
*
* @param string $xeroInvoiceId Xero invoice unique identifier.
* @return string PDF binary response.
* @throws \yii\web\ServerErrorHttpException
*/
public function actionDownloadInvoice(string $xeroInvoiceId): string
{
$xero = null;
// Get your $xero instance
// *****
if ($xero === null) {
throw new \yii\web\ServerErrorHttpException('Xero client is not available.');
}
try {
$invoice = $xero->loadByGUID(
Invoice::class,
$xeroInvoiceId,
['Accept' => 'application/pdf']
);
if ($invoice === null) {
throw new \yii\web\NotFoundHttpException('Invoice not found.');
}
Yii::$app->response->format = \yii\web\Response::FORMAT_RAW;
Yii::$app->response->headers
->set('Content-Type', 'application/pdf')
->set(
'Content-Disposition',
'inline; filename="invoice-' . $xeroInvoiceId . '.pdf"'
);
return $invoice->getPDF();
} catch (\yii\web\HttpException $e) {
throw $e;
} catch (\Throwable $e) {
Yii::error($e->getMessage(), __METHOD__);
throw new \yii\web\ServerErrorHttpException(
'Unable to download invoice.'
);
}
}
Taking it further, you can give the PDF output a custom filename by customizing the following portion of the code:
filename="invoice-' . $xeroInvoiceId . '.pdf"'
Instead of just using the raw $xeroInvoiceId, which isn’t meaningful for end users. Consider incorporating the invoice date, client’s name and invoice number for clarity, though the exact format depends on your specific business requirements.