做公众平台应用开发,真正的开发开始之前、要有三个准备:
- 搭建一个自己的服务器(也就是第三方的服务器),这是你实现功能的地方
- 注册一个微信开放平台的账号,用来管理你的应用
- 并在此申请一个公众号(或免费的测试号),就是最后的作品啦
第一步,注册微信开放平台的账号
微信开放平台: https://open.weixin.qq.com/
第二步,绑定一个测试号
因为绑定公众号需要资质认证,资质认证需要交钱,所以就先绑定测试账号玩玩了。
- 入口在 “ 管理中心 >> 公众号开发 >> 绑定测试号 ”
这一步需要appID和secret来绑定这个账号、而你现在还没有appID。那就先点击右边的链接、去获取appID。
填写并验证第三方服务器信息,获取appID
appID用来唯一标识一个第三方的服务器。这个appID是在公众平台验证了你的服务器地址有效之后,生成出来给你的。
在这一步,需要提供你的服务器的url和token,token随意填写、代表公众平台的身份。随后,公众平台会发送一个消息、并带上这个token去验证这个url。
右边的链接中,具体描述了验证过程。总之我在我的http://2.wangxiaokuai.applinzi.com/weixin 处理函数中实现了这样一段代码:
from cgi import parse_qs
# test url: http://2.wangxiaokuai.applinzi.com/weixin?echostr=hellowangxiaokuai
def weixinHandler(environ, start_response):
query_dict = parse_qs(environ["QUERY_STRING"])
# get the echostr and return
echostr = query_dict.get("echostr", [""]).pop(0)
status = '200 OK'
response_headers = [('Content-type','text/plain')]
response_headers.append(("Access-Control-Allow-Origin", "*"))
start_response(status, response_headers)
return echostr
它只做了一件事情:解析请求的query_string,并把其中echostr的值、在响应消息体中返回。
用appID绑定公众号(测试号)
回到上一页,填好提交就绑定好了。现在,这个测试号就跟你的第三方服务绑定在一起了。
第三步,关注我的公众号
通过开放平台生成的二维码关注这个公众号(测试号),现在我就变成它唯一的订阅者了。然后就开始测试~
### 第四步,获取access_token
第三方服务器向公众平台发送请求时,要用access_token来表明身份。这个access_token是用appID、并调用公众平台提供的restful接口来获取到的。每个access_token有效期为2小时,这就需要服务器定时获取新的token并缓存起来。而任何地方需要用token、就去这个缓存中取。
获取token并缓存到数据库
第一段代码调用Restful接口获取access_token,并写到KV数据库中。同时把返回的expire_in、也就是token过期时间记录下来。
# get token from remote and update into KVDB
def updateToken(self):
params = {
"grant_type": "client_credential",
"appid": APP_ID,
"secret": APP_SECRET
}
# response is like:{"access_token":"ACCESS_TOKEN","expires_in":7200}
r = requests.get(WX_TOKEN_URL, params=params)
if r.status_code == 200:
data = r.json()
access_token = data.get("access_token")
expires_in = data.get("expires_in")
global EXPIRES_IN
EXPIRES_IN = expires_in
self.kv_client.set("access_token", access_token)
self.kv_client.set("access_token_updated_at", time.time())
return access_token
第二段代码先判断token有没有过期,如果过期了就调一下更新接口,然后返回token。这个接口就是提供给其他服务用的。
def getToken(self):
updated_at = self.kv_client.get("access_token_updated_at")
if not updated_at or time.time() - updated_at >= EXPIRES_IN:
self.updateToken()
return self.kv_client.get("access_token")
我知道以后看到这几行代码会想吐、我知道我应该起一个独立的定时器去刷新token,让这里的逻辑保持干净。但我试了threading.timer会让服务挂死,SAE提供的Cron定时任务服务配置不生效。。。。只好退了两步,改成在每次调用时、判断是否过期。。。呃
### 第五步,创建自定义菜单
菜单创建的命令格式:
POST(请使用https协议) [https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN](https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN)
具体可参考开发者文档,非常详细。
这里用到了刚才保存的token。
def create(self):
print "Hey, I am going to create a menu!"
# request
token = TokenServer().getToken()
params = {"access_token": token}
data = json.dumps(MENU_BODY, ensure_ascii=False)
print data
r = requests.post(const.WX_MENU_URL, data=data, params=params)
print params
print data
# response
status_code = r.status_code
resp_data = r.json()
if status_code != 200 or resp_data.get("errcode") != 0:
pass
print "Finish creating the menu, %s, %s" % (status_code, resp_data)
其中的body体定义:
MENU_BODY = {
"button":[
{
"type":"click",
"name": "买入",
"key":"BUY_IN"
},
{
"name":"查收益",
"sub_button":[
{
"type":"view",
"name":"昨日收益",
"url":"http://www.soso.com/"
},
{
"type":"view",
"name":"本周收益",
"url":"http://v.qq.com/"
}]
},
{
"type": "click",
"name": "卖出",
"key": "SELL_OUT"
}]
}
这个创建菜单的动作要服务器主动触发、而不是写在任何响应Handler里。想来想去,我把它的调用放在了这里:
Menu().create()
print "server is running!"
application = sae.create_wsgi_app(simple_app)
哈哈,在起wsgi server之前就创建!然后到我的手机上看一下 —— Bingo!
现在想想三者的关系:
第三方服务和公众号绑定,并通过公众平台进行通信、而不是直接通信。公众平台为第三方服务提供API、用于对公众号的各种操作、比如定义菜单、推送消息啥的。
所以,公众平台就是横在两者之间的平台,一边规范了应用的形式,一边规范了开发者的开发方式。我猜是这样吧……