/// <summary>
        /// Method is called when the order is being canceled by the merchant before the <see cref="Payment"/> is acquired.
        /// </summary>
        /// <param name="payment">The payment.</param>
        /// <param name="status">The status.</param>
        protected override bool CancelPaymentInternal(Payment payment, out string status)
        {
            var    paymentMethod = payment.PaymentMethod;
            string pspId         = paymentMethod.DynamicProperty <string>().PspId;
            string password      = paymentMethod.DynamicProperty <string>().Password;
            string userId        = paymentMethod.DynamicProperty <string>().UserId;
            string shaSignIn     = paymentMethod.DynamicProperty <string>().ShaSignIn;
            bool   testMode      = paymentMethod.DynamicProperty <bool>().TestMode;

            int ogonePaymentStatus = RequestPaymentStatusAtOgone(payment, pspId, userId, password, testMode);

            if (ogonePaymentStatus == 9 || ogonePaymentStatus == 91)
            {
                return(RefundPaymentInternal(payment, out status));
            }
            if (ogonePaymentStatus != 5)
            {
                status = string.Format("expected status was 5 or 91 for cancel payment, but was {0}. Check STATUS message at {1}"
                                       , ogonePaymentStatus
                                       , "https://secure.ogone.com/ncol/param_cookbook.asp?CSRFSP=%2Fncol%2Ftest%2Fdownload_docs%2Easp&CSRFKEY=7E003EFC9703DF1A30BF28559ED87B534C0F0309&CSRFTS=20110822081113"
                                       );
                return(false);
            }

            var dict = new Dictionary <string, string>();

            dict.Add("amount", payment.Amount.ToCents().ToString());
            dict.Add("currency", payment.PurchaseOrder.BillingCurrency.ISOCode);
            dict.Add("operation", "DES");
            dict.Add("orderid", payment.PurchaseOrder.OrderId.ToString());
            dict.Add("payid", payment.TransactionId);
            dict.Add("pspid", pspId);
            dict.Add("pswd", password);
            dict.Add("userid", userId);

            var shaComputer            = new OgoneSha1Computer();
            var cancelPaymentShaSignIn = new CancelPaymentShaSignIn();

            dict.Add("SHASign", shaComputer.ComputeHash(cancelPaymentShaSignIn.BuildHashString(dict, shaSignIn)).ToUpper());

            var url = GetMaintenanceDirectUrl(testMode);

            var oGoneDataCapture = RequestOgone(url, dict);

            var ncresponse        = oGoneDataCapture.Descendants("ncresponse").Single();
            var maintenanceStatus = Convert.ToInt32(ncresponse.Attributes("STATUS").Single().Value);

            payment.PaymentStatus = PaymentStatus.Get((int)ConvertCancelResultToPaymentStatus(maintenanceStatus));
            status = "";
            if (payment.PaymentStatus.PaymentStatusId == (int)PaymentStatusCode.Declined)
            {
                status = GetNCResponseErrorMessage(ncresponse);
                return(false);
            }

            return(true);
        }
        /// <summary>
        /// Method is called when the order is being canceled by the merchant, after the <see cref="Payment"/> have been acquired by the merchant.
        /// </summary>
        /// <param name="payment">The payment.</param>
        /// <param name="status">The status.</param>
        protected override bool RefundPaymentInternal(Payment payment, out string status)
        {
            var    paymentMethod = payment.PaymentMethod;
            string pspId         = paymentMethod.DynamicProperty <string>().PspId;
            string password      = paymentMethod.DynamicProperty <string>().Password;
            string userId        = paymentMethod.DynamicProperty <string>().UserId;
            string shaSignIn     = paymentMethod.DynamicProperty <string>().ShaSignIn;
            bool   testMode      = paymentMethod.DynamicProperty <bool>().TestMode;

            int paymentStatus = RequestPaymentStatusAtOgone(payment, pspId, userId, password, testMode);

            if (paymentStatus != 9 && paymentStatus != 91)
            {
                status = string.Format("Expected status was 'Payment requested' (9) or 'Payment Processig' (91) for refund, but was {0}. Check 'STATUS' message at {1}",
                                       paymentStatus,
                                       "https://secure.ogone.com/ncol/param_cookbook.asp"
                                       );
                return(false);
            }
            var dict = new Dictionary <string, string>();

            dict.Add("amount", payment.Amount.ToCents().ToString());
            dict.Add("currency", payment.PurchaseOrder.BillingCurrency.ISOCode);
            dict.Add("operation", "RFS");
            dict.Add("orderid", payment.ReferenceId);
            dict.Add("payid", payment.TransactionId);
            dict.Add("pspid", pspId);
            dict.Add("pswd", password);
            dict.Add("userid", userId);

            var shaComputer = new OgoneSha1Computer();
            var hashString  = new CancelPaymentShaSignIn();

            dict.Add("SHASign", shaComputer.ComputeHash(hashString.BuildHashString(dict, shaSignIn)).ToUpper());

            var url = GetMaintenanceDirectUrl(testMode);

            var oGoneDataCapture = RequestOgone(url, dict);
            var ncresponse       = oGoneDataCapture.Descendants("ncresponse").Single();

            var maintenanceStatus = Convert.ToInt32(ncresponse.Attributes("STATUS").Single().Value);

            payment.PaymentStatus = PaymentStatus.Get((int)ConvertRefundResultToPaymentStatus(maintenanceStatus));

            status = "";
            if (payment.PaymentStatus.PaymentStatusId == (int)PaymentStatusCode.Declined)
            {
                status = GetNCResponseErrorMessage(ncresponse);
                return(false);
            }

            return(true);
        }