微信公众号开发填坑
# 基础知识填坑
一、注册完小程序后,想开发订阅号,仍需进行订阅号注册,并且需绑定不同邮箱。一个邮箱只能绑定一个服务。
二、个人订阅号每天只能发布一次内容,不过一次最多可以发8篇文章
# 高级开发填坑
一、私有云接收用户消息并回复
- Token认证:公众号-基本配置-Token,这里的Token和access_token没有任何关系,这里的Token自己随便填
- 官方demo中
urls = (
'/wx', 'Handle',
)
应该改为
urls = (
'/', 'Handle',
)
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 ""
哈希部分计算有问题,不用管什么问题了,直接改成下面,因为平台最终能拿到它发出的消息,就算成功,我们这里就简单粗暴原样返回。
token = "sdfsaf"
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
- Token 认证成功后,就可以接收用户的消息,并自行回复了,下面是完整代码:
main.py
# -*- coding: utf-8 -*-
# filename: main.py
import web
from handle import Handle
urls = (
'/', 'Handle',
)
if __name__ == '__main__':
app = web.application(urls, globals())
app.run()
handle.py
# -*- coding: utf-8 -*-
# filename: handle.py
import hashlib
import web
import receive
import time
import os
import reply
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 = "sdfsaf"
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)
#打印消息体日志
recMsg = receive.parse_xml(webData)
if isinstance(recMsg, receive.Msg) and recMsg.MsgType == 'text':
toUser = recMsg.FromUserName
fromUser = recMsg.ToUserName
content = str(recMsg.Content)
print('Reply message info:\n')
print('toUser =', toUser)
print('fromUser = ', fromUser)
print('content = ', content)
replyMsg = reply.TextMsg(toUser, fromUser, content)
return replyMsg.send()
#return "success"
#return self.render.reply_text(toUser, fromUser, int(time.time()), content)
else:
print("不支持的消息类型:",recMsg.MsgType)
return "success"
except (Exception) as 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
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
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)
运行结果:
[root@VM_0_14_centos weixin2]# python3 main.py 80
http://0.0.0.0:80/
handle/GET func: hashcode, signature: 80cff3a11f705dbfd4d13544938e8f0604e15713 80cff3a11f705dbfd4d13544938e8f0604e15713
121.51.66.120:26665 - - [05/Mar/2020 23:42:23] "HTTP/1.1 GET /" - 200 OK
218.90.129.90:5470 - - [05/Mar/2020 23:42:24] "HTTP/1.1 GET /livereload" - 404 Not Found
Handle Post webdata is:
b'<xml><ToUserName><![CDATA[gh_10cbc87900a0]]></ToUserName>\n<FromUserName><![CDATA[oTK-mwSbfgfFvLW55TkFabanv5EY]]></FromUserName>\n<CreateTime>1583422953</CreateTime>\n<MsgType><![CDATA[text]]></MsgType>\n<Content><![CDATA[\xe6\xb5\x8b\xe8\xaf\x95]]></Content>\n<MsgId>22669168083602861</MsgId>\n</xml>'
Reply message info:
toUser = oTK-mwSbfgfFvLW55TkFabanv5EY
fromUser = gh_10cbc87900a0
content = 测试
121.51.66.16:10414 - - [05/Mar/2020 23:42:33] "HTTP/1.1 POST /" - 200 OK
Handle Post webdata is:
b'<xml><ToUserName><![CDATA[gh_10cbc87900a0]]></ToUserName>\n<FromUserName><![CDATA[oTK-mwSbfgfFvLW55TkFabanv5EY]]></FromUserName>\n<CreateTime>1583422958</CreateTime>\n<MsgType><![CDATA[text]]></MsgType>\n<Content><![CDATA[\xe4\xbd\xa0\xe5\xa5\xbd]]></Content>\n<MsgId>22669167649346895</MsgId>\n</xml>'
Reply message info:
toUser = oTK-mwSbfgfFvLW55TkFabanv5EY
fromUser = gh_10cbc87900a0
content = 你好
121.51.66.16:10415 - - [05/Mar/2020 23:42:38] "HTTP/1.1 POST /" - 200 OK