CCPRestSDK.py 30 KB

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