No WeChat no life (part III): implementing an echo service

06 Apr, 2018
Xebia Background Header Wave

In this three-part series on WeChat, Léon will show you how the Chinese alternative to WhatsApp’ is transforming the on- and offline lives of Chinese consumers, thereby forcing companies to reconsider their marketing and sales strategies. In the previous two parts, he argued for the necessity of a presence on WeChat for companies facing Chinese customers and gave an overview of the features. In this part, he will show you how to build a simple echo service using the WeChat APIs.
After the previous two more theoretical posts, it is time to get our hands dirty. As you might recall from part 2 of this series, companies can register an official account (OA) on WeChat to get access to all the APIs that the platform provides. An OA shows up in a user’s chat list, either between the regular chats or in a dedicated folder, and can send and receive messages to users or provide other useful on-demand services in the chat. Today, we will build an endpoint that follows the WeChat standards and can be tested on WeChat using the debug sandbox. It will echo any message a user sends by replying with the contents of the message reversed. Although this is not a really compelling example, it sets you up with the right tools to build more enticing user experiences on WeChat (and it forces you to register a WeChat account ;)). 

We will build the endpoint using Express, a library for creating web applications on Node.js, but it is important to understand that any type of HTTP server can be used. If you have an existing backend that needs to integrate with WeChat, you could of course implement it on the existing stack. As long as it fulfils the (simple) requirements set forth by WeChat, it will suffice. Let’s get started. The final code is on GitHub.

Step 1: Setup

  1. Make sure you have the latest (or a pretty recent) Node.js and NPM installed on your machine.
  2. Install ngrok. It will be used as a secure tunnel to your machine that WeChat can access, more on that later.
  3. Create a new directory on your filesystem and initialize a new project (this guide assumes you are on a macOS machine, Linux or Windows users should change the commands and directories accordingly):
  1. Install Express through NPM
  1. Open the code editor of your choice and point it at the directory you just created (it should contain a <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">package.json</span>, <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">package-lock.json</span> and <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">node_modules/</span> directory).

Step 2: Get access to the WeChat sandbox

  1. Install WeChat through the App Store or Google Play if you haven’t already and register an account. If you’re already on WeChat, you can skip this step.
  2. Browse to the sandbox (unfortunately, the authentication in the English edition seems to be broken, so we will use the Chinese edition).
  3. Log in by clicking the green button (登录 log in’) and scanning the QR code (you can find the scanner by tapping the +’ on the chat overview).
  4. Authorize the sandbox by confirming the login on your phone.
  5. You should be taken to a page that shows your <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">appID</span> and <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">appsecret</span> .

Step 3: Initialize the Express app

Create a file <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">index.js</span> and set up a simple Express app:

This should be enough to test your setup. Go back to the terminal and run Node on the current directory (or <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">index.js</span>):

You should see the message <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">WeChat endpoint listening on port 3000...</span> logged to the terminal. Open a browser and browse to https://localhost:3000. It should show the simple message WeChat endpoint’. 

Step 4: Connect your app to WeChat

We will set up the routes that are specific to WeChat in a new file. Create a new file <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">wechat.js</span>, in the same directory as <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">index.js</span>, and set up the Express router in that file:

The first time you set up your server as the endpoint of an Official Account, it needs to respond with an echo string to verify that everything works correctly. WeChat will send a signature, nonce, timestamp and echo string (<span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">echostr</span>) to your app with which you can verify that it is indeed WeChat that is connecting. If the signature is correct, you should respond with the <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">echostr</span>. To make this blog post a bit shorter, we will short-circuit this and always return the <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">echostr</span> (in production, you want to make sure that everything is correct though): 

This code will check if an <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">echostr</span> is set as a query parameter and outputs it if it is set. Otherwise, it returns a 404 status code and error message. The logging statements will be shown in the terminal session you used to start up the Node application.
Before we can test whether our setup is working, we need to tell Express to also load the route in the <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">wechat.js</span> file when starting up in <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">index.js</span>. You can do that by adding the following line to <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">index.js</span>:

Put this below the <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">app.get(</span><span class="inline-code">'</span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">/</span><span class="inline-code">'</span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">)</span> call we created earlier, above the port definition.
You are now ready to check if WeChat can reach your application through an ngrok tunnel. If your Node application is still running, kill it with Ctrl-C and then restart it with <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">node .</span>. Make sure there are no errors while starting up and then open a second terminal window. Run ngrok and have it create a tunnel to port 3000 with the following command:

After a few seconds you should see the output from ngrok. Copy-paste the second Forwarding’ URL (the https:// one) and paste it in your browser. This should connect without problems. You can open the ngrok web interface if you want (mentioned under the Web Interface’ entry).
Now go back to the WeChat sandbox page, and log in if necessary. There should be two fields named URL’ and Token’ in the second panel. Append <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">/wechat</span> to the https:// URL of ngrok and paste it in the URL’ field. Then type a random string in the Token’ field (like 123456, the contents don’t matter because we are not checking the signature). 
Click the green button (提交 submit’). You probably get an error. Click the button again. You should now see a 200 OK request coming in on the ngrok dashboard, and the URL and token should be saved in the sandbox. Your account has been set up!

1 – Fill in your ngrok URL and a token (can be anything)

2 – After clicking the green button twice, this should appear (with your URL and token)

Step 5: Process incoming messages

Whenever a user starts following your official accounts, sends a message to your account or unfollows it, you will receive a POST request with some XML describing the message. To handle these messages, we need to add another endpoint to our wechat.js file, but instead of calling app.get() to create a handler for GET requests, we will call to register a handler for POST requests. As we don’t want to write a lot of XML-parsing boilerplate code ourselves, we will install an XML body parser for Express that can handle this for us. Let’s start with that.
Install body-parser and body-parser-xml with the following command in your terminal:

Let’s set up the body parser. In index.js, change the two top lines (the ones that set up the Express app) so they reflect the following:

This again sets up an Express app but now also installs the body-parser XML middleware which will help us parse the incoming request bodies. Let’s write the POST request handler, below all other code in <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z95lz89zyft2og2z75zez76z3z80zvpz80zz76zz80zz82zz88zz90zz69zez70zp4hw">wechat.js</span>:

This piece of code sets up a POST handler on the router (line 6), takes the parsed XML out of the body and switches over the message type (line 9, the XML parser puts single text nodes into an array so that’s why we need to access it with index 0). The function then forwards the response object and parsed XML to one of three handlers (line 11, 13 and 15), for handling new events, text messages and any messages of unknown type respectively. The last step will involve implementing these handlers and returning an XML response that will be sent to the user.

Step 6: Write message handlers

This is the final step of implementing our WeChat echo service! As WeChat requires us to respond with XML, we will use template strings to easily create an XML string that can be written to the response object. WeChat then sends our message to the user’s device, so it feels as if they are talking to an actual person.
The function for setting up the template is as follows:

This will inject the receiver, sender and text content into an XML string that can be sent in the handlers. You should add this function above the handlers, by replacing TODO 3.
Next, we’ll set up our handlers. The most complex one is the handler for event type messages, as there can be multiple types of events that are triggered. We are only interested in the `subscribe` event, that is triggered when a user scans your QR code and taps ‘Follow’. This is the handler:

The handleEvent function extracts the event type from the XML data and checks if it is a subscribe event. It then creates an XML response by flipping the sender and receiver from the XML data and adding a string message. This will welcome new followers with the ‘Welcome to our Official Account!’ message.
While we’re at it, let’s implement the other message handlers:

In the handleText function, the string that is sent back is the reversed text message sent by the user. In the handleUnknown function, we just send back a message telling the user that our echo service does not (yet) understand what they’re saying.
And that’s it! After all the hard work it is time to see what happens when we start to follow our own Official Account and send some messages. To start following yourself, scan the QR code that is shown on the WeChat sandbox page, halfway down. On your phone, tab the ‘+’ at the top-right corner in the chat overview, then tap ‘Scan QR code’. After scanning the code, you should see a simple page with a large ‘Follow’ button. If you tap that, WeChat should open a new chat with the echo service. It should welcome you with the message we added earlier. If you send a text message, the echo service should reply with your message reversed. If you send anything else (a picture maybe, or your location) the echo service will tell you that it doesn’t understand that message type. If this all works, good job!

Wrap up

You’ve now seen how you can build a simple application on WeChat using the Official Account debug sandbox. As an exercise, you could try changing the code so the service greets the user with a menu, and based on the user’s response trigger an action like sending a video or image. The technical documentation of WeChat will help you in figuring out how to handle incoming media files and how to respond to them. Luckily, the ideas are similar to what you have seen so far.
Also, you could host your Node application somewhere in the cloud so it keeps reacting to new messages. Right now, if you kill your ngrok tunnel and/or Node app, WeChat will show an error to users that sent anything to your sandbox account. You can look into tools like Zeit Now to easily deploy your Node app in a more persistent way, or try the Amazon and Google clouds for easy hosting. After setting up your application elsewhere, don’t forget to change the URL on the sandbox page.
I hope the implementation of a simple echo service helped you assess whether or not WeChat is the right platform for your business and whether or not it can help you get more traction within the Chinese market. If you decide to go with WeChat, the first steps in this blog post should help you get up and running as quickly as possible. Should you inadvertently need help with the strategic or technical implementation of WeChat for your proposition on the Chinese market, please don’t hesitate to contact us!
Léon Rodenburg is a full stack development consultant at Xebia. He has a background in Computer Science and Sinology and is always on the lookout for the crossroads between the two. Having lived and studied in China for quite some time, he has put his knowledge of the Chinese language into practice by experiencing on- and offline daily life in Beijing like a local.

Some useful links:
Léon Rodenburg
Léon Rodenburg is a full stack development consultant at Xebia. He has a background in Computer Science and Sinology and is always on the lookout for the crossroads between the two. Having lived and studied in China for quite some time, he has put his knowledge of the Chinese language into practice by experiencing on- and offline daily life in Beijing like a local.

Get in touch with us to learn more about the subject and related solutions

Explore related posts