Integrate WeChat with Sitecore and Create Contact Profile of WeChat User

Recently, we did research on how can we integrate WeChat – Chinese multi-purpose messaging, social media and mobile payment app – with Sitecore for one of our clients.Firstly, a quick overview of services provided by WeChat to connect with WeChat users.

WeChat Official Account Admin Platform

WeChat provides Official Account Admin Platform to connect with billions of WeChat users. The WeChat Official Account is equivalent of a Facebook page. It is an interface a brand can use to gather followers, send them push notifications and redirect them to a website/e-commerce. Users can then open the account to access a conversation interface where they can either click on push notifications or access information through the bottom menu interface.

WeChat Official Account Admin Platform API

WeChat Official Account Admin Platform API allows developers to access and integrate the functionality of WeChat with other applications. Some example API methods include receiving messages, sending messages, managing users, etc.You can refer following to get started with WeChat Official Account Platform:http://open.wechat.com/cgi-bin/newreadtemplate?t=overseas_open/section_detail&show=officehttps://admin.wechat.com/cgi-bin/readtemplate?t=ibg_en/en_faq_tmpl&type=info&lang=en_UShttp://admin.wechat.com/wiki/index.php?title=API_Introductionhttp://open.wechat.com/cgi-bin/newreadtemplate?t=overseas_open/docs/oa/index#oa_indexLet’s discuss the research requirement and approach.

Requirement:

When customer clicks on link through WeChat application, the link shall take customer to page hosted in Sitecore.Once the customer lands on the Sitecore website, create a contact with the customer’s personal information which should be taken from WeChat system.

Approach:

Before using API, developers need to create an application on WeChat Official Account Platform and verify validity of server address to access the platform. WeChat provides test account application which allows developers to test all API methods of the platform directly.

To create WeChat Sandbox Official Account:

1. Navigate to https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login2. Click on login and scan QR code through your WeChat public profile.This will create a test account and you will get the AppId and Appsecret. This information will be used to access the WeChat API.3. Follow the steps provided in below link to complete server configuration and verify validity of server address:http://open.wechat.com/cgi-bin/newreadtemplate?t=overseas_open/docs/oa/getting-started/getting-started#getting-started_getting-startedNext, we created a page which displays QR code of sandbox official account using Generating Parametric QR Codes API method. User can scan this code by using WeChat’s embedded QR code scanner to subscribe.

To generate QR code of official account:

1. Get access token using below API methodhttp://open.wechat.com/cgi-bin/newreadtemplate?t=overseas_open/docs/oa/basic-info/access-tokens#basic-info_access-tokensLet's look at implementation of Get Access Token API:

public static string GetAccessToken()        {            HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("accessToken");            // Check if cookie exists in the current request.            if (cookie == null)            {                AccessToken token = (AccessToken)JsonConvert.DeserializeObject(AppService.HttpRequestGet("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appsecret), typeof(AccessToken));                if (token != null && !string.IsNullOrWhiteSpace(token.Access_Token))                {                    cookie = new HttpCookie("accessToken")                    {                        Value = token.Access_Token,                        // Set cookie to expire in 2 hours.                        Expires = DateTime.Now.AddHours(2)                    };                    // Insert the cookie in the current HttpResponse.                    HttpContext.Current.Response.Cookies.Add(cookie);                    return token.Access_Token;                }                else                {                    return "Try again in sometime.";                }            }            else            {                return cookie.Value;            }        }

2. Generate permanent QR code using below API methodhttp://open.wechat.com/cgi-bin/newreadtemplate?t=overseas_open/docs/oa/promoting/generating-parametric-qr-codes#promoting_generating-parametric-qr-codesLet's look at implementation of Generate Parametric QR Codes:

public static string CreateQRCode()        {            string accessToken = AccessTokenService.GetAccessToken();            string url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + accessToken;            var qrCodeParams = new CreateQRCodeParams()            {                action_name = "QR_LIMIT_SCENE",                action_info = new Scene()                {                    scene_id = "1803"                }            };            string parameters = JsonConvert.SerializeObject(qrCodeParams);                        return AppService.WebRequestPost(url, parameters);                           }

3. You will obtain QR code ticket in response. Use this ticket to exchange the QR code using Exchange QR Code via Ticket API method:https://admin.wechat.com/cgi-bin/showqrcode?ticket=TICKET4. Download the QR code image obtained in response and include it into web page.Next you need to provide some way through which user can access your website. It can be push notification, link or bottom menu interface. We created a user-defined menu which has a link of page hosted in Sitecore. When user clicks on this, Sitecore obtains user's profile information using Web-based Authorization API, identifies the contact and sets the Personal Information contact facet.Developers can create custom menus in Official Account using below API method:http://open.wechat.com/cgi-bin/newreadtemplate?t=overseas_open/docs/oa/custom-menus/create#custom-menus_createDevelopers can obtain a user's profile information or execute service logic via below API when a user visits a third-party web page for an Official Account on WeChat:http://open.wechat.com/cgi-bin/newreadtemplate?t=overseas_open/docs/oa/web/user-profile-auth#web_user-profile-auth

To create menu button, get user information and create a contact profile:

1. Set the callback domain name. It can be set for sandbox account as below:

  • Find “Web page authorization for basic user information” in “Experience interface permission table” on your sandbox account page. You will find “modify” link to set callback domain.

  • Click on modify and set the domain as per instructions.

2. Create a view-only menu button which allows WeChat user to click and open the URL entered by developer on the button. Use the below URL on menu button. This will provide you an access token which will be used in further steps.https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

  • appid: The unique ID of the Official Account
  • redirect_uri: Callback redirection URL after authorization (URL of your website)
  • response_type: Code
  • scope:   App authorization scope. Use snsapi_userinfo scope to get user’s basic information
  • state: This parameter is included in the link after redirection. The developer can set a random value.

Let's look at implementation of Create Custom Menu API:

public class CreateMenuService    {        public static string CreateMenu()        {            string accessToken = AccessTokenService.GetAccessToken();            string url = "https://api.wechat.com/cgi-bin/menu/create?access_token=" + accessToken;            var createMenuParams = new CreateMenuParams();            createMenuParams.button.Add(new CreateMenuParams.MenuButton()            {                type = "view",                name = "Sitecore Experience Platform",                url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxe50bdb27143920a2&redirect_uri=http://wechatpoc.com/&response_type=code&scope=snsapi_userinfo&state=1803#wechat_redirect"            });            string parameters = JsonConvert.SerializeObject(createMenuParams);            return AppService.WebRequestPost(url, parameters);                    }    }

 When user clicks on above created custom menu, user will be redirected to a page hosted in Sitecore and below steps will executed in background:3. Request the following API method to obtain access token after you receive the code as a response of menu button click request:https://api.wechat.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

  • appid: The unique ID of the Official Account
  • secret: The appsecret of the Official Account
  • code: The code parameter obtained in the above step
  • grant_type: authorization_code

4. Request the following API method to obtain user information after you receive access token and user’s open id as a response above request:https://api.wechat.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID

  • access_token: The certificate for calling the web authorization API. Note: this access token is not the one mentioned in the Basic Support pages.
  • Openid: A unique user ID specific to a given Official Account. A non-follower visiting an Official Account's web pages can also generate a unique OpenID.

You will get user’s nick name, gender, province, city, county, profile image and privileges as a response.Let's look at implementation of User Profile Authorization API:

public static UserInfo GetUserInfo(string code)        {            if (!string.IsNullOrWhiteSpace(code))            {                string tokenUrl = string.Format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code", appid, appsecret, code);                AuthTokenResponse token = (AuthTokenResponse)JsonConvert.DeserializeObject(AppService.HttpRequestGet(tokenUrl), typeof(AuthTokenResponse));                if (token != null)                {                    var expiresIn = DateTime.UtcNow.AddSeconds(Convert.ToDouble(token.Expires_in));                    if (DateTime.UtcNow > expiresIn)                    {                        string refreshTokenUrl = string.Format("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid={0}&grant_type=refresh_token&refresh_token={1}", appid, token.Refresh_token);                        token = (AuthTokenResponse)JsonConvert.DeserializeObject(AppService.HttpRequestGet(refreshTokenUrl), typeof(AuthTokenResponse));                    }                    if (token != null && !string.IsNullOrWhiteSpace(token.Access_token))                    {                        string userInfoUrl = string.Format("https://api.weixin.qq.com/sns/userinfo?access_token={0}&openid={1}&lang=en", token.Access_token, token.Openid);                        UserInfo userInfo = (UserInfo)JsonConvert.DeserializeObject(AppService.HttpRequestGet(userInfoUrl), typeof(UserInfo));                        return userInfo;                    }                }            }            return null;        }

5. Now, identify the contact using user’s Open Id and set the Personal Information contact facet using xConnect API.

public static void AddContact(UserInfo userInfo)        {            using (XConnectClient client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())            {                try                {                    //Identify contact                    Sitecore.Analytics.Tracker.Current.Session.IdentifyAs("wechat", userInfo.Openid);                    //Retrieve contact                    Contact existingContact = client.Get(new IdentifiedContactReference("wechat", userInfo.Openid), new ContactExpandOptions(PersonalInformation.DefaultFacetKey));                    if (existingContact != null)                    {                        //Retrieve facet by name                        var personalInfoFacet = existingContact.GetFacet<PersonalInformation>(PersonalInformation.DefaultFacetKey);                        if (personalInfoFacet != null)                        {                            //Change facet properties                            personalInfoFacet.FirstName = userInfo.Nickname;                            personalInfoFacet.Nickname = userInfo.Nickname;                            personalInfoFacet.Gender = !string.IsNullOrWhiteSpace(userInfo.Sex) ? (userInfo.Sex.Equals("1") ? "Male" : (userInfo.Sex.Equals("2") ? "Female" : string.Empty)) : string.Empty;                            personalInfoFacet.PreferredLanguage = userInfo.Language;                            //Set the updated facet                            client.SetFacet(existingContact, personalInfoFacet);                        }                        else                        {                            //Create facet                            personalInfoFacet = new PersonalInformation()                            {                                FirstName = userInfo.Nickname,                                Nickname = userInfo.Nickname,                                Gender = !string.IsNullOrWhiteSpace(userInfo.Sex) ? (userInfo.Sex.Equals("1") ? "Male" : (userInfo.Sex.Equals("2") ? "Female" : string.Empty)) : string.Empty,                                PreferredLanguage = userInfo.Language                            };                            client.SetFacet(existingContact, personalInfoFacet);                        }                                                client.Submit();                    }                               }                catch (XdbExecutionException ex)                {                    Log.Error("Contact Service - Add Contact", ex, "");                }            }        }

Following these steps, the contact will be created in xDB and it can be viewed in Experience Profile:You can grab the code from WeChat Integration with Sitecore repository.