protected function setPaymentComplete($sTxnId = null, $iFee = null)
    {
        //  Ensure we have a payment
        if (empty($this->oPayment)) {
            throw new RequestException('No payment selected.');
        }

        //  Ensure we have an invoice
        if (empty($this->oInvoice)) {
            throw new RequestException('No invoice selected.');
        }

        //  Update the payment
        $aData = ['txn_id' => $sTxnId ? $sTxnId : null];

        if (!is_null($iFee)) {
            $aData['fee'] = $iFee;
        }

        if (!$this->oPaymentModel->setComplete($this->oPayment->id, $aData)) {
            throw new RequestException('Failed to update existing payment.');
        }

        //  Has the invoice been paid in full? If so, mark it as paid and fire the invoice.paid event
        if ($this->oInvoiceModel->isPaid($this->oInvoice->id)) {

            //  Mark Invoice as PAID
            if (!$this->oInvoiceModel->setPaid($this->oInvoice->id)) {
                throw new RequestException('Failed to mark invoice as paid.');
            }
        }

        //  Send receipt email
        $this->oPaymentModel->sendReceipt($this->oPayment->id);

        return $this;
    }