Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Gordon Saxby 1444 posts 1855 karma points
    Feb 01, 2017 @ 16:46
    Gordon Saxby
    0

    Override FastTrack Checkout process

    I am using FastTrack to give me the shopping site basics quickly. However, the shopping site will only be available within an existing secured area. I am using a custom membership provider.

    When the user puts something in the basket and goes to checkout, I want it to use the address details that are obtainable via the custom membership provider.

    The simplest option is to pre-fill the customer / shipping fields and allow the user to just click through. Alternatively, the process could skip the (visual) steps for name & address details.

    Is that possible?

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Feb 01, 2017 @ 18:36
    Rusty Swayne
    0

    Yes - there are quite a few ways you could do this.

    First, you will want to create your own CustomerContext for your custom membership provider so you can create a Merchello customer or Merchello Anonymous customer based on your authentication provider.

    All that is required to do that is to create a class inheriting from Merchello.Web.Pluggable.CustomerContextBase, build out the abstract methods (which basically translate your membership provider interactions to Merchello - three methods if I remember correctly.

    To register your class with Merchello, update the Merchello .config file

      <object alias="CustomerContext" type="[YOUR CLASS], [YOUR LIBRARY]" />
    

    For the addresses, you could either override the CheckoutAddressController in fasttrack (or simply replace it using the same base classes with your own completely custom instance) and then reference the new endpoint in your views

    e.g.

     @using (Html.BeginUmbracoForm<[YOURCONTROLLER]>("SaveBillingAddress", new { area = "[YOUR_AREA]" }, new { data_muistage = "BillingAddress" }))
    

    If you need something more sophisticated than that, you can also totally swap out the individual CheckoutManager(s) by creating classes that inherit from their respective base classes and again updating the Merchello.config with the new assembly references. My guess is you won't need to go that far, but I thought I'd mention it. If you think your going to go down that route, we can start a thread on that =)

  • Gordon Saxby 1444 posts 1855 karma points
    Feb 02, 2017 @ 13:04
    Gordon Saxby
    0

    Hi Rusty,

    First, you will want to create your own CustomerContext for your custom membership provider so you can create a Merchello customer or Merchello Anonymous customer based on your authentication provider.

    All customers will be authenticated, because they will have already logged in to gain access to the shop. What do you mean by "create a Merchello customer"? Do I have to use the "Merchello Customer" member type?

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Feb 02, 2017 @ 19:48
    Rusty Swayne
    0

    No - you don't have to use Umbraco's Member types if you are using your own membership provider.

    The purpose of the customer context is to create a relationship between your authenticated user and a Merchello IAnonymousCustomer and ICustomer - so that a basket can be associated and checkout processes can be performed.

    It sounds like in your case, you will really never have IAnonymousCustomers but that's handled internally (in the CustomerContextBase) anyway so it should not be an issue for you.

    The CustomerContext is required to keep track of the CurrentCustomer (the customer involved in the request) and whether or not that customer is a known customer (has a customer record) or is anonymous (meaning an anonymous customer record needs to be retrieved or created). Associated with these records are the ItemCaches (basket, wishlist and checkout items) which Merchello uses to ultimately create invoices at the end of the checkout process.

    To tie your membership provider to Merchello you just need to implement your own CustomerContext based off CustomerContextBase as mentioned in the previous post.

    All you need to do is implement the three abstract methods - sort of an adapter to your membership provider to Merchello ... make sense?

              /// <summary>
        /// Returns true or false indicating whether or not the current membership user is logged in.
        /// </summary>
        /// <returns>
        /// The <see cref="bool"/> indicating whether the current user is logged in.
        /// </returns>
        protected abstract bool GetIsCurrentlyLoggedIn();
    
        /// <summary>
        /// Gets the member/user login or user name used to sign in
        /// </summary>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        /// <remarks>
        /// Merchello makes the association between membership provider users and Merchello customers by username
        /// </remarks>
        protected abstract string GetMembershipProviderUserName();
    
        /// <summary>
        /// Gets the unique ID from the Membership Provider
        /// </summary>
        /// <returns>
        /// The ID or key from the Membership provider as a string value 
        /// </returns>
        protected abstract string GetMembershipProviderKey();
    
  • Gordon Saxby 1444 posts 1855 karma points
    Feb 03, 2017 @ 08:05
    Gordon Saxby
    0

    OK, I have this for CustomerContext:

    public class CustomerContext : CustomerContextBase
    {
        public CustomerContext(UmbracoContext umbracoContext) : base(umbracoContext)
        {
        }
    
        public CustomerContext(IMerchelloContext merchelloContext, UmbracoContext umbracoContext) : base(merchelloContext, umbracoContext)
        {
        }
    
        protected override bool GetIsCurrentlyLoggedIn()
        {
            var umbracoHelper = new UmbracoHelper(UmbracoContext);
    
            return umbracoHelper.MemberIsLoggedOn();
        }
    
        protected override string GetMembershipProviderUserName()
        {
            var currentMember = Membership.GetUser();
    
            return currentMember.UserName;
        }
    
        protected override string GetMembershipProviderKey()
        {
            var currentMember = Membership.GetUser();
    
            return currentMember.ProviderUserKey.ToString();
        }
    }
    

    Is that all I need?

  • Gordon Saxby 1444 posts 1855 karma points
    Feb 03, 2017 @ 09:09
    Gordon Saxby
    0

    OK, I have this for CustomerContext:

    public class CustomerContext : CustomerContextBase
    {
        public CustomerContext(UmbracoContext umbracoContext) : base(umbracoContext)
        {
        }
    
        public CustomerContext(IMerchelloContext merchelloContext, UmbracoContext umbracoContext) : base(merchelloContext, umbracoContext)
        {
        }
    
        protected override bool GetIsCurrentlyLoggedIn()
        {
            var umbracoHelper = new UmbracoHelper(UmbracoContext);
    
            return umbracoHelper.MemberIsLoggedOn();
        }
    
        protected override string GetMembershipProviderUserName()
        {
            var currentMember = Membership.GetUser();
    
            return currentMember.UserName;
        }
    
        protected override string GetMembershipProviderKey()
        {
            var currentMember = Membership.GetUser();
    
            return currentMember.ProviderUserKey.ToString();
        }
    }
    

    Is that all I need?

    And regarding the checkout process, all I need is a confirmation of their details on screen as they won't need to enter them (it comes from their membership record). I would like to make the forms read-only though, just for future-proofing! Currently, a user is logged on in order to access the shop pages, but their details do not appear on the form - do I need to override CheckoutAddressController in order to populate the form fields? Do I need to view the FastTrack source to see what needs to be done? Is there any relevant documentation available?

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Feb 03, 2017 @ 16:01
    Rusty Swayne
    0

    I thought you said you were using a custom membership provider - that looks like your using Umbraco's membership provider ...

    That's roughly the same thing as the CustomerContext shipped with Merchello:

    https://github.com/Merchello/Merchello/blob/merchello-dev/src/Merchello.Web/CustomerContext.cs

  • Gordon Saxby 1444 posts 1855 karma points
    Feb 03, 2017 @ 16:22
    Gordon Saxby
    0

    Umm, I am pretty sure it's a custom provider, as it connects to a remote MySQL database. This is the web.config setup:

    <membership defaultProvider="UmbracoMembershipProvider" userIsOnlineTimeWindow="15">
      <providers>
        <clear />
        <add name="UmbracoMembershipProvider" type="MySiteMembership.CustomMembershipProvider" minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="8" useLegacyEncoding="true" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" defaultMemberTypeAlias="Member" passwordFormat="Hashed" connectionStringName="MemberTies" />
        <add name="UsersMembershipProvider" type="Umbraco.Web.Security.Providers.UsersMembershipProvider, Umbraco" minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="8" useLegacyEncoding="false" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" passwordFormat="Hashed" hashAlgorithmType="HMACSHA256" />
      </providers>
    </membership>
    <!-- Role Provider -->
    <roleManager enabled="true" defaultProvider="UmbracoRoleProvider">
      <providers>
        <clear />
        <!--<add name="UmbracoRoleProvider" type="Umbraco.Web.Security.Providers.MembersRoleProvider" />-->
        <add name="UmbracoRoleProvider" type="MySiteMembership.CustomRoleProvider" connectionStringName="RemoteDBConn" />
      </providers>
    </roleManager>
    

    The provider is defined as:

    public class CustomMembershipProvider : MembershipProvider
    {
        ....
    }
    

    If I don't use the custom CustomerContext, I get an error (would have to switch back to find out what the error was).

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Feb 03, 2017 @ 21:30
    Rusty Swayne
    0

    Ok - great. Your implementation should be fine if the methods are returning as they appear to be.

    Are you saying it does not work after you change your Merchello.config reference to use your CustomerContext?

  • Gordon Saxby 1444 posts 1855 karma points
    Feb 06, 2017 @ 18:14
    Gordon Saxby
    0

    No, I'm saying it doesn't work if I use the Merchello version. I get this error when using the default Merchello CustomerContext:

    An IMember model can only be retreived when using the built-in Umbraco membership providers
    
  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Feb 07, 2017 @ 17:43
    Rusty Swayne
    0

    Sorry Gordon - I guess I still don't understand where we're getting cross wired.

    If the custom CustomerContext works with your membership provider then Merchello should be able to present you with an IAnonymousCustomer or ICustomer. These are the only thing that Merchello needs for checkout.

    IMember is Umbraco and other than the default CustomerContext (in a sense via the MembershipHelper) to determine the authenticated state.

    If you are storing values in the member content (e.g. member properties) - like address information, then you need to use Umbraco's membership API or whatever you're using for a custom implementation to retrieve those values.

    For an address, you would map those stored properties to Merchello's IAddress which is used in the checkout process.

    If that is the case, take a look at overriding the CheckoutAddressController in FastTrack and building the models from your Membership provider as you need.

  • Gordon Saxby 1444 posts 1855 karma points
    Feb 07, 2017 @ 19:39
    Gordon Saxby
    0

    Regarding CustomerContext, all I'm saying is that I have to create my own version because I am using a custom membership provider and that causes the error.

    What I'm not sure about is whether I am doing the right things in the functions that I have to override.

    The aim is to get the "customer" details and populate the details for the order process. I do not want the customer entering any personal data - actually, they do not need to as nothing will ever be delivered, only collected in person. The website is for a club and orders will be made available to collect on "club night".

    Regarding member records - I have changed the config ("memberTypes") to use the standard "Member", is that OK? Do I need to do any extra coding to support that? What will happen in the "Customers" section in Merchello?

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Feb 08, 2017 @ 17:53
    Rusty Swayne
    0

    You can test your CustomerContext by checking the CurrentCustomer property.

       var customer = customerContext.CurrentCustomer;
    
       if (customer.IsAnonymous)
       {
           // Merchello views the customer as not being logged in
           // e.g. your implementation reported not logged in
           //  customer is IAnonymousCustomer
       }
       else
       {
          // Merchello views the customer as being logged in
          // customer is ICustomer
       }
    

    The MemberType should not be an issue unless you've overridden the basket conversion call like is done by default in Merchello https://github.com/Merchello/Merchello/blob/merchello-dev/src/Merchello.Web/CustomerContext.cs#L119

    The reason this is done in Merchello is to allow for sites to more easily segment their members between customers and non customers ... e.g. if a member is not logged into a membership account that is not on that list they are ALWAYS treated as an anonymous customer.

    I did not see that you had the override, so your essentially skipping that check ... so your CustomerContext will not check the member type, which I'm guessing is just fine from what you described.

  • Ayo Adesina 430 posts 1023 karma points
    Dec 08, 2018 @ 23:08
    Ayo Adesina
    0

    Hi Rusty, Hi Gordon,

    I have been trying for a while now to customise the checkout process that ships with fast track.

    I have got the site up and running, products, basket and a payment provider all configured and working.

    What I'm trying to do is:

    Firstly: Change the order that the data is collected from the user, so instead of Billing Address, I want to Collect the Shipping address then billing address (if its not the same as the shipping one)

    Secondly: I want to add an extra step in the process, a post code address finder.

    To keep things simple, I want to do this on a completely separate page, get the address, then pass it to the Shipping address page.

    Those are the only things I want to change, everything else is all good.

    I have all the source code hooked up to my visual studio solution and have just tried to swap the logic so shipping address comes first, but I can't quite get it to work.

    Can you help me out here guys? Just a general idea of the steps I need to take to do this.

  • Ayo Adesina 430 posts 1023 karma points
    Dec 11, 2018 @ 11:26
    Ayo Adesina
    0

    Every time I ask a question about Merchello, I find it hard to get any responses....

    Am I asking my question in the wrong way?

    I really like merchello and I'm starting to get the hang of some of it, but I'm still having issues with working out how to customise the check out process.

    can anyone anywhere help me here please....? I might have to try another platform as I'm really stuck here.

    Anyone?

  • Dave Clinton 31 posts 106 karma points
    Dec 11, 2018 @ 14:57
    Dave Clinton
    1

    Hi Ayo,

    In our project we've made some changes to the default checkout process as we needed a couple more fields on the Ship Rate Quote page. We did this by creating a new controller that inherited from CheckoutShipRateQuoteControllerBase that used a custom model. We then overrided the methods we wanted to perform the custom functionality in. You should be able to do this for any of the checkout controllers for the steps you want to change though.

    As for introducing a new checkout step this isn't something I've done before but I'd suspect it would involve creating a new page with a custom controller/model and then changing where the previous step redirects to. If the model inherits from ISuccessRedirectUrl you should be able to use SuccessRedirectUrl perhaps in combination with the ExampleUiHelper.CheckoutWorkflow.GetPageForStage method? The CheckoutStage enum does have a value for Custom I've noticed so it feels like that might be the right way to go...

    Dave

Please Sign in or register to post replies

Write your reply to:

Draft