utils.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. # -*- coding: utf-8 -*-
  2. # Author : Charley
  3. # Python : 3.10.8
  4. # Date : 2025/12/12 16:00
  5. import time
  6. import requests
  7. import json
  8. import random
  9. from loguru import logger
  10. from Crypto.Cipher import AES
  11. from Crypto.Util.Padding import pad, unpad
  12. import base64
  13. def generate_nonce_str(length=32):
  14. """生成随机字符串,对应JS中的s()函数"""
  15. chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678"
  16. return ''.join(random.choice(chars) for _ in range(length))
  17. def generate_random_char():
  18. """生成单个随机字符,对应JS中的c()函数"""
  19. chars = "abcdefghijklmnopqrstuvwxyz0123456789"
  20. return random.choice(chars)
  21. def obfuscate_encrypted_data(encrypted_data):
  22. """对加密数据进行混淆处理,对应JS中的d()函数"""
  23. data_list = list(encrypted_data)
  24. # 在索引3位置插入随机字符
  25. data_list.insert(3, generate_random_char())
  26. # 在索引5位置插入随机字符
  27. data_list.insert(5, generate_random_char())
  28. return ''.join(data_list)
  29. def sort_dict_by_key(data_dict):
  30. """对字典按键排序,对应JS中的a()函数"""
  31. sorted_keys = sorted(data_dict.keys())
  32. sorted_dict = {}
  33. for key in sorted_keys:
  34. sorted_dict[key] = data_dict[key]
  35. return sorted_dict
  36. def aes_encrypt(plaintext: str) -> str:
  37. """
  38. AES ECB 模式加密,PKCS7 填充
  39. """
  40. key = "pSlJACAvYnAgOIlluJgK2F=="
  41. # 将密钥转换为字节(UTF-8编码)
  42. key_bytes = key.encode('utf-8')
  43. # AES 要求密钥长度为 16/24/32 字节
  44. # 如果密钥长度不符合要求,需要调整
  45. # 这里密钥是24字节,符合AES-192的要求
  46. # 创建 AES 加密器(ECB 模式)
  47. cipher = AES.new(key_bytes, AES.MODE_ECB)
  48. # 将明文转换为字节并进行 PKCS7 填充
  49. plaintext_bytes = plaintext.encode('utf-8')
  50. padded_data = pad(plaintext_bytes, AES.block_size)
  51. # 加密
  52. encrypted_bytes = cipher.encrypt(padded_data)
  53. # 返回 Base64 编码的密文
  54. return base64.b64encode(encrypted_bytes).decode('utf-8')
  55. def create_request_data(original_data,nonce_field_name='nonceStr'):
  56. """创建完整的请求数据"""
  57. # 添加必要字段
  58. data_with_fields = original_data.copy()
  59. data_with_fields['time'] = int(time.time() * 1000) # 时间戳
  60. # data_with_fields['nonceStr'] = generate_nonce_str() # 随机字符串
  61. data_with_fields[nonce_field_name] = generate_nonce_str() # 随机字符串
  62. data_with_fields['miniName'] = 'YFSXZF' # 根据环境确定
  63. # data_with_fields = {"miniName":"YFSXZF","nonceStr":"iCxy35dfFNJtQSKcrB8yZsRd7B4p3c2h","orderType":0,"pageNum":6,"pageSize":10,"status":0,"time":1765792372017,"type":1}
  64. # 按键排序
  65. sorted_data = sort_dict_by_key(data_with_fields)
  66. # print(f'sorted_data: {sorted_data}')
  67. # 转换为JSON字符串
  68. json_str = json.dumps(sorted_data, separators=(',', ':'))
  69. # print(f'json_str: {json_str}')
  70. # AES加密
  71. encrypted_data = aes_encrypt(json_str)
  72. # "ssB0tJIFaPpO+oDa/FVfaEedp/7js3I0kaRkoTVblr7ssvn71/Y5zDsys/XxOXoNXP3fNdhJdAymwswqYNCmd/7Fk3GT1+5xowXLd64Z7BErz3v1AZuI7yithKjcFlYbafeUkOXI9LPHdUWc7/m4YWpZI3EhJhhGs322ScFsr/31Lu5TN6M/SQ9mZf8IaaNl2xlI+wr+ADV5zC2nEFxg1A=="
  73. # ssB0tJIFaPpO+oDa/FVfaEedp/7js3I0kaRkoTVblr7ssvn71/Y5zDsys/XxOXoNXP3fNdhJdAymwswqYNCmd/7Fk3GT1+5xowXLd64Z7BErz3v1AZuI7yithKjcFlYbafeUkOXI9LPHdUWc7/m4YWpZI3EhJhhGs322ScFsr/31Lu5TN6M/SQ9mZf8IaaNl2xlI+wr+ADV5zC2nEFxg1A==
  74. # print(f'encrypted_data: {encrypted_data}')
  75. # 混淆处理
  76. final_data = obfuscate_encrypted_data(encrypted_data)
  77. # print(f'final_data: {final_data}')
  78. return final_data
  79. # -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  80. def deobfuscate_encrypted_data(obfuscated_data):
  81. """反混淆处理,移除d()函数插入的随机字符"""
  82. data_list = list(obfuscated_data)
  83. # 先移除索引5位置的字符(后插入的先移除)
  84. del data_list[5]
  85. # 再移除索引3位置的字符
  86. del data_list[3]
  87. return ''.join(data_list)
  88. def aes_decrypt(ciphertext: str) -> str:
  89. """
  90. AES ECB 模式解密,PKCS7 填充
  91. """
  92. key = "pSlJACAvYnAgOIlluJgK2F=="
  93. key_bytes = key.encode('utf-8')
  94. cipher = AES.new(key_bytes, AES.MODE_ECB)
  95. # Base64解码
  96. encrypted_bytes = base64.b64decode(ciphertext)
  97. # 解密
  98. decrypted_padded = cipher.decrypt(encrypted_bytes)
  99. # 移除PKCS7填充
  100. decrypted_data = unpad(decrypted_padded, AES.block_size)
  101. return decrypted_data.decode('utf-8')
  102. def decrypt_request_data(obfuscated_data: str) -> dict:
  103. """解密请求数据,返回明文字典"""
  104. # 1. 反混淆
  105. encrypted_data = deobfuscate_encrypted_data(obfuscated_data)
  106. # 2. AES解密
  107. json_str = aes_decrypt(encrypted_data)
  108. # 3. 解析JSON
  109. return json.loads(json_str)
  110. # ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  111. def get_req():
  112. # 原始数据对象
  113. original_data = {
  114. # "miniName": "YFSXZF",
  115. # "nonceStr": nonce_str,
  116. "orderType": 0,
  117. "pageNum": 1,
  118. "pageSize": 10,
  119. "status": 0,
  120. # "time": timestamp,
  121. "type": 1,
  122. }
  123. # raw_data={"miniName":"YFSXZF","nonceStr":"iCxy35dfFNJtQSKcrB8yZsRd7B4p3c2h","orderType":0,"pageNum":6,"pageSize":10,"status":0,"time":1765792372017,"type":1}
  124. # "{"areaType":1,"awardType":2,"miniName":"YFSXZF","nonceStr":"iXbhcQ53iEJbdcwaC5mjpdbK43GsfxCP","pageNum":1,"pageSize":100,"time":1765949383885}"
  125. request_data = create_request_data(original_data)
  126. headers = {
  127. 'authority': 'wechatapp.ichibankuji.cn',
  128. 'accept': '*/*',
  129. 'accept-language': 'zh-CN,zh;q=0.9',
  130. 'content-type': 'application/json',
  131. 'referer': 'https://servicewechat.com/wxd21e3190b2a44f73/21/page-frame.html',
  132. # 'sec-fetch-dest': 'empty',
  133. # 'sec-fetch-mode': 'cors',
  134. # 'sec-fetch-site': 'cross-site',
  135. # 'terminalos': 'YFSXZF',
  136. 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090c33) XWEB/9129',
  137. 'authorization': 'c3e87jrY!1q!2QwQclRyFVXzctNU6lVSUiF9WkPqIzNPL5YN5P3pxQbmzGDyajASc5BcFFM!2MeZG39B2EPdxesjVngQbw=='
  138. }
  139. payload = {
  140. "da": request_data
  141. }
  142. # 发送POST请求
  143. response = requests.post(
  144. 'https://wechatapp.ichibankuji.cn/wechat/yfs/getSetList',
  145. headers=headers,
  146. json=payload
  147. )
  148. print("响应状态码:", response.status_code)
  149. print("响应内容:", response.text)
  150. def test_getsetlist():
  151. headers = {
  152. "authority": "wechatapp.ichibankuji.cn",
  153. "accept": "*/*",
  154. "accept-language": "zh-CN,zh;q=0.9",
  155. # "authorization": "28380RBWRJQZN9UkYGYXeOZrd2GjFh9eteBx7Rz5rDxG3Tq!1m6vSq7EQTr!2ln2jtcinFZ2D8AuMyCjxckvBV2sRazTA==",
  156. "authorization": "6974cjrY!1q!2QwQclRyFVXzctNU5!2B7lMuGi5lR70PeegsV0vYbrPmb8JQT!2oQDnJG7J0qCJlt3CZC!29Fz8JNmlv3X1Q==",
  157. "content-type": "application/json",
  158. "referer": "https://servicewechat.com/wx57f3ee376518bba9/164/page-frame.html",
  159. "sec-fetch-dest": "empty",
  160. "sec-fetch-mode": "cors",
  161. "sec-fetch-site": "cross-site",
  162. "terminalos": "YFSJJ",
  163. "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090c33) XWEB/9129",
  164. "xweb_xhr": "1"
  165. }
  166. url = "https://wechatapp.ichibankuji.cn/wechat/yfs/getSetList"
  167. raw_data = {
  168. # "miniName": "YFSXZF",
  169. # "nonceStr": nonce_str,
  170. "orderType": 0,
  171. "pageNum": 2,
  172. "pageSize": 10,
  173. "areaType": 2,
  174. # "time": timestamp,
  175. "type": 1,
  176. }
  177. resp = requests.post(url, headers=headers, json=raw_data)
  178. print(resp.text)
  179. print(resp)
  180. def test_boxdetail():
  181. headers = {
  182. "authority": "wechatapp.ichibankuji.cn",
  183. "accept": "*/*",
  184. "accept-language": "zh-CN,zh;q=0.9",
  185. "authorization": "7d04b7ZDRB9Vb65wzF4G6!1xyVJssI4IR!1zre6RpycuTj2sZm3Fi8UAH6MWYSwNXxKdjcSYJ3sHeZm!1bVUMVa2A295TA==",
  186. "content-type": "application/json",
  187. "referer": "https://servicewechat.com/wxd21e3190b2a44f73/21/page-frame.html",
  188. "sec-fetch-dest": "empty",
  189. "sec-fetch-mode": "cors",
  190. "sec-fetch-site": "cross-site",
  191. "terminalos": "YFSXZF",
  192. "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090c33) XWEB/9129",
  193. "xweb_xhr": "1"
  194. }
  195. url = "https://wechatapp.ichibankuji.cn/wechat/yfs/firstBoxDetail"
  196. # data = {
  197. # "da": "ssB20vtJIFaPpO+oDa/FVfaEedp/7js3I0kaRkoTVblr7XIZ7YGVs8AcEOmSfhlz/+5BiZQXv6PS329MWxHrSbuhLwwyqZfHGNqP2CKzweRzmqwL/nj2D3zd8Su96eyrCx+0+4Q/6jBhNNiRg8eaW3E9Y+5PmRdyItuydMbDWc5uA="
  198. # }
  199. """
  200. "{"miniName":"YFSXZF","nonceStr":"eNjXXEYNNHiji3BCy6m8PFs7eBneZ6fB","queueMode":2,"setId":"9882","time":1765963408861}"
  201. "{"boxId":84301,"commentId":0,"miniName":"YFSXZF","nonceStr":"64PZEyTKQsC6cX8FWNKcAZ2Zr8QAEk7T","startTime":"","time":1765963457147}"
  202. "{"buyNum":80,"miniName":"YFSXZF","nonceStr":"EkjQQkSYarsWdjykFjAraQ2SXMmmXEPJ","pageNum":1,"pageSize":100,"productId":9882,"time":1765963504672,"type":1}"
  203. """
  204. original_data = {
  205. "queueMode": 2,
  206. "setId": "9882"
  207. }
  208. request_data = create_request_data(original_data)
  209. payload = {
  210. "da": request_data
  211. }
  212. response = requests.post(url, headers=headers, json=payload)
  213. print(response.text)
  214. print(response)
  215. def test_draw():
  216. headers = {
  217. "authority": "wechatapp.ichibankuji.cn",
  218. "accept": "*/*",
  219. "accept-language": "zh-CN,zh;q=0.9",
  220. # "authorization": "7d04b7ZDRB9Vb65wzF4G6!1xyVJssI4IR!1zre6RpycuTj2sZm3Fi8UAH6MWYSwNXxKdjcSYJ3sHeZm!1bVUMVa2A295TA==",
  221. "content-type": "application/json",
  222. "referer": "https://servicewechat.com/wxd21e3190b2a44f73/21/page-frame.html",
  223. "sec-fetch-dest": "empty",
  224. "sec-fetch-mode": "cors",
  225. "sec-fetch-site": "cross-site",
  226. "terminalos": "YFSXZF",
  227. "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090c33) XWEB/9129",
  228. "xweb_xhr": "1"
  229. }
  230. url = "https://wechatapp.ichibankuji.cn/wechat/yfs/getBoxDrawLog"
  231. # data = {
  232. # "da": "uO9f53IZgBHpi/l7iN2eu3MfwMsBfYtK0eJTXuKAii4+3zCldZE24R/vWUbRFLfvwdm5QCsWJ5pSEq7f48nPOIfhaST5NZn2H3uJSbj/tcC/cXI5He79UNx2uULpFXxLhP6iVhvKmUuxt9bpZ8TzSIw/bAZNaSXafp5GgWORhDTMx/YBnhZGrFp345Y32X7Qpw"
  233. # }
  234. original_data = {
  235. "boxId": 84301,
  236. "pageSize": 30,
  237. "isMine": 0,
  238. "pageNum": 1
  239. }
  240. """
  241. "{"boxId":84301,"commentId":0,"miniName":"YFSXZF","nonceStr":"RRxbFkS66F4saYPMwJPDn5pswCfCfHeY","startTime":"2025-12-17 17:25:04","time":1765963725767}"
  242. "{"boxId":84301,"isMine":0,"miniName":"YFSXZF","nonceStr":"7sfHGRhdwp23bndHKzbBR67RG2EP4pxR","pageNum":1,"pageSize":30,"time":1765963927009}"
  243. """
  244. request_data = create_request_data(original_data)
  245. payload = {
  246. "da": request_data
  247. }
  248. response = requests.post(url, headers=headers, json=payload)
  249. print(response.text)
  250. print(response)
  251. # 示例使用
  252. if __name__ == "__main__":
  253. # get_req()
  254. # test_boxdetail()
  255. test_draw()
  256. # test_getsetlist()
  257. # en_data = {"miniName": "YFSJJ", "nonceStr": "Rmn4Ee8WajfDimtfCTPhRfGmGrp7pXrB", "orderType": 0, "pageNum": 2, "pageSize": 10, "status": 0, "time": 1765524424213, "type": 1}
  258. # generate_sign(en_data)
  259. # 404a70c1316dd2b0b234d6cb5d25d8c3
  260. # y = "ssB0tJIFaPpO+oDa/FVfaEedp/7js3I0kaRkoTVblr58IvkiE/orkJbZG+zg/g+fqP+J6wOBxsxo3+xBbc3J10pvq0el2y2mnxWMDL8TlBnNRnLu5l2SsmKM/C8QFg16"
  261. # print(d(y))
  262. # "ssBp0ntJIFaPpO+oDa/FVfaEedp/7js3I0kaRkoTVblr58IvkiE/orkJbZG+zg/g+fqP+J6wOBxsxo3+xBbc3J10pvq0el2y2mnxWMDL8TlBnNRnLu5l2SsmKM/C8QFg16"
  263. # ssBf0tnJIFaPpO+oDa/FVfaEedp/7js3I0kaRkoTVblr58IvkiE/orkJbZG+zg/g+fqP+J6wOBxsxo3+xBbc3J10pvq0el2y2mnxWMDL8TlBnNRnLu5l2SsmKM/C8QFg1