Example #1
0
        /// <summary>
        /// Handle authentication (via Merchant ID) and authorization (via API key).
        /// MerchantId is delivered as a header since it will (probably) be necessary for
        /// every call and should not pollute all request-specific models.
        ///
        /// Improvement Idea: Allow granular error messages to return to the caller,
        /// though this can in some instances be a slight security risk.
        /// Also: Introduce caching for enhanced performance and scalability.
        /// </summary>
        /// <param name="merchant">The Merchant based on the Merchant ID that was read from the headers</param>
        /// <returns></returns>
        private bool EnsureMerchantValidity(out Merchant merchant)
        {
            merchant = null;

            // check merchant ID
            if (!Request.Headers.ContainsKey(PaymentGatewayConstants.MerchantHeaderName))
            {
                return(false);
            }

            var rawMerchantId = Request.Headers[PaymentGatewayConstants.MerchantHeaderName].First();

            if (!Guid.TryParse(rawMerchantId, out var parsedMerchantId))
            {
                return(false);
            }

            // check if merchant with the merchant ID exists and is enabled
            merchant = _merchantRepository.GetByMerchantId(parsedMerchantId);
            if (merchant == null)
            {
                return(false);
            }

            if (!merchant.IsEnabled)
            {
                return(false);
            }

            // check api key
            if (!Request.Headers.ContainsKey(PaymentGatewayConstants.ApiKeyHeaderName))
            {
                return(false);
            }

            var rawApiKey = Request.Headers[PaymentGatewayConstants.ApiKeyHeaderName].First();
            var apiKey    = Encoding.UTF8.GetString(Convert.FromBase64String(rawApiKey));

            if (apiKey != merchant.ApiKey)
            {
                return(false);
            }

            return(true);
        }