实践 | 微信公众平台开发 — 从0到实现自定义菜单

做公众平台应用开发,真正的开发开始之前、要有三个准备:

  • 搭建一个自己的服务器(也就是第三方的服务器),这是你实现功能的地方
  • 注册一个微信开放平台的账号,用来管理你的应用
  • 并在此申请一个公众号(或免费的测试号),就是最后的作品啦
实践 | 微信公众平台开发 — 从0到实现自定义菜单_第1张图片
Picture from unsplash.com

第一步,注册微信开放平台的账号

微信开放平台: https://open.weixin.qq.com/

第二步,绑定一个测试号

因为绑定公众号需要资质认证,资质认证需要交钱,所以就先绑定测试账号玩玩了。

  • 入口在 “ 管理中心 >> 公众号开发 >> 绑定测试号 ”
实践 | 微信公众平台开发 — 从0到实现自定义菜单_第2张图片
Paste_Image.png

这一步需要appID和secret来绑定这个账号、而你现在还没有appID。那就先点击右边的链接、去获取appID。

实践 | 微信公众平台开发 — 从0到实现自定义菜单_第3张图片
Paste_Image.png

填写并验证第三方服务器信息,获取appID

appID用来唯一标识一个第三方的服务器。这个appID是在公众平台验证了你的服务器地址有效之后,生成出来给你的。

在这一步,需要提供你的服务器的url和token,token随意填写、代表公众平台的身份。随后,公众平台会发送一个消息、并带上这个token去验证这个url。

实践 | 微信公众平台开发 — 从0到实现自定义菜单_第4张图片
Paste_Image.png

右边的链接中,具体描述了验证过程。总之我在我的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绑定公众号(测试号)

回到上一页,填好提交就绑定好了。现在,这个测试号就跟你的第三方服务绑定在一起了。

第三步,关注我的公众号

实践 | 微信公众平台开发 — 从0到实现自定义菜单_第5张图片
Paste_Image.png

通过开放平台生成的二维码关注这个公众号(测试号),现在我就变成它唯一的订阅者了。然后就开始测试~

实践 | 微信公众平台开发 — 从0到实现自定义菜单_第6张图片
Paste_Image.png

### 第四步,获取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!

实践 | 微信公众平台开发 — 从0到实现自定义菜单_第7张图片
Paste_Image.png

现在想想三者的关系:
第三方服务和公众号绑定,并通过公众平台进行通信、而不是直接通信。公众平台为第三方服务提供API、用于对公众号的各种操作、比如定义菜单、推送消息啥的。

所以,公众平台就是横在两者之间的平台,一边规范了应用的形式,一边规范了开发者的开发方式。我猜是这样吧……

你可能感兴趣的:(实践 | 微信公众平台开发 — 从0到实现自定义菜单)