public void SetBranding(UserAccount currentUser)
        {
            if (currentUser != null)
            {
                BrandingConfiguration brandingConfiguration = CompanyProfileServiceFacade.RetrieveBrandingConfigurationByHierarchy(new BrandingConfigurationHierarchy()
                {
                    BranchId   = currentUser.BranchId,
                    ChannelId  = currentUser.ChannelId,
                    DivisionId = currentUser.DivisionId
                });

                if (brandingConfiguration != null)
                {
                    HttpContext.Current.Session[SessionHelper.BrandName]             = brandingConfiguration.DisplayName;
                    HttpContext.Current.Session[SessionHelper.StyleSheetTheme]       = brandingConfiguration.Theme;
                    HttpContext.Current.Session[SessionHelper.BrandNameShort]        = brandingConfiguration.NameShort;
                    HttpContext.Current.Session[SessionHelper.BrandNameDomain]       = brandingConfiguration.Url;
                    HttpContext.Current.Session[SessionHelper.BrandPhone]            = brandingConfiguration.Phone;
                    HttpContext.Current.Session[SessionHelper.CompanyCopyrightName]  = brandingConfiguration.CopyrightName;
                    HttpContext.Current.Session[SessionHelper.CompanyProfileId]      = brandingConfiguration.CompanyProfileId;
                    HttpContext.Current.Session[SessionHelper.BrandingConfiguration] = brandingConfiguration;
                    HttpContext.Current.Session[SessionHelper.BrandNameCssFile]      = brandingConfiguration.BrandNameCssFile;
                    HttpContext.Current.Session[SessionHelper.BrandingConfiguration] = brandingConfiguration;
                }
            }
        }
        /// <summary>
        /// Retrieves the portal branding.
        /// </summary>
        /// <returns>The portal branding information.</returns>
        public async Task <Models.BrandingConfiguration> RetrieveAsync()
        {
            //BrandingConfiguration portalBranding = await ApplicationDomain.CachingService
            //    .FetchAsync<BrandingConfiguration>(PortalBrandingCacheKey).ConfigureAwait(false);

            //if (portalBranding == null)
            //{
            CloudBlockBlob portalBrandingBlob = await GetPortalBrandingBlobAsync().ConfigureAwait(false);

            BrandingConfiguration portalBranding = new BrandingConfiguration();

            if (await portalBrandingBlob.ExistsAsync().ConfigureAwait(false))
            {
                portalBranding = JsonConvert.DeserializeObject <BrandingConfiguration>(await portalBrandingBlob.DownloadTextAsync().ConfigureAwait(false));
                await NormalizeAsync(portalBranding).ConfigureAwait(false);
            }
            else
            {
                // portal branding has not been configured yet
                portalBranding.OrganizationName = Resources.DefaultOrganizationName;
            }

            // cache the portal branding
            //await ApplicationDomain.CachingService.StoreAsync(
            //    PortalBrandingCacheKey,
            //    portalBranding).ConfigureAwait(false);
            //}

            return(portalBranding);
        }
        /// <summary>
        /// Retrieves the portal branding.
        /// </summary>
        /// <returns>The portal branding information.</returns>
        public async Task <BrandingConfiguration> RetrieveAsync()
        {
            var portalBranding = await this.ApplicationDomain.CachingService
                                 .FetchAsync <BrandingConfiguration>(PortalBranding.PortalBrandingCacheKey);

            if (portalBranding == null)
            {
                var portalBrandingBlob = await this.GetPortalBrandingBlobAsync();

                portalBranding = new BrandingConfiguration();

                if (await portalBrandingBlob.ExistsAsync())
                {
                    portalBranding = JsonConvert.DeserializeObject <BrandingConfiguration>(await portalBrandingBlob.DownloadTextAsync());
                    await this.NormalizeAsync(portalBranding);
                }
                else
                {
                    // portal branding has not been configured yet
                    portalBranding.OrganizationName = Resources.DefaultOrganizationName;
                }

                // cache the portal branding
                await this.ApplicationDomain.CachingService.StoreAsync <BrandingConfiguration>(
                    PortalBranding.PortalBrandingCacheKey,
                    portalBranding);
            }

            return(portalBranding);
        }
Beispiel #4
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));
        }
        public GetStarted GetStarted(HttpContextBase httpContext, UserAccount user, Guid token, String username, bool isEmbedded, Int32?contactId = null, Guid?loanId = null, int?openInterviewPage = null, bool?isTempUser = false, Guid?parentLoanId = null, string sectionTitle = null)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(GetChannelBorrowerSiteURL(user.UserAccountId));
            sb.Append("LoanRequest.aspx?impersonateUser=1");
            if (openInterviewPage.Equals(1))
            {
                sb.Append("&openInterviewPage=1");
            }
            sb.Append("&token=");
            sb.Append(httpContext.Server.UrlEncode(EncryptionHelper.EncryptRijndael(token.ToString(), EncriptionKeys.Default)));
            sb.Append("&uname=");  // username of new created account
            sb.Append(httpContext.Server.UrlEncode(EncryptionHelper.EncryptRijndael(username, EncriptionKeys.Default)));
            sb.Append("&cuid=");   // concierge Id
            sb.Append(httpContext.Server.UrlEncode(EncryptionHelper.EncryptRijndael(user.UserAccountId.ToString(), EncriptionKeys.Default)));
            sb.Append("&chid=");
            BrandingConfiguration bc = (BrandingConfiguration)httpContext.Session[SessionHelper.BrandingConfiguration];

            sb.Append(bc == null ? 0 : bc.ChannelId);
            if (contactId != null && contactId != -1)
            {
                sb.Append("&contactId=");   // contact Id of the contact associated with new user account
                sb.Append(httpContext.Server.UrlEncode(EncryptionHelper.EncryptRijndael(contactId.ToString(), EncriptionKeys.Default)));
            }
            if (loanId != null && loanId != Guid.Empty)
            {
                sb.Append("&lid=");
                sb.Append(httpContext.Server.UrlEncode(EncryptionHelper.EncryptRijndael(loanId.ToString(), EncriptionKeys.Default)));
            }

            sb.Append("&isEmbedded=");
            sb.Append(isEmbedded ? "1" : "0");

            sb.Append("&isTempUser="******"1" : "0");

            sb.Append("&LoanCenter=1");

            if (parentLoanId != null)
            {
                sb.Append("&plid=").Append(httpContext.Server.UrlEncode(EncryptionHelper.EncryptRijndael(parentLoanId.ToString(), EncriptionKeys.Default)));
            }

            return(new GetStarted()
            {
                BorrowerUrl = sb.ToString(), SectionTitle = !string.IsNullOrEmpty(sectionTitle) ? sectionTitle : "Start a Prospect/New Loan"
            });
        }
        /// <summary>
        /// Updates the portal branding.
        /// </summary>
        /// <param name="updatedBrandingConfiguration">The new portal branding.</param>
        /// <returns>The updated portal branding.</returns>
        public async Task <BrandingConfiguration> UpdateAsync(BrandingConfiguration updatedBrandingConfiguration)
        {
            updatedBrandingConfiguration.AssertNotNull(nameof(updatedBrandingConfiguration));

            await this.NormalizeAsync(updatedBrandingConfiguration);

            var portalBrandingBlob = await this.GetPortalBrandingBlobAsync();

            await portalBrandingBlob.UploadTextAsync(JsonConvert.SerializeObject(updatedBrandingConfiguration));

            // invalidate the cache, we do not update it to avoid race condition between web instances
            await this.ApplicationDomain.CachingService.ClearAsync(PortalBranding.PortalBrandingCacheKey);

            return(updatedBrandingConfiguration);
        }
        /// <summary>
        /// Updates the portal branding.
        /// </summary>
        /// <param name="updatedBrandingConfiguration">The new portal branding.</param>
        /// <returns>The updated portal branding.</returns>
        public async Task <BrandingConfiguration> UpdateAsync(BrandingConfiguration updatedBrandingConfiguration)
        {
            updatedBrandingConfiguration.AssertNotNull(nameof(updatedBrandingConfiguration));

            await NormalizeAsync(updatedBrandingConfiguration).ConfigureAwait(false);

            CloudBlockBlob portalBrandingBlob = await GetPortalBrandingBlobAsync().ConfigureAwait(false);

            await portalBrandingBlob.UploadTextAsync(JsonConvert.SerializeObject(updatedBrandingConfiguration)).ConfigureAwait(false);

            // invalidate the cache, we do not update it to avoid race condition between web instances
            await ApplicationDomain.CachingService.ClearAsync(PortalBrandingCacheKey).ConfigureAwait(false);

            // re-initialize the telemetry service because the configuration might have changed.
            await ApplicationDomain.TelemetryService.InitializeAsync().ConfigureAwait(false);

            return(updatedBrandingConfiguration);
        }
        public async Task <ActionResult> Home()
        {
            BrandingConfiguration portalBranding = await ApplicationDomain.Instance.PortalBranding.RetrieveAsync().ConfigureAwait(false);

            if (portalBranding.HeaderImage != null)
            {
                ViewBag.HeaderImage = portalBranding.HeaderImage.ToString();
            }

            if (portalBranding.PrivacyAgreement != null)
            {
                ViewBag.PrivacyAgreement = portalBranding.PrivacyAgreement.ToString();
            }

            CustomerPortalPrincipal principal = HttpContext.User as CustomerPortalPrincipal;

            ViewBag.OrganizationName = portalBranding.OrganizationName;
            ViewBag.IsPortalAdmin    = principal.IsPortalAdmin;

            return(PartialView());
        }
Beispiel #9
0
        public async Task <PaymentConfiguration> UpdatePaymentConfiguration(PaymentConfiguration paymentConfiguration)
        {
            // validate the payment configuration before saving.
            PayPalGateway.ValidateConfiguration(paymentConfiguration);

            // check if branding configuration has been setup else don't create web experience profile.
            bool isBrandingConfigured = await ApplicationDomain.Instance.PortalBranding.IsConfiguredAsync();

            if (isBrandingConfigured)
            {
                // create a web experience profile using the branding for the web store.
                BrandingConfiguration brandConfig = await ApplicationDomain.Instance.PortalBranding.RetrieveAsync();

                paymentConfiguration.WebExperienceProfileId = PayPalGateway.CreateWebExperienceProfile(paymentConfiguration, brandConfig, ApplicationDomain.Instance.PortalLocalization.CountryIso2Code);
            }

            // Save the validated & complete payment configuration to repository.
            PaymentConfiguration paymentConfig = await ApplicationDomain.Instance.PaymentConfigurationRepository.UpdateAsync(paymentConfiguration);

            return(paymentConfig);
        }
        public async Task <ActionResult> FrameworkFragments()
        {
            WebPortalConfigurationManager builder = ApplicationConfiguration.WebPortalConfigurationManager;

            ViewBag.Templates = (await builder.AggregateNonStartupAssets().ConfigureAwait(false)).Templates;

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

            ViewBag.OrganizationName = portalBranding.OrganizationName;

            if (portalBranding.OrganizationLogo != null)
            {
                ViewBag.OrganizationLogo = portalBranding.OrganizationLogo.ToString();
            }

            ViewBag.ContactUs    = portalBranding.ContactUs;
            ViewBag.ContactSales = portalBranding.ContactSales;

            ViewBag.CurrencySymbol = ApplicationDomain.Instance.PortalLocalization.CurrencySymbol;

            return(PartialView());
        }
        protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            try
            {
                if (Context.Handler is IRequiresSessionState)
                {
                    if (Session[SessionHelper.BrandName] == null || Session[SessionHelper.StyleSheetTheme] == null ||
                        Session[SessionHelper.BrandNameShort] == null || Session[SessionHelper.BrandNameDomain] == null ||
                        Session[SessionHelper.BrandPhone] == null || Session[SessionHelper.CompanyCopyrightName] == null ||
                        Session[SessionHelper.CompanyProfileId] == null)
                    {
                        BrandingConfiguration brandingConfiguration = CompanyProfileServiceFacade.RetrieveBrandingConfiguration(StringHelper.FixUrl(Context.Request.Url.Host));

                        if (brandingConfiguration != null)
                        {
                            Session[SessionHelper.BrandName]             = brandingConfiguration.DisplayName;
                            Session[SessionHelper.StyleSheetTheme]       = brandingConfiguration.Theme;
                            Session[SessionHelper.BrandNameShort]        = brandingConfiguration.NameShort;
                            Session[SessionHelper.BrandNameDomain]       = brandingConfiguration.Url;
                            Session[SessionHelper.BrandPhone]            = brandingConfiguration.Phone;
                            Session[SessionHelper.CompanyCopyrightName]  = brandingConfiguration.CopyrightName;
                            Session[SessionHelper.CompanyProfileId]      = brandingConfiguration.CompanyProfileId;
                            Session[SessionHelper.BrandingConfiguration] = brandingConfiguration;
                            Session[SessionHelper.BrandNameCssFile]      = brandingConfiguration.BrandNameCssFile;
                            Session[SessionHelper.BrandingConfiguration] = brandingConfiguration;
                        }
                    }
                }

                // CDNHelper.SetCdnSettingInSession();
                BundleConfig.RegisterBundles(BundleTable.Bundles);
            }
            catch (Exception ex)
            {
                TraceHelper.Error(TraceCategory.Global, "Error occurred in Global.asax.cs  - Application_PreRequestHandlerExecute()!", ex, Guid.Empty, -1);
            }
        }
        /// <summary>
        /// Gets the subscriptions managed by customers and partners
        /// </summary>
        /// <returns>returns managed subscriptions view model</returns>
        private async Task <ManagedSubscriptionsViewModel> GetManagedSubscriptions()
        {
            DateTime startTime = DateTime.Now;

            string clientCustomerId = Principal.PartnerCenterCustomerId;

            // responseCulture determines decimals, currency and such
            CultureInfo responseCulture = new CultureInfo(ApplicationDomain.Instance.PortalLocalization.Locale);

            // localeSpecificApiClient allows pulling offer names localized to supported portal locales compatible with Offer API supported locales.
            IPartner localeSpecificPartnerCenterClient = ApplicationDomain.Instance.PartnerCenterClient.With(RequestContextFactory.Instance.Create(ApplicationDomain.Instance.PortalLocalization.OfferLocale));

            // Get all subscriptions of customer from PC
            ResourceCollection <Subscription> customerAllSubscriptions = await localeSpecificPartnerCenterClient.Customers.ById(clientCustomerId).Subscriptions.GetAsync().ConfigureAwait(false);

            IEnumerable <CustomerSubscriptionEntity> customerSubscriptions = await ApplicationDomain.Instance.CustomerSubscriptionsRepository.RetrieveAsync(clientCustomerId).ConfigureAwait(false);

            IEnumerable <PartnerOffer> allPartnerOffers = await ApplicationDomain.Instance.OffersRepository.RetrieveAsync().ConfigureAwait(false);

            IEnumerable <MicrosoftOffer> currentMicrosoftOffers = await ApplicationDomain.Instance.OffersRepository.RetrieveMicrosoftOffersAsync().ConfigureAwait(false);

            List <SubscriptionViewModel> customerSubscriptionsView = new List <SubscriptionViewModel>();

            // iterate through and build the list of customer's subscriptions.
            foreach (CustomerSubscriptionEntity subscription in customerSubscriptions)
            {
                PartnerOffer partnerOfferItem  = allPartnerOffers.FirstOrDefault(offer => offer.Id == subscription.PartnerOfferId);
                string       subscriptionTitle = partnerOfferItem.Title;
                string       portalOfferId     = partnerOfferItem.Id;
                decimal      portalOfferPrice  = partnerOfferItem.Price;

                DateTime subscriptionExpiryDate = subscription.ExpiryDate.ToUniversalTime();
                int      remainingDays          = (subscriptionExpiryDate.Date - DateTime.UtcNow.Date).Days;
                bool     isRenewable            = remainingDays <= 30;                                 // IsRenewable is true if subscription is going to expire in 30 days.
                bool     isEditable             = DateTime.UtcNow.Date <= subscriptionExpiryDate.Date; // IsEditable is true if today is lesser or equal to subscription expiry date.

                // Temporarily mark this partnerOffer item as inactive and dont allow store front customer to manage this subscription.
                MicrosoftOffer alignedMicrosoftOffer = currentMicrosoftOffers.FirstOrDefault(offer => offer.Offer.Id == partnerOfferItem.MicrosoftOfferId);

                if (alignedMicrosoftOffer == null)
                {
                    // The offer is inactive (marked for deletion) then dont allow renewals or editing on this subscription tied to this offer.
                    partnerOfferItem.IsInactive = true;
                    isRenewable = false;
                    isEditable  = false;
                }

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

                // Compute the pro rated price per seat for this subcription & return for client side processing during updates.
                decimal proratedPerSeatPrice = Math.Round(CommerceOperations.CalculateProratedSeatCharge(subscription.ExpiryDate,
                                                                                                         portalOfferPrice,
                                                                                                         portalBranding.BillingCycle),
                                                          Resources.Culture.NumberFormat.CurrencyDecimalDigits);

                SubscriptionViewModel subscriptionItem = new SubscriptionViewModel()
                {
                    SubscriptionId            = subscription.SubscriptionId,
                    FriendlyName              = subscriptionTitle,
                    PortalOfferId             = portalOfferId,
                    PortalOfferPrice          = portalOfferPrice.ToString("C", responseCulture),
                    IsRenewable               = isRenewable,
                    IsEditable                = isEditable,
                    SubscriptionExpiryDate    = subscriptionExpiryDate.Date.ToString("d", responseCulture),
                    SubscriptionProRatedPrice = proratedPerSeatPrice
                };

                // add this subcription to the customer's subscription list.
                customerSubscriptionsView.Add(subscriptionItem);
            }

            List <CustomerSubscriptionModel> customerManagedSubscriptions = new List <CustomerSubscriptionModel>();
            List <PartnerSubscriptionModel>  partnerManagedSubscriptions  = new List <PartnerSubscriptionModel>();

            // Divide the subscriptions by customer and partner
            foreach (Subscription customerSubscriptionFromPC in customerAllSubscriptions.Items)
            {
                SubscriptionViewModel subscription = customerSubscriptionsView.FirstOrDefault(sub => sub.SubscriptionId == customerSubscriptionFromPC.Id);

                // Customer managed subscription found
                if (subscription != null)
                {
                    CustomerSubscriptionModel customerSubscription = new CustomerSubscriptionModel()
                    {
                        SubscriptionId            = customerSubscriptionFromPC.Id,
                        LicensesTotal             = customerSubscriptionFromPC.Quantity.ToString("G", responseCulture),
                        Status                    = GetStatusType(customerSubscriptionFromPC.Status),
                        CreationDate              = customerSubscriptionFromPC.CreationDate.ToString("d", responseCulture),
                        FriendlyName              = subscription.FriendlyName,
                        IsRenewable               = subscription.IsRenewable,
                        IsEditable                = subscription.IsEditable,
                        PortalOfferId             = subscription.PortalOfferId,
                        SubscriptionProRatedPrice = subscription.SubscriptionProRatedPrice
                    };

                    customerManagedSubscriptions.Add(customerSubscription);
                }
                else
                {
                    PartnerSubscriptionModel partnerSubscription = new PartnerSubscriptionModel()
                    {
                        Id           = customerSubscriptionFromPC.Id,
                        OfferName    = customerSubscriptionFromPC.OfferName,
                        Quantity     = customerSubscriptionFromPC.Quantity.ToString("G", responseCulture),
                        Status       = GetStatusType(customerSubscriptionFromPC.Status),
                        CreationDate = customerSubscriptionFromPC.CreationDate.ToString("d", responseCulture),
                    };

                    partnerManagedSubscriptions.Add(partnerSubscription);
                }
            }

            ManagedSubscriptionsViewModel managedSubscriptions = new ManagedSubscriptionsViewModel()
            {
                CustomerManagedSubscriptions = customerManagedSubscriptions.OrderByDescending(customerManagedSubscription => customerManagedSubscription.CreationDate),
                PartnerManagedSubscriptions  = partnerManagedSubscriptions.OrderByDescending(partnerManagedSubscription => partnerManagedSubscription.CreationDate)
            };

            // Capture the request for customer managed subscriptions and partner managed subscriptions for analysis.
            Dictionary <string, string> eventProperties = new Dictionary <string, string> {
                { "CustomerId", clientCustomerId }
            };

            // Track the event measurements for analysis.
            Dictionary <string, double> eventMetrics = new Dictionary <string, double> {
                { "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds }, { "CustomerManagedSubscriptions", customerManagedSubscriptions.Count }, { "PartnerManagedSubscriptions", partnerManagedSubscriptions.Count }
            };

            ApplicationDomain.Instance.TelemetryService.Provider.TrackEvent("GetManagedSubscriptions", eventProperties, eventMetrics);

            return(managedSubscriptions);
        }
        /// <summary>
        /// Applies business rules to <see cref="BrandingConfiguration"/> instances.
        /// </summary>
        /// <param name="brandingConfiguration">A branding configuration instance.</param>
        /// <returns>A task.</returns>
        private async Task NormalizeAsync(BrandingConfiguration brandingConfiguration)
        {
            brandingConfiguration.AssertNotNull(nameof(brandingConfiguration));

            brandingConfiguration.OrganizationName.AssertNotEmpty("OrganizationName");

            if (brandingConfiguration.ContactUs == null)
            {
                throw new PartnerDomainException(ErrorCode.InvalidInput, "ContactUs section not found in portal branding configuration").AddDetail("Field", "ContactUs");
            }

            brandingConfiguration.ContactUs.Email.AssertNotEmpty("Email");

            try
            {
                new MailAddress(brandingConfiguration.ContactUs.Email);
            }
            catch (FormatException)
            {
                throw new PartnerDomainException(ErrorCode.InvalidInput, "Invalid contact us email address").AddDetail("Field", "ContactUs.Email");
            }

            try
            {
                brandingConfiguration.ContactUs.Phone.AssertNotEmpty("ContactUs.Phone");
            }
            catch (ArgumentException)
            {
                throw new PartnerDomainException(ErrorCode.InvalidInput, "Invalid contact us phone").AddDetail("Field", "ContactUs.Phone");
            }

            if (brandingConfiguration.ContactSales == null)
            {
                // default the contact sales to the contact us information
                brandingConfiguration.ContactSales = new ContactUsInformation()
                {
                    Email = brandingConfiguration.ContactUs.Email,
                    Phone = brandingConfiguration.ContactUs.Phone
                };
            }
            else
            {
                if (string.IsNullOrWhiteSpace(brandingConfiguration.ContactSales.Email))
                {
                    brandingConfiguration.ContactSales.Email = brandingConfiguration.ContactUs.Email;
                }
                else
                {
                    try
                    {
                        new MailAddress(brandingConfiguration.ContactSales.Email);
                    }
                    catch (FormatException)
                    {
                        throw new PartnerDomainException(ErrorCode.InvalidInput, "Invalid contact sales email address").AddDetail("Field", "ContactSales.Email");
                    }
                }

                if (string.IsNullOrWhiteSpace(brandingConfiguration.ContactSales.Phone))
                {
                    brandingConfiguration.ContactSales.Phone = brandingConfiguration.ContactUs.Phone;
                }
                else
                {
                    try
                    {
                        brandingConfiguration.ContactSales.Phone.AssertNotEmpty("ContactSales.Phone");
                    }
                    catch (ArgumentException)
                    {
                        throw new PartnerDomainException(ErrorCode.InvalidInput, "Invalid contact sales phone").AddDetail("Field", "ContactSales.Phone");
                    }
                }
            }

            if (brandingConfiguration.OrganizationLogoContent != null)
            {
                // there is an logo image specified, upload it to BLOB storage and setup the URI property to point to it
                brandingConfiguration.OrganizationLogo = await this.UploadStreamToBlobStorageAsync(
                    "OrganizationLogo",
                    brandingConfiguration.OrganizationLogoContent);

                brandingConfiguration.OrganizationLogoContent = null;
            }

            if (brandingConfiguration.HeaderImageContent != null)
            {
                // there is a header image specified, upload it to BLOB storage and setup the URI property to point to it
                brandingConfiguration.HeaderImage = await this.UploadStreamToBlobStorageAsync(
                    "HeaderImage",
                    brandingConfiguration.HeaderImageContent);

                brandingConfiguration.HeaderImageContent = null;
            }
        }
        public async Task <BrandingConfiguration> UpdateBrandingConfiguration()
        {
            BrandingConfiguration brandingConfiguration = new BrandingConfiguration()
            {
                AgreementUserId  = HttpContext.Current.Request.Form["AgreementUserId"],
                OrganizationName = HttpContext.Current.Request.Form["OrganizationName"],
                ContactUs        = new ContactUsInformation()
                {
                    Email = HttpContext.Current.Request.Form["ContactUsEmail"],
                    Phone = HttpContext.Current.Request.Form["ContactUsPhone"],
                },
                ContactSales = new ContactUsInformation()
                {
                    Email = HttpContext.Current.Request.Form["ContactSalesEmail"],
                    Phone = HttpContext.Current.Request.Form["ContactSalesPhone"],
                }
            };

            string         organizationLogo           = HttpContext.Current.Request.Form["OrganizationLogo"];
            HttpPostedFile organizationLogoPostedFile = HttpContext.Current.Request.Files["OrganizationLogoFile"];

            if (organizationLogoPostedFile != null && Path.GetFileName(organizationLogoPostedFile.FileName) == organizationLogo)
            {
                // there is a new organization logo to be uploaded
                if (!organizationLogoPostedFile.ContentType.Trim().StartsWith("image/", StringComparison.InvariantCultureIgnoreCase))
                {
                    throw new PartnerDomainException(ErrorCode.InvalidFileType, Resources.InvalidOrganizationLogoFileTypeMessage).AddDetail("Field", "OrganizationLogoFile");
                }

                brandingConfiguration.OrganizationLogoContent = organizationLogoPostedFile.InputStream;
            }
            else if (!string.IsNullOrWhiteSpace(organizationLogo))
            {
                try
                {
                    // the user either did not specify a logo or he did but changed the organization logo text to point to somewhere else i.e. a URI
                    brandingConfiguration.OrganizationLogo = new Uri(organizationLogo, UriKind.Absolute);
                }
                catch (UriFormatException invalidUri)
                {
                    throw new PartnerDomainException(ErrorCode.InvalidInput, Resources.InvalidOrganizationLogoUriMessage, invalidUri).AddDetail("Field", "OrganizationLogo");
                }
            }

            string         headerImage = HttpContext.Current.Request.Form["HeaderImage"];
            HttpPostedFile headerImageUploadPostedFile = HttpContext.Current.Request.Files["HeaderImageFile"];

            if (headerImageUploadPostedFile != null && Path.GetFileName(headerImageUploadPostedFile.FileName) == headerImage)
            {
                // there is a new header image to be uploaded
                if (!headerImageUploadPostedFile.ContentType.Trim().StartsWith("image/", StringComparison.InvariantCultureIgnoreCase))
                {
                    throw new PartnerDomainException(ErrorCode.InvalidFileType, Resources.InvalidHeaderImageMessage).AddDetail("Field", "HeaderImageFile");
                }

                brandingConfiguration.HeaderImageContent = headerImageUploadPostedFile.InputStream;
            }
            else if (!string.IsNullOrWhiteSpace(headerImage))
            {
                try
                {
                    // the user either did not specify a header image or he did but changed the organization logo text to point to somewhere else i.e. a URI
                    brandingConfiguration.HeaderImage = new Uri(headerImage, UriKind.Absolute);
                }
                catch (UriFormatException invalidUri)
                {
                    throw new PartnerDomainException(ErrorCode.InvalidInput, Resources.InvalidHeaderImageUriMessage, invalidUri).AddDetail("Field", "HeaderImage");
                }
            }

            if (!string.IsNullOrWhiteSpace(HttpContext.Current.Request.Form["PrivacyAgreement"]))
            {
                try
                {
                    brandingConfiguration.PrivacyAgreement = new Uri(HttpContext.Current.Request.Form["PrivacyAgreement"], UriKind.Absolute);
                }
                catch (UriFormatException invalidUri)
                {
                    throw new PartnerDomainException(ErrorCode.InvalidInput, Resources.InvalidPrivacyUriMessage, invalidUri).AddDetail("Field", "PrivacyAgreement");
                }
            }

            if (!string.IsNullOrWhiteSpace(HttpContext.Current.Request.Form["InstrumentationKey"]))
            {
                brandingConfiguration.InstrumentationKey = HttpContext.Current.Request.Form["InstrumentationKey"];
            }

            BrandingConfiguration updatedBrandingConfiguration = await ApplicationDomain.Instance.PortalBranding.UpdateAsync(brandingConfiguration).ConfigureAwait(false);

            bool isPaymentConfigurationSetup = await ApplicationDomain.Instance.PaymentConfigurationRepository.IsConfiguredAsync().ConfigureAwait(false);

            if (isPaymentConfigurationSetup)
            {
                // update the web experience profile.
                PaymentConfiguration paymentConfiguration = await ApplicationDomain.Instance.PaymentConfigurationRepository.RetrieveAsync().ConfigureAwait(false);

                paymentConfiguration.WebExperienceProfileId = PaymentGatewayConfig.GetPaymentGatewayInstance(ApplicationDomain.Instance, "retrieve payment").CreateWebExperienceProfile(paymentConfiguration, updatedBrandingConfiguration, ApplicationDomain.Instance.PortalLocalization.CountryIso2Code);
                await ApplicationDomain.Instance.PaymentConfigurationRepository.UpdateAsync(paymentConfiguration).ConfigureAwait(false);
            }

            return(updatedBrandingConfiguration);
        }
 /// <summary>
 /// Creates Web Experience profile using portal branding and payment configuration.
 /// </summary>
 /// <param name="paymentConfig">The Payment configuration.</param>
 /// <param name="brandConfig">The branding configuration.</param>
 /// <param name="countryIso2Code">The locale code used by the web experience profile. Example-US.</param>
 /// <returns>The created web experience profile id.</returns>
 public string CreateWebExperienceProfile(PaymentConfiguration paymentConfig, BrandingConfiguration brandConfig, string countryIso2Code)
 {
     ////no need to implement this method
     return(string.Empty);
 }
Beispiel #16
0
        /// <summary>
        /// Fetches all Microsoft CSP offers.
        /// </summary>
        /// <returns>A list of all Microsoft CSP offers.</returns>
        public async Task <IEnumerable <MicrosoftOffer> > RetrieveMicrosoftOffersAsync()
        {
            List <MicrosoftOffer> microsoftOffers = await ApplicationDomain.CachingService
                                                    .FetchAsync <List <MicrosoftOffer> >(MicrosoftOffersCacheKey).ConfigureAwait(false);

            if (microsoftOffers == null)
            {
                // Need to manage this based on the offer locale supported by the Offer API. Either its english or using one of the supported offer locale to retrieve localized offers for the store front.
                IPartner localeSpecificPartnerCenterClient = ApplicationDomain.PartnerCenterClient.With(RequestContextFactory.Instance.Create(ApplicationDomain.PortalLocalization.OfferLocale));

                // Offers.ByCountry is required to pull country / region specific offers.
                PartnerCenter.Models.ResourceCollection <PartnerCenter.Models.Offers.Offer> partnerCenterOffers = await localeSpecificPartnerCenterClient.Offers.ByCountry(ApplicationDomain.PortalLocalization.CountryIso2Code).GetAsync().ConfigureAwait(false);

                // Get the current billing cycle to filter down the eligible offers
                BrandingConfiguration portalBranding = await ApplicationDomain.Instance.PortalBranding.RetrieveAsync().ConfigureAwait(false);

                PartnerCenter.Models.Offers.BillingCycleType offerBillingCycle = PartnerCenter.Models.Offers.BillingCycleType.Unknown;

                switch (portalBranding.BillingCycle)
                {
                case BillingCycleType.Annual:
                    offerBillingCycle = PartnerCenter.Models.Offers.BillingCycleType.Monthly;
                    break;

                case BillingCycleType.Monthly:
                    offerBillingCycle = PartnerCenter.Models.Offers.BillingCycleType.Annual;
                    break;

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

                // Get offers which support the desired billing cycle
                IEnumerable <PartnerCenter.Models.Offers.Offer> eligibleOffers = partnerCenterOffers?.Items.Where(offer =>
                                                                                                                  !offer.IsAddOn &&
                                                                                                                  (offer.PrerequisiteOffers == null || !offer.PrerequisiteOffers.Any()) &&
                                                                                                                  offer.IsAvailableForPurchase &&
                                                                                                                  offer.SupportedBillingCycles.Contains(offerBillingCycle));

                microsoftOffers = new List <MicrosoftOffer>();

                if (eligibleOffers != null)
                {
                    foreach (PartnerCenter.Models.Offers.Offer partnerCenterOffer in eligibleOffers)
                    {
                        microsoftOffers.Add(new MicrosoftOffer()
                        {
                            Offer        = partnerCenterOffer,
                            ThumbnailUri = new Uri(await ApplicationDomain.MicrosoftOfferLogoIndexer.GetOfferLogoUriAsync(partnerCenterOffer).ConfigureAwait(false), UriKind.Relative)
                        });
                    }
                }

                // cache the Microsoft offers for one day
                await ApplicationDomain.CachingService.StoreAsync(
                    MicrosoftOffersCacheKey,
                    microsoftOffers,
                    TimeSpan.FromDays(1)).ConfigureAwait(false);
            }

            return(microsoftOffers);
        }
 /// <summary>
 /// Creates Web Experience profile using portal branding and payment configuration.
 /// </summary>
 /// <param name="paymentConfig">The Payment configuration.</param>
 /// <param name="brandConfig">The branding configuration.</param>
 /// <param name="countryIso2Code">The locale code used by the web experience profile. Example-US.</param>
 /// <returns>The created web experience profile id.</returns>
 public string CreateWebExperienceProfile(PaymentConfiguration paymentConfig, BrandingConfiguration brandConfig, string countryIso2Code)
 {
     ////Payu does not provide the concept of webprofile
     ////stored authorization in WebExperienceProfileId
     return(paymentConfig.WebExperienceProfileId);
 }
Beispiel #18
0
        /// <summary>
        /// Normalizes an order to add seats to a subscription.
        /// </summary>
        /// <returns>Normalized order.</returns>
        public async Task <OrderViewModel> NormalizePurchaseAdditionalSeatsOrderAsync()
        {
            OrderViewModel order = Order;

            order.CustomerId.AssertNotEmpty(nameof(order.CustomerId));

            if (order.OperationType != CommerceOperationType.AdditionalSeatsPurchase)
            {
                throw new PartnerDomainException(ErrorCode.InvalidInput, Resources.InvalidOperationForOrderMessage).AddDetail("Field", "OperationType");
            }

            // create result order object prefilling it with operation type & customer id.
            OrderViewModel orderResult = new OrderViewModel()
            {
                CustomerId    = order.CustomerId,
                OrderId       = order.OrderId,
                OperationType = order.OperationType
            };

            order.Subscriptions.AssertNotNull(nameof(order.Subscriptions));
            List <OrderSubscriptionItemViewModel> orderSubscriptions = order.Subscriptions.ToList();

            if (orderSubscriptions.Count != 1)
            {
                throw new PartnerDomainException(ErrorCode.InvalidInput).AddDetail("ErrorMessage", Resources.MoreThanOneSubscriptionUpdateErrorMessage);
            }

            string subscriptionId  = orderSubscriptions.First().SubscriptionId;
            int    seatsToPurchase = orderSubscriptions.First().Quantity;

            subscriptionId.AssertNotEmpty(nameof(subscriptionId)); // is Required for the commerce operation.
            seatsToPurchase.AssertPositive("seatsToPurchase");

            // grab the customer subscription from our store
            CustomerSubscriptionEntity subscriptionToAugment = await GetSubscriptionAsync(subscriptionId, order.CustomerId).ConfigureAwait(false);

            // retrieve the partner offer this subscription relates to, we need to know the current price
            PartnerOffer partnerOffer = await ApplicationDomain.Instance.OffersRepository.RetrieveAsync(subscriptionToAugment.PartnerOfferId).ConfigureAwait(false);

            if (partnerOffer.IsInactive)
            {
                // renewing deleted offers is prohibited
                throw new PartnerDomainException(ErrorCode.PurchaseDeletedOfferNotAllowed).AddDetail("Id", partnerOffer.Id);
            }

            // retrieve the subscription from Partner Center
            Subscriptions.ISubscription subscriptionOperations = ApplicationDomain.Instance.PartnerCenterClient.Customers.ById(order.CustomerId).Subscriptions.ById(subscriptionId);

            // if subscription expiry date.Date is less than today's UTC date then subcription has expired.
            if (subscriptionToAugment.ExpiryDate.Date < DateTime.UtcNow.Date)
            {
                // this subscription has already expired, don't permit adding seats until the subscription is renewed
                throw new PartnerDomainException(ErrorCode.SubscriptionExpired);
            }

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

            decimal proratedSeatCharge = Math.Round(CommerceOperations.CalculateProratedSeatCharge(subscriptionToAugment.ExpiryDate,
                                                                                                   partnerOffer.Price,
                                                                                                   portalBranding.BillingCycle),
                                                    Resources.Culture.NumberFormat.CurrencyDecimalDigits);
            //decimal totalCharge = Math.Round(proratedSeatCharge * seatsToPurchase, Resources.Culture.NumberFormat.CurrencyDecimalDigits);

            List <OrderSubscriptionItemViewModel> resultOrderSubscriptions = new List <OrderSubscriptionItemViewModel>
            {
                new OrderSubscriptionItemViewModel()
                {
                    OfferId                = subscriptionId,
                    SubscriptionId         = subscriptionId,
                    PartnerOfferId         = subscriptionToAugment.PartnerOfferId,
                    SubscriptionExpiryDate = subscriptionToAugment.ExpiryDate,
                    Quantity               = seatsToPurchase,
                    SeatPrice              = proratedSeatCharge,
                    SubscriptionName       = partnerOffer.Title
                }
            };

            orderResult.Subscriptions = resultOrderSubscriptions;

            return(orderResult);
        }
        /// <summary>
        /// Gets the summary of subscriptions for a portal customer.
        /// </summary>
        /// <param name="customerId">The customer Id.</param>
        /// <returns>Subscription Summary.</returns>
        private async Task <SubscriptionsSummary> GetSubscriptionSummaryAsync(string customerId)
        {
            DateTime startTime = DateTime.Now;
            IEnumerable <CustomerSubscriptionEntity> customerSubscriptions = await ApplicationDomain.Instance.CustomerSubscriptionsRepository.RetrieveAsync(customerId).ConfigureAwait(false);

            IEnumerable <CustomerPurchaseEntity> customerSubscriptionsHistory = await ApplicationDomain.Instance.CustomerPurchasesRepository.RetrieveAsync(customerId).ConfigureAwait(false);

            IEnumerable <PartnerOffer> allPartnerOffers = await ApplicationDomain.Instance.OffersRepository.RetrieveAsync().ConfigureAwait(false);

            IEnumerable <MicrosoftOffer> currentMicrosoftOffers = await ApplicationDomain.Instance.OffersRepository.RetrieveMicrosoftOffersAsync().ConfigureAwait(false);

            // start building the summary.
            decimal summaryTotal = 0;

            // format all responses to client using portal locale.
            CultureInfo responseCulture = new CultureInfo(ApplicationDomain.Instance.PortalLocalization.Locale);
            List <SubscriptionViewModel> customerSubscriptionsView = new List <SubscriptionViewModel>();

            // iterate through and build the list of customer's subscriptions.
            foreach (CustomerSubscriptionEntity subscription in customerSubscriptions)
            {
                decimal subscriptionTotal = 0;
                int     licenseTotal      = 0;
                List <SubscriptionHistory> historyItems = new List <SubscriptionHistory>();

                // collect the list of history items for this subcription.
                IOrderedEnumerable <CustomerPurchaseEntity> subscriptionHistoryList = customerSubscriptionsHistory
                                                                                      .Where(historyItem => historyItem.SubscriptionId == subscription.SubscriptionId)
                                                                                      .OrderBy(historyItem => historyItem.TransactionDate);

                // iterate through and build the SubsriptionHistory for this subscription.
                foreach (CustomerPurchaseEntity historyItem in subscriptionHistoryList)
                {
                    decimal orderTotal = Math.Round(historyItem.SeatPrice * historyItem.SeatsBought, responseCulture.NumberFormat.CurrencyDecimalDigits);
                    historyItems.Add(new SubscriptionHistory()
                    {
                        OrderTotal    = orderTotal.ToString("C", responseCulture),                                // Currency format.
                        PricePerSeat  = historyItem.SeatPrice.ToString("C", responseCulture),                     // Currency format.
                        SeatsBought   = historyItem.SeatsBought.ToString("G", responseCulture),                   // General format.
                        OrderDate     = historyItem.TransactionDate.ToLocalTime().ToString("d", responseCulture), // Short date format.
                        OperationType = GetOperationType(historyItem.PurchaseType)                                // Localized Operation type string.
                    });

                    // Increment the subscription total.
                    licenseTotal += historyItem.SeatsBought;

                    // Increment the subscription total.
                    subscriptionTotal += orderTotal;
                }

                PartnerOffer partnerOfferItem  = allPartnerOffers.FirstOrDefault(offer => offer.Id == subscription.PartnerOfferId);
                string       subscriptionTitle = partnerOfferItem.Title;
                string       portalOfferId     = partnerOfferItem.Id;
                decimal      portalOfferPrice  = partnerOfferItem.Price;

                DateTime subscriptionExpiryDate = subscription.ExpiryDate.ToUniversalTime();
                int      remainingDays          = (subscriptionExpiryDate.Date - DateTime.UtcNow.Date).Days;
                bool     isRenewable            = remainingDays <= 30;
                bool     isEditable             = DateTime.UtcNow.Date <= subscriptionExpiryDate.Date;

                // TODO :: Handle Microsoft offer being pulled back due to EOL.

                // Temporarily mark this partnerOffer item as inactive and dont allow store front customer to manage this subscription.
                MicrosoftOffer alignedMicrosoftOffer = currentMicrosoftOffers.FirstOrDefault(offer => offer.Offer.Id == partnerOfferItem.MicrosoftOfferId);
                if (alignedMicrosoftOffer == null)
                {
                    partnerOfferItem.IsInactive = true;
                }

                if (partnerOfferItem.IsInactive)
                {
                    // in case the offer is inactive (marked for deletion) then dont allow renewals or editing on this subscription tied to this offer.
                    isRenewable = false;
                    isEditable  = false;
                }

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

                // Compute the pro rated price per seat for this subcription & return for client side processing during updates.
                decimal proratedPerSeatPrice = Math.Round(CommerceOperations.CalculateProratedSeatCharge(subscription.ExpiryDate,
                                                                                                         portalOfferPrice,
                                                                                                         portalBranding.BillingCycle),
                                                          Resources.Culture.NumberFormat.CurrencyDecimalDigits);

                SubscriptionViewModel subscriptionItem = new SubscriptionViewModel()
                {
                    SubscriptionId            = subscription.SubscriptionId,
                    FriendlyName              = subscriptionTitle,
                    PortalOfferId             = portalOfferId,
                    PortalOfferPrice          = portalOfferPrice.ToString("C", responseCulture),
                    IsRenewable               = isRenewable,                                                // IsRenewable is true if subscription is going to expire in 30 days.
                    IsEditable                = isEditable,                                                 // IsEditable is true if today is lesser or equal to subscription expiry date.
                    LicensesTotal             = licenseTotal.ToString("G", responseCulture),                // General format.
                    SubscriptionTotal         = subscriptionTotal.ToString("C", responseCulture),           // Currency format.
                    SubscriptionExpiryDate    = subscriptionExpiryDate.Date.ToString("d", responseCulture), // Short date format.
                    SubscriptionOrderHistory  = historyItems,
                    SubscriptionProRatedPrice = proratedPerSeatPrice
                };

                // add this subcription to the customer's subscription list.
                customerSubscriptionsView.Add(subscriptionItem);

                // Increment the summary total.
                summaryTotal += subscriptionTotal;
            }

            // Capture the request for the customer summary for analysis.
            Dictionary <string, string> eventProperties = new Dictionary <string, string> {
                { "CustomerId", customerId }
            };

            // Track the event measurements for analysis.
            Dictionary <string, double> eventMetrics = new Dictionary <string, double> {
                { "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds }, { "NumberOfSubscriptions", customerSubscriptionsView.Count }
            };

            ApplicationDomain.Instance.TelemetryService.Provider.TrackEvent("GetSubscriptionSummaryAsync", eventProperties, eventMetrics);

            // Sort List of subscriptions based on portal offer name.
            return(new SubscriptionsSummary()
            {
                Subscriptions = customerSubscriptionsView.OrderBy(subscriptionItem => subscriptionItem.FriendlyName),
                SummaryTotal = summaryTotal.ToString("C", responseCulture)      // Currency format.
            });
        }
Beispiel #20
0
        public async Task <SubscriptionsSummary> ProcessOrderForUnAuthenticatedCustomer(string customerId, string paymentId, string payerId)
        {
            DateTime startTime = DateTime.Now;

            customerId.AssertNotEmpty(nameof(customerId));
            paymentId.AssertNotEmpty(nameof(paymentId));
            payerId.AssertNotEmpty(nameof(payerId));

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

            CustomerViewModel customerRegistrationInfoPersisted = await ApplicationDomain.Instance.CustomerRegistrationRepository.RetrieveAsync(customerId).ConfigureAwait(false);

            Customer newCustomer = new Customer()
            {
                CompanyProfile = new CustomerCompanyProfile()
                {
                    Domain = customerRegistrationInfoPersisted.DomainName,
                },
                BillingProfile = new CustomerBillingProfile()
                {
                    Culture     = customerRegistrationInfoPersisted.BillingCulture,
                    Language    = customerRegistrationInfoPersisted.BillingLanguage,
                    Email       = customerRegistrationInfoPersisted.Email,
                    CompanyName = customerRegistrationInfoPersisted.CompanyName,

                    DefaultAddress = new Address()
                    {
                        FirstName    = customerRegistrationInfoPersisted.FirstName,
                        LastName     = customerRegistrationInfoPersisted.LastName,
                        AddressLine1 = customerRegistrationInfoPersisted.AddressLine1,
                        AddressLine2 = customerRegistrationInfoPersisted.AddressLine2,
                        City         = customerRegistrationInfoPersisted.City,
                        State        = customerRegistrationInfoPersisted.State,
                        Country      = customerRegistrationInfoPersisted.Country,
                        PostalCode   = customerRegistrationInfoPersisted.ZipCode,
                        PhoneNumber  = customerRegistrationInfoPersisted.Phone,
                    }
                }
            };

            // Register customer
            newCustomer = await ApplicationDomain.Instance.PartnerCenterClient.Customers.CreateAsync(newCustomer).ConfigureAwait(false);

            ResourceCollection <AgreementMetaData> agreements = await ApplicationDomain.Instance.PartnerCenterClient.AgreementDetails.GetAsync().ConfigureAwait(false);

            // Obtain reference to the Microsoft Cloud Agreement.
            AgreementMetaData microsoftCloudAgreement = agreements.Items.FirstOrDefault(agr => agr.AgreementType == AgreementType.MicrosoftCloudAgreement);

            // Attest that the customer has accepted the Microsoft Cloud Agreement (MCA).
            await ApplicationDomain.Instance.PartnerCenterClient.Customers[newCustomer.Id].Agreements.CreateAsync(
                new Agreement
            {
                DateAgreed     = DateTime.UtcNow,
                PrimaryContact = new PartnerCenter.Models.Agreements.Contact
                {
                    Email       = customerRegistrationInfoPersisted.Email,
                    FirstName   = customerRegistrationInfoPersisted.FirstName,
                    LastName    = customerRegistrationInfoPersisted.LastName,
                    PhoneNumber = customerRegistrationInfoPersisted.Phone
                },
                TemplateId = microsoftCloudAgreement.TemplateId,
                Type       = AgreementType.MicrosoftCloudAgreement,
                UserId     = branding.AgreementUserId
            });

            string newCustomerId = newCustomer.CompanyProfile.TenantId;

            CustomerViewModel customerViewModel = new CustomerViewModel()
            {
                AddressLine1     = newCustomer.BillingProfile.DefaultAddress.AddressLine1,
                AddressLine2     = newCustomer.BillingProfile.DefaultAddress.AddressLine2,
                City             = newCustomer.BillingProfile.DefaultAddress.City,
                State            = newCustomer.BillingProfile.DefaultAddress.State,
                ZipCode          = newCustomer.BillingProfile.DefaultAddress.PostalCode,
                Country          = newCustomer.BillingProfile.DefaultAddress.Country,
                Phone            = newCustomer.BillingProfile.DefaultAddress.PhoneNumber,
                Language         = newCustomer.BillingProfile.Language,
                FirstName        = newCustomer.BillingProfile.DefaultAddress.FirstName,
                LastName         = newCustomer.BillingProfile.DefaultAddress.LastName,
                Email            = newCustomer.BillingProfile.Email,
                CompanyName      = newCustomer.BillingProfile.CompanyName,
                MicrosoftId      = newCustomer.CompanyProfile.TenantId,
                UserName         = newCustomer.BillingProfile.Email,
                Password         = newCustomer.UserCredentials.Password,
                AdminUserAccount = newCustomer.UserCredentials.UserName + "@" + newCustomer.CompanyProfile.Domain
            };

            IPaymentGateway paymentGateway = PaymentGatewayConfig.GetPaymentGatewayInstance(ApplicationDomain.Instance, "ProcessingOrder");
            OrderViewModel  orderToProcess = await paymentGateway.GetOrderDetailsFromPaymentAsync(payerId, paymentId, string.Empty, string.Empty).ConfigureAwait(false);

            // Assign the actual customer Id
            orderToProcess.CustomerId = newCustomerId;

            CommerceOperations commerceOperation = new CommerceOperations(ApplicationDomain.Instance, newCustomerId, paymentGateway);
            await commerceOperation.PurchaseAsync(orderToProcess).ConfigureAwait(false);

            SubscriptionsSummary summaryResult = await GetSubscriptionSummaryAsync(newCustomerId).ConfigureAwait(false);

            // Remove the persisted customer registration info.
            await ApplicationDomain.Instance.CustomerRegistrationRepository.DeleteAsync(customerId).ConfigureAwait(false);

            // Capture the request for the customer summary for analysis.
            Dictionary <string, string> eventProperties = new Dictionary <string, string> {
                { "CustomerId", orderToProcess.CustomerId }
            };

            // Track the event measurements for analysis.
            Dictionary <string, double> eventMetrics = new Dictionary <string, double> {
                { "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds }
            };

            ApplicationDomain.Instance.TelemetryService.Provider.TrackEvent("api/order/NewCustomerProcessOrder", eventProperties, eventMetrics);

            summaryResult.CustomerViewModel = customerViewModel;

            return(summaryResult);
        }
Beispiel #21
0
        public async Task <BrandingConfiguration> UpdateBrandingConfiguration()
        {
            BrandingConfiguration brandingConfiguration = new BrandingConfiguration()
            {
                OrganizationName = HttpContext.Current.Request.Form["OrganizationName"],
                ContactUs        = new ContactUsInformation()
                {
                    Email = HttpContext.Current.Request.Form["ContactUsEmail"],
                    Phone = HttpContext.Current.Request.Form["ContactUsPhone"],
                },
                ContactSales = new ContactUsInformation()
                {
                    Email = HttpContext.Current.Request.Form["ContactSalesEmail"],
                    Phone = HttpContext.Current.Request.Form["ContactSalesPhone"],
                },
            };

            string organizationLogo           = HttpContext.Current.Request.Form["OrganizationLogo"];
            var    organizationLogoPostedFile = HttpContext.Current.Request.Files["OrganizationLogoFile"];

            if (organizationLogoPostedFile != null && Path.GetFileName(organizationLogoPostedFile.FileName) == organizationLogo)
            {
                // there is a new organization logo to be uploaded
                if (!organizationLogoPostedFile.ContentType.Trim().StartsWith("image/"))
                {
                    throw new PartnerDomainException(ErrorCode.InvalidFileType, "Provide an image file type for the organization logo").AddDetail("Field", "OrganizationLogoFile");
                }

                brandingConfiguration.OrganizationLogoContent = organizationLogoPostedFile.InputStream;
            }
            else if (!string.IsNullOrWhiteSpace(organizationLogo))
            {
                try
                {
                    // the user either did not specify a logo or he did but changed the organization logo text to point to somewhere else i.e. a URI
                    brandingConfiguration.OrganizationLogo = new Uri(organizationLogo, UriKind.Absolute);
                }
                catch (UriFormatException invalidUri)
                {
                    throw new PartnerDomainException(ErrorCode.InvalidInput, "Invalid organization logo URI uploaded", invalidUri).AddDetail("Field", "OrganizationLogo");
                }
            }

            string headerImage = HttpContext.Current.Request.Form["HeaderImage"];
            var    headerImageUploadPostedFile = HttpContext.Current.Request.Files["HeaderImageFile"];

            if (headerImageUploadPostedFile != null && Path.GetFileName(headerImageUploadPostedFile.FileName) == headerImage)
            {
                // there is a new header image to be uploaded
                if (!headerImageUploadPostedFile.ContentType.Trim().StartsWith("image/"))
                {
                    throw new PartnerDomainException(ErrorCode.InvalidFileType, "Provide an image file type for the header image").AddDetail("Field", "HeaderImageFile");
                }

                brandingConfiguration.HeaderImageContent = headerImageUploadPostedFile.InputStream;
            }
            else if (!string.IsNullOrWhiteSpace(headerImage))
            {
                try
                {
                    // the user either did not specify a header image or he did but changed the organization logo text to point to somewhere else i.e. a URI
                    brandingConfiguration.HeaderImage = new Uri(headerImage, UriKind.Absolute);
                }
                catch (UriFormatException invalidUri)
                {
                    throw new PartnerDomainException(ErrorCode.InvalidInput, "Invalid header image URI uploaded", invalidUri).AddDetail("Field", "HeaderImage");
                }
            }

            if (!string.IsNullOrWhiteSpace(HttpContext.Current.Request.Form["PrivacyAgreement"]))
            {
                try
                {
                    brandingConfiguration.PrivacyAgreement = new Uri(HttpContext.Current.Request.Form["PrivacyAgreement"], UriKind.Absolute);
                }
                catch (UriFormatException invalidUri)
                {
                    throw new PartnerDomainException(ErrorCode.InvalidInput, "Invalid privacy agreement URI uploaded", invalidUri).AddDetail("Field", "PrivacyAgreement");
                }
            }

            return(await ApplicationDomain.Instance.PortalBranding.UpdateAsync(brandingConfiguration));
        }
        /// <summary>
        /// Creates Web Experience profile using portal branding and payment configuration.
        /// </summary>
        /// <param name="paymentConfig">The Payment configuration.</param>
        /// <param name="brandConfig">The branding configuration.</param>
        /// <param name="countryIso2Code">The locale code used by the web experience profile. Example-US.</param>
        /// <returns>The created web experience profile id.</returns>
        public static string CreateWebExperienceProfile(PaymentConfiguration paymentConfig, BrandingConfiguration brandConfig, string countryIso2Code)
        {
            try
            {
                Dictionary <string, string> configMap = new Dictionary <string, string>();
                configMap.Add("clientId", paymentConfig.ClientId);
                configMap.Add("clientSecret", paymentConfig.ClientSecret);
                configMap.Add("mode", paymentConfig.AccountType);
                configMap.Add("connectionTimeout", "120000");

                string accessToken = new OAuthTokenCredential(configMap).GetAccessToken();
                var    apiContext  = new APIContext(accessToken);
                apiContext.Config = configMap;

                // Pickup logo & brand name from branding configuration.
                // create the web experience profile.
                var profile = new WebProfile
                {
                    name         = Guid.NewGuid().ToString(),
                    presentation = new Presentation
                    {
                        brand_name  = brandConfig.OrganizationName,
                        logo_image  = brandConfig.HeaderImage?.ToString(),
                        locale_code = countryIso2Code
                    },
                    input_fields = new InputFields()
                    {
                        address_override = 1,
                        allow_note       = false,
                        no_shipping      = 1
                    },
                    flow_config = new FlowConfig()
                    {
                        landing_page_type = "billing"
                    }
                };

                var createdProfile = profile.Create(apiContext);

                // Now that new experience profile is created hence delete the older one.
                if (!string.IsNullOrWhiteSpace(paymentConfig.WebExperienceProfileId))
                {
                    try
                    {
                        WebProfile existingWebProfile = WebProfile.Get(apiContext, paymentConfig.WebExperienceProfileId);
                        existingWebProfile.Delete(apiContext);
                    }
                    catch
                    {
                    }
                }

                return(createdProfile.id);
            }
            catch (PayPalException paypalException)
            {
                if (paypalException is IdentityException)
                {
                    // thrown when API Context couldn't be setup.
                    IdentityException identityFailure = paypalException as IdentityException;
                    IdentityError     failureDetails  = identityFailure.Details;
                    if (failureDetails != null && failureDetails.error.ToLower() == "invalid_client")
                    {
                        throw new PartnerDomainException(ErrorCode.PaymentGatewayIdentityFailureDuringConfiguration).AddDetail("ErrorMessage", Resources.PaymentGatewayIdentityFailureDuringConfiguration);
                    }
                }

                // if this is not an identity exception rather some other issue.
                throw new PartnerDomainException(ErrorCode.PaymentGatewayFailure).AddDetail("ErrorMessage", paypalException.Message);
            }
        }
Beispiel #23
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));
        }