示例#1
0
        /// <summary>
        /// Adds the scheduled payment.
        /// </summary>
        /// <param name="financialGateway">The financial gateway.</param>
        /// <param name="schedule">The schedule.</param>
        /// <param name="paymentInfo">The payment info.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialScheduledTransaction AddScheduledPayment( FinancialGateway financialGateway, PaymentSchedule schedule, PaymentInfo paymentInfo, out string errorMessage )
        {
            errorMessage = string.Empty;

            var scheduledTransaction = new FinancialScheduledTransaction();
            scheduledTransaction.IsActive = true;
            scheduledTransaction.StartDate = schedule.StartDate;
            scheduledTransaction.NextPaymentDate = schedule.StartDate;
            scheduledTransaction.TransactionCode = "T" + RockDateTime.Now.ToString("yyyyMMddHHmmssFFF");
            scheduledTransaction.GatewayScheduleId = "P" + RockDateTime.Now.ToString("yyyyMMddHHmmssFFF");
            scheduledTransaction.LastStatusUpdateDateTime = RockDateTime.Now;
            return scheduledTransaction;
        }
示例#2
0
        /// <summary>
        /// Shows the detail.
        /// </summary>
        /// <param name="gatewayId">The gateway identifier.</param>
        public void ShowDetail( int gatewayId )
        {
            FinancialGateway gateway = null;

            bool editAllowed = IsUserAuthorized( Authorization.EDIT );

            if ( !gatewayId.Equals( 0 ) )
            {
                gateway = new FinancialGatewayService( new RockContext() ).Get( gatewayId );
                editAllowed = editAllowed || gateway.IsAuthorized( Authorization.EDIT, CurrentPerson );
                pdAuditDetails.SetEntity( gateway, ResolveRockUrl( "~" ) );
            }

            if ( gateway == null )
            {
                gateway = new FinancialGateway { Id = 0, IsActive = true };
                // hide the panel drawer that show created and last modified dates
                pdAuditDetails.Visible = false;
            }

            GatewayId = gateway.Id;

            bool readOnly = false;

            nbEditModeMessage.Text = string.Empty;
            if ( !editAllowed || !IsUserAuthorized( Authorization.EDIT ) )
            {
                readOnly = true;
                nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed( FinancialGateway.FriendlyTypeName );
            }

            if ( readOnly )
            {
                ShowReadonlyDetails( gateway );
            }
            else
            {
                ShowEditDetails( gateway );
            }
        }
        /// <summary>
        /// Shows the detail.
        /// </summary>
        /// <param name="gatewayId">The gateway identifier.</param>
        public void ShowDetail( int gatewayId )
        {
            FinancialGateway gateway = null;

            bool editAllowed = IsUserAuthorized( Authorization.EDIT );

            if ( !gatewayId.Equals( 0 ) )
            {
                gateway = new FinancialGatewayService( new RockContext() ).Get( gatewayId );
                editAllowed = editAllowed || gateway.IsAuthorized( Authorization.EDIT, CurrentPerson );
            }

            if ( gateway == null )
            {
                gateway = new FinancialGateway { Id = 0, IsActive = true };
            }

            GatewayId = gateway.Id;

            bool readOnly = false;

            nbEditModeMessage.Text = string.Empty;
            if ( !editAllowed || !IsUserAuthorized( Authorization.EDIT ) )
            {
                readOnly = true;
                nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed( FinancialGateway.FriendlyTypeName );
            }

            if ( readOnly )
            {
                ShowReadonlyDetails( gateway );
            }
            else
            {
                ShowEditDetails( gateway );
            }
        }
示例#4
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 = "This gateway does not support charging transactions. Transactions should be created through the Reach interface.";
     return(null);
 }
示例#5
0
        /// <summary>
        /// Gets the merchant information.
        /// </summary>
        /// <returns></returns>
        private RequestMessage GetMerchantInfo( FinancialGateway financialGateway, bool includeEnvironment = true )
        {
            if ( financialGateway.Attributes == null )
            {
                financialGateway.LoadAttributes();
            }

            RequestMessage request = new RequestMessage();
            request.merchantID = GetAttributeValue( financialGateway, "MerchantID" );
            request.merchantReferenceCode = Guid.NewGuid().ToString();

            if ( includeEnvironment )
            {
                request.clientLibraryVersion = Environment.Version.ToString();
                request.clientApplication = VersionInfo.GetRockProductVersionFullName();
                request.clientApplicationVersion = VersionInfo.GetRockProductVersionNumber();
                request.clientApplicationUser = GetAttributeValue( financialGateway, "OrganizationName" );
                request.clientEnvironment =
                    Environment.OSVersion.Platform +
                    Environment.OSVersion.Version.ToString() + "-CLR" +
                    Environment.Version.ToString();
            }

            return request;
        }
示例#6
0
        /// <summary>
        /// Creates the saved account.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="paymentDetail">The payment detail.</param>
        /// <param name="financialGateway">The financial gateway.</param>
        /// <param name="person">The person.</param>
        /// <param name="rockContext">The rock context.</param>
        /// <returns></returns>
        private FinancialPersonSavedAccount CreateSavedAccount( PaymentParameters parameters, FinancialPaymentDetail paymentDetail, FinancialGateway financialGateway, Person person, RockContext rockContext)
        {
            var lastFour = paymentDetail.AccountNumberMasked.Substring(paymentDetail.AccountNumberMasked.Length - 4);
            var name = string.Empty;

            if ( parameters.AccountType.ToLower() != "credit" )
            {
                if ( string.IsNullOrWhiteSpace( parameters.RoutingNumber ) )
                {
                    GenerateResponse( HttpStatusCode.BadRequest, "RoutingNumber is required for ACH transactions" );
                    return null;
                }

                if ( string.IsNullOrWhiteSpace( parameters.AccountNumber ) )
                {
                    GenerateResponse( HttpStatusCode.BadRequest, "AccountNumber is required" );
                    return null;
                }

                name = "Bank card ***" + lastFour;
                var bankAccountService = new FinancialPersonBankAccountService( rockContext );
                var accountNumberSecured = FinancialPersonBankAccount.EncodeAccountNumber( parameters.RoutingNumber, parameters.AccountNumber );
                var bankAccount = bankAccountService.Queryable().Where( a =>
                    a.AccountNumberSecured == accountNumberSecured &&
                    a.PersonAliasId == person.PrimaryAliasId.Value ).FirstOrDefault();

                if ( bankAccount == null )
                {
                    bankAccount = new FinancialPersonBankAccount();
                    bankAccount.PersonAliasId = person.PrimaryAliasId.Value;
                    bankAccount.AccountNumberMasked = paymentDetail.AccountNumberMasked;
                    bankAccount.AccountNumberSecured = accountNumberSecured;
                    bankAccountService.Add( bankAccount );
                }
            }
            else
            {
                name = "Credit card ***" + lastFour;
            }

            var savedAccount = new FinancialPersonSavedAccount {
                PersonAliasId = person.PrimaryAliasId,
                FinancialGatewayId = financialGateway.Id,
                Name = name,
                FinancialPaymentDetailId = paymentDetail.Id
            };

            new FinancialPersonSavedAccountService(rockContext).Add( savedAccount );
            rockContext.SaveChanges();
            return savedAccount;
        }
示例#7
0
        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;
        }
示例#8
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);
        }
示例#9
0
文件: Gateway.cs 项目: sjison/Rock
 /// <summary>
 /// Prompts for the person name associated with a bank account.
 /// </summary>
 /// <param name="financialGateway">The financial gateway.</param>
 /// <returns></returns>
 public override bool PromptForBankAccountName(FinancialGateway financialGateway)
 {
     return(true);
 }
示例#10
0
文件: Gateway.cs 项目: sjison/Rock
        /// <summary>
        /// Performs the third step of adding a new payment schedule
        /// </summary>
        /// <param name="financialGateway">The financial gateway.</param>
        /// <param name="resultQueryString">The result query string from step 2.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">tokenId</exception>
        public override FinancialScheduledTransaction AddScheduledPaymentStep3(FinancialGateway financialGateway, string resultQueryString, out string errorMessage)
        {
            errorMessage = string.Empty;

            try
            {
                var rootElement = GetRoot(financialGateway, "complete-action");
                rootElement.Add(new XElement("token-id", resultQueryString.Substring(10)));
                XDocument xdoc   = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"), rootElement);
                var       result = PostToGateway(financialGateway, xdoc);

                if (result == null)
                {
                    errorMessage = "Invalid Response from NMI!";
                    return(null);
                }

                if (result.GetValueOrNull("result") != "1")
                {
                    errorMessage = result.GetValueOrNull("result-text");
                    return(null);
                }

                var scheduledTransaction = new FinancialScheduledTransaction();
                scheduledTransaction.IsActive           = true;
                scheduledTransaction.GatewayScheduleId  = result.GetValueOrNull("subscription-id");
                scheduledTransaction.FinancialGatewayId = financialGateway.Id;

                scheduledTransaction.FinancialPaymentDetail = new FinancialPaymentDetail();
                string ccNumber = result.GetValueOrNull("billing_cc-number");
                if (!string.IsNullOrWhiteSpace(ccNumber))
                {
                    // cc payment
                    var curType = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD);
                    scheduledTransaction.FinancialPaymentDetail.CurrencyTypeValueId   = curType != null ? curType.Id : (int?)null;
                    scheduledTransaction.FinancialPaymentDetail.CreditCardTypeValueId = CreditCardPaymentInfo.GetCreditCardType(ccNumber.Replace('*', '1').AsNumeric())?.Id;
                    scheduledTransaction.FinancialPaymentDetail.AccountNumberMasked   = ccNumber.Masked(true);

                    string mmyy = result.GetValueOrNull("billing_cc-exp");
                    if (!string.IsNullOrWhiteSpace(mmyy) && mmyy.Length == 4)
                    {
                        scheduledTransaction.FinancialPaymentDetail.ExpirationMonthEncrypted = Encryption.EncryptString(mmyy.Substring(0, 2));
                        scheduledTransaction.FinancialPaymentDetail.ExpirationYearEncrypted  = Encryption.EncryptString(mmyy.Substring(2, 2));
                    }
                }
                else
                {
                    // ach payment
                    var curType = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_ACH);
                    scheduledTransaction.FinancialPaymentDetail.CurrencyTypeValueId = curType != null ? curType.Id : (int?)null;
                    scheduledTransaction.FinancialPaymentDetail.AccountNumberMasked = result.GetValueOrNull("billing_account_number").Masked(true);
                }

                GetScheduledPaymentStatus(scheduledTransaction, out errorMessage);

                return(scheduledTransaction);
            }

            catch (WebException webException)
            {
                string message = GetResponseMessage(webException.Response.GetResponseStream());
                errorMessage = webException.Message + " - " + message;
                return(null);
            }

            catch (Exception ex)
            {
                errorMessage = ex.Message;
                return(null);
            }
        }
示例#11
0
        /// <summary>Process all transactions (payments) from Service Reef.</summary>
        /// <param name="message">The message that is returned depending on the result.</param>
        /// <param name="state">The state of the process.</param>
        /// <returns><see cref="WorkerResultStatus"/></returns>
        public void Execute(IJobExecutionContext context)
        {
            RockContext                 dbContext                   = new RockContext();
            FinancialBatchService       financialBatchService       = new FinancialBatchService(dbContext);
            PersonService               personService               = new PersonService(dbContext);
            PersonAliasService          personAliasService          = new PersonAliasService(dbContext);
            FinancialAccountService     financialAccountService     = new FinancialAccountService(dbContext);
            FinancialAccountService     accountService              = new FinancialAccountService(dbContext);
            FinancialTransactionService financialTransactionService = new FinancialTransactionService(dbContext);
            FinancialGatewayService     financialGatewayService     = new FinancialGatewayService(dbContext);
            DefinedValueService         definedValueService         = new DefinedValueService(dbContext);
            DefinedTypeService          definedTypeService          = new DefinedTypeService(dbContext);
            TransactionService          transactionService          = new TransactionService(new PayPalReporting.Data.PayPalReportingContext());

            // Get the datamap for loading attributes
            JobDataMap dataMap = context.JobDetail.JobDataMap;

            String warnings = string.Empty;

            FinancialBatch batch       = null;
            Double         totalAmount = 0;
            var            total       = 1;
            var            processed   = 0;

            try
            {
                DateRange dateRange = Rock.Web.UI.Controls.SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues(dataMap.GetString("DateRange") ?? "-1||");

                String            SRApiKey          = Encryption.DecryptString(dataMap.GetString("ServiceReefAPIKey"));
                String            SRApiSecret       = Encryption.DecryptString(dataMap.GetString("ServiceReefAPISecret"));
                String            SRApiUrl          = dataMap.GetString("ServiceReefAPIURL");
                DefinedValueCache transactionSource = DefinedValueCache.Read(dataMap.GetString("TransactionSource").AsGuid(), dbContext);
                DefinedValueCache connectionStatus  = DefinedValueCache.Read(dataMap.GetString("ConnectionStatus").AsGuid(), dbContext);
                DefinedValueCache contribution      = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION);

                // Setup some lookups
                DefinedTypeCache        creditCards = DefinedTypeCache.Read(Rock.SystemGuid.DefinedType.FINANCIAL_CREDIT_CARD_TYPE.AsGuid(), dbContext);
                DefinedTypeCache        tenderType  = DefinedTypeCache.Get(Rock.SystemGuid.DefinedType.FINANCIAL_CURRENCY_TYPE.AsGuid(), dbContext);
                FinancialAccount        specialFund = accountService.Get(dataMap.GetString("Account").AsGuid());
                FinancialGateway        gateway     = financialGatewayService.Get(dataMap.GetString("FinancialGateway").AsGuid());
                List <FinancialAccount> trips       = financialAccountService.Queryable().Where(fa => fa.ParentAccountId == specialFund.Id).OrderBy(fa => fa.Order).ToList();

                // Get the trips
                DefinedValueCache serviceReefAccountType = DefinedValueCache.Get(dataMap.Get("ServiceReefAccountType").ToString().AsGuid());

                // Setup the ServiceReef API Client
                var client = new RestClient(SRApiUrl);
                client.Authenticator = new HMACAuthenticator(SRApiKey, SRApiSecret);

                // Get all payments from ServiceReef
                var request = new RestRequest("v1/payments", Method.GET);
                request.AddParameter("pageSize", 100);
                if (dateRange.Start.HasValue)
                {
                    request.AddParameter("startDate", dateRange.Start.Value.ToString("o"));
                }
                if (dateRange.End.HasValue)
                {
                    request.AddParameter("endDate", dateRange.End.Value.ToString("o"));
                }
                request.AddParameter("page", 1);

                while (total > processed)
                {
                    var response = client.Execute <Contracts.Payments>(request);
                    if (response.StatusCode != System.Net.HttpStatusCode.OK)
                    {
                        throw new Exception("ServiceReef API Response: " + response.StatusDescription + " Content Length: " + response.ContentLength);
                    }
                    if (response.Data != null && response.Data.PageInfo != null)
                    {
                        total = response.Data.PageInfo.TotalRecords;
                        foreach (Contracts.Payments.Result result in response.Data.Results)
                        {
                            // Process the transaction
                            if (result.PaymentProcessorTransactionId != null)
                            {
                                if (result.FirstName == null || result.LastName == null)
                                {
                                    warnings += "Missing Firstname/Lastname for ServiceReef transaction Id: " + result.TransactionId + Environment.NewLine;
                                    processed++;
                                    continue;
                                }
                                FinancialAccount trip = null;
                                // Make sure we have a sub-account to go with this transaction
                                if (result.EventId > 0)
                                {
                                    trip = trips.Where(t => t.GlCode == result.EventCode && t.Url == result.EventUrl).FirstOrDefault();
                                }
                                if (trip == null)
                                {
                                    if (result.EventCode == null)
                                    {
                                        warnings += "Event Code is missing on the Service Reef Trip for ServiceReef transaction Id: " + result.TransactionId + Environment.NewLine;
                                        processed++;
                                        continue;
                                    }

                                    // Create the trip subaccount
                                    FinancialAccount tripFA = new FinancialAccount();
                                    tripFA.Name = result.EventName;
                                    // Name is limited to 50
                                    if (tripFA.Name.Length > 50)
                                    {
                                        tripFA.Name = tripFA.Name.Substring(0, 50);
                                    }
                                    tripFA.Description = "Service Reef Event.  Name: " + result.EventName + " ID: " + result.EventId;
                                    tripFA.GlCode      = result.EventCode;
                                    tripFA.Url         = result.EventUrl;
                                    tripFA.PublicName  = result.EventName;
                                    // Public Name is limited to 50
                                    if (tripFA.PublicName.Length > 50)
                                    {
                                        tripFA.PublicName = tripFA.PublicName.Substring(0, 50);
                                    }
                                    tripFA.IsTaxDeductible    = true;
                                    tripFA.IsPublic           = false;
                                    tripFA.ParentAccountId    = specialFund.Id;
                                    tripFA.Order              = specialFund.Order + 1;
                                    tripFA.AccountTypeValueId = serviceReefAccountType.Id;
                                    // Figure out what order it should be;
                                    foreach (FinancialAccount tmpTrip in trips)
                                    {
                                        if (tmpTrip.Name.CompareTo(tripFA.Name) < 0)
                                        {
                                            tripFA.Order++;
                                        }
                                    }

                                    financialAccountService.Add(tripFA);

                                    // Now save the trip
                                    dbContext.SaveChanges();
                                    // Increment all the rest of the Orders
                                    financialAccountService.Queryable().Where(fa => fa.Order >= tripFA.Order && fa.Id != tripFA.Id).ToList().ForEach(c => c.Order++);
                                    dbContext.SaveChanges();
                                    trips = financialAccountService.Queryable().Where(fa => fa.ParentAccountId == specialFund.Id).OrderBy(fa => fa.Order).ToList();
                                    trip  = tripFA;
                                }

                                FinancialTransaction tran = financialTransactionService.Queryable().Where(tx => tx.TransactionCode == result.PaymentProcessorTransactionId).FirstOrDefault();

                                // We haven't processed this before so get busy!
                                if (tran == null)
                                {
                                    tran = new FinancialTransaction();
                                    tran.FinancialPaymentDetail = new FinancialPaymentDetail();
                                    if (result.Type == "CreditCard")
                                    {
                                        tran.FinancialPaymentDetail.CurrencyTypeValueId = tenderType.DefinedValues.Where(t => t.Value == "Credit Card").FirstOrDefault().Id;
                                    }
                                    else
                                    {
                                        tran.TransactionTypeValueId = tenderType.DefinedValues.Where(t => t.Value == "Credit Card").FirstOrDefault().Id;
                                    }

                                    Person person = null;
                                    // Find the person this transaction belongs to
                                    // 1. First start by determining whether this was a person
                                    //    paying their application fee or contributing to themselves
                                    //    because then we can just use their member info
                                    if (result.UserId > 0 &&
                                        result.DonatedToUserId == result.UserId &&
                                        result.DonatedToFirstName == result.FirstName &&
                                        result.DonatedToLastName == result.LastName)
                                    {
                                        var memberRequest = new RestRequest("v1/members/{userId}", Method.GET);
                                        memberRequest.AddUrlSegment("userId", result.UserId.ToString());
                                        var memberResult = client.Execute <Contracts.Member>(memberRequest);
                                        if (memberResult.Data != null && memberResult.Data.ArenaId > 0)
                                        {
                                            try
                                            {
                                                Person personMatch = personAliasService.Queryable().Where(pa => pa.AliasPersonId == memberResult.Data.ArenaId).Select(pa => pa.Person).FirstOrDefault();
                                                if (personMatch == null)
                                                {
                                                    throw new Exception("Person not found: " + memberResult.Data.ArenaId);
                                                }
                                                person = personMatch;
                                            } catch (Exception e)
                                            {
                                                warnings += "Loading the person failed transaction id " + result.TransactionId + " for " + result.FirstName + " " + result.LastName + " with the following error: " + e.Message + Environment.NewLine;
                                                processed++;
                                                continue;
                                            }
                                        }
                                    }
                                    // 2. If we didn't get a person match via their Alias Id
                                    //    then just use the standard person match logic
                                    if (person == null)
                                    {
                                        String street1    = null;
                                        String postalCode = null;
                                        if (result.Address != null)
                                        {
                                            street1    = result.Address.Address1;
                                            postalCode = result.Address.Zip;
                                        }
                                        List <Person> matches = personService.GetByMatch(result.FirstName.Trim(), result.LastName.Trim(), null, result.Email, null, street1, postalCode).ToList();

                                        if (matches.Count > 1)
                                        {
                                            // Find the oldest member record in the list
                                            person = matches.Where(p => p.ConnectionStatusValue.Value == "Member").OrderBy(p => p.Id).FirstOrDefault();
                                            if (person == null)
                                            {
                                                // Find the oldest attendee record in the list
                                                person = matches.Where(p => p.ConnectionStatusValue.Value == "Attendee").OrderBy(p => p.Id).FirstOrDefault();
                                                if (person == null)
                                                {
                                                    person = matches.OrderBy(p => p.Id).First();
                                                }
                                            }
                                        }
                                        else if (matches.Count == 1)
                                        {
                                            person = matches.First();
                                        }
                                        else
                                        {
                                            // Create the person
                                            person           = new Person();
                                            person.FirstName = result.FirstName.Trim();
                                            person.LastName  = result.LastName.Trim();
                                            if (result.Email.IsValidEmail())
                                            {
                                                person.Email = result.Email.Trim();
                                            }
                                            person.RecordTypeValueId       = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.PERSON_RECORD_TYPE_PERSON.AsGuid()).Id;
                                            person.ConnectionStatusValueId = connectionStatus.Id;
                                            person.RecordStatusValueId     = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.PERSON_RECORD_STATUS_ACTIVE.AsGuid()).Id;
                                            Group         family   = PersonService.SaveNewPerson(person, dbContext);
                                            GroupLocation location = new GroupLocation();
                                            location.GroupLocationTypeValueId = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.GROUP_LOCATION_TYPE_HOME).Id;
                                            location.Location = new Location()
                                            {
                                                Street1    = result.Address.Address1,
                                                Street2    = result.Address.Address2,
                                                City       = result.Address.City,
                                                State      = result.Address.State,
                                                PostalCode = result.Address.Zip,
                                                Country    = result.Address.Country
                                            };
                                            family.CampusId = CampusCache.All().FirstOrDefault().Id;
                                            family.GroupLocations.Add(location);
                                            dbContext.SaveChanges();
                                        }
                                    }

                                    // Get details about the transaction from our PayPal report table
                                    Transaction tx = transactionService.Get(result.PaymentProcessorTransactionId);
                                    if (tx != null)
                                    {
                                        if (tx.TenderType.Contains("ACH"))
                                        {
                                            result.Type   = "ACH";
                                            result.Method = null;
                                        }
                                        else
                                        {
                                            result.Type   = "Credit Card";
                                            result.Method = tx.TenderType;
                                        }
                                    }
                                    else
                                    {
                                        // Defaults
                                        result.Type   = "Credit Card";
                                        result.Method = "Visa";

                                        warnings += "Unable to find transaction in _org_secc_PaypalReporting_Transaction table: " + result.TransactionId + Environment.NewLine;
                                    }

                                    // If we don't have a batch, create one
                                    if (batch == null)
                                    {
                                        batch = new FinancialBatch();
                                        batch.BatchStartDateTime = result.Date;
                                        batch.BatchEndDateTime   = DateTime.Now;
                                        batch.Name   = "Service Reef Payments";
                                        batch.Status = BatchStatus.Open;
                                        financialBatchService.Add(batch);
                                        dbContext.SaveChanges();
                                    }

                                    // Complete the FinancialTransaction
                                    tran.AuthorizedPersonAliasId = person.PrimaryAliasId;
                                    tran.BatchId             = batch.Id;
                                    tran.Summary             = "F" + specialFund.Id + ":$" + result.Amount.ToString();
                                    tran.TransactionDateTime = result.Date;
                                    tran.FinancialGatewayId  = gateway.Id;

                                    FinancialTransactionDetail financialTransactionDetail = new FinancialTransactionDetail();
                                    financialTransactionDetail.AccountId = trip.Id;
                                    financialTransactionDetail.Amount    = result.Amount.ToString().AsDecimal();
                                    tran.TransactionDetails.Add(financialTransactionDetail);
                                    tran.TransactionTypeValueId = contribution.Id;

                                    tran.FinancialPaymentDetail = new FinancialPaymentDetail();
                                    tran.FinancialPaymentDetail.CurrencyTypeValueId = tenderType.DefinedValues.Where(type => type.Value.ToLower() == result.Type.ToLower()).FirstOrDefault().Id;
                                    if (result.Method != null)
                                    {
                                        tran.FinancialPaymentDetail.CreditCardTypeValueId = creditCards.DefinedValues.Where(card => card.Value.ToLower() == result.Method.ToLower()).FirstOrDefault().Id;
                                    }
                                    tran.TransactionCode   = result.PaymentProcessorTransactionId;
                                    tran.SourceTypeValueId = transactionSource.Id;

                                    financialTransactionService.Add(tran);
                                    dbContext.SaveChanges();

                                    totalAmount += result.Amount;
                                }
                            }
                            processed++;
                        }
                    }
                    else
                    {
                        total = 0;
                    }
                    // Update the page number for the next request
                    var pageParam = request.Parameters.Where(p => p.Name == "page").FirstOrDefault();
                    pageParam.Value = (int)pageParam.Value + 1;
                }
            }
            catch (Exception ex)
            {
                throw new Exception("ServiceReef Job Failed", ex);
            } finally
            {
                if (batch != null && totalAmount > 0)
                {
                    batch.ControlAmount = (Decimal)totalAmount;
                }
                dbContext.SaveChanges();
            }
            if (warnings.Length > 0)
            {
                throw new Exception(warnings);
            }
            context.Result = "Successfully imported " + processed + " transactions.";
        }
示例#12
0
文件: Gateway.cs 项目: sjison/Rock
 /// <summary>
 /// Adds the scheduled payment.
 /// </summary>
 /// <param name="financialGateway">The financial gateway.</param>
 /// <param name="schedule">The schedule.</param>
 /// <param name="paymentInfo">The payment info.</param>
 /// <param name="errorMessage">The error message.</param>
 /// <returns></returns>
 public override FinancialScheduledTransaction AddScheduledPayment(FinancialGateway financialGateway, PaymentSchedule schedule, PaymentInfo paymentInfo, out string errorMessage)
 {
     errorMessage = "The Payment Gateway only supports adding scheduled payment using a three-step process.";
     return(null);
 }
示例#13
0
文件: Gateway.cs 项目: sjison/Rock
        /// <summary>
        /// Performs the first step of adding a new payment schedule
        /// </summary>
        /// <param name="financialGateway">The financial gateway.</param>
        /// <param name="schedule">The schedule.</param>
        /// <param name="paymentInfo">The payment information.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">paymentInfo</exception>
        public override string AddScheduledPaymentStep1(FinancialGateway financialGateway, PaymentSchedule schedule, PaymentInfo paymentInfo, out string errorMessage)
        {
            errorMessage = string.Empty;

            try
            {
                if (paymentInfo == null)
                {
                    throw new ArgumentNullException("paymentInfo");
                }

                var rootElement = GetRoot(financialGateway, "add-subscription");

                rootElement.Add(
                    new XElement("start-date", schedule.StartDate.ToString("yyyyMMdd")),
                    new XElement("order-description", paymentInfo.Description),
                    new XElement("currency", "USD"),
                    new XElement("tax-amount", "0.00"));

                bool isReferencePayment = (paymentInfo is ReferencePaymentInfo);
                if (isReferencePayment)
                {
                    var reference = paymentInfo as ReferencePaymentInfo;
                    rootElement.Add(new XElement("customer-vault-id", reference.ReferenceNumber));
                }

                if (paymentInfo.AdditionalParameters != null)
                {
                    foreach (var keyValue in paymentInfo.AdditionalParameters)
                    {
                        XElement xElement = new XElement(keyValue.Key, keyValue.Value);
                        rootElement.Add(xElement);
                    }
                }

                rootElement.Add(GetPlan(schedule, paymentInfo));

                rootElement.Add(GetBilling(paymentInfo));

                XDocument xdoc   = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"), rootElement);
                var       result = PostToGateway(financialGateway, xdoc);

                if (result == null)
                {
                    errorMessage = "Invalid Response from NMI!";
                    return(null);
                }

                if (result.GetValueOrNull("result") != "1")
                {
                    errorMessage = result.GetValueOrNull("result-text");
                    return(null);
                }

                return(result.GetValueOrNull("form-url"));
            }

            catch (WebException webException)
            {
                string message = GetResponseMessage(webException.Response.GetResponseStream());
                errorMessage = webException.Message + " - " + message;
                return(null);
            }

            catch (Exception ex)
            {
                errorMessage = ex.Message;
                return(null);
            }
        }
示例#14
0
文件: Gateway.cs 项目: sjison/Rock
        /// <summary>
        /// Performs the final step of a three-step charge.
        /// </summary>
        /// <param name="financialGateway">The financial gateway.</param>
        /// <param name="resultQueryString">The result query string from step 2.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialTransaction ChargeStep3(FinancialGateway financialGateway, string resultQueryString, out string errorMessage)
        {
            errorMessage = string.Empty;

            try
            {
                var rootElement = GetRoot(financialGateway, "complete-action");
                rootElement.Add(new XElement("token-id", resultQueryString.Substring(10)));
                XDocument xdoc   = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"), rootElement);
                var       result = PostToGateway(financialGateway, xdoc);

                if (result == null)
                {
                    errorMessage = "Invalid Response from NMI!";
                    return(null);
                }

                if (result.GetValueOrNull("result") != "1")
                {
                    errorMessage = result.GetValueOrNull("result-text");

                    string resultCodeMessage = GetResultCodeMessage(result);
                    if (resultCodeMessage.IsNotNullOrWhitespace())
                    {
                        errorMessage += string.Format(" ({0})", resultCodeMessage);
                    }

                    // write result error as an exception
                    ExceptionLogService.LogException(new Exception($"Error processing NMI transaction. Result Code:  {result.GetValueOrNull( "result-code" )} ({resultCodeMessage}). Result text: {result.GetValueOrNull( "result-text" )}. Card Holder Name: {result.GetValueOrNull( "first-name" )} {result.GetValueOrNull( "last-name" )}. Amount: {result.GetValueOrNull( "total-amount" )}. Transaction id: {result.GetValueOrNull( "transaction-id" )}. Descriptor: {result.GetValueOrNull( "descriptor" )}. Order description: {result.GetValueOrNull( "order-description" )}."));

                    return(null);
                }

                var transaction = new FinancialTransaction();
                transaction.TransactionCode        = result.GetValueOrNull("transaction-id");
                transaction.ForeignKey             = result.GetValueOrNull("customer-vault-id");
                transaction.FinancialPaymentDetail = new FinancialPaymentDetail();

                string ccNumber = result.GetValueOrNull("billing_cc-number");
                if (!string.IsNullOrWhiteSpace(ccNumber))
                {
                    // cc payment
                    var curType = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD);
                    transaction.FinancialPaymentDetail.NameOnCardEncrypted   = Encryption.EncryptString($"{result.GetValueOrNull( "billing_first-name" )} {result.GetValueOrNull( "billing_last-name" )}");
                    transaction.FinancialPaymentDetail.CurrencyTypeValueId   = curType != null ? curType.Id : (int?)null;
                    transaction.FinancialPaymentDetail.CreditCardTypeValueId = CreditCardPaymentInfo.GetCreditCardType(ccNumber.Replace('*', '1').AsNumeric())?.Id;
                    transaction.FinancialPaymentDetail.AccountNumberMasked   = ccNumber.Masked(true);

                    string mmyy = result.GetValueOrNull("billing_cc-exp");
                    if (!string.IsNullOrWhiteSpace(mmyy) && mmyy.Length == 4)
                    {
                        transaction.FinancialPaymentDetail.ExpirationMonthEncrypted = Encryption.EncryptString(mmyy.Substring(0, 2));
                        transaction.FinancialPaymentDetail.ExpirationYearEncrypted  = Encryption.EncryptString(mmyy.Substring(2, 2));
                    }
                }
                else
                {
                    // ach payment
                    var curType = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_ACH);
                    transaction.FinancialPaymentDetail.CurrencyTypeValueId = curType != null ? curType.Id : (int?)null;
                    transaction.FinancialPaymentDetail.AccountNumberMasked = result.GetValueOrNull("billing_account-number").Masked(true);
                }

                transaction.AdditionalLavaFields = new Dictionary <string, object>();
                foreach (var keyVal in result)
                {
                    transaction.AdditionalLavaFields.Add(keyVal.Key, keyVal.Value);
                }

                return(transaction);
            }

            catch (WebException webException)
            {
                string message = GetResponseMessage(webException.Response.GetResponseStream());
                errorMessage = webException.Message + " - " + message;
                return(null);
            }

            catch (Exception ex)
            {
                errorMessage = ex.Message;
                return(null);
            }
        }
示例#15
0
文件: Gateway.cs 项目: sjison/Rock
 /// <summary>
 /// Charges the specified payment info.
 /// </summary>
 /// <param name="financialGateway">The financial gateway.</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 = "The Payment Gateway only supports a three-step charge.";
     return(null);
 }
示例#16
0
文件: Gateway.cs 项目: sjison/Rock
 /// <summary>
 /// Gets a value indicating whether [address required].
 /// </summary>
 /// <value>
 /// <c>true</c> if [address required]; otherwise, <c>false</c>.
 /// </value>
 public override bool PromptForBillingAddress(FinancialGateway financialGateway)
 {
     return(GetAttributeValue(financialGateway, "PromptForAddress").AsBoolean());
 }
示例#17
0
        /// <summary>
        /// Gets the proxy client.
        /// </summary>
        /// <param name="financialGateway">The financial gateway.</param>
        /// <returns></returns>
        private TransactionProcessorClient GetProxyClient( FinancialGateway financialGateway, out string errorMessage )
        {
            errorMessage = string.Empty;
            string merchantID = GetAttributeValue( financialGateway, "MerchantID" );
            string transactionkey = GetAttributeValue( financialGateway, "TransactionKey" );

            string gatewayEndpoint = null;
            if ( GetAttributeValue( financialGateway, "Mode" ).Equals( "Live", StringComparison.CurrentCultureIgnoreCase ) )
            {
                gatewayEndpoint = GetAttributeValue( financialGateway, "LiveGatewayURL" );
            }
            else
            {
                gatewayEndpoint = GetAttributeValue( financialGateway, "TestGatewayURL" );
            }

            EndpointAddress address = null;
            if ( !string.IsNullOrEmpty( gatewayEndpoint ) )
            {
                gatewayEndpoint = gatewayEndpoint.EnsureTrailingForwardslash();
                address = new EndpointAddress( string.Format( "{0}CyberSourceTransaction_{1}", gatewayEndpoint, GATEWAY_VERSION ) );
            }
            else
            {
                errorMessage = "Financial gateway is not configured with a valid endpoint.";
                return null;
            }

            BasicHttpBinding binding = new BasicHttpBinding();
            binding.Name = "ITransactionProcessor";
            binding.MaxBufferSize = 2147483647;
            binding.MaxBufferPoolSize = 2147483647;
            binding.MaxReceivedMessageSize = 2147483647;
            binding.ReaderQuotas.MaxDepth = 2147483647;
            binding.ReaderQuotas.MaxArrayLength = 2147483647;
            binding.ReaderQuotas.MaxBytesPerRead = 2147483647;
            binding.ReaderQuotas.MaxStringContentLength = 2147483647;
            binding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential;

            var proxy = new TransactionProcessorClient( binding, address );
            proxy.ClientCredentials.UserName.UserName = merchantID;
            proxy.ClientCredentials.UserName.Password = transactionkey;
            proxy.Endpoint.Address = address;
            proxy.Endpoint.Binding = binding;
            return proxy;
        }
示例#18
0
文件: Gateway.cs 项目: sjison/Rock
        /// <summary>
        /// Gets the payments that have been processed for any scheduled transactions
        /// </summary>
        /// <param name="financialGateway">The financial gateway.</param>
        /// <param name="startDate">The start date.</param>
        /// <param name="endDate">The end date.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override List <Payment> GetPayments(FinancialGateway financialGateway, DateTime startDate, DateTime endDate, out string errorMessage)
        {
            errorMessage = string.Empty;

            var txns = new List <Payment>();

            var restClient  = new RestClient(GetAttributeValue(financialGateway, "QueryUrl"));
            var restRequest = new RestRequest(Method.GET);

            restRequest.AddParameter("username", GetAttributeValue(financialGateway, "AdminUsername"));
            restRequest.AddParameter("password", GetAttributeValue(financialGateway, "AdminPassword"));
            restRequest.AddParameter("start_date", startDate.ToString("yyyyMMddHHmmss"));
            restRequest.AddParameter("end_date", endDate.ToString("yyyyMMddHHmmss"));

            try
            {
                var response = restClient.Execute(restRequest);
                if (response != null)
                {
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        var xdocResult = GetXmlResponse(response);
                        if (xdocResult != null)
                        {
                            var errorResponse = xdocResult.Root.Element("error_response");
                            if (errorResponse != null)
                            {
                                errorMessage = errorResponse.Value;
                            }
                            else
                            {
                                foreach (var xTxn in xdocResult.Root.Elements("transaction"))
                                {
                                    Payment payment = new Payment();
                                    payment.TransactionCode = GetXElementValue(xTxn, "transaction_id");
                                    payment.Status          = GetXElementValue(xTxn, "condition").FixCase();
                                    payment.IsFailure       =
                                        payment.Status == "Failed" ||
                                        payment.Status == "Abandoned" ||
                                        payment.Status == "Canceled";
                                    payment.TransactionCode   = GetXElementValue(xTxn, "transaction_id");
                                    payment.GatewayScheduleId = GetXElementValue(xTxn, "original_transaction_id").Trim();

                                    var      statusMessage = new StringBuilder();
                                    DateTime?txnDateTime   = null;

                                    foreach (var xAction in xTxn.Elements("action"))
                                    {
                                        DateTime?actionDate   = ParseDateValue(GetXElementValue(xAction, "date"));
                                        string   actionType   = GetXElementValue(xAction, "action_type");
                                        string   responseText = GetXElementValue(xAction, "response_text");

                                        if (actionDate.HasValue)
                                        {
                                            statusMessage.AppendFormat("{0} {1}: {2}; Status: {3}",
                                                                       actionDate.Value.ToShortDateString(), actionDate.Value.ToShortTimeString(),
                                                                       actionType.FixCase(), responseText);
                                            statusMessage.AppendLine();
                                        }

                                        decimal?txnAmount = GetXElementValue(xAction, "amount").AsDecimalOrNull();
                                        if (txnAmount.HasValue && actionDate.HasValue)
                                        {
                                            payment.Amount = txnAmount.Value;
                                        }

                                        if (actionType == "sale")
                                        {
                                            txnDateTime = actionDate.Value;
                                        }

                                        if (actionType == "settle")
                                        {
                                            payment.IsSettled      = true;
                                            payment.SettledGroupId = GetXElementValue(xAction, "processor_batch_id").Trim();
                                            payment.SettledDate    = actionDate;
                                            txnDateTime            = txnDateTime.HasValue ? txnDateTime.Value : actionDate.Value;
                                        }
                                    }

                                    if (txnDateTime.HasValue)
                                    {
                                        payment.TransactionDateTime = txnDateTime.Value;
                                        payment.StatusMessage       = statusMessage.ToString();
                                        txns.Add(payment);
                                    }
                                }
                            }
                        }
                        else
                        {
                            errorMessage = "Invalid XML Document Returned From Gateway!";
                        }
                    }
                    else
                    {
                        errorMessage = string.Format("Invalid Response from Gateway: [{0}] {1}", response.StatusCode.ConvertToString(), response.ErrorMessage);
                    }
                }
                else
                {
                    errorMessage = "Null Response From Gateway!";
                }
            }
            catch (WebException webException)
            {
                string message = GetResponseMessage(webException.Response.GetResponseStream());
                throw new Exception(webException.Message + " - " + message);
            }

            return(txns);
        }
示例#19
0
        /// <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());
            }
        }
示例#20
0
文件: Gateway.cs 项目: sjison/Rock
 /// <summary>
 /// Gets a value indicating whether the gateway requires the name on card for CC processing
 /// </summary>
 /// <value>
 /// <c>true</c> if [name on card required]; otherwise, <c>false</c>.
 /// </value>
 public override bool PromptForNameOnCard(FinancialGateway financialGateway)
 {
     return(GetAttributeValue(financialGateway, "PromptForName").AsBoolean());
 }
示例#21
0
 /// <summary>
 /// Gets a value indicating whether [address required].
 /// </summary>
 /// <param name="financialGateway">The financial gateway.</param>
 /// <returns></returns>
 /// <value>
 ///   <c>true</c> if [address required]; otherwise, <c>false</c>.
 /// </value>
 public override bool PromptForBillingAddress(FinancialGateway financialGateway)
 {
     return(false);
 }
示例#22
0
        /// <summary>
        /// Process the data read from the card reader and generate the transaction.
        /// </summary>
        /// <param name="swipeData">The data read from the card.</param>
        private void ProcessSwipe(string swipeData)
        {
            try
            {
                using (var rockContext = new RockContext())
                {
                    // create swipe object
                    SwipePaymentInfo swipeInfo = new SwipePaymentInfo(swipeData);
                    swipeInfo.Amount = tbAmount.Text.AsDecimal();

                    // add comment to the transation
                    swipeInfo.Comment1 = PageParameter("Memo");

                    // get gateway
                    FinancialGateway financialGateway = null;
                    GatewayComponent gateway          = null;
                    Guid?            gatewayGuid      = GetAttributeValue("CreditCardGateway").AsGuidOrNull();
                    if (gatewayGuid.HasValue)
                    {
                        financialGateway = new FinancialGatewayService(rockContext).Get(gatewayGuid.Value);

                        if (financialGateway != null)
                        {
                            financialGateway.LoadAttributes(rockContext);
                        }

                        gateway = financialGateway.GetGatewayComponent();
                    }

                    if (gateway == null)
                    {
                        lSwipeErrors.Text = "<div class='alert alert-danger'>Invalid gateway provided. Please provide a gateway. Transaction not processed.</div>";
                        return;
                    }

                    //
                    // Process the transaction.
                    //
                    string errorMessage = string.Empty;
                    var    transaction  = gateway.Charge(financialGateway, swipeInfo, out errorMessage);

                    if (transaction == null)
                    {
                        lSwipeErrors.Text = String.Format("<div class='alert alert-danger'>An error occurred while process this transaction. Message: {0}</div>", errorMessage);
                        return;
                    }

                    _transactionCode = transaction.TransactionCode;

                    //
                    // Set some common information about the transaction.
                    //
                    transaction.AuthorizedPersonAliasId = new PersonService(rockContext).Get(SelectedPersonGuid).PrimaryAliasId;
                    transaction.TransactionDateTime     = RockDateTime.Now;
                    transaction.FinancialGatewayId      = financialGateway.Id;
                    transaction.TransactionTypeValueId  = DefinedValueCache.Read(GetAttributeValue("TransactionType")).Id;
                    transaction.SourceTypeValueId       = DefinedValueCache.Read(GetAttributeValue("Source")).Id;
                    transaction.Summary = swipeInfo.Comment1;

                    //
                    // Ensure we have payment details.
                    //
                    if (transaction.FinancialPaymentDetail == null)
                    {
                        transaction.FinancialPaymentDetail = new FinancialPaymentDetail();
                    }
                    transaction.FinancialPaymentDetail.SetFromPaymentInfo(swipeInfo, gateway, rockContext);

                    var transactionDetail = new FinancialTransactionDetail();
                    transactionDetail.Amount    = swipeInfo.Amount;
                    transactionDetail.AccountId = new FinancialAccountService(rockContext).Get(GetAttributeValue("Account").AsGuid()).Id;
                    transaction.TransactionDetails.Add(transactionDetail);

                    var batchService = new FinancialBatchService(rockContext);

                    // Get the batch
                    var batch = batchService.Get(
                        GetAttributeValue("BatchNamePrefix"),
                        swipeInfo.CurrencyTypeValue,
                        swipeInfo.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.WrapTransaction(() =>
                    {
                        rockContext.SaveChanges();

                        HistoryService.SaveChanges(
                            rockContext,
                            typeof(FinancialBatch),
                            Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(),
                            batch.Id,
                            batchChanges
                            );
                    });

                    ShowReceiptPanel();
                }
            }
            catch (Exception ex)
            {
                lSwipeErrors.Text = String.Format("<div class='alert alert-danger'>An error occurred while process this transaction. Message: {0}</div>", ex.Message);
            }
        }
示例#23
0
        /// <summary>
        /// Gets the payments that have been processed for any scheduled transactions
        /// </summary>
        /// <param name="financialGateway"></param>
        /// <param name="startDate">The start date.</param>
        /// <param name="endDate">The end date.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override List <Payment> GetPayments(FinancialGateway financialGateway, DateTime startDate, DateTime endDate, out string errorMessage)
        {
            var reportingApi = new Reporting.Api(
                GetAttributeValue(financialGateway, "User"),
                GetAttributeValue(financialGateway, "Vendor"),
                GetAttributeValue(financialGateway, "Partner"),
                GetAttributeValue(financialGateway, "Password"),
                GetAttributeValue(financialGateway, "Mode").Equals("Test", StringComparison.CurrentCultureIgnoreCase));

            // Query the PayFlowPro Recurring Billing Report for transactions that were processed during data range
            var recurringBillingParams = new Dictionary <string, string>();

            recurringBillingParams.Add("start_date", startDate.ToString("yyyy-MM-dd HH:mm:ss"));
            recurringBillingParams.Add("end_date", endDate.ToString("yyyy-MM-dd HH:mm:ss"));
            recurringBillingParams.Add("include_declines", "false");
            DataTable recurringBillingTable = reportingApi.GetReport("RecurringBillingReport", recurringBillingParams, out errorMessage);

            if (recurringBillingTable != null)
            {
                // The Recurring Billing Report items does not include the amounts for each transaction, so need
                // to run a custom report to try and get the amount/tender type for each transaction
                var transactionCodes = new Dictionary <string, int>();
                var customParams     = new Dictionary <string, string>();
                customParams.Add("start_date", startDate.ToString("yyyy-MM-dd HH:mm:ss"));
                customParams.Add("end_date", endDate.ToString("yyyy-MM-dd HH:mm:ss"));
                customParams.Add("maximum_amount", "1000000");
                customParams.Add("results", "Approvals Only");
                customParams.Add("recurring_only", "true");
                customParams.Add("show_order_id", "false");
                customParams.Add("show_transaction_id", "true");
                customParams.Add("show_time", "false");
                customParams.Add("show_type", "false");
                customParams.Add("show_tender_type", "true");
                customParams.Add("show_account_number", "false");
                customParams.Add("show_expires", "false");
                customParams.Add("show_aba_routing_number", "false");
                customParams.Add("show_amount", "true");
                customParams.Add("show_result_code", "true");
                customParams.Add("show_response_msg", "false");
                customParams.Add("show_comment1", "false");
                customParams.Add("show_comment2", "false");
                customParams.Add("show_tax_amount", "false");
                customParams.Add("show_purchase_order", "false");
                customParams.Add("show_original_transaction_id", "false");
                customParams.Add("show_avs_street_match", "false");
                customParams.Add("show_avs_zip_match", "false");
                customParams.Add("show_invoice_number", "false");
                customParams.Add("show_authcode", "false");
                customParams.Add("show_batch_id", "false");
                customParams.Add("show_csc_match", "false");
                customParams.Add("show_billing_first_name", "false");
                customParams.Add("show_billing_last_name", "false");
                customParams.Add("show_billing_company_name", "false");
                customParams.Add("show_billing_address", "false");
                customParams.Add("show_billing_city", "false");
                customParams.Add("show_billing_state", "false");
                customParams.Add("show_billing_zip", "false");
                customParams.Add("show_billing_email", "false");
                customParams.Add("show_billing_country", "false");
                customParams.Add("show_shipping_first_name", "false");
                customParams.Add("show_shipping_last_name", "false");
                customParams.Add("show_shipping_address", "false");
                customParams.Add("show_shipping_city", "false");
                customParams.Add("show_shipping_state", "false");
                customParams.Add("show_shipping_zip", "false");
                customParams.Add("show_shipping_country", "false");
                customParams.Add("show_customer_code", "false");
                customParams.Add("show_freight_amount", "false");
                customParams.Add("show_duty_amount", "false");
                DataTable customTable = reportingApi.GetReport("CustomReport", customParams, out errorMessage);
                if (customTable != null)
                {
                    for (int i = 0; i < customTable.Rows.Count; i++)
                    {
                        transactionCodes.Add(customTable.Rows[i]["Transaction Id"].ToString().Trim(), i);
                    }
                }

                var txns = new List <Payment>();

                var transactionIdParams = new Dictionary <string, string>();
                transactionIdParams.Add("transaction_id", string.Empty);

                var creditCardTypes = DefinedTypeCache.Get(Rock.SystemGuid.DefinedType.FINANCIAL_CREDIT_CARD_TYPE.AsGuid()).DefinedValues;

                foreach (DataRow recurringBillingRow in recurringBillingTable.Rows)
                {
                    bool    foundTxn      = false;
                    string  transactionId = recurringBillingRow["Transaction ID"].ToString().Trim();
                    decimal amount        = decimal.MinValue;
                    string  tenderType    = string.Empty;

                    if (transactionCodes.ContainsKey(transactionId))
                    {
                        int rowNumber = transactionCodes[transactionId];
                        amount     = decimal.TryParse(customTable.Rows[rowNumber]["Amount"].ToString(), out amount) ? (amount / 100) : 0.0M;
                        tenderType = customTable.Rows[rowNumber]["Tender Type"].ToString();
                        foundTxn   = true;
                    }
                    else
                    {
                        // If the custom report did not include the transaction, run a transactionIDSearch report to get the amount and tender type
                        transactionIdParams["transaction_id"] = transactionId;
                        DataTable transactionIdTable = reportingApi.GetSearch("TransactionIDSearch", transactionIdParams, out errorMessage);
                        if (transactionIdTable != null && transactionIdTable.Rows.Count == 1)
                        {
                            amount     = decimal.TryParse(transactionIdTable.Rows[0]["Amount"].ToString(), out amount) ? (amount / 100) : 0.0M;
                            tenderType = transactionIdTable.Rows[0]["Tender Type"].ToString();
                            foundTxn   = true;
                        }
                    }

                    if (foundTxn)
                    {
                        var payment = new Payment();
                        payment.Amount = amount;
                        payment.TransactionDateTime = recurringBillingRow["Time"].ToString().AsDateTime() ?? DateTime.MinValue;
                        payment.TransactionCode     = recurringBillingRow["Transaction ID"].ToString().Trim();
                        payment.GatewayScheduleId   = recurringBillingRow["Profile ID"].ToString();
                        payment.ScheduleActive      = recurringBillingRow["Status"].ToString() == "Active";
                        payment.CreditCardTypeValue = creditCardTypes.Where(t => t.Value == tenderType).FirstOrDefault();
                        txns.Add(payment);
                    }
                    else
                    {
                        errorMessage = "The TransactionIDSearch report did not return a value for transaction: " + recurringBillingRow["Transaction ID"].ToString();
                        return(null);
                    }
                }

                return(txns);
            }

            errorMessage = "The RecurringBillingReport report did not return any data";
            return(null);
        }
示例#24
0
        private void SaveTransaction(FinancialGateway financialGateway, GatewayComponent gateway, Person person, PaymentInfo paymentInfo, FinancialTransaction transaction, RockContext rockContext)
        {
            transaction.AuthorizedPersonAliasId = person.PrimaryAliasId;
            if (RockTransactionEntry != null)
            {
                RockCheckBox cbGiveAnonymouslyControl = (( RockCheckBox )(RockTransactionEntry.FindControl("cbGiveAnonymously")));
                if (cbGiveAnonymouslyControl != null)
                {
                    transaction.ShowAsAnonymous = cbGiveAnonymouslyControl.Checked;
                }
            }
            transaction.TransactionDateTime = RockDateTime.Now;
            transaction.FinancialGatewayId  = financialGateway.Id;

            var txnType = DefinedValueCache.Get(this.GetAttributeValue("TransactionType").AsGuidOrNull() ?? Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid());

            transaction.TransactionTypeValueId = txnType.Id;

            transaction.Summary = paymentInfo.Comment1;

            if (transaction.FinancialPaymentDetail == null)
            {
                transaction.FinancialPaymentDetail = new FinancialPaymentDetail();
            }
            transaction.FinancialPaymentDetail.SetFromPaymentInfo(paymentInfo, gateway, rockContext);

            Guid sourceGuid = Guid.Empty;

            if (Guid.TryParse(GetAttributeValue("Source"), out sourceGuid))
            {
                var source = DefinedValueCache.Get(sourceGuid);
                if (source != null)
                {
                    transaction.SourceTypeValueId = source.Id;
                }
            }

            var transactionEntity = this.GetTransactionEntity();

            foreach (var account in GetSelectedAccounts().Where(a => a.Amount > 0))
            {
                var transactionDetail = new FinancialTransactionDetail();
                transactionDetail.Amount    = account.Amount;
                transactionDetail.AccountId = account.Id;
                if (transactionEntity != null)
                {
                    transactionDetail.EntityTypeId = transactionEntity.TypeId;
                    transactionDetail.EntityId     = transactionEntity.Id;
                }

                transaction.TransactionDetails.Add(transactionDetail);
            }

            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 History.HistoryChangeList();

            if (batch.Id == 0)
            {
                batchChanges.AddCustom("Add", "Record", "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;
            transaction.LoadAttributes(rockContext);

            var allowedTransactionAttributes = GetAttributeValue("AllowedTransactionAttributesFromURL").Split(',').AsGuidList().Select(x => AttributeCache.Get(x).Key);

            foreach (KeyValuePair <string, AttributeValueCache> attr in transaction.AttributeValues)
            {
                if (PageParameters().ContainsKey("Attribute_" + attr.Key) && allowedTransactionAttributes.Contains(attr.Key))
                {
                    attr.Value.Value = Server.UrlDecode(PageParameter("Attribute_" + attr.Key));
                }
            }

            batch.Transactions.Add(transaction);

            rockContext.SaveChanges();
            transaction.SaveAttributeValues();

            HistoryService.SaveChanges(
                rockContext,
                typeof(FinancialBatch),
                Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(),
                batch.Id,
                batchChanges
                );

            SendReceipt(transaction.Id);

            TransactionCode = transaction.TransactionCode;
        }
示例#25
0
        /// <summary>
        /// Shows the readonly details.
        /// </summary>
        /// <param name="gateway">The gateway.</param>
        private void ShowReadonlyDetails( FinancialGateway gateway )
        {
            SetEditMode( false );

            lActionTitle.Text = gateway.Name.FormatAsHtmlTitle();
            hlInactive.Visible = !gateway.IsActive;
            lGatewayDescription.Text = gateway.Description;

            DescriptionList descriptionList = new DescriptionList();

            if ( gateway.EntityType != null )
            {
                descriptionList.Add( "Gateway Type", gateway.EntityType.Name );
            }

            var timeSpan = gateway.GetBatchTimeOffset();
            if ( timeSpan.Ticks > 0 )
            {
                descriptionList.Add( "Batch Time Offset", timeSpan.ToString() );
            }

            lblMainDetails.Text = descriptionList.Html;
        }
示例#26
0
 /// <summary>
 /// Adds the scheduled payment.
 /// </summary>
 /// <param name="financialGateway"></param>
 /// <param name="schedule">The schedule.</param>
 /// <param name="paymentInfo">The payment info.</param>
 /// <param name="errorMessage">The error message.</param>
 /// <returns></returns>
 public override FinancialScheduledTransaction AddScheduledPayment(FinancialGateway financialGateway, PaymentSchedule schedule, PaymentInfo paymentInfo, out string errorMessage)
 {
     errorMessage = "This gateway does not support adding scheduled transactions. Transactions should be created through the Reach interface.";
     return(null);
 }
        /// <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( FinancialGateway 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 initialControlAmounts = new Dictionary<Guid, decimal>();

            var allBatchChanges = new Dictionary<Guid, List<string>>();
            var allTxnChanges = new Dictionary<Guid, List<string>>();
            var txnPersonNames = new Dictionary<Guid, string>();

            using ( 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 contributionTxnType = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid() );

                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();

                var batchTxnChanges = new Dictionary<Guid, List<string>>();
                var batchBatchChanges = new Dictionary<Guid, List<string>>();

                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 txnChanges = new List<string>();

                            var transaction = new FinancialTransaction();
                            transaction.FinancialPaymentDetail = new FinancialPaymentDetail();

                            transaction.Guid = Guid.NewGuid();
                            allTxnChanges.Add( transaction.Guid, txnChanges );
                            txnChanges.Add( "Created Transaction (Downloaded from Gateway)" );

                            transaction.TransactionCode = payment.TransactionCode;
                            History.EvaluateChange( txnChanges, "Transaction Code", string.Empty, transaction.TransactionCode );

                            transaction.TransactionDateTime = payment.TransactionDateTime;
                            History.EvaluateChange( txnChanges, "Date/Time", null, transaction.TransactionDateTime );

                            transaction.ScheduledTransactionId = scheduledTransaction.Id;

                            transaction.AuthorizedPersonAliasId = scheduledTransaction.AuthorizedPersonAliasId;
                            History.EvaluateChange( txnChanges, "Person", string.Empty, scheduledTransaction.AuthorizedPersonAlias.Person.FullName );
                            txnPersonNames.Add( transaction.Guid, scheduledTransaction.AuthorizedPersonAlias.Person.FullName );

                            transaction.FinancialGatewayId = gateway.Id;
                            History.EvaluateChange( txnChanges, "Gateway", string.Empty, gateway.Name );

                            transaction.TransactionTypeValueId = contributionTxnType.Id;
                            History.EvaluateChange( txnChanges, "Type", string.Empty, contributionTxnType.Value );

                            var currencyTypeValue = payment.CurrencyTypeValue;
                            var creditCardTypevalue = payment.CreditCardTypeValue;

                            if ( scheduledTransaction.FinancialPaymentDetail != null )
                            {
                                if ( currencyTypeValue == null && scheduledTransaction.FinancialPaymentDetail.CurrencyTypeValueId.HasValue )
                                {
                                    currencyTypeValue = DefinedValueCache.Read( scheduledTransaction.FinancialPaymentDetail.CurrencyTypeValueId.Value );
                                }

                                if ( creditCardTypevalue == null && scheduledTransaction.FinancialPaymentDetail.CreditCardTypeValueId.HasValue )
                                {
                                    creditCardTypevalue = DefinedValueCache.Read( scheduledTransaction.FinancialPaymentDetail.CreditCardTypeValueId.Value );
                                }

                                transaction.FinancialPaymentDetail.AccountNumberMasked = scheduledTransaction.FinancialPaymentDetail.AccountNumberMasked;
                                transaction.FinancialPaymentDetail.NameOnCardEncrypted = scheduledTransaction.FinancialPaymentDetail.NameOnCardEncrypted;
                                transaction.FinancialPaymentDetail.ExpirationMonthEncrypted = scheduledTransaction.FinancialPaymentDetail.ExpirationMonthEncrypted;
                                transaction.FinancialPaymentDetail.ExpirationYearEncrypted = scheduledTransaction.FinancialPaymentDetail.ExpirationYearEncrypted;
                            }

                            if ( currencyTypeValue != null )
                            {
                                transaction.FinancialPaymentDetail.CurrencyTypeValueId = currencyTypeValue.Id;
                                History.EvaluateChange( txnChanges, "Currency Type", string.Empty, currencyTypeValue.Value );
                            }
                            if ( creditCardTypevalue != null )
                            {
                                transaction.FinancialPaymentDetail.CreditCardTypeValueId = creditCardTypevalue.Id;
                                History.EvaluateChange( txnChanges, "Credit Card Type", string.Empty, creditCardTypevalue.Value );
                            }

                            //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 );

                                History.EvaluateChange( txnChanges, detail.Account.Name, 0.0M.ToString( "C2" ), transactionDetail.Amount.ToString( "C2" ) );
                                History.EvaluateChange( txnChanges, "Summary", string.Empty, transactionDetail.Summary );

                                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.";
                                }

                                History.EvaluateChange( txnChanges, defaultAccount.Name, 0.0M.ToString( "C2" ), transactionDetail.Amount.ToString( "C2" ) );
                                History.EvaluateChange( txnChanges, "Summary", string.Empty, transactionDetail.Summary );
                            }

                            // Get the batch
                            var batch = batchService.Get(
                                batchNamePrefix,
                                currencyTypeValue,
                                creditCardTypevalue,
                                transaction.TransactionDateTime.Value,
                                gateway.GetBatchTimeOffset(),
                                batches );

                            var batchChanges = new List<string>();
                            if ( batch.Id != 0 )
                            {
                                initialControlAmounts.AddOrIgnore( batch.Guid, batch.ControlAmount );
                            }
                            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++;
                    }
                }

                foreach ( var batch in batches )
                {
                    var batchChanges = new List<string>();
                    allBatchChanges.Add( batch.Guid, batchChanges );

                    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 );
                    }

                    if ( initialControlAmounts.ContainsKey( batch.Guid ) )
                    {
                        History.EvaluateChange( batchChanges, "Control Amount", initialControlAmounts[batch.Guid].ToString( "C2" ), batch.ControlAmount.ToString( "C2" ) );
                    }
                }

                rockContext.WrapTransaction( () =>
                {
                    rockContext.SaveChanges();

                    foreach ( var batch in batches )
                    {
                        HistoryService.SaveChanges(
                            rockContext,
                            typeof( FinancialBatch ),
                            Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(),
                            batch.Id,
                            allBatchChanges[batch.Guid]
                        );

                        foreach ( var transaction in batch.Transactions )
                        {
                            if ( allTxnChanges.ContainsKey( transaction.Guid ) )
                            {
                                HistoryService.SaveChanges(
                                    rockContext,
                                    typeof( FinancialBatch ),
                                    Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(),
                                    batch.Id,
                                    allTxnChanges[transaction.Guid],
                                    txnPersonNames[transaction.Guid],
                                    typeof( FinancialTransaction ),
                                    transaction.Id
                                );
                            }
                        }
                    }

                    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();
        }
示例#28
0
 /// <summary>
 /// Performs the first step of a three-step charge
 /// </summary>
 /// <param name="financialGateway">The financial gateway.</param>
 /// <param name="paymentInfo">The payment information.</param>
 /// <param name="errorMessage">The error message.</param>
 /// <returns></returns>
 public abstract string ChargeStep1(FinancialGateway financialGateway, PaymentInfo paymentInfo, out string errorMessage);
示例#29
0
        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;
                }
            }
        }
示例#30
0
 /// <summary>
 /// Performs the final step of a three-step charge.
 /// </summary>
 /// <param name="financialGateway">The financial gateway.</param>
 /// <param name="resultQueryString">The result query string from step 2.</param>
 /// <param name="errorMessage">The error message.</param>
 /// <returns></returns>
 public abstract FinancialTransaction ChargeStep3(FinancialGateway financialGateway, string resultQueryString, out string errorMessage);
示例#31
0
 /// <summary>
 /// Gets a value indicating whether the gateway requires the name on card for CC processing
 /// </summary>
 /// <value>
 /// <c>true</c> if [name on card required]; otherwise, <c>false</c>.
 /// </value>
 public override bool PromptForNameOnCard( FinancialGateway financialGateway )
 {
     return GetAttributeValue( financialGateway, "PromptForName" ).AsBoolean();
 }
示例#32
0
 /// <summary>
 /// Performs the first step of adding a new payment schedule
 /// </summary>
 /// <param name="financialGateway">The financial gateway.</param>
 /// <param name="schedule">The schedule.</param>
 /// <param name="paymentInfo">The payment information.</param>
 /// <param name="errorMessage">The error message.</param>
 /// <returns></returns>
 public abstract string AddScheduledPaymentStep1(FinancialGateway financialGateway, PaymentSchedule schedule, PaymentInfo paymentInfo, out string errorMessage);
示例#33
0
        /// <summary>
        /// Gets the payment information.
        /// </summary>
        /// <returns></returns>
        private RequestMessage GetPaymentInfo( FinancialGateway financialGateway, PaymentInfo paymentInfo )
        {
            RequestMessage request = GetMerchantInfo( financialGateway );

            if ( paymentInfo is CreditCardPaymentInfo )
            {
                var cc = paymentInfo as CreditCardPaymentInfo;
                request.card = GetCard( cc );
            }
            else if ( paymentInfo is ACHPaymentInfo )
            {
                var ach = paymentInfo as ACHPaymentInfo;
                request.check = GetCheck( ach );
            }
            else if ( paymentInfo is ReferencePaymentInfo )
            {
                var reference = paymentInfo as ReferencePaymentInfo;
                request.recurringSubscriptionInfo = new RecurringSubscriptionInfo();
                request.recurringSubscriptionInfo.subscriptionID = reference.ReferenceNumber;
            }
            else
            {
                return null;
            }

            return request;
        }
示例#34
0
 /// <summary>
 /// Performs the third step of adding a new payment schedule
 /// </summary>
 /// <param name="financialGateway">The financial gateway.</param>
 /// <param name="resultQueryString">The result query string from step 2.</param>
 /// <param name="errorMessage">The error message.</param>
 /// <returns></returns>
 public abstract FinancialScheduledTransaction AddScheduledPaymentStep3(FinancialGateway financialGateway, string resultQueryString, out string errorMessage);
示例#35
0
        /// <summary>
        /// Handles the Swipe event of the csPayWithCard control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="SwipeEventArgs"/> instance containing the event data.</param>
        protected void csPayWithCard_Swipe(object sender, SwipeEventArgs e)
        {
            using (var rockContext = new RockContext())
            {
                try
                {
                    var swipeInfo = e.PaymentInfo;
                    var person    = Customer;

                    if (person == null)
                    {
                        person = new PersonAliasService(rockContext).GetPerson(GetAttributeValue("GuestCustomer").AsGuid());

                        if (person == null)
                        {
                            nbSwipeErrors.Text = "No guest customer configured. Transaction not processed.";
                            return;
                        }
                    }

                    //
                    // Get the gateway to use.
                    //
                    FinancialGateway financialGateway = null;
                    GatewayComponent gateway          = null;
                    Guid?            gatewayGuid      = GetAttributeValue("CreditCardGateway").AsGuidOrNull();
                    if (gatewayGuid.HasValue)
                    {
                        financialGateway = new FinancialGatewayService(rockContext).Get(gatewayGuid.Value);

                        if (financialGateway != null)
                        {
                            financialGateway.LoadAttributes(rockContext);
                        }

                        gateway = financialGateway.GetGatewayComponent();
                    }

                    if (gateway == null)
                    {
                        nbSwipeErrors.Text = "Invalid gateway provided. Please provide a gateway. Transaction not processed.";
                        return;
                    }

                    swipeInfo.Amount = Cart.Total;

                    //
                    // Process the transaction.
                    //
                    string errorMessage = string.Empty;
                    var    transaction  = gateway.Charge(financialGateway, swipeInfo, out errorMessage);

                    if (transaction == null)
                    {
                        nbSwipeErrors.Text = String.Format("An error occurred while process this transaction. Message: {0}", errorMessage);
                        return;
                    }

                    //
                    // Set some common information about the transaction.
                    //
                    transaction.AuthorizedPersonAliasId = person.PrimaryAliasId;
                    transaction.TransactionDateTime     = RockDateTime.Now;
                    transaction.FinancialGatewayId      = financialGateway.Id;
                    transaction.TransactionTypeValueId  = DefinedValueCache.Get(GetAttributeValue("TransactionType")).Id;
                    transaction.SourceTypeValueId       = DefinedValueCache.Get(GetAttributeValue("Source")).Id;
                    transaction.Summary = swipeInfo.Comment1;

                    //
                    // Ensure we have payment details.
                    //
                    if (transaction.FinancialPaymentDetail == null)
                    {
                        transaction.FinancialPaymentDetail = new FinancialPaymentDetail();
                    }
                    transaction.FinancialPaymentDetail.SetFromPaymentInfo(swipeInfo, gateway, rockContext);

                    //
                    // Setup the transaction details to credit the correct account.
                    //
                    GetTransactionDetails(rockContext).ForEach(d => transaction.TransactionDetails.Add(d));

                    var batchService = new FinancialBatchService(rockContext);

                    //
                    // Get the batch
                    //
                    var batch = batchService.Get(
                        GetAttributeValue("BatchNamePrefix"),
                        swipeInfo.CurrencyTypeValue,
                        swipeInfo.CreditCardTypeValue,
                        transaction.TransactionDateTime.Value,
                        financialGateway.GetBatchTimeOffset());

                    var batchChanges = new History.HistoryChangeList();

                    if (batch.Id == 0)
                    {
                        batchChanges.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "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);
                    }

                    //
                    // Update the control amount.
                    //
                    decimal newControlAmount = batch.ControlAmount + transaction.TotalAmount;
                    History.EvaluateChange(batchChanges, "Control Amount", batch.ControlAmount.FormatAsCurrency(), newControlAmount.FormatAsCurrency());
                    batch.ControlAmount = newControlAmount;

                    //
                    // Add the transaction to the batch.
                    //
                    transaction.BatchId = batch.Id;
                    batch.Transactions.Add(transaction);

                    //
                    // Generate the receipt.
                    //
                    int receiptId;
                    using (var rockContext2 = new RockContext())
                    {
                        var receipt = GenerateReceipt(rockContext2);
                        receiptId = receipt.Id;
                    }

                    //
                    // Update each transaction detail to reference the receipt.
                    //
                    foreach (var transactionDetail in transaction.TransactionDetails)
                    {
                        transactionDetail.EntityTypeId = EntityTypeCache.Get(typeof(InteractionComponent)).Id;
                        transactionDetail.EntityId     = receiptId;
                    }

                    rockContext.WrapTransaction(() =>
                    {
                        rockContext.SaveChanges();

                        HistoryService.SaveChanges(
                            rockContext,
                            typeof(FinancialBatch),
                            Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(),
                            batch.Id,
                            batchChanges
                            );
                    });

                    ShowReceiptPanel();
                }
                catch (Exception ex)
                {
                    nbSwipeErrors.Text = String.Format("An error occurred while process this transaction. Message: {0}", ex.Message);
                }
            }
        }
示例#36
0
 /// <summary>
 /// Performs the third step of adding a new payment schedule
 /// </summary>
 /// <param name="financialGateway">The financial gateway.</param>
 /// <param name="resultQueryString">The result query string from step 2.</param>
 /// <param name="errorMessage">The error message.</param>
 /// <returns></returns>
 public abstract FinancialScheduledTransaction AddScheduledPaymentStep3( FinancialGateway financialGateway, string resultQueryString, out string errorMessage );
        //
        // Swipe Panel Events
        //

        private void ProcessSwipe(string swipeData)
        {
            try
            {
                using (var rockContext = new RockContext())
                {
                    // create swipe object
                    SwipePaymentInfo swipeInfo = new SwipePaymentInfo(swipeData);
                    swipeInfo.Amount = this.Amounts.Sum(a => a.Value);
                    var txnType = DefinedValueCache.Get(new Guid(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION));
                    swipeInfo.TransactionTypeValueId = txnType.Id;

                    // if not anonymous then add contact info to the gateway transaction
                    if (this.AnonymousGiverPersonAliasId != this.SelectedGivingUnit.PersonAliasId)
                    {
                        var giver = new PersonAliasService(rockContext).Queryable("Person, Person.PhoneNumbers").Where(p => p.Id == this.SelectedGivingUnit.PersonAliasId).FirstOrDefault();
                        swipeInfo.FirstName = giver.Person.NickName;
                        swipeInfo.LastName  = giver.Person.LastName;

                        if (giver.Person.PhoneNumbers != null)
                        {
                            Guid homePhoneValueGuid = new Guid(Rock.SystemGuid.DefinedValue.PERSON_PHONE_TYPE_HOME);
                            var  homephone          = giver.Person.PhoneNumbers.Where(p => p.NumberTypeValue.Guid == homePhoneValueGuid).FirstOrDefault();
                            if (homephone != null)
                            {
                                swipeInfo.Phone = homephone.NumberFormatted;
                            }
                        }

                        var homeLocation = giver.Person.GetHomeLocation();

                        if (homeLocation != null)
                        {
                            swipeInfo.Street1 = homeLocation.Street1;

                            if (!string.IsNullOrWhiteSpace(homeLocation.Street2))
                            {
                                swipeInfo.Street2 = homeLocation.Street2;
                            }

                            swipeInfo.City       = homeLocation.City;
                            swipeInfo.State      = homeLocation.State;
                            swipeInfo.PostalCode = homeLocation.PostalCode;
                        }
                    }

                    // add comment to the transaction
                    swipeInfo.Comment1 = GetAttributeValue("PaymentComment");

                    // get gateway
                    FinancialGateway financialGateway = null;
                    GatewayComponent gateway          = null;
                    Guid?            gatewayGuid      = GetAttributeValue("CreditCardGateway").AsGuidOrNull();
                    if (gatewayGuid.HasValue)
                    {
                        financialGateway = new FinancialGatewayService(rockContext).Get(gatewayGuid.Value);
                        if (financialGateway != null)
                        {
                            financialGateway.LoadAttributes(rockContext);
                        }
                        gateway = financialGateway.GetGatewayComponent();
                    }

                    if (gateway != null)
                    {
                        string errorMessage = string.Empty;
                        var    transaction  = gateway.Charge(financialGateway, swipeInfo, out errorMessage);

                        if (transaction != null)
                        {
                            _transactionCode = transaction.TransactionCode;

                            var personName = new PersonAliasService(rockContext)
                                             .Queryable().AsNoTracking()
                                             .Where(a => a.Id == this.SelectedGivingUnit.PersonAliasId)
                                             .Select(a => a.Person.NickName + " " + a.Person.LastName)
                                             .FirstOrDefault();

                            transaction.AuthorizedPersonAliasId = this.SelectedGivingUnit.PersonAliasId;
                            transaction.TransactionDateTime     = RockDateTime.Now;
                            transaction.FinancialGatewayId      = financialGateway.Id;

                            transaction.TransactionTypeValueId = txnType.Id;

                            transaction.Summary = swipeInfo.Comment1;

                            if (transaction.FinancialPaymentDetail == null)
                            {
                                transaction.FinancialPaymentDetail = new FinancialPaymentDetail();
                            }
                            transaction.FinancialPaymentDetail.SetFromPaymentInfo(swipeInfo, gateway, rockContext);

                            Guid sourceGuid = Guid.Empty;
                            if (Guid.TryParse(GetAttributeValue("Source"), out sourceGuid))
                            {
                                var source = DefinedValueCache.Get(sourceGuid);
                                if (source != null)
                                {
                                    transaction.SourceTypeValueId = source.Id;
                                }
                            }

                            foreach (var accountAmount in this.Amounts.Where(a => a.Value > 0))
                            {
                                var transactionDetail = new FinancialTransactionDetail();
                                transactionDetail.Amount    = accountAmount.Value;
                                transactionDetail.AccountId = accountAmount.Key;
                                transaction.TransactionDetails.Add(transactionDetail);
                                var account = new FinancialAccountService(rockContext).Get(accountAmount.Key);
                            }

                            var batchService = new FinancialBatchService(rockContext);

                            // Get the batch
                            var batch = batchService.Get(
                                GetAttributeValue("BatchNamePrefix"),
                                swipeInfo.CurrencyTypeValue,
                                swipeInfo.CreditCardTypeValue,
                                transaction.TransactionDateTime.Value,
                                financialGateway.GetBatchTimeOffset());

                            var batchChanges = new History.HistoryChangeList();

                            if (batch.Id == 0)
                            {
                                batchChanges.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "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.WrapTransaction(() =>
                            {
                                rockContext.SaveChanges();
                                HistoryService.SaveChanges(
                                    rockContext,
                                    typeof(FinancialBatch),
                                    Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(),
                                    batch.Id,
                                    batchChanges
                                    );
                            });

                            // send receipt in one is configured and not giving anonymously
                            if (!string.IsNullOrWhiteSpace(GetAttributeValue("ReceiptEmail")) && (this.AnonymousGiverPersonAliasId != this.SelectedGivingUnit.PersonAliasId))
                            {
                                _receiptSent = true;

                                SendReceipt();
                            }

                            HidePanels();
                            ShowReceiptPanel();
                        }
                        else
                        {
                            lSwipeErrors.Text = String.Format("<div class='alert alert-danger'>An error occurred while process this transaction. Message: {0}</div>", errorMessage);
                        }
                    }
                    else
                    {
                        lSwipeErrors.Text = "<div class='alert alert-danger'>Invalid gateway provided. Please provide a gateway. Transaction not processed.</div>";
                    }
                }
            }
            catch (Exception ex)
            {
                lSwipeErrors.Text = String.Format("<div class='alert alert-danger'>An error occurred while process this transaction. Message: {0}</div>", ex.Message);
            }
        }
示例#38
0
 /// <summary>
 /// Performs the first step of a three-step charge
 /// </summary>
 /// <param name="financialGateway">The financial gateway.</param>
 /// <param name="paymentInfo">The payment information.</param>
 /// <param name="errorMessage">The error message.</param>
 /// <returns></returns>
 public abstract string ChargeStep1( FinancialGateway financialGateway, PaymentInfo paymentInfo, out string errorMessage );
示例#39
0
 /// <summary>
 /// Gets a value indicating whether the gateway requires the name on card for CC processing
 /// </summary>
 /// <param name="financialGateway">The financial gateway.</param>
 /// <returns></returns>
 /// <value>
 ///   <c>true</c> if [name on card required]; otherwise, <c>false</c>.
 /// </value>
 public override bool PromptForNameOnCard(FinancialGateway financialGateway)
 {
     return(false);
 }
示例#40
0
 /// <summary>
 /// Performs the final step of a three-step charge.
 /// </summary>
 /// <param name="financialGateway">The financial gateway.</param>
 /// <param name="resultQueryString">The result query string from step 2.</param>
 /// <param name="errorMessage">The error message.</param>
 /// <returns></returns>
 public abstract FinancialTransaction ChargeStep3( FinancialGateway financialGateway, string resultQueryString, out string errorMessage );
示例#41
0
        /// <summary>
        /// Authorizes 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 Authorize(FinancialGateway financialGateway, PaymentInfo paymentInfo, out string errorMessage)
        {
            errorMessage = string.Empty;
            Response ppResponse = null;

            var invoice = GetInvoice(paymentInfo);

            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("Authorization", reference.TransactionCode, GetUserInfo(financialGateway), GetConnection(financialGateway), invoice, tender, PayflowUtility.RequestId);
                    ppResponse = ppTransaction.SubmitTransaction();
                }
                else
                {
                    var ppTransaction = new AuthorizationTransaction(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;
                        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);
        }
示例#42
0
 /// <summary>
 /// Handles the SelectedIndexChanged event of the cpGatewayType 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 cpGatewayType_SelectedIndexChanged( object sender, EventArgs e )
 {
     var gateway = new FinancialGateway { Id = GatewayId, EntityTypeId = cpGatewayType.SelectedEntityTypeId };
     BuildDynamicControls( gateway, true );
 }
示例#43
0
        /// <summary>
        /// Adds the scheduled payment.
        /// </summary>
        /// <param name="financialGateway"></param>
        /// <param name="schedule">The schedule.</param>
        /// <param name="paymentInfo">The payment info.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialScheduledTransaction AddScheduledPayment(FinancialGateway financialGateway, PaymentSchedule schedule, PaymentInfo paymentInfo, out string errorMessage)
        {
            errorMessage = string.Empty;

            var recurring = GetRecurring(schedule);

            if (paymentInfo is CreditCardPaymentInfo)
            {
                recurring.OptionalTrx = "A";
            }

            var ppTransaction = new RecurringAddTransaction(GetUserInfo(financialGateway), GetConnection(financialGateway), GetInvoice(paymentInfo), GetTender(paymentInfo),
                                                            recurring, PayflowUtility.RequestId);

            if (paymentInfo is ReferencePaymentInfo)
            {
                var reference = paymentInfo as ReferencePaymentInfo;
                ppTransaction.OrigId = reference.TransactionCode;
            }
            var ppResponse = ppTransaction.SubmitTransaction();

            if (ppResponse != null)
            {
                TransactionResponse txnResponse = ppResponse.TransactionResponse;
                if (txnResponse != null)
                {
                    if (txnResponse.Result == 0)   // Success
                    {
                        RecurringResponse recurringResponse = ppResponse.RecurringResponse;

                        if (recurringResponse != null)
                        {
                            var scheduledTransaction = new FinancialScheduledTransaction();
                            scheduledTransaction.TransactionCode    = recurringResponse.TrxPNRef;
                            scheduledTransaction.GatewayScheduleId  = recurringResponse.ProfileId;
                            scheduledTransaction.FinancialGatewayId = financialGateway.Id;

                            GetScheduledPaymentStatus(scheduledTransaction, out errorMessage);
                            return(scheduledTransaction);
                        }
                        else
                        {
                            errorMessage = "Invalid recurring response from the financial gateway";
                        }
                    }
                    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);
        }
示例#44
0
        private void BuildDynamicControls( FinancialGateway gateway, bool SetValues )
        {
            GatewayEntityTypeId = gateway.EntityTypeId;
            if ( gateway.EntityTypeId.HasValue )
            {
                var GatewayComponentEntityType = EntityTypeCache.Read( gateway.EntityTypeId.Value );
                var GatewayEntityType = EntityTypeCache.Read( "Rock.Model.FinancialGateway " );
                if ( GatewayComponentEntityType != null && GatewayEntityType != null )
                {
                    using ( var rockContext = new RockContext() )
                    {
                        Rock.Attribute.Helper.UpdateAttributes( GatewayComponentEntityType.GetEntityType(), GatewayEntityType.Id, "EntityTypeId", GatewayComponentEntityType.Id.ToString(), rockContext );
                        gateway.LoadAttributes( rockContext );
                    }
                }
            }

            phAttributes.Controls.Clear();
            Rock.Attribute.Helper.AddEditControls( gateway, phAttributes, SetValues, BlockValidationGroup, new List<string> { "Active", "Order" } );
        }
示例#45
0
 /// <summary>
 /// Gets the payments that have been processed for any scheduled transactions
 /// </summary>
 /// <param name="financialGateway">The financial gateway.</param>
 /// <param name="startDate">The start date.</param>
 /// <param name="endDate">The end date.</param>
 /// <param name="errorMessage">The error message.</param>
 /// <returns></returns>
 public override List <Payment> GetPayments(FinancialGateway financialGateway, DateTime startDate, DateTime endDate, out string errorMessage)
 {
     errorMessage = string.Empty;
     return(new List <Payment>());
 }
示例#46
0
        /// <summary>
        /// Gets the payments that have been processed for any scheduled transactions
        /// </summary>
        /// <param name="gateway">The gateway.</param>
        /// <param name="startDate">The start date.</param>
        /// <param name="endDate">The end date.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override List <Payment> GetPayments(FinancialGateway gateway, DateTime startDate, DateTime endDate, out string errorMessage)
        {
            var today             = RockDateTime.Now;
            var lookupContext     = new RockContext();
            var accountLookup     = new FinancialAccountService(lookupContext);
            var transactionLookup = new FinancialTransactionService(lookupContext);
            var donationUrl       = GetBaseUrl(gateway, "donations", out errorMessage);
            var supporterUrl      = GetBaseUrl(gateway, "sponsorship_supporters", out errorMessage);
            var categoryUrl       = GetBaseUrl(gateway, "donation_categories", out errorMessage);
            var projectsUrl       = GetBaseUrl(gateway, "projects", out errorMessage);

            if (donationUrl.IsNullOrWhiteSpace() || supporterUrl.IsNullOrWhiteSpace())
            {
                // errorMessage already set
                return(null);
            }

            var authenticator = GetAuthenticator(gateway, out errorMessage);

            if (authenticator == null)
            {
                // errorMessage already set
                return(null);
            }

            var reachAccountMaps   = DefinedTypeCache.Get(GetAttributeValue(gateway, "AccountMap")).DefinedValues;
            var connectionStatus   = DefinedValueCache.Get(GetAttributeValue(gateway, "PersonStatus"));
            var reachSourceType    = DefinedValueCache.Get(GetAttributeValue(gateway, "SourceType"));
            var defaultAccount     = accountLookup.Get(GetAttributeValue(gateway, "DefaultAccount").AsGuid());
            var updatePrimaryEmail = GetAttributeValue(gateway, "UpdatePrimaryEmail").AsBoolean();

            if (connectionStatus == null || reachAccountMaps == null || reachSourceType == null || defaultAccount == null)
            {
                errorMessage = "The Reach Account Map, Person Status, Source Type, or Default Account is not configured correctly in gateway settings.";
                return(null);
            }

            var currentPage             = 1;
            var queryHasResults         = true;
            var skippedTransactionCount = 0;
            var errorMessages           = new List <string>();
            var newTransactions         = new List <FinancialTransaction>();
            var categoryResult          = Api.PostRequest(categoryUrl, authenticator, null, out errorMessage);
            var categories    = JsonConvert.DeserializeObject <List <Reporting.Category> >(categoryResult.ToStringSafe());
            var projectResult = Api.PostRequest(projectsUrl, authenticator, null, out errorMessage);
            var projects      = JsonConvert.DeserializeObject <List <Reporting.Project> >(projectResult.ToStringSafe());

            if (categories == null)
            {
                // errorMessage already set
                return(null);
            }

            while (queryHasResults)
            {
                var parameters = new Dictionary <string, string>
                {
                    { "from_date", startDate.ToString("yyyy-MM-dd") },
                    { "to_date", endDate.ToString("yyyy-MM-dd") },
                    { "per_page", "50" },
                    { "page", currentPage.ToString() }
                };

                // to_date doesn't have a timestamp, so it includes transactions posted after the cutoff
                var donationResult = Api.PostRequest(donationUrl, authenticator, parameters, out errorMessage);
                var donations      = JsonConvert.DeserializeObject <List <Donation> >(donationResult.ToStringSafe());
                if (donations != null && donations.Any() && errorMessage.IsNullOrWhiteSpace())
                {
                    // only process completed transactions with confirmation codes and within the date range
                    foreach (var donation in donations.Where(d => d.updated_at >= startDate && d.updated_at < endDate && d.status.Equals("complete") && d.confirmation.IsNotNullOrWhiteSpace()))
                    {
                        var transaction = transactionLookup.Queryable()
                                          .FirstOrDefault(t => t.FinancialGatewayId.HasValue &&
                                                          t.FinancialGatewayId.Value == gateway.Id &&
                                                          t.TransactionCode == donation.confirmation);
                        if (transaction == null)
                        {
                            // find or create this person asynchronously for performance
                            var personAlias = Api.FindPersonAsync(lookupContext, donation, connectionStatus.Id, updatePrimaryEmail);

                            var reachAccountName = string.Empty;
                            var donationItem     = donation.line_items.FirstOrDefault();
                            if (donationItem != null && donationItem.referral_type.Equals("DonationOption", StringComparison.InvariantCultureIgnoreCase))
                            {
                                // one-time gift, should match a known category
                                var category = categories.FirstOrDefault(c => c.id == donationItem.referral_id);
                                if (category != null)
                                {
                                    reachAccountName = category.title.Trim();
                                }
                            }
                            else if (donationItem != null && donationItem.referral_type.Equals("Project", StringComparison.InvariantCultureIgnoreCase))
                            {
                                // one-time gift, should match a known project
                                var project = projects.FirstOrDefault(c => c.id == donationItem.referral_id);
                                if (project != null)
                                {
                                    reachAccountName = string.Format("PROJECT {0}", project.title.Trim());
                                }
                            }
                            else
                            {
                                // recurring gift, lookup the sponsor info
                                var referralId       = donation.referral_id ?? donationItem.referral_id;
                                var supporterResults = Api.PostRequest(string.Format("{0}/{1}", supporterUrl, referralId), authenticator, null, out errorMessage);
                                var supporter        = JsonConvert.DeserializeObject <Supporter>(supporterResults.ToStringSafe());
                                if (supporter != null)
                                {
                                    var place           = supporter.sponsorship?.place?.title;
                                    var sponsorshipType = supporter.sponsorship?.sponsorship_type_title;
                                    var shareType       = supporter.share_type_id;

                                    string shareTypeName;
                                    switch (shareType)
                                    {
                                    case "668":
                                        shareTypeName = "Primary";
                                        break;

                                    case "669":
                                        shareTypeName = "Secondary";
                                        break;

                                    default:
                                        shareTypeName = string.Empty;
                                        break;
                                    }

                                    reachAccountName = string.Format("{0} {1} {2}", place, sponsorshipType, shareTypeName).Trim();
                                }
                            }

                            int?rockAccountId  = defaultAccount.Id;
                            var accountMapping = reachAccountMaps.FirstOrDefault(v => v.Value.Equals(reachAccountName, StringComparison.CurrentCultureIgnoreCase));
                            if (accountMapping != null)
                            {
                                var accountGuid = accountMapping.GetAttributeValue("RockAccount").AsGuidOrNull();
                                if (accountGuid.HasValue)
                                {
                                    rockAccountId = accountLookup.Get(( Guid )accountGuid).Id;
                                }
                            }

                            // verify person alias was found or created
                            personAlias.Wait();
                            if (!personAlias.Result.HasValue)
                            {
                                var infoMessage = string.Format("{0} Reach import skipped {1} {2}'s donation {3} for {4} because their record could not be found or created",
                                                                endDate.ToString("d"), donation.first_name, donation.last_name, donation.confirmation, reachAccountName);
                                ExceptionLogService.LogException(new Exception(infoMessage), null);
                                continue;
                            }

                            // create the transaction
                            var summary = string.Format("Reach Donation for {0} from {1} using {2} on {3} ({4})",
                                                        reachAccountName, donation.name, donation.payment_method, donation.updated_at, donation.token);
                            transaction = new FinancialTransaction
                            {
                                TransactionDateTime    = donation.updated_at,
                                ProcessedDateTime      = donation.updated_at,
                                TransactionCode        = donation.confirmation,
                                Summary                = summary,
                                SourceTypeValueId      = reachSourceType.Id,
                                TransactionTypeValueId = contributionTypeId,
                                Guid                    = Guid.NewGuid(),
                                CreatedDateTime         = today,
                                ModifiedDateTime        = today,
                                AuthorizedPersonAliasId = personAlias.Result.Value,
                                FinancialGatewayId      = gateway.Id,
                                ForeignId               = donation.id,
                                FinancialPaymentDetail  = new FinancialPaymentDetail(),
                                TransactionDetails      = new List <FinancialTransactionDetail>
                                {
                                    new FinancialTransactionDetail
                                    {
                                        AccountId        = (int)rockAccountId,
                                        Amount           = (decimal)donation.amount,
                                        Summary          = summary,
                                        Guid             = Guid.NewGuid(),
                                        CreatedDateTime  = today,
                                        ModifiedDateTime = today
                                    }
                                }
                            };

                            newTransactions.Add(transaction);
                        }
                        else if (transaction != null)
                        {
                            skippedTransactionCount++;
                        }
                    }
                }
                else
                {
                    queryHasResults = false;
                }

                currentPage++;
            }

            if (skippedTransactionCount > 0)
            {
                ExceptionLogService.LogException(new Exception(string.Format("{0} Reach import skipped downloading {1} transactions because they already exist",
                                                                             endDate.ToString("d"), skippedTransactionCount)), null);
            }

            if (newTransactions.Any())
            {
                using (var rockContext = new RockContext())
                {
                    // create batch and add transactions
                    var batchPrefix = GetAttributeValue(gateway, "BatchPrefix");
                    var batchDate   = newTransactions.GroupBy(t => t.TransactionDateTime.Value.Date).OrderByDescending(t => t.Count())
                                      .Select(g => g.Key).FirstOrDefault();
                    var batch = new FinancialBatchService(rockContext).GetByNameAndDate(string.Format("{0} {1}",
                                                                                                      batchPrefix, batchDate.ToString("d")), endDate, gateway.GetBatchTimeOffset());
                    batch.BatchStartDateTime = batchDate;
                    batch.BatchEndDateTime   = endDate;
                    batch.Note           = string.Format("{0} transactions downloaded starting {1} to {2}", batchPrefix, startDate, endDate);
                    batch.ControlAmount += newTransactions.Select(t => t.TotalAmount).Sum();

                    var currentChanges = 0;
                    foreach (var transaction in newTransactions)
                    {
                        // save in large batches so it doesn't overload context
                        batch.Transactions.Add(transaction);
                        if (currentChanges++ > 100)
                        {
                            rockContext.SaveChanges(disablePrePostProcessing: true);
                            currentChanges = 0;
                        }
                    }

                    // by default Rock associates with the current person
                    rockContext.SaveChanges(disablePrePostProcessing: true);
                }
            }

            if (errorMessages.Any())
            {
                errorMessage = string.Join("<br>", errorMessages);
            }

            return(new List <Payment>());
        }
示例#47
0
        protected override void LoadViewState( object savedState )
        {
            base.LoadViewState( savedState );

            var gateway = new FinancialGateway { Id = GatewayId, EntityTypeId = GatewayEntityTypeId };
            BuildDynamicControls( gateway, false );
        }
示例#48
0
        /// <summary>
        /// Submits the transaction.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns></returns>
        private ReplyMessage SubmitTransaction( FinancialGateway financialGateway, RequestMessage request, out string errorMessage )
        {
            ReplyMessage reply = new ReplyMessage();
            TransactionProcessorClient client = GetProxyClient( financialGateway, out errorMessage );

            // Error message already set, return
            if ( client == null )
            {
                return null;
            }

            try
            {
                reply = client.runTransaction( request );
                return reply;
            }
            catch ( TimeoutException e )
            {
                reply.reasonCode = "151";
                reply.additionalData = e.ToString();
                return reply;
            }
            catch ( FaultException e )
            {
                reply.reasonCode = "150";
                reply.additionalData = e.ToString();
                return reply;
            }
            catch ( Exception e )
            {
                reply.reasonCode = "";
                reply.additionalData = e.ToString();
                return reply;
            }
        }
示例#49
0
        /// <summary>
        /// Shows the edit details.
        /// </summary>
        /// <param name="gateway">The gateway.</param>
        private void ShowEditDetails( FinancialGateway gateway )
        {
            if ( gateway.Id == 0 )
            {
                lActionTitle.Text = ActionTitle.Add( FinancialGateway.FriendlyTypeName ).FormatAsHtmlTitle();
            }
            else
            {
                lActionTitle.Text = gateway.Name.FormatAsHtmlTitle();
            }

            hlInactive.Visible = !gateway.IsActive;

            SetEditMode( true );

            tbName.Text = gateway.Name;
            cbIsActive.Checked = gateway.IsActive;
            tbDescription.Text = gateway.Description;
            cpGatewayType.SetValue( gateway.EntityType != null ? gateway.EntityType.Guid.ToString().ToUpper() : string.Empty );
            tpBatchTimeOffset.SelectedTime = gateway.GetBatchTimeOffset();

            BuildDynamicControls( gateway, true );
        }
示例#50
0
        /// <summary>
        /// Adds the scheduled payment.
        /// </summary>
        /// <param name="schedule">The schedule.</param>
        /// <param name="paymentInfo">The payment info.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialScheduledTransaction AddScheduledPayment( FinancialGateway financialGateway, PaymentSchedule schedule, PaymentInfo paymentInfo, out string errorMessage )
        {
            errorMessage = string.Empty;
            RequestMessage request = GetPaymentInfo( financialGateway, paymentInfo );

            if ( request == null )
            {
                errorMessage = "Payment type not implemented";
                return null;
            }

            if ( request.recurringSubscriptionInfo == null )
            {
                request.recurringSubscriptionInfo = new RecurringSubscriptionInfo();
            }

            request.recurringSubscriptionInfo.startDate = GetStartDate( schedule );
            request.recurringSubscriptionInfo.frequency = GetFrequency( schedule );
            request.recurringSubscriptionInfo.amount = paymentInfo.Amount.ToString();
            request.paySubscriptionCreateService = new PaySubscriptionCreateService();
            request.paySubscriptionCreateService.run = "true";
            request.purchaseTotals = GetTotals();
            request.billTo = GetBillTo( paymentInfo );
            request.item = GetItems( paymentInfo );

            request.subscription = new Subscription();
            if ( !paymentInfo.CurrencyTypeValue.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD ) ) )
            {
                request.subscription.paymentMethod = "check";
            }

            if ( paymentInfo is ReferencePaymentInfo )
            {
                request.paySubscriptionCreateService.paymentRequestID = ( (ReferencePaymentInfo)paymentInfo ).TransactionCode;
            }

            // Schedule the payment
            ReplyMessage reply = SubmitTransaction( financialGateway, request, out errorMessage );
            if ( reply != null && reply.reasonCode.Equals( GATEWAY_RESPONSE_SUCCESS ) )
            {
                var transactionGuid = new Guid( reply.merchantReferenceCode );
                var scheduledTransaction = new FinancialScheduledTransaction { Guid = transactionGuid };
                scheduledTransaction.TransactionCode = reply.paySubscriptionCreateReply.subscriptionID;
                scheduledTransaction.GatewayScheduleId = reply.paySubscriptionCreateReply.subscriptionID;
                scheduledTransaction.FinancialGateway = financialGateway;
                scheduledTransaction.FinancialGatewayId = financialGateway.Id;
                GetScheduledPaymentStatus( scheduledTransaction, out errorMessage );
                return scheduledTransaction;
            }
            else if ( string.IsNullOrEmpty( errorMessage ) )
            {
                errorMessage = string.Format( "Your order was not approved.{0}", ProcessError( reply ) );
            }

            return null;
        }
示例#51
0
        /// <summary>
        /// Authorizes/tokenizes the specified payment info.
        /// </summary>
        /// <param name="paymentInfo">The payment info.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialTransaction Authorize( FinancialGateway financialGateway, PaymentInfo paymentInfo, out string errorMessage )
        {
            errorMessage = string.Empty;
            RequestMessage request = GetPaymentInfo( financialGateway, paymentInfo );

            if ( request == null )
            {
                errorMessage = "Payment type not implemented";
                return null;
            }

            if ( request.recurringSubscriptionInfo == null )
            {
                request.recurringSubscriptionInfo = new RecurringSubscriptionInfo();
            }

            request.recurringSubscriptionInfo.frequency = "ON-DEMAND";
            request.recurringSubscriptionInfo.amount = paymentInfo.Amount.ToString();
            request.paySubscriptionCreateService = new PaySubscriptionCreateService();
            request.paySubscriptionCreateService.run = "true";
            request.purchaseTotals = GetTotals();
            request.billTo = GetBillTo( paymentInfo );
            request.item = GetItems( paymentInfo );

            request.subscription = new Subscription();
            if ( !paymentInfo.CurrencyTypeValue.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD ) ) )
            {
                request.subscription.paymentMethod = "check";
            }

            if ( paymentInfo is ReferencePaymentInfo )
            {
                request.paySubscriptionCreateService.paymentRequestID = ( (ReferencePaymentInfo)paymentInfo ).TransactionCode;
            }

            // Authorize the transaction
            ReplyMessage reply = SubmitTransaction( financialGateway, request, out errorMessage );
            if ( reply != null && reply.reasonCode.Equals( GATEWAY_RESPONSE_SUCCESS ) )
            {
                var transactionGuid = new Guid( reply.merchantReferenceCode );
                var transaction = new FinancialTransaction { Guid = transactionGuid };
                transaction.TransactionCode = reply.requestID;
                return transaction;
            }
            else if ( string.IsNullOrEmpty( errorMessage ) )
            {
                errorMessage = string.Format( "Unable to authorize this transaction.{0}", ProcessError( reply ) );
            }

            return null;
        }
示例#52
0
        /// <summary>
        /// Charges the specified payment info.
        /// </summary>
        /// <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;
            RequestMessage request = GetPaymentInfo( financialGateway, paymentInfo );
            if ( request == null )
            {
                errorMessage = "Payment type not implemented";
                return null;
            }

            request.purchaseTotals = GetTotals();
            request.billTo = GetBillTo( paymentInfo );
            request.item = GetItems( paymentInfo );

            if ( !paymentInfo.CurrencyTypeValue.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD ) ) )
            {
                request.ecDebitService = new ECDebitService();
                request.ecDebitService.commerceIndicator = "internet";
                request.ecDebitService.run = "true";
            }
            else
            {
                request.ccAuthService = new CCAuthService();
                request.ccAuthService.commerceIndicator = "internet";
                request.ccAuthService.run = "true";
                request.ccCaptureService = new CCCaptureService();
                request.ccCaptureService.run = "true";
            }

            // Charge the transaction
            ReplyMessage reply = SubmitTransaction( financialGateway, request, out errorMessage );
            if ( reply != null && reply.reasonCode.Equals( GATEWAY_RESPONSE_SUCCESS ) )
            {
                var transactionGuid = new Guid( reply.merchantReferenceCode );
                var transaction = new FinancialTransaction { Guid = transactionGuid };
                transaction.TransactionCode = reply.requestID;
                return transaction;
            }
            else if ( string.IsNullOrEmpty( errorMessage ) )
            {
                errorMessage = string.Format( "Unable to process this order.{0}", ProcessError( reply ) );
            }

            return null;
        }
示例#53
0
        /// <summary>
        /// Gets the batch.
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="financialGateway">The financial gateway.</param>
        /// <param name="suffix">The suffix.</param>
        /// <returns></returns>
        private FinancialBatch GetBatch( RockContext rockContext, FinancialGateway financialGateway, string suffix )
        {
            if ( suffix == null )
            {
                suffix = string.Empty;
            }

            if ( suffix.Length > 1 )
            {
                suffix = char.ToUpper( suffix[0] ) + suffix.Substring( 1 );
            }

            var batchService = new FinancialBatchService( rockContext );
            var batchName = string.Format( "{0}: {1}", BATCH_PREFIX, suffix );
            return batchService.GetByNameAndDate( batchName, RockDateTime.Now, financialGateway.GetBatchTimeOffset() );
        }
示例#54
0
        /// <summary>
        /// Gets the payments that have been processed for any scheduled transactions
        /// </summary>
        /// <param name="startDate">The start date.</param>
        /// <param name="endDate">The end date.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override List<Payment> GetPayments( FinancialGateway financialGateway, DateTime startDate, DateTime endDate, out string errorMessage )
        {
            errorMessage = string.Empty;
            List<Payment> paymentList = new List<Payment>();
            var reportParams = new Dictionary<string, string>();
            var reportingApi = new Reporting.Api(
                GetAttributeValue( financialGateway, "MerchantID" ),
                GetAttributeValue( financialGateway, "TransactionKey" ),
                GetAttributeValue( financialGateway, "ReportUser" ),
                GetAttributeValue( financialGateway, "ReportPassword" ),
                GetAttributeValue( financialGateway, "Mode" ).Equals( "Live", StringComparison.CurrentCultureIgnoreCase )
            );

            TimeSpan timeDifference = endDate - startDate;
            for ( int offset = 0; offset <= timeDifference.TotalDays; offset++ )
            {
                DateTime offsetDate = startDate.AddDays( offset ) < endDate ? startDate.AddDays( offset ) : endDate;
                reportParams.Add( "date", offsetDate.ToString( "yyyy/MM/dd" ) );

                DataTable dt = reportingApi.GetReport( "SubscriptionDetailReport", reportParams, out errorMessage );
                if ( dt != null && dt.Rows.Count > 0 )
                {
                    foreach ( DataRow row in dt.Rows )
                    {
                        var payment = new Payment();

                        decimal amount = decimal.MinValue;
                        payment.Amount = decimal.TryParse( row["Amount"].ToString(), out amount ) ? amount : 0.0M;

                        var time = DateTime.MinValue;
                        payment.TransactionDateTime = DateTime.TryParse( row["Time"].ToString(), out time ) ? time : DateTime.MinValue;

                        payment.TransactionCode = row["Code"].ToString();
                        payment.GatewayScheduleId = row["Schedule"].ToString();
                        payment.ScheduleActive = row["Status"].ToString() == "CURRENT";
                        paymentList.Add( payment );
                    }
                }

                reportParams.Clear();
            }

            if ( paymentList.Any() )
            {
                return paymentList;
            }
            else
            {
                errorMessage = "The subscription detail report did not return any data for the timeframe";
                return null;
            }
        }
示例#55
0
        private GatewayComponent GetGatewayComponent( RockContext rockContext, FinancialGateway gateway )
        {
            if ( gateway != null )
            {
                gateway.LoadAttributes( rockContext );
                var gatewayComponent = gateway.GetGatewayComponent();
                if ( gatewayComponent != null )
                {
                    var threeStepGateway = gatewayComponent as ThreeStepGatewayComponent;
                    if ( threeStepGateway != null )
                    {
                        _using3StepGateway = true;
                        Step2IFrameUrl = ResolveRockUrl( threeStepGateway.Step2FormUrl );
                    }
                }

                return gatewayComponent;
            }
            return null;
        }
示例#56
0
 /// <summary>
 /// Prompts the name of for bank account.
 /// </summary>
 /// <param name="financialGateway">The financial gateway.</param>
 /// <returns></returns>
 public override bool PromptForBankAccountName( FinancialGateway financialGateway )
 {
     return GetAttributeValue( financialGateway, "PromptForBankAccountName" ).AsBoolean();
 }
示例#57
0
        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;
        }
示例#58
0
 /// <summary>
 /// Gets a value indicating whether [address required].
 /// </summary>
 /// <value>
 /// <c>true</c> if [address required]; otherwise, <c>false</c>.
 /// </value>
 public override bool PromptForBillingAddress( FinancialGateway financialGateway )
 {
     return GetAttributeValue( financialGateway, "PromptForAddress" ).AsBoolean();
 }
        /// <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>
        /// <param name="receiptEmail">The receipt email.</param>
        /// <returns></returns>
        public static string ProcessPayments( FinancialGateway gateway, string batchNamePrefix, List<Payment> payments, string batchUrlFormat = "", Guid? receiptEmail = null )
        {
            int totalPayments = 0;
            int totalAlreadyDownloaded = 0;
            int totalNoScheduledTransaction = 0;
            int totalAdded = 0;
            int totalReversals = 0;
            int totalStatusChanges = 0;

            var batches = new List<FinancialBatch>();
            var batchSummary = new Dictionary<Guid, List<Decimal>>();
            var initialControlAmounts = new Dictionary<Guid, decimal>();

            var txnPersonNames = new Dictionary<Guid, string>();

            var gatewayComponent = gateway.GetGatewayComponent();

            var newTransactions = new List<FinancialTransaction>();

            using ( 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 contributionTxnType = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid() );

                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();

                var batchTxnChanges = new Dictionary<Guid, List<string>>();
                var batchBatchChanges = new Dictionary<Guid, List<string>>();
                var scheduledTransactionIds = new List<int>();

                foreach ( var payment in payments.Where( p => p.Amount > 0.0M ) )
                {
                    totalPayments++;

                    var scheduledTransaction = scheduledTxnService.GetByScheduleId( payment.GatewayScheduleId );
                    if ( scheduledTransaction != null )
                    {
                        // Find existing payments with same transaction code
                        var txns = txnService
                            .Queryable( "TransactionDetails" )
                            .Where( t => t.TransactionCode == payment.TransactionCode )
                            .ToList();

                        // Calculate whether a transaction needs to be added
                        var txnAmount = CalculateTransactionAmount( payment, txns );
                        if ( txnAmount != 0.0M )
                        {
                            scheduledTransactionIds.Add( scheduledTransaction.Id );
                            if ( payment.ScheduleActive.HasValue )
                            {
                                scheduledTransaction.IsActive = payment.ScheduleActive.Value;
                            }

                            var transaction = new FinancialTransaction();
                            transaction.FinancialPaymentDetail = new FinancialPaymentDetail();

                            transaction.Guid = Guid.NewGuid();
                            transaction.TransactionCode = payment.TransactionCode;
                            transaction.TransactionDateTime = payment.TransactionDateTime;
                            transaction.Status = payment.Status;
                            transaction.StatusMessage = payment.StatusMessage;
                            transaction.ScheduledTransactionId = scheduledTransaction.Id;
                            transaction.AuthorizedPersonAliasId = scheduledTransaction.AuthorizedPersonAliasId;
                            transaction.SourceTypeValueId = scheduledTransaction.SourceTypeValueId;
                            txnPersonNames.Add( transaction.Guid, scheduledTransaction.AuthorizedPersonAlias.Person.FullName );
                            transaction.FinancialGatewayId = gateway.Id;
                            transaction.TransactionTypeValueId = contributionTxnType.Id;

                            if ( txnAmount < 0.0M )
                            {
                                transaction.Summary = "Reversal for previous transaction that failed during processing." + Environment.NewLine;
                            }

                            var currencyTypeValue = payment.CurrencyTypeValue;
                            var creditCardTypevalue = payment.CreditCardTypeValue;

                            if ( scheduledTransaction.FinancialPaymentDetail != null )
                            {
                                if ( currencyTypeValue == null && scheduledTransaction.FinancialPaymentDetail.CurrencyTypeValueId.HasValue )
                                {
                                    currencyTypeValue = DefinedValueCache.Read( scheduledTransaction.FinancialPaymentDetail.CurrencyTypeValueId.Value );
                                }

                                if ( creditCardTypevalue == null && scheduledTransaction.FinancialPaymentDetail.CreditCardTypeValueId.HasValue )
                                {
                                    creditCardTypevalue = DefinedValueCache.Read( scheduledTransaction.FinancialPaymentDetail.CreditCardTypeValueId.Value );
                                }

                                transaction.FinancialPaymentDetail.AccountNumberMasked = scheduledTransaction.FinancialPaymentDetail.AccountNumberMasked;
                                transaction.FinancialPaymentDetail.NameOnCardEncrypted = scheduledTransaction.FinancialPaymentDetail.NameOnCardEncrypted;
                                transaction.FinancialPaymentDetail.ExpirationMonthEncrypted = scheduledTransaction.FinancialPaymentDetail.ExpirationMonthEncrypted;
                                transaction.FinancialPaymentDetail.ExpirationYearEncrypted = scheduledTransaction.FinancialPaymentDetail.ExpirationYearEncrypted;
                                transaction.FinancialPaymentDetail.BillingLocationId = scheduledTransaction.FinancialPaymentDetail.BillingLocationId;
                            }

                            if ( currencyTypeValue != null )
                            {
                                transaction.FinancialPaymentDetail.CurrencyTypeValueId = currencyTypeValue.Id;
                            }
                            if ( creditCardTypevalue != null )
                            {
                                transaction.FinancialPaymentDetail.CreditCardTypeValueId = creditCardTypevalue.Id;
                            }

                            // Try to allocate the amount of the transaction based on the current scheduled transaction accounts
                            decimal remainingAmount = Math.Abs( txnAmount );
                            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.";
                                    transactionDetail.Amount = remainingAmount;
                                    transactionDetail.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 )
                                    .FirstOrDefault();
                                if ( transactionDetail == null && defaultAccount != null )
                                {
                                    transactionDetail = new FinancialTransactionDetail();
                                    transactionDetail.AccountId = defaultAccount.Id;
                                    transaction.TransactionDetails.Add( transactionDetail );
                                }
                                if ( transactionDetail != null )
                                {
                                    transactionDetail.Amount += remainingAmount;
                                    transactionDetail.Summary = "Note: Extra amount was applied to this account.";
                                }
                            }

                            // If the amount to apply was negative, update all details to be negative (absolute value was used when allocating to accounts)
                            if ( txnAmount < 0.0M )
                            {
                                foreach ( var txnDetail in transaction.TransactionDetails )
                                {
                                    txnDetail.Amount = 0 - txnDetail.Amount;
                                }
                            }

                            // Get the batch
                            var batch = batchService.Get(
                                batchNamePrefix,
                                currencyTypeValue,
                                creditCardTypevalue,
                                transaction.TransactionDateTime.Value,
                                gateway.GetBatchTimeOffset(),
                                batches );

                            var batchChanges = new List<string>();
                            if ( batch.Id != 0 )
                            {
                                initialControlAmounts.AddOrIgnore( batch.Guid, batch.ControlAmount );
                            }
                            batch.ControlAmount += transaction.TotalAmount;

                            batch.Transactions.Add( transaction );

                            if ( txnAmount > 0.0M && receiptEmail.HasValue )
                            {
                                newTransactions.Add( transaction );
                            }

                            // Add summary
                            if ( !batchSummary.ContainsKey( batch.Guid ) )
                            {
                                batchSummary.Add( batch.Guid, new List<Decimal>() );
                            }
                            batchSummary[batch.Guid].Add( txnAmount );

                            if ( txnAmount > 0.0M )
                            {
                                totalAdded++;
                            }
                            else
                            {
                                totalReversals++;
                            }
                        }
                        else
                        {
                            totalAlreadyDownloaded++;

                            foreach ( var txn in txns.Where( t => t.Status != payment.Status || t.StatusMessage != payment.StatusMessage ) )
                            {
                                txn.Status = payment.Status;
                                txn.StatusMessage = payment.StatusMessage;
                                totalStatusChanges++;
                            }
                        }
                    }
                    else
                    {
                        totalNoScheduledTransaction++;
                    }
                }

                rockContext.SaveChanges();

                // Queue a transaction to update the status of all affected scheduled transactions
                var updatePaymentStatusTxn = new Rock.Transactions.UpdatePaymentStatusTransaction( gateway.Id, scheduledTransactionIds );
                Rock.Transactions.RockQueue.TransactionQueue.Enqueue( updatePaymentStatusTxn );

                if ( receiptEmail.HasValue )
                {
                    // Queue a transaction to send receipts
                    var newTransactionIds = newTransactions.Select( t => t.Id ).ToList();
                    var sendPaymentReceiptsTxn = new Rock.Transactions.SendPaymentReceipts( receiptEmail.Value, newTransactionIds );
                    Rock.Transactions.RockQueue.TransactionQueue.Enqueue( sendPaymentReceiptsTxn );
                }
            }

            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 ( totalStatusChanges > 0 )
            {
                sb.AppendFormat( "<li>{0} {1} previously downloaded but had a change of status.</li>", totalStatusChanges.ToString( "N0" ),
                ( totalStatusChanges == 1 ? "payment was" : "payments were" ) );
            }

            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" ) );

            if ( totalReversals > 0 )
            {
                sb.AppendFormat( "<li>{0} {1} added as a reversal to a previous transaction.</li>", totalReversals.ToString( "N0" ),
                    ( totalReversals == 1 ? "payment was" : "payments were" ) );
            }

            if ( totalStatusChanges > 0 )
            {
                sb.AppendFormat( "<li>{0} {1} previously downloaded but had a change of status.</li>", totalStatusChanges.ToString( "N0" ),
                    ( totalStatusChanges == 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.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.FormatAsCurrency(), batchName );
                }
            }

            return sb.ToString();
        }
 public abstract void PreRedirect(FinancialGateway financialGateway, PaymentInfo paymentInfo, List <GatewayAccountItem> SelectedAccounts, out string errorMessage);