public Task <PaymentAuthorizationGuiResponse> ProcessResponse(
            PaymentProviderConfiguration configuration,
            NameValueCollection paramsCollection,
            ResponseParameters additionalParameters)
        {
            string timestamp         = paramsCollection[RealexFields.RealexFieldTimestamp];
            string merchantid        = paramsCollection[RealexFields.RealexFieldMerchantId];
            string orderid           = paramsCollection[RealexFields.RealexFieldOrderId];
            string authcode          = paramsCollection[RealexFields.RealexFieldAuthCode];
            string resultCode        = paramsCollection[RealexFields.RealexFieldResult];
            string textmsg           = paramsCollection[RealexFields.RealexFieldResponseTextMessage];
            string receiptNumber     = paramsCollection[RealexFields.RealexFieldPasRef];
            string responseSignature = paramsCollection[RealexFields.RealexFieldHashSignature];
            string amountString      = paramsCollection[RealexFields.RealexFieldAmount];

            string[] fieldsForResponseSignature = new string[]
            {
                timestamp,
                merchantid,
                orderid,
                resultCode,
                textmsg,
                receiptNumber, // PASREF
                authcode
            };
            string expectedResponseHash = CalculateRealexSignature(fieldsForResponseSignature, configuration.SharedSecret);

            decimal amount;

            if (decimal.TryParse(amountString, out amount))
            {
                amount = amount / 100m;
            }
            else
            {
                amount = 0;
            }

            if (expectedResponseHash != responseSignature)
            {
                PaymentAuthorizationResponse dummyBackendResponse = new PaymentAuthorizationResponse(false, PaymentAuthorizationResult.Unknown, amount,
                                                                                                     "incorrect SHA1HASH.", receiptNumber)
                {
                    ResponseCode  = resultCode,
                    TransactionId = orderid
                };
                return(Task.FromResult(new PaymentAuthorizationGuiResponse(dummyBackendResponse, null)));
            }

            PaymentAuthorizationResult isAuthorized = IsResponseCodeSuccess(resultCode) ? PaymentAuthorizationResult.Authorized : PaymentAuthorizationResult.Declined;

            var savedCardResponse = new SavedCardResponse();

            if (!string.IsNullOrEmpty(paramsCollection[RealVaultFields.ResponsePayerSetupResultCode]) && paramsCollection[RealVaultFields.ResponsePayerSetupResultCode] == "00")
            {
                savedCardResponse.NewCardholderSaved = true;
            }

            if (!string.IsNullOrEmpty(paramsCollection[RealVaultFields.ResponseSavedPayerRef]))
            {
                savedCardResponse.CardholderReference = paramsCollection[RealVaultFields.ResponseSavedPayerRef];
            }

            if (!string.IsNullOrEmpty(paramsCollection[RealVaultFields.ResponseSavedCardResultCode]))
            {
                if (IsResponseCodeSuccess(paramsCollection[RealVaultFields.ResponseSavedCardResultCode]))
                {
                    savedCardResponse.CardSaved     = true;
                    savedCardResponse.CardReference = paramsCollection[RealVaultFields.ResponseSavedCardRef];
                    savedCardResponse.CardDigits    = paramsCollection[RealVaultFields.ResponseMaskedCardDigits];
                    savedCardResponse.ExpiryDate    =
                        Utility.ParseExpiryDate(paramsCollection[RealVaultFields.ResponseSavedCardExpiryDate]);
                }
                else
                {
                    savedCardResponse.CardSaved      = false;
                    savedCardResponse.CardSaveStatus = paramsCollection[RealVaultFields.ResponseSavedCardResultMessage];
                }
            }

            PaymentAuthorizationResponse response = new PaymentAuthorizationResponse(
                IsResponseCodeSuccess(resultCode), isAuthorized, amount, textmsg, receiptNumber)
            {
                ResponseCode  = resultCode,
                TransactionId = orderid,
                SavedCard     = savedCardResponse
            };

            var realExResponse = new RealExServerResponse();

            StringBuilder displayText = new StringBuilder();

            if (!response.ResponseOk)
            {
                realExResponse.ImagePath         = additionalParameters.FailureImageUrl;
                realExResponse.ConfigDescription = "Payment failed";

                displayText.Append("There was an error while processing your payment.<br />Please contact <a href=\"mailto:[email protected]\">My Play Service Support</a><br />");

                displayText.AppendFormat($"ERROR DETAILS : {textmsg}");
            }
            else
            {
                // TODO: show AUTHCODE to user (a legal requirement?) and an absolute hyperlink back in to the ebooking application

                realExResponse.ConfigDescription = "Payment Success";

                displayText.AppendFormat($"Payment Reference Number = {response.ReceiptNumber}<br />");
                displayText.AppendFormat($"Amount Paid = {response.AmountAuthorized:c}<br />");
                displayText.AppendFormat("Booking Reference Number {0}<br />", additionalParameters.Reference);
                displayText.AppendFormat("A confirmation email will be sent shortly with all details and invoice");

                realExResponse.ImagePath = additionalParameters.SuccessImageUrl;
                realExResponse.AdditionalSuccessMessage = additionalParameters.AdditionalSuccessMessage;
            }
            realExResponse.MainResult = displayText.ToString();

            realExResponse.NextUrl = additionalParameters.NextUrl;

            PartialViewResult serverReply = PaymentFrameworkUtility.CreatePartialView("~/Views/Payment/ReplyToRealEx.cshtml", realExResponse);

            PaymentAuthorizationGuiResponse guiResponse = new PaymentAuthorizationGuiResponse(response, serverReply);

            return(Task.FromResult <PaymentAuthorizationGuiResponse>(guiResponse));
        }
        private PaymentAuthorizationResponse ParseResponseFromCapitaResponse(scpSimpleQueryResponse1 capitaResponse)
        {
            if (null == capitaResponse?.scpSimpleQueryResponse)
            {
                return(new PaymentAuthorizationResponse(true, PaymentAuthorizationResult.ErrorUnknownStatus, 0, "null response", null));
            }

            switch (capitaResponse.scpSimpleQueryResponse.transactionState)
            {
            case transactionState.COMPLETE:
                // continue processing
                break;

            case transactionState.IN_PROGRESS:
                return(new PaymentAuthorizationResponse(true, PaymentAuthorizationResult.Unknown, 0, "Transaction is still in progress", null));

            case transactionState.INVALID_REFERENCE:
                return(new PaymentAuthorizationResponse(true, PaymentAuthorizationResult.Unknown, 0, "Transaction has been in validated", null));
            }


            string       errorMessage = string.Empty;
            decimal      amount       = 0;
            errorDetails item         = capitaResponse.scpSimpleQueryResponse.paymentResult.Item as errorDetails;

            if (item != null)
            {
                errorMessage = $"Response code = {capitaResponse.scpSimpleQueryResponse.paymentResult.status}, ErrorId: {item.errorId}, ErrorMsg: {item.errorMessage}";
            }
            else
            {
                string responseDetails = $"Capita Query Response for RequestId {capitaResponse.scpSimpleQueryResponse.requestId}: ScpReference = {capitaResponse.scpSimpleQueryResponse.scpReference} ";

                simplePayment paymentDetails = capitaResponse.scpSimpleQueryResponse.paymentResult.Item as simplePayment;
                if (paymentDetails != null)
                {
                    if (paymentDetails.paymentHeader != null)
                    {
                        responseDetails += $", TransactionDateUtc: {paymentDetails.paymentHeader.transactionDate.ToUniversalTime()}, MachineCode: {paymentDetails.paymentHeader.machineCode}, TransactionId: {paymentDetails.paymentHeader.uniqueTranId}";
                    }


                    authDetails authInfo = paymentDetails.Item as authDetails;
                    if (authInfo != null)
                    {
                        amount = authInfo.amountInMinorUnits;
                        //Convert minor unit amount value into larger unit. For example from pennies to pounds
                        amount           = amount / 100m;
                        responseDetails += $", Amount (Minor Units): {authInfo.amountInMinorUnits}, AuthCode: {authInfo.authCode}, MerchantNumber: {authInfo.merchantNumber}";
                    }
                }

                this.Logger.CreateEntry(typeof(CapitaApiProvider), LogLevel.Info, responseDetails);
            }

            switch (capitaResponse.scpSimpleQueryResponse.paymentResult.status)
            {
            case status.SUCCESS:

                CapitaSavedCardResponse cardResponse  = null;
                string storeCardDetailsFailureMessage = string.Empty;
                if (capitaResponse.scpSimpleQueryResponse.storeCardResult != null)
                {
                    if (capitaResponse.scpSimpleQueryResponse.storeCardResult.status != status.SUCCESS &&
                        capitaResponse.scpSimpleQueryResponse.storeCardResult.status != status.NOT_ATTEMPTED)
                    {
                        errorDetails storeCardErrorDetails =
                            capitaResponse.scpSimpleQueryResponse.storeCardResult.Item as errorDetails;

                        if (storeCardErrorDetails != null)
                        {
                            storeCardDetailsFailureMessage = $"ErrorId: {storeCardErrorDetails.errorId}, ErrorMessage: {storeCardErrorDetails.errorMessage}";
                        }
                        else
                        {
                            storeCardDetailsFailureMessage = "Error: Card details could not be stored. ";
                        }

                        cardResponse = new CapitaSavedCardResponse()
                        {
                            CardSaved      = false,
                            CardSaveStatus = storeCardDetailsFailureMessage
                        };
                    }
                    else
                    {
                        storedCardDetails cardDetails = capitaResponse.scpSimpleQueryResponse.storeCardResult.Item as storedCardDetails;
                        if (cardDetails != null)
                        {
                            cardResponse = new CapitaSavedCardResponse()
                            {
                                CardSaved       = true,
                                CardReference   = cardDetails.storedCardKey.token,
                                CardDigits      = cardDetails.storedCardKey.lastFourDigits,
                                CardDescription = cardDetails.cardDescription.ToString(),
                                CardType        = cardDetails.cardType.ToString(),
                                ExpiryDate      = Utility.ParseExpiryDate(cardDetails.expiryDate)
                            };
                        }
                    }
                }

                string description =
                    $"{storeCardDetailsFailureMessage} ScpReference = {capitaResponse.scpSimpleQueryResponse.scpReference} and RequestId = {capitaResponse.scpSimpleQueryResponse.requestId}.";

                var authorizationResponse = new PaymentAuthorizationResponse(true, PaymentAuthorizationResult.Authorized, amount, description, capitaResponse.scpSimpleQueryResponse.requestId);

                if (cardResponse != null)
                {
                    authorizationResponse.SavedCard = cardResponse;
                }

                return(authorizationResponse);

            case status.INVALID_REQUEST:
            case status.CARD_DETAILS_REJECTED:
            case status.CANCELLED:
            case status.LOGGED_OUT:
            case status.NOT_ATTEMPTED:
                // record not found : either user is still in the GUI or abandonded the process
                return(new PaymentAuthorizationResponse(true, PaymentAuthorizationResult.Declined, 0, errorMessage, capitaResponse.scpSimpleQueryResponse.requestId));

            default:
                return(new PaymentAuthorizationResponse(true, PaymentAuthorizationResult.ErrorUnknownStatus, 0, errorMessage, capitaResponse.scpSimpleQueryResponse.requestId));
            }
        }