PushService.py 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. # -*- coding: utf-8 -*-
  2. """
  3. @Time : 2022/5/19 11:43
  4. @Auth : Locky
  5. @File :PushService.py
  6. @IDE :PyCharm
  7. """
  8. import hashlib
  9. import json
  10. import logging
  11. import os
  12. import time
  13. import apns2
  14. import firebase_admin
  15. import jpush
  16. import requests
  17. from firebase_admin import messaging
  18. from firebase_admin.messaging import UnregisteredError
  19. from pyfcm import FCMNotification
  20. from AnsjerPush.config import APP_BUNDLE_DICT, APNS_MODE, BASE_DIR, APNS_CONFIG, FCM_CONFIG, JPUSH_CONFIG, XMPUSH_CONFIG \
  21. , VIVOPUSH_CONFIG, OPPOPUSH_CONFIG, MEIZUPUSH_CONFIG, CONFIG_INFO, HONORPUSH_CONFIG, DATA_PUSH_EVENT_TYPE_LIST
  22. from Model.models import UidPushModel
  23. from Object.RedisObject import RedisObject
  24. from Object.S3Email import S3Email
  25. from Object.enums.EventTypeEnum import EventTypeEnumObj
  26. from Service.CommonService import CommonService
  27. from Service.VivoPushService.push_admin.APIMessage import PushMessage
  28. from Service.VivoPushService.push_admin.APISender import APISender
  29. from AnsjerPush.config import LOGGER
  30. TIME_LOGGER = logging.getLogger('time')
  31. class PushObject:
  32. # 推送对象
  33. @staticmethod
  34. def get_msg_title(nickname):
  35. """
  36. 获取推送消息标题
  37. @param nickname: 设备名
  38. @return: msg_title
  39. """
  40. return nickname
  41. @staticmethod
  42. def get_gateway_msg_text(n_time, tz, lang, alarm):
  43. """
  44. 获取网关推送消息内容
  45. @param n_time: 当前时间
  46. @param tz: 时区
  47. @param lang: 语言
  48. @param alarm: 警报
  49. @return: msg_text
  50. """
  51. n_date = CommonService.get_now_time_str(n_time=n_time, tz=tz, lang=lang)
  52. if lang == 'cn':
  53. msg_text = '{} 日期:{}'.format(alarm, n_date)
  54. else:
  55. msg_text = '{} date:{}'.format(alarm, n_date)
  56. return msg_text
  57. @staticmethod
  58. def get_ai_msg_text(channel, n_time, lang, tz, label):
  59. """
  60. 获取AI推送内容
  61. @param channel: 通道
  62. @param n_time: 当前时间
  63. @param lang: 语言
  64. @param tz: 时区
  65. @param label: 识别到的标签
  66. @return: ai_msg_text
  67. """
  68. n_date = CommonService.get_now_time_str(n_time=n_time, tz=tz, lang=lang)
  69. if lang == 'cn':
  70. msg = '摄像头AI识别到了{}'.format(label)
  71. ai_msg_text = '{msg} 通道:{channel} 日期:{date}'.format(msg=msg, channel=channel, date=n_date)
  72. else:
  73. msg = 'Camera AI recognizes {}'.format(label)
  74. ai_msg_text = '{msg} channel:{channel} date:{date}'.format(msg=msg, channel=channel, date=n_date)
  75. return ai_msg_text
  76. @staticmethod
  77. def get_low_power_msg_text(channel, n_time, lang, tz, electricity, is_sys=0):
  78. """
  79. 获取低电量推送内容
  80. @param channel: 通道
  81. @param n_time: 当前时间
  82. @param lang: 语言
  83. @param tz: 时区
  84. @param electricity: 电量
  85. @param is_sys: 是否为系统消息
  86. @return: low_power_msg_text
  87. """
  88. n_date = CommonService.get_now_time_str(n_time=n_time, tz=tz, lang=lang)
  89. if lang == 'cn':
  90. alarm = '剩余电量 ' + electricity
  91. if is_sys:
  92. low_power_msg_text = '{} 通道:{}'.format(alarm, channel)
  93. else:
  94. low_power_msg_text = '{} 通道:{} 日期:{}'.format(alarm, channel, n_date)
  95. else:
  96. alarm = 'Battery remaining ' + electricity
  97. if is_sys:
  98. low_power_msg_text = '{} channel:{}'.format(alarm, channel)
  99. else:
  100. low_power_msg_text = '{} channel:{} date:{}'.format(alarm, channel, n_date)
  101. return low_power_msg_text
  102. @staticmethod
  103. def ios_apns_push(nickname, app_bundle_id, token_val, n_time, event_type, msg_title, msg_text,
  104. uid='', channel='1', launch_image=None):
  105. """
  106. ios apns 推送
  107. @param nickname: 设备昵称
  108. @param app_bundle_id: app包id
  109. @param token_val: 推送token
  110. @param n_time: 当前时间
  111. @param event_type: 事件类型
  112. @param msg_title: 推送标题
  113. @param msg_text: 推送内容
  114. @param uid: uid
  115. @param channel: 通道
  116. @param launch_image: 推送图片链接
  117. @return: bool
  118. """
  119. pem_path = os.path.join(BASE_DIR, APNS_CONFIG[app_bundle_id]['pem_path'])
  120. try:
  121. cli = apns2.APNSClient(mode=APNS_MODE, client_cert=pem_path)
  122. alert = apns2.PayloadAlert(title=msg_title, body=msg_text, launch_image=launch_image)
  123. # 跳转类型,1:推送消息,2:系统消息,3:音视频通话消息
  124. jump_type = CommonService.get_jump_type(event_type)
  125. push_data = {'alert': msg_text, 'msg': '', 'sound': '', 'zpush': '1', 'uid': uid, 'channel': channel,
  126. 'received_at': n_time, 'event_time': n_time, 'event_type': event_type, 'nickname': nickname,
  127. 'image_url': launch_image, 'jump_type': jump_type
  128. }
  129. sound = 'call_phone.mp3' if event_type in DATA_PUSH_EVENT_TYPE_LIST else 'default'
  130. payload = apns2.Payload(alert=alert, custom=push_data, sound=sound, category='myCategory',
  131. mutable_content=True)
  132. n = apns2.Notification(payload=payload, priority=apns2.PRIORITY_LOW)
  133. res = cli.push(n=n, device_token=token_val, topic=app_bundle_id)
  134. if res.status_code != 200 and res.status_code != 410:
  135. LOGGER.info('{}IOS推送响应异常: 状态码: {}'.format(uid, res.status_code))
  136. return True
  137. except Exception as e:
  138. LOGGER.info('{}IOS推送异常:{},错误行数:{},证书路径: {}'.
  139. format(uid, repr(e), e.__traceback__.tb_lineno, pem_path))
  140. return False
  141. @staticmethod
  142. def android_fcm_push(nickname, app_bundle_id, token_val, n_time, event_type, msg_title, msg_text,
  143. uid='', channel='1', image=''):
  144. """
  145. android fcm 推送
  146. @param nickname: 设备昵称
  147. @param app_bundle_id: app包id
  148. @param token_val: 推送token
  149. @param n_time: 当前时间
  150. @param event_type: 事件类型
  151. @param msg_title: 推送标题
  152. @param msg_text: 推送内容
  153. @param uid: uid
  154. @param channel: 通道
  155. @param image: 推送图片链接
  156. @return: bool
  157. """
  158. try:
  159. serverKey = FCM_CONFIG[app_bundle_id]
  160. push_service = FCMNotification(api_key=serverKey)
  161. push_data = {'alert': msg_text, 'msg': '', 'zpush': '1', 'image': image,
  162. 'received_at': n_time, 'event_time': n_time, 'event_type': event_type, 'nickname': nickname,
  163. 'uid': uid, 'channel': channel
  164. }
  165. if event_type in DATA_PUSH_EVENT_TYPE_LIST:
  166. push_data['priority'] = 'high'
  167. push_data['content_available'] = True
  168. push_data['direct_boot_ok'] = True
  169. sound = 'android.resource://com.ansjer.zccloud_a/raw/phone_call'
  170. result = push_service.notify_single_device(registration_id=token_val, message_title=msg_title,
  171. message_body=msg_text, data_message=push_data, sound=sound,
  172. android_channel_id='video',
  173. click_action='android.intent.action.VIEW',
  174. extra_kwargs={'default_sound': False,
  175. 'default_vibrate_timings': True,
  176. 'default_light_settings': True,
  177. },
  178. )
  179. else:
  180. result = push_service.notify_single_device(registration_id=token_val, message_title=msg_title,
  181. message_body=msg_text, data_message=push_data,
  182. click_action='android.intent.action.VIEW',
  183. extra_kwargs={'default_sound': True,
  184. 'default_vibrate_timings': True,
  185. 'default_light_settings': True,
  186. },
  187. )
  188. TIME_LOGGER.info('uid:{}fcm推送结果:{}'.format(uid, result))
  189. return True
  190. except Exception as e:
  191. TIME_LOGGER.error('uid:{}fcm推送异常:{}'.format(uid, repr(e)))
  192. return False
  193. @staticmethod
  194. def android_fcm_push_v1(nickname, app_bundle_id, token_val, n_time, event_type, msg_title, msg_text,
  195. uid='', channel='1', image=''):
  196. """
  197. android fcm 推送
  198. @param nickname: 设备昵称
  199. @param app_bundle_id: app包id
  200. @param token_val: 推送token
  201. @param n_time: 当前时间
  202. @param event_type: 事件类型
  203. @param msg_title: 推送标题
  204. @param msg_text: 推送内容
  205. @param uid: uid
  206. @param channel: 通道
  207. @param image: 推送图片链接
  208. @return: bool
  209. """
  210. try:
  211. event_type = str(event_type)
  212. n_time = str(n_time)
  213. # 跳转类型
  214. jump_type = str(CommonService.get_jump_type(event_type))
  215. # 推送数据类型必须为字符串,否则抛ValueError('Message.data must not contain non-string values.')异常
  216. push_data = {'alert': msg_text, 'msg': '', 'sound': 'sound.aif', 'zpush': '1',
  217. 'received_at': n_time, 'event_time': n_time, 'event_type': event_type, 'nickname': nickname,
  218. 'uid': uid, 'channel': channel, 'jump_type': jump_type
  219. }
  220. if event_type in DATA_PUSH_EVENT_TYPE_LIST:
  221. push_data['priority'] = 'high'
  222. push_data['content_available'] = True
  223. push_data['direct_boot_ok'] = True
  224. message = messaging.Message(
  225. notification=messaging.Notification(
  226. title=msg_title,
  227. body=msg_text,
  228. image=image
  229. ),
  230. data=push_data,
  231. token=token_val,
  232. )
  233. # Send a message to the device corresponding to the provided
  234. # registration token.
  235. result = messaging.send(message)
  236. LOGGER.info('uid:{} fcm推送结果:{}'.format(uid, result))
  237. return True
  238. except UnregisteredError as e:
  239. LOGGER.info('uid:{},token:{},fcm推送异常UnregisteredError:{}'.format(uid, token_val, repr(e)))
  240. # 删除失效token数据
  241. UidPushModel.objects.filter(uid_set__uid=uid, token_val=token_val).delete()
  242. except Exception as e:
  243. LOGGER.info('uid:{} fcm推送异常:{}'.format(uid, repr(e)))
  244. return False
  245. @staticmethod
  246. def android_jpush(nickname, app_bundle_id, token_val, n_time, event_type, msg_title, msg_text, channel=1):
  247. """
  248. android 极光 推送
  249. @param nickname: 设备昵称
  250. @param app_bundle_id: app包id
  251. @param token_val: 推送token
  252. @param n_time: 当前时间
  253. @param event_type: 事件类型
  254. @param msg_title: 推送标题
  255. @param msg_text: 推送内容
  256. @param channel: 设备通道
  257. @return: bool
  258. """
  259. try:
  260. # app_key = JPUSH_CONFIG[app_bundle_id]['Key']
  261. # master_secret = JPUSH_CONFIG[app_bundle_id]['Secret']
  262. # # 换成各自的app_key和master_secret
  263. # _jpush = jpush.JPush(app_key, master_secret)
  264. # push = _jpush.create_push()
  265. # push.audience = jpush.registration_id(token_val)
  266. # if event_type in DATA_PUSH_EVENT_TYPE_LIST:
  267. # channel_id = '111934'
  268. # else:
  269. # channel_id = '1'
  270. # push_data = {'alert': msg_text, 'msg': '', 'sound': 'sound.aif', 'zpush': '1', 'uid': nickname,
  271. # 'received_at': n_time, 'event_time': n_time, 'event_type': event_type, 'nickname': nickname,
  272. # 'channel': channel
  273. # }
  274. # android = jpush.android(title=msg_title, big_text=msg_text, alert=msg_text, extras=push_data,
  275. # priority=1, style=1, alert_type=7, channel_id=channel_id
  276. # )
  277. # push.notification = jpush.notification(android=android)
  278. # push.platform = jpush.all_
  279. # res = push.send()
  280. # assert res.status_code == 200
  281. return True
  282. except Exception as e:
  283. LOGGER.info('uid:{},time:{},极光推送异常:{}'.format(nickname, n_time, repr(e)))
  284. return False
  285. @staticmethod
  286. def jpush(nickname, app_bundle_id, token_val, n_time, event_type, msg_title, msg_text, channel=1):
  287. """
  288. android 极光 推送
  289. @param nickname: 设备昵称
  290. @param app_bundle_id: app包id
  291. @param token_val: 推送token
  292. @param n_time: 当前时间
  293. @param event_type: 事件类型
  294. @param msg_title: 推送标题
  295. @param msg_text: 推送内容
  296. @param channel: 设备通道
  297. @return: bool
  298. """
  299. try:
  300. app_key = JPUSH_CONFIG[app_bundle_id]['Key']
  301. master_secret = JPUSH_CONFIG[app_bundle_id]['Secret']
  302. # 换成各自的app_key和master_secret
  303. _jpush = jpush.JPush(app_key, master_secret)
  304. push = _jpush.create_push()
  305. push.audience = jpush.registration_id(token_val)
  306. if event_type in DATA_PUSH_EVENT_TYPE_LIST:
  307. channel_id = '111934'
  308. else:
  309. channel_id = '1'
  310. # 跳转类型
  311. jump_type = CommonService.get_jump_type(event_type)
  312. push_data = {'alert': msg_text, 'msg': '', 'sound': 'sound.aif', 'zpush': '1', 'uid': nickname,
  313. 'received_at': n_time, 'event_time': n_time, 'event_type': event_type, 'nickname': nickname,
  314. 'channel': channel, 'jump_type': jump_type
  315. }
  316. android = jpush.android(title=msg_title, big_text=msg_text, alert=msg_text, extras=push_data,
  317. priority=1, style=1, alert_type=7, channel_id=channel_id
  318. )
  319. push.notification = jpush.notification(android=android)
  320. push.platform = jpush.all_
  321. res = push.send()
  322. assert res.status_code == 200
  323. LOGGER.info('极光推送响应:{}, 参数:{}, 令牌:{}'.format(res, push_data, token_val))
  324. return True
  325. except Exception as e:
  326. LOGGER.info('极光推送异常:{}'.format(repr(e)))
  327. return False
  328. @staticmethod
  329. def android_xmpush(channel_id, nickname, app_bundle_id, token_val, n_time, event_type, msg_title, msg_text,
  330. uid='', channel='1', image=''):
  331. """
  332. android 小米 推送
  333. @param channel_id: 通知通道
  334. @param nickname: 设备昵称
  335. @param app_bundle_id: app包id
  336. @param token_val: 推送token
  337. @param n_time: 当前时间
  338. @param event_type: 事件类型
  339. @param msg_title: 推送标题
  340. @param msg_text: 推送内容
  341. @param uid: uid
  342. @param channel: 通道
  343. @param image: 推送图片链接
  344. @return: bool
  345. """
  346. try:
  347. url = 'https://api.xmpush.xiaomi.com/v3/message/regid'
  348. app_secret = XMPUSH_CONFIG[app_bundle_id]
  349. # 跳转类型
  350. jump_type = CommonService.get_jump_type(event_type)
  351. data = {
  352. 'title': msg_title,
  353. 'description': msg_text,
  354. 'payload': 'payload',
  355. 'restricted_package_name': app_bundle_id,
  356. 'registration_id': token_val,
  357. 'extra.channel_id': channel_id,
  358. 'extra.alert': msg_text,
  359. 'extra.msg': '',
  360. 'extra.sound': 'sound.aif',
  361. 'extra.zpush': '1',
  362. 'extra.received_at': n_time,
  363. 'extra.event_time': n_time,
  364. 'extra.event_type': event_type,
  365. 'extra.nickname': nickname,
  366. 'extra.uid': uid,
  367. 'extra.channel': channel,
  368. 'extra.jump_type': jump_type
  369. }
  370. # if image:
  371. # data['extra.notification_style_type'] = 2
  372. # data['extra.notification_bigPic_uri'] = image
  373. headers = {
  374. 'Authorization': 'key={}'.format(app_secret)
  375. }
  376. response = requests.post(url, data=data, headers=headers)
  377. LOGGER.info("小米推送返回值:{}".format(response.json()))
  378. assert response.status_code == 200
  379. return True
  380. except Exception as e:
  381. LOGGER.info("小米推送异常:{}".format(repr(e)))
  382. return False
  383. @staticmethod
  384. def android_vivopush(token_val, n_time, event_type, msg_title, msg_text, app_bundle_id='', uid='', channel='1',
  385. image='', nickname='', appBundleId='', jg_token_val=''):
  386. """
  387. vivo 推送(不支持图片)
  388. @param app_bundle_id: app包名
  389. @param appBundleId: app包名
  390. @param token_val: 推送token
  391. @param jg_token_val: 极光推送token
  392. @param event_type: 事件类型
  393. @param msg_title: 推送标题
  394. @param msg_text: 推送内容
  395. @param n_time: 当前时间
  396. @param nickname: 设备昵称
  397. @param uid: uid
  398. @param image: 推送图片链接
  399. @param channel: 通道
  400. @return: bool
  401. """
  402. try:
  403. app_bundle_id = app_bundle_id if app_bundle_id != '' else appBundleId
  404. # 获取redis里面的authToken
  405. if msg_title == '':
  406. msg_title = APP_BUNDLE_DICT[app_bundle_id]
  407. app_id = VIVOPUSH_CONFIG[app_bundle_id]['ID']
  408. app_key = VIVOPUSH_CONFIG[app_bundle_id]['Key']
  409. app_secret = VIVOPUSH_CONFIG[app_bundle_id]['Secret']
  410. sender = APISender(app_secret)
  411. rec = sender.get_token(app_id, app_key)
  412. # 鉴权接口调用获得authToken
  413. sender_send = APISender(app_secret)
  414. sender_send.set_token(rec['authToken'])
  415. # 跳转类型
  416. jump_type = CommonService.get_jump_type(event_type)
  417. push_data = {'alert': msg_text, 'msg': '', 'sound': 'sound.aif', 'zpush': '1', 'image': image,
  418. 'received_at': n_time, 'event_time': n_time, 'event_type': event_type, 'nickname': nickname,
  419. 'uid': uid, 'channel': channel, 'jump_type': jump_type
  420. }
  421. # 获取唯一标识符
  422. uid_push_qs = UidPushModel.objects.filter(token_val=token_val).values('m_code')
  423. m_code = uid_push_qs[0]['m_code'] if uid_push_qs[0]['m_code'] else ''
  424. # 推送 push_mode: 推送模式 (0:正式推送;1:测试推送,默认为0)
  425. # 推送 event_type: 消息类型 (0:运营类消息,1:系统类消息。默认为 0)
  426. # 推送 skip_type: 跳转类型(1:打开 APP 首页 2:打开链接 3:自定义 4:打开 app 内指定页面)
  427. activity = 'vpushscheme://com.vivo.pushvideo/detail'
  428. message = PushMessage() \
  429. .reg_id(token_val) \
  430. .title(msg_title) \
  431. .content(msg_text) \
  432. .push_mode(0) \
  433. .notify_type(3) \
  434. .skip_type(4) \
  435. .skip_content(activity) \
  436. .request_id(m_code) \
  437. .classification(1) \
  438. .client_custom_map(**push_data) \
  439. .message_dict()
  440. rec = sender_send.send(message)
  441. LOGGER.info('vivo推送结果:{}, 设备uid:{}'.format(rec, uid))
  442. if rec['result'] == 0 and event_type in DATA_PUSH_EVENT_TYPE_LIST:
  443. PushObject.jpush_transparent_transmission(msg_title, msg_text, app_bundle_id, jg_token_val, push_data)
  444. return True
  445. except Exception as e:
  446. LOGGER.error('vivo推送异常,uid:{},error_line:{},error_msg:{}'.
  447. format(uid, e.__traceback__.tb_lineno, repr(e)))
  448. return False
  449. @staticmethod
  450. def android_oppopush(channel_id, nickname, app_bundle_id, token_val, n_time, event_type, msg_title, msg_text,
  451. uid='', channel='1', image='', jg_token_val=''):
  452. """
  453. android oppo 推送
  454. @param channel_id: 通知通道id
  455. @param nickname: 设备昵称
  456. @param app_bundle_id: app包id
  457. @param token_val: 推送token
  458. @param jg_token_val: 推送token
  459. @param n_time: 当前时间
  460. @param event_type: 事件类型
  461. @param msg_title: 推送标题
  462. @param msg_text: 推送内容
  463. @param uid: uid
  464. @param channel: 通道
  465. @param image: 推送图片链接
  466. @return: bool
  467. """
  468. try:
  469. """
  470. android 国内oppo APP消息提醒推送
  471. """
  472. app_key = OPPOPUSH_CONFIG[app_bundle_id]['Key']
  473. master_secret = OPPOPUSH_CONFIG[app_bundle_id]['Secret']
  474. url = 'https://api.push.oppomobile.com/'
  475. now_time = str(round(time.time() * 1000))
  476. # 1、实例化一个sha256对象
  477. sha256 = hashlib.sha256()
  478. # 2、调用update方法进行加密
  479. sha256.update((app_key + now_time + master_secret).encode('utf-8'))
  480. # 3、调用hexdigest方法,获取加密结果
  481. sign = sha256.hexdigest()
  482. # 获取auth_token
  483. get_token_url = url + 'server/v1/auth'
  484. post_data = {
  485. 'app_key': app_key,
  486. 'sign': sign,
  487. 'timestamp': now_time
  488. }
  489. headers = {'Content-Type': 'application/x-www-form-urlencoded'}
  490. response = requests.post(get_token_url, data=post_data, headers=headers)
  491. result = response.json()
  492. # 发送推送
  493. push_url = url + 'server/v1/message/notification/unicast'
  494. extra_data = {'alert': msg_text, 'msg': '', 'sound': 'sound.aif', 'zpush': '1',
  495. 'received_at': n_time, 'event_time': n_time, 'event_type': event_type, 'nickname': nickname,
  496. 'uid': uid, 'channel': channel
  497. }
  498. message = {
  499. "target_type": 2,
  500. "target_value": token_val,
  501. "notification": {
  502. "title": msg_title,
  503. "content": msg_text,
  504. 'channel_id': channel_id,
  505. 'action_parameters': extra_data,
  506. 'click_action_type': 1,
  507. 'click_action_activity': OPPOPUSH_CONFIG[app_bundle_id]['click_action_activity']
  508. }
  509. }
  510. push_data = {
  511. 'auth_token': result['data']['auth_token'],
  512. 'message': json.dumps(message)
  513. }
  514. response = requests.post(push_url, data=push_data, headers=headers)
  515. LOGGER.info("oppo推送返回值:{}".format(response.json()))
  516. if response.status_code == 200 and event_type in DATA_PUSH_EVENT_TYPE_LIST:
  517. PushObject.jpush_transparent_transmission(msg_title, msg_text, app_bundle_id, jg_token_val, extra_data)
  518. return True
  519. except Exception as e:
  520. LOGGER.info("oppo推送异常:{}".format(repr(e)))
  521. return False
  522. @staticmethod
  523. def android_meizupush(token_val, n_time, event_type, msg_title, msg_text, uid='', channel='1',
  524. app_bundle_id='', appBundleId='', nickname='', image=''):
  525. """
  526. android 魅族推送(不支持图片)
  527. @param app_bundle_id: app包名
  528. @param appBundleId: app包名
  529. @param token_val: 推送token
  530. @param event_type: 消息类型 (0:运营类消息,1:系统类消息。默认为 0)
  531. @param msg_title: 推送标题
  532. @param msg_text: 推送内容
  533. @param n_time: 当前时间
  534. @param nickname: 设备昵称
  535. @param uid: uid
  536. @param image: 推送图片链接
  537. @param channel: 通道
  538. @return: bool
  539. """
  540. try:
  541. # 获取包和AppSecret
  542. app_bundle_id = app_bundle_id if app_bundle_id != '' else appBundleId
  543. appId = MEIZUPUSH_CONFIG[app_bundle_id]['ID']
  544. appSecret = MEIZUPUSH_CONFIG[app_bundle_id]['AppSecret']
  545. url = 'https://server-api-push.meizu.com/garcia/api/server/push/varnished/pushByPushId'
  546. # 跳转类型
  547. jump_type = CommonService.get_jump_type(event_type)
  548. extra_data = {'alert': msg_text, 'msg': '', 'sound': 'sound.aif', 'zpush': '1',
  549. 'received_at': n_time, 'event_time': n_time, 'event_type': event_type, 'nickname': nickname,
  550. 'uid': uid, 'channel': channel, 'jump_type': jump_type
  551. }
  552. # 转换为json格式
  553. extra_data = json.dumps(extra_data)
  554. if msg_title == '':
  555. msg_title = APP_BUNDLE_DICT[app_bundle_id]
  556. # 拼接发送内容
  557. activity = MEIZUPUSH_CONFIG[app_bundle_id]['click_action_activity']
  558. # clickType点击动作, 0打开应用, 1打开应用页面, 2打开url页面, 3应用客户端自定义
  559. messageJson = '{"clickTypeInfo": {"activity": "%s",' \
  560. '"clickType": 1, "parameters": %s },"extra": {},' % (activity, extra_data)
  561. noticeBarInfo = ('"noticeBarInfo": {"title": "%s", "content": "%s"},' % (msg_title, msg_text))
  562. noticeExpandInfo = '"noticeExpandInfo": {"noticeExpandType": 0}, "pushTimeInfo": {"validTime": 24}}'
  563. messageJson += noticeBarInfo
  564. messageJson += noticeExpandInfo
  565. data_meizu = {
  566. 'appId': appId,
  567. 'pushIds': token_val,
  568. 'messageJson': messageJson
  569. }
  570. # 魅族MD5加密,生成密钥
  571. sign = CommonService.getMD5Sign(data=data_meizu, key=appSecret)
  572. data = {
  573. 'appId': appId,
  574. 'messageJson': messageJson,
  575. 'sign': sign,
  576. 'pushIds': token_val,
  577. }
  578. # 进行推送
  579. response = requests.post(url, data=data)
  580. LOGGER.info("uid:{},time:{},魅族推送结果:{}".format(uid, n_time, response.json()))
  581. return True
  582. except Exception as e:
  583. LOGGER.info("uid:{},time:{},魅族推送异常:{}".format(uid, n_time, repr(e)))
  584. return False
  585. @staticmethod
  586. def android_honorpush(token_val, n_time, event_type, msg_title, msg_text,
  587. uid='', channel='1', image='', app_bundle_id='', appBundleId='', channel_id='', nickname=''):
  588. """
  589. android honor 推送
  590. @param channel_id: 通知通道id
  591. @param nickname: 设备昵称
  592. @param app_bundle_id: app包id
  593. @param appBundleId: app包id
  594. @param token_val: 推送token
  595. @param n_time: 当前时间
  596. @param event_type: 事件类型
  597. @param msg_title: 推送标题
  598. @param msg_text: 推送内容
  599. @param uid: uid
  600. @param channel: 通道
  601. @param image: 推送图片链接
  602. @return: bool
  603. """
  604. app_bundle_id = appBundleId if appBundleId else app_bundle_id
  605. try:
  606. client_id = HONORPUSH_CONFIG[app_bundle_id]['client_id']
  607. client_secret = HONORPUSH_CONFIG[app_bundle_id]['client_secret']
  608. app_id = HONORPUSH_CONFIG[app_bundle_id]['app_id']
  609. get_access_token_url = 'https://iam.developer.hihonor.com/auth/token'
  610. post_data = {
  611. 'grant_type': 'client_credentials',
  612. 'client_id': client_id,
  613. 'client_secret': client_secret
  614. }
  615. headers = {'Content-Type': 'application/x-www-form-urlencoded'}
  616. access_token_response = requests.post(get_access_token_url, data=post_data, headers=headers)
  617. access_result = access_token_response.json()
  618. authorization_token = 'Bearer ' + access_result['access_token']
  619. # 发送推送
  620. push_url = 'https://push-api.cloud.hihonor.com/api/v1/{}/sendMessage'.format(app_id)
  621. headers = {'Content-Type': 'application/json', 'Authorization': authorization_token,
  622. 'timestamp': str(int(time.time()) * 1000)}
  623. # 跳转类型
  624. jump_type = CommonService.get_jump_type(event_type)
  625. extra_data = {'alert': msg_text, 'msg': '', 'sound': 'sound.aif', 'zpush': '1',
  626. 'received_at': n_time, 'event_time': n_time, 'event_type': str(event_type),
  627. 'nickname': nickname, 'uid': uid, 'channel': channel, 'title': msg_title, 'body': msg_text,
  628. 'jump_type': jump_type
  629. }
  630. # 通知推送
  631. push_data = {
  632. "android": {
  633. "notification": {
  634. "body": msg_text,
  635. "title": msg_title,
  636. "importance": "NORMAL",
  637. "clickAction": {
  638. "type": 3
  639. }
  640. },
  641. "targetUserType": 0,
  642. "data": json.dumps(extra_data)
  643. },
  644. "token": [token_val]
  645. }
  646. response = requests.post(push_url, json=push_data, headers=headers)
  647. LOGGER.info("uid:{},时间:{},荣耀推送通知返回值:{}".format(uid, n_time, response.json()))
  648. # 一键通话透传推送
  649. if int(event_type) in DATA_PUSH_EVENT_TYPE_LIST:
  650. push_data = {
  651. "data": json.dumps(extra_data),
  652. "token": [token_val]
  653. }
  654. response = requests.post(push_url, json=push_data, headers=headers)
  655. LOGGER.info("uid:{},时间:{},荣耀透传推送返回值:{}".format(uid, n_time, response.json()))
  656. return True
  657. except Exception as e:
  658. LOGGER.info("荣耀推送异常:error_line:{},error_msg:{}".format(e.__traceback__.tb_lineno, repr(e)))
  659. return False
  660. @staticmethod
  661. def jpush_transparent_transmission(msg_title, msg_text, app_bundle_id, token_val, extra_data):
  662. """
  663. android 极光透传
  664. @param msg_title: 推送标题
  665. @param msg_text: 推送内容
  666. @param token_val: 推送token
  667. @param app_bundle_id: app包id
  668. @param extra_data: 额外数据
  669. @return: None
  670. """
  671. try:
  672. app_key = JPUSH_CONFIG[app_bundle_id]['Key']
  673. master_secret = JPUSH_CONFIG[app_bundle_id]['Secret']
  674. # 换成各自的app_key和master_secret
  675. _jpush = jpush.JPush(app_key, master_secret)
  676. push = _jpush.create_push()
  677. push.audience = jpush.registration_id(token_val)
  678. push.message = jpush.message(msg_content=msg_text, title=msg_title, extras=extra_data)
  679. push.platform = jpush.all_
  680. res = push.send()
  681. LOGGER.info('极光透传,结果:{},参数:{},令牌:{}'.format(res, extra_data, token_val))
  682. except Exception as e:
  683. LOGGER.info('jpush_transparent_transmission极光透传异常:errLine:{}, errMsg:{}, 参数:{}'.format(
  684. e.__traceback__.tb_lineno, repr(e), extra_data))