private static decimal CalculateTransactionAmount( Payment payment, List<FinancialTransaction> transactions ) { decimal rockAmount = 0.0M; decimal processedAmount = payment.IsFailure ? 0.0M : payment.Amount; if ( transactions != null && transactions.Any() ) { rockAmount = transactions.Sum( t => t.TotalAmount ); } return processedAmount - rockAmount; }
/// <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( DateTime startDate, DateTime endDate, out string errorMessage ) { var reportingApi = new Reporting.Api( GetAttributeValue( "User" ), GetAttributeValue( "Vendor" ), GetAttributeValue( "Partner" ), GetAttributeValue( "Password" ), GetAttributeValue( "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" ) ); 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( "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_num", "false" ); customParams.Add( "show_amount", "true" ); customParams.Add( "show_result_code", "false" ); 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_transactio", "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_", "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_na", "false" ); customParams.Add( "show_shipping_last_na", "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(), i ); } } var txns = new List<Payment>(); var transactionIdParams = new Dictionary<string, string>(); transactionIdParams.Add( "transaction_id", string.Empty ); var creditCardTypes = DefinedTypeCache.Read( Rock.SystemGuid.DefinedType.FINANCIAL_CREDIT_CARD_TYPE.AsGuid() ).DefinedValues; foreach ( DataRow recurringBillingRow in recurringBillingTable.Rows ) { bool foundTxn = false; string transactionId = recurringBillingRow["Transaction ID"].ToString(); 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(); 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; }
/// <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( DateTime startDate, DateTime endDate, out string errorMessage ) { var reportingApi = new Reporting.Api( GetAttributeValue( "User" ), GetAttributeValue( "Vendor" ), GetAttributeValue( "Partner" ), GetAttributeValue( "Password" ) ); var reportParams = new Dictionary<string, string>(); reportParams.Add( "start_date", startDate.ToString( "yyyy-MM-dd HH:mm:ss" ) ); reportParams.Add( "end_date", endDate.ToString( "yyyy-MM-dd HH:mm:ss" ) ); DataTable dt = reportingApi.GetReport( "RecurringBillingReport", reportParams, out errorMessage ); if ( dt != null ) { var txns = new List<Payment>(); // The Recurring Billing Report items does not include the amounts for each transaction, so need // to do a transactionIDSearch to get the amount for each transaction reportParams = new Dictionary<string, string>(); reportParams.Add( "transaction_id", string.Empty ); foreach ( DataRow row in dt.Rows ) { reportParams["transaction_id"] = row["Transaction ID"].ToString(); DataTable dtTxn = reportingApi.GetSearch( "TransactionIDSearch", reportParams, out errorMessage ); if ( dtTxn != null && dtTxn.Rows.Count == 1 ) { var payment = new Payment(); decimal amount = decimal.MinValue; payment.Amount = decimal.TryParse( dtTxn.Rows[0]["Amount"].ToString(), out amount ) ? (amount / 100) : 0.0M; var time = DateTime.MinValue; payment.TransactionDateTime = DateTime.TryParse( row["Time"].ToString(), out time ) ? time : DateTime.MinValue; payment.TransactionCode = row["Transaction ID"].ToString(); payment.GatewayScheduleId = row["Profile ID"].ToString(); payment.ScheduleActive = row["Status"].ToString() == "Active"; txns.Add( payment ); } else { errorMessage = "The TransactionIDSearch report did not return a value for transaction: " + row["Transaction ID"].ToString(); return null; } } return txns; } errorMessage = "The RecurringBillingReport report did not return any data"; return null; }
/// <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; } }
/// <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" ) ) { string subscriptionId = GetXElementValue( xTxn, "original_transaction_id" ).Trim(); if ( !string.IsNullOrWhiteSpace( subscriptionId ) ) { Payment payment = null; var statusMessage = new StringBuilder(); 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(); } if ( payment == null && actionType == "sale" && GetXElementValue( xAction, "source" ) == "recurring" ) { decimal? txnAmount = GetXElementValue( xAction, "amount" ).AsDecimalOrNull(); if ( txnAmount.HasValue && actionDate.HasValue ) { payment = new Payment(); payment.Status = GetXElementValue( xTxn, "condition" ).FixCase(); payment.IsFailure = payment.Status == "Failed"; payment.StatusMessage = GetXElementValue( xTxn, "response_text" ); payment.Amount = txnAmount.Value; payment.TransactionDateTime = actionDate.Value; payment.TransactionCode = GetXElementValue( xTxn, "transaction_id" ); payment.GatewayScheduleId = subscriptionId; } } } if ( payment != null ) { 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; }