微信公众号开发

微信公众账号开发

话说2013年的最后几分钟和2014的最开始几分钟我都是献给这货的.BTW,纯属个人折腾

人生苦短,我爱python

至于做的具体东西就在此略过了,以下是截图.主要是分享开发过程中的经验,我的代码是部署在自己的VPS上面

现在注册一个微信的服务号的成本很高了,一次人工审批不过的话就需要300元, 我用的是微信公众平台测试号.只要填写手机号和验证码。其限制条件是,只能有20个订阅粉丝.没关系,我要的是调通整个通讯以及业务化定制.

#####注册
会给你一个 APPID, APPSeceret,这个步骤需要你填写自己 Server 的 URL,以及填写 TOKEN,这些是未来完成通讯的许可证明

#####微信认证
Server 端应该对每个请求进行验证,确认是来自微信服务器的请求才做出相应

加密/校验流程如下:

  • tokentimestampnonce 三个参数进行字典序排序
  • 将三个参数字符串拼接成一个字符串进行sha1加密
  • 开发者获得加密后的字符串可与 signature 对比,标识该请求来源于微信
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class BaseHandler(tornado.web.RequestHandler):
#基类,实现基本认证,子类只需要继承就可以完成微信认证
def prepare(self):
timestamp = self.get_argument("timestamp", None)
nonce = self.get_argument("nonce", None)
signature = self.get_argument("signature", None)
print 'request:', timestamp, nonce, signature
print self.request.method, timestamp, nonce, signature
if validate(timestamp, nonce, signature) is False:
print "=========validate failed ====="
self.finish()

def validate(timestamp, nonce, signature):
print 'validate:', timestamp, nonce, signature
if timestamp is None or nonce is None or signature is None:
return False
tmp = [TOKEN, timestamp, nonce]
tmp = sorted(tmparr)
tmpStr = ''.join(tmp)
hashStr = sha1(tmpStr).hexdigest()
return (hashStr == signature)

验证成功之后,才能进入业务逻辑,当我们在微信公众号填写自己服务的URL的时候,weixin会向该URL发起Get请求.做为首次验证,根据文档,需要将接收到的字符串原文返回

1
2
3
4
class serverHandler(BaseHandler):
def get(self):
echostr = self.get_argument('echostr', None)
self.write(echostr)

#####. 菜单订制
为了支持微信通信过程中不允许使用”/u” 字符编码,这里用到了tornado的render_string,一开始我是直接生成一个json.dump(menu)然后post过去,但一直存在编码问题, 使用render_string就解决了。感谢@ihao提醒

1
2
3
4
class UIHandler(tornado.web.RequestHandler):
def get(self):
msg = self.render_string('menu.json')
createMenu(menu)

#####. 响应用户按键输入

1
2
3
4
5
6
7
8
9
10
11
12
xml = uni(self.request.body)        #获取微信服务器发送过来的xml,转化为unicode
dic = xml2dict(xml) #将xml解析成dict
if dic['MsgType'].lower() == 'event':
event = dic['Event'].lower()
if event == 'subscribe':
ctx = do_subscribe(dic) #订阅逻辑
msg = self.render_string('text_resp.xml', dic=ctx)
self.write(msg)
elif event == 'click':
ctx = do_click(dic) #点击逻辑
msg = self.render_string('text_resp.xml', dic=ctx)
self.write(msg)

self.write(msg)是将要发给用户的信息返回给微信服务器,之后微信服务器会将信息发送给用户

相关链接

开发中用到的库

  • tornado
  • virtualenv
  • pyquery(做爬虫)
  • pymongo
  • lxml
  • urllib2