开发者社区> 问答> 正文

短信消息API---Python



简介


当您使用短信的API接口发送短信后,可以通过使用MNS的Queue模型来接收短信的回执消息,假如服务出现异常情况时(如网络问题),导致消息回执未成功获取,还可以通过短信发送状态查询API接口进行一定的补偿(目前支持30天内发送记录的查询)。

消息的订阅

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


消息类型


短信提供2种消息类型SmsReport(短信回执报告消息) 和 SmsUp(上行短信消息)
  • 通过订阅SmsReport短信状态报告,可以获知每条短信的发送情况,了解短信是否达到终端用户的状态与相关信息
  • 通过订阅SmsUp上行短信消息,可以获知终端用户回复短信的内容


短信回执消息SmsReport消息体格式

名称类型描述示例是否必须
phone_numberString短信接收号码13000000000可选
successBoolean发送是否成功true必须
biz_idString发送回执ID1234^345必须
out_idString调用发送短信接口时传的outId123456可选
send_timeString转发给运营商的时间2017-06-01 10:00:00必须
report_timeString收到运营商回执的时间2017-06-01 10:00:05可选
err_codeString错误码UNKNOW可选
err_msgString错误信息未知异常可选
sms_sizeString140字节算一条短信,短信长度超过140字节时会拆分成多条短信发送1,2,3可选


上行短信消息SmsUp

名称类型描述示例是否必须
phone_numberString短信接收号码13000000000可选
contentString短信内容true必须
send_timeString时间20150101120000必须
dest_codeString扩展码123456必须
sequence_idString消息序列ID123456必须


技术对接步骤



下载消息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="">
  1. #!/usr/bin/env python
  2. # coding=utf8
  3. import sys
  4. from aliyunsdkcore.acs_exception.exceptions import ServerException
  5. from aliyunsdkcore.client import AcsClient
  6. from aliyunsdkdybaseapi.request.v20170525.QueryTokenForMnsQueueRequest import QueryTokenForMnsQueueRequest
  7. import datetime
  8. from mns.account import Account
  9. from mns.queue import *
  10. try:
  11.     import json
  12. except ImportError:
  13.     import simplejson as json
  14. """
  15. 云通信基础能力业务回执消息消费示例,供参考。
  16. Created on 2017-06-13
  17. """
  18. reload(sys)
  19. sys.setdefaultencoding('utf8')
  20. regionid = "cn-hangzhou"
  21. # ACCESS_KEY_ID/ACCESS_KEY_SECRET 根据实际申请的账号信息进行替换
  22. accesskeyid = "yourAccessKeyId"
  23. accesskeysecret = "yourAccessKeySecret"
  24. endpoint = "http://1943695596114318.mns.cn-hangzhou.aliyuncs.com"
  25. # 短信回执报告:SmsReport,短息上行:SmsUp
  26. msgtype = "SmsReport"
  27. # 在云通信页面开通相应业务消息后,就能在页面上获得对应的queueName
  28. qname = "Alicom-Queue-1093695199815616-SmsReport"
  29. #初始化acs_client
  30. acs_client = AcsClient(accesskeyid, accesskeysecret, regionid)
  31. # 云通信业务token存在失效时间,需动态更新。
  32. class Token():
  33.     def __init__(self, token=None, tmp_access_id=None, tmp_access_key=None, expire_time=None):
  34.         self.__token = token
  35.         self.__tmp_access_id = tmp_access_id
  36.         self.__tmp_access_key = tmp_access_key
  37.         self.__expire_time = expire_time
  38.     def get_token(self):
  39.         return self.__token
  40.     def set_token(self, token):
  41.         self.__token = token
  42.     def get_tmp_access_id(self):
  43.         return self.__tmp_access_id
  44.     def set_tmp_access_id(self, tmp_access_id):
  45.         self.__tmp_access_id = tmp_access_id
  46.     def get_tmp_access_key(self):
  47.         return self.__tmp_access_key
  48.     def set_tmp_access_key(self, tmp_access_key):
  49.         self.__tmp_access_key = tmp_access_key
  50.     def get_expire_time(self):
  51.         return self.__expire_time
  52.     def set_expire_time(self, expire_time):
  53.         self.__expire_time = expire_time
  54.     def is_refresh(self):
  55.         # 失效时间与当前系统时间比较,提前2分钟刷新token
  56.         now = datetime.datetime.now()
  57.         expire = datetime.datetime.strptime(self.__expire_time, "%Y-%m-%d %H:%M:%S")
  58.         # intval = (expire - now).seconds
  59.         # print "token生效剩余时长(秒):" + str(intval)
  60.         if (expire - now).seconds < 120:
  61.             return 1
  62.         return 0
  63.     def refresh(self):
  64.         print "start refresh token..."
  65.         request = QueryTokenForMnsQueueRequest()
  66.         request.set_MessageType(msgtype)
  67.         response = acs_client.do_action_with_exception(request)
  68.         # print response
  69.         if response is None:
  70.             raise ServerException("GET_TOKEN_FAIL", "获取token时无响应")
  71.         response_body = json.loads(response)
  72.         if response_body.get("Code") != "OK":
  73.             raise ServerException("GET_TOKEN_FAIL", "获取token失败")
  74.         self.__tmp_access_key = response_body.get("MessageTokenDTO").get("AccessKeySecret")
  75.         self.__tmp_access_id = response_body.get("MessageTokenDTO").get("AccessKeyId")
  76.         self.__expire_time = response_body.get("MessageTokenDTO").get("ExpireTime")
  77.         self.__token = response_body.get("MessageTokenDTO").get("SecurityToken")
  78.         print "finsh refresh token..."
  79. # 初始化 my_account, my_queue
  80. token = Token()
  81. token.refresh()
  82. my_account = Account(endpoint, token.get_tmp_access_id(), token.get_tmp_access_key(), token.get_token())
  83. my_queue = my_account.get_queue(qname)
  84. # my_queue.set_encoding(False)
  85. # 循环读取删除消息直到队列空
  86. # receive message请求使用long polling方式,通过wait_seconds指定长轮询时间为3秒
  87. ## long polling 解析:
  88. ### 当队列中有消息时,请求立即返回;
  89. ### 当队列中没有消息时,请求在MNS服务器端挂3秒钟,在这期间,有消息写入队列,请求会立即返回消息,3秒后,请求返回队列没有消息;
  90. wait_seconds = 3
  91. print "%sReceive And Delete Message From Queue%s\nQueueName:%s\nWaitSeconds:%s\n" % (
  92.     10 * "=", 10 * "=", qname, wait_seconds)
  93. while True:
  94.     # 读取消息
  95.     try:
  96.         if token.is_refresh() == 1:
  97.             # 刷新token
  98.             token.refresh()
  99.             my_account.mns_client.close_connection();
  100.             my_account = Account(endpoint, token.get_tmp_access_id(), token.get_tmp_access_key(), token.get_token())
  101.             my_queue = my_account.get_queue(qname)
  102.             # my_queue.set_encoding(False)
  103.         recv_msg = my_queue.receive_message(wait_seconds)
  104.         print "Receive Message Succeed! ReceiptHandle:%s MessageBody:%s MessageID:%s" % (
  105.             recv_msg.receipt_handle, recv_msg.message_body, recv_msg.message_id)
  106.     except MNSExceptionBase, e:
  107.         if e.type == "QueueNotExist":
  108.             print "Queue not exist, please create queue before receive message."
  109.             sys.exit(0)
  110.         elif e.type == "MessageNotExist":
  111.             print "Queue is empty! sleep 10s"
  112.             time.sleep(10)
  113.             continue
  114.         print "Receive Message Fail! Exception:%s\n" % e
  115.         continue
  116.     # 删除消息
  117.     try:
  118.         my_queue.delete_message(recv_msg.receipt_handle)
  119.         print "Delete Message Succeed!  ReceiptHandle:%s" % recv_msg.receipt_handle
  120.     except MNSExceptionBase, e:
  121.         print "Delete Message Fail! Exception:%s\n" % e

展开
收起
nicenelly 2017-10-25 11:49:14 2490 0
0 条回答
写回答
取消 提交回答
问答排行榜
最热
最新

相关电子书

更多
Spring Boot2.0实战Redis分布式缓存 立即下载
CUDA MATH API 立即下载
API PLAYBOOK 立即下载