/// <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(this.ApplicationDomain, order); order = await orderNormalizer.NormalizePurchaseSubscriptionOrderAsync(); // build the purchase line items. List <PurchaseLineItem> purchaseLineItems = new List <PurchaseLineItem>(); foreach (var 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. var lineItemsWithOffers = await this.AssociateWithPartnerOffersAsync(purchaseLineItems); ICollection <IBusinessTransaction> subTransactions = new List <IBusinessTransaction>(); // prepare payment authorization var paymentAuthorization = new AuthorizePayment(this.PaymentGateway); subTransactions.Add(paymentAuthorization); // build the Partner Center order and pass it to the place order transaction Order partnerCenterPurchaseOrder = this.BuildPartnerCenterOrder(lineItemsWithOffers); var placeOrder = new PlaceOrder( this.ApplicationDomain.PartnerCenterClient.Customers.ById(this.CustomerId), partnerCenterPurchaseOrder); subTransactions.Add(placeOrder); // configure a transaction to save the new resulting subscriptions and purchases into persistence var persistSubscriptionsAndPurchases = new PersistNewlyPurchasedSubscriptions( this.CustomerId, this.ApplicationDomain.CustomerSubscriptionsRepository, this.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 var capturePayment = new CapturePayment(this.PaymentGateway, () => paymentAuthorization.Result); subTransactions.Add(capturePayment); // build an aggregated transaction from the previous steps and execute it as a whole await CommerceOperations.RunAggregatedTransaction(subTransactions); return(new TransactionResult(persistSubscriptionsAndPurchases.Result, DateTime.UtcNow)); }
/// <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(this.ApplicationDomain, order); order = await orderNormalizer.NormalizePurchaseAdditionalSeatsOrderAsync(); 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 var paymentAuthorization = new AuthorizePayment(this.PaymentGateway); subTransactions.Add(paymentAuthorization); // configure a purchase additional seats transaction with the requested seats to purchase subTransactions.Add(new PurchaseExtraSeats( this.ApplicationDomain.PartnerCenterClient.Customers.ById(this.CustomerId).Subscriptions.ById(subscriptionId), seatsToPurchase)); DateTime rightNow = DateTime.UtcNow; // record the purchase in our purchase store subTransactions.Add(new RecordPurchase( this.ApplicationDomain.CustomerPurchasesRepository, new CustomerPurchaseEntity(CommerceOperationType.AdditionalSeatsPurchase, Guid.NewGuid().ToString(), this.CustomerId, subscriptionId, seatsToPurchase, proratedSeatCharge, rightNow))); // add a capture payment to the transaction pipeline subTransactions.Add(new CapturePayment(this.PaymentGateway, () => paymentAuthorization.Result)); // build an aggregated transaction from the previous steps and execute it as a whole await CommerceOperations.RunAggregatedTransaction(subTransactions); var additionalSeatsPurchaseResult = new TransactionResultLineItem( subscriptionId, partnerOfferId, seatsToPurchase, proratedSeatCharge, seatsToPurchase * proratedSeatCharge); return(new TransactionResult( new TransactionResultLineItem[] { additionalSeatsPurchaseResult }, rightNow)); }
/// <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(this.ApplicationDomain, order); order = await orderNormalizer.NormalizeRenewSubscriptionOrderAsync(); 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 var subscriptionOperations = this.ApplicationDomain.PartnerCenterClient.Customers.ById(this.CustomerId).Subscriptions.ById(subscriptionId); var partnerCenterSubscription = await subscriptionOperations.GetAsync(); // 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 var paymentAuthorization = new AuthorizePayment(this.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( this.ApplicationDomain.CustomerPurchasesRepository, new CustomerPurchaseEntity(CommerceOperationType.Renewal, Guid.NewGuid().ToString(), this.CustomerId, subscriptionId, partnerCenterSubscription.Quantity, partnerOfferPrice, rightNow))); // extend the expiry date by one year subTransactions.Add(new UpdatePersistedSubscription( this.ApplicationDomain.CustomerSubscriptionsRepository, new CustomerSubscriptionEntity(this.CustomerId, subscriptionId, partnerOfferId, subscriptionExpiryDate.AddYears(1)))); // add a capture payment to the transaction pipeline subTransactions.Add(new CapturePayment(this.PaymentGateway, () => paymentAuthorization.Result)); // run the pipeline await CommerceOperations.RunAggregatedTransaction(subTransactions); var renewSubscriptionResult = new TransactionResultLineItem( subscriptionId, partnerOfferId, partnerCenterSubscription.Quantity, partnerOfferPrice, totalCharge); return(new TransactionResult( new TransactionResultLineItem[] { renewSubscriptionResult }, rightNow)); }