Example #1
0
        /// <summary>
        /// Purchases one or more partner offers.
        /// </summary>
        /// <param name="order">The order to execute.</param>
        /// <returns>A transaction result which summarizes its outcome.</returns>
        public async Task <TransactionResult> PurchaseAsync(OrderViewModel order)
        {
            // use the normalizer to validate the order.
            OrderNormalizer orderNormalizer = new OrderNormalizer(ApplicationDomain, order);

            order = await orderNormalizer.NormalizePurchaseSubscriptionOrderAsync().ConfigureAwait(false);

            // build the purchase line items.
            List <PurchaseLineItem> purchaseLineItems = new List <PurchaseLineItem>();

            foreach (OrderSubscriptionItemViewModel orderItem in order.Subscriptions)
            {
                string offerId  = orderItem.OfferId;
                int    quantity = orderItem.Quantity;

                purchaseLineItems.Add(new PurchaseLineItem(offerId, quantity));
            }

            // associate line items in order to partner offers.
            IEnumerable <PurchaseLineItemWithOffer> lineItemsWithOffers = await AssociateWithPartnerOffersAsync(purchaseLineItems).ConfigureAwait(false);

            ICollection <IBusinessTransaction> subTransactions = new List <IBusinessTransaction>();

            // prepare payment authorization
            AuthorizePayment paymentAuthorization = new AuthorizePayment(PaymentGateway);

            subTransactions.Add(paymentAuthorization);

            BrandingConfiguration portalBranding = await ApplicationDomain.Instance.PortalBranding.RetrieveAsync().ConfigureAwait(false);

            // build the Partner Center order and pass it to the place order transaction
            Order partnerCenterPurchaseOrder = BuildPartnerCenterOrder(lineItemsWithOffers, portalBranding.BillingCycle);

            PlaceOrder placeOrder = new PlaceOrder(
                ApplicationDomain.PartnerCenterClient.Customers.ById(CustomerId),
                partnerCenterPurchaseOrder);

            subTransactions.Add(placeOrder);

            // configure a transaction to save the new resulting subscriptions and purchases into persistence
            PersistNewlyPurchasedSubscriptions persistSubscriptionsAndPurchases = new PersistNewlyPurchasedSubscriptions(
                CustomerId,
                ApplicationDomain.CustomerSubscriptionsRepository,
                ApplicationDomain.CustomerPurchasesRepository,
                () => new Tuple <Order, IEnumerable <PurchaseLineItemWithOffer> >(placeOrder.Result, lineItemsWithOffers));

            subTransactions.Add(persistSubscriptionsAndPurchases);

            // configure a capture payment transaction and let it read the auth code from the payment authorization output
            CapturePayment capturePayment = new CapturePayment(PaymentGateway, () => paymentAuthorization.Result);

            subTransactions.Add(capturePayment);

            // build an aggregated transaction from the previous steps and execute it as a whole
            await RunAggregatedTransaction(subTransactions).ConfigureAwait(false);

            return(new TransactionResult(persistSubscriptionsAndPurchases.Result, DateTime.UtcNow));
        }
Example #2
0
        /// <summary>
        /// Purchases additional seats for an existing subscription the customer has already bought.
        /// </summary>
        /// <param name="order">The order to execute.</param>
        /// <returns>A transaction result which summarizes its outcome.</returns>
        public async Task <TransactionResult> PurchaseAdditionalSeatsAsync(OrderViewModel order)
        {
            // use the normalizer to validate the order.
            OrderNormalizer orderNormalizer = new OrderNormalizer(ApplicationDomain, order);

            order = await orderNormalizer.NormalizePurchaseAdditionalSeatsOrderAsync().ConfigureAwait(false);

            List <OrderSubscriptionItemViewModel> orderSubscriptions = order.Subscriptions.ToList();
            string  subscriptionId     = orderSubscriptions.First().SubscriptionId;
            int     seatsToPurchase    = orderSubscriptions.First().Quantity;
            decimal proratedSeatCharge = orderSubscriptions.First().SeatPrice;
            string  partnerOfferId     = orderSubscriptions.First().PartnerOfferId;

            // we will add up the transactions here
            ICollection <IBusinessTransaction> subTransactions = new List <IBusinessTransaction>();

            // configure a transaction to charge the payment gateway with the prorated rate
            AuthorizePayment paymentAuthorization = new AuthorizePayment(PaymentGateway);

            subTransactions.Add(paymentAuthorization);

            // configure a purchase additional seats transaction with the requested seats to purchase
            subTransactions.Add(new PurchaseExtraSeats(
                                    ApplicationDomain.PartnerCenterClient.Customers.ById(CustomerId).Subscriptions.ById(subscriptionId),
                                    seatsToPurchase));

            DateTime rightNow = DateTime.UtcNow;

            // record the purchase in our purchase store
            subTransactions.Add(new RecordPurchase(
                                    ApplicationDomain.CustomerPurchasesRepository,
                                    new CustomerPurchaseEntity(CommerceOperationType.AdditionalSeatsPurchase, Guid.NewGuid().ToString(), CustomerId, subscriptionId, seatsToPurchase, proratedSeatCharge, rightNow)));

            // add a capture payment to the transaction pipeline
            subTransactions.Add(new CapturePayment(PaymentGateway, () => paymentAuthorization.Result));

            // build an aggregated transaction from the previous steps and execute it as a whole
            await RunAggregatedTransaction(subTransactions).ConfigureAwait(false);

            TransactionResultLineItem additionalSeatsPurchaseResult = new TransactionResultLineItem(
                subscriptionId,
                partnerOfferId,
                seatsToPurchase,
                proratedSeatCharge,
                seatsToPurchase * proratedSeatCharge);

            return(new TransactionResult(
                       new TransactionResultLineItem[] { additionalSeatsPurchaseResult },
                       rightNow));
        }
Example #3
0
        /// <summary>
        /// Renews an existing subscription for a customer.
        /// </summary>
        /// <param name="order">The order to execute.</param>
        /// <returns>A transaction result which summarizes its outcome.</returns>
        public async Task <TransactionResult> RenewSubscriptionAsync(OrderViewModel order)
        {
            // use the normalizer to validate the order.
            OrderNormalizer orderNormalizer = new OrderNormalizer(ApplicationDomain, order);

            order = await orderNormalizer.NormalizeRenewSubscriptionOrderAsync().ConfigureAwait(false);

            List <OrderSubscriptionItemViewModel> orderSubscriptions = order.Subscriptions.ToList();
            string   subscriptionId         = orderSubscriptions.First().SubscriptionId;
            string   partnerOfferId         = orderSubscriptions.First().PartnerOfferId;
            decimal  partnerOfferPrice      = orderSubscriptions.First().SeatPrice;
            DateTime subscriptionExpiryDate = orderSubscriptions.First().SubscriptionExpiryDate;
            int      quantity    = orderSubscriptions.First().Quantity;
            decimal  totalCharge = Math.Round(quantity * partnerOfferPrice, Resources.Culture.NumberFormat.CurrencyDecimalDigits);

            // retrieve the subscription from Partner Center
            Subscriptions.ISubscription subscriptionOperations = ApplicationDomain.PartnerCenterClient.Customers.ById(CustomerId).Subscriptions.ById(subscriptionId);
            PartnerCenter.Models.Subscriptions.Subscription partnerCenterSubscription = await subscriptionOperations.GetAsync().ConfigureAwait(false);

            // we will add up the transactions here
            ICollection <IBusinessTransaction> subTransactions = new List <IBusinessTransaction>();

            // configure a transaction to charge the payment gateway with the prorated rate
            AuthorizePayment paymentAuthorization = new AuthorizePayment(PaymentGateway);

            subTransactions.Add(paymentAuthorization);

            // add a renew subscription transaction to the pipeline
            subTransactions.Add(new RenewSubscription(
                                    subscriptionOperations,
                                    partnerCenterSubscription));

            DateTime rightNow = DateTime.UtcNow;

            // record the renewal in our purchase store
            subTransactions.Add(new RecordPurchase(
                                    ApplicationDomain.CustomerPurchasesRepository,
                                    new CustomerPurchaseEntity(CommerceOperationType.Renewal, Guid.NewGuid().ToString(), CustomerId, subscriptionId, partnerCenterSubscription.Quantity, partnerOfferPrice, rightNow)));

            DateTime expirationDate = subscriptionExpiryDate;
            BrandingConfiguration portalBranding = await ApplicationDomain.Instance.PortalBranding.RetrieveAsync().ConfigureAwait(false);

            switch (portalBranding.BillingCycle)
            {
            case BillingCycleType.Annual:
                expirationDate = expirationDate.AddYears(1);
                break;

            case BillingCycleType.Monthly:
                expirationDate = expirationDate.AddMonths(1);
                break;

            default:
                throw new NotImplementedException($"Billing cycle {portalBranding.BillingCycle} is not implemented");
            }

            // extend the expiry date by one month or one year
            subTransactions.Add(new UpdatePersistedSubscription(
                                    ApplicationDomain.CustomerSubscriptionsRepository,
                                    new CustomerSubscriptionEntity(CustomerId, subscriptionId, partnerOfferId, expirationDate)));

            // add a capture payment to the transaction pipeline
            subTransactions.Add(new CapturePayment(PaymentGateway, () => paymentAuthorization.Result));

            // run the pipeline
            await RunAggregatedTransaction(subTransactions).ConfigureAwait(false);

            TransactionResultLineItem renewSubscriptionResult = new TransactionResultLineItem(
                subscriptionId,
                partnerOfferId,
                partnerCenterSubscription.Quantity,
                partnerOfferPrice,
                totalCharge);

            return(new TransactionResult(
                       new TransactionResultLineItem[] { renewSubscriptionResult },
                       rightNow));
        }