微信公众平台开发(免费云BAE+高效优雅的Python+网站开放的API)
虽然校园App是个我认为的绝对的好主意,但最近有个也不错的营销+开发的模式出现:微信平台+固定域名服务器。
微信公众平台的运行模式不外两个:
一、机器人模式或称转发模式,将说话内容转发到服务器上完成,拿服务器的回复再一次转发,就完成一次问答谈话。
二、人控模式,一个自然人登陆公众平台上,能直接接触到所有关注者,与之交互,这一定也是最累的。
微信公众平台若是服务号,用来做微网站,省去了登录认证过程。但说白了就是微信定制版的微网站。这我一学期后才搞懂,如果早些弄懂就不会做那么多无用功。
微信公众平台须有正面头像+身份证的照片来实名认证,非常严格。顺便一说,微信公众平台官方说法是偏支持大企而非个人。
服务器(准确的说只是一个引擎)有新浪云SAE,百度云BAE,阿里云AAE。
SAE最早,但使用云豆消费,注册只送500个。到现在,BAE允许创建10个应用而不用实名认证,SAE是需实名认证的。还有BAE比SAE强的就是支持git,虽然两者都支持svn,非常合时,刚好我学习git中,我果断选择BAE。云上建的每个应用可有20个版本,但任一个版都可以并且唯一上线。AAE(阿里云)一直不支持python,很让人失望。
第一阶段:入门——轻轻走过飘过。
下面是用数天时间借鉴前人成果Kingson的《一个用Python和Bottle实现基于微信公众平台API和SAE查询豆瓣电影的简单应用》开发的。
这个例子非常适合在用Python的开发人员。经过一番狠狠的折腾,我还弄懂了其它问题:云的概念、OAuth、token、微信API调用,网站API调用、python等,百度谷歌都会有答案。
还有很多像微信API通信认证(话说竞然用xml而不用json通信,不过这是取舍问题,无可厚非),python web框架,git对接云服务器……用了我许多时间。过程曲折复杂,看起来只是转移一下云平台,但实名认证,开发者域名的认证等浪费了我很多时间,因为没经验,很多各种问题都撞上了,尤其是我这种粗心大意,心眼碗粗的人,整个过程实在不算顺利,但我相信别人都会比我顺利,因为我连最低级的错都犯了。不多说,贴上关键代码代码。
下载地址:http://pan.baidu.com/s/1d1g3l
- #! /usr/bin/env python
- # coding=utf-8
- __author__ = 'jszhou'
- from bottle import *
- import hashlib
- import xml.etree.ElementTree as ET
- import urllib2
- # import requests
- import json
- app = Bottle()
- """
- Change Log:
- 03-04--03-08 完成微信API+Python自动回复代码雏形,可以通过电影ID查询电影信息,以Text形式返回给用户电影
- Title和电影summary
- # 03-11 完成通过电影名称查询并返回图文格式的数据
- # 03-13 1.增加给新关注的用户自动返回“欢迎关注豆瓣电影,输入电影名称即可快速查询电影讯息哦!”信息的功能
- 2.完善注释信息
- 关于本地调试问题:
- 微信没有提供本地调试功能,给用户造成不小的麻烦。
- 打开Bottle的Debug功能,在本地运行自己的代码(启动Server),使用Chrome或Firefox上的Advanced Rest Client插件来模拟微信服务器向自己的应用发送请求,
- 这样就可以看到详细的报错信息,方便开发者定位修复问题,其相当于,自己的应用是SAE,而Advanced Rest Client模拟的是新微信客户端和微信服务器。
- 也有同学自己写脚本,模拟微信服务器发送数据,这也是同样的道理。
- 遗留问题:
- 1.从豆瓣拿到的海报图片都是竖向的,而微信中显示的是横向的,所以在微信看图片就被裁了一节,不过还好能看,
- 如何能完整显示海报图片,有待进一步research;
- 2.现在的通过电影名称返回的结果,实际上是拿的豆瓣返回的第一条数据,这样就有可能不准确,如何精确匹配用户的
- 查询条件,也还需要进一步研究。
- """
- @app.get("/")
- def checkSignature():
- """
- 这里是用来做接口验证的,从微信Server请求的URL中拿到“signature”,“timestamp”,"nonce"和“echostr”,
- 然后再将token, timestamp, nonce三个排序并进行Sha1计算,并将计算结果和拿到的signature进行比较,
- 如果相等,就说明验证通过。
- 话说微信的这个验证做的很渣,因为只要把echostr返回去,就能通过验证,这也就造成我看到一个Blog中,
- 验证那儿只返回了一个echostr,而纳闷了半天。
- 附微信Server请求的Url示例:http://yoursaeappid.sinaapp.com//?signature=730e3111ed7303fef52513c8733b431a0f933c7c
- &echostr=5853059253416844429×tamp=1362713741&nonce=1362771581
- """
- token = "" # 你在微信公众平台上设置的TOKEN
- signature = request.GET.get('signature', None) # 拼写不对害死人那,把signature写成singnature,直接导致怎么也认证不成功
- timestamp = request.GET.get('timestamp', None)
- nonce = request.GET.get('nonce', None)
- echostr = request.GET.get('echostr', None)
- tmpList = [token, timestamp, nonce]
- tmpList.sort()
- tmpstr = "%s%s%s" % tuple(tmpList)
- hashstr = hashlib.sha1(tmpstr).hexdigest()
- if hashstr == signature:
- return echostr
- else:
- return "wws:indentify error"
- def parse_msg():
- """
- 这里是用来解析微信Server Post过来的XML数据的,取出各字段对应的值,以备后面的代码调用,也可用lxml等模块。
- """
- recvmsg = request.body.read() # 严重卡壳的地方,最后还是在Stack OverFlow上找到了答案
- root = ET.fromstring(recvmsg)
- msg = {}
- for child in root:
- msg[child.tag] = child.text
- return msg
- def query_movie_info():
- """
- 这里使用豆瓣的电影search API,通过关键字查询电影信息,这里的关键点是,一是关键字取XML中的Content值,
- 二是如果Content中存在汉字,就需要先转码,才能进行请求
- """
- movieurlbase = "http://api.douban.com/v2/movie/search"
- DOUBAN_APIKEY = "" # 这里需要填写你自己在豆瓣上申请的应用的APIKEY
- movieinfo = parse_msg()
- searchkeys = urllib2.quote(movieinfo["Content"].encode("utf-8")) # 如果Content中存在汉字,就需要先转码,才能进行请求
- url = '%s?q=%s&apikey=%s' % (movieurlbase, searchkeys, DOUBAN_APIKEY)
- # return "<p>{'url': %s}</p>" % url
- # url = '%s%s?apikey=%s' % (movieurlbase, id["Content"], DOUBAN_APIKEY)
- # resp = requests.get(url=url, headers=header)
- resp = urllib2.urlopen(url)
- movie = json.loads(resp.read())
- # return "<p>{'movie': %s}</p>" % movie
- # info = movie["subjects"][0]["title"] + movie["subjects"][0]["alt"]
- # info = movie['title'] + ': ' + ''.join(movie['summary'])
- return movie
- # return info
- def query_movie_details():
- """
- 这里使用豆瓣的电影subject API,通过在query_movie_info()中拿到的电影ID,来获取电影的summary。
- """
- movieurlbase = "http://api.douban.com/v2/movie/subject/"
- DOUBAN_APIKEY = "" # 这里需要填写你自己在豆瓣上申请的应用的APIKEY
- id = query_movie_info()
- url = '%s%s?apikey=%s' % (movieurlbase, id["subjects"][0]["id"], DOUBAN_APIKEY)
- resp = urllib2.urlopen(url)
- description = json.loads(resp.read())
- description = ''.join(description['summary'])
- return description
- @app.post("/")
- def response_msg():
- """
- 这里是响应微信Server的请求,并返回数据的主函数,判断Content内容,如果是“Hello2BizUser”,就
- 表明是一个新注册用户,调用纯文本格式返回,如果是其他的内容就组织数据以图文格式返回。
- 基本思路:
- # 拿到Post过来的数据
- # 分析数据(拿到FromUserName、ToUserName、CreateTime、MsgType和content)
- # 构造回复信息(将你组织好的content返回给用户)
- """
- #拿到并解析数据
- msg = parse_msg()
- #设置返回数据模板
- #纯文本格式
- textTpl = """<xml>
- <ToUserName><![CDATA[%s]]></ToUserName>
- <FromUserName><![CDATA[%s]]></FromUserName>
- <CreateTime>%s</CreateTime>
- <MsgType><![CDATA[%s]]></MsgType>
- <Content><![CDATA[%s]]></Content>
- <FuncFlag>0</FuncFlag>
- </xml>"""
- #图文格式
- pictextTpl = """<xml>
- <ToUserName><![CDATA[%s]]></ToUserName>
- <FromUserName><![CDATA[%s]]></FromUserName>
- <CreateTime>%s</CreateTime>
- <MsgType><![CDATA[news]]></MsgType>
- <ArticleCount>1</ArticleCount>
- <Articles>
- <item>
- <Title><![CDATA[%s]]></Title>
- <Description><![CDATA[%s]]></Description>
- <PicUrl><![CDATA[%s]]></PicUrl>
- <Url><![CDATA[%s]]></Url>
- </item>
- </Articles>
- <FuncFlag>1</FuncFlag>
- </xml> """
- #判断Content内容,如果等于"Hello2BizUser",表明是一个新关注用户,如果不是,就返回电影标题,电影简介
- #和电影海报组成的图文信息
- if msg["Content"] == "Hello2BizUser":
- echostr = textTpl % (
- msg['FromUserName'], msg['ToUserName'], str(int(time.time())), msg['MsgType'],
- u"欢迎关注豆瓣电影,输入电影名称即可快速查询电影讯息哦!")
- return echostr
- else:
- Content = query_movie_info()
- description = query_movie_details()
- echostr = pictextTpl % (msg['FromUserName'], msg['ToUserName'], str(int(time.time())),
- Content["subjects"][0]["title"], description,
- Content["subjects"][0]["images"]["large"], Content["subjects"][0]["alt"])
- return echostr
- if __name__ == "__main__":
- # Interactive mode
- debug(True)
- run(app,host='127.0.0.1', port=8080, reloader=True)
- else:
- # Mod WSGI launch
- # import sae
- # debug(True)
- # os.chdir(os.path.dirname(__file__))
- # app = default_app()
- # application = sae.create_wsgi_app(app)
- #################################################
- #os.chdir(os.path.dirname(__file__))#Forbidden to access
- from bae.core.wsgi import WSGIApplication
- application = WSGIApplication(app)
注:代码中用json.dumps会更好。 后注:此注不对。
深入阶段,将http://www.cnblogs.com/mchina/tag/%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97/里的功能用python实现之。
……
本代码需要与bottle.py一并上传到服务器空间。
微信开发调试小工具下载:http://www.cnblogs.com/linkbiz/archive/2013/05/16/3080306.html
附上一些特别信息:
本人微信公众号pythonwoodpub, 开发项目澳洲红酒微信服务号,
,
微信公众平台开发(免费云BAE+高效优雅的Python+网站开放的API)的更多相关文章
- 【原创】【2015最新】微信公众平台开发手把手入门之一:缘起微信公众号(PHP,MYSQL, BAE)
最近因为业务的需要,老板布置做了两个月简单的的微信公众平台开发,从网上搜了一些资料,实话说资料不多. 在参考学习的过程中也遇到了不少难缠的小问题,虽然不难逾越,但是确实浪费了时间. 我发现网上仅有不多 ...
- 第一篇:微信公众平台开发实战Java版之了解微信公众平台基础知识以及资料准备
相信很多人或多或少听说了微信公众平台的火热.但是开发还是有一点门槛,鉴于挺多朋友问我怎么开发,问多了,自己平时也进行以下总结.所以下面给大家分享一下我的经验: 微信公众号是什么? 官网的介绍:再小的个 ...
- PHP实现微信公众平台开发 全套视频资源下载
好久没有在博客园更新东西了,今天给大家分享一份比较不错的视频学习资源吧. 主要是关于PHP实现微信公众平台开发, 不知道大家对于微信平台的开发有多少了解,那么今天就从基础开始吧,资源目录如下(PS ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(四):Hello World
============= 以下写于2013-07-20 ============= 这一篇文章其实可以写在很前面,不过我还是希望开发者们尽多地了解清楚原理之后再下手. 通过上一篇Senparc.W ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(九):自定义菜单接口说明
上一篇<Senparc.Weixin.MP SDK 微信公众平台开发教程(八):通用接口说明>介绍了如何通过通用接口获取AccessToken,有了AccessToken,我们就可以来操作 ...
- 微信公众平台开发(26) ACCESS TOKEN
本文介绍微信公众平台下Access Token的概念及获取方法. 一.Access Token access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token.正常 ...
- 第九篇 :微信公众平台开发实战Java版之如何实现自定义分享内容
第一部分:微信JS-SDK介绍 微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包. 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统 ...
- 第四篇 :微信公众平台开发实战Java版之完成消息接受与相应以及消息的处理
温馨提示: 这篇文章是依赖前几篇的文章的. 第一篇:微信公众平台开发实战之了解微信公众平台基础知识以及资料准备 第二篇 :微信公众平台开发实战之开启开发者模式,接入微信公众平台开发 第三篇 :微信公众 ...
- 第二篇 :微信公众平台开发实战Java版之开启开发者模式,接入微信公众平台开发
第一部分:微信公众号对接的基本介绍 一.填写服务器配置信息的介绍 登录微信公众平台官网后,进入到公众平台后台管理页面. 选择 公众号基本设置->基本配置 ,点击“修改配置”按钮,填写服务器地址( ...
随机推荐
- maya 操作自我整理(二)
随身携带自己的maya习惯我们在一台电脑上设置好自己的使用习惯,包括自己定义的快捷键.标记菜单.界面颜色.工具架等信息,当换到另一个工作环境时再进行设置十分不便利,将自己的习惯随身带走有利于我们更快捷 ...
- Java正则表达式(1)
String类的三个内建正则表达式工具: 1.matches()方法 示例:检查一个句子是否以大写字母开头,以句号结尾 public static boolean checkFormat(String ...
- 《A First Course in Probability》-chaper7-期望的性质-期望的性质-协方差
在实际的问题中,我们往往想要通过已有的数据来分析判断两个事件的发生是否有相关性.当然一个角度去寻找这两个事件内在的逻辑关系,这个角度需要深究两个事件的本质,而另外一个角度就是概率论提供的简单方法:基于 ...
- Struct2 向Action中传递参数(中文乱码问题)
就是把视图上的值传递到Action定义的方法中 也就是把数据从前台传递到后台 三种方式: 1. 使用action属性接收参数 比如jsp页面: <body> 使用action属性接收参数 ...
- 洛谷 P1005 矩阵取数游戏
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...
- linux操作系统cron详解
Linux操作系统定时任务系统 Cron 入门 cron是一个linux下的定时执行工具,可以在无需人工干预的情况下运行作业.由于Cron 是Linux的内置服务,但它不自动起来,可以用以下的方法启动 ...
- html5之canvas困惑 在canvas标签内需要设置了宽跟高,如果在css中设置同样的宽跟高,画出来的图像变形了?
<canvas class="cvs"></canvas> 遇到的问题: 如css 中设.cvs{width:500px;height:400px;},也就 ...
- MST(Kruskal’s Minimum Spanning Tree Algorithm)
You may refer to the main idea of MST in graph theory. http://en.wikipedia.org/wiki/Minimum_spanning ...
- [RxJS] Filtering operators: takeUntil, takeWhile
take(), takeLast(), first(), last(), those opreators all take number or no param. takeUtil and takeW ...
- 学习Oracle应该准备的技能
首先数据库方面的技能:数据库体系结构.基本概念和基本理论.数据库管理.备份.恢复.SQL开发.PLSQL开发.工具的使用等等. 操作系统方面的技能:对Linux/Unix系统应该有相当的基础.理解RA ...