public function refund(int $iPaymentId, int $iAmount = null, string $sReason = null): bool
    {
        try {

            //  Validate payment
            $oPayment = $this->getById($iPaymentId, ['expand' => ['invoice']]);
            if (!$oPayment) {
                throw new PaymentException('Invalid payment ID.');
            }

            //  Set up RefundRequest object
            /** @var RefundRequest $oRefundRequest */
            $oRefundRequest = Factory::factory('RefundRequest', 'nails/module-invoice');

            //  Set the driver to use for the request
            $oRefundRequest->setDriver($oPayment->driver->slug);

            //  Describe the charge
            $oRefundRequest->setReason($sReason);

            //  Set the payment we're refunding against
            $oRefundRequest->setPayment($oPayment->id);

            //  Attempt the refund
            /** @var RefundResponse $oRefundResponse */
            $oRefundResponse = $oRefundRequest->execute($iAmount);

            if ($oRefundResponse->isProcessing() || $oRefundResponse->isComplete()) {
                //  It's all good
            } elseif ($oRefundResponse->isFailed()) {
                //  Refund failed, throw an error which will be caught and displayed to the user
                throw new PaymentException('Refund failed: ' . $oRefundResponse->getError()->user);
            } else {
                //Something which we've not accounted for went wrong.
                throw new PaymentException('Refund failed.');
            }

            return true;

        } catch (PaymentException $e) {
            $this->setError($e->getMessage());
            return false;
        }
    }