一. Django基于python3.6使用容联发送短信流程

  容联官方的python支持2.7版本,当我们python解释器采用3版本时,需要修改容联接口中的一些参数及方法。

  首先去容联官网注册账号,申请测试账号无需实名认证,而且开始账号自带8元钱,一条短信大概2分。

1.1 调用接口前的准备

  首先注册登录之后再控制台中添加测试号码:

  点击导航栏的开发文档:

  选择短信开发手册:

  之后点击Demo示例:

  下载基于python的Demo:

  下载完成后解压,将其中的两个文件复制:

  然后在python项目文件夹下新建文件夹,比如libs,里面再新建一个文件夹,将这两个文件黏贴在其中:

  然后在yuntongxun文件下新建sms.py文件,同时将接口调用示例中年的代码复制黏贴至其中:

  将sms.py中的报错修改一下:

  以上几个参数在控制台中可以看到:

  同时可以修改一下sms.py文件中调用接口的函数,修改一下返回的信息,方便后续加入自己的逻辑,这里我将其函数名也修改了:

  1. def send_msg(to, datas, tempId):
  2. # 初始化REST SDK
  3. rest = REST(serverIP, serverPort, softVersion)
  4. rest.setAccount(accountSid, accountToken)
  5. rest.setAppId(appId)
  6.  
  7. result = rest.sendTemplateSMS(to, datas, tempId)
  8. if result.get('statusCode') == '':
  9. print('发送成功')
  10. return True
  11. else:
  12. print('发送失败')
  13. return False

  result中的信息可以在开发文档中查看:

1.2 使用容联接口

  打开CCPRestSDK.py发现报错:

  将其中的模块修改如下,修改三个地方:

  1. # 修改
  2. from hashlib import md5
  3. import base64
  4. import datetime
  5. # 修改
  6. from urllib import request as urllib2
  7. import json
  8. # 修改
  9. from .xmltojson import xmltojson
  10. from xml.dom import minidom

  然后里面还有很多报错如下:

  修改成以下格式即可(将Exception后的逗号去掉改为as即可),将所有该报错修改,共13个:

  然后将第定位至235行:

  首先修改生成sig中的内容:

  1. #生成sig
  2. signature = self.AccountSid + self.AccountToken + self.Batch;
  3. md5_obj = md5()
  4. md5_obj.md5.new(signature)
  5. sig = md5_obj.hexdigest().upper()

  再修改生成auth中的内容:

  1. # 仅仅修改其中的auth
  2. auth = base64.encodebytes(src.encode()).decode().strip()

  再修改269行的代码:

  修改如下:

  1. req.data = body.encode()

  然后775行的代码也需要加个类型转换:

  使用Int将其转为整型:

  1. if(int(self.ServerPort)<=0):
  2. print('');
  3. print('端口错误(小于等于0)');

  接着在yuntongxun文件夹下的__init__.py中加入以下语句:

  1. from .sms import send_msg

  然后新建一个测试文件测试,需要搭建django测试环境,代码如下:

  1. import os
  2.  
  3. # 以下三行配置django测试环境
  4. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffyapi.settings.dev')
  5. import django
  6. django.setup()
  7.  
  8. from luffyapi.libs.yuntongxun import send_msg
  9.  
  10. # send_msg('接收方手机号',(验证码,过期时间分钟), 模块编号)
  11. # 模板编号测试环境中只能为1,接收方手机号是我们控制台测试号码中配置的
  12. # 过期时间客户端收到的是以分钟为单位的,我们通过该值配置redis等非关系型数据库中该验证码的过期时间
  13. result = send_msg('', ('python', 5), 1)
  14. print(result)
  1. # -*- coding: UTF-8 -*-
  2. # Copyright (c) 2014 The CCP project authors. All Rights Reserved.
  3. #
  4. # Use of this source code is governed by a Beijing Speedtong Information Technology Co.,Ltd license
  5. # that can be found in the LICENSE file in the root of the web site.
  6. #
  7. # http://www.yuntongxun.com
  8. #
  9. # An additional intellectual property rights grant can be found
  10. # in the file PATENTS. All contributing project authors may
  11. # be found in the AUTHORS file in the root of the source tree.
  12.  
  13. from hashlib import md5
  14. import base64
  15. import datetime
  16. from urllib import request as urllib2
  17. import json
  18. from .xmltojson import xmltojson
  19.  
  20. class REST:
  21. AccountSid = ''
  22. AccountToken = ''
  23. AppId = ''
  24. SubAccountSid = ''
  25. SubAccountToken = ''
  26. ServerIP = ''
  27. ServerPort = ''
  28. SoftVersion = ''
  29. Iflog = False # 是否打印日志
  30. Batch = '' # 时间戳
  31. BodyType = 'xml' # 包体格式,可填值:json 、xml
  32.  
  33. # 初始化
  34. # @param serverIP 必选参数 服务器地址
  35. # @param serverPort 必选参数 服务器端口
  36. # @param softVersion 必选参数 REST版本号
  37. def __init__(self, ServerIP, ServerPort, SoftVersion):
  38.  
  39. self.ServerIP = ServerIP
  40. self.ServerPort = ServerPort
  41. self.SoftVersion = SoftVersion
  42.  
  43. # 设置主帐号
  44. # @param AccountSid 必选参数 主帐号
  45. # @param AccountToken 必选参数 主帐号Token
  46.  
  47. def setAccount(self, AccountSid, AccountToken):
  48. self.AccountSid = AccountSid
  49. self.AccountToken = AccountToken
  50.  
  51. # 设置子帐号
  52. #
  53. # @param SubAccountSid 必选参数 子帐号
  54. # @param SubAccountToken 必选参数 子帐号Token
  55.  
  56. def setSubAccount(self, SubAccountSid, SubAccountToken):
  57. self.SubAccountSid = SubAccountSid
  58. self.SubAccountToken = SubAccountToken
  59.  
  60. # 设置应用ID
  61. #
  62. # @param AppId 必选参数 应用ID
  63.  
  64. def setAppId(self, AppId):
  65. self.AppId = AppId
  66.  
  67. def log(self, url, body, data):
  68. print('这是请求的URL:')
  69. print(url)
  70. print('这是请求包体:')
  71. print(body)
  72. print('这是响应包体:')
  73. print(data)
  74. print('********************************')
  75.  
  76. # 创建子账号
  77. # @param friendlyName 必选参数 子帐号名称
  78. def CreateSubAccount(self, friendlyName):
  79.  
  80. self.accAuth()
  81. nowdate = datetime.datetime.now()
  82. self.Batch = nowdate.strftime("%Y%m%d%H%M%S")
  83. # 生成sig
  84. signature = self.AccountSid + self.AccountToken + self.Batch
  85. sig = md5(signature.encode()).hexdigest().upper()
  86. # 拼接URL
  87. url = "https://" + self.ServerIP + ":" + self.ServerPort + "/" + self.SoftVersion + "/Accounts/" + self.AccountSid + "/SubAccounts?sig=" + sig
  88. # 生成auth
  89. src = self.AccountSid + ":" + self.Batch
  90. auth = base64.encodebytes(src.encode()).decode().strip()
  91. req = urllib2.Request(url)
  92. self.setHttpHeader(req)
  93. req.add_header("Authorization", auth)
  94. # xml格式
  95. body = '''<?xml version="1.0" encoding="utf-8"?><SubAccount><appId>%s</appId>\
  96. <friendlyName>%s</friendlyName>\
  97. </SubAccount>\
  98. ''' % (self.AppId, friendlyName)
  99.  
  100. if self.BodyType == 'json':
  101. # json格式
  102. body = '''{"friendlyName": "%s", "appId": "%s"}''' % (friendlyName, self.AppId)
  103. data = ''
  104. req.data = body.encode()
  105. try:
  106. res = urllib2.urlopen(req)
  107. data = res.read()
  108. res.close()
  109.  
  110. if self.BodyType == 'json':
  111. # json格式
  112. locations = json.loads(data)
  113. else:
  114. # xml格式
  115. xtj = xmltojson()
  116. locations = xtj.main(data)
  117. if self.Iflog:
  118. self.log(url, body, data)
  119. return locations
  120. except Exception as error:
  121. if self.Iflog:
  122. self.log(url, body, data)
  123. return {'': '网络错误'}
  124.  
  125. # 获取子帐号
  126. # @param startNo 可选参数 开始的序号,默认从0开始
  127. # @param offset 可选参数 一次查询的最大条数,最小是1条,最大是100条
  128. def getSubAccounts(self, startNo, offset):
  129.  
  130. self.accAuth()
  131. nowdate = datetime.datetime.now()
  132. self.Batch = nowdate.strftime("%Y%m%d%H%M%S")
  133. # 生成sig
  134. signature = self.AccountSid + self.AccountToken + self.Batch
  135. sig = md5(signature.encode()).hexdigest().upper()
  136. # 拼接URL
  137. url = "https://" + self.ServerIP + ":" + self.ServerPort + "/" + self.SoftVersion + "/Accounts/" + self.AccountSid + "/GetSubAccounts?sig=" + sig
  138. # 生成auth
  139. src = self.AccountSid + ":" + self.Batch
  140. # auth = base64.encodestring(src).strip()
  141. auth = base64.encodebytes(src.encode()).decode().strip()
  142. req = urllib2.Request(url)
  143. self.setHttpHeader(req)
  144. req.add_header("Authorization", auth)
  145. # xml格式
  146. body = '''<?xml version="1.0" encoding="utf-8"?><SubAccount><appId>%s</appId>\
  147. <startNo>%s</startNo><offset>%s</offset>\
  148. </SubAccount>\
  149. ''' % (self.AppId, startNo, offset)
  150.  
  151. if self.BodyType == 'json':
  152. # json格式
  153. body = '''{"appId": "%s", "startNo": "%s", "offset": "%s"}''' % (self.AppId, startNo, offset)
  154. data = ''
  155. req.data = body.encode()
  156. try:
  157. res = urllib2.urlopen(req)
  158. data = res.read()
  159. res.close()
  160.  
  161. if self.BodyType == 'json':
  162. # json格式
  163. locations = json.loads(data)
  164. else:
  165. # xml格式
  166. xtj = xmltojson()
  167. locations = xtj.main(data)
  168. if self.Iflog:
  169. self.log(url, body, data)
  170. return locations
  171. except Exception as error:
  172. if self.Iflog:
  173. self.log(url, body, data)
  174. return {'': '网络错误'}
  175.  
  176. # 子帐号信息查询
  177. # @param friendlyName 必选参数 子帐号名称
  178.  
  179. def querySubAccount(self, friendlyName):
  180.  
  181. self.accAuth()
  182. nowdate = datetime.datetime.now()
  183. self.Batch = nowdate.strftime("%Y%m%d%H%M%S")
  184. # 生成sig
  185. signature = self.AccountSid + self.AccountToken + self.Batch
  186. sig = md5(signature.encode()).hexdigest().upper()
  187. # 拼接URL
  188. url = "https://" + self.ServerIP + ":" + self.ServerPort + "/" + self.SoftVersion + "/Accounts/" + self.AccountSid + "/QuerySubAccountByName?sig=" + sig
  189. # 生成auth
  190. src = self.AccountSid + ":" + self.Batch
  191. # auth = base64.encodestring(src).strip()
  192. auth = base64.encodebytes(src.encode()).decode().strip()
  193. req = urllib2.Request(url)
  194. self.setHttpHeader(req)
  195.  
  196. req.add_header("Authorization", auth)
  197.  
  198. # 创建包体
  199. body = '''<?xml version="1.0" encoding="utf-8"?><SubAccount><appId>%s</appId>\
  200. <friendlyName>%s</friendlyName>\
  201. </SubAccount>\
  202. ''' % (self.AppId, friendlyName)
  203. if self.BodyType == 'json':
  204. body = '''{"friendlyName": "%s", "appId": "%s"}''' % (friendlyName, self.AppId)
  205. data = ''
  206. req.data = body.encode()
  207. try:
  208. res = urllib2.urlopen(req)
  209. data = res.read()
  210. res.close()
  211.  
  212. if self.BodyType == 'json':
  213. # json格式
  214. locations = json.loads(data)
  215. else:
  216. # xml格式
  217. xtj = xmltojson()
  218. locations = xtj.main(data)
  219. if self.Iflog:
  220. self.log(url, body, data)
  221. return locations
  222. except Exception as error:
  223. if self.Iflog:
  224. self.log(url, body, data)
  225. return {'': '网络错误'}
  226.  
  227. # 发送模板短信
  228. # @param to 必选参数 短信接收彿手机号码集合,用英文逗号分开
  229. # @param datas 可选参数 内容数据
  230. # @param tempId 必选参数 模板Id
  231. def sendTemplateSMS(self, to, datas, tempId):
  232.  
  233. self.accAuth()
  234. nowdate = datetime.datetime.now()
  235. self.Batch = nowdate.strftime("%Y%m%d%H%M%S")
  236. # 生成sig
  237. signature = self.AccountSid + self.AccountToken + self.Batch
  238. sig = md5(signature.encode()).hexdigest().upper()
  239. # 拼接URL
  240. url = "https://" + self.ServerIP + ":" + self.ServerPort + "/" + self.SoftVersion + "/Accounts/" + self.AccountSid + "/SMS/TemplateSMS?sig=" + sig
  241. # 生成auth
  242. src = self.AccountSid + ":" + self.Batch
  243. # auth = base64.encodestring(src).strip()
  244. auth = base64.encodebytes(src.encode()).decode().strip()
  245. req = urllib2.Request(url)
  246. self.setHttpHeader(req)
  247. req.add_header("Authorization", auth)
  248. # 创建包体
  249. b = ''
  250. for a in datas:
  251. b += '<data>%s</data>' % (a)
  252.  
  253. body = '<?xml version="1.0" encoding="utf-8"?><SubAccount><datas>' + b + '</datas><to>%s</to><templateId>%s</templateId><appId>%s</appId>\
  254. </SubAccount>\
  255. ' % (to, tempId, self.AppId)
  256. if self.BodyType == 'json':
  257. # if this model is Json ..then do next code
  258. b = '['
  259. for a in datas:
  260. b += '"%s",' % (a)
  261. b += ']'
  262. body = '''{"to": "%s", "datas": %s, "templateId": "%s", "appId": "%s"}''' % (to, b, tempId, self.AppId)
  263. req.data = body.encode()
  264. data = ''
  265. try:
  266. res = urllib2.urlopen(req)
  267. data = res.read()
  268. res.close()
  269.  
  270. if self.BodyType == 'json':
  271. # json格式
  272. locations = json.loads(data)
  273. else:
  274. # xml格式
  275. xtj = xmltojson()
  276. locations = xtj.main(data)
  277. if self.Iflog:
  278. self.log(url, body, data)
  279. return locations
  280. except Exception as error:
  281. if self.Iflog:
  282. self.log(url, body, data)
  283. return {'': '网络错误'}
  284.  
  285. # 外呼通知
  286. # @param to 必选参数 被叫号码
  287. # @param mediaName 可选参数 语音文件名称,格式 wav。与mediaTxt不能同时为空。当不为空时mediaTxt属性失效。
  288. # @param mediaTxt 可选参数 文本内容
  289. # @param displayNum 可选参数 显示的主叫号码
  290. # @param playTimes 可选参数 循环播放次数,1-3次,默认播放1次。
  291. # @param respUrl 可选参数 外呼通知状态通知回调地址,云通讯平台将向该Url地址发送呼叫结果通知。
  292. # @param userData 可选参数 用户私有数据
  293. # @param maxCallTime 可选参数 最大通话时长
  294. # @param speed 可选参数 发音速度
  295. # @param volume 可选参数 音量
  296. # @param pitch 可选参数 音调
  297. # @param bgsound 可选参数 背景音编号
  298.  
  299. def landingCall(self, to, mediaName, mediaTxt, displayNum, playTimes, respUrl, userData, maxCallTime, speed, volume,
  300. pitch, bgsound):
  301.  
  302. self.accAuth()
  303. nowdate = datetime.datetime.now()
  304. self.Batch = nowdate.strftime("%Y%m%d%H%M%S")
  305. # 生成sig
  306. signature = self.AccountSid + self.AccountToken + self.Batch
  307. sig = md5(signature.encode()).hexdigest().upper()
  308. # 拼接URL
  309. url = "https://" + self.ServerIP + ":" + self.ServerPort + "/" + self.SoftVersion + "/Accounts/" + self.AccountSid + "/Calls/LandingCalls?sig=" + sig
  310. # 生成auth
  311. src = self.AccountSid + ":" + self.Batch
  312. # auth = base64.encodestring(src).strip()
  313. auth = base64.encodebytes(src.encode()).decode().strip()
  314. req = urllib2.Request(url)
  315. self.setHttpHeader(req)
  316. req.add_header("Authorization", auth)
  317.  
  318. # 创建包体
  319. body = '''<?xml version="1.0" encoding="utf-8"?><LandingCall>\
  320. <to>%s</to><mediaName>%s</mediaName><mediaTxt>%s</mediaTxt><appId>%s</appId><displayNum>%s</displayNum>\
  321. <playTimes>%s</playTimes><respUrl>%s</respUrl><userData>%s</userData><maxCallTime>%s</maxCallTime><speed>%s</speed>
  322. <volume>%s</volume><pitch>%s</pitch><bgsound>%s</bgsound></LandingCall>\
  323. ''' % (
  324. to, mediaName, mediaTxt, self.AppId, displayNum, playTimes, respUrl, userData, maxCallTime, speed, volume,
  325. pitch, bgsound)
  326. if self.BodyType == 'json':
  327. body = '''{"to": "%s", "mediaName": "%s","mediaTxt": "%s","appId": "%s","displayNum": "%s","playTimes": "%s","respUrl": "%s","userData": "%s","maxCallTime": "%s","speed": "%s","volume": "%s","pitch": "%s","bgsound": "%s"}''' % (
  328. to, mediaName, mediaTxt, self.AppId, displayNum, playTimes, respUrl, userData, maxCallTime, speed,
  329. volume,
  330. pitch, bgsound)
  331. req.data = body.encode()
  332. data = ''
  333. try:
  334. res = urllib2.urlopen(req)
  335. data = res.read()
  336. res.close()
  337.  
  338. if self.BodyType == 'json':
  339. # json格式
  340. locations = json.loads(data)
  341. else:
  342. # xml格式
  343. xtj = xmltojson()
  344. locations = xtj.main(data)
  345. if self.Iflog:
  346. self.log(url, body, data)
  347. return locations
  348. except Exception as error:
  349. if self.Iflog:
  350. self.log(url, body, data)
  351. return {'': '网络错误'}
  352.  
  353. # 语音验证码
  354. # @param verifyCode 必选参数 验证码内容,为数字和英文字母,不区分大小写,长度4-8位
  355. # @param playTimes 可选参数 播放次数,1-3次
  356. # @param to 必选参数 接收号码
  357. # @param displayNum 可选参数 显示的主叫号码
  358. # @param respUrl 可选参数 语音验证码状态通知回调地址,云通讯平台将向该Url地址发送呼叫结果通知
  359. # @param lang 可选参数 语言类型
  360. # @param userData 可选参数 第三方私有数据
  361.  
  362. def voiceVerify(self, verifyCode, playTimes, to, displayNum, respUrl, lang, userData):
  363.  
  364. self.accAuth()
  365. nowdate = datetime.datetime.now()
  366. self.Batch = nowdate.strftime("%Y%m%d%H%M%S")
  367. # 生成sig
  368. signature = self.AccountSid + self.AccountToken + self.Batch
  369. sig = md5(signature.encode()).hexdigest().upper()
  370. # 拼接URL
  371. url = "https://" + self.ServerIP + ":" + self.ServerPort + "/" + self.SoftVersion + "/Accounts/" + self.AccountSid + "/Calls/VoiceVerify?sig=" + sig
  372. # 生成auth
  373. src = self.AccountSid + ":" + self.Batch
  374. # auth = base64.encodestring(src).strip()
  375. auth = base64.encodebytes(src.encode()).decode().strip()
  376. req = urllib2.Request(url)
  377. self.setHttpHeader(req)
  378.  
  379. req.add_header("Authorization", auth)
  380.  
  381. # 创建包体
  382. body = '''<?xml version="1.0" encoding="utf-8"?><VoiceVerify>\
  383. <appId>%s</appId><verifyCode>%s</verifyCode><playTimes>%s</playTimes><to>%s</to><respUrl>%s</respUrl>\
  384. <displayNum>%s</displayNum><lang>%s</lang><userData>%s</userData></VoiceVerify>\
  385. ''' % (self.AppId, verifyCode, playTimes, to, respUrl, displayNum, lang, userData)
  386. if self.BodyType == 'json':
  387. # if this model is Json ..then do next code
  388. body = '''{"appId": "%s", "verifyCode": "%s","playTimes": "%s","to": "%s","respUrl": "%s","displayNum": "%s","lang": "%s","userData": "%s"}''' % (
  389. self.AppId, verifyCode, playTimes, to, respUrl, displayNum, lang, userData)
  390. req.data = body.encode()
  391. data = ''
  392. try:
  393. res = urllib2.urlopen(req)
  394. data = res.read()
  395. res.close()
  396.  
  397. if self.BodyType == 'json':
  398. # json格式
  399. locations = json.loads(data)
  400. else:
  401. # xml格式
  402. xtj = xmltojson()
  403. locations = xtj.main(data)
  404. if self.Iflog:
  405. self.log(url, body, data)
  406. return locations
  407. except Exception as error:
  408. if self.Iflog:
  409. self.log(url, body, data)
  410. return {'': '网络错误'}
  411.  
  412. # IVR外呼
  413. # @param number 必选参数 待呼叫号码,为Dial节点的属性
  414. # @param userdata 可选参数 用户数据,在<startservice>通知中返回,只允许填写数字字符,为Dial节点的属性
  415. # @param record 可选参数 是否录音,可填项为true和false,默认值为false不录音,为Dial节点的属性
  416.  
  417. def ivrDial(self, number, userdata, record):
  418.  
  419. self.accAuth()
  420. nowdate = datetime.datetime.now()
  421. self.Batch = nowdate.strftime("%Y%m%d%H%M%S")
  422. # 生成sig
  423. signature = self.AccountSid + self.AccountToken + self.Batch;
  424. sig = md5(signature.encode()).hexdigest().upper()
  425. # 拼接URL
  426. url = "https://" + self.ServerIP + ":" + self.ServerPort + "/" + self.SoftVersion + "/Accounts/" + self.AccountSid + "/ivr/dial?sig=" + sig
  427. # 生成auth
  428. src = self.AccountSid + ":" + self.Batch
  429. auth = base64.encodebytes(src.encode()).decode().strip()
  430. req = urllib2.Request(url)
  431. req.add_header("Accept", "application/xml")
  432. req.add_header("Content-Type", "application/xml;charset=utf-8")
  433. req.add_header("Authorization", auth)
  434.  
  435. # 创建包体
  436. body = '''<?xml version="1.0" encoding="utf-8"?>
  437. <Request>
  438. <Appid>%s</Appid>
  439. <Dial number="%s" userdata="%s" record="%s"></Dial>
  440. </Request>
  441. ''' % (self.AppId, number, userdata, record)
  442. req.data = body.encode()
  443. data = ''
  444. try:
  445. res = urllib2.urlopen(req)
  446. data = res.read()
  447. res.close()
  448. xtj = xmltojson()
  449. locations = xtj.main(data)
  450. if self.Iflog:
  451. self.log(url, body, data)
  452. return locations
  453. except Exception as error:
  454. if self.Iflog:
  455. self.log(url, body, data)
  456. return {'': '网络错误'}
  457.  
  458. # 话单下载
  459. # @param date 必选参数 day 代表前一天的数据(从00:00 – 23:59),目前只支持按天查询
  460. # @param keywords 可选参数 客户的查询条件,由客户自行定义并提供给云通讯平台。默认不填忽略此参数
  461. def billRecords(self, date, keywords):
  462.  
  463. self.accAuth()
  464. nowdate = datetime.datetime.now()
  465. self.Batch = nowdate.strftime("%Y%m%d%H%M%S")
  466. # 生成sig
  467. signature = self.AccountSid + self.AccountToken + self.Batch
  468. sig = md5(signature.encode()).hexdigest().upper()
  469. # 拼接URL
  470. url = "https://" + self.ServerIP + ":" + self.ServerPort + "/" + self.SoftVersion + "/Accounts/" + self.AccountSid + "/BillRecords?sig=" + sig
  471. # 生成auth
  472. src = self.AccountSid + ":" + self.Batch
  473. auth = base64.encodebytes(src.encode()).decode().strip()
  474. req = urllib2.Request(url)
  475. self.setHttpHeader(req)
  476. req.add_header("Authorization", auth)
  477.  
  478. # 创建包体
  479. body = '''<?xml version="1.0" encoding="utf-8"?><BillRecords>\
  480. <appId>%s</appId><date>%s</date><keywords>%s</keywords>\
  481. </BillRecords>\
  482. ''' % (self.AppId, date, keywords)
  483. if self.BodyType == 'json':
  484. # if this model is Json ..then do next code
  485. body = '''{"appId": "%s", "date": "%s","keywords": "%s"}''' % (self.AppId, date, keywords)
  486. req.data = body.encode()
  487. data = ''
  488. try:
  489. res = urllib2.urlopen(req)
  490. data = res.read()
  491.  
  492. res.close()
  493.  
  494. if self.BodyType == 'json':
  495. # json格式
  496. locations = json.loads(data)
  497. else:
  498. # xml格式
  499. xtj = xmltojson()
  500. locations = xtj.main(data)
  501. if self.Iflog:
  502. self.log(url, body, data)
  503. return locations
  504. except Exception as error:
  505. if self.Iflog:
  506. self.log(url, body, data)
  507. return {'': '网络错误'}
  508.  
  509. # 主帐号信息查询
  510.  
  511. def queryAccountInfo(self):
  512.  
  513. self.accAuth()
  514. nowdate = datetime.datetime.now()
  515. self.Batch = nowdate.strftime("%Y%m%d%H%M%S")
  516. # 生成sig
  517. signature = self.AccountSid + self.AccountToken + self.Batch
  518. sig = md5(signature.encode()).hexdigest().upper()
  519. # 拼接URL
  520. url = "https://" + self.ServerIP + ":" + self.ServerPort + "/" + self.SoftVersion + "/Accounts/" + self.AccountSid + "/AccountInfo?sig=" + sig
  521. # 生成auth
  522. src = self.AccountSid + ":" + self.Batch
  523. auth = base64.encodebytes(src.encode()).decode().strip()
  524. req = urllib2.Request(url)
  525. self.setHttpHeader(req)
  526. body = ''
  527. req.add_header("Authorization", auth)
  528. data = ''
  529. try:
  530. res = urllib2.urlopen(req)
  531. data = res.read()
  532. res.close()
  533.  
  534. if self.BodyType == 'json':
  535. # json格式
  536. locations = json.loads(data)
  537. else:
  538. # xml格式
  539. xtj = xmltojson()
  540. locations = xtj.main(data)
  541. if self.Iflog:
  542. self.log(url, body, data)
  543. return locations
  544. except Exception as error:
  545. if self.Iflog:
  546. self.log(url, body, data)
  547. return {'': '网络错误'}
  548.  
  549. # 短信模板查询
  550. # @param templateId 必选参数 模板Id,不带此参数查询全部可用模板
  551.  
  552. def QuerySMSTemplate(self, templateId):
  553.  
  554. self.accAuth()
  555. nowdate = datetime.datetime.now()
  556. self.Batch = nowdate.strftime("%Y%m%d%H%M%S")
  557. # 生成sig
  558. signature = self.AccountSid + self.AccountToken + self.Batch
  559. sig = md5(signature.encode()).hexdigest().upper()
  560. # 拼接URL
  561. url = "https://" + self.ServerIP + ":" + self.ServerPort + "/" + self.SoftVersion + "/Accounts/" + self.AccountSid + "/SMS/QuerySMSTemplate?sig=" + sig
  562. # 生成auth
  563. src = self.AccountSid + ":" + self.Batch
  564. auth = base64.encodebytes(src.encode()).decode().strip()
  565. req = urllib2.Request(url)
  566. self.setHttpHeader(req)
  567.  
  568. req.add_header("Authorization", auth)
  569.  
  570. # 创建包体
  571. body = '''<?xml version="1.0" encoding="utf-8"?><Request>\
  572. <appId>%s</appId><templateId>%s</templateId></Request>
  573. ''' % (self.AppId, templateId)
  574. if self.BodyType == 'json':
  575. # if this model is Json ..then do next code
  576. body = '''{"appId": "%s", "templateId": "%s"}''' % (self.AppId, templateId)
  577. req.data = body.encode()
  578. data = ''
  579. try:
  580. res = urllib2.urlopen(req)
  581. data = res.read()
  582. res.close()
  583.  
  584. if self.BodyType == 'json':
  585. # json格式
  586. locations = json.loads(data)
  587. else:
  588. # xml格式
  589. xtj = xmltojson()
  590. locations = xtj.main2(data)
  591. if self.Iflog:
  592. self.log(url, body, data)
  593. return locations
  594. except Exception as error:
  595. if self.Iflog:
  596. self.log(url, body, data)
  597. return {'': '网络错误'}
  598.  
  599. # 呼叫结果查询
  600. # @param callsid 必选参数 呼叫ID
  601.  
  602. def CallResult(self, callSid):
  603.  
  604. self.accAuth()
  605. nowdate = datetime.datetime.now()
  606. self.Batch = nowdate.strftime("%Y%m%d%H%M%S")
  607. # 生成sig
  608. signature = self.AccountSid + self.AccountToken + self.Batch
  609. sig = md5(signature.encode()).hexdigest().upper()
  610. # 拼接URL
  611. url = "https://" + self.ServerIP + ":" + self.ServerPort + "/" + self.SoftVersion + "/Accounts/" + self.AccountSid + "/CallResult?sig=" + sig + "&callsid=" + callSid
  612. # 生成auth
  613. src = self.AccountSid + ":" + self.Batch
  614. auth = base64.encodebytes(src.encode()).decode().strip()
  615. req = urllib2.Request(url)
  616. self.setHttpHeader(req)
  617. body = ''
  618. req.add_header("Authorization", auth)
  619. data = ''
  620. try:
  621. res = urllib2.urlopen(req)
  622. data = res.read()
  623. res.close()
  624.  
  625. if self.BodyType == 'json':
  626. # json格式
  627. locations = json.loads(data)
  628. else:
  629. # xml格式
  630. xtj = xmltojson()
  631. locations = xtj.main(data)
  632. if self.Iflog:
  633. self.log(url, body, data)
  634. return locations
  635. except Exception as error:
  636. if self.Iflog:
  637. self.log(url, body, data)
  638. return {'': '网络错误'}
  639.  
  640. # 呼叫状态查询
  641. # @param callid 必选参数 一个由32个字符组成的电话唯一标识符
  642. # @param action 可选参数 查询结果通知的回调url地址
  643. def QueryCallState(self, callid, action):
  644.  
  645. self.accAuth()
  646. nowdate = datetime.datetime.now()
  647. self.Batch = nowdate.strftime("%Y%m%d%H%M%S")
  648. # 生成sig
  649. signature = self.AccountSid + self.AccountToken + self.Batch
  650. sig = md5(signature.encode()).hexdigest().upper()
  651. # 拼接URL
  652. url = "https://" + self.ServerIP + ":" + self.ServerPort + "/" + self.SoftVersion + "/Accounts/" + self.AccountSid + "/ivr/call?sig=" + sig + "&callid=" + callid
  653. # 生成auth
  654. src = self.AccountSid + ":" + self.Batch
  655. auth = base64.encodebytes(src.encode()).decode().strip()
  656. req = urllib2.Request(url)
  657. self.setHttpHeader(req)
  658. req.add_header("Authorization", auth)
  659.  
  660. # 创建包体
  661. body = '''<?xml version="1.0" encoding="utf-8"?><Request>\
  662. <Appid>%s</Appid><QueryCallState callid="%s" action="%s"/>\
  663. </Request>\
  664. ''' % (self.AppId, callid, action)
  665. if self.BodyType == 'json':
  666. # if this model is Json ..then do next code
  667. body = '''{"Appid":"%s","QueryCallState":{"callid":"%s","action":"%s"}}''' % (self.AppId, callid, action)
  668. req.data = body.encode()
  669. data = ''
  670. try:
  671. res = urllib2.urlopen(req)
  672. data = res.read()
  673.  
  674. res.close()
  675.  
  676. if self.BodyType == 'json':
  677. # json格式
  678. locations = json.loads(data)
  679. else:
  680. # xml格式
  681. xtj = xmltojson()
  682. locations = xtj.main(data)
  683. if self.Iflog:
  684. self.log(url, body, data)
  685. return locations
  686. except Exception as error:
  687. if self.Iflog:
  688. self.log(url, body, data)
  689. return {'': '网络错误'}
  690.  
  691. # 语音文件上传
  692. # @param filename 必选参数 文件名
  693. # @param body 必选参数 二进制串
  694. def MediaFileUpload(self, filename, body):
  695.  
  696. self.accAuth()
  697. nowdate = datetime.datetime.now()
  698. self.Batch = nowdate.strftime("%Y%m%d%H%M%S")
  699. # 生成sig
  700. signature = self.AccountSid + self.AccountToken + self.Batch
  701. sig = md5(signature.encode()).hexdigest().upper()
  702. # 拼接URL
  703. url = "https://" + self.ServerIP + ":" + self.ServerPort + "/" + self.SoftVersion + "/Accounts/" + self.AccountSid + "/Calls/MediaFileUpload?sig=" + sig + "&appid=" + self.AppId + "&filename=" + filename
  704. # 生成auth
  705. src = self.AccountSid + ":" + self.Batch
  706. auth = base64.encodebytes(src.encode()).decode().strip()
  707. req = urllib2.Request(url)
  708. req.add_header("Authorization", auth)
  709. if self.BodyType == 'json':
  710. req.add_header("Accept", "application/json")
  711. req.add_header("Content-Type", "application/octet-stream")
  712.  
  713. else:
  714. req.add_header("Accept", "application/xml")
  715. req.add_header("Content-Type", "application/octet-stream")
  716.  
  717. # 创建包体
  718. req.data = body.encode()
  719.  
  720. try:
  721. res = urllib2.urlopen(req)
  722. data = res.read()
  723.  
  724. res.close()
  725.  
  726. if self.BodyType == 'json':
  727. # json格式
  728. locations = json.loads(data)
  729. else:
  730. # xml格式
  731. xtj = xmltojson()
  732. locations = xtj.main(data)
  733. if self.Iflog:
  734. self.log(url, body, data)
  735. return locations
  736. except Exception as error:
  737. if self.Iflog:
  738. self.log(url, body, data)
  739. return {'': '网络错误'}
  740.  
  741. # 子帐号鉴权
  742. def subAuth(self):
  743. if (self.ServerIP == ""):
  744. print('')
  745. print('IP为空')
  746.  
  747. if (int(self.ServerPort) <= 0):
  748. print('')
  749. print('端口错误(小于等于0)')
  750.  
  751. if (self.SoftVersion == ""):
  752. print('')
  753. print('版本号为空')
  754.  
  755. if (self.SubAccountSid == ""):
  756. print('')
  757. print('子帐号为空')
  758.  
  759. if (self.SubAccountToken == ""):
  760. print('')
  761. print('子帐号令牌为空')
  762.  
  763. if (self.AppId == ""):
  764. print('')
  765. print('应用ID为空')
  766.  
  767. # 主帐号鉴权
  768. def accAuth(self):
  769. if (self.ServerIP == ""):
  770. print('')
  771. print('IP为空')
  772.  
  773. if (int(self.ServerPort) <= 0):
  774. print('')
  775. print('端口错误(小于等于0)')
  776.  
  777. if (self.SoftVersion == ""):
  778. print('')
  779. print('版本号为空')
  780.  
  781. if (self.AccountSid == ""):
  782. print('')
  783. print('主帐号为空')
  784.  
  785. if (self.AccountToken == ""):
  786. print('')
  787. print('主帐号令牌为空')
  788.  
  789. if (self.AppId == ""):
  790. print('')
  791. print('应用ID为空')
  792.  
  793. # 设置包头
  794. def setHttpHeader(self, req):
  795. if self.BodyType == 'json':
  796. req.add_header("Accept", "application/json")
  797. req.add_header("Content-Type", "application/json;charset=utf-8")
  798.  
  799. else:
  800. req.add_header("Accept", "application/xml")
  801. req.add_header("Content-Type", "application/xml;charset=utf-8")

CCPRestSDK修改后的代码

  1. from .CCPRestSDK import REST
  2. from django.conf import settings
  3. # 注:在配置文件dev中完成四个配置信息
  4. # 说明:主账号,登陆云通讯网站后,可在"控制台-应用"中看到开发者主账号ACCOUNT SID
  5. _accountSid = settings.SMS_ACCOUNTSID
  6. # 说明:主账号Token,登陆云通讯网站后,可在控制台-应用中看到开发者主账号AUTH TOKEN
  7. _accountToken = settings.SMS_ACCOUNTTOKEN
  8. # 说明:请使用管理控制台首页的APPID或自己创建应用的APPID
  9. _appId = settings.SMS_APPID
  10. # 说明:请求地址,生产环境配置成app.cloopen.com,开发环境配置成sandboxapp.cloopen.com
  11. _serverIP = settings.SMS_SERVERIP
  12.  
  13. # 说明:请求端口 ,生产环境为8883
  14. _serverPort = ""
  15. # 说明:REST API版本号保持不变
  16. _softVersion = '2013-12-26'
  17.  
  18. def send_sms(mobile, code_expire_tuple, temp_id):
  19. # 配置
  20. rest = REST(_serverIP, _serverPort, _softVersion)
  21. rest.setAccount(_accountSid, _accountToken)
  22. rest.setAppId(_appId)
  23. # 发送
  24. result = rest.sendTemplateSMS(mobile, code_expire_tuple, temp_id)
  25. # 结果:信息成功发生,结果字典result中 statuCode 字段为 "000000"
  26. if result.get("statusCode") == "":
  27. return True # 表示发送短信成功
  28. else:
  29. return False # 表示发送失败

sms.py代码

django中基于python3.6使用容联发送短信的更多相关文章

  1. .Net core----使用容联云短信推送

    一直在忙于写接口,也没有时间去好好的整理的一片文档,写一篇经常的用到的短信推送案例 还是比较喜欢干货  作为有个程序员 有时候复制粘贴习惯了   实在的还是比较实在 比如能用复制解决的为什么不用复制 ...

  2. Android 打开URL中的网页和拨打电话、发送短信功能

    拨打电话需要的权限 <uses-permission android:name="android.permission.CALL_PHONE"/> 为了省事界面都写一起 ...

  3. python-在python3中使用容联云通讯发送短信验证码

    容联云通讯是第三方平台,能够提供短信验证码和语音通信等功能,这里只测试使用短信验证码的功能,因此只需完成注册登录(无需实名认证等)即可使用其短信验证码免费测试服务,不过免费测试服务只能给控制台中指定的 ...

  4. 潭州课堂25班:Ph201805201 django 项目 第十一课 手机号是否存在,短信验证分析 (课堂笔记)

    判断手机号是否注册功能实现 1.分析 请求方法:GET url定义:/mobiles/(?P<mobile>1[3-9]\d{9})/ 请求参数:url路径参数 参数 类型 前端是否必须传 ...

  5. Python3实现发送邮件和发送短信验证码

    Python3实现发送邮件和发送短信验证码 Python3实现发送邮件: import smtplib from email.mime.text import MIMEText from email. ...

  6. Moto C118 基于 Osmocom-BB 和 OpenBTS 搭建小型GSM短信基站

    此文章PDF文档下载地址:点击下载 0x00 写在前面 大家应该都听说过摩托罗拉C118配合Osmocom-BB实现GSM网络下的短信拦截功能吧,在14年左右新出了一种玩法就是Osmocom-BB的s ...

  7. android 中调用接口发送短信

    android中可以通过两种方式发送短信 第一:调用系统短信接口直接发送短信:主要代码如下: //直接调用短信接口发短信 SmsManager smsManager = SmsManager.getD ...

  8. IOS程序开发中-跳转到 发送短信界面 实现发短信

    前言:我发现我标题取的不好,谁帮我取个承接上下文的标题?评论一下,我改 项目需求:在程序开发中,我们需要在某个程序里面发送一些短信验证(不是接收短信验证,关于短信验证,传送门:http://www.c ...

  9. Android开发之Intent跳转到系统应用中的拨号界面、联系人界面、短信界面

    现在开发中的功能需要直接跳转到拨号.联系人.短信界面等等,查找了很多资料,自己整理了一下. 1.跳转到拨号界面,代码如下: 1)直接拨打 Intent intentPhone = new Intent ...

随机推荐

  1. etcd安装部署步骤

    我是通过yum直接安装的(yum install etcd -y),其生成的配置文件在/etc/etcd/etcd.conf. 这里分单机版和集群版来介绍配置项 单机配置 ETCD_DATA_DIR: ...

  2. git 学习 3

    远程仓库 添加远程库 GitHub 注册账号并建立 repository,Clone with SSH 1 $ ssh-keygen -t rsa -C "youremail@example ...

  3. ProjectSend R561 SQL INJ Analysis

    注入出现在./client-edit.php中 ...... if (isset($_GET['id'])) { $client_id = mysql_real_escape_string($_GET ...

  4. webpack插件

    插件 plugins:[ new ExtractTextPlugin.extrct({ }) //创建html new HtmlWebpackPlugin({ title:"first pa ...

  5. XML转换

    找到两个不错的c#的关于XML转string和将string格式化XML输出 感谢以下两位的分享: [string格式化XML输出]http://blog.csdn.net/a497785609/ar ...

  6. [红日安全]Web安全Day4 - SSRF实战攻防

    本文由红日安全成员: MisakiKata 编写,如有不当,还望斧正. 大家好,我们是红日安全-Web安全攻防小组.此项目是关于Web安全的系列文章分享,还包含一个HTB靶场供大家练习,我们给这个项目 ...

  7. windows 10 右键菜单注册表位置

    1. 查找 1.1. 打开注册表 # 1. 使用快捷键打开 “运行” win + r # 2. 在 “运行” 中输入 regedit # 3. 回车 1.2. 点击 查找 # 1. 方法 1 : 点击 ...

  8. 一起了解 .Net Foundation 项目 No.13

    .Net 基金会中包含有很多优秀的项目,今天就和笔者一起了解一下其中的一些优秀作品吧. 中文介绍 中文介绍内容翻译自英文介绍,主要采用意译.如与原文存在出入,请以原文为准. MVVM Light To ...

  9. 【colab pytorch】使用tensorboardcolab可视化

    import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from ...

  10. CSS 权重图

    关系图 图片出处我找不到了. 结论 权重从高到低排序 1. !important 2. style 3. #id 4. .class .child-class 5. .class1.class2 6. ...