微信公众号开发
入门指引
微信公众平台教程:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1472017492_58YV5
教程2:http://cj.fangguagua.com/bak/wd/17/2d4265491f12608cd170a95559800f2d.html
知乎文章:https://zhuanlan.zhihu.com/p/35047444
Linux云服务器使用官方教程:https://cloud.tencent.com/document/product/213/2936
安装 Windows 远程登录软件PuTTy:https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
python官方文档:https://docs.python.org/2/
申请服务器
我购买的是腾讯云搭载Centos7.5操作系统的服务器
使用远程登录软件PuTTY,计算机密码登录,参考云服务教程
搭建服务
以web.py网络框,python,腾讯云服务器为例介绍
1)安装软件
Centos7安装python3方法:(腾讯云里面的默认安装版本为python2,即使得python3与python2并存)。
参考:https://www.cnblogs.com/FZfangzheng/p/7588944.html
安装结果测试
安装web.p
安装libxml2, libxslt, lxml python
(如果没有pip )
Centos7下使用yum安装pip(如果当前用户不具有root权限,加上sudo):
yum -y install epel-release
yum -y install python-pip
yum clean all
pip install web.py
yum install libxml2
yum install libxslt
pip install lxml
2)测试服务器
Linux常用命令大全:https://www.cnblogs.com/yjd_hycf_space/p/7730690.html
vim常用命令使用:https://www.cnblogs.com/yangjig/p/6014198.html
创建文件夹wood放代码:mkdir wood
查看文件目录:ls
进入文件夹wood: cd /wood
进入编辑模式:i
写完代码退出编辑模式:Esc
保存文件并退出vim: :wq
main.cpp代码:
# -*- 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 出现下图界面:
申请公众号
微信公众平台上
开发者基本配置
参考开发文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1472017492_58YV5
url:
http://云服务器公网IP/wx
Token:自主设置,这个token与公众平台wiki中常提的access_token不是一回事。这个token只用于验证开发者服务器。
EndcodingASEKey:消息加密密钥,为方便入门 明文模式
服务器还不知道暗号,要给服务器也配置一下。ctrl+z退出上次运行。
1、修改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()
流程图:
代码:
# -*- 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 = "xxxx" #请按照公众平台官网\基本配置中信息填写
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
重新启动成功后(python main.py 80),点击提交按钮。若提示”token验证失败”, 请认真检查代码或网络链接等。若token验证成功,会自动返回基本配置的主页面,点击启动按钮。
注意这里可能因为之前启动的main.py占用80端口而启动失败,杀了占用端口的进程,再重新运行main.py。
netstat -tunlp |grep 80 #查询端口
kill -9 22248 #kill
我的公众号
你说我学
1.接受文本消息
wiki:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140543
粉丝给公众号发送文本消息:“欢迎开启公众号开发者模式”,在开发者后台,收到公众平台发送的xml 如下:(下文均隐藏了ToUserName 及 FromUserName 信息):
<xml>
<ToUserName><![CDATA[公众号]]></ToUserName>
<FromUserName><![CDATA[粉丝号]]></FromUserName>
<CreateTime>1460537339</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[欢迎开启公众号开发者模式]]></Content>
<MsgId>6272960105994287618</MsgId>
</xml>
and 图片消息,语音消息,视频消息,小视频消息,地理位置消息,链接消息
2.被动回复消息
wiki:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140543
1) 被动回复消息,即发送被动响应消息,不同于客服消息接口
2) 它其实并不是一种接口,而是对微信服务器发过来消息的一次回复
3) 收到粉丝消息后不想或者不能5秒内回复时,需回复“success”字符串(下文详细介绍)
4) 客服接口在满足一定条件下随时调用
公众号想回复给粉丝一条文本消息,内容为“test”, 那么开发者发送给公众平台后台的xml 内容如下:
<xml>
<ToUserName><![CDATA[粉丝号]]></ToUserName>
<FromUserName><![CDATA[公众号]]></FromUserName>
<CreateTime>1460541339</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[test]]></Content>
</xml>
1)ToUserName(接受者)、FromUserName(发送者) 字段请实际填写。
2)createtime 只用于标记开发者回复消息的时间,微信后台发送此消息都是不受这个字段约束。
3)text : 用于标记 此次行为是发送文本消息 (当然可以是image/voice等类型)。
4)文本换行 ‘\n’。
3.回复success文档
查询官方wiki 开头强调: 假如服务器无法保证在五秒内处理回复,则必须回复“success”或者“”(空串),否则微信后台会发起三次重试。
4.流程图
5.代码
# -*- coding: utf-8 -*-
# filename: handle.py
import hashlib
import reply
import receive
import web
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 = "980202" #请按照公众平台官网\基本配置中信息填写
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
写入receive.py文件
#-*-coding: utf-8 -*-
#filename: receive.py
import xml.etree.ElementTree as ET
def parse_xml(web_data):
if len(web_data) == 0:
return None
#公众平台发送的xml
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)
#分析提取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
#文本消息再加content
#如果是图片消息,除了继承以上的数据包结构外还有
#PicUrl:图片链接(由系统生成)
#Mediald:图片消息媒体id,可以调用多媒体文件下载接口拉取数据
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.PicUrl = xmlData.find('MediaTd').text
写入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['ToUsrName'] = toUserName
self.__dict['FromUserName'] = fromUserName
self.__dict['CreateTime'] = int(time.time())
self.__dict['Content'] = content
def send(self):
XmlFrom = """
<xml>
<ToUserName><![CDATA[{ToUserName}]]></ToUserName>
<FromUserName><![CDATA[{FromUserName}]]></FromUserName>
<CreateTime>{CreateTime}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[{Content}]]></Content>
</xml>
"""
return XmlFrom.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)
运行:python main.py 80
结果:
使用supervisor管理进程未成功
方法2:
nohup python main.py &
终于ok了,辣鸡
再实现图片,语音回复功能(参考文档)。
pycharm配置微信公众号开发环境
python2&python3兼容并切换使用详解
博客:
https://www.cnblogs.com/shabbylee/p/6792555.html
windows上如何安装libxml2,libxlst
下载Python包地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/
(11.16)