/// <summary>
 /// Constructor
 /// </summary>
 /// <param name="payment">The Payment object associated with this request</param>
 /// <param name="subscriptionPlan">The SubscriptionPlan associated witht this request</param>
 /// <param name="remoteIP">Remote IP of the user initiating the request</param>
 public AuthorizeRecurringTransactionRequest(Payment payment, SubscriptionPlan subscriptionPlan, string remoteIP) : base(payment, remoteIP)
 {
     this._TransactionOrigin = TransactionOrigin.Internet;
     if (subscriptionPlan != null)
     {
         this.SubscriptionName         = subscriptionPlan.Name;
         this.Amount                   = payment.Amount;
         this.RecurringChargeSpecified = subscriptionPlan.RecurringChargeSpecified;
         // GET THE SUBSCRIPTION CHARGE WITH TAX
         Order      order            = payment.Order;
         int        billToProvinceId = ProvinceDataSource.GetProvinceIdByName(order.BillToCountryCode, order.BillToProvince);
         TaxAddress billingAddress   = new TaxAddress(order.BillToCountryCode, billToProvinceId, order.BillToPostalCode);
         this.RecurringCharge      = TaxHelper.GetPriceWithTax(subscriptionPlan.RecurringCharge, subscriptionPlan.TaxCodeId, billingAddress, billingAddress);
         this.NumberOfPayments     = subscriptionPlan.NumberOfPayments;
         this.PaymentFrequency     = subscriptionPlan.PaymentFrequency;
         this.PaymentFrequencyUnit = subscriptionPlan.PaymentFrequencyUnit;
     }
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Generates payment records for an order
        /// </summary>
        /// <param name="order">The order being created</param>
        /// <param name="checkoutRequest">The checkout request</param>
        /// <param name="giftCertPayments">The collection of gift certificate payments for this order</param>
        /// <param name="giftCertPaymentMethodId">The ID of the gift certificate payment method</param>
        /// <param name="orderItemSubscriptions">Order Item subscriptions</param>
        internal static void GenerateOrderPayments(Order order, CheckoutRequest checkoutRequest, List <BasketPaymentItem> giftCertPayments, int giftCertPaymentMethodId, Dictionary <int, Subscription[]> orderItemSubscriptions)
        {
            //THIS VARIABLE SHOULD ONLY CONTAIN DATA IF POST-CHECKOUT GATEWAY PROCESSING IS REQUIRED
            string saveAccountData = string.Empty;
            //USE A COMMON DATE FOR ALL PAYMENTS REGISTERED
            DateTime paymentDate = LocaleHelper.LocalNow;
            //CONVERT GIFT CERTIFICATE PLACEHOLDERS INTO PAYMENT ITEMS
            LSDecimal totalGiftCertPayment = 0;

            foreach (BasketPaymentItem giftCertItem in giftCertPayments)
            {
                Payment giftCertPayment = giftCertItem.GetPaymentObject();
                totalGiftCertPayment           += giftCertPayment.Amount;
                giftCertPayment.OrderId         = order.OrderId;
                giftCertPayment.PaymentMethodId = giftCertPaymentMethodId;
                giftCertPayment.PaymentDate     = paymentDate;
                order.Payments.Add(giftCertPayment);
                giftCertPayment.Save();
            }
            //IF PAYMENT DATA WAS PASSED WITH CHECKOUT REQUEST, ADD TO ORDER RECORD NOW
            if (checkoutRequest != null && checkoutRequest.Payment != null)
            {
                //BUILD A LIST OF PAYMENTS TO ADD TO THE ORDER BASED ON CONTENTS
                Payment originalPayment = checkoutRequest.Payment;
                //DETERMINE TOTAL PAYMENT REQUIRED FOR ITEMS
                LSDecimal remainingPaymentAmount = order.Items.TotalPrice();
                //PRESERVE ACCOUNT DATA
                saveAccountData = originalPayment.AccountData;
                //DECIDE WHETHER PAYMENTS MUST BE DIVIDED BECAUSE OF ARB SUBSCRIPTIONS
                if (orderItemSubscriptions.Count > 0)
                {
                    //LOOP EACH ORDER ITEM WITH A RECURRING SUBSCRIPTION
                    foreach (int orderItemId in orderItemSubscriptions.Keys)
                    {
                        // THIS STORES THE DISCOUNT TO APPLY TO EACH SUBSCRIPTION PAYMENT
                        LSDecimal subscriptionDiscount = 0;
                        // THIS STORES ADDITIONAL DISCOUNT TO APPLY ONLY TO THE FIRST SUBSCRIPTION
                        LSDecimal firstSubscriptionAdjustment = 0;
                        // GET THE TOTAL DISCOUNTS APPLIED TO THIS ORDER ITEM (VALUE SHOULD BE NEGATIVE)
                        LSDecimal totalItemAdjustments = GetOrderItemAdjustments(order, orderItemId);
                        // IF THERE IS A DISCOUNT, DETERMINE PRO-RATED DISCOUNT FOR EACH PAYMENT (ITEM)
                        if (totalItemAdjustments != 0)
                        {
                            // THERE IS A DISCOUNT THAT APPLIES TO THIS ORDER ITEM, WE NEED TO DETERMINE AMOUNT
                            // SUBSCRIPTION DISCOUNT IS TOTAL DISCOUNT BY THE NUMBER OF SUBSCRIPTION ITEMS
                            subscriptionDiscount = (LSDecimal)Math.Floor((decimal)(totalItemAdjustments / orderItemSubscriptions[orderItemId].Length));
                            // DETERMINE THE TOTAL DISCOUNT AMOUNT USING CALCULATED PER-SUBSCRIPTION VALUE
                            LSDecimal calculatedTotal = subscriptionDiscount * orderItemSubscriptions[orderItemId].Length;
                            // THE TOTAL DISCOUNT MUST MATCH THE LUMP SUM, SO CALCULATE ANY LEFTOVER DISCOUNT FOR THE FIRST PAYMENT
                            firstSubscriptionAdjustment = (totalItemAdjustments - calculatedTotal);
                        }

                        // WE MUST DETERMINE THE PRICE OF THE ITEM (INCLUDING TAX)
                        // GET THE ORDER ITEM FOR THIS RECURRING SUBSCRIPTION
                        OrderItem orderItem = order.Items[order.Items.IndexOf(orderItemId)];
                        // GET THE PRICE OF THE ITEM (INCLUDING TAX)
                        int        billToProvinceId  = ProvinceDataSource.GetProvinceIdByName(order.BillToCountryCode, order.BillToProvince);
                        TaxAddress billingAddress    = new TaxAddress(order.BillToCountryCode, billToProvinceId, order.BillToPostalCode);
                        LSDecimal  subscriptionPrice = TaxHelper.GetPriceWithTax(orderItem.Price + subscriptionDiscount, orderItem.TaxCodeId, billingAddress, billingAddress);

                        // LOOP ALL THE SUBSCRIPTIONS AND CREATE CORRESPONDING PAYMENT ITEMS
                        foreach (Subscription s in orderItemSubscriptions[orderItemId])
                        {
                            // ADD PAYMENT ITEM ASSOCIATED WITH THE SUBSCRIPTION
                            Payment arbPayment = new Payment();
                            arbPayment.SubscriptionId    = s.SubscriptionId;
                            arbPayment.Amount            = subscriptionPrice + firstSubscriptionAdjustment;
                            arbPayment.CurrencyCode      = originalPayment.CurrencyCode;
                            arbPayment.OrderId           = order.OrderId;
                            arbPayment.PaymentDate       = paymentDate;
                            arbPayment.PaymentMethodId   = originalPayment.PaymentMethodId;
                            arbPayment.PaymentMethodName = originalPayment.PaymentMethodName;
                            arbPayment.PaymentStatus     = PaymentStatus.Unprocessed;
                            arbPayment.ReferenceNumber   = originalPayment.ReferenceNumber;
                            arbPayment.AccountData       = saveAccountData;
                            order.Payments.Add(arbPayment);
                            arbPayment.Save();

                            //ACCOUNT DATA IS RESET AFTER SAVE IN CASE THE SAVE METHOD ALTERS IT BASED
                            //ON MERCHANT SECURITY SETTINGS, WE STILL NEED THE VALUE FOR THE CHECKOUT PROCESS
                            arbPayment.AccountData = saveAccountData;
                            arbPayment.IsDirty     = false;

                            // SUBTRACT THIS PAYMENT FROM THE REMAINING TOTAL
                            remainingPaymentAmount -= arbPayment.Amount;

                            // RESET ADJUSTMENT THAT SHOULD APPLY TO FIRST SUBSCRIPTION ONLY
                            firstSubscriptionAdjustment = 0;
                        }
                    }

                    //CREATE AN ADDITIONAL PAYMENT IF THERE IS ANY AMOUNT LEFT TO BE COLLECTED
                    if (remainingPaymentAmount > 0)
                    {
                        //NEED ONE PAYMENT FOR EACH SUBSCRIPTION
                        Payment remainingPayment = new Payment();
                        remainingPayment.SubscriptionId = 0;
                        if (remainingPaymentAmount >= originalPayment.Amount)
                        {
                            remainingPayment.Amount = originalPayment.Amount;
                        }
                        else
                        {
                            remainingPayment.Amount = remainingPaymentAmount;
                        }
                        remainingPayment.CurrencyCode      = originalPayment.CurrencyCode;
                        remainingPayment.OrderId           = order.OrderId;
                        remainingPayment.PaymentDate       = paymentDate;
                        remainingPayment.PaymentMethodId   = originalPayment.PaymentMethodId;
                        remainingPayment.PaymentMethodName = originalPayment.PaymentMethodName;
                        remainingPayment.PaymentStatus     = PaymentStatus.Unprocessed;
                        remainingPayment.ReferenceNumber   = originalPayment.ReferenceNumber;
                        remainingPayment.AccountData       = saveAccountData;
                        order.Payments.Add(remainingPayment);
                        remainingPayment.Save();
                        //ACCOUNT DATA IS RESET AFTER SAVE IN CASE THE SAVE METHOD ALTERS IT BASED
                        //ON MERCHANT SECURITY SETTINGS, WE STILL NEED THE VALUE FOR THE CHECKOUT PROCESS
                        remainingPayment.AccountData = saveAccountData;
                        remainingPayment.IsDirty     = false;
                    }
                }
                else
                {
                    originalPayment.PaymentId      = 0;
                    originalPayment.SubscriptionId = 0;
                    originalPayment.PaymentStatus  = PaymentStatus.Unprocessed;
                    originalPayment.OrderId        = order.OrderId;
                    originalPayment.PaymentDate    = paymentDate;
                    order.Payments.Add(originalPayment);
                    originalPayment.Save();
                    //ACCOUNT DATA IS RESET AFTER SAVE IN CASE THE SAVE METHOD ALTERS IT BASED
                    //ON MERCHANT SECURITY SETTINGS, WE STILL NEED THE VALUE FOR THE CHECKOUT PROCESS
                    originalPayment.AccountData = saveAccountData;
                    originalPayment.IsDirty     = false;
                }
            }
        }