语音回执消息---Python

当您使用语音的API接口发送外呼后,可以通过使用MNS的Queue模型来接收语音的回执消息。

消息的订阅

云通信的所有业务消息都用过MNS消息服务向外发送。用户每订阅一个类别的消息(比如语音呼叫消息VoiceReport),系统都会为用户分配一个独立的消息队列。用户可以通过阿里云账号拿到一个临时的token用于获取队列中的消息。用户可以下载demo,编写简单的消息处理类即可完成消息处理的任务。在页面上订阅消息,订阅完消息后,能拿到消息队列名称(QueueName)。比如:Alicom-Queue-xxxxxx-VoiceReport 。队列名字每个用户都不同。

消息类型

语音提供一种消息类型,呼叫记录消息(VoiceReport)

语音呼叫记录消息VoiceReport消息体格式

名称

类型

描述

示例

是否必须

call_id

String

呼叫ID。

100001616500^100001871490

必须

start_time

String

通话开始时间,未接通则为空。

2017-06-01 10:00:00

可选

end_time

String

通话结束时间,未接通则为空。

2017-06-01 10:00:00

可选

duration

String

通话时长,未接通为0。

10

可选

status_code

String

呼叫结果状态码。

200010

必须

status_msg

String

结果描述。

执行完成

可选

out_id

String

扩展字段回传,将调用API时传入的字段返回。

123456

可选

dtmf

String

DTMF按键。

123456

可选

技术对接步骤

下载消息SDK

SDK工具包中一共包含了3个目录:

  • aliyun-python-sdk-core:阿里云API调用的核心代码库,Python版本。

  • mns_python_sdk:阿里云MNS产品消息订阅SDK代码库。

  • aliyunsdkdybaseapi:云通信业务(语音、流量、短信)基础接口代码,用于订阅消息时获取token以及账号信息。

确定本机已经安装了Python,版本要求:2.6.5 或以上版本。

进入aliyun-python-sdk-core目录执行:python setup.py install。

进入mns_python_sdk目录执行:python setup.py install。

运行demo示例。进入alicom-mns-receive-samples-python目录执行:python sample.py 。

SDK&DEMO下载地址,请参见SDK&DEMO下载

编写样例代码(以短信回执报告为例)

说明

调用接口前,需配置环境变量,通过环境变量读取访问凭证。AccessKey ID和AccessKey Secret的环境变量名:VMS_AK_ENV 、VMS_SK_ENV。配置详情请参见配置访问凭证

#!/usr/bin/env python
# coding=utf8
import os
import sys
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkcore.client import AcsClient
from aliyunsdkdybaseapi.request.v20170525.QueryTokenForMnsQueueRequest import QueryTokenForMnsQueueRequest

import datetime
from mns.account import Account
from mns.queue import *

try:
    import json
except ImportError:
    import simplejson as json

"""
云通信基础能力业务回执消息消费示例,供参考。
Created on 2017-06-13
"""

reload(sys)
sys.setdefaultencoding('utf8')

regionid = "cn-hangzhou"

# 阿里云账号AccessKey ID拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户
# 此处以把AccessKey ID和AccessKey Secret保存在环境变量为例说明。 您也可以根据业务需要,保存到配置文件里
# 强烈建议不要把AccessKey ID和AccessKey Secret保存到代码里,会存在密钥泄漏风险
accesskeyid = os.getenv("VMS_AK_ENV")
accesskeysecret = os.getenv("VMS_SK_ENV")

# 语音回执消息VoiceReport
msgtype = "VoiceReport"
# 在云通信页面开通相应业务消息后,就能在页面上获得对应的queueName
qname = "Alicom-Queue-1093695199815616-VoiceReport"
#初始化acs_client
acs_client = AcsClient(accesskeyid, accesskeysecret, regionid)

# 云通信业务token存在失效时间,需动态更新。
class Token():
    def __init__(self, token=None, tmp_access_id=None, tmp_access_key=None, expire_time=None):
        self.__token = token
        self.__tmp_access_id = tmp_access_id
        self.__tmp_access_key = tmp_access_key
        self.__expire_time = expire_time

    def get_token(self):
        return self.__token

    def set_token(self, token):
        self.__token = token

    def get_tmp_access_id(self):
        return self.__tmp_access_id

    def set_tmp_access_id(self, tmp_access_id):
        self.__tmp_access_id = tmp_access_id

    def get_tmp_access_key(self):
        return self.__tmp_access_key

    def set_tmp_access_key(self, tmp_access_key):
        self.__tmp_access_key = tmp_access_key

    def get_expire_time(self):
        return self.__expire_time

    def set_expire_time(self, expire_time):
        self.__expire_time = expire_time

    def is_refresh(self):
        # 失效时间与当前系统时间比较,提前2分钟刷新token
        now = datetime.datetime.now()
        expire = datetime.datetime.strptime(self.__expire_time, "%Y-%m-%d %H:%M:%S")
        # intval = (expire - now).seconds
        # print "token生效剩余时长(秒):" + str(intval)
        if (expire - now).seconds < 120:
            return 1
        return 0

    def refresh(self):
        print "start refresh token..."
        request = QueryTokenForMnsQueueRequest()
        request.set_MessageType(msgtype)
        response = acs_client.do_action_with_exception(request)
        # print response
        if response is None:
            raise ServerException("GET_TOKEN_FAIL", "获取token时无响应")

        response_body = json.loads(response)

        if response_body.get("Code") != "OK":
            raise ServerException("GET_TOKEN_FAIL", "获取token失败")

        self.__tmp_access_key = response_body.get("MessageTokenDTO").get("AccessKeySecret")
        self.__tmp_access_id = response_body.get("MessageTokenDTO").get("AccessKeyId")
        self.__expire_time = response_body.get("MessageTokenDTO").get("ExpireTime")
        self.__token = response_body.get("MessageTokenDTO").get("SecurityToken")

        print "finsh refresh token..."


# 初始化 my_account, my_queue
token = Token()
token.refresh()
my_account = Account(endpoint, token.get_tmp_access_id(), token.get_tmp_access_key(), token.get_token())
my_queue = my_account.get_queue(qname)
# my_queue.set_encoding(False)
# 循环读取删除消息直到队列空
# receive message请求使用long polling方式,通过wait_seconds指定长轮询时间为3秒

## long polling 解析:
### 当队列中有消息时,请求立即返回;
### 当队列中没有消息时,请求在MNS服务器端挂3秒钟,在这期间,有消息写入队列,请求会立即返回消息,3秒后,请求返回队列没有消息;

wait_seconds = 3
print "%sReceive And Delete Message From Queue%s\nQueueName:%s\nWaitSeconds:%s\n" % (
    10 * "=", 10 * "=", qname, wait_seconds)
while True:
    # 读取消息
    try:
        if token.is_refresh() == 1:
            # 刷新token
            token.refresh()
            my_account.mns_client.close_connection();
            my_account = Account(endpoint, token.get_tmp_access_id(), token.get_tmp_access_key(), token.get_token())
            my_queue = my_account.get_queue(qname)
            # my_queue.set_encoding(False)
        recv_msg = my_queue.receive_message(wait_seconds)
        print "Receive Message Succeed! ReceiptHandle:%s MessageBody:%s MessageID:%s" % (
            recv_msg.receipt_handle, recv_msg.message_body, recv_msg.message_id)
    except MNSExceptionBase, e:
        if e.type == "QueueNotExist":
            print "Queue not exist, please create queue before receive message."
            sys.exit(0)
        elif e.type == "MessageNotExist":
            print "Queue is empty! sleep 10s"
            time.sleep(10)
            continue
        print "Receive Message Fail! Exception:%s\n" % e
        continue

    # 删除消息
    try:
        my_queue.delete_message(recv_msg.receipt_handle)
        print "Delete Message Succeed!  ReceiptHandle:%s" % recv_msg.receipt_handle
    except MNSExceptionBase, e:
        print "Delete Message Fail! Exception:%s\n" % e