Python微信公众号开发

内容转载自我自己的博客
代码已上传Github仓库 https://github.com/zfb132/wechatPlatform

准备工作

首先,申请一个属于自己的微信公众号(必须保证全局管理员是自己的微信账户,否则会很麻烦),还要拥有自己的服务器(Ubuntu 系统)来部署代码,且服务器已经成功安装了网络相关的两个常用软件 uwsgi 和 nginx ,前者一般用于进程控制,后者用于反向代理。

服务器端部署流程

第一步,在 Ubuntu 系统安装 venv :
sudo apt-get install python3-venv
第二步,创建 Python3 的虚拟环境:
python3 -m venv myvenv
注意source myvenv/bin/activate表示激活虚拟环境,deactivate退出虚拟环境
第三步,在虚拟环境中升级pip:
pip install --upgrade pip
然后安装requirements.txt文件内的模块:
pip install -r requirements.txt
第四步:主代码的编写,主要有两种方法:
一种方法,直接下载我已经写好的代码运行即可:
git clone git@github.com:zfb132/wechatPlatform.git
另一种方法,自己逐个创建代码,创建所有代码后的目录文件结构如下:

wechatPlatform/
wechatPlatform/app/
wechatPlatform/app/__init__.py
wechatPlatform/app/config.py
wechatPlatform/app/controller/
wechatPlatform/app/controller/main.py
wechatPlatform/log.py
wechatPlatform/requirements.txt
wechatPlatform/runserver.py

各<a href="#1">文件内容</a>附在文章的最后。其中,要把config.example.py文件重命名为config.py,然后把里面的token改成自己的
第五步,编辑nginx.conf文件:
sudo vi /etc/nginx/nginx.conf
在合适位置添加以下内容:

    server{
        listen 80;
        server_name xxxx.whuzfb.cn;
        access_log /home/ubuntu/wechatPlatform/log/access.log;
        error_log /home/ubuntu/wechatPlatform/log/error.log;
        location /{
            include uwsgi_params;
            uwsgi_pass 127.0.0.1:8111;
            proxy_pass http://127.0.0.1:8111/;
        }
    }

然后再重启 nginx 服务:
service nginx restart
最后启动本代码在后台运行:
uwsgi uwsgi_wechat.ini -d ./server.log
至此,服务器端的代码已经全部编写并部署完成
注意:在启动uwsgi后会生成四个进程监听8111端口,如果想要杀死他们,先查看占用8111端口的所有进程的ID(不能直接关闭uwsgi,这可能会影响到其他项目),终端输入lsof -i:8111命令即可查看,然后使用kill -9 id依次杀死各个进程;这种方法比较麻烦,另一种快速的方法是:
kill -9 $(lsof -t -i:8111)
此命令可一步到位杀死所有占用8111端口的进程

微信平台网页端配置

浏览器打开微信公众平台登录自己的管理员账户,点击开发栏目,选择基本配置,根据网页提示填写这三个内容(一般选择明文模式):

网页端配置

需要注意的是,一定要先在服务器端把代码运行起来,这样才能成功保存网页端的配置

附录<a name="1" />

log.py文件内容:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import logging
from logging.handlers import RotatingFileHandler

LOG_FORMAT = "%(asctime)s [%(funcName)s: %(filename)s,%(lineno)d] - %(levelname)s : %(message)s"
DATE_FORMAT = "%m/%d/%Y %H:%M:%S"
LOG_PATH = "./log/"

# 初始化日志文件配置
def initLog(fileName,logger):
    # 创建日志文件夹
    if not os.path.exists(LOG_PATH):
        os.mkdir(LOG_PATH)
    myapp = logging.getLogger(logger)
    myapp.setLevel(logging.DEBUG)
    # 切割日志文件
    handler = RotatingFileHandler(LOG_PATH+fileName, maxBytes=128*1024,backupCount=60)
    handler.setFormatter(logging.Formatter(LOG_FORMAT,DATE_FORMAT))
    myapp.addHandler(handler)
    return myapp

runserver.py文件内容:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from app import app
from log import initLog
logging = initLog('wechat.log','runserver')
if __name__ == '__main__':
    app.run(debug=True,port=8111)
application = app

config.py文件内容:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
DEFAULTMESSAGE = "你好,消息已收到"
token = "mytoken"

__init__.py文件内容:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask
import logging
import os

app = Flask(__name__)
app.secret_key = "thisissecretkey"

from app.controller.main import *

main.py文件内容:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from app import app
from flask import request
import app.config as config
import logging

from wechatpy.utils import check_signature
from wechatpy.exceptions import InvalidSignatureException
from wechatpy import parse_message
from wechatpy.replies import TextReply
from wechatpy.replies import ImageReply

logging = logging.getLogger('runserver.main')

def handlemsg(data):
    msg = parse_message(data)
    print(msg)
    logging.debug('handle msg:'.format(msg))
    xml = txtreply(msg,msg.content)
    return xml

# 微信消息接口
@app.route('/',methods=["POST","GET"])
def main():
    logging.debug('进入主页面')
    try:
        signature = request.args.get("signature", "")
        timestamp = request.args.get("timestamp", "")
        nonce = request.args.get("nonce", "")
        echostr = request.args.get("echostr", "")
        # echostr是微信用来验证服务器的参数,需原样返回
        if echostr:
            try:
                logging.debug('正在验证服务器签名')
                check_signature(config.token, signature, timestamp, nonce)
                logging.debug('验证签名成功')
                return echostr
            except InvalidSignatureException as e:
                logging.error('检查签名出错: '.format(e))
                return 'Check Error'
        # 也可以通过POST与GET来区别
        # 不是在进行服务器验证,而是正常提交用户数据
        logging.debug('开始处理用户消息')
        xml = handlemsg(request.data)
        return xml
    # 处理异常情况或忽略
    except Exception as e:
        logging.error('获取参数失败: '.format(e))

def imgreply(msg,id):
    reply = ImageReply(message=msg)
    reply.media_id = id
    xml = reply.render()
    return xml

def txtreply(msg,txt):
    reply = TextReply(content=txt, message=msg)
    xml = reply.render()
    return xml

uwsgi_wechat.ini文件内容:

[uwsgi]
# http协议对客户端开发的端口号
http = 0.0.0.0:8111
# 应用目录,即python代码所在目录
pythonpath = ./
# web 应用python主程序
wsgi-file = ./runserver.py
# 一般在主运行程序里指定 app = Flask(__name__)
callable = app
# 工作进程数
processes = 4
# 线程数
threads = 2
# 指定日志文件
demonize = ./server.log
# python 虚拟环境目录
home = ./myvenv

后记

虽然目前这个代码只是把用户发来的消息再原封不动的返回给用户,看起来好像折腾了半天并没有实现啥有趣的功能,但是它最少实现了解析用户发来的消息以及返回给用户文字消息的功能,这已经足够了。消息处理的逻辑可以自己继续慢慢完善,比如接入图灵机器人等有趣功能

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 54,299评论 1 121
  • 1. 周嘉洛拥有一个不好说有没有用的异能。 异能管理局的人给他的异能起名为「前方高能预警」。 2. 周嘉洛第一次发...
    沈念sama阅读 26,538评论 2 115
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 15,035评论 1 103
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 11,273评论 0 59
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 9,149评论 0 54
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 13,435评论 0 103
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 12,173评论 0 58
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 5,435评论 2 128
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 5,008评论 0 36
  • 想象着我的养父在大火中拼命挣扎,窒息,最后皮肤化为焦炭。我心中就已经是抑制不住地欢快,这就叫做以其人之道,还治其人...
    爱写小说的胖达阅读 2,983评论 1 71
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 6,258评论 0 95
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 5,823评论 1 97
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 6,251评论 0 84
  • 白月光回国,霸总把我这个替身辞退。还一脸阴沉的警告我。[不要出现在思思面前, 不然我有一百种方法让你生不如死。]我...
    爱写小说的胖达阅读 1,798评论 0 10
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 4,533评论 2 86
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 6,538评论 3 84
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 3,902评论 0 1
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 3,714评论 0 33
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 6,796评论 2 98
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 7,764评论 1 106

推荐阅读更多精彩内容