Exemplo n.º 1
0
        /// <summary>
        /// Charges the specified payment info.
        /// </summary>
        /// <param name="financialGateway"></param>
        /// <param name="paymentInfo">The payment info.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialTransaction Charge(FinancialGateway financialGateway, PaymentInfo paymentInfo, out string errorMessage)
        {
            var financialTransaction = base.Charge(financialGateway, paymentInfo, out errorMessage);

            // Handle issues with the "Original transaction ID not found" error more gracefully
            if (paymentInfo is ReferencePaymentInfo && errorMessage == "[19] Original transaction ID not found")
            {
                // First delete the saved account--it is worthless
                var rockContext         = new RockContext();
                var savedAccountService = new FinancialPersonSavedAccountService(rockContext);
                var savedAccount        = savedAccountService.Queryable()
                                          .Where(s =>
                                                 s.TransactionCode == (( ReferencePaymentInfo )paymentInfo).TransactionCode &&
                                                 s.FinancialGatewayId.HasValue &&
                                                 s.FinancialGatewayId.Value == financialGateway.Id)
                                          .FirstOrDefault();
                if (savedAccount != null)
                {
                    savedAccountService.Delete(savedAccount);
                    rockContext.SaveChanges();
                    errorMessage = "The previously saved payment method is no longer valid.  Please select a different method.";
                }
            }
            return(financialTransaction);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Gets the saved accounts.
        /// </summary>
        /// <returns></returns>
        private List <FinancialPersonSavedAccount> GetSavedAccounts()
        {
            if (_savedAccounts == null)
            {
                var person = GetPerson();

                if (person != null)
                {
                    var supportedGatewayIds = GetSupportedGatewayIds();

                    if (supportedGatewayIds != null && supportedGatewayIds.Any())
                    {
                        var rockContext = GetRockContext();
                        var service     = new FinancialPersonSavedAccountService(rockContext);

                        _savedAccounts = service
                                         .GetByPersonId(person.Id)
                                         .Include(sa => sa.FinancialPaymentDetail)
                                         .AsNoTracking()
                                         .Where(sa =>
                                                sa.FinancialGatewayId.HasValue &&
                                                supportedGatewayIds.Contains(sa.FinancialGatewayId.Value))
                                         .OrderBy(sa => sa.IsDefault)
                                         .ThenByDescending(sa => sa.CreatedDateTime)
                                         .ToList();
                    }
                }
            }

            return(_savedAccounts);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Gets the existing saved account.
        /// </summary>
        /// <param name="giveParameters">The give parameters.</param>
        /// <param name="person">The person.</param>
        /// <param name="rockContext">The rock context.</param>
        /// <returns></returns>
        private FinancialPersonSavedAccount GetExistingSavedAccount(GiveParameters giveParameters, Person person, RockContext rockContext)
        {
            if (!giveParameters.SourceAccountId.HasValue)
            {
                return(null);
            }

            var savedAccount = new FinancialPersonSavedAccountService(rockContext).Get(giveParameters.SourceAccountId.Value);

            if (savedAccount == null)
            {
                GenerateResponse(HttpStatusCode.BadRequest, "The SourceAccountId passed is invalid");
                return(null);
            }

            if (!savedAccount.PersonAliasId.HasValue)
            {
                GenerateResponse(HttpStatusCode.BadRequest, "The SourceAccount doesn't belong to anyone");
                return(null);
            }

            if (person.Aliases.All(a => a.Id != savedAccount.PersonAliasId.Value))
            {
                GenerateResponse(HttpStatusCode.BadRequest, "The SourceAccount doesn't belong to the passed PersonId");
                return(null);
            }

            return(savedAccount);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Handles the Click event of the btnSavePaymentInfo control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void btnSavePaymentInfo_Click(object sender, EventArgs e)
        {
            var    accountService  = new FinancialPersonSavedAccountService();
            var    configValues    = (Dictionary <string, object>)Session["CachedMergeFields"];
            string accountNickname = txtPaymentNick.Text;
            Person person          = FindPerson();

            var account = accountService.Queryable().Where(a => a.Name == accountNickname &&
                                                           a.PersonId == person.Id).FirstOrDefault();

            if (account == null)
            {
                account = new FinancialPersonSavedAccount();
                accountService.Add(account, person.Id);
            }

            account.Name = accountNickname;
            // #TODO WITH GATEWAY CALL
            account.TransactionCode = "Unknown";

            account.PersonId            = person.Id;
            account.MaskedAccountNumber = configValues["PaymentLastFour"].ToString();

            if (!string.IsNullOrEmpty(txtCreditCard.Text))
            {
                account.PaymentMethod = PaymentMethod.CreditCard;
            }
            else if (!string.IsNullOrEmpty(txtAccountNumber.Text))
            {
                account.PaymentMethod = PaymentMethod.ACH;
            }

            accountService.Save(account, person.Id);
            divPaymentNick.Visible = false;
        }
        /// <summary>
        /// Binds the person saved accounts.
        /// </summary>
        private void BindPersonSavedAccounts()
        {
            var rockContext = new RockContext();

            var scheduledTransaction = this.GetFinancialScheduledTransaction(rockContext);
            var targetPersonId       = scheduledTransaction.AuthorizedPersonAlias.PersonId;

            var personSavedAccountsQuery = new FinancialPersonSavedAccountService(rockContext)
                                           .GetByPersonId(targetPersonId)
                                           .Where(a => !a.IsSystem)
                                           .AsNoTracking();

            DefinedValueCache[] allowedCurrencyTypes =
            {
                DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD.AsGuid()),
                DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_ACH.AsGuid())
            };

            int[] allowedCurrencyTypeIds = allowedCurrencyTypes.Select(a => a.Id).ToArray();

            var financialGateway = this.FinancialGateway;

            if (financialGateway == null)
            {
                return;
            }

            personSavedAccountsQuery = personSavedAccountsQuery.Where(a =>
                                                                      a.FinancialGatewayId == financialGateway.Id &&
                                                                      (a.FinancialPaymentDetail.CurrencyTypeValueId != null) &&
                                                                      allowedCurrencyTypeIds.Contains(a.FinancialPaymentDetail.CurrencyTypeValueId.Value));

            var personSavedAccountList = personSavedAccountsQuery.OrderBy(a => a.Name).AsNoTracking().Select(a => new
            {
                a.Id,
                a.Name,
                a.GatewayPersonIdentifier,
                a.FinancialPaymentDetail.AccountNumberMasked,
            }).ToList();

            ddlPersonSavedAccount.Items.Clear();
            foreach (var personSavedAccount in personSavedAccountList)
            {
                var displayName = string.Format("{0} ({1})", personSavedAccount.Name, personSavedAccount.AccountNumberMasked);
                ddlPersonSavedAccount.Items.Add(new ListItem(displayName, personSavedAccount.Id.ToString()));
            }

            string errorMessage;
            var    financialGateComponent  = this.FinancialGatewayComponent;
            var    gatewayPersonIdentifier = (financialGateComponent as GatewayComponent).GetReferenceNumber(scheduledTransaction, out errorMessage);

            int?selectedSavedAccountId = personSavedAccountList.Where(a => a.GatewayPersonIdentifier == gatewayPersonIdentifier).Select(a => ( int? )a.Id).FirstOrDefault();

            ddlPersonSavedAccount.SetValue(selectedSavedAccountId);
        }
Exemplo n.º 6
0
        public void RockCleanup_Execute_ShouldUpdatePeopleWithFinancialPersonSavedAccountToAccountProtectionProfileHigh()
        {
            var personGuid = Guid.NewGuid();
            var personWithFinancialPersonBankAccount = new Person
            {
                FirstName = "Test",
                LastName  = personGuid.ToString(),
                Email     = $"{personGuid}@test.com",
                Guid      = personGuid
            };

            using (var rockContext = new RockContext())
            {
                var personService = new PersonService(rockContext);
                personService.Add(personWithFinancialPersonBankAccount);
                rockContext.SaveChanges();

                personWithFinancialPersonBankAccount = personService.Get(personWithFinancialPersonBankAccount.Id);

                var financialGateway    = new FinancialGatewayService(rockContext).Get("6432D2D2-32FF-443D-B5B3-FB6C8414C3AD".AsGuid());
                var creditCardTypeValue = DefinedTypeCache.Get(SystemGuid.DefinedType.FINANCIAL_CREDIT_CARD_TYPE.AsGuid()).DefinedValues.OrderBy(a => Guid.NewGuid()).First().Id;
                var currencyTypeValue   = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD.AsGuid()).Id;
                var definedValueService = new DefinedValueService(rockContext);

                var financialPersonSavedAccount = new FinancialPersonSavedAccount
                {
                    Name                   = "Test Saved Account",
                    PersonAliasId          = personWithFinancialPersonBankAccount.PrimaryAliasId.Value,
                    FinancialGateway       = financialGateway,
                    FinancialPaymentDetail = new FinancialPaymentDetail
                    {
                        AccountNumberMasked = "1111",
                        CreditCardTypeValue = definedValueService.Get(creditCardTypeValue),
                        CurrencyTypeValue   = definedValueService.Get(currencyTypeValue),
                        NameOnCard          = "Test User"
                    }
                };

                var service = new FinancialPersonSavedAccountService(rockContext);
                service.Add(financialPersonSavedAccount);
                rockContext.SaveChanges();
            }

            ExecuteRockCleanupJob();

            using (var rockContext = new RockContext())
            {
                var actualPerson = new PersonService(rockContext).Get(personGuid);
                Assert.That.AreEqual(AccountProtectionProfile.High, actualPerson.AccountProtectionProfile);
            }
        }
        /// <summary>
        /// Binds the saved account list.
        /// </summary>
        private void BindSavedAccountList()
        {
            var rockContext = new RockContext();
            var financialPersonSavedAccountService = new FinancialPersonSavedAccountService(rockContext);
            var savedAccountList = financialPersonSavedAccountService
                                   .Queryable()
                                   .Where(a => a.PersonAliasId == this.Person.PrimaryAliasId.Value && a.FinancialPaymentDetail != null)
                                   .ToList();

            rptSavedAccounts.DataSource = savedAccountList;
            rptSavedAccounts.DataBind();

            pnlSavedAccounts.Visible = savedAccountList.Any();
        }
Exemplo n.º 8
0
        /// <summary>
        /// Binds the saved payments if there are any.
        /// </summary>
        protected void BindSavedPayments()
        {
            var savedAccountService = new FinancialPersonSavedAccountService();
            var person = FindPerson();

            var accountsQueryable = savedAccountService.Queryable().Where(a => a.PersonId == person.Id);

            if (accountsQueryable.Count() > 0)
            {
                var ccCurrencyType = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD));
                if (accountsQueryable.Where(a => a.FinancialTransaction.CurrencyTypeValueId == ccCurrencyType.Id).Any())
                {
                    var savedCreditCard = accountsQueryable.Where(a => a.FinancialTransaction.CurrencyTypeValueId == ccCurrencyType.Id)
                                          .ToDictionary(a => "Use " + a.Name + " ending in *************" + a.MaskedAccountNumber, a => a.Id);
                    savedCreditCard.Add("Use a different card", 0);
                    rblSavedCard.DataSource     = savedCreditCard;
                    rblSavedCard.DataValueField = "Value";
                    rblSavedCard.DataTextField  = "Key";
                    rblSavedCard.DataBind();
                    divSavedCard.Visible        = true;
                    divNewCard.Style["display"] = "none";
                }

                var achCurrencyType = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_ACH));
                if (accountsQueryable.Where(a => a.FinancialTransaction.CurrencyTypeValueId == achCurrencyType.Id).Any())
                {
                    var savedACH = accountsQueryable.Where(a => a.FinancialTransaction.CurrencyTypeValueId == achCurrencyType.Id)
                                   .ToDictionary(a => "Use " + a.Name + " account ending in *************" + a.MaskedAccountNumber, a => a.Id);
                    savedACH.Add("Use a different account", 0);
                    rblSavedCheck.DataSource     = savedACH;
                    rblSavedCheck.DataValueField = "Value";
                    rblSavedCheck.DataTextField  = "Key";
                    rblSavedCheck.DataBind();
                    divSavedCheck.Visible        = true;
                    divNewCheck.Style["display"] = "none";
                }
            }
            else
            {
                divSavedCard.Visible      = false;
                divSavedCheck.Visible     = false;
                txtCreditCard.Required    = true;
                mypExpiration.Required    = true;
                txtCVV.Required           = true;
                txtCardName.Required      = true;
                txtBankName.Required      = true;
                txtRoutingNumber.Required = true;
                txtAccountNumber.Required = true;
            }
        }
        /// <summary>
        /// Binds the saved account list.
        /// </summary>
        private void BindSavedAccountList()
        {
            var rockContext = new RockContext();
            var financialPersonSavedAccountService = new FinancialPersonSavedAccountService(rockContext);
            var savedAccountList = financialPersonSavedAccountService
                                   .GetByPersonId(this.Person.Id)
                                   .Where(a => a.FinancialPaymentDetail != null)
                                   .ToList();

            rptSavedAccounts.DataSource = savedAccountList;
            rptSavedAccounts.DataBind();

            pnlSavedAccounts.Visible = savedAccountList.Any();
        }
        /// <summary>
        /// Removes any expired saved accounts (if <see cref="AttributeKey.RemovedExpiredSavedAccountDays"/> is set)
        /// </summary>
        /// <param name="context">The context.</param>
        private FinancialPersonSavedAccountService.RemoveExpiredSavedAccountsResult RemoveExpiredSavedAccounts(IJobExecutionContext context)
        {
            var dataMap = context.JobDetail.JobDataMap;
            int?removedExpiredSavedAccountDays = dataMap.GetString(AttributeKey.RemovedExpiredSavedAccountDays).AsIntegerOrNull();

            if (!removedExpiredSavedAccountDays.HasValue)
            {
                return(new FinancialPersonSavedAccountService.RemoveExpiredSavedAccountsResult());
            }

            var service = new FinancialPersonSavedAccountService(new RockContext());

            return(service.RemoveExpiredSavedAccounts(removedExpiredSavedAccountDays.Value));
        }
Exemplo n.º 11
0
        /// <summary>
        /// Binds the saved payments if there are any.
        /// </summary>
        protected void BindSavedPayments()
        {
            var savedAccountService = new FinancialPersonSavedAccountService();
            var person = FindPerson();

            var accountsQueryable = savedAccountService.Queryable().Where(a => a.PersonId == person.Id);

            if (accountsQueryable.Count() > 0)
            {
                if (accountsQueryable.Where(a => a.PaymentMethod == PaymentMethod.CreditCard).Any())
                {
                    var savedCreditCard = accountsQueryable.Where(a => a.PaymentMethod == PaymentMethod.CreditCard)
                                          .ToDictionary(a => "Use " + a.Name + " ending in *************" + a.MaskedAccountNumber, a => a.Id);
                    savedCreditCard.Add("Use a different card", 0);
                    rblSavedCard.DataSource     = savedCreditCard;
                    rblSavedCard.DataValueField = "Value";
                    rblSavedCard.DataTextField  = "Key";
                    rblSavedCard.DataBind();
                    divSavedCard.Visible        = true;
                    divNewCard.Style["display"] = "none";
                }

                if (accountsQueryable.Where(a => a.PaymentMethod == PaymentMethod.ACH).Any())
                {
                    var savedACH = accountsQueryable.Where(a => a.PaymentMethod == PaymentMethod.ACH)
                                   .ToDictionary(a => "Use " + a.Name + " account ending in *************" + a.MaskedAccountNumber, a => a.Id);
                    savedACH.Add("Use a different account", 0);
                    rblSavedCheck.DataSource     = savedACH;
                    rblSavedCheck.DataValueField = "Value";
                    rblSavedCheck.DataTextField  = "Key";
                    rblSavedCheck.DataBind();
                    divSavedCheck.Visible        = true;
                    divNewCheck.Style["display"] = "none";
                }
            }
            else
            {
                divSavedCard.Visible      = false;
                divSavedCheck.Visible     = false;
                txtCreditCard.Required    = true;
                mypExpiration.Required    = true;
                txtCVV.Required           = true;
                txtCardName.Required      = true;
                txtBankName.Required      = true;
                txtRoutingNumber.Required = true;
                txtAccountNumber.Required = true;
            }
        }
        /// <summary>
        /// Gets the saved accounts.
        /// </summary>
        /// <returns></returns>
        private List <FinancialPersonSavedAccount> GetSavedAccounts()
        {
            var financialGateway = this.FinancialGateway;

            if (financialGateway == null)
            {
                return(new List <FinancialPersonSavedAccount>());
            }

            var rockContext = new RockContext();

            var scheduledTransaction = this.GetFinancialScheduledTransaction(rockContext);
            var targetPersonId       = scheduledTransaction.AuthorizedPersonAlias.PersonId;

            if (targetPersonId != CurrentPersonId)
            {
                if (GetAttributeValue(AttributeKey.ImpersonatorCanSeeSavedAccounts).AsBoolean() == false)
                {
                    return(new List <FinancialPersonSavedAccount>());
                }
            }

            var personSavedAccountsQuery = new FinancialPersonSavedAccountService(rockContext)
                                           .GetByPersonId(targetPersonId)
                                           .Where(a => !a.IsSystem)
                                           .AsNoTracking();

            DefinedValueCache[] allowedCurrencyTypes =
            {
                DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD.AsGuid()),
                DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_ACH.AsGuid())
            };

            int[] allowedCurrencyTypeIds = allowedCurrencyTypes.Select(a => a.Id).ToArray();

            personSavedAccountsQuery = personSavedAccountsQuery.Where(a =>
                                                                      a.FinancialGatewayId == financialGateway.Id &&
                                                                      (a.FinancialPaymentDetail.CurrencyTypeValueId != null) &&
                                                                      allowedCurrencyTypeIds.Contains(a.FinancialPaymentDetail.CurrencyTypeValueId.Value));

            var personSavedAccountList = personSavedAccountsQuery.OrderBy(a => a.Name).Include(a => a.FinancialPaymentDetail).AsNoTracking().ToList();

            return(personSavedAccountList);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Create a new payment processor to handle a single automated payment.
        /// </summary>
        /// <param name="currentPersonAliasId">The current user's person alias ID. Possibly the REST user.</param>
        /// <param name="automatedPaymentArgs">The arguments describing how to charge the payment and store the resulting transaction</param>
        /// <param name="rockContext">The context to use for loading and saving entities</param>
        /// <param name="enableDuplicateChecking">If false, the payment will be charged even if there is a similar transaction for the same person
        /// within a short time period.</param>
        /// <param name="enableScheduleAdherenceProtection">If false and a schedule is indicated in the args, the payment will be charged even if
        /// the schedule has already been processed according to it's frequency.</param>
        public AutomatedPaymentProcessor(int?currentPersonAliasId, AutomatedPaymentArgs automatedPaymentArgs, RockContext rockContext, bool enableDuplicateChecking = true, bool enableScheduleAdherenceProtection = true)
        {
            _rockContext                       = rockContext;
            _automatedPaymentArgs              = automatedPaymentArgs;
            _currentPersonAliasId              = currentPersonAliasId;
            _enableDuplicateChecking           = enableDuplicateChecking;
            _enableScheduleAdherenceProtection = enableScheduleAdherenceProtection;
            _futureTransaction                 = null;

            _personAliasService                   = new PersonAliasService(_rockContext);
            _financialGatewayService              = new FinancialGatewayService(_rockContext);
            _financialAccountService              = new FinancialAccountService(_rockContext);
            _financialPersonSavedAccountService   = new FinancialPersonSavedAccountService(_rockContext);
            _financialBatchService                = new FinancialBatchService(_rockContext);
            _financialTransactionService          = new FinancialTransactionService(_rockContext);
            _financialScheduledTransactionService = new FinancialScheduledTransactionService(_rockContext);

            _payment = null;
        }
Exemplo n.º 14
0
        private List <PersonSavedAccountInfo> GetSavedAccounts()
        {
            var financialGateway = this.FinancialGateway;

            if (financialGateway == null)
            {
                return(new List <PersonSavedAccountInfo>());
            }

            var rockContext = new RockContext();

            var scheduledTransaction = this.GetFinancialScheduledTransaction(rockContext);
            var targetPersonId       = scheduledTransaction.AuthorizedPersonAlias.PersonId;

            var personSavedAccountsQuery = new FinancialPersonSavedAccountService(rockContext)
                                           .GetByPersonId(targetPersonId)
                                           .Where(a => !a.IsSystem)
                                           .AsNoTracking();

            DefinedValueCache[] allowedCurrencyTypes =
            {
                DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD.AsGuid()),
                DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_ACH.AsGuid())
            };

            int[] allowedCurrencyTypeIds = allowedCurrencyTypes.Select(a => a.Id).ToArray();

            personSavedAccountsQuery = personSavedAccountsQuery.Where(a =>
                                                                      a.FinancialGatewayId == financialGateway.Id &&
                                                                      (a.FinancialPaymentDetail.CurrencyTypeValueId != null) &&
                                                                      allowedCurrencyTypeIds.Contains(a.FinancialPaymentDetail.CurrencyTypeValueId.Value));

            List <PersonSavedAccountInfo> personSavedAccountList = personSavedAccountsQuery.OrderBy(a => a.Name).AsNoTracking().Select(a => new PersonSavedAccountInfo
            {
                Id   = a.Id,
                Name = a.Name,
                GatewayPersonIdentifier = a.GatewayPersonIdentifier,
                AccountNumberMasked     = a.FinancialPaymentDetail.AccountNumberMasked,
            }).ToList();

            return(personSavedAccountList);
        }
        /// <summary>
        /// Event when the user clicks to delete the saved accounts
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void rptSavedAccounts_Delete(object sender, CommandEventArgs e)
        {
            var bankAccountGuid = e.CommandArgument.ToStringSafe().AsGuid();
            var rockContext     = new RockContext();
            var financialPersonSavedAccountService = new FinancialPersonSavedAccountService(rockContext);
            var financialPersonSavedAccount        = financialPersonSavedAccountService.Get(bankAccountGuid);

            if (financialPersonSavedAccount != null)
            {
                string errorMessage;
                if (!financialPersonSavedAccountService.CanDelete(financialPersonSavedAccount, out errorMessage))
                {
                    mdWarningAlert.Show(errorMessage, ModalAlertType.Information);
                    return;
                }

                financialPersonSavedAccountService.Delete(financialPersonSavedAccount);
                rockContext.SaveChanges();
            }

            ShowDetail();
        }
Exemplo n.º 16
0
        /// <summary>
        /// Handles the Delete event of the gSavedAccounts control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="RowEventArgs"/> instance containing the event data.</param>
        protected void gSavedAccounts_Delete(object sender, RowEventArgs e)
        {
            var    rockContext  = new RockContext();
            var    service      = new FinancialPersonSavedAccountService(rockContext);
            var    savedAccount = service.Get(e.RowKeyId);
            string errorMessage;

            if (savedAccount == null)
            {
                return;
            }

            if (!service.CanDelete(savedAccount, out errorMessage))
            {
                mdGridWarning.Show(errorMessage, ModalAlertType.Information);
                return;
            }

            service.Delete(savedAccount);
            rockContext.SaveChanges();

            BindGrid();
        }
        /// <summary>
        /// Handles the Click event of the btnSaveAccount control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void SaveNewFinancialPersonSavedAccount(FinancialScheduledTransaction financialScheduledTransaction)
        {
            var rockContext = new RockContext();

            var scheduledTransaction = this.GetFinancialScheduledTransaction(rockContext);
            var targetPerson         = scheduledTransaction.AuthorizedPersonAlias.Person;

            var financialGatewayComponent = this.FinancialGatewayComponent;
            var financialGateway          = this.FinancialGateway;

            var savedAccount = new FinancialPersonSavedAccount();

            var paymentDetail = financialScheduledTransaction.FinancialPaymentDetail;

            savedAccount.PersonAliasId           = targetPerson.PrimaryAliasId;
            savedAccount.ReferenceNumber         = paymentDetail.GatewayPersonIdentifier;
            savedAccount.Name                    = tbSaveAccount.Text;
            savedAccount.TransactionCode         = financialScheduledTransaction.TransactionCode;
            savedAccount.GatewayPersonIdentifier = paymentDetail.GatewayPersonIdentifier;
            savedAccount.FinancialGatewayId      = financialGateway.Id;
            savedAccount.FinancialPaymentDetail  = new FinancialPaymentDetail();
            savedAccount.FinancialPaymentDetail.AccountNumberMasked   = paymentDetail.AccountNumberMasked;
            savedAccount.FinancialPaymentDetail.CurrencyTypeValueId   = paymentDetail.CurrencyTypeValueId;
            savedAccount.FinancialPaymentDetail.CreditCardTypeValueId = paymentDetail.CreditCardTypeValueId;
            savedAccount.FinancialPaymentDetail.NameOnCard            = paymentDetail.NameOnCard;
            savedAccount.FinancialPaymentDetail.ExpirationMonth       = paymentDetail.ExpirationMonth;
            savedAccount.FinancialPaymentDetail.ExpirationYear        = paymentDetail.ExpirationYear;
            savedAccount.FinancialPaymentDetail.BillingLocationId     = paymentDetail.BillingLocationId;

            var savedAccountService = new FinancialPersonSavedAccountService(rockContext);

            savedAccountService.Add(savedAccount);
            rockContext.SaveChanges();

            savedAccount.FinancialPaymentDetail.FinancialPersonSavedAccountId = savedAccount.Id;
        }
Exemplo n.º 18
0
        /// <summary>
        /// Create a new payment processor to handle a single automated payment from a future transaction (probably generated from text-to-give).
        /// </summary>
        /// <param name="futureTransaction">The transaction with a FutureProcessingDateTime</param>
        /// <param name="rockContext">The context to use for loading and saving entities</param>
        public AutomatedPaymentProcessor(FinancialTransaction futureTransaction, RockContext rockContext)
        {
            _rockContext          = rockContext;
            _automatedPaymentArgs = null;
            _currentPersonAliasId = futureTransaction.CreatedByPersonAliasId;
            _futureTransaction    = futureTransaction;

            // The job charging these future transactions could have a variable run frequency and be charging a days worth at a time, so the duplicate
            // checking could very easily provide false positives. Therefore, we rely on the "dry-run" to have previously validated
            _enableDuplicateChecking           = false; // These future transactions should have already had a "dry-run" and been validated.
            _enableScheduleAdherenceProtection = false; // These future transactions should have already had a "dry-run" and been validated

            _personAliasService                   = new PersonAliasService(_rockContext);
            _financialGatewayService              = new FinancialGatewayService(_rockContext);
            _financialAccountService              = new FinancialAccountService(_rockContext);
            _financialPersonSavedAccountService   = new FinancialPersonSavedAccountService(_rockContext);
            _financialBatchService                = new FinancialBatchService(rockContext);
            _financialTransactionService          = new FinancialTransactionService(_rockContext);
            _financialScheduledTransactionService = new FinancialScheduledTransactionService(_rockContext);

            _payment = null;

            CopyFutureTransactionToArgs();
        }
        /// <summary>
        /// Updates the scheduled payment.
        /// </summary>
        /// <param name="usePaymentToken">if set to <c>true</c> [use payment token].</param>
        /// <param name="paymentToken">The payment token.</param>
        protected void UpdateScheduledPayment(bool usePaymentToken, string paymentToken = null)
        {
            var giftTerm = this.GetAttributeValue(AttributeKey.GiftTerm);

            if (dtpStartDate.SelectedDate <= RockDateTime.Today)
            {
                nbUpdateScheduledPaymentWarning.Visible = true;
                nbUpdateScheduledPaymentWarning.Text    = string.Format("When scheduling a {0}, make sure the starting date is in the future (after today)", giftTerm.ToLower());
                return;
            }

            var rockContext = new RockContext();

            var financialScheduledTransactionService = new FinancialScheduledTransactionService(rockContext);
            int scheduledTransactionId        = hfScheduledTransactionId.Value.AsInteger();
            var financialScheduledTransaction = financialScheduledTransactionService.Get(scheduledTransactionId);

            financialScheduledTransaction.StartDate = dtpStartDate.SelectedDate.Value;
            financialScheduledTransaction.TransactionFrequencyValueId = ddlFrequency.SelectedValue.AsInteger();

            ReferencePaymentInfo referencePaymentInfo;

            var person = financialScheduledTransaction.AuthorizedPersonAlias.Person;

            string errorMessage;

            var financialGateway          = this.FinancialGateway;
            var financialGatewayComponent = this.FinancialGatewayComponent;

            if (usePaymentToken)
            {
                referencePaymentInfo           = new ReferencePaymentInfo();
                referencePaymentInfo.FirstName = person.FirstName;
                referencePaymentInfo.LastName  = person.LastName;

                referencePaymentInfo.UpdateAddressFieldsFromAddressControl(acBillingAddress);

                referencePaymentInfo.ReferenceNumber = paymentToken;

                var customerToken = financialGatewayComponent.CreateCustomerAccount(this.FinancialGateway, referencePaymentInfo, out errorMessage);

                if (errorMessage.IsNotNullOrWhiteSpace() || customerToken.IsNullOrWhiteSpace())
                {
                    nbMessage.NotificationBoxType = NotificationBoxType.Danger;
                    nbMessage.Text    = errorMessage ?? "Unknown Error";
                    nbMessage.Visible = true;
                    return;
                }

                referencePaymentInfo.GatewayPersonIdentifier = customerToken;
            }
            else
            {
                var savedAccountId = ddlPersonSavedAccount.SelectedValue.AsInteger();

                var savedAccount = new FinancialPersonSavedAccountService(rockContext).Get(savedAccountId);
                if (savedAccount != null)
                {
                    referencePaymentInfo = savedAccount.GetReferencePayment();
                }
                else
                {
                    throw new Exception("Unable to determine Saved Account");
                }
            }

            var selectedAccountAmounts = caapPromptForAccountAmounts.AccountAmounts.Where(a => a.Amount.HasValue && a.Amount.Value != 0).Select(a => new { a.AccountId, Amount = a.Amount.Value }).ToArray();

            referencePaymentInfo.Amount = selectedAccountAmounts.Sum(a => a.Amount);

            var successfullyUpdated = financialGatewayComponent.UpdateScheduledPayment(financialScheduledTransaction, referencePaymentInfo, out errorMessage);

            if (!successfullyUpdated)
            {
                nbMessage.NotificationBoxType = NotificationBoxType.Danger;
                nbMessage.Text    = errorMessage ?? "Unknown Error";
                nbMessage.Visible = true;
                return;
            }

            financialScheduledTransaction.FinancialPaymentDetail.SetFromPaymentInfo(referencePaymentInfo, financialGatewayComponent as GatewayComponent, rockContext);

            var selectedAccountIds        = selectedAccountAmounts.Select(a => a.AccountId).ToArray();
            var deletedTransactionDetails = financialScheduledTransaction.ScheduledTransactionDetails.ToList().Where(a => selectedAccountIds.Contains(a.AccountId)).ToList();

            foreach (var deletedTransactionDetail in deletedTransactionDetails)
            {
                financialScheduledTransaction.ScheduledTransactionDetails.Remove(deletedTransactionDetail);
            }

            foreach (var selectedAccountAmount in selectedAccountAmounts)
            {
                var scheduledTransactionDetail = financialScheduledTransaction.ScheduledTransactionDetails.FirstOrDefault(a => a.AccountId == selectedAccountAmount.AccountId);
                if (scheduledTransactionDetail == null)
                {
                    scheduledTransactionDetail           = new FinancialScheduledTransactionDetail();
                    scheduledTransactionDetail.AccountId = selectedAccountAmount.AccountId;
                    financialScheduledTransaction.ScheduledTransactionDetails.Add(scheduledTransactionDetail);
                }

                scheduledTransactionDetail.Amount = selectedAccountAmount.Amount;
            }

            rockContext.SaveChanges();

            var mergeFields = LavaHelper.GetCommonMergeFields(this.RockPage, this.CurrentPerson, new CommonMergeFieldsOptions {
                GetLegacyGlobalMergeFields = false
            });
            var finishLavaTemplate = this.GetAttributeValue(AttributeKey.FinishLavaTemplate);

            mergeFields.Add("Transaction", financialScheduledTransaction);
            mergeFields.Add("Person", financialScheduledTransaction.AuthorizedPersonAlias.Person);
            mergeFields.Add("PaymentDetail", financialScheduledTransaction.FinancialPaymentDetail);
            mergeFields.Add("BillingLocation", financialScheduledTransaction.FinancialPaymentDetail.BillingLocation);

            pnlPromptForChanges.Visible   = false;
            pnlTransactionSummary.Visible = true;

            lTransactionSummaryHTML.Text = finishLavaTemplate.ResolveMergeFields(mergeFields);
        }
Exemplo n.º 20
0
        /// <summary>
        /// Charges the specified payment info.
        /// </summary>
        /// <param name="financialGateway"></param>
        /// <param name="paymentInfo">The payment info.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialTransaction Charge(FinancialGateway financialGateway, PaymentInfo paymentInfo, out string errorMessage)
        {
            errorMessage = string.Empty;
            Response ppResponse = null;

            var invoice = GetInvoice(paymentInfo);

            // add in spark reference code
            BrowserInfo browser = new BrowserInfo();

            browser.ButtonSource = "SparkDevelopmentNetwork_SP";
            invoice.BrowserInfo  = browser;

            var tender = GetTender(paymentInfo);

            if (tender != null)
            {
                if (paymentInfo is ReferencePaymentInfo)
                {
                    var reference     = paymentInfo as ReferencePaymentInfo;
                    var ppTransaction = new ReferenceTransaction("Sale", reference.TransactionCode, GetUserInfo(financialGateway), GetConnection(financialGateway), invoice, tender, PayflowUtility.RequestId);
                    ppResponse = ppTransaction.SubmitTransaction();
                }
                else
                {
                    var ppTransaction = new SaleTransaction(GetUserInfo(financialGateway), GetConnection(financialGateway), invoice, tender, PayflowUtility.RequestId);
                    ppResponse = ppTransaction.SubmitTransaction();
                }
            }
            else
            {
                errorMessage = "Could not create tender from PaymentInfo";
            }

            if (ppResponse != null)
            {
                TransactionResponse txnResponse = ppResponse.TransactionResponse;
                if (txnResponse != null)
                {
                    if (txnResponse.Result == 0)   // Success
                    {
                        var transaction = new FinancialTransaction();
                        transaction.TransactionCode = txnResponse.Pnref;

                        // Get the stored payment method that was used so we can update it
                        //  with the latest transaction code.  We do this because Paypal
                        //  will only let us use the same transaction code in reference
                        //  transactions for up to 12 months.
                        if (paymentInfo is ReferencePaymentInfo)
                        {
                            var reference    = paymentInfo as ReferencePaymentInfo;
                            var rockContext  = new RockContext();
                            var savedAccount = new FinancialPersonSavedAccountService(rockContext)
                                               .Queryable()
                                               .Where(s =>
                                                      s.TransactionCode == reference.TransactionCode &&
                                                      s.FinancialGatewayId.HasValue &&
                                                      s.FinancialGatewayId.Value == financialGateway.Id)
                                               .FirstOrDefault();
                            if (savedAccount != null)
                            {
                                savedAccount.TransactionCode = txnResponse.Pnref;
                                rockContext.SaveChanges();
                            }
                        }

                        return(transaction);
                    }
                    else
                    {
                        errorMessage = string.Format("[{0}] {1}", txnResponse.Result, txnResponse.RespMsg);
                    }
                }
                else
                {
                    errorMessage = "Invalid transaction response from the financial gateway";
                }
            }
            else
            {
                errorMessage = "Invalid response from the financial gateway.";
            }

            return(null);
        }
Exemplo n.º 21
0
        /// <summary>
        /// Removes any expired saved accounts (if <see cref="AttributeKey.RemovedExpiredSavedAccountDays"/> is set)
        /// </summary>
        /// <param name="context">The context.</param>
        private RemoveExpiredSavedAccountsResult RemoveExpiredSavedAccounts(IJobExecutionContext context)
        {
            var dataMap = context.JobDetail.JobDataMap;
            int?removedExpiredSavedAccountDays = dataMap.GetString(AttributeKey.RemovedExpiredSavedAccountDays).AsIntegerOrNull();

            if (!removedExpiredSavedAccountDays.HasValue)
            {
                return(new RemoveExpiredSavedAccountsResult());
            }

            var financialPersonSavedAccountQry = new FinancialPersonSavedAccountService(new RockContext()).Queryable()
                                                 .Where(a => a.FinancialPaymentDetail.ExpirationMonthEncrypted != null)
                                                 .Where(a => a.PersonAliasId.HasValue || a.GroupId.HasValue)
                                                 .Where(a => a.FinancialPaymentDetailId.HasValue)
                                                 .Where(a => a.IsSystem == false)
                                                 .OrderBy(a => a.Id);

            var savedAccountInfoList = financialPersonSavedAccountQry.Select(a => new SavedAccountInfo
            {
                Id = a.Id,
                FinancialPaymentDetail = a.FinancialPaymentDetail
            }).ToList();

            DateTime now          = DateTime.Now;
            int      currentMonth = now.Month;
            int      currentYear  = now.Year;

            var result = new RemoveExpiredSavedAccountsResult()
            {
                // if today is 3/16/2020 and removedExpiredSavedAccountDays is 90, only delete card if it expired before 12/17/2019
                DeleteIfExpiredBeforeDate = RockDateTime.Today.AddDays(-removedExpiredSavedAccountDays.Value)
            };

            foreach (var savedAccountInfo in savedAccountInfoList)
            {
                int?expirationMonth = savedAccountInfo.FinancialPaymentDetail.ExpirationMonth;
                int?expirationYear  = savedAccountInfo.FinancialPaymentDetail.ExpirationYear;
                if (!expirationMonth.HasValue || !expirationMonth.HasValue)
                {
                    continue;
                }

                if (expirationMonth.Value < 1 || expirationMonth.Value > 12 || expirationYear <= DateTime.MinValue.Year || expirationYear >= DateTime.MaxValue.Year)
                {
                    // invalid month (or year)
                    continue;
                }

                // a credit card with an expiration of April 2020 would be expired on May 1st, 2020
                var cardExpirationDate = new DateTime(expirationYear.Value, expirationMonth.Value, 1).AddMonths(1);

                /* Example:
                 * Today's Date: 2020-3-16
                 * removedExpiredSavedAccountDays: 90
                 * Expired Before Date: 2019-12-17 (Today (2020-3-16) - removedExpiredSavedAccountDays)
                 * Cards that expired before 2019-12-17 should be deleted
                 * Delete 04/20 (Expires 05/01/2020) card? No
                 * Delete 05/20 (Expires 06/01/2020) card? No
                 * Delete 01/20 (Expires 03/01/2020) card? No
                 * Delete 12/19 (Expires 01/01/2020) card? No
                 * Delete 11/19 (Expires 12/01/2019) card? Yes
                 * Delete 10/19 (Expires 11/01/2019) card? Yes
                 *
                 * Today's Date: 2020-3-16
                 * removedExpiredSavedAccountDays: 0
                 * Expired Before Date: 2019-03-16 (Today (2020-3-16) - 0)
                 * Cards that expired before 2019-03-16 should be deleted
                 * Delete 04/20 (Expires 05/01/2020) card? No
                 * Delete 05/20 (Expires 06/01/2020) card? No
                 * Delete 01/20 (Expires 03/01/2020) card? Yes
                 * Delete 12/19 (Expires 01/01/2020) card? Yes
                 * Delete 11/19 (Expires 12/01/2019) card? Yes
                 * Delete 10/19 (Expires 11/01/2019) card? Yes
                 */

                if (cardExpirationDate >= result.DeleteIfExpiredBeforeDate)
                {
                    // We want to only delete cards that expired more than X days ago, so if this card expiration day is after that, skip
                    continue;
                }

                // Card expiration date is older than X day ago, so delete it.
                // Wrapping the following in a try/catch so a single deletion failure doesn't end the process for all deletion candidates.
                try
                {
                    using (var savedAccountRockContext = new RockContext())
                    {
                        var financialPersonSavedAccountService = new FinancialPersonSavedAccountService(savedAccountRockContext);
                        var financialPersonSavedAccount        = financialPersonSavedAccountService.Get(savedAccountInfo.Id);
                        if (financialPersonSavedAccount != null)
                        {
                            if (financialPersonSavedAccountService.CanDelete(financialPersonSavedAccount, out _))
                            {
                                financialPersonSavedAccountService.Delete(financialPersonSavedAccount);
                                savedAccountRockContext.SaveChanges();
                                result.AccountsDeletedCount++;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    // Provide better identifying context in case the caught exception is too vague.
                    var exception = new Exception($"Unable to delete FinancialPersonSavedAccount (ID = {savedAccountInfo.Id}).", ex);

                    result.AccountRemovalExceptions.Add(exception);
                }
            }

            return(result);
        }
Exemplo n.º 22
0
        public SaveFinancialAccountFormResult SaveFinancialAccount(Guid gatewayGuid, [FromBody] SaveFinancialAccountFormArgs args)
        {
            // Validate the args
            if (args?.TransactionCode.IsNullOrWhiteSpace() != false)
            {
                return(new SaveFinancialAccountFormResult
                {
                    Title = "Sorry",
                    Detail = "The account information cannot be saved as there's not a valid transaction code to reference",
                    IsSuccess = false
                });
            }

            if (args.SavedAccountName.IsNullOrWhiteSpace())
            {
                return(new SaveFinancialAccountFormResult
                {
                    Title = "Missing Account Name",
                    Detail = "Please enter a name to use for this account",
                    IsSuccess = false
                });
            }

            var currentPerson = GetPerson();
            var isAnonymous   = currentPerson == null;

            using (var rockContext = new RockContext())
            {
                if (isAnonymous)
                {
                    if (args.Username.IsNullOrWhiteSpace() || args.Password.IsNullOrWhiteSpace())
                    {
                        return(new SaveFinancialAccountFormResult
                        {
                            Title = "Missing Information",
                            Detail = "A username and password are required when saving an account",
                            IsSuccess = false
                        });
                    }

                    var userLoginService = new UserLoginService(rockContext);

                    if (userLoginService.GetByUserName(args.Username) != null)
                    {
                        return(new SaveFinancialAccountFormResult
                        {
                            Title = "Invalid Username",
                            Detail = "The selected Username is already being used. Please select a different Username",
                            IsSuccess = false
                        });
                    }

                    if (!UserLoginService.IsPasswordValid(args.Password))
                    {
                        return(new SaveFinancialAccountFormResult
                        {
                            Title = "Invalid Password",
                            Detail = UserLoginService.FriendlyPasswordRules(),
                            IsSuccess = false
                        });
                    }
                }

                // Load the gateway from the database
                var financialGatewayService = new FinancialGatewayService(rockContext);
                var financialGateway        = financialGatewayService.Get(gatewayGuid);
                var gateway = financialGateway?.GetGatewayComponent();

                if (gateway is null)
                {
                    return(new SaveFinancialAccountFormResult
                    {
                        Title = "Invalid Gateway",
                        Detail = "Sorry, the financial gateway information is not valid.",
                        IsSuccess = false
                    });
                }

                // Load the transaction from the database
                var financialTransactionService = new FinancialTransactionService(rockContext);
                var transaction            = financialTransactionService.GetByTransactionCode(financialGateway.Id, args.TransactionCode);
                var transactionPersonAlias = transaction?.AuthorizedPersonAlias;
                var transactionPerson      = transactionPersonAlias?.Person;
                var paymentDetail          = transaction?.FinancialPaymentDetail;

                if (transactionPerson is null || paymentDetail is null)
                {
                    return(new SaveFinancialAccountFormResult
                    {
                        Title = "Invalid Transaction",
                        Detail = "Sorry, the account information cannot be saved as there's not a valid transaction to reference",
                        IsSuccess = false
                    });
                }

                // Create the login if needed
                if (isAnonymous)
                {
                    var user = UserLoginService.Create(
                        rockContext,
                        transactionPerson,
                        AuthenticationServiceType.Internal,
                        EntityTypeCache.Get(SystemGuid.EntityType.AUTHENTICATION_DATABASE.AsGuid()).Id,
                        args.Username,
                        args.Password,
                        false);

                    var mergeFields = Lava.LavaHelper.GetCommonMergeFields(null, currentPerson);
                    // TODO mergeFields.Add( "ConfirmAccountUrl", RootPath + "ConfirmAccount" );
                    mergeFields.Add("Person", transactionPerson);
                    mergeFields.Add("User", user);

                    var emailMessage = new RockEmailMessage(SystemGuid.SystemCommunication.SECURITY_CONFIRM_ACCOUNT.AsGuid());
                    emailMessage.AddRecipient(new RockEmailMessageRecipient(transactionPerson, mergeFields));
                    // TODO emailMessage.AppRoot = ResolveRockUrl( "~/" );
                    // TODO emailMessage.ThemeRoot = ResolveRockUrl( "~~/" );
                    emailMessage.CreateCommunicationRecord = false;
                    emailMessage.Send();
                }

                var savedAccount = new FinancialPersonSavedAccount
                {
                    PersonAliasId           = transactionPersonAlias.Id,
                    ReferenceNumber         = args.TransactionCode,
                    GatewayPersonIdentifier = args.GatewayPersonIdentifier,
                    Name                   = args.SavedAccountName,
                    TransactionCode        = args.TransactionCode,
                    FinancialGatewayId     = financialGateway.Id,
                    FinancialPaymentDetail = new FinancialPaymentDetail
                    {
                        AccountNumberMasked   = paymentDetail.AccountNumberMasked,
                        CurrencyTypeValueId   = paymentDetail.CurrencyTypeValueId,
                        CreditCardTypeValueId = paymentDetail.CreditCardTypeValueId,
                        NameOnCard            = paymentDetail.NameOnCard,
                        ExpirationMonth       = paymentDetail.ExpirationMonth,
                        ExpirationYear        = paymentDetail.ExpirationYear,
                        BillingLocationId     = paymentDetail.BillingLocationId
                    }
                };

                var financialPersonSavedAccountService = new FinancialPersonSavedAccountService(rockContext);
                financialPersonSavedAccountService.Add(savedAccount);
                rockContext.SaveChanges();

                return(new SaveFinancialAccountFormResult
                {
                    Title = "Success",
                    Detail = "The account has been saved for future use",
                    IsSuccess = true
                });
            }
        }
Exemplo n.º 23
0
        /// <summary>
        /// Executes the specified workflow.
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="action">The action.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public override bool Execute(RockContext rockContext, WorkflowAction action, Object entity, out List <string> errorMessages)
        {
            errorMessages = new List <string>();
            var continueOnError = GetAttributeValue(action, "ContinueOnError").AsBoolean();

            // Get the gateway
            var gateway = GetEntityFromAttributeValue <FinancialGateway>(action, "FinancialGateway", true, rockContext);

            if (gateway == null)
            {
                errorMessages.Add("The gateway is not valid");
            }

            // Get the person
            var person = GetPersonFromAttributeValue(action, "Person", true, rockContext);

            if (person == null || !person.PrimaryAliasId.HasValue)
            {
                errorMessages.Add("A valid person was not provided.");
            }

            // If there are any errors accumulated, exit
            if (errorMessages.Any())
            {
                return(HandleExit(action, errorMessages, continueOnError));
            }

            // Find the saved account
            var savedAccountQry = new FinancialPersonSavedAccountService(rockContext)
                                  .GetByPersonId(person.Id)
                                  .AsNoTracking()
                                  .Where(sa => sa.FinancialGatewayId == gateway.Id);
            var savedAccount = savedAccountQry.FirstOrDefault(sa => sa.IsDefault) ?? savedAccountQry.FirstOrDefault();

            // Log the result and set the result attribute
            if (savedAccount == null)
            {
                action.AddLogEntry(string.Format(
                                       "{0} does not have a saved account for {1}",
                                       person.FullName,
                                       gateway.Name));

                var attribute = SetWorkflowAttributeValue(action, "ResultAttribute", ( int? )null);
                if (attribute != null)
                {
                    action.AddLogEntry(string.Format("Set '{0}' attribute to null.", attribute.Name));
                }
            }
            else
            {
                action.AddLogEntry(string.Format(
                                       "{0} has a saved account with ID {1} for {2}",
                                       person.FullName,
                                       savedAccount.Id,
                                       gateway.Name));

                var attribute = SetWorkflowAttributeValue(action, "ResultAttribute", savedAccount.Id);
                if (attribute != null)
                {
                    action.AddLogEntry(string.Format("Set '{0}' attribute to '{1}'.", attribute.Name, savedAccount.Id));
                }
            }

            return(HandleExit(action, errorMessages, continueOnError));
        }
        /// <summary>
        /// Handles the Click event of the btnMigrateSavedAccounts control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void btnMigrateSavedAccounts_Click(object sender, EventArgs e)
        {
            BinaryFile binaryFile        = null;
            var        rockContext       = new RockContext();
            var        binaryFileService = new BinaryFileService(rockContext);
            var        binaryFileId      = fuCustomerVaultImportFile.BinaryFileId;

            if (binaryFileId.HasValue)
            {
                binaryFile = binaryFileService.Get(binaryFileId.Value);
            }

            Dictionary <string, string> nmiToPiCustomerIdLookup = null;

            var importData = binaryFile.ContentsToString();

            StringReader stringReader = new StringReader(importData);
            CsvReader    csvReader    = new CsvReader(stringReader);

            csvReader.Configuration.HasHeaderRecord = false;

            nmiToPiCustomerIdLookup = csvReader.GetRecords <CustomerVaultImportRecord>().ToDictionary(k => k.NMICustomerId, v => v.PiCustomerId);

            var financialGatewayService = new FinancialGatewayService(rockContext);
            var nmiFinancialGatewayID   = ddlNMIGateway.SelectedValue.AsInteger();
            var nmiFinancialGateway     = financialGatewayService.Get(nmiFinancialGatewayID);
            var nmiGatewayComponent     = nmiFinancialGateway.GetGatewayComponent();
            var piFinancialGatewayId    = ddlPiGateway.SelectedValue.AsInteger();
            var piFinancialGateway      = financialGatewayService.Get(piFinancialGatewayId);
            var piGatewayComponent      = piFinancialGateway.GetGatewayComponent() as IHostedGatewayComponent;

            var financialPersonSavedAccountService = new FinancialPersonSavedAccountService(rockContext);
            var nmiPersonSavedAccountList          = financialPersonSavedAccountService.Queryable().Where(a => a.FinancialGatewayId == nmiFinancialGatewayID).ToList();

            var personSavedAccountResultsBuilder = new StringBuilder();

            var nmiPersonSavedAccountListCount = nmiPersonSavedAccountList.Count();

            foreach (var nmiPersonSavedAccount in nmiPersonSavedAccountList)
            {
                var nmiCustomerId = nmiPersonSavedAccount.GatewayPersonIdentifier ?? nmiPersonSavedAccount.ReferenceNumber;
                var piCustomerId  = nmiToPiCustomerIdLookup.GetValueOrNull(nmiCustomerId);

                nmiPersonSavedAccount.GatewayPersonIdentifier = piCustomerId;
                nmiPersonSavedAccount.FinancialGatewayId      = piFinancialGatewayId;

                // NOTE: NMI Customer IDs created after the Vault import file was created won't have a piCustomerId

                personSavedAccountResultsBuilder.AppendFormat(
                    "FinancialPersonSavedAccount.Id: {0} NMI CustomerId: '{1}', NMI GatewayPersonIdentifier: '{2}', NMI ReferenceNumber: '{3}', Pi CustomerId: '{4}'" + Environment.NewLine,
                    nmiPersonSavedAccount.Id,
                    nmiCustomerId,
                    nmiPersonSavedAccount.GatewayPersonIdentifier,
                    nmiPersonSavedAccount.ReferenceNumber,
                    piCustomerId
                    );
            }

            rockContext.SaveChanges();

            string resultSummary = string.Format("Migrated {0} Saved Accounts", nmiPersonSavedAccountList.Count());

            personSavedAccountResultsBuilder.AppendLine(resultSummary);

            if (!nmiPersonSavedAccountList.Any())
            {
                nbMigrateSavedAccounts.NotificationBoxType = Rock.Web.UI.Controls.NotificationBoxType.Warning;
                nbMigrateSavedAccounts.Text = "No NMI Saved Accounts Found";
            }
            else
            {
                nbMigrateSavedAccounts.Title = "Success";
                nbMigrateSavedAccounts.NotificationBoxType = Rock.Web.UI.Controls.NotificationBoxType.Success;
                nbMigrateSavedAccounts.Text = resultSummary;
            }

            nbMigrateSavedAccounts.Visible = true;
            nbMigrateSavedAccounts.Details = personSavedAccountResultsBuilder.ToString();
            this.SetBlockUserPreference("MigrateSavedAccountsResultSummary", nbMigrateSavedAccounts.Text);
            this.SetBlockUserPreference("MigrateSavedAccountsResultDetails", personSavedAccountResultsBuilder.ToString());
        }
Exemplo n.º 25
0
        /// <summary>
        /// Enables processing of HTTP Web requests by a custom <see langword="HttpHandler" /> that implements the <see cref="T:System.Web.IHttpHandler" /> interface.
        /// </summary>
        /// <param name="context">An <see cref="T:System.Web.HttpContext" /> object that provides references to the intrinsic server objects (for example, <see langword="Request" />, <see langword="Response" />, <see langword="Session" />, and <see langword="Server" />) used to service HTTP requests.</param>
        public void ProcessRequest(HttpContext context)
        {
            // see https://sandbox.gotnpgateway.com/docs/webhooks/#core-webhook-response-format for example payload
            HttpRequest request  = context.Request;
            var         response = context.Response;

            response.ContentType = "text/plain";

            // Signature https://sandbox.gotnpgateway.com/docs/webhooks/#security
            // see signature @ https://sandbox.fluidpay.com/merchant/settings/webhooks/search
            var postedSignature = request.Headers["Signature"];

            string postedData = string.Empty;

            using (var reader = new StreamReader(request.InputStream))
            {
                postedData = reader.ReadToEnd();
            }

            var cardSyncWebhookResponse = postedData.FromJsonOrNull <CardSyncWebhookResponse>();

            if (cardSyncWebhookResponse == null)
            {
                response.StatusCode        = ( int )HttpStatusCode.BadRequest;
                response.StatusDescription = "Unable to determine response format.";
                return;
            }

            var paymentMethodData = cardSyncWebhookResponse.PaymentMethodData;

            if (paymentMethodData == null)
            {
                response.StatusCode        = ( int )HttpStatusCode.BadRequest;
                response.StatusDescription = "Unable to determine payment method 'data'.";
                return;
            }

            var rockContext = new RockContext();
            FinancialPersonSavedAccountService financialPersonSavedAccountService = new FinancialPersonSavedAccountService(rockContext);
            var financialPersonSavedAccountQuery = financialPersonSavedAccountService.Queryable()
                                                   .Where(a => a.GatewayPersonIdentifier == paymentMethodData.RecordId || a.FinancialPaymentDetail.GatewayPersonIdentifier == paymentMethodData.RecordId);

            var savedAccounts = financialPersonSavedAccountQuery.Include(a => a.FinancialPaymentDetail).Include(a => a.FinancialGateway).ToList();

            // There probably is only one saved account for the GatewayPersonIdentifier, but just in case, we'll loop thru.
            foreach (var savedAccount in savedAccounts)
            {
                var financialGateway = savedAccount.FinancialGateway;
                var myWellGateway    = savedAccount.FinancialGateway?.GetGatewayComponent() as MyWellGateway;
                if (myWellGateway == null)
                {
                    ExceptionLogService.LogException(new MyWellGatewayException($"Unable to determine Gateway for CardSync GatewayPersonIdentifier: {paymentMethodData.RecordId} and FinancialGatewayId: {savedAccount.FinancialGatewayId}"));

                    response.StatusCode        = ( int )HttpStatusCode.BadRequest;
                    response.StatusDescription = $"Unable to find matching financial gateway record for recordId: {paymentMethodData.RecordId}";
                    return;
                }

                financialGateway.LoadAttributes();
                var validSignature = myWellGateway.VerifySignature(financialGateway, postedSignature, postedData);
                if (!validSignature)
                {
                    ExceptionLogService.LogException(new MyWellGatewayException($"Invalid WebHook signature included in header. (PostedData for RecordId: {paymentMethodData.RecordId} and FinancialGatewayId: {savedAccount.FinancialGatewayId})"));
                    response.StatusCode        = ( int )HttpStatusCode.Forbidden;
                    response.StatusDescription = "Invalid WebHook signature included in header";
                    return;
                }

                var financialPaymentDetail = savedAccount.FinancialPaymentDetail;
                if (financialPaymentDetail == null)
                {
                    // shouldn't happen
                    continue;
                }

                if (paymentMethodData.ExpirationDate.IsNotNullOrWhiteSpace() && paymentMethodData.ExpirationDate.Length == 5)
                {
                    // now that we validated this is a 5 char string (MM/YY), extract MM and YY as integers
                    financialPaymentDetail.ExpirationMonth = paymentMethodData.ExpirationDate.Substring(0, 2).AsIntegerOrNull();
                    financialPaymentDetail.ExpirationYear  = paymentMethodData.ExpirationDate.Substring(3, 2).AsIntegerOrNull();

                    // ToDo: See if they send us the CreditCardType (visa, mastercard)
                    // ?? financialPaymentDetail.CreditCardTypeValueId
                }

                financialPaymentDetail.AccountNumberMasked = paymentMethodData.MaskedNumber;
                rockContext.SaveChanges();
            }

            // NOTE: If it takes us more than 5 seconds to respond, they'll retry.
            // Otherwise, if we respond with a 200, they'll assume we processed it.
            // See https://sandbox.gotnpgateway.com/docs/webhooks/#acknowledge-and-retry for additional details
            response.StatusCode = ( int )HttpStatusCode.OK;
        }
Exemplo n.º 26
0
        public HttpResponseMessage ConfigureTextToGive(int personId, [FromBody] ConfigureTextToGiveArgs args)
        {
            // Validate the person
            var person = Service.Get(personId);

            if (person == null)
            {
                return(ControllerContext.Request.CreateResponse(HttpStatusCode.NotFound, "The person ID is not valid"));
            }

            // Load the person's saved accounts
            var rockContext          = Service.Context as RockContext;
            var savedAccountService  = new FinancialPersonSavedAccountService(rockContext);
            var personsSavedAccounts = savedAccountService.Queryable()
                                       .Include(sa => sa.PersonAlias)
                                       .Where(sa => sa.PersonAlias.PersonId == personId)
                                       .ToList();

            // Loop through each saved account. Set default to false unless the args dictate that it is the default
            var foundDefaultAccount = false;

            foreach (var savedAccount in personsSavedAccounts)
            {
                if (!foundDefaultAccount && savedAccount.Id == args.FinancialPersonSavedAccountId)
                {
                    savedAccount.IsDefault = true;
                    foundDefaultAccount    = true;
                }
                else
                {
                    savedAccount.IsDefault = false;
                }
            }

            // If the args specified an account to be default but it was not found, then return an error
            if (args.FinancialPersonSavedAccountId.HasValue && !foundDefaultAccount)
            {
                return(ControllerContext.Request.CreateResponse(HttpStatusCode.NotFound, "The saved account ID is not valid"));
            }

            // Validate the account if it is being set
            if (args.ContributionFinancialAccountId.HasValue)
            {
                var accountService = new FinancialAccountService(rockContext);
                var account        = accountService.Get(args.ContributionFinancialAccountId.Value);

                if (account == null)
                {
                    return(ControllerContext.Request.CreateResponse(HttpStatusCode.NotFound, "The financial account ID is not valid"));
                }

                if (!account.IsActive)
                {
                    return(ControllerContext.Request.CreateResponse(HttpStatusCode.BadRequest, "The financial account is not active"));
                }

                if (account.IsPublic.HasValue && !account.IsPublic.Value)
                {
                    return(ControllerContext.Request.CreateResponse(HttpStatusCode.BadRequest, "The financial account is not public"));
                }
            }

            // Set the person's contribution account ID
            person.ContributionFinancialAccountId = args.ContributionFinancialAccountId;

            // Success
            rockContext.SaveChanges();
            return(ControllerContext.Request.CreateResponse(HttpStatusCode.OK));
        }
        /// <summary>
        /// Gets the saved financial accounts associated with the specified
        /// person and returns the view models that represent those accounts.
        /// </summary>
        /// <param name="personId">The person identifier whose accounts should be retrieved.</param>
        /// <param name="options">The options for filtering and limiting the results.</param>
        /// <returns>A list of <see cref="SavedFinancialAccountListItemViewModel"/> objects that represent the accounts.</returns>
        public List <SavedFinancialAccountListItemViewModel> GetSavedFinancialAccountsForPersonAsAccountListItems(int personId, SavedFinancialAccountOptions options = null)
        {
            var financialPersonSavedAccountService = new FinancialPersonSavedAccountService(RockContext);

            options = options ?? DefaultSavedFinancialAccountOptions;

            var queryOptions = options.ToQueryOptions();

            // Limit the query to just the one person we are interested in.
            queryOptions.PersonIds = new List <int> {
                personId
            };

            // Build the query to get all the matching saved accounts for
            // the specified person.
            var savedAccountsQuery = financialPersonSavedAccountService
                                     .GetFinancialPersonSavedAccountsQuery(queryOptions);

            // Get the data from the database, pulling in only the bits we need.
            var savedAccounts = savedAccountsQuery
                                .Select(a => new
            {
                a.Guid,
                a.Name,
                a.FinancialPaymentDetail.ExpirationMonth,
                a.FinancialPaymentDetail.ExpirationYear,
                a.FinancialPaymentDetail.AccountNumberMasked,
                a.FinancialPaymentDetail.CurrencyTypeValueId,
                a.FinancialPaymentDetail.CreditCardTypeValueId
            })
                                .ToList();

            // Note: We don't perform a security check because saved accounts
            // don't have explicit security. It is implied that the matching
            // person identifier is enough security check.

            // Translate the saved accounts into something that will be
            // recognized by the client.
            return(savedAccounts
                   .Select(a =>
            {
                string image = null;
                string expirationDate = null;

                if (a.ExpirationMonth.HasValue && a.ExpirationYear.HasValue)
                {
                    // ExpirationYear returns 4 digits, but just in case,
                    // check if it is 4 digits before just getting the last 2.
                    string expireYY = a.ExpirationYear.Value.ToString();
                    if (expireYY.Length == 4)
                    {
                        expireYY = expireYY.Substring(2);
                    }

                    expirationDate = $"{a.ExpirationMonth.Value:00}/{expireYY:00}";
                }

                // Determine the descriptive text to associate with this account.
                string description = a.AccountNumberMasked != null && a.AccountNumberMasked.Length >= 4
                        ? $"Ending in {a.AccountNumberMasked.Right( 4 )} and Expires {expirationDate}"
                        : $"Expires {expirationDate}";

                // Determine the image to use for this account.
                if (a.CreditCardTypeValueId.HasValue)
                {
                    var creditCardTypeValueCache = DefinedValueCache.Get(a.CreditCardTypeValueId.Value);

                    image = creditCardTypeValueCache?.GetAttributeValue(SystemKey.CreditCardTypeAttributeKey.IconImage);
                }

                return new SavedFinancialAccountListItemViewModel
                {
                    Value = a.Guid.ToString(),
                    Text = a.Name,
                    Description = description,
                    Image = image
                };
            })
                   .OrderBy(a => a.Text)
                   .ToList());
        }
        /// <summary>
        /// Updates the scheduled payment.
        /// </summary>
        /// <param name="usePaymentToken">if set to <c>true</c> [use payment token].</param>
        /// <param name="paymentToken">The payment token.</param>
        protected void UpdateScheduledPayment(bool usePaymentToken, string paymentToken = null)
        {
            var giftTerm = this.GetAttributeValue(AttributeKey.GiftTerm);

            if (dtpStartDate.SelectedDate <= RockDateTime.Today)
            {
                nbUpdateScheduledPaymentWarning.Visible = true;
                nbUpdateScheduledPaymentWarning.Text    = string.Format("When scheduling a {0}, make sure the starting date is in the future (after today)", giftTerm.ToLower());
                return;
            }

            var rockContext = new RockContext();

            var  financialScheduledTransactionService       = new FinancialScheduledTransactionService(rockContext);
            var  financialScheduledTransactionDetailService = new FinancialScheduledTransactionDetailService(rockContext);
            Guid scheduledTransactionGuid      = hfScheduledTransactionGuid.Value.AsGuid();
            var  financialScheduledTransaction = financialScheduledTransactionService.Get(scheduledTransactionGuid);

            financialScheduledTransaction.StartDate = dtpStartDate.SelectedDate.Value;
            financialScheduledTransaction.TransactionFrequencyValueId = ddlFrequency.SelectedValue.AsInteger();

            ReferencePaymentInfo referencePaymentInfo;

            var person = financialScheduledTransaction.AuthorizedPersonAlias.Person;

            string errorMessage;

            var financialGateway                      = this.FinancialGateway;
            var financialGatewayComponent             = this.FinancialGatewayComponent;
            var existingPaymentOrPersonSavedAccountId = rblExistingPaymentOrPersonSavedAccount.SelectedValue.AsInteger();

            bool useExistingPaymentMethod = pnlUseExistingPaymentNoSavedAccounts.Visible || existingPaymentOrPersonSavedAccountId == 0;
            bool useSavedAccount          = pnlUseExistingPaymentWithSavedAccounts.Visible && existingPaymentOrPersonSavedAccountId > 0;

            if (usePaymentToken)
            {
                referencePaymentInfo           = new ReferencePaymentInfo();
                referencePaymentInfo.FirstName = person.FirstName;
                referencePaymentInfo.LastName  = person.LastName;

                referencePaymentInfo.UpdateAddressFieldsFromAddressControl(acBillingAddress);

                referencePaymentInfo.ReferenceNumber = paymentToken;

                var customerToken = financialGatewayComponent.CreateCustomerAccount(this.FinancialGateway, referencePaymentInfo, out errorMessage);

                if (errorMessage.IsNotNullOrWhiteSpace() || customerToken.IsNullOrWhiteSpace())
                {
                    nbMessage.NotificationBoxType = NotificationBoxType.Danger;
                    nbMessage.Text    = errorMessage ?? "Unknown Error";
                    nbMessage.Visible = true;
                    return;
                }

                referencePaymentInfo.GatewayPersonIdentifier = customerToken;
            }
            else if (useExistingPaymentMethod)
            {
                // use save payment method as original transaction
                referencePaymentInfo = new ReferencePaymentInfo();
                referencePaymentInfo.GatewayPersonIdentifier       = financialScheduledTransaction.FinancialPaymentDetail.GatewayPersonIdentifier;
                referencePaymentInfo.FinancialPersonSavedAccountId = financialScheduledTransaction.FinancialPaymentDetail.FinancialPersonSavedAccountId;
            }
            else if (useSavedAccount)
            {
                var savedAccount = new FinancialPersonSavedAccountService(rockContext).Get(existingPaymentOrPersonSavedAccountId);
                if (savedAccount != null)
                {
                    referencePaymentInfo = savedAccount.GetReferencePayment();
                }
                else
                {
                    // shouldn't happen
                    throw new Exception("Unable to determine Saved Account");
                }
            }
            else
            {
                // shouldn't happen
                throw new Exception("Unable to determine payment method");
            }

            var selectedAccountAmounts = caapPromptForAccountAmounts.AccountAmounts.Where(a => a.Amount.HasValue && a.Amount.Value != 0).Select(a => new { a.AccountId, Amount = a.Amount.Value }).ToArray();

            referencePaymentInfo.Amount = selectedAccountAmounts.Sum(a => a.Amount);

            var originalGatewayScheduleId = financialScheduledTransaction.GatewayScheduleId;

            try
            {
                financialScheduledTransaction.FinancialPaymentDetail.ClearPaymentInfo();
                var successfullyUpdated = financialGatewayComponent.UpdateScheduledPayment(financialScheduledTransaction, referencePaymentInfo, out errorMessage);

                if (!successfullyUpdated)
                {
                    nbMessage.NotificationBoxType = NotificationBoxType.Danger;
                    nbMessage.Text    = errorMessage ?? "Unknown Error";
                    nbMessage.Visible = true;
                    return;
                }

                financialScheduledTransaction.FinancialPaymentDetail.SetFromPaymentInfo(referencePaymentInfo, financialGatewayComponent as GatewayComponent, rockContext);

                var selectedAccountIds        = selectedAccountAmounts.Select(a => a.AccountId).ToArray();
                var deletedTransactionDetails = financialScheduledTransaction.ScheduledTransactionDetails.ToList().Where(a => !selectedAccountIds.Contains(a.AccountId)).ToList();

                foreach (var deletedTransactionDetail in deletedTransactionDetails)
                {
                    financialScheduledTransaction.ScheduledTransactionDetails.Remove(deletedTransactionDetail);
                    financialScheduledTransactionDetailService.Delete(deletedTransactionDetail);
                }

                foreach (var selectedAccountAmount in selectedAccountAmounts)
                {
                    var scheduledTransactionDetail = financialScheduledTransaction.ScheduledTransactionDetails.FirstOrDefault(a => a.AccountId == selectedAccountAmount.AccountId);
                    if (scheduledTransactionDetail == null)
                    {
                        scheduledTransactionDetail           = new FinancialScheduledTransactionDetail();
                        scheduledTransactionDetail.AccountId = selectedAccountAmount.AccountId;
                        financialScheduledTransaction.ScheduledTransactionDetails.Add(scheduledTransactionDetail);
                    }

                    scheduledTransactionDetail.Amount = selectedAccountAmount.Amount;
                }

                rockContext.SaveChanges();
                Task.Run(() => ScheduledGiftWasModifiedMessage.PublishScheduledTransactionEvent(financialScheduledTransaction.Id, ScheduledGiftEventTypes.ScheduledGiftUpdated));
            }
            catch (Exception)
            {
                // if the GatewayScheduleId was updated, but there was an exception,
                // make sure we save the  financialScheduledTransaction record with the updated GatewayScheduleId so we don't orphan it
                if (financialScheduledTransaction.GatewayScheduleId.IsNotNullOrWhiteSpace() && (originalGatewayScheduleId != financialScheduledTransaction.GatewayScheduleId))
                {
                    rockContext.SaveChanges();
                }

                throw;
            }

            var mergeFields = LavaHelper.GetCommonMergeFields(this.RockPage, this.CurrentPerson, new CommonMergeFieldsOptions {
                GetLegacyGlobalMergeFields = false
            });
            var finishLavaTemplate = this.GetAttributeValue(AttributeKey.FinishLavaTemplate);

            // re-fetch financialScheduledTransaction with a new RockContext from database to ensure that lazy loaded fields will be populated
            using (var rockContextForSummary = new RockContext())
            {
                if (pnlHostedPaymentControl.Visible && hfSaveNewAccount.Value.AsInteger() == 1 && tbSaveAccount.Text.IsNotNullOrWhiteSpace())
                {
                    SaveNewFinancialPersonSavedAccount(financialScheduledTransaction);
                }

                financialScheduledTransaction = new FinancialScheduledTransactionService(rockContextForSummary).Get(scheduledTransactionGuid);

                mergeFields.Add("Transaction", financialScheduledTransaction);
                mergeFields.Add("Person", financialScheduledTransaction.AuthorizedPersonAlias.Person);
                mergeFields.Add("PaymentDetail", financialScheduledTransaction.FinancialPaymentDetail);
                mergeFields.Add("BillingLocation", financialScheduledTransaction.FinancialPaymentDetail.BillingLocation);

                pnlPromptForChanges.Visible   = false;
                pnlTransactionSummary.Visible = true;

                lTransactionSummaryHTML.Text = finishLavaTemplate.ResolveMergeFields(mergeFields);
            }
        }