private CallbackResult GenerateAbortedCallbackResponse(OrderReadOnly order, CallbackRequestModel request, OpayoSettings settings)
        {
            logger.Warn <OpayoServerClient>("Payment transaction aborted:\n\tOpayoTx: {VPSTxId}\n\tDetail: {StatusDetail}", request.VPSTxId, request.StatusDetail);

            var validSig = ValidateVpsSigniture(order, request, settings);

            return(new CallbackResult
            {
                HttpResponse = new HttpResponseMessage(System.Net.HttpStatusCode.OK)
                {
                    Content = validSig
                        ? GenerateAbortCallbackResponseBody()
                        : GenerateInvalidCallbackResponseBody()
                }
            });
        }
        private CallbackResult GeneratePendingCallbackResponse(OrderReadOnly order, CallbackRequestModel request, OpayoSettings settings)
        {
            logger.Warn <OpayoServerClient>("Payment transaction pending:\n\tOpayoTx: {VPSTxId}", request.VPSTxId);

            var validSig = ValidateVpsSigniture(order, request, settings);

            return(new CallbackResult
            {
                TransactionInfo = validSig
                    ? new TransactionInfo
                {
                    TransactionId = request.VPSTxId,
                    AmountAuthorized = order.TotalPrice.Value.WithTax,
                    TransactionFee = request.Surcharge,
                    PaymentStatus = PaymentStatus.PendingExternalSystem
                }
                    : null,
                HttpResponse = new HttpResponseMessage(System.Net.HttpStatusCode.OK)
                {
                    Content = validSig
                        ? GenerateOkCallbackResponseBody()
                        : GenerateInvalidCallbackResponseBody()
                }
            });
        }
        private CallbackResult GenerateNotAuthorisedCallbackResponse(OrderReadOnly order, CallbackRequestModel request, OpayoSettings settings)
        {
            logger.Warn <OpayoServerClient>("Payment transaction not authorised:\n\tOpayoTx: {VPSTxId}", request.VPSTxId);

            var validSig = ValidateVpsSigniture(order, request, settings);

            return(new CallbackResult
            {
                TransactionInfo = validSig
                    ? new TransactionInfo
                {
                    TransactionId = request.VPSTxId,
                    AmountAuthorized = 0,
                    TransactionFee = request.Surcharge,
                    PaymentStatus = PaymentStatus.Error
                }
                    : null,
                HttpResponse = new HttpResponseMessage(System.Net.HttpStatusCode.OK)
                {
                    Content = validSig
                        ? GenerateRejectedCallbackResponseBody()
                        : GenerateInvalidCallbackResponseBody()
                },
                MetaData = validSig
                    ? new Dictionary <string, string>
                {
                    { OpayoConstants.OrderProperties.TransDetails, string.Join(":", request.TxAuthNo, request.CardType, request.Last4Digits) },
                    { OpayoConstants.OrderProperties.TransDetailsHash, string.Join(":", request.TxAuthNo, request.CardType, request.Last4Digits).ToMD5Hash() }
                }
                    : null
            });
        }
        private CallbackResult GenerateAuthenticatedCallbackResponse(OrderReadOnly order, CallbackRequestModel request, OpayoSettings settings)
        {
            logger.Warn <OpayoServerClient>("Payment transaction Authenticated:\n\tOpayoTx: {VPSTxId}", request.VPSTxId);

            var validSig = ValidateVpsSigniture(order, request, settings);

            return(new CallbackResult
            {
                HttpResponse = new HttpResponseMessage(System.Net.HttpStatusCode.OK)
                {
                    Content = validSig
                        ? GenerateOkCallbackResponseBody()
                        : GenerateInvalidCallbackResponseBody()
                },
                MetaData = validSig
                    ? new Dictionary <string, string>
                {
                    { OpayoConstants.OrderProperties.TransDetails, string.Join(":", request.TxAuthNo, request.CardType, request.Last4Digits) },
                    { OpayoConstants.OrderProperties.TransDetailsHash, string.Join(":", request.TxAuthNo, request.CardType, request.Last4Digits).ToMD5Hash() }
                }
                    : null
            });
        }
        public CallbackResult HandleCallback(OrderReadOnly order, CallbackRequestModel request, OpayoSettings settings)
        {
            switch (request.Status)
            {
            case OpayoConstants.CallbackRequest.Status.Abort:
                return(GenerateAbortedCallbackResponse(order, request, settings));

            case OpayoConstants.CallbackRequest.Status.Rejected:
                return(GenerateRejectedCallbackResponse(order, request, settings));

            case OpayoConstants.CallbackRequest.Status.Registered:
            case OpayoConstants.CallbackRequest.Status.Error:
                return(GenerateErrorCallbackResponse(order, request, settings));

            case OpayoConstants.CallbackRequest.Status.Pending:
                return(GeneratePendingCallbackResponse(order, request, settings));

            case OpayoConstants.CallbackRequest.Status.Ok:
                return(GenerateOkCallbackResponse(order, request, settings));

            case OpayoConstants.CallbackRequest.Status.NotAuthorised:
                return(GenerateNotAuthorisedCallbackResponse(order, request, settings));

            case OpayoConstants.CallbackRequest.Status.Authenticated:
                return(GenerateAuthenticatedCallbackResponse(order, request, settings));

            default:
                logger.Warn <SagePayServerClient>("Unknown callback response status recieved: {status}", request.Status);
                return(CallbackResult.Empty);
            }
        }
        private bool ValidateVpsSigniture(OrderReadOnly order, CallbackRequestModel callbackRequest, OpayoSettings settings)
        {
            var md5Values = new List <string>
            {
                callbackRequest.VPSTxId,
                callbackRequest.VendorTxCode,
                callbackRequest.Status,
                callbackRequest.TxAuthNo,
                settings.VendorName.ToLowerInvariant(),
                callbackRequest.AVSCV2,
                order.Properties[OpayoConstants.OrderProperties.SecurityKey]?.Value,
                callbackRequest.AddressResult,
                callbackRequest.PostCodeResult,
                callbackRequest.CV2Result,
                callbackRequest.GiftAid,
                callbackRequest.SecureStatus,
                callbackRequest.CAVV,
                callbackRequest.AddressStatus,
                callbackRequest.PayerStatus,
                callbackRequest.CardType,
                callbackRequest.Last4Digits,
                callbackRequest.DeclineCode,
                callbackRequest.ExpiryDate,
                callbackRequest.FraudResponse,
                callbackRequest.BankAuthCode
            };

            string calcedMd5Hash = string.Join("", md5Values.Where(v => string.IsNullOrEmpty(v) == false)).ToMD5Hash().ToUpperInvariant();

            return(callbackRequest.VPSSignature == calcedMd5Hash);
        }