Inheritance: mobSocial.Core.Data.BaseEntity
Ejemplo n.º 1
0
        public IHttpActionResult ProcessPayment(FormCollection parameters)
        {
            //first get the payment processor
            var paymentMethodName = parameters.Get(PaymentParameterNames.PaymentMethodTypeName);
            if (string.IsNullOrEmpty(paymentMethodName))
            {
                VerboseReporter.ReportError("Invalid payment method", "process_payment");
                return RespondFailure();
            }

            //the transaction amount
            decimal amount;
            var amountString = parameters.Get(PaymentParameterNames.Amount) ?? "0";
            decimal.TryParse(amountString, out amount);

            PaymentMethodType methodType;
            if (System.Enum.TryParse(paymentMethodName, out methodType))
            {
                methodType = PaymentMethodType.CreditCard;
            }

            //get the payment processor now
            var paymentProcessor = _paymentProcessingService.GetPaymentProcessorPlugin(amount, methodType);

            if (paymentProcessor == null)
            {
                VerboseReporter.ReportError("Invalid payment method", "process_payment");
                return RespondFailure();
            }

            //convert form collection to dictionary to check if parameters are valid
            var formCollectionDictionary = parameters.ToDictionary(pair => pair.Key, pair => (object)pair.Value);

            var isValid = paymentProcessor.AreParametersValid(formCollectionDictionary);

            UserPaymentMethod paymentMethod = null;
            if (!isValid)
            {
                //the parameters are not valid. but that may also mean that the user is selecting an already saved payment method
                //and so he wouldn't have sent that data again
                var savedPaymentMethodIdString = parameters.Get(PaymentParameterNames.UserSavedPaymentMethodId);
                int savedPaymentMethodId;
                if (int.TryParse(savedPaymentMethodIdString, out savedPaymentMethodId))
                {
                    var userPaymentMethods =
                    _paymentMethodService.Get(x => x.UserId == ApplicationContext.Current.CurrentUser.Id && x.Id == savedPaymentMethodId, null);

                    if (userPaymentMethods.Any())
                    {
                        paymentMethod = userPaymentMethods.First();
                        isValid = true;
                    }
                }
                //still invalid? something is not right then.
                if (!isValid)
                {
                    VerboseReporter.ReportError("Invalid parameters to process payment", "process_payment");
                    return RespondFailure();
                }

            }

            //we save the payment method in our database if it's CreditCard
            if (paymentProcessor.Supports(PaymentMethodType.CreditCard))
            {

                if (paymentMethod == null)
                {
                    #region saving payment method to database
                    var creditCardNumber = parameters.Get(PaymentParameterNames.CardNumber);
                    //let's validate the card for level 1 check (luhn's test) first before storing
                    var isCardValid = PaymentCardHelper.IsCardNumberValid(creditCardNumber);
                    //card number
                    if (!isCardValid)
                    {
                        VerboseReporter.ReportError("Invalid card number", "process_payment");
                        return RespondFailure();
                    }
                    //expiration date
                    var expireMonth = parameters.Get(PaymentParameterNames.ExpireMonth);
                    var expireYear = parameters.Get(PaymentParameterNames.ExpireYear);
                    if (!expireYear.IsInteger() || !expireMonth.IsInteger())
                    {
                        VerboseReporter.ReportError("Invalid expiration month or year", "process_payment");
                        return RespondFailure();
                    }
                    //card issuer
                    var cardIssuer = PaymentCardHelper.GetCardTypeFromNumber(creditCardNumber);
                    if (!cardIssuer.HasValue)
                    {
                        VerboseReporter.ReportError("Unsupported card provider", "process_payment");
                        return RespondFailure();
                    }

                    var nameOnCard = parameters.Get(PaymentParameterNames.NameOnCard);
                    //encrypt credit card info to store in db
                    var key = ConfigurationManager.AppSettings.Get("EncryptionKey");
                    var salt = ConfigurationManager.AppSettings.Get("Salt");

                    var cardNumber = _cryptographyService.Encrypt(creditCardNumber, key, salt); //encrypt the card info
                    //fine if the card is valid, but is the card number already in our record, then not possible to save the same again
                    if (_paymentMethodService.DoesCardNumberExist(cardNumber))
                    {
                        VerboseReporter.ReportError("The card number is already saved in records", "process_payment");
                        return RespondFailure();
                    }

                    paymentMethod = new UserPaymentMethod() {
                        UserId = ApplicationContext.Current.CurrentUser.Id,
                        IsVerified = false,
                        PaymentMethodType = PaymentMethodType.CreditCard,
                        CardIssuerType = cardIssuer.ToString().ToLowerInvariant(),
                        CardNumber = creditCardNumber,
                        CardNumberMasked = PaymentCardHelper.MaskCardNumber(creditCardNumber),
                        NameOnCard = nameOnCard,

                    };
                    //save this payment method
                    _paymentMethodService.Insert(paymentMethod);
                    #endregion
                }
            }

            //we need to see if we should only authorize or capture as well
            //the idea is if it's a sponsorship context, it's better to authorize the payment transaction and capture later when
            //the sponsorship is accepted //we thought of initially only authorizing sponsorship transactions and capture when it's accepted.
            //but that flow doesn't seem to work quite well, thoughts?
            var authorizeOnly = false; // (parameters.Get(PaymentParameterNames.PaymentContext) ?? string.Empty) == "sponsor";

            //so we are ready for payment processing, let's create a paymenttrasaction for storing in our db
            var paymentTransaction = new PaymentTransaction() {
                IsLocalTransaction = true,
                PaymentStatus = PaymentStatus.Pending,
                TransactionAmount = amount,
                TransactionGuid = Guid.NewGuid(),
                CreatedOn = DateTime.UtcNow,
                UserIpAddress = WebHelper.GetClientIpAddress()
            };
            _paymentTransactionService.Insert(paymentTransaction);

            //now proceed further with the payment
            //create the transaction request
            var transactionRequest = new TransactionRequest() {
                Amount = amount,
                CurrencyIsoCode = "USD",//TODO: SET CURRENCY AS SELECTED BY USER
                PaymentProcessorSystemName = paymentProcessor.PluginInfo.SystemName,
                UserId = ApplicationContext.Current.CurrentUser.Id,
                Parameters = formCollectionDictionary,
                TransactionUniqueId = paymentTransaction.TransactionGuid.ToString()
            };

            var response = paymentProcessor.Process(transactionRequest, authorizeOnly);
            //update values of transaction parameters for future reference
            paymentTransaction.TransactionCodes = response.ResponseParameters;
            //update payment transaction
            _paymentTransactionService.Update(paymentTransaction);

            if (response.Success)
            {
                //let's verify the payment method first if it's not
                if (paymentMethod != null && !paymentMethod.IsVerified)
                {
                    paymentMethod.IsVerified = true;
                    _paymentMethodService.Update(paymentMethod);
                }

                //now since the response was success, we can actually assign some credits to the user
                var creditCount = amount * (1 / _paymentSettings.CreditExchangeRate);
                var credit = new Credit()
                {
                    PaymentTransactionId = paymentTransaction.Id,
                    CreatedOnUtc = DateTime.UtcNow,
                    CreditCount = creditCount,
                    CreditExchangeRate = _paymentSettings.CreditExchangeRate,
                    //if it's authorize only transaction, we assign the credits, but they won't be usable before they are approved by capture
                    CreditTransactionType = CreditTransactionType.Issued,
                    CreditType = CreditType.Transactional,
                    IsExpired = false
                };

                //save credit
                _creditService.Insert(credit);

                //get total available credits of user
                var usableCreditCount = _creditService.GetUsableCreditsCount(ApplicationContext.Current.CurrentUser.Id);
                return RespondSuccess(new {
                    UsableCreditCount = usableCreditCount
                });
            }
            VerboseReporter.ReportError("An error occured while processing payment", "process_payment");
            return RespondFailure();
        }
        public ITransactionProcessResult ProcessPayment(User user, UserPaymentMethod paymentMethod, ITransactionProcessRequest processRequest, bool authorizeOnly = false)
        {
            if(processRequest == null)
                throw new mobSocialException("Can't process null request");

            //check if the plugin is installed and activated
            //depending on the payment amount, we may wish to switch between macro and micro payments
            //check if plugin is installed or not
            //TODO: Change the other payment method to appropriate one for macro payments
            var paymentPluginSystemName = processRequest.Amount < MicroMacroPaymentSwitchingAmount ? "Payments.PayPalDirect" : "Payments.PayPalDirect";

            //if we get an instance, then the plugin is installed
            var plugin = GetPluginInstance(paymentPluginSystemName);

            //plugin should be available and if it's an authorization transaction, the plugin should actually support authorize and capture
            if (plugin == null || (!plugin.CaptureSupported && authorizeOnly))
                return null;

               //process the payment now
            var result = plugin.Process(processRequest);
            return result;
        }