platform_order_api_util_new.py 22 KB

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