/// <summary>
        /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="IHttpHandler"/> interface.
        /// </summary>
        /// <param name="context">
        /// An System.Web.HttpContext object that provides references to the intrinsic
        /// server objects (for example, Request, Response, Session, and Server) used
        /// to service HTTP requests.
        /// </param>
        public void ProcessRequest(HttpContext context)
        {
            string token = string.Empty;

            try
            {
                token = context.Request.Cookies["iapplypagetoken"].Value;
                string formId = context.Request.QueryString["formId"];
                string applicationId = context.Request.QueryString["applicationId"];

                SessionData sessionData = SessionDataSerializer.Deserialize(Global.Crypto, token);

                ApplicationManager applicationManager = Global.DependencyInjectionContainer.Resolve<ApplicationManager>();
                TransactionVariableFactory factory = Global.DependencyInjectionContainer.Resolve<TransactionVariableFactory>(formId);
                ApplicationPaymentManager manager = Global.DependencyInjectionContainer.Resolve<ApplicationPaymentManager>();

                RetrieveApplicationResponse appResponse = applicationManager.GetApplicationSecure(sessionData, applicationId);
                Application application = appResponse.Application;
                ApplicationData applicationData = application == null ? null : application.ApplicationData;
                TransactionVariables variables = factory.Create(formId, applicationId, applicationData);

                SecurePayTransactionResponse response = new SecurePayTransactionResponse();
                HttpRequestToTransactionResponseConverter converter = new HttpRequestToTransactionResponseConverter();
                converter.Convert(context.Request, response, variables);

                manager.SavePaymentResponse(applicationId, response);

                if (response.TransactionResult != SecurePayTransactionResult.Approved)
                {
                    string url = string.Format("{0}?0={1}&1={2}&2={3}", BASE_URL, PAYMENT_PROVIDER_KEY, applicationId, response.ResponseText);
                    context.Response.Redirect(url, true);
                }

                context.Response.ContentEncoding = Encoding.UTF8;
                context.Response.ContentType = "text/html";
                context.Response.Write(string.Format("<p class=\"receipt-text\">Thank you for your payment, your receipt number is <strong>{0}</strong></p>", context.Request["txnid"]));
            }
            catch (Exception e)
            {
                e.Data.Add("token", token);
                bool rethrow = ExceptionPolicy.HandleException(e, "Default");
                if (rethrow)
                {
                    throw;
                }

                context.Response.ContentEncoding = Encoding.UTF8;
                context.Response.ContentType = "text/html";
                context.Response.Write("<p class=\"receipt-text\">There was an error processing your payment. Please contact the system administrator.</p>");
            }
        }
        /// <summary>
        /// Sets the properties of a <see cref="SecurePayTransactionResponse"/> object
        /// based on the parameters of a <see cref="HttpRequest"/> object.
        /// </summary>
        /// <param name="httpRequest">A <see cref="HttpRequest"/> object to read from.</param>
        /// <param name="securePayResponse">A <see cref="SecurePayTransactionResponse"/> object to write to.</param>
        /// <param name="variables">The transaction variables.</param>
        /// <exception cref="SecurityException">
        /// The returned fingerprint value does not match the expected value.
        /// </exception>
        public void Convert(HttpRequest httpRequest, SecurePayTransactionResponse securePayResponse, TransactionVariables variables)
        {
            string merchantId = this.RequestParamNullGuard(httpRequest, SecurePayConstants.Result.MERCHANT_ID);
            string referenceId = this.RequestParamNullGuard(httpRequest, SecurePayConstants.Result.REFERENCE_ID);
            string timestamp = this.RequestParamNullGuard(httpRequest, SecurePayConstants.Result.TIMESTAMP);
            string summaryCode = this.RequestParamNullGuard(httpRequest, SecurePayConstants.Result.SUMMARY_CODE);
            string fingerprint = this.RequestParamNullGuard(httpRequest, SecurePayConstants.Result.FINGERPRINT);

            string localFingerprint = string.Format(
                "{0}|{1}|{2}|{3}|{4}|{5}",
                merchantId,
                variables.MerchantPassword,
                referenceId,
                variables.TransactionAmount.ToString("F2"),
                timestamp,
                summaryCode).ToSha1Hash();

            if (!localFingerprint.Equals(fingerprint))
            {
                throw new SecurityException("Invalid fingerprint.");
            }

            securePayResponse.TransactionResult = !string.IsNullOrEmpty(summaryCode) ? (SecurePayTransactionResult)Enum.Parse(typeof(SecurePayTransactionResult), summaryCode) : SecurePayTransactionResult.Unknown;
            securePayResponse.SummaryCode = summaryCode;
            securePayResponse.ResponseCode = this.RequestParamNullGuard(httpRequest, SecurePayConstants.Result.RESPONSE_CODE);
            securePayResponse.ResponseText = this.RequestParamNullGuard(httpRequest, SecurePayConstants.Result.RESPONSE_TEXT);
            securePayResponse.ReferenceId = referenceId;
            securePayResponse.TransactionId = this.RequestParamNullGuard(httpRequest, SecurePayConstants.Result.TRANSACTION_ID);
            securePayResponse.Amount = variables.TransactionAmount;
            string settlementDatestamp = this.RequestParamNullGuard(httpRequest, SecurePayConstants.Result.SETTLEMENT_DATE);
            if (!string.IsNullOrEmpty(settlementDatestamp))
            {
                securePayResponse.SettlementDate = new DateTime(
                    System.Convert.ToInt32(settlementDatestamp.Substring(0, 4)),
                    System.Convert.ToInt32(settlementDatestamp.Substring(4, 2)),
                    System.Convert.ToInt32(settlementDatestamp.Substring(6, 2)));
            }

            securePayResponse.PreAuthorisationId = this.RequestParamNullGuard(httpRequest, SecurePayConstants.Result.PREAUTHORISATION_ID);
            securePayResponse.ExpiryDate = this.RequestParamNullGuard(httpRequest, SecurePayConstants.Result.EXPIRY_DATE);
            securePayResponse.MerchantId = merchantId;
            securePayResponse.Timestamp = timestamp;
        }
        /// <summary>
        /// Converts a <see cref="MongoDB.Bson.BsonDocument" /> to a <see cref="SecurePayTransactionResponse" />.
        /// </summary>
        /// <param name="bsonResponse">A <see cref="MongoDB.Bson.BsonDocument" />.</param>
        /// <returns>A new <see cref="SecurePayTransactionResponse"/> which is the result of converting the <paramref name="bsonResponse"/>.</returns>
        private SecurePayTransactionResponse BsonDocumentToTransactionResponse(BsonDocument bsonResponse)
        {
            SecurePayTransactionResponse secureResponse = new SecurePayTransactionResponse
                                                          {
                                                              TransactionId = bsonResponse["TransactionId"].AsString,
                                                              TransactionResult = (SecurePayTransactionResult)Enum.Parse(typeof(SecurePayTransactionResult), bsonResponse["TransactionResult"].AsString),
                                                              SummaryCode = bsonResponse["SummaryCode"].AsString,
                                                              ResponseCode = bsonResponse["ResponseCode"].AsString,
                                                              ResponseText = bsonResponse["ResponseText"].AsString,
                                                              ReferenceId = bsonResponse["ReferenceId"].AsString,
                                                              Amount = bsonResponse["Amount"].AsDouble,
                                                              PreAuthorisationId = bsonResponse["PreAuthorisationId"].AsString,
                                                              ExpiryDate = bsonResponse["ExpiryDate"].AsString,
                                                              MerchantId = bsonResponse["MerchantId"].AsString,
                                                              Timestamp = bsonResponse["Timestamp"].AsString
                                                          };

            if (!bsonResponse["SettlementDate"].IsBsonNull)
            {
                secureResponse.SettlementDate = bsonResponse["SettlementDate"].ToUniversalTime();
            }

            return secureResponse;
        }