private void SetGatewayOptions( RockContext rockContext ) { _ccGateway = GetGateway( rockContext, "CCGateway" ); _ccGatewayComponent = GetGatewayComponent( rockContext, _ccGateway ); bool ccEnabled = _ccGatewayComponent != null; _achGateway = GetGateway( rockContext, "ACHGateway" ); _achGatewayComponent = GetGatewayComponent( rockContext, _achGateway ); bool achEnabled = _achGatewayComponent != null; if ( _using3StepGateway && _ccGateway != null && _achGateway != null && _ccGateway.Id != _achGateway.Id ) { _gatewaysIncompatible = true; } _ccSavedAccountFreqSupported = GetSavedAcccountFreqSupported( _ccGatewayComponent ); _achSavedAccountFreqSupported = GetSavedAcccountFreqSupported( _achGatewayComponent ); bool allowScheduled = GetAttributeValue( "AllowScheduled" ).AsBoolean(); if ( allowScheduled && ( ccEnabled || achEnabled ) ) { var supportedFrequencies = ccEnabled ? _ccGatewayComponent.SupportedPaymentSchedules : _achGatewayComponent.SupportedPaymentSchedules; // If CC and ACH gateways are both enabled, but different, only allow frequencies supported by both payment gateways (if different) if ( ccEnabled && achEnabled && _ccGatewayComponent.TypeId != _achGatewayComponent.TypeId ) { supportedFrequencies = _ccGatewayComponent.SupportedPaymentSchedules .Where( c => _achGatewayComponent.SupportedPaymentSchedules .Select( a => a.Id ) .Contains( c.Id ) ) .ToList(); } if ( supportedFrequencies.Any() ) { btnFrequency.DataSource = supportedFrequencies; btnFrequency.DataBind(); // If gateway didn't specifically support one-time, add it anyway for immediate gifts var oneTimeFrequency = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.TRANSACTION_FREQUENCY_ONE_TIME ); if ( !supportedFrequencies.Where( f => f.Id == oneTimeFrequency.Id ).Any() ) { btnFrequency.Items.Insert( 0, new ListItem( oneTimeFrequency.Value, oneTimeFrequency.Id.ToString() ) ); } btnFrequency.SelectedValue = oneTimeFrequency.Id.ToString(); dtpStartDate.SelectedDate = RockDateTime.Today; } } }
private void ShowSuccess( GatewayComponent gatewayComponent, Person person, PaymentInfo paymentInfo, PaymentSchedule schedule, FinancialPaymentDetail paymentDetail, RockContext rockContext ) { tdTransactionCodeReceipt.Description = TransactionCode; tdTransactionCodeReceipt.Visible = !string.IsNullOrWhiteSpace( TransactionCode ); tdScheduleId.Description = ScheduleId; tdScheduleId.Visible = !string.IsNullOrWhiteSpace( ScheduleId ); tdNameReceipt.Description = paymentInfo.FullName; tdPhoneReceipt.Description = paymentInfo.Phone; tdEmailReceipt.Description = paymentInfo.Email; tdAddressReceipt.Description = string.Format( "{0} {1}, {2} {3}", paymentInfo.Street1, paymentInfo.City, paymentInfo.State, paymentInfo.PostalCode ); rptAccountListReceipt.DataSource = SelectedAccounts.Where( a => a.Amount != 0 ); rptAccountListReceipt.DataBind(); tdTotalReceipt.Description = paymentInfo.Amount.ToString( "C" ); tdPaymentMethodReceipt.Description = paymentInfo.CurrencyTypeValue.Description; string acctNumber = paymentInfo.MaskedNumber; if ( string.IsNullOrWhiteSpace( acctNumber ) && paymentDetail != null && !string.IsNullOrWhiteSpace( paymentDetail.AccountNumberMasked ) ) { acctNumber = paymentDetail.AccountNumberMasked; } tdAccountNumberReceipt.Description = acctNumber; tdAccountNumberReceipt.Visible = !string.IsNullOrWhiteSpace( acctNumber ); tdWhenReceipt.Description = schedule != null ? schedule.ToString() : "Today"; // If there was a transaction code returned and this was not already created from a previous saved account, // show the option to save the account. if ( !( paymentInfo is ReferencePaymentInfo ) && !string.IsNullOrWhiteSpace( TransactionCode ) && gatewayComponent.SupportsSavedAccount( paymentInfo.CurrencyTypeValue ) ) { cbSaveAccount.Visible = true; pnlSaveAccount.Visible = true; txtSaveAccount.Visible = true; // If current person does not have a login, have them create a username and password phCreateLogin.Visible = !new UserLoginService( rockContext ).GetByPersonId( person.Id ).Any(); } else { pnlSaveAccount.Visible = false; } }
private void SaveScheduledTransaction( FinancialGateway financialGateway, GatewayComponent gateway, Person person, PaymentInfo paymentInfo, PaymentSchedule schedule, FinancialScheduledTransaction scheduledTransaction, RockContext rockContext ) { scheduledTransaction.TransactionFrequencyValueId = schedule.TransactionFrequencyValue.Id; scheduledTransaction.StartDate = schedule.StartDate; scheduledTransaction.AuthorizedPersonAliasId = person.PrimaryAliasId.Value; scheduledTransaction.FinancialGatewayId = financialGateway.Id; if ( scheduledTransaction.FinancialPaymentDetail == null ) { scheduledTransaction.FinancialPaymentDetail = new FinancialPaymentDetail(); } scheduledTransaction.FinancialPaymentDetail.SetFromPaymentInfo( paymentInfo, gateway, rockContext ); Guid sourceGuid = Guid.Empty; if ( Guid.TryParse( GetAttributeValue( "Source" ), out sourceGuid ) ) { var source = DefinedValueCache.Read( sourceGuid ); if ( source != null ) { scheduledTransaction.SourceTypeValueId = source.Id; } } var changeSummary = new StringBuilder(); changeSummary.AppendFormat( "{0} starting {1}", schedule.TransactionFrequencyValue.Value, schedule.StartDate.ToShortDateString() ); changeSummary.AppendLine(); changeSummary.Append( paymentInfo.CurrencyTypeValue.Value ); if ( paymentInfo.CreditCardTypeValue != null ) { changeSummary.AppendFormat( " - {0}", paymentInfo.CreditCardTypeValue.Value ); } changeSummary.AppendFormat( " {0}", paymentInfo.MaskedNumber ); changeSummary.AppendLine(); foreach ( var account in SelectedAccounts.Where( a => a.Amount > 0 ) ) { var transactionDetail = new FinancialScheduledTransactionDetail(); transactionDetail.Amount = account.Amount; transactionDetail.AccountId = account.Id; scheduledTransaction.ScheduledTransactionDetails.Add( transactionDetail ); changeSummary.AppendFormat( "{0}: {1}", account.Name, account.Amount.FormatAsCurrency() ); changeSummary.AppendLine(); } if ( !string.IsNullOrWhiteSpace( paymentInfo.Comment1 ) ) { changeSummary.Append( paymentInfo.Comment1 ); changeSummary.AppendLine(); } var transactionService = new FinancialScheduledTransactionService( rockContext ); transactionService.Add( scheduledTransaction ); rockContext.SaveChanges(); // If this is a transfer, now we can delete the old transaction if ( _scheduledTransactionToBeTransferred != null ) { DeleteOldTransaction( _scheduledTransactionToBeTransferred.Id ); } // Add a note about the change var noteType = NoteTypeCache.Read( Rock.SystemGuid.NoteType.SCHEDULED_TRANSACTION_NOTE.AsGuid() ); if ( noteType != null ) { var noteService = new NoteService( rockContext ); var note = new Note(); note.NoteTypeId = noteType.Id; note.EntityId = scheduledTransaction.Id; note.Caption = "Created Transaction"; note.Text = changeSummary.ToString(); noteService.Add( note ); } rockContext.SaveChanges(); ScheduleId = scheduledTransaction.GatewayScheduleId; TransactionCode = scheduledTransaction.TransactionCode; }
private void SaveTransaction( FinancialGateway financialGateway, GatewayComponent gateway, Person person, PaymentInfo paymentInfo, FinancialTransaction transaction, RockContext rockContext ) { var txnChanges = new List<string>(); txnChanges.Add( "Created Transaction" ); History.EvaluateChange( txnChanges, "Transaction Code", string.Empty, transaction.TransactionCode ); transaction.AuthorizedPersonAliasId = person.PrimaryAliasId; History.EvaluateChange( txnChanges, "Person", string.Empty, person.FullName ); transaction.TransactionDateTime = RockDateTime.Now; History.EvaluateChange( txnChanges, "Date/Time", null, transaction.TransactionDateTime ); transaction.FinancialGatewayId = financialGateway.Id; History.EvaluateChange( txnChanges, "Gateway", string.Empty, financialGateway.Name ); var txnType = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION ) ); transaction.TransactionTypeValueId = txnType.Id; History.EvaluateChange( txnChanges, "Type", string.Empty, txnType.Value ); transaction.Summary = paymentInfo.Comment1; History.EvaluateChange( txnChanges, "Summary", string.Empty, transaction.Summary ); if ( transaction.FinancialPaymentDetail == null ) { transaction.FinancialPaymentDetail = new FinancialPaymentDetail(); } transaction.FinancialPaymentDetail.SetFromPaymentInfo( paymentInfo, gateway, rockContext, txnChanges ); Guid sourceGuid = Guid.Empty; if ( Guid.TryParse( GetAttributeValue( "Source" ), out sourceGuid ) ) { var source = DefinedValueCache.Read( sourceGuid ); if ( source != null ) { transaction.SourceTypeValueId = source.Id; History.EvaluateChange( txnChanges, "Source", string.Empty, source.Value ); } } foreach ( var account in SelectedAccounts.Where( a => a.Amount > 0 ) ) { var transactionDetail = new FinancialTransactionDetail(); transactionDetail.Amount = account.Amount; transactionDetail.AccountId = account.Id; transaction.TransactionDetails.Add( transactionDetail ); History.EvaluateChange( txnChanges, account.Name, 0.0M.FormatAsCurrency(), transactionDetail.Amount.FormatAsCurrency() ); } var batchService = new FinancialBatchService( rockContext ); // Get the batch var batch = batchService.Get( GetAttributeValue( "BatchNamePrefix" ), paymentInfo.CurrencyTypeValue, paymentInfo.CreditCardTypeValue, transaction.TransactionDateTime.Value, financialGateway.GetBatchTimeOffset() ); var batchChanges = new List<string>(); if ( batch.Id == 0 ) { batchChanges.Add( "Generated the batch" ); History.EvaluateChange( batchChanges, "Batch Name", string.Empty, batch.Name ); History.EvaluateChange( batchChanges, "Status", null, batch.Status ); History.EvaluateChange( batchChanges, "Start Date/Time", null, batch.BatchStartDateTime ); History.EvaluateChange( batchChanges, "End Date/Time", null, batch.BatchEndDateTime ); } decimal newControlAmount = batch.ControlAmount + transaction.TotalAmount; History.EvaluateChange( batchChanges, "Control Amount", batch.ControlAmount.FormatAsCurrency(), newControlAmount.FormatAsCurrency() ); batch.ControlAmount = newControlAmount; transaction.BatchId = batch.Id; batch.Transactions.Add( transaction ); rockContext.SaveChanges(); HistoryService.SaveChanges( rockContext, typeof( FinancialBatch ), Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(), batch.Id, batchChanges ); HistoryService.SaveChanges( rockContext, typeof( FinancialBatch ), Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(), batch.Id, txnChanges, person.FullName, typeof( FinancialTransaction ), transaction.Id ); SendReceipt( transaction.Id ); TransactionCode = transaction.TransactionCode; }
/// <summary> /// Safely load entities that have not yet been assigned a non-null value based on the arguments. /// </summary> private void LoadEntities() { if (_automatedPaymentArgs.ScheduledTransactionId.HasValue && _financialScheduledTransaction == null) { _financialScheduledTransaction = _financialScheduledTransactionService.Queryable() .AsNoTracking() .Include(s => s.TransactionFrequencyValue) .FirstOrDefault(s => s.Id == _automatedPaymentArgs.ScheduledTransactionId.Value); } if (_authorizedPerson == null) { _authorizedPerson = _personAliasService.GetPersonNoTracking(_automatedPaymentArgs.AuthorizedPersonAliasId); } if (_financialGateway == null) { _financialGateway = _financialGatewayService.GetNoTracking(_automatedPaymentArgs.AutomatedGatewayId); } if (_financialGateway != null && _automatedGatewayComponent == null) { _automatedGatewayComponent = _financialGateway.GetGatewayComponent(); } if (_financialAccounts == null) { var accountIds = _automatedPaymentArgs.AutomatedPaymentDetails.Select(d => d.AccountId).ToList(); _financialAccounts = _financialAccountService.GetByIds(accountIds).AsNoTracking().ToDictionary(fa => fa.Id, fa => fa); } if (_authorizedPerson != null && _financialPersonSavedAccount == null && _financialGateway != null) { // Pick the correct saved account based on args or default for the user var financialGatewayId = _financialGateway.Id; var savedAccounts = _financialPersonSavedAccountService .GetByPersonId(_authorizedPerson.Id) .AsNoTracking() .Where(sa => sa.FinancialGatewayId == financialGatewayId) .Include(sa => sa.FinancialPaymentDetail) .OrderByDescending(sa => sa.CreatedDateTime ?? DateTime.MinValue) .ToList(); if (_automatedPaymentArgs.FinancialPersonSavedAccountId.HasValue) { // If there is an indicated saved account to use, don't assume any other saved account even with a schedule var savedAccountId = _automatedPaymentArgs.FinancialPersonSavedAccountId.Value; _financialPersonSavedAccount = savedAccounts.FirstOrDefault(sa => sa.Id == savedAccountId); } else { // If there is a schedule and no indicated saved account to use, try to use payment info associated with the schedule if (_financialScheduledTransaction != null) { _financialPersonSavedAccount = // sa.ReferenceNumber == fst.TransactionCode savedAccounts.FirstOrDefault(sa => !string.IsNullOrEmpty(sa.ReferenceNumber) && sa.ReferenceNumber == _financialScheduledTransaction.TransactionCode) ?? // sa.GatewayPersonIdentifier == fst.TransactionCode savedAccounts.FirstOrDefault(sa => !string.IsNullOrEmpty(sa.GatewayPersonIdentifier) && sa.GatewayPersonIdentifier == _financialScheduledTransaction.TransactionCode) ?? // sa.FinancialPaymentDetailId == fst.FinancialPaymentDetailId savedAccounts.FirstOrDefault(sa => sa.FinancialPaymentDetailId.HasValue && sa.FinancialPaymentDetailId == _financialScheduledTransaction.FinancialPaymentDetailId) ?? // sa.TransactionCode == fst.TransactionCode savedAccounts.FirstOrDefault(sa => !string.IsNullOrEmpty(sa.TransactionCode) && sa.TransactionCode == _financialScheduledTransaction.TransactionCode); } if (_financialPersonSavedAccount == null) { // Use the default or first if no default _financialPersonSavedAccount = savedAccounts.FirstOrDefault(sa => sa.IsDefault) ?? savedAccounts.FirstOrDefault(); } } } if (_financialPersonSavedAccount != null && _referencePaymentInfo == null) { _referencePaymentInfo = _financialPersonSavedAccount.GetReferencePayment(); } if (_transactionType == null) { _transactionType = DefinedValueCache.Get(_automatedPaymentArgs.TransactionTypeGuid ?? SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid()); } if (_financialSource == null) { _financialSource = DefinedValueCache.Get(_automatedPaymentArgs.FinancialSourceGuid ?? SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_WEBSITE.AsGuid()); } }
private string GetSavedAcccountFreqSupported( GatewayComponent component ) { if ( component != null ) { if ( component.SupportsSavedAccount( true ) ) { if ( component.SupportsSavedAccount( false ) ) { return "both"; } else { return "repeating"; } } else { if ( component.SupportsSavedAccount( false ) ) { return "onetime"; } } } return "none"; }
/// <summary> /// Raises the <see cref="E:System.Web.UI.Control.Init" /> event. /// </summary> /// <param name="e">An <see cref="T:System.EventArgs" /> object that contains the event data.</param> protected override void OnInit( EventArgs e ) { base.OnInit( e ); if ( !Page.IsPostBack ) { lPanelTitle1.Text = GetAttributeValue( "PanelTitle" ); lPanelTitle2.Text = GetAttributeValue( "PanelTitle" ); lContributionInfoTitle.Text = GetAttributeValue( "ContributionInfoTitle" ); lPersonalInfoTitle.Text = GetAttributeValue( "PersonalInfoTitle" ); lPaymentInfoTitle.Text = GetAttributeValue( "PaymentInfoTitle" ); lConfirmationTitle.Text = GetAttributeValue( "ConfirmationTitle" ); lSuccessTitle.Text = GetAttributeValue( "SuccessTitle" ); lSaveAcccountTitle.Text = GetAttributeValue( "SaveAccountTitle" ); } // If impersonation is allowed, and a valid person key was used, set the target to that person if ( GetAttributeValue( "Impersonation" ).AsBooleanOrNull() ?? false ) { string personKey = PageParameter( "Person" ); if ( !string.IsNullOrWhiteSpace( personKey ) ) { TargetPerson = new PersonService( new RockContext() ).GetByUrlEncodedKey( personKey ); } } // if TargetPerson wasn't set by Impersonation, try to get it from the PersonId parameter (if specified) if (TargetPerson == null) { int? personId = PageParameter( "PersonId" ).AsIntegerOrNull(); if ( personId.HasValue ) { TargetPerson = new PersonService( new RockContext() ).Get( personId.Value ); } } if ( TargetPerson == null ) { TargetPerson = CurrentPerson; } // Enable payment options based on the configured gateways bool ccEnabled = false; bool achEnabled = false; var supportedFrequencies = new List<DefinedValueCache>(); string ccGatewayGuid = GetAttributeValue( "CCGateway" ); if ( !string.IsNullOrWhiteSpace( ccGatewayGuid ) ) { _ccGateway = GatewayContainer.GetComponent( ccGatewayGuid ); if ( _ccGateway != null ) { ccEnabled = true; txtCardFirstName.Visible = _ccGateway.SplitNameOnCard; txtCardLastName.Visible = _ccGateway.SplitNameOnCard; txtCardName.Visible = !_ccGateway.SplitNameOnCard; mypExpiration.MinimumYear = RockDateTime.Now.Year; } } string achGatewayGuid = GetAttributeValue( "ACHGateway" ); if ( !string.IsNullOrWhiteSpace( achGatewayGuid ) ) { _achGateway = GatewayContainer.GetComponent( achGatewayGuid ); achEnabled = _achGateway != null; } hfCurrentPage.Value = "1"; RockPage page = Page as RockPage; if ( page != null ) { page.PageNavigate += page_PageNavigate; } if ( ccEnabled || achEnabled ) { if ( ccEnabled ) { supportedFrequencies = _ccGateway.SupportedPaymentSchedules; hfPaymentTab.Value = "CreditCard"; } else { supportedFrequencies = _achGateway.SupportedPaymentSchedules; hfPaymentTab.Value = "ACH"; } if ( ccEnabled && achEnabled ) { phPills.Visible = true; // If CC and ACH gateways are different, only allow frequencies supported by both payment gateways (if different) if ( _ccGateway.TypeId != _achGateway.TypeId ) { supportedFrequencies = _ccGateway.SupportedPaymentSchedules .Where( c => _achGateway.SupportedPaymentSchedules .Select( a => a.Id ) .Contains( c.Id ) ) .ToList(); } divCCPaymentInfo.AddCssClass( "tab-pane" ); divACHPaymentInfo.AddCssClass( "tab-pane" ); } divCCPaymentInfo.Visible = ccEnabled; divACHPaymentInfo.Visible = achEnabled; if ( supportedFrequencies.Any() ) { bool allowScheduled = false; if ( bool.TryParse( GetAttributeValue( "AllowScheduled" ), out allowScheduled ) && allowScheduled ) { _showRepeatingOptions = true; var oneTimeFrequency = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.TRANSACTION_FREQUENCY_ONE_TIME ); divRepeatingPayments.Visible = true; btnFrequency.DataSource = supportedFrequencies; btnFrequency.DataBind(); // If gateway didn't specifically support one-time, add it anyway for immediate gifts if ( !supportedFrequencies.Where( f => f.Id == oneTimeFrequency.Id ).Any() ) { btnFrequency.Items.Insert( 0, new ListItem( oneTimeFrequency.Value, oneTimeFrequency.Id.ToString() ) ); } btnFrequency.SelectedValue = oneTimeFrequency.Id.ToString(); dtpStartDate.SelectedDate = RockDateTime.Today; } } // Display Options btnAddAccount.Title = GetAttributeValue( "AddAccountText" ); bool displayEmail = GetAttributeValue( "DisplayEmail" ).AsBoolean(); txtEmail.Visible = displayEmail; tdEmailConfirm.Visible = displayEmail; tdEmailReceipt.Visible = displayEmail; bool displayPhone = GetAttributeValue( "DisplayPhone" ).AsBoolean(); pnbPhone.Visible = displayPhone; tdPhoneConfirm.Visible = displayPhone; tdPhoneReceipt.Visible = displayPhone; FluidLayout = GetAttributeValue( "LayoutStyle" ) == "Fluid"; BindSavedAccounts(); if ( rblSavedCC.Items.Count > 0 ) { rblSavedCC.Items[0].Selected = true; rblSavedCC.Visible = true; divNewCard.Style[HtmlTextWriterStyle.Display] = "none"; } else { rblSavedCC.Visible = false; divNewCard.Style[HtmlTextWriterStyle.Display] = "block"; } if ( rblSavedAch.Items.Count > 0 ) { rblSavedAch.Items[0].Selected = true; rblSavedAch.Visible = true; divNewBank.Style[HtmlTextWriterStyle.Display] = "none"; } else { rblSavedAch.Visible = false; divNewCard.Style[HtmlTextWriterStyle.Display] = "block"; } RegisterScript(); // Resolve the text field merge fields var configValues = new Dictionary<string, object>(); Rock.Web.Cache.GlobalAttributesCache.Read().AttributeValues .Where( v => v.Key.StartsWith( "Organization", StringComparison.CurrentCultureIgnoreCase ) ) .ToList() .ForEach( v => configValues.Add( v.Key, v.Value ) ); phConfirmationHeader.Controls.Add( new LiteralControl( GetAttributeValue( "ConfirmationHeader" ).ResolveMergeFields( configValues ) ) ); phConfirmationFooter.Controls.Add( new LiteralControl( GetAttributeValue( "ConfirmationFooter" ).ResolveMergeFields( configValues ) ) ); phSuccessHeader.Controls.Add( new LiteralControl( GetAttributeValue( "SuccessHeader" ).ResolveMergeFields( configValues ) ) ); phSuccessFooter.Controls.Add( new LiteralControl( GetAttributeValue( "SuccessFooter" ).ResolveMergeFields( configValues ) ) ); //// Temp values for testing... /* txtCreditCard.Text = "5105105105105100"; txtCVV.Text = "023"; txtBankName.Text = "Test Bank"; txtRoutingNumber.Text = "111111118"; txtAccountNumber.Text = "1111111111"; */ } }
private bool SaveTransaction( GatewayComponent gateway, Registration registration, FinancialTransaction transaction, PaymentInfo paymentInfo, RockContext rockContext ) { if ( transaction != null ) { var txnChanges = new List<string>(); txnChanges.Add( "Created Transaction" ); History.EvaluateChange( txnChanges, "Transaction Code", string.Empty, transaction.TransactionCode ); transaction.AuthorizedPersonAliasId = registration.PersonAliasId; transaction.TransactionDateTime = RockDateTime.Now; History.EvaluateChange( txnChanges, "Date/Time", null, transaction.TransactionDateTime ); transaction.FinancialGatewayId = RegistrationTemplate.FinancialGatewayId; History.EvaluateChange( txnChanges, "Gateway", string.Empty, RegistrationTemplate.FinancialGateway.Name ); var txnType = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_EVENT_REGISTRATION ) ); transaction.TransactionTypeValueId = txnType.Id; History.EvaluateChange( txnChanges, "Type", string.Empty, txnType.Value ); if ( transaction.FinancialPaymentDetail == null ) { transaction.FinancialPaymentDetail = new FinancialPaymentDetail(); } DefinedValueCache currencyType = null; DefinedValueCache creditCardType = null; if ( paymentInfo != null ) { transaction.FinancialPaymentDetail.SetFromPaymentInfo( paymentInfo, gateway, rockContext, txnChanges ); currencyType = paymentInfo.CurrencyTypeValue; creditCardType = paymentInfo.CreditCardTypeValue; } Guid sourceGuid = Guid.Empty; if ( Guid.TryParse( GetAttributeValue( "Source" ), out sourceGuid ) ) { var source = DefinedValueCache.Read( sourceGuid ); if ( source != null ) { transaction.SourceTypeValueId = source.Id; History.EvaluateChange( txnChanges, "Source", string.Empty, source.Value ); } } transaction.Summary = registration.GetSummary( RegistrationInstanceState ); var transactionDetail = new FinancialTransactionDetail(); transactionDetail.Amount = RegistrationState.PaymentAmount ?? 0.0m; transactionDetail.AccountId = RegistrationInstanceState.AccountId.Value; transactionDetail.EntityTypeId = EntityTypeCache.Read( typeof( Rock.Model.Registration ) ).Id; transactionDetail.EntityId = registration.Id; transaction.TransactionDetails.Add( transactionDetail ); History.EvaluateChange( txnChanges, RegistrationInstanceState.Account.Name, 0.0M.FormatAsCurrency(), transactionDetail.Amount.FormatAsCurrency() ); var batchChanges = new List<string>(); rockContext.WrapTransaction( () => { var batchService = new FinancialBatchService( rockContext ); // determine batch prefix string batchPrefix = string.Empty; if ( !string.IsNullOrWhiteSpace( RegistrationTemplate.BatchNamePrefix ) ) { batchPrefix = RegistrationTemplate.BatchNamePrefix; } else { batchPrefix = GetAttributeValue( "BatchNamePrefix" ); } // Get the batch var batch = batchService.Get( batchPrefix, currencyType, creditCardType, transaction.TransactionDateTime.Value, RegistrationTemplate.FinancialGateway.GetBatchTimeOffset() ); if ( batch.Id == 0 ) { batchChanges.Add( "Generated the batch" ); History.EvaluateChange( batchChanges, "Batch Name", string.Empty, batch.Name ); History.EvaluateChange( batchChanges, "Status", null, batch.Status ); History.EvaluateChange( batchChanges, "Start Date/Time", null, batch.BatchStartDateTime ); History.EvaluateChange( batchChanges, "End Date/Time", null, batch.BatchEndDateTime ); } decimal newControlAmount = batch.ControlAmount + transaction.TotalAmount; History.EvaluateChange( batchChanges, "Control Amount", batch.ControlAmount.FormatAsCurrency(), newControlAmount.FormatAsCurrency() ); batch.ControlAmount = newControlAmount; transaction.BatchId = batch.Id; batch.Transactions.Add( transaction ); rockContext.SaveChanges(); } ); if ( transaction.BatchId.HasValue ) { Task.Run( () => HistoryService.SaveChanges( new RockContext(), typeof( FinancialBatch ), Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(), transaction.BatchId.Value, batchChanges, true, CurrentPersonAliasId ) ); Task.Run( () => HistoryService.SaveChanges( new RockContext(), typeof( FinancialBatch ), Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(), transaction.BatchId.Value, txnChanges, CurrentPerson != null ? CurrentPerson.FullName : string.Empty, typeof( FinancialTransaction ), transaction.Id, true, CurrentPersonAliasId ) ); } List<string> registrationChanges = new List<string>(); registrationChanges.Add( string.Format( "Made {0} payment", transaction.TotalAmount.FormatAsCurrency() ) ); Task.Run( () => HistoryService.SaveChanges( new RockContext(), typeof( Registration ), Rock.SystemGuid.Category.HISTORY_EVENT_REGISTRATION.AsGuid(), registration.Id, registrationChanges, true, CurrentPersonAliasId ) ); TransactionCode = transaction.TransactionCode; return true; } else { return false; } }
private CreditCardPaymentInfo GetCCPaymentInfo( GatewayComponent gateway ) { var ccPaymentInfo = new CreditCardPaymentInfo( txtCreditCard.Text, txtCVV.Text, mypExpiration.SelectedDate.Value ); ccPaymentInfo.NameOnCard = gateway != null && gateway.SplitNameOnCard ? txtCardFirstName.Text : txtCardName.Text; ccPaymentInfo.LastNameOnCard = txtCardLastName.Text; ccPaymentInfo.BillingStreet1 = acBillingAddress.Street1; ccPaymentInfo.BillingStreet2 = acBillingAddress.Street2; ccPaymentInfo.BillingCity = acBillingAddress.City; ccPaymentInfo.BillingState = acBillingAddress.State; ccPaymentInfo.BillingPostalCode = acBillingAddress.PostalCode; ccPaymentInfo.BillingCountry = acBillingAddress.Country; ccPaymentInfo.Amount = RegistrationState.PaymentAmount ?? 0.0m; ccPaymentInfo.Email = RegistrationState.ConfirmationEmail; ccPaymentInfo.FirstName = RegistrationState.FirstName; ccPaymentInfo.LastName = RegistrationState.LastName; return ccPaymentInfo; }
private void BindSavedAccounts( GatewayComponent component ) { var currentValue = rblSavedCC.SelectedValue; rblSavedCC.Items.Clear(); if ( CurrentPerson != null ) { // Get the saved accounts for the currently logged in user var savedAccounts = new FinancialPersonSavedAccountService( new RockContext() ) .GetByPersonId( CurrentPerson.Id ); // Verify component is valid and that it supports using saved accounts for one-time, credit card transactions var ccCurrencyType = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD ) ); if ( component != null && component.SupportsSavedAccount( false ) && component.SupportsSavedAccount( ccCurrencyType ) ) { rblSavedCC.DataSource = savedAccounts .Where( a => a.FinancialGatewayId == RegistrationTemplate.FinancialGateway.Id && a.FinancialPaymentDetail != null && a.FinancialPaymentDetail.CurrencyTypeValueId == ccCurrencyType.Id ) .OrderBy( a => a.Name ) .Select( a => new { Id = a.Id, Name = "Use " + a.Name + " (" + a.FinancialPaymentDetail.AccountNumberMasked + ")" } ).ToList(); rblSavedCC.DataBind(); if ( rblSavedCC.Items.Count > 0 ) { rblSavedCC.Items.Add( new ListItem( "Use a different card", "0" ) ); rblSavedCC.SetValue( currentValue ); } } } }
/// <summary> /// Processes the payments. /// </summary> /// <param name="gateway">The gateway.</param> /// <param name="batchNamePrefix">The batch name prefix.</param> /// <param name="payments">The payments.</param> /// <param name="batchUrlFormat">The batch URL format.</param> /// <returns></returns> public static string ProcessPayments( GatewayComponent gateway, string batchNamePrefix, List<Payment> payments, string batchUrlFormat = "" ) { int totalPayments = 0; int totalAlreadyDownloaded = 0; int totalNoScheduledTransaction = 0; int totalAdded = 0; var batches = new List<FinancialBatch>(); var batchSummary = new Dictionary<Guid, List<Payment>>(); var rockContext = new RockContext(); var accountService = new FinancialAccountService( rockContext ); var txnService = new FinancialTransactionService( rockContext ); var batchService = new FinancialBatchService( rockContext ); var scheduledTxnService = new FinancialScheduledTransactionService( rockContext ); var contributionTxnTypeId = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid() ).Id; var defaultAccount = accountService.Queryable() .Where( a => a.IsActive && !a.ParentAccountId.HasValue && ( !a.StartDate.HasValue || a.StartDate.Value <= RockDateTime.Now ) && ( !a.EndDate.HasValue || a.EndDate.Value >= RockDateTime.Now ) ) .OrderBy( a => a.Order ) .FirstOrDefault(); foreach ( var payment in payments.Where( p => p.Amount > 0.0M ) ) { totalPayments++; // Only consider transactions that have not already been added if ( txnService.GetByTransactionCode( payment.TransactionCode ) == null ) { var scheduledTransaction = scheduledTxnService.GetByScheduleId( payment.GatewayScheduleId ); if ( scheduledTransaction != null ) { scheduledTransaction.IsActive = payment.ScheduleActive; var transaction = new FinancialTransaction(); transaction.TransactionCode = payment.TransactionCode; transaction.TransactionDateTime = payment.TransactionDateTime; transaction.ScheduledTransactionId = scheduledTransaction.Id; transaction.AuthorizedPersonAliasId = scheduledTransaction.AuthorizedPersonAliasId; transaction.GatewayEntityTypeId = gateway.TypeId; transaction.TransactionTypeValueId = contributionTxnTypeId; var currencyTypeValue = payment.CurrencyTypeValue; if ( currencyTypeValue == null && scheduledTransaction.CurrencyTypeValueId.HasValue ) { currencyTypeValue = DefinedValueCache.Read( scheduledTransaction.CurrencyTypeValueId.Value ); } if ( currencyTypeValue != null ) { transaction.CurrencyTypeValueId = currencyTypeValue.Id; } var creditCardTypevalue = payment.CreditCardTypeValue; if ( creditCardTypevalue == null && scheduledTransaction.CreditCardTypeValueId.HasValue ) { creditCardTypevalue = DefinedValueCache.Read( scheduledTransaction.CreditCardTypeValueId.Value ); } if ( creditCardTypevalue != null ) { transaction.CreditCardTypeValueId = creditCardTypevalue.Id; } //transaction.SourceTypeValueId = DefinedValueCache.Read( sourceGuid ).Id; // Try to allocate the amount of the transaction based on the current scheduled transaction accounts decimal remainingAmount = payment.Amount; foreach ( var detail in scheduledTransaction.ScheduledTransactionDetails.Where( d => d.Amount != 0.0M ) ) { var transactionDetail = new FinancialTransactionDetail(); transactionDetail.AccountId = detail.AccountId; if ( detail.Amount <= remainingAmount ) { // If the configured amount for this account is less than or equal to the remaining // amount, allocate the configured amount transactionDetail.Amount = detail.Amount; remainingAmount -= detail.Amount; } else { // If the configured amount is greater than the remaining amount, only allocate // the remaining amount transaction.Summary = "Note: Downloaded transaction amount was less than the configured allocation amounts for the Scheduled Transaction."; detail.Amount = remainingAmount; detail.Summary = "Note: The downloaded amount was not enough to apply the configured amount to this account."; remainingAmount = 0.0M; } transaction.TransactionDetails.Add( transactionDetail ); if ( remainingAmount <= 0.0M ) { // If there's no amount left, break out of details break; } } // If there's still amount left after allocating based on current config, add the remainder // to the account that was configured for the most amount if ( remainingAmount > 0.0M ) { transaction.Summary = "Note: Downloaded transaction amount was greater than the configured allocation amounts for the Scheduled Transaction."; var transactionDetail = transaction.TransactionDetails .OrderByDescending( d => d.Amount ) .First(); if ( transactionDetail == null && defaultAccount != null ) { transactionDetail = new FinancialTransactionDetail(); transactionDetail.AccountId = defaultAccount.Id; } if ( transactionDetail != null ) { transactionDetail.Amount += remainingAmount; transactionDetail.Summary = "Note: Extra amount was applied to this account."; } } // Get the batch var batch = batchService.Get( batchNamePrefix, currencyTypeValue, creditCardTypevalue, transaction.TransactionDateTime.Value, gateway.BatchTimeOffset, batches ); batch.ControlAmount += transaction.TotalAmount; batch.Transactions.Add( transaction ); // Add summary if ( !batchSummary.ContainsKey( batch.Guid ) ) { batchSummary.Add( batch.Guid, new List<Payment>() ); } batchSummary[batch.Guid].Add( payment ); totalAdded++; } else { totalNoScheduledTransaction++; } } else { totalAlreadyDownloaded++; } } rockContext.SaveChanges(); StringBuilder sb = new StringBuilder(); sb.AppendFormat( "<li>{0} {1} downloaded.</li>", totalPayments.ToString( "N0" ), ( totalPayments == 1 ? "payment" : "payments" ) ); if ( totalAlreadyDownloaded > 0 ) { sb.AppendFormat( "<li>{0} {1} previously downloaded and {2} already been added.</li>", totalAlreadyDownloaded.ToString( "N0" ), ( totalAlreadyDownloaded == 1 ? "payment was" : "payments were" ), ( totalAlreadyDownloaded == 1 ? "has" : "have" ) ); } if ( totalNoScheduledTransaction > 0 ) { sb.AppendFormat( "<li>{0} {1} could not be matched to an existing scheduled payment profile.</li>", totalNoScheduledTransaction.ToString( "N0" ), ( totalNoScheduledTransaction == 1 ? "payment" : "payments" ) ); } sb.AppendFormat( "<li>{0} {1} successfully added.</li>", totalAdded.ToString( "N0" ), ( totalAdded == 1 ? "payment was" : "payments were" ) ); foreach ( var batchItem in batchSummary ) { int items = batchItem.Value.Count; if (items > 0) { var batch = batches .Where( b => b.Guid.Equals( batchItem.Key ) ) .FirstOrDefault(); string batchName = string.Format("'{0} ({1})'", batch.Name, batch.BatchStartDateTime.Value.ToString("d")); if ( !string.IsNullOrWhiteSpace( batchUrlFormat ) ) { batchName = string.Format( "<a href='{0}'>{1}</a>", string.Format( batchUrlFormat, batch.Id ), batchName ); } decimal sum = batchItem.Value.Select( p => p.Amount ).Sum(); string summaryformat = items == 1 ? "<li>{0} transaction of {1} was added to the {2} batch.</li>" : "<li>{0} transactions totaling {1} were added to the {2} batch</li>"; sb.AppendFormat( summaryformat, items.ToString( "N0" ), sum.ToString( "C2" ), batchName ); } } return sb.ToString(); }