简介
当您使用短信的API接口发送短信后,可以通过使用MNS的Queue模型来接收短信的回执消息,假如服务出现异常情况时(如网络问题),导致消息回执未成功获取,还可以通过短信发送状态查询API接口进行一定的补偿(目前支持30天内发送记录的查询)。
消息的订阅
- 云通信的所有业务消息都用过MNS消息服务向外发送。用户每订阅一个类别的消息(比如上行短信消息SmsUp),系统都会为用户分配一个独立的消息队列。
- 用户可以通过阿里云账号拿到一个临时的token用于获取队列中的消息。用户可以下载demo,编写简单的消息处理类即可完成消息处理的任务。
- 在页面上订阅消息,订阅完消息后,能拿到消息队列名称(queueName)。比如:Alicom-Queue-xxxxxx-SmsReport 。队列名字每个用户都不同。
消息类型
短信提供2种消息类型SmsReport(短信回执报告消息) 和 SmsUp(上行短信消息)
- 通过订阅SmsReport短信状态报告,可以获知每条短信的发送情况,了解短信是否达到终端用户的状态与相关信息
- 通过订阅SmsUp上行短信消息,可以获知终端用户回复短信的内容
短信回执消息SmsReport消息体格式
上行短信消息SmsUp
技术对接步骤
下载消息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[
下载地址]
编写样例代码
<pre style='background: rgb(246, 246, 246); font: 12px/1.6 "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; padding: 10px; outline: 0px; border-radius: 3px; border: 1px solid rgb(221, 221, 221); color: rgb(51, 51, 51); text-transform: none; text-indent: 0px; letter-spacing: normal; overflow: auto; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; word-spacing: 0px; white-space: pre-wrap; word-wrap: break-word; box-sizing: border-box; orphans: 2; widows: 2; font-size-adjust: none; font-stretch: normal; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;' prettyprinted?="" linenums="">
- #!/usr/bin/env python
- # coding=utf8
- 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"
- # ACCESS_KEY_ID/ACCESS_KEY_SECRET 根据实际申请的账号信息进行替换
- accesskeyid = "yourAccessKeyId"
- accesskeysecret = "yourAccessKeySecret"
- endpoint = "http://1943695596114318.mns.cn-hangzhou.aliyuncs.com"
- # 短信回执报告:SmsReport,短息上行:SmsUp
- msgtype = "SmsReport"
- # 在云通信页面开通相应业务消息后,就能在页面上获得对应的queueName
- qname = "Alicom-Queue-1093695199815616-SmsReport"
- #初始化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