protected function complete($oPayment)
    {
        $oPaymentModel = Factory::model('Payment', 'nails/module-invoice');

        $this->data['oPayment'] = $oPayment;
        $this->data['oInvoice'] = $oPayment->invoice;

        if ($oPayment->status->id === $oPaymentModel::STATUS_FAILED) {
            //  Payments which FAILED should be ignored
            show404();

        } elseif ($oPayment->status->id === $oPaymentModel::STATUS_COMPLETE) {

            //  Payment is already complete
            redirect($oPayment->urls->thanks);

        } elseif ($oPayment->status->id === $oPaymentModel::STATUS_PROCESSING) {

            //  Payment is already complete and is being processed
            redirect($oPayment->urls->processing);

        } else {

            try {

                //  Set up CompleteRequest object
                $oCompleteRequest = Factory::factory('CompleteRequest', 'nails/module-invoice');

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

                //  Set the payment we're completing
                $oCompleteRequest->setPayment($oPayment->id);

                //  Set the invoice we're completing
                $oCompleteRequest->setInvoice($oPayment->invoice->id);

                //  Set the complete URL, if there is one
                $oCompleteRequest->setContinueUrl($oPayment->urls->continue);

                //  Attempt completion
                $oInput            = Factory::service('Input');
                $oCompleteResponse = $oCompleteRequest->execute(
                    $oInput->get(),
                    $oInput->post()
                );

                if ($oCompleteResponse->isProcessing()) {

                    //  Payment was successful but has not been confirmed
                    if ($oCompleteRequest->getContinueUrl()) {
                        redirect($oCompleteRequest->getContinueUrl());
                    } else {
                        redirect($oPayment->urls->processing);
                    }

                } elseif ($oCompleteResponse->isComplete()) {

                    //  Payment has completed fully
                    if ($oCompleteRequest->getContinueUrl()) {
                        redirect($oCompleteRequest->getContinueUrl());
                    } else {
                        redirect($oPayment->urls->thanks);
                    }

                } elseif ($oCompleteResponse->isFailed()) {
                    throw new NailsException('Payment failed: ' . $oCompleteResponse->getError()->user, 1);
                } else {
                    throw new NailsException('Payment failed.', 1);
                }

            } catch (\Exception $e) {
                $oSession = Factory::service('Session', 'nails/module-auth');
                $oSession->setFlashData('error', $e->getMessage());
                redirect($oPayment->invoice->urls->payment);
            }
        }
    }