了解IT技术
老九你最好的选择

微信公众号开发 腾讯云 Python

最近申请了个微信公众号,发现其提供的基础功能只有一个——向用户推送图文消息,其他功能基本都需要公众号的拥有者具备基本的开发能力。简单了解,实践后,我写下这篇教程,供大家参考。

基本步骤我是参考微信公众平台的技术文档,中间会遇到的几个问题,我会在本文中指出。

一、申请服务器并完成环境配置

我购买的是腾讯云搭载Centos7.4操作系统的服务器,当然也可以购买阿里云、百度云等服务器。但在选择操作系统时建议选择Linux系列操作系统。

购买完成后,进入控制台中的云主机就可以看到服务器的公网ip,点击右侧的登陆按钮(账号密码都在站内信里)即可登陆购买服务器的操作系统。

没有接触过Linux操作系统的人面对这样的界面可能有点害怕。一步步来,不怕不怕。

首先输入python检查一下python版本,这里腾讯云里的默认安装版本是2.7,所以之后的代码都是python2的代码。

如果安装的是python3,需要修改后面提供的代码。

绝大多数Linux操作系统都内置了Python,不幸没有Python环境的话,还是自己搜一下Linux下Python的安装,这里不再赘述。

之后依次安装web.py、libxml2、libxslt、lxml 库,命令如下:

pip install web.py
pip install libxml2
pip install libxslt
pip install lxml

如果没有pip,也自行搜一下pip的安装,这里也不再赘述。安装完成这些库后就可以开始基本的开发了。

二、测试服务器

输入命令

vim main.py

进入Linux著名的经典的极度糟心的vim编辑器编写第一个python文件。

这里简单说一下vim的操作:

  1. 进入编辑器后按i键,进入编辑模式
  2. 输入代码,或者按ctrl+shift+v粘贴代码
  3. 确认无误后,按Esc键退出编辑模式,输入:wq保存文件并退出vim

想要其他vim操作,读者可以自行搜索。

main.py的代码如下:

# -*- coding: utf-8 -*-
# filename: main.py
import web

urls = (
    '/wx', 'Handle',
)

class Handle(object):
    def GET(self):
        return "hello, this is a handle view"

if __name__ == '__main__':
    app = web.application(urls, globals())
    app.run()

编辑完成后,输入命令

python main.py 80

此时如果运行成功则不会报错,并且浏览器输入http://外网IP:80/wx会出现下图界面

如果报“socket.error: No socket could be created”错误,则有2种可能:

1、未获取root权限,输入命令

sudo python main.py 80

2、端口占用

先查询端口占用的进程

netstat -tunlp |grep 80

这里我查出22248进程占用了我的80端口,然后我把这个进程杀死,输入命令

kill -9 22248

接下来就可以顺利运行 python main.py 80了。

三、公众号Token配置

这里默认已经申请好了公众号,点击公众号的左侧最下方开发里的基本配置,然后填写服务器配置信息。

URL填写为http://公网IP/wx

令牌即为自己设置的暗号,微信平台和服务器只有对上了这个暗号才能通信

消息加解密密钥初次开发不用涉及,点击随机生成就好

消息加解密方式选择明文模式就是不管上面的那个密钥

完成配置后先不要提交,因为服务器还不知道暗号,要给服务器也配置一下。ctrl+z退出上次运行。

1、修改main.py文件,输入命令

vim main.py

文件修改为

# -*- 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、写入handle.py文件,输入命令

vim handle.py

handle.py文件如下,注意将刚刚设置的暗号替换注释行的xxx

# -*- coding: utf-8 -*-
# filename: handle.py

import hashlib
import web

class Handle(object):
    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 = "xxx" #你的暗号

            list = [token, timestamp, nonce]
            list.sort()
            sha1 = hashlib.sha1()
            map(sha1.update, list)
            hashcode = sha1.hexdigest()
            print "handle/GET func: hashcode, signature: ", hashcode, signature
            if hashcode == signature:
                return echostr
            else:
                return ""
        except Exception, Argument:
            return Argument

3、重启main.py,输入命令

python main.py 80

注意这里可能因为之前启动的main.py占用80端口而启动失败,可参考之前的方法,杀了占用端口的进程,再重新运行main.py。

再回到公众平台点击提交按钮,若提示”token验证失败”, 请认真检查代码或网络链接等;若token验证成功,会自动返回基本配置的主页面,点击启动按钮。此时服务器和公众号已经建立了消息连接。

四、写一个功能

这一节我们可以写一个简单的微信公众号小程序——“你说我学”。

即用户发送消息给公众号,公众号回应同样的消息。

这里先简单讲解一下原理:

用户发送给公众号的消息包含如下几个重要字段:

ToUserName:公众号

FromUserName:用户号

MsgType:标记是消息类型,Text即为文本消息

Content:消息内容

实现你说我学这个功能时,公众号回复用户的消息中,只需要将ToUserName和FromUserName倒过来,MsgType和Content原封不动的发送给用户即可。

1、服务器上修改handle.py文件

# -*- coding: utf-8 -*-
# filename: handle.py

import hashlib
import web
import lxml
import time
import os
import reply
import receive

class Handle(object):

    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 = "xxx" #你的暗号

            list = [token, timestamp, nonce]
            list.sort()
            sha1 = hashlib.sha1()
            map(sha1.update, list)
            hashcode = sha1.hexdigest()
            print "handle/GET func: hashcode, signature: ", hashcode, signature
            if hashcode == signature:
                return echostr
            else:
                return ""
        except Exception, Argument:
            return Argument

    def POST(self):
        try:
            webData = web.data()
            print "Handle Post webdata is ", webData
            recMsg = receive.parse_xml(webData)
            if isinstance(recMsg, receive.Msg) and recMsg.MsgType == 'text':
                toUser = recMsg.FromUserName 
                fromUser = recMsg.ToUserName
                content = recMsg.content
                replyMsg = reply.TextMsg(toUser, fromUser, content)
                return replyMsg.send()
            else:
                print "暂且不处理"
                return "success"
        except Exception, Argment:
            return Argment

2、写入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)

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.encode("utf-8")

class ImageMsg(Msg):
    def __init__(self, xmlData):
        Msg.__init__(self, xmlData)
        self.PicUrl = xmlData.find('PicUrl').text
        self.MediaId = xmlData.find('MediaId').text

3、写入reply.py文件

import time
class Msg(object):
    def __init__(self):
        pass
    def send(self):
        return "success"

class TextMsg(Msg):
    def __init__(self, toUserName, fromUserName, content):
        self.__dict = dict()
        self.__dict['ToUserName'] = toUserName
        self.__dict['FromUserName'] = fromUserName
        self.__dict['CreateTime'] = int(time.time())
        self.__dict['Content'] = content
    def send(self):
        XmlForm = """
        <xml>
        <ToUserName><![CDATA[{ToUserName}]]></ToUserName>
        <FromUserName><![CDATA[{FromUserName}]]></FromUserName>
        <CreateTime>{CreateTime}</CreateTime>
        <MsgType><![CDATA[text]]></MsgType>
        <Content><![CDATA[{Content}]]></Content>
        </xml>
        """
        return XmlForm.format(**self.__dict)

class ImageMsg(Msg):
    def __init__(self, toUserName, fromUserName, mediaId):
        self.__dict = dict()
        self.__dict['ToUserName'] = toUserName
        self.__dict['FromUserName'] = fromUserName
        self.__dict['CreateTime'] = int(time.time())
        self.__dict['MediaId'] = mediaId
    def send(self):
        XmlForm = """
        <xml>
        <ToUserName><![CDATA[{ToUserName}]]></ToUserName>
        <FromUserName><![CDATA[{FromUserName}]]></FromUserName>
        <CreateTime>{CreateTime}</CreateTime>
        <MsgType><![CDATA[image]]></MsgType>
        <Image>
        <MediaId><![CDATA[{MediaId}]]></MediaId>
        </Image>
        </xml>
        """
        return XmlForm.format(**self.__dict)

4、重新运行python main.py 80,现在可以再公众号上实验这个小程序了。

五、后台运行

如果关闭了服务器的控制台,main.py文件不再运行,公众号就不具备回复用户消息的功能了,所以要在服务器中设置永久运行main.py。

这里介绍的方法是使用supervisor管理进程。

1、输入pwd查看当前目录,并记下来。

2、依次输入以下命令,安装supervisor,并生成配置文件:

pip install supervisor
echo_supervisord_conf > /etc/supervisord.conf

3、找到并修改etc/supervisord.conf文件

cd etc/
vim supervisord.conf

在该文件的最后加上

[program:myProgram]

command=python /root/main.py 80

autostart=true

stdout_logfile=/home/main.log

第一行的myProgram自己取个名字,表示你的项目就行

第二行的python /root/main.py 80表示你运行程序的命令

第三行表示自动启动,如果值为false则表示不自动启动

最后一行表示程序打印出的信息都记录在该main.log文件内,是日志文件

4、执行该配置

sudo supervisord

此时即使你关闭控制台,main.py文件也在运行了。

赞(3) 打赏
未经允许不得转载:老九IT技术网 » 微信公众号开发 腾讯云 Python

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

老九为IT技术人提供最全面的IT资讯和交流互动

欢迎投稿广告合作

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏