Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save willwhui/fd511cee75153bc73d51f451f3d9e0a2 to your computer and use it in GitHub Desktop.
Save willwhui/fd511cee75153bc73d51f451f3d9e0a2 to your computer and use it in GitHub Desktop.
搭建api.ai webhook(在朋友google cloud搭建的vps上使用python+flask+jinja)
搭建api.ai webhook(在朋友google cloud搭建的vps上使用python+flask+jinja)
@willwhui
Copy link
Author

willwhui commented Jul 3, 2017

从Let's Encrypt获取并安装自己的ssl证书

按照Let‘s Encrypt官方的教程,通过certbot来创建。
操作倒也方便。

不知为何没有自动配置成功
按照这里的说明手动搞一下:

Certificate Files
After obtaining the cert, you will have the following PEM-encoded files:
cert.pem: Your domain's certificate
chain.pem: The Let's Encrypt chain certificate
fullchain.pem: cert.pem and chain.pem combined
privkey.pem: Your certificate's private key

Certbot creates symbolic links to the most recent certificate files in the 
/etc/letsencrypt/live/your_domain_name directory. 
Because the links will always point to the most recent certificate files, 
this is the path that you should use to refer to your certificate files.

因此手动修改nginx的https配置

ssl_certificate /etc/letsencrypt/live/mypals.today/fullchain.pem #注意不能用cert.pem,它不包含完整信息(公钥?),会导致SSL被python, api.ai判定为不可信,从而导致webhook不可用
ssl_certificate_key /etc/letsencrypt/live/mypals.today/privkey.pem

其他方法(没试过):
pythonprogramming.net提到的教程

@willwhui
Copy link
Author

willwhui commented Jul 3, 2017

webhook错误206排除

绑定域名,设定了ssl之后,api.ai依然返回错误:
"status": {
"code": 206,
"errorType": "partial_content",
"errorDetails": "Webhook call failed. Error: Webhook response was empty."
},
服务器返回json的函数依然没有被调用到。

尝试在python3命令行中进行如下操作:

>>> import requests
>>> r = requests.get('https://mydomainname/webhook')

失败:requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:600)

>>> import requests
>>> r = requests.get('http://mydomainname/webhook')
>>> print(r)
<Response [200]>

成功。

说明ssl有问题。

经过一番查找,发现这里(stackoverflow)的答案:
在nginx的配置中,必须使用“fullchan.pem”
ssl_certificate /etc/letsencrypt/live/mydomainname/fullchain.pem;

重启nginx之后,在python命令行中运行requests.get成功。

@willwhui
Copy link
Author

willwhui commented Jul 4, 2017

根据api.ai Action返回不同的结果

这里有简单示例
根据action来判断应该执行何种动作

@willwhui
Copy link
Author

willwhui commented Jul 4, 2017

让Google Home播放mp3文件

参见stackoverflow

var msg = `
  <speak>
    Tone one
    <audio src="https://examaple.com/wav/Dtmf-1.wav"></audio>
    Tone two
    <audio src="https://example.com/wav16/Dtmf-2.wav"></audio>
    Foghorn
    <audio src="https://example.com/mp3/foghorn.mp3"></audio>
    Done
  </speak>
  `;

  var reply = {
    speech: msg,
    data:{
      google:{
        "expect_user_response": true,
        "is_ssml": true
      }
    }
  };

  res.send( reply );

以上js代码的关键点在于:

  • api.ai的webhook返回字段的“speech"部分用msg来填充
  • 增加data字段
  • msg要符合google home要求的"SSML"规范
    参见google的文档:Format of response from the webhook
    根据SSML规范,speak字段中可以返回文本和mp3文件链接的混合物。

@willwhui
Copy link
Author

willwhui commented Jul 5, 2017

在flask中使用静态文件返回指向mp3的json

参见这里
只需要在template同级目录建立static目录就可以直接输入完整网址访问此目录下的所有文件

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment