preface

If you don’t know what the enterprise wechat sidebar is, you can cross this article out. If you know what this is, you must be very upset about how to start.

Since last year has been doing the enterprise wechat sidebar application. To be honest, the development and debugging experience was awful, and I didn’t even know how to open it when I got started.

The most difficult thing is that the official document is not carefully written, even the simplest Demo can run, let’s go to the development discussion area, the official customer service is not very familiar with the code, even without asking, many posts are netizens help each other.

So in order to help more people use the sidebar, I wrote a tutorial website and two front-end and back-end demos.

This tutorial and Demo are both on this Organization, you can also pay attention to it.

Of course, this article is not simple hydrology, so let’s briefly talk about some important parts of the enterprise wechat sidebar.

What is the

The enterprise wechat sidebar (hereafter referred to as the enterprise wechat sidebar) is actually a sidebar (WebView) on the right side of the enterprise wechat.

However, not all sessions can open the sidebar. The sidebar button can only be opened in the lower right corner of conversations between external contacts and external contact groups.

What about external contacts and external contact groups? Why should it be opened only in this case? This brings us to the problem that the sidebar is trying to solve.

why

The real pain point that the sidebar is addressing is community/customer operations and management.

Maybe you only have about 300 friends on wechat, but have you ever thought that if you are a salesperson, you may need to add 1000+ customers, create 100+ group chats, and receive hundreds of messages every day?

These customers may be divided into: those who want to buy products, those who want to buy products, those who have bought products, ordinary customers, VIPs, SVIPs, etc.

Group chats may be divided into: November 2020 study group, VIP group, fan group, etc.

So many customers and group chat, for a single sales staff is very headache. It is easy to forget which partition, which category, and which label the customer belongs to.

What’s more, the sales staff’s main job is to refine operations and chat with customers and groups on a daily basis. When, how, and what to talk about are all college questions, and it’s even more difficult when you’re talking to so many clients and groups. By way of analogy, a time management guru can only talk to 10 people at most and is already at his peak.

So the enterprise wechat thought: can there be a toolbox in the chat session, the sales staff can view the customer/group chat business array in this toolbox, or better operation through this toolbox. That’s where the sidebar comes in.

These “customers” and “group chats” are called “external contacts” and “external contact groups,” and by “external” I mean people outside the organization.

Sidebar application architecture

The sidebar is also essentially a WebView, so we just need to write the front end, and either normal HTML or SPA App can be placed on the sidebar.

However, the common front end is not enough. If you want to interact with the enterprise wechat, such as sending messages, immediately creating group chats and opening personal information pop-ups, you need the JS-SDK provided by the enterprise wechat. Please see the specific document here.

However, jS-SDK can only be used normally before config, and the parameters of config need to obtain jSAPi_ticket from the enterprise wechat server to generate signature before jS-SDK can be initialized normally.

wx.agentConfig({
    corpid: ' '.// Mandatory, enterprise wechat corPID, must be the same as the current login enterprise
    agentid: ' '.// mandatory, enterprise wechat application id (e.g. 1000247)
    timestamp:,// Mandatory to generate the timestamp of the signature
    nonceStr: ' '.// Mandatory to generate a random string of signatures
    signature: ' '.// Mandatory, signature, see appendix - js-SDK Using permission signature algorithm
    jsApiList: ['selectExternalContact'].// Mandatory, passing in the name of the interface to be used
    success: function(res) {
        / / callback
    },
    fail: function(res) {
        if(res.errMsg.indexOf('function not exist') > -1){
            alert('Version too old please upgrade')}}});Copy the code

The key parameter access_token is required to obtain jSAPi_ticket from the enterprise wechat server, and access_token cannot be cached directly in the front end. Therefore, another back-end (middle layer) is needed to cache access_token. It also provides the forwarding service of enterprise wechat server API.

So, in general, the sidebar looks like a front-end thing, but its infrastructure is at least a sidebar, a business server, and an enterprise micro server.

The enterprise micro server has been provided by the enterprise wechat, then what we want to achieve is the sidebar and business server. If you’re new to the sidebar, it’s going to get pretty annoying, so I recommend forking my sidebar (front end) template and my back-end template, and making changes from there.

Key parts of development

Because there is so much detail in this, it is better to look at the two templates to see the implementation, but here are just a few important points.

The forward service

First, let’s talk about the forwarding service. It needs to forward the API of the micro and enterprise server, and the request of the server needs the access_token as an important parameter to transfer, but the access_token cannot be requested all the time, so redis cache is needed.

And Redis needs Docker to start, have to say that in order to make a simple web page, even Docker is on the whole:

version: '3'
services:
  redis:
    image: redis
    container_name: 'wecom-sidebar-redis'
    ports:
      - "6379:6379"
    restart: always
Copy the code

Forwarding service in the template I use a simple Koa implementation, redis client NPM package, can use ioredis cache.

If the proxy is set to false, an error will be reported:

const axios = require('axios')

const baseURL = 'https://qyapi.weixin.qq.com/cgi-bin';

const proxy = axios.create({
  baseURL,
  proxy: false / / do not specify an SSL routines: ssl3_get_record: wrong version number, reference: https://github.com/guzzle/guzzle/issues/2593
})

module.exports = proxy
Copy the code

The specific forward call API I believe we will not say how to write.

Redirect to get the userId

This mechanism of obtaining userId is similar to wechat web development. You need to redirect a URL, then obtain the code from the search parameter, and then use this code to exchange the userId from the enterprise wechat server through the forwarding service above. The specific implementation can be seen in the document here.

/** * Get the OAuth path for relocation *@returns {string}* /
const generateOAuthUrl = (config: Config) = > {
  const [redirectUri] = window.location.href.split(The '#');

  const searchObj = {
    appid: config.corpId,
    redirect_uri: encodeURIComponent(redirectUri),
    response_type: 'code'.scope: 'snsapi_base'.agentid: config.agentId,
    state: 'A1'};const search = Object.entries(searchObj)
    .map(entry= > {
      const [key, value] = entry;
      return `${key}=${value}`;
    })
    .join('&');

  return `https://open.weixin.qq.com/connect/oauth2/authorize?${search}#wechat_redirect`;
};

/** * Determine whether the current page needs to be redirected */
const checkRedirect = async (config: Config, getUserId: GetUserId) => {
  if (isMock) return

  const userId = Cookies.get('userId')

  constunAuth = ! userId || userId ==='undefined' || userId === 'null'

  const codeExist = window.location.search.includes('code');

  // Determine whether a redirect is required
  if(unAuth && ! codeExist) {window.location.replace(generateOAuthUrl(config));
  }

  // Determine whether to obtain the userId again
  if (unAuth) {
    const code = qs.parse(window.location.search.slice(1)).code as string

    const newUserId = await getUserId(code)

    Cookies.set('userId', newUserId)
  }
};
Copy the code

JS – SDK initialization

This is the most important step when using the client API, and the JS-SDK API of enterprise Micro is very troublesome to use, so I encapsulate its API again, mainly with the operation of promisify:

const agentConfig = (agentSetting: Omit<wx.AgentConfigParams, 'success' | 'fail'>) :Promise<wx.WxFnCallbackRes> => {
  return new Promise((resolve, reject) = >{ wx.agentConfig({ ... agentSetting,success: resolve,
      fail: reject,
    });
  });
};
Copy the code

Then get signature from our forwarding service and call agentConfig (not config above 3.0.24),

const initSdk = async (config: Config, getSignatures: GetSignatures) => {
  const { corpId, agentId } = config;

  / / get the ticket
  const signaturesRes = await getSignatures();

  const agentConfigRes = await jsSdk.agentConfig({
    corpid: corpId,
    agentid: agentId,
    timestamp: signaturesRes.meta.timestamp,
    nonceStr: signaturesRes.meta.nonceStr,
    signature: signaturesRes.app.signature,
    jsApiList: apis,
  }).catch(e= > {
    console.error(e)
  });

  console.log('agentConfig res', agentConfigRes);

  wx.error(console.error);
};
Copy the code

Local development

Local development should be an ideal environment for all front-end development. However, when configuring the HTML address of the sidebar application, you can’t directly enter localhost, it must be a trusted domain name! Some tutorials on the web may ask you to change the hosts file directly to localhost.

The solution I give is to use Whistle to proxy the traffic of enterprise wechat to local localhost, so that it can be developed locally. The specific operation can be seen here.

Proxy front end (sidebar page proxy to local port 3000), Here to your own address configuration H5 / / service-aj0odbig-1253834571.gz.apigw.tencentcs.com http://127.0.0.1:3000 # agent back-end (back-end template baseURL write to death Backend.com, which proxies to local port 5000) //backend.com http://127.0.0.1:5000Copy the code

However, it is still a hassle to debug our application on the enterprise wechat sidebar. We prefer to debug the application directly on the browser, and then debug it in the real sidebar environment when we are ready to develop.

With this in mind, I implement Mock patterns in my front-end templates as well. To see how this works, you can directly Mock the client API’s return values and user identities. Can greatly improve the development efficiency.

conclusion

Overall, I personally feel that while sidebar development is a hassle with a lot of bugs and compatibility issues, it is a very useful tool for the client/community to run.

Hopefully this article has brought some basic concepts to the sidebar, and you can learn more about them in my tutorial.