shakearound.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. # -*- coding: utf-8 -*-
  2. from __future__ import absolute_import, unicode_literals
  3. import time
  4. import datetime
  5. import six
  6. from optionaldict import optionaldict
  7. from library.wechatpy.client.api.base import BaseWeChatAPI
  8. class WeChatShakeAround(BaseWeChatAPI):
  9. API_BASE_URL = 'https://api.weixin.qq.com/'
  10. @classmethod
  11. def _to_timestamp(cls, date):
  12. if isinstance(date, six.string_types):
  13. date = datetime.datetime.strptime(date, '%Y-%m-%d %H:%M:%S')
  14. if isinstance(date, datetime.datetime):
  15. timestamp = int(time.mktime(date.timetuple()))
  16. return timestamp
  17. return int(date)
  18. def apply_device_id(self, quantity, reason, poi_id=None, comment=None):
  19. """
  20. 申请设备ID
  21. 详情请参考
  22. http://mp.weixin.qq.com/wiki/15/b9e012f917e3484b7ed02771156411f3.html
  23. :param quantity: 申请的设备ID的数量,单次新增设备超过500个,需走人工审核流程
  24. :param reason: 申请理由,不超过100个字
  25. :param poi_id: 可选,设备关联的门店ID
  26. :param comment: 可选,备注,不超过15个汉字或30个英文字母
  27. :return: 申请的设备信息
  28. """
  29. data = optionaldict()
  30. data['quantity'] = quantity
  31. data['apply_reason'] = reason
  32. data['poi_id'] = poi_id
  33. data['comment'] = comment
  34. res = self._post(
  35. 'shakearound/device/applyid',
  36. data=data,
  37. result_processor=lambda x: x['data']
  38. )
  39. return res
  40. def update_device(self, device_id=None, uuid=None, major=None,
  41. minor=None, comment=None):
  42. """
  43. 更新设备信息
  44. 详情请参考
  45. http://mp.weixin.qq.com/wiki/15/b9e012f917e3484b7ed02771156411f3.html
  46. :param device_id: 设备编号,若填了UUID、major、minor,则可不填设备编号,若二者都填,则以设备编号为优先
  47. :param uuid: UUID
  48. :param major: major
  49. :param minor: minor
  50. :param comment: 设备的备注信息,不超过15个汉字或30个英文字母。
  51. :return: 返回的 JSON 数据包
  52. """
  53. data = optionaldict()
  54. data['comment'] = comment
  55. data['device_identifier'] = {
  56. 'device_id': device_id,
  57. 'uuid': uuid,
  58. 'major': major,
  59. 'minor': minor
  60. }
  61. return self._post(
  62. 'shakearound/device/update',
  63. data=data
  64. )
  65. def bind_device_location(self, poi_id, device_id=None, uuid=None,
  66. major=None, minor=None):
  67. """
  68. 配置设备与门店的关联关系
  69. 详情请参考
  70. http://mp.weixin.qq.com/wiki/15/b9e012f917e3484b7ed02771156411f3.html
  71. :param poi_id: 待关联的门店ID
  72. :param device_id: 设备编号,若填了UUID、major、minor,则可不填设备编号,若二者都填,则以设备编号为优先
  73. :param uuid: UUID
  74. :param major: major
  75. :param minor: minor
  76. :return: 返回的 JSON 数据包
  77. """
  78. data = optionaldict()
  79. data['poi_id'] = poi_id
  80. data['device_identifier'] = {
  81. 'device_id': device_id,
  82. 'uuid': uuid,
  83. 'major': major,
  84. 'minor': minor
  85. }
  86. return self._post(
  87. 'shakearound/device/bindlocation',
  88. data=data
  89. )
  90. def search_device(self, identifiers=None, apply_id=None,
  91. begin=0, count=10):
  92. """
  93. 查询设备列表
  94. 详情请参考
  95. http://mp.weixin.qq.com/wiki/15/b9e012f917e3484b7ed02771156411f3.html
  96. :param identifiers: 设备 ID 信息列表
  97. :param apply_id: 批次ID,申请设备ID超出500个时所返回批次ID
  98. :param begin: 设备列表的起始索引值
  99. :param count: 待查询的设备个数
  100. :return: 设备列表
  101. """
  102. data = optionaldict()
  103. data['begin'] = begin
  104. data['count'] = count
  105. data['apply_id'] = apply_id
  106. if identifiers:
  107. data['device_identifiers'] = identifiers
  108. res = self._post(
  109. 'shakearound/device/search',
  110. data=data,
  111. result_processor=lambda x: x['data']
  112. )
  113. return res
  114. def add_page(self, title, description, icon_url, page_url, comment=None):
  115. """
  116. 新增页面
  117. 详情请参考
  118. http://mp.weixin.qq.com/wiki/5/6626199ea8757c752046d8e46cf13251.html
  119. :param title: 在摇一摇页面展示的主标题,不超过6个字
  120. :param description: 在摇一摇页面展示的副标题,不超过7个字
  121. :param icon_url: 在摇一摇页面展示的图片。图片需先上传至微信侧服务器,
  122. 用“素材管理-上传图片素材”接口上传图片,返回的图片URL再配置在此处
  123. :param page_url: 跳转链接
  124. :param comment: 可选,页面的备注信息,不超过15个字
  125. :return: 页面信息
  126. """
  127. data = optionaldict()
  128. data['title'] = title
  129. data['description'] = description
  130. data['icon_url'] = icon_url
  131. data['page_url'] = page_url
  132. data['comment'] = comment
  133. res = self._post(
  134. 'shakearound/page/add',
  135. data=data,
  136. result_processor=lambda x: x['data']
  137. )
  138. return res
  139. def update_page(self, page_id, title, description,
  140. icon_url, page_url, comment=None):
  141. """
  142. 编辑页面信息
  143. 详情请参考
  144. http://mp.weixin.qq.com/wiki/5/6626199ea8757c752046d8e46cf13251.html
  145. :param page_id: 摇周边页面唯一ID
  146. :param title: 在摇一摇页面展示的主标题,不超过6个字
  147. :param description: 在摇一摇页面展示的副标题,不超过7个字
  148. :param icon_url: 在摇一摇页面展示的图片。图片需先上传至微信侧服务器,
  149. 用“素材管理-上传图片素材”接口上传图片,返回的图片URL再配置在此处
  150. :param page_url: 跳转链接
  151. :param comment: 可选,页面的备注信息,不超过15个字
  152. :return: 页面信息
  153. """
  154. data = optionaldict()
  155. data['page_id'] = page_id
  156. data['title'] = title
  157. data['description'] = description
  158. data['icon_url'] = icon_url
  159. data['page_url'] = page_url
  160. data['comment'] = comment
  161. res = self._post(
  162. 'shakearound/page/update',
  163. data=data,
  164. result_processor=lambda x: x['data']
  165. )
  166. return res
  167. def search_pages(self, page_ids=None, begin=0, count=10):
  168. """
  169. 查询页面列表
  170. 详情请参考
  171. http://mp.weixin.qq.com/wiki/5/6626199ea8757c752046d8e46cf13251.html
  172. :param page_ids: 指定页面的id列表
  173. :param begin: 页面列表的起始索引值
  174. :param count: 待查询的页面个数
  175. :return: 页面查询结果信息
  176. """
  177. if not page_ids:
  178. data = {
  179. 'type': 2,
  180. 'begin': begin,
  181. 'count': count
  182. }
  183. else:
  184. if not isinstance(page_ids, (tuple, list)):
  185. page_ids = [page_ids]
  186. data = {
  187. 'type': 1,
  188. 'page_ids': page_ids
  189. }
  190. res = self._post(
  191. 'shakearound/page/search',
  192. data=data,
  193. result_processor=lambda x: x['data']
  194. )
  195. return res
  196. def delete_page(self, page_id):
  197. """
  198. 删除页面
  199. 详情请参考
  200. http://mp.weixin.qq.com/wiki/5/6626199ea8757c752046d8e46cf13251.html
  201. :param page_id: 指定页面的id列表
  202. :return: 返回的 JSON 数据包
  203. """
  204. return self._post(
  205. 'shakearound/page/delete',
  206. data={
  207. 'page_id': page_id
  208. }
  209. )
  210. def add_material(self, media_file, media_type='icon'):
  211. """
  212. 上传图片素材
  213. 详情请参考
  214. http://mp.weixin.qq.com/wiki/5/e997428269ff189d8f9a4b9e177be2d9.html
  215. :param media_file: 要上传的文件,一个 File-object
  216. :param media_type: 摇一摇素材类型, 取值为 icon或者 license, 默认 icon.
  217. :return: 上传的素材信息
  218. """
  219. res = self._post(
  220. 'shakearound/material/add',
  221. files={
  222. 'media': media_file
  223. },
  224. params={
  225. 'type': media_type
  226. },
  227. result_processor=lambda x: x['data']
  228. )
  229. return res
  230. def bind_device_pages(self, page_ids, bind, append, device_id=None,
  231. uuid=None, major=None, minor=None):
  232. """
  233. 配置设备与页面的关联关系
  234. 详情请参考
  235. http://mp.weixin.qq.com/wiki/12/c8120214ec0ba08af5dfcc0da1a11400.html
  236. :param page_ids: 待关联的页面列表
  237. :param bind: 关联操作标志位, 0为解除关联关系,1为建立关联关系
  238. :param append: 新增操作标志位, 0为覆盖,1为新增
  239. :param device_id: 设备编号,若填了UUID、major、minor,则可不填设备编号,若二者都填,则以设备编号为优先
  240. :param uuid: UUID
  241. :param major: major
  242. :param minor: minor
  243. :return: 返回的 JSON 数据包
  244. """
  245. if not isinstance(page_ids, (tuple, list)):
  246. page_ids = [page_ids]
  247. data = {
  248. 'page_ids': page_ids,
  249. 'bind': int(bind),
  250. 'append': int(append),
  251. 'device_identifier': {
  252. 'device_id': device_id,
  253. 'uuid': uuid,
  254. 'major': major,
  255. 'minor': minor
  256. }
  257. }
  258. return self._post(
  259. 'shakearound/device/bindpage',
  260. data=data
  261. )
  262. def get_shake_info(self, ticket):
  263. """
  264. 获取摇周边的设备及用户信息
  265. 详情请参考
  266. http://mp.weixin.qq.com/wiki/3/34904a5db3d0ec7bb5306335b8da1faf.html
  267. :param ticket: 摇周边业务的ticket,可在摇到的URL中得到,ticket生效时间为30分钟
  268. :return: 设备及用户信息
  269. """
  270. res = self._post(
  271. 'shakearound/user/getshakeinfo',
  272. data={
  273. 'ticket': ticket
  274. },
  275. result_processor=lambda x: x['data']
  276. )
  277. return res
  278. def get_device_statistics(self, begin_date, end_date, device_id=None,
  279. uuid=None, major=None, minor=None):
  280. """
  281. 以设备为维度的数据统计接口
  282. http://mp.weixin.qq.com/wiki/0/8a24bcacad40fe7ee98d1573cb8a6764.html
  283. :param begin_date: 起始时间,最长时间跨度为30天
  284. :param end_date: 结束时间,最长时间跨度为30天
  285. :param device_id: 设备编号,若填了UUID、major、minor,则可不填设备编号,若二者都填,则以设备编号为优先
  286. :param uuid: UUID
  287. :param major: major
  288. :param minor: minor
  289. """
  290. data = {
  291. 'device_identifier': {
  292. 'device_id': device_id,
  293. 'uuid': uuid,
  294. 'major': major,
  295. 'minor': minor
  296. },
  297. 'begin_date': self._to_timestamp(begin_date),
  298. 'end_date': self._to_timestamp(end_date)
  299. }
  300. res = self._post(
  301. 'shakearound/statistics/device',
  302. data=data,
  303. result_processor=lambda x: x['data']
  304. )
  305. return res
  306. def get_page_statistics(self, page_id, begin_date, end_date):
  307. """
  308. 以页面为维度的数据统计接口
  309. 详情请参考
  310. http://mp.weixin.qq.com/wiki/0/8a24bcacad40fe7ee98d1573cb8a6764.html
  311. :param page_id: 页面 ID
  312. :param begin_date: 起始时间,最长时间跨度为30天
  313. :param end_date: 结束时间,最长时间跨度为30天
  314. :return: 统计数据
  315. """
  316. res = self._post(
  317. 'shakearound/statistics/page',
  318. data={
  319. 'page_id': page_id,
  320. 'begin_date': self._to_timestamp(begin_date),
  321. 'end_date': self._to_timestamp(end_date),
  322. },
  323. result_processor=lambda x: x['data']
  324. )
  325. return res
  326. def get_apply_status(self, apply_id):
  327. """
  328. 查询设备ID申请审核状态
  329. 详情请参考
  330. http://mp.weixin.qq.com/wiki/15/b9e012f917e3484b7ed02771156411f3.html
  331. :param apply_id: 批次ID,申请设备ID时所返回的批次ID
  332. :return: 批次状态信息
  333. """
  334. res = self._post(
  335. 'shakearound/device/applystatus',
  336. data={
  337. 'apply_id': apply_id,
  338. },
  339. result_processor=lambda x: x['data']
  340. )
  341. return res