Help Center> Elastic Cloud Server> Best Practices> Deploying an ECS for Handling Text Messages from an Official WeChat Account
Updated on 2024-03-06 GMT+08:00

Deploying an ECS for Handling Text Messages from an Official WeChat Account

Overview

The best practices for Huawei Cloud ECS guide you through the deployment of an ECS as an official WeChat account server so that the ECS receives text messages from the WeChat server and sends processing results to end users. On this ECS, Python is used to compile the logic code for processing WeChat messages. Figure 1 shows the service flow.

Figure 1 Flowchart for processing text messages

Before performing the operations described in this section, you are required to have basic knowledge on the CentOS (Linux), Python language, Web.py framework, and HTTP/XML protocol.

Preparations

  • Apply for an official WeChat account.

    URL: https://mp.weixin.qq.com/

    This section uses the Service Infographics WeChat account as an example.

  • Purchase an ECS.

    If you don't have an account, register a HUAWEI ID and enable Huawei Cloud services.

    This section uses an ECS running CentOS 7.4 as an example.

    Figure 2 Public image
  • Purchase an EIP.

    Purchase an EIP with your ECS. The EIP will be configured in the official WeChat account.

    Figure 3 EIP

Installing Basic Software

This section uses Python and Web.py to develop the official WeChat account. You are required to install or upgrade Python, pip, Web.py framework, and WinSCP software.

Upgrade the default Python version.

The Python version delivered with CentOS 7.4 is too old to use. You are advised to upgrade it to Python 3.

  1. Run the following command to view the Python version:

    python --version

    Figure 4 Viewing the Python version
  2. Download the Python installation package, for example, Python 3.6.0.

    wget https://www.python.org/ftp/python/3.6.0/Python-3.6.0a1.tar.xz

    Figure 5 Downloading the Python installation package
  3. Run the following command to decompress the installation package:

    tar xvf Python-3.6.0a1.tar.xz

  4. Run the following commands to configure Python:

    cd Python-3.6.0a1

    ./configure

    • If information similar to the following is displayed, the command has been successfully executed.
      Figure 6 Successful execution
    • If the message "configure: error: no acceptable C compiler found in $PATH" is displayed, no proper compiler has been installed.

      Solution:

      Run the following command to install or upgrade GCC and its dependent packages:

      sudo yum install gcc-c++

      Enter y and press Enter as prompted. If information shown in Figure 7 is displayed, the dependency packages have been installed.

      Figure 7 Successful installation

      Run the ./configure command again.

  5. Run the following command to install Python:

    make && make install

    If the system displays a pip error after the command execution, the openssl-devel package is unavailable. Ignore the error.

    Figure 8 Successful execution
  6. Run the following command to view the Python 3 version:

    python3 --version

    Figure 9 Viewing the Python 3 version
  7. Run the following command to verify the Python 3 installation:

    python3

    If information shown in the following figure is displayed, Python 3 has been installed.

    Figure 10 Successful installation

    Before performing subsequent operations, exit the Python CLI by running any of the following commands and press Enter:

    • Ctrl+Z
    • exit()
    • quit()

Upgrade the default pip version.

pip is a common Python package management tool, which allows you to search for, download, install, and uninstall Python packages. pip3 is delivered with Python 3, but the version is too old to use. Upgrade pip to the latest version. During Python 3 installation, the error message "Ignoring ensurepip failure: pip 8.1.1 requires SSL/TLS" indicates a pip installation failure. Therefore, pip must be reinstalled.

  1. Run the following command to install the openssl-devel package:

    yum install openssl-devel -y

    Figure 11 Installing the openssl-devel package
  2. Run the following command to install pip:

    make && make install

    If information shown in the following figure is displayed, pip has been installed.

    Figure 12 Successful installation
  3. Run the following command to upgrade pip3:

    pip3 install --upgrade pip

    If information shown in the following figure is displayed, pip has been upgraded to the latest version.

    Figure 13 Successful upgrade

Install the Web.py framework.

To obtain the official Web.py installation tutorial, log in at http://webpy.org/. Run the following command to install Web.py:

pip3 install web.py==0.40.dev0

Figure 14 Installing Web.py

Install WinSCP.

Code is generally edited on a local Windows OS and uploaded to the CentOS ECS. WinSCP is an SSH-based open source SFTP client for Windows and supports SCP. Its main function is file transfer between a local and a remote computer. Additionally, WinSCP offers scripting and basic file manager functionality.

Download WinSCP from https://winscp.net/eng/index.php.

Uploading Code

  1. Create the main.py file and copy the following data:
    # -*- coding: utf-8 -*-
    # filename: main.py
    import web
    from handle import Handle
    
    urls = (
        '/wx', 'Handle',
    )
    
    if __name__ == '__main__':
        app = web.application(urls, globals())
        app.run()
  2. Create the handle.py file and copy the following data:
    # -*- coding: utf-8 -*-
    # filename: handle.py
    
    import hashlib
    import web
    import receive
    import time
    import os
    
    class Handle(object):
    
        def __init__(self):
            self.app_root = os.path.dirname(__file__)
            self.templates_root = os.path.join(self.app_root, 'templates')
            self.render = web.template.render(self.templates_root)
    
        def GET(self):
            try:
                data = web.input()
                if len(data) == 0:
                    return "hello, this is handle view"
                signature = data.signature
                timestamp = data.timestamp
                nonce = data.nonce
                echostr = data.echostr
                token = "Use the taken value obtained in the basic configuration of the official WeChat account."
    
                list = [token, timestamp, nonce]
                list.sort()
                s = list[0] + list[1] + list[2]
                hashcode = hashlib.sha1(s.encode('utf-8')).hexdigest()
                print( "handle/GET func: hashcode, signature: ", hashcode, signature)
                if hashcode == signature:
                    return echostr
                else:
                    return echostr
            except (Exception) as Argument:
                return Argument
    
        def POST(self):
            try:
                webData = web.data()
                print("Handle Post webdata is:\n", webData)
                #Print message body logs.
                recMsg = receive.parse_xml(webData)
    
                if isinstance(recMsg, receive.Msg) and recMsg.MsgType == 'text':
                    toUser = recMsg.FromUserName
                    fromUser = recMsg.ToUserName
                    content = "Welcome to Service Infographics." + str(recMsg.Content)
                    print('Reply message info:\n')
                    print('toUser =', toUser)
                    print('fromUser = ', fromUser)
                    print('content = ', content)
                    return self.render.reply_text(toUser, fromUser, int(time.time()), content)
                else:
                    print("Message types not supported:",recMsg.MsgType)
                    return "success"
            except (Exception) as Argment:
                return Argment
  3. Create the receive.py file and copy the following data:
    # -*- coding: utf-8 -*-
    # filename: receive.py
    import xml.etree.ElementTree as ET
    
    def parse_xml(web_data):
        if len(web_data) == 0:
            return None
        xmlData = ET.fromstring(web_data)
        msg_type = xmlData.find('MsgType').text
        if msg_type == 'text':
            return TextMsg(xmlData)
        elif msg_type == 'image':
            return ImageMsg(xmlData)
        elif msg_type == 'location':
            return LocationMsg(xmlData)
        elif msg_type == 'event':
            return EventMsg(xmlData)
    
    class Event(object):
        def __init__(self, xmlData):
            self.ToUserName = xmlData.find('ToUserName').text
            self.FromUserName = xmlData.find('FromUserName').text
            self.CreateTime = xmlData.find('CreateTime').text
            self.MsgType = xmlData.find('MsgType').text
            self.Eventkey = xmlData.find('EventKey').text
    
    class Msg(object):
        def __init__(self, xmlData):
            self.ToUserName = xmlData.find('ToUserName').text
            self.FromUserName = xmlData.find('FromUserName').text
            self.CreateTime = xmlData.find('CreateTime').text
            self.MsgType = xmlData.find('MsgType').text
            self.MsgId = xmlData.find('MsgId').text
    
    class TextMsg(Msg):
        def __init__(self, xmlData):
            Msg.__init__(self, xmlData)
            self.Content = xmlData.find('Content').text
    
    class ImageMsg(Msg):
        def __init__(self, xmlData):
            Msg.__init__(self, xmlData)
            self.PicUrl = xmlData.find('PicUrl').text
            self.MediaId = xmlData.find('MediaId').text
    
    class LocationMsg(Msg):
        def __init__(self, xmlData):
            Msg.__init__(self, xmlData)
            self.Location_X = xmlData.find('Location_X').text
            self.Location_Y = xmlData.find('Location_Y').text
    
    class EventMsg(Msg):
        def __init__(self, xmlData):
            Event.__init__(self, xmlData)
            self.Event = xmlData.find('Event').text
  4. Create the templates folder and the reply_text.xml file in the folder. Then, copy the following data:
    $def with (toUser,fromUser,createTime,content)
    <xml>
    <ToUserName><![CDATA[$toUser]]></ToUserName>
    <FromUserName><![CDATA[$fromUser]]></FromUserName>
    <CreateTime>$createTime</CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[$content]]></Content>
    </xml>
  5. Obtain the local file.
    Figure 15 Local file
  6. Use WinSCP to upload the preceding files and folder to the specified directory on the ECS.
    Figure 16 Uploading files

Starting the Service

Run the following command to start the service:

python3 main.py 80

If the command output shown in Figure 17 is displayed, the service has been started.

Figure 17 Successful service startup

Enabling the Developer Mode

  1. Log in to official WeChat platform, choose Develop > Basic Configuration, and click Modify Configuration.
  2. Specify the following basic configurations and click Submit.
    • URL: https://EIP bound to the ECS/wx. Port 80 is not required.
    • Token: the same as the token value in the handle.py file.
    • EncodingAESKey: generated randomly.
    • Message encryption and decryption: plaintext in this example.
  3. Authenticate the token and click Enable.

    If authenticating the token failed, check whether the token configuration is the same as that in the code for processing GET messages in the handle.py file.

Verifying Service Deployment

Send a text message to the official WeChat account. If the response is properly received, the service has been successfully deployed.