public function testServerCompleteAuthorizeResponseSuccess()
    {
        $response = new ServerCompleteAuthorizeResponse(
            $this->getMockRequest(),
            array(
                'Status' => 'OK',
                'TxAuthNo' => 'b',
                'AVSCV2' => 'c',
                'AddressResult' => 'd',
                'PostCodeResult' => 'e',
                'CV2Result' => 'f',
                'GiftAid' => 'g',
                '3DSecureStatus' => 'h',
                'CAVV' => 'i',
                'AddressStatus' => 'j',
                'PayerStatus' => 'k',
                'CardType' => 'l',
                'Last4Digits' => 'm',
            )
        );

        $this->getMockRequest()->shouldReceive('getTransactionId')->once()->andReturn('123');
        $this->getMockRequest()->shouldReceive('getTransactionReference')->once()->andReturn('{"SecurityKey":"JEUPDN1N7E","TxAuthNo":"4255","VPSTxId":"{F955C22E-F67B-4DA3-8EA3-6DAC68FA59D2}","VendorTxCode":"438791"}');

        $this->assertTrue($response->isSuccessful());
        $this->assertFalse($response->isRedirect());
        $this->assertSame('{"SecurityKey":"JEUPDN1N7E","TxAuthNo":"b","VPSTxId":"{F955C22E-F67B-4DA3-8EA3-6DAC68FA59D2}","VendorTxCode":"123"}', $response->getTransactionReference());
        $this->assertNull($response->getMessage());
    }
// Get the gateway driver.
// Don't forget to use your own vendor name.
// Always "Server". "Direct" will never get here.
$gateway = OmniPay::create('SagePay\\Server')->setVendor(getenv('VENDOR'))->setTestMode(true);
// Get the "complete purchase" message.
$requestMessage = $gateway->completePurchase(['transactionReference' => $transactionReference]);
// Do a "send" - this will validate everything.
try {
    $responseMessage = $requestMessage->send();
} catch (\Exception $e) {
    // InvalidResponseException will not catch a null transactionReference.
    // You may want to catch them separately and return different error messages.
    // This is a nasty hack, manually creating a message in the
    // event of an exception caused by a security failure.
    $requestMessage = $gateway->completePurchase([]);
    $responseMessage = new ServerCompleteAuthorizeResponse($requestMessage, []);
    $responseMessage->invalid($finalUrl, $e->getMessage());
}
// Handle the actions based on successful (or not) authorisation
// of the transaction.
if ($responseMessage->isSuccessful()) {
    $finalStatus = 'APPROVED';
    // Set the ball rolling here with processing the transaction.
    // Perhaps throw the result in a queue.
} else {
    $finalStatus = 'REJECTED';
}
// Store the result.
Storage::update($transactionId, ['finalStatus' => $finalStatus, 'status' => $responseMessage->getStatus(), 'message' => $responseMessage->getMessage(), 'notifyData' => $responseMessage->getData()]);
// Return to SagePay with a big, fat "got it, thanks" message.
$responseMessage->confirm($finalUrl);