platform_order_api_util.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. __title__ = '各个平台的订单API接口'
  5. @Time : 2020/9/30 12:33
  6. @Author : Kenny-PC
  7. @Software: PyCharm
  8. # code is far away from bugs with the god animal protecting
  9. I love animals. They taste delicious.
  10. ┏┓ ┏┓
  11. ┏┛┻━━━┛┻┓
  12. ┃ ☃ ┃
  13. ┃ ┳┛ ┗┳ ┃
  14. ┃ ┻ ┃
  15. ┗━┓ ┏━┛
  16. ┃ ┗━━━┓
  17. ┃ 神兽保佑 ┣┓
  18. ┃ 永无BUG! ┏┛
  19. ┗┓┓┏━┳┓┏┛
  20. ┃┫┫ ┃┫┫
  21. ┗┻┛ ┗┻┛
  22. """
  23. import datetime
  24. import hashlib
  25. import math
  26. import time
  27. from concurrent.futures import ProcessPoolExecutor
  28. from urllib import parse
  29. import requests
  30. from util import date_util
  31. from util import platform_config_util
  32. from util import robust_util
  33. # md5加密,使用utf-8编码
  34. def md5(s):
  35. md5 = hashlib.md5()
  36. md5.update(s.encode("utf-8"))
  37. return md5.hexdigest()
  38. ## sha1加密,使用utf-8编码
  39. def sha1(s):
  40. sha1 = hashlib.sha1()
  41. sha1.update(s.encode("utf-8"))
  42. return sha1.hexdigest()
  43. # 阅文
  44. @robust_util.catch_exception
  45. def get_yuewen_order(st, et, account_list):
  46. start_exec_seconds = date_util.getCurrentSecondTime()
  47. total_order_list = ()
  48. #account_list = platform_config_util.get_yuewen_account_list()
  49. executor = ProcessPoolExecutor(max_workers=5)
  50. futures = []
  51. for account in account_list:
  52. future = executor.submit(get_yuewen_order_task, st, et, account)
  53. futures.append(future)
  54. executor.shutdown(True)
  55. for future in futures:
  56. order_list = future.result()
  57. if len(order_list) > 0:
  58. total_order_list = order_list + total_order_list
  59. print('阅文订单数量:', len(total_order_list), '执行时长(秒):', date_util.getCurrentSecondTime() - start_exec_seconds)
  60. return total_order_list
  61. def get_yuewen_order_task(st, et, account):
  62. order_list = ()
  63. email = account[0]
  64. appsecert = account[1]
  65. url = 'https://open.yuewen.com/cpapi/wxRecharge/querychargelog'
  66. version = 1
  67. order_status = 2 # 已支付
  68. page_count = 100 # 每页100条数据
  69. start_time = st
  70. for i in range((et - st) // 86400 + 1):
  71. page = 1
  72. last_min_id = ''
  73. last_max_id = ''
  74. total_count = ''
  75. last_page = ''
  76. while True:
  77. if start_time == et:
  78. break
  79. end_time = min(start_time + 86400, et)
  80. timestamp = int(time.time())
  81. params = {
  82. 'email': email,
  83. 'version': version,
  84. 'timestamp': timestamp,
  85. 'start_time': start_time,
  86. 'end_time': end_time,
  87. 'page': page,
  88. 'order_status': order_status
  89. }
  90. if page > 1:
  91. params['last_min_id'] = last_min_id
  92. params['last_max_id'] = last_max_id
  93. params['total_count'] = total_count
  94. params['last_page'] = last_page
  95. sorted_data = sorted(params.items())
  96. str_params = ''
  97. for k, v in sorted_data:
  98. str_params = str_params + str(k) + str(v)
  99. sign = md5(appsecert + str_params).upper()
  100. # 放入签名
  101. params['sign'] = sign
  102. response_result_json = requests.get(url=url, params=params).json()
  103. code = response_result_json['code']
  104. ## 此接口有调用频率限制,相同查询条件每分钟仅能请求一次
  105. if code != 0:
  106. print('阅文查询充值接口异常:', response_result_json, '参数', params)
  107. break
  108. response_data = response_result_json['data']
  109. total_count = response_data['total_count']
  110. if total_count == 0:
  111. continue
  112. last_min_id = response_data['min_id']
  113. last_max_id = response_data['max_id']
  114. last_page = response_data['page']
  115. order_item_list = response_data['list']
  116. for order_item in order_item_list:
  117. order_time = order_item['order_time']
  118. dtime = datetime.datetime.strptime(order_time, "%Y-%m-%d %H:%M:%S")
  119. order_time_unix = int(time.mktime(dtime.timetuple()))
  120. order_id = order_item['order_id']
  121. order = {}
  122. order['platform'] = '阅文'
  123. order['channel'] = order_item['app_name']
  124. order['from_novel'] = order_item['book_name']
  125. order['user_id'] = order_item['openid']
  126. order['stage'] = ''
  127. order['channel_id'] = 0
  128. order['order_time'] = order_time
  129. order['amount'] = order_item['amount']
  130. order['reg_time'] = order_item['reg_time']
  131. order['order_id'] = order_id
  132. # print(order_time)
  133. order['date'] =int(time.mktime(time.strptime(order_time[:10],'%Y-%m-%d')))
  134. order = sorted(order.items(), key=lambda item: item[0])
  135. order = dict(order)
  136. order = tuple(order.values())
  137. order_list = order_list + ((order),)
  138. if int(page) >= math.ceil(total_count / int(page_count)):
  139. break
  140. page = page + 1
  141. start_time = start_time + 86400 # 天数加1
  142. return order_list
  143. # 掌读
  144. @robust_util.catch_exception
  145. def get_zhangdu_order(st, et, account_list):
  146. start_exec_seconds = date_util.getCurrentSecondTime()
  147. total_order_list = ()
  148. #account_list = platform_config_util.get_zhangdu_account_list()
  149. executor = ProcessPoolExecutor(max_workers=5)
  150. futures = []
  151. for account in account_list:
  152. future = executor.submit(get_zhangdu_order_task, st, et, account)
  153. futures.append(future)
  154. executor.shutdown(True)
  155. for future in futures:
  156. order_list = future.result()
  157. if len(order_list) > 0:
  158. total_order_list = order_list + total_order_list
  159. print('掌读订单数量:', len(total_order_list), '执行时长(秒):', date_util.getCurrentSecondTime() - start_exec_seconds)
  160. return total_order_list
  161. def get_zhangdu_order_task(st, et, account):
  162. order_list = ()
  163. url = 'https://api.zhangdu520.com/channel/getorder'
  164. uid = account[0]
  165. appsecert = account[1]
  166. channel = account[2]
  167. timestamp = int(time.time())
  168. sign = md5(str(uid) + '&' + appsecert + '&' + str(timestamp))
  169. starttime = st
  170. timespace = 90 * 3600 * 24
  171. endtime = min(et, st + timespace)
  172. for x in range((et - st) // timespace + 1): # 分时段
  173. if x > 0:
  174. print('掌读跨天数查询:', x)
  175. page = 1
  176. while True:
  177. params = {
  178. 'uid': uid,
  179. 'timestamp': timestamp,
  180. 'sign': sign,
  181. 'starttime': starttime,
  182. 'endtime': endtime,
  183. 'page': page
  184. }
  185. response_result_json = requests.get(url=url, params=params).json()
  186. if 'data' not in response_result_json.keys():
  187. print('掌读账号【{key}】, 查询时间【{start_time} - {end_time}】,本次请求数据异常,响应报文【{result}】'
  188. .format(key=uid, start_time=date_util.getSecondsToDatetime(starttime),
  189. end_time=date_util.getSecondsToDatetime(endtime), result=response_result_json))
  190. break
  191. result_data = response_result_json['data']
  192. page_count = result_data['pageCount']
  193. if page_count == 0:
  194. break
  195. order_item_list = result_data['list']
  196. for order_item in order_item_list:
  197. if order_item['status'] != '1':#1为已支付
  198. continue
  199. order = {}
  200. order['amount'] = order_item['amount']
  201. order['channel_id'] = uid
  202. order['order_id'] = str(order_item['orderno'])
  203. order['order_time']=order_item['ctime']
  204. # order['order_time'] = date_util.stamp_to_str(int(order_item['ctime']))
  205. order['user_id'] = order_item['openid']
  206. order['platform'] = '掌读'
  207. order['channel'] = channel
  208. order['reg_time']=order_item['regtime']
  209. # order['reg_time'] = date_util.stamp_to_str(int(order_item['regtime']))
  210. order['from_novel'] = order_item.get('book_entry','')
  211. order['stage'] = ''
  212. order_time=date_util.stamp_to_str(int(order_item['ctime']))
  213. order['date']=int(time.mktime(time.strptime(order_time[:10],'%Y-%m-%d')))
  214. x = sorted(order.items(), key=lambda item: item[0])
  215. x = dict(x)
  216. x = tuple(x.values())
  217. order_list = order_list + ((x),)
  218. if page == page_count: #是最后一页
  219. break
  220. page = page + 1
  221. starttime = starttime + timespace
  222. endtime = min(et, starttime + timespace)
  223. return order_list
  224. # 花生
  225. @robust_util.catch_exception
  226. def get_huasheng_order(st, et, account_list):
  227. start_exec_seconds = date_util.getCurrentSecondTime()
  228. total_order_list = ()
  229. #account_list = platform_config_util.get_huasheng_account_list()
  230. executor = ProcessPoolExecutor(max_workers=5)
  231. futures = []
  232. for account in account_list:
  233. url = 'https://vip.rlcps.cn/api/getMerchants'
  234. apiKey = str(account[0])
  235. apiSecurity = account[1]
  236. timestamp = str(int(time.time()))
  237. sign = md5(apiKey + timestamp + apiSecurity).upper()
  238. params = {
  239. 'apiKey': apiKey,
  240. 'apiSecurity': apiSecurity,
  241. 'timestamp': timestamp,
  242. 'sign': sign
  243. }
  244. response_result_json = requests.post(url, params).json()
  245. if 'data' not in response_result_json.keys():
  246. print('花生账号【{apiKey}】本次请求数据异常,响应报文【{result}】'.format(apiKey=apiKey, result=response_result_json))
  247. continue
  248. for merchant in response_result_json['data']:
  249. future = executor.submit(get_huasheng_order_task, st, et, account, merchant)
  250. futures.append(future)
  251. executor.shutdown(True)
  252. for future in futures:
  253. order_list = future.result()
  254. if len(order_list) > 0:
  255. total_order_list = order_list + total_order_list
  256. print('花生订单数量:', len(total_order_list), '执行时长(秒):', date_util.getCurrentSecondTime() - start_exec_seconds)
  257. return total_order_list
  258. def get_huasheng_order_task(st, et, account, merchant):
  259. order_list = ()
  260. apiKey = str(account[0])
  261. apiSecurity = account[1]
  262. stage = account[2]
  263. timestamp = str(int(time.time()))
  264. order_url = 'https://vip.rlcps.cn/api/orderList'
  265. merchant_id = merchant['merchant_id']
  266. merchant_name = merchant['merchant_name']
  267. start_time = st
  268. limit = 500
  269. for i in range((et - st) // 86400 + 1):
  270. page = 1
  271. while True:
  272. date = time.strftime("%Y-%m-%d", time.localtime(start_time))
  273. sign = md5(apiKey + date + str(merchant_id) + timestamp + apiSecurity).upper()
  274. order_params = {
  275. 'apiKey': apiKey,
  276. 'apiSecurity': apiSecurity,
  277. 'timestamp': timestamp,
  278. 'date': date,
  279. 'merchant_id': merchant_id,
  280. 'sign': sign,
  281. 'page': page,
  282. 'limit': limit
  283. }
  284. response_result_json = requests.post(order_url, order_params).json()
  285. if 'data' not in response_result_json.keys():
  286. print('花生账号【{key}】, 查询时间【{date}】, 渠道【{merchant_id}:{merchant_name}】本次请求数据异常,响应报文【{result}】'
  287. .format(key=apiKey, date=date, merchant_id=merchant_id, merchant_name=merchant_name,
  288. result=response_result_json))
  289. break
  290. if len(response_result_json['data']) == 0:
  291. break
  292. total_count = response_result_json['count']
  293. order_item_list = response_result_json['data']
  294. for order_item in order_item_list:
  295. if order_item['order_status'] == 1: # 1为已支付
  296. order = {}
  297. order['user_id'] = order_item['openid']
  298. order['order_id'] = order_item['trans_id']
  299. order['order_time'] = order_item['pay_at']
  300. order['reg_time'] = order_item['join_at']
  301. order['channel'] = merchant_name
  302. order['channel_id'] = merchant_id
  303. order['platform'] = '花生'
  304. order['stage'] = stage
  305. order['from_novel'] = order_item['book_name']
  306. order['amount'] = order_item['amount']
  307. order["date"]=int(time.mktime(time.strptime(order_item['pay_at'][:10],"%Y-%m-%d")))
  308. order = sorted(order.items(), key=lambda item: item[0])
  309. order = dict(order)
  310. order = tuple(order.values())
  311. order_list = order_list + ((order),)
  312. if int(page) >= math.ceil(total_count / int(limit)):
  313. break
  314. page = page + 1
  315. start_time = start_time + 86400 # 天数加1
  316. return order_list
  317. # 掌中云
  318. @robust_util.catch_exception
  319. def get_zhangzhongyun_order(st, et, account_list):
  320. start_exec_seconds = date_util.getCurrentSecondTime()
  321. total_order_list = ()
  322. executor = ProcessPoolExecutor(max_workers=5)
  323. futures = []
  324. for account in account_list:
  325. url = 'https://inovel.818tu.com/partners/channel/channels/list?'
  326. key = account[0]
  327. secert = account[1]
  328. sign = md5(secert + 'key=' + key)
  329. params = 'key=' + key + '&sign=' + sign
  330. response_result_json = requests.get(url + params).json() # 获取子渠道列表
  331. if 'data' not in response_result_json.keys():
  332. print('掌中云账号【{key}】本次请求数据异常,响应报文【{result}】'.format(key=key, result=response_result_json))
  333. continue
  334. items = response_result_json['data']['items']
  335. for channel in items:
  336. # 获取channel_id 后逐个拉取历史orders
  337. future = executor.submit(get_zhangzhongyun_order_task, st, et, account, channel)
  338. futures.append(future)
  339. executor.shutdown(True)
  340. for future in futures:
  341. order_list = future.result()
  342. if len(order_list) > 0:
  343. total_order_list = order_list + total_order_list
  344. print('掌中云订单数量:', len(total_order_list), '执行时长(秒):', date_util.getCurrentSecondTime() - start_exec_seconds)
  345. return total_order_list
  346. def get_zhangzhongyun_order_task(st, et, account, channel):
  347. # 掌中云的时间格式比较特殊,转换下
  348. get_time=datetime.datetime.strptime(date_util.stamp_to_str(st),"%Y-%m-%d %H:%M:%S").strftime("%Y-%m-%dT%H:%M:%S+08:00")
  349. limit_time=datetime.datetime.strptime(date_util.stamp_to_str(et),"%Y-%m-%d %H:%M:%S").strftime("%Y-%m-%dT%H:%M:%S+08:00")
  350. order_list = ()
  351. key = account[0]
  352. secert = account[1]
  353. stage = account[2]
  354. order_url = 'https://openapi.818tu.com/partners/channel/orders/list?'
  355. channel_id = channel['id']
  356. channel_name = channel['nickname']
  357. status = str(1)
  358. page = str(1)
  359. per_page = str(1000)
  360. gte = parse.urlencode({'created_at[gte]': get_time}) # gte就是ge 大于等于开始时间
  361. lt = parse.urlencode({'created_at[lt]': limit_time}) # 小于 结束时间
  362. while True:
  363. sign = md5(secert + 'channel_id=' + str(
  364. channel_id) + '&created_at[gte]=' + get_time + '&created_at[lt]=' + limit_time + '&key=' + key + '&page=' + str(
  365. page) + '&per_page=' + per_page + '&status=' + status)
  366. params = 'channel_id=' + str(channel_id) + '&' + gte + '&' + lt + '&page=' + str(
  367. page) + '&per_page=' + per_page + '&status=' + status + '&key=' + key + '&sign=' + sign
  368. response_result_json={}
  369. while True:
  370. r = requests.get(order_url + params)
  371. if r.status_code==200:
  372. response_result_json = r.json()
  373. break
  374. else:
  375. time.sleep(1)
  376. print("掌中云接口调用sleep 1s...")
  377. if 'data' not in response_result_json.keys():
  378. print('掌中云账号【{key}】,查询时间【{start_time} - {end_time}】,渠道【{channel_id}:{channel_name}】本次请求数据异常,响应报文【{result}】'
  379. .format(key=key, start_time=date_util.getSecondsToDatetime(get_time),
  380. end_time=date_util.getSecondsToDatetime(limit_time),channel_id=channel_id, channel_name=channel_name, result=response_result_json))
  381. break
  382. total_count = response_result_json['data']['count'] # 总数量
  383. order_item_list = response_result_json['data']['items'] # 订单列表
  384. for order_item in order_item_list:
  385. order = {}
  386. order['user_id'] = str(order_item['member']['openid'])
  387. order['channel'] = channel_name
  388. order['reg_time']=order_item['member']['created_at']
  389. # order['reg_time'] = datetime.datetime.strptime(order_item['member']['created_at'],"%Y-%m-%dT%H:%M:%S+08:00").strftime("%Y-%m-%d %H:%M:%S")
  390. order['channel_id'] = channel_id
  391. order['amount'] = round(order_item['price'] / 100, 2)
  392. order['order_id'] = str(order_item['id'])
  393. order['order_time']= order_item['created_at']
  394. # order['order_time'] = datetime.datetime.strptime(order_item['created_at'],"%Y-%m-%dT%H:%M:%S+08:00").strftime("%Y-%m-%d %H:%M:%S")
  395. order['platform'] = '掌中云'
  396. order['stage'] = stage
  397. order_time=datetime.datetime.strptime(order_item['created_at'],"%Y-%m-%dT%H:%M:%S+08:00").strftime("%Y-%m-%d %H:%M:%S")
  398. order['date'] =int(time.mktime(time.strptime(order_time[:10],"%Y-%m-%d")))
  399. if str(order_item['from_novel_id']) != 'None':
  400. order['from_novel'] = order_item['from_novel']['title']
  401. else:
  402. order['from_novel'] = 'None'
  403. x = sorted(order.items(), key=lambda item: item[0])
  404. x = dict(x)
  405. x = tuple(x.values())
  406. order_list = order_list + ((x),)
  407. if int(page) >= math.ceil(total_count / int(per_page)):
  408. break
  409. page = int(page) + 1
  410. return order_list
  411. # 悠书阁
  412. @robust_util.catch_exception
  413. def get_youshuge_order(st, et, account_list):
  414. start_exec_seconds = date_util.getCurrentSecondTime()
  415. total_order_list = ()
  416. executor = ProcessPoolExecutor(max_workers=5)
  417. futures = []
  418. for account in account_list:
  419. future = executor.submit(get_youshuge_order_task, st, et, account)
  420. futures.append(future)
  421. executor.shutdown(True)
  422. for future in futures:
  423. order_list = future.result()
  424. if len(order_list) > 0:
  425. total_order_list = order_list + total_order_list
  426. print('悠书阁订单数量:', len(total_order_list), '执行时长(秒):', date_util.getCurrentSecondTime() - start_exec_seconds)
  427. return total_order_list
  428. def get_youshuge_order_task(st, et, account):
  429. # 悠书阁的查询end_date时间必须要大于start_date
  430. start_date, end_date = platform_config_util.get_youshuge_order_query_time(st, et)
  431. order_list = ()
  432. host_name = account[0]
  433. channel_id = int(account[1])
  434. secert_key = account[2]
  435. channel = account[3]
  436. stage = account[4]
  437. url = 'https://novel.youshuge.com/v2/open/orders'
  438. page = 1
  439. timestamp = int(time.time())
  440. while True:
  441. sign = md5('channel_id=' + str(channel_id) + '&end_date=' + end_date + '&host_name=' + host_name + '&page='
  442. + str(page) + '&pay_status=1' + '&start_date=' + start_date + '&time=' + str(timestamp) + '&key=' + secert_key).upper()
  443. params = {
  444. 'sign': sign,
  445. 'host_name': host_name,
  446. 'time': timestamp,
  447. 'channel_id': channel_id,
  448. 'page': page,
  449. 'pay_status': 1,
  450. 'start_date': start_date,
  451. 'end_date': end_date
  452. }
  453. respone = requests.post(url, params)
  454. if respone.status_code == 400:
  455. print('悠书阁订单查询接口respone', respone)
  456. response_result_json = respone.json()
  457. if 'data' not in response_result_json.keys():
  458. print('悠书阁账号【{key}】,查询时间【{start_time} - {end_time}】,渠道【{channel_id}:{channel_name}】本次请求数据异常,响应报文【{result}】'
  459. .format(key=host_name, start_time=start_date, end_time=end_date, channel_id=channel_id, result=response_result_json))
  460. break
  461. order_item_list = response_result_json['data']
  462. if len(order_item_list) == 0:
  463. break
  464. for order_item in order_item_list:
  465. order = {}
  466. order['order_id'] = order_item['order_num']
  467. order['amount'] = round(int(order_item['price']) / 100, 2)
  468. order['order_time'] = order_item['create_time']
  469. order['channel'] = channel
  470. order['from_novel'] = order_item['book_name']
  471. order['stage'] = stage
  472. order['user_id'] = order_item['openid']
  473. order['channel_id'] = channel_id
  474. order['platform'] = '悠书阁'
  475. order['reg_time'] = order_item['reg_time']
  476. order['date']=int(time.mktime(time.strptime(order['order_time'][:10],'%Y-%m-%d')))
  477. order = sorted(order.items(), key=lambda item: item[0])
  478. order = dict(order)
  479. order = tuple(order.values())
  480. order_list = order_list + ((order),)
  481. total_count = order_item_list[0]['count']
  482. if page == total_count:
  483. break
  484. page = page + 1
  485. return order_list
  486. def build_ysg_order_data(channel, channel_id, result_json, stage):
  487. order_list = ()
  488. if 'data' in result_json.keys():
  489. data = result_json['data']
  490. if len(data) > 0:
  491. for x in data:
  492. y = {}
  493. dtime = datetime.datetime.strptime(x['create_time'][0:10], "%Y-%m-%d")
  494. y['date'] = ((int(
  495. time.mktime(dtime.timetuple())) + 8 * 3600) // 86400) * 86400 - 8 * 3600
  496. y['order_id'] = x['order_num']
  497. y['amount'] = round(int(x['price']) / 100, 2)
  498. y['order_time'] = x['create_time']
  499. y['channel'] = channel
  500. y['from_novel'] = x['book_name']
  501. y['stage'] = stage
  502. y['user_id'] = x['openid']
  503. y['channel_id'] = channel_id
  504. y['platform'] = '悠书阁'
  505. y['reg_time'] = x['reg_time']
  506. y = sorted(y.items(), key=lambda item: item[0])
  507. y = dict(y)
  508. y = tuple(y.values())
  509. order_list = order_list + ((y),)
  510. return order_list