Seamless facebook integration with nopcommerce at www.pocomaru.com!!!

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
12 Jahre weitere
Ok. Now comes the code of FBUtils.aspx. (Note that you don't necessary need to put yr web service method into a separate file)

nopCommerce_1.90_Source\NopCommerceStore\FBUtils.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="FBUtils.aspx.cs" Inherits="NopSolutions.NopCommerce.Web.FBUtils" %>



nopCommerce_1.90_Source\NopCommerceStore\FBUtils.aspx.cs

using System;
using System.Configuration;
using System.Web.Services;
using NopSolutions.NopCommerce.BusinessLogic.Infrastructure;
using NopSolutions.NopCommerce.BusinessLogic.CustomerManagement;
using Facebook;
using System.Web.Security;
using NopSolutions.NopCommerce.Common;
using System.Web.UI;
using System.Web;
using NopSolutions.NopCommerce.Common.Utils;
using PayPal.Payments.DataObjects;
using System.Text;
using NopSolutions.NopCommerce.BusinessLogic;


namespace NopSolutions.NopCommerce.Web
{
    public partial class FBUtils : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

  
        [WebMethod]
        public static string UserIDExists(string uid, string accesstoken, string returnurl)
        {
            string result = "false";
            var facebokClient = string.IsNullOrEmpty(accesstoken) ? new FacebookClient() : new FacebookClient(accesstoken);
            dynamic me = facebokClient.Get("me?fields=email");
            string email = me.email;
            Customer customer = IoC.Resolve<ICustomerService>().GetCustomerByFacebookId(uid);
            if (customer == null)
            {              
                customer = IoC.Resolve<ICustomerService>().GetCustomerByEmail(email);
                if (customer != null)
                {
                    //However the customer with the same email exits, we combine them together
                    customer.FacebookId = uid;
                    IoC.Resolve<ICustomerService>().UpdateCustomer(customer);
                }
                else
                {
                    // this customer does not exist, we add this customer to our login system
                    Customer facebookCustomer = new Customer();
                    MembershipCreateStatus createStatus = MembershipCreateStatus.Success;

                    IoC.Resolve<ICustomerService>().AddCustomer(email, uid, email, string.Empty, false, false, true, out createStatus);

                    if (createStatus != MembershipCreateStatus.Success)
                    {
                        result = "false";
                        //throw new NopException(string.Format("Could not create new customer: {0}", createStatus.ToString()));
                    }
                }
            }
            else
            {
                // need to combine this with the existing customer in our db
            }

            result = "true";          

            if (string.Equals(result, "true", StringComparison.OrdinalIgnoreCase))
            {
                // login this facebook user into our system
                IoC.Resolve<ICustomerService>().Login(email);
                FormsAuthentication.SetAuthCookie(email, false);
                // facebook login succeeded, we need a flag to indicate that this is a facebook  login so that if user click
                // logout we will log facebook out

                NopContext.IsFacebookLogin = true;
            }

            if (String.IsNullOrEmpty(returnurl))
            {
                returnurl = CommonHelper.GetStoreLocation();
            }
            else
            {
                returnurl = HttpUtility.UrlDecode(returnurl);
            }

            StringBuilder oBuilder = new StringBuilder();
            oBuilder.Append("{");
            oBuilder.AppendFormat(@"""{0}"":""{1}"",", "result", result);
            oBuilder.AppendFormat(@"""{0}"":""{1}""", "returnUrl", returnurl);
            oBuilder.Append("}");
            return oBuilder.ToString();

        }
    }
}


Remember the web service has to have [WebMethod] attribute, and has to be a static method
in this method, you will see all the functions I defined in previous posts get called.

When we call the webservice UserIDExists (see previous post), we pass in a uid, a accesstoken and a returnurl

In UserIDExists, we use the access token to retrieve the email of this facebook user; and use uid as the FacebookId of
this user.

If the customer with the specified facebook id does not exist in our system, but the customer with the same email already in our system, we combine them together :
                    customer.FacebookId = uid;
                    IoC.Resolve<ICustomerService>().UpdateCustomer(customer);


If the customer with the specified facebook id does not exist in our system, and there is no customer with the same email in our system(meaning this is a brand new customer), we add this customer to our login system.

Customer facebookCustomer = new Customer();
                    MembershipCreateStatus createStatus = MembershipCreateStatus.Success;

                    IoC.Resolve<ICustomerService>().AddCustomer(email, uid, email, string.Empty, false, false, true, out createStatus);


If we add this facebook user into our login system successfully, we then login this facebook user into our system by:
 // login this facebook user into our system
                IoC.Resolve<ICustomerService>().Login(email);
                FormsAuthentication.SetAuthCookie(email, false);
                // facebook login succeeded, we need a flag to indicate that this is a facebook  login so that if user click
                // logout we will log facebook out

                NopContext.IsFacebookLogin = true;


  FormsAuthentication.SetAuthCookie(email, false); is the magic here. Note that I haven't figured out how to
detect 'remember me' checkbox on the facebook login popup. The behavior i am using always act as if remeber me is checked. You can tell me if you find solution to detect 'remember me' check box and thus set SetAuthCookie accordingly.

After the facebook login successfully, i save a flag in a static global member
NopContext.IsFacebookLogin = true;

IsFacebookLogin is defined in nopCommerce_1.90_Source\Libraries\Nop.BusinessLogic\NopContext.cs
        public static bool IsFacebookLogin;

We need this information when the user log out:
if this user is a facebook user, we need to do facebook log out.

Again, using IsFacebookLogin  is just one way (maybe not so good way) to save the state. I just pick one to make everything work first, so apparently the above code also need some refactoring in the future.

The webservice returns a jason object which contains a result and a return url, the jason object is used in ajax response:
success: function (data) {                          
                            var obj = jQuery.parseJSON(data.d);
                            if (obj['result'] == "true") {
                                response.session["isfacebooklogin"] = "true";
                                window.location = obj['returnUrl'];
                            }
                        }

I will finish things up in the next post due to the length limit of each post.
12 Jahre weitere
In the previous post, inside function UserIDExists there is
IoC.Resolve<ICustomerService>().Login(email);

The code for this is in
nopCommerce_1.90_Source\Libraries\Nop.BusinessLogic\Customer\ICustomerService.cs

        /// <summary>
        /// Login a facebook customer
        /// </summary>
        /// <param name="email">A customer email</param>  
        /// <returns>Result</returns>
        bool Login(string email);

and
nopCommerce_1.90_Source\Libraries\Nop.BusinessLogic\Customer\CustomerService.cs

        /// <summary>
        /// Login a facebook customer
        /// </summary>
        /// <param name="email">A customer email</param>    
        /// <returns>Result</returns>
        public bool Login(string email)
        {
            if (email == null)
                email = string.Empty;
            email = email.Trim();

            var customer = GetCustomerByEmail(email);

            if (customer == null)
                return false;

            if (!customer.Active)
                return false;

            if (customer.Deleted)
                return false;

            if (customer.IsGuest)
                return false;


            var registeredCustomerSession = GetCustomerSessionByCustomerId(customer.CustomerId);
            if (registeredCustomerSession != null)
            {
                registeredCustomerSession.IsExpired = false;
                var anonCustomerSession = NopContext.Current.Session;
                var cart1 = IoC.Resolve<IShoppingCartService>().GetCurrentShoppingCart(ShoppingCartTypeEnum.ShoppingCart);
                var cart2 = IoC.Resolve<IShoppingCartService>().GetCurrentShoppingCart(ShoppingCartTypeEnum.Wishlist);
                NopContext.Current.Session = registeredCustomerSession;

                if ((anonCustomerSession != null) && (anonCustomerSession.CustomerSessionGuid != registeredCustomerSession.CustomerSessionGuid))
                {
                    if (anonCustomerSession.Customer != null)
                    {
                        customer = ApplyDiscountCouponCode(customer.CustomerId, anonCustomerSession.Customer.LastAppliedCouponCode);
                        customer = ApplyGiftCardCouponCode(customer.CustomerId, anonCustomerSession.Customer.GiftCardCouponCodes);
                    }

                    foreach (ShoppingCartItem item in cart1)
                    {
                        IoC.Resolve<IShoppingCartService>().AddToCart(
                            item.ShoppingCartType,
                            item.ProductVariantId,
                            item.AttributesXml,
                            item.CustomerEnteredPrice,
                            item.Quantity);
                        IoC.Resolve<IShoppingCartService>().DeleteShoppingCartItem(item.ShoppingCartItemId, true);
                    }
                    foreach (ShoppingCartItem item in cart2)
                    {
                        IoC.Resolve<IShoppingCartService>().AddToCart(
                            item.ShoppingCartType,
                            item.ProductVariantId,
                            item.AttributesXml,
                            item.CustomerEnteredPrice,
                            item.Quantity);
                        IoC.Resolve<IShoppingCartService>().DeleteShoppingCartItem(item.ShoppingCartItemId, true);
                    }
                }
            }
            if (NopContext.Current.Session == null)
                NopContext.Current.Session = NopContext.Current.GetSession(true);
            NopContext.Current.Session.IsExpired = false;
            NopContext.Current.Session.LastAccessed = DateTime.UtcNow;
            NopContext.Current.Session.CustomerId = customer.CustomerId;
            NopContext.Current.Session = SaveCustomerSession(NopContext.Current.Session.CustomerSessionGuid, NopContext.Current.Session.CustomerId, NopContext.Current.Session.LastAccessed, NopContext.Current.Session.IsExpired);

            return true;
        }


Now the final easiest logout part:
In NopCommerceStore\Modules\Header.ascx

<li>
                            <% if (NopContext.IsFacebookLogin)
                               { %>
                                    <a href="<%=Page.ResolveUrl("~/logout.aspx")%>" class="ico-logout" onclick='FB.logout()'><%=GetLocaleResourceString("Account.Logout")%></a>
                            <% } %>
                            <% else
                               { %>
                            <a href="<%=Page.ResolveUrl("~/logout.aspx")%>" class="ico-logout">
                                <%=GetLocaleResourceString("Account.Logout")%></a>
                            <% } %>
                        </li>

You can see how NopContext.IsFacebookLogin comes into play here: if this is a facebook login, then when user clicks logout, FB.logout() should be called first.

That completes the integration of facebook login into nopcommerce.
Thanks for reading and let me know any issues/improvement
12 Jahre weitere
cynosureabu - thanks very much for sharing this great update! Is there any chance you could just zip all the files up, and let the people who need it download the .zip? Less chance of copy/paste issues, etc.  I've recently done the same thing for code updates on the SagePay Server implementation, because I know what a bugger it is to copy everything manually.  Thanks again!
12 Jahre weitere
Can this only be accomplished with the nopCommerce_1.90_Source version ?
12 Jahre weitere
Seems there are some typographical errors...facebokClient INSTEAD of facebookClient (twice). Am I correct?

[WebMethod]
public static string UserIDExists(string uid, string accesstoken, string returnurl)        
{            
string result = "false";
            var facebokClient = string.IsNullOrEmpty(accesstoken) ? new FacebookClient() : new FacebookClient(accesstoken);            
dynamic me = facebokClient.Get("me?fields=email");
12 Jahre weitere
Also which Facebook SDK are you using?

1. Developer toolkit

OR

2. Facebook C# SDK

EDIT-
I can see your using the Facebook C# SDK V5, no need to answer.
12 Jahre weitere
Can this only be done with the source version ? Has anyone been able to put together a comprehensive tutorial ?
12 Jahre weitere
Thanks a lot. This is working in our site! I´m also working in more facebook integration now. Thanks! When my site is ready for prime time I will post a link here.

One tip for the others. You dont need to download all the code in a package what worked best for me is to read all his post in order and make the changes he explains in my on code. This will also help you understand everything better (reading developers.facebook.com will help but all you need to do is creat an app id).

Just cut and paste some of the bits his posted and its ok. For the final part you will have to add the facebook library on http://facebooksdk.codeplex.com/ (I recomend using NuGet Package) but this is used only in the end.
12 Jahre weitere
Thank you rbnunes. You proved that i was not lying! :-)

and yeah that's the purpose of my posting. I don't want just upload all my source code as I have many other changes as well. I may post some other topics like ajax late loading, jquey slideshow etc once I have spare time.


rbnunes wrote:
Thanks a lot. This is working in our site! I´m also working in more facebook integration now. Thanks! When my site is ready for prime time I will post a link here.

One tip for the others. You dont need to download all the code in a package what worked best for me is to read all his post in order and make the changes he explains in my on code. This will also help you understand everything better (reading developers.facebook.com will help but all you need to do is creat an app id).

Just cut and paste some of the bits his posted and its ok. For the final part you will have to add the facebook library on http://facebooksdk.codeplex.com/ (I recomend using NuGet Package) but this is used only in the end.
12 Jahre weitere
Still doesn't answer my question but ok.
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.