Files
qinglong/脚本库/web版/账密/str,_token_str/2025-09-22_PPark_120e7330.py
2026-05-23 18:48:48 +00:00

389 lines
17 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Source: https://github.com/lksky8/sign-ql/blob/main/PPark.py
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/PPark.py
# Repo: lksky8/sign-ql
# Path: PPark.py
# UploadedAt: 2025-09-22T11:01:17Z
# SHA256: 120e73308bc1ccfb9db8ebd87357364850257a25ba1bc039d67c2967fe6c8e19
# Category: web版/账密
# Evidence: web/H5关键词 + username/password/login
"""
PP停车签到
作者https://github.com/lksky8/sign-ql
最后更新日期2025-9-22
食用方法变量输入export pp_token=账号1#token1&账号2#token2
支持多用户运行
多用户用&或者@隔开
例如账号113800000000#eyJhbGciOiJIUzI1NiJ9.eyj 账号2 139000000000#eyJhbGciOiJIUzI1NiJ9.eyj
则变量为
export pp_token="13800000000#eyJhbGciOiJIUzI1NiJ9.eyj&13900000000#eyJhbGciOiJIUzI1NiJ9.eyj"
每天运行两次否则token会过期
cron: 0 40 0,12 * * *
"""
import requests
import base64
from urllib.parse import quote
import json
import hashlib
import time
import os
import re
KEY_ENCRYPT = "2363ECDFC54A5AF12477D3D45333A19F" # key1 用于加密
KEY_DECRYPT = "466d67cf8f9810707404fae5ed172b8e" # key2 用于解密
WX_ENCRYPT = "riegh^ee:w0fok5je5eeS{eecaes1nep"
send_msg = ''
one_msg = ''
def Log(cont=''):
global send_msg, one_msg
if cont:
one_msg += f'\n{cont}'
send_msg += f'\n{cont}'
def send_notification_message(title):
try:
from notify import send
print("加载通知服务成功!")
send(title, send_msg)
except Exception as e:
if e:
print('发送通知消息失败!')
api_headers = {
'Host': 'api.660pp.com',
'accept': '*/*',
'content-type': 'application/x-www-form-urlencoded',
'rest_api_type': '1',
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Parking/4.3.2 (iOS 16.6.1; iPhone15,2; Build/1312) NetType/WIFI',
'accept-language': 'zh_CN',
}
wx_headers = {
'Host': 'user-api.4pyun.com',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090a13) UnifiedPCWindowsWechat(0xf2541022) XWEB/16467',
'xweb_xhr': '1',
'content-type': 'application/x-www-form-urlencoded',
'accept': '*/*',
'sec-fetch-site': 'cross-site',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
'referer': 'https://servicewechat.com/wxa204074068ad40ef/879/page-frame.html',
'accept-language': 'zh-CN,zh;q=0.9',
'priority': 'u=1, i',
}
def transform(bytes_data: bytearray, key: str) -> bytearray:
len_key = len(key)
len_b = len(bytes_data)
for i in range(len_b):
index = (len_b - i) % len_key
key_byte = ord(key[index])
in_byte = bytes_data[i]
flipped = in_byte ^ 0xFF
bytes_data[i] = key_byte ^ flipped
return bytes_data
def encrypt(arg: str, key: str) -> str:
"""加密,对应提供的 encrypt 方法"""
bytes_data = bytearray(arg.encode('utf-8'))
transformed = transform(bytes_data, key)
return base64.b64encode(transformed).decode('utf-8')
def decrypt(arg: str) -> str:
"""解密,对应提供的 decrypt 方法"""
bytes_data = bytearray(base64.b64decode(arg))
transformed = transform(bytes_data, KEY_DECRYPT)
return transformed.decode('utf-8')
def save_or_update_phone_data(phone_key, new_data, file_path='PPark_data.json'):
if os.path.exists(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
existing_data = json.load(f)
else:
existing_data = {}
if phone_key in existing_data:
existing_data[phone_key].update(new_data) # 合并新旧数据
print(f"[{phone_key}] 数据已更新!")
else:
existing_data[phone_key] = new_data # 新增数据
print(f"[{phone_key}] 新增数据!")
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(existing_data, f, ensure_ascii=False, indent=4)
def get_user_ids_and_tokens(file_path='PPark_data.json'):
try:
with open(file_path, 'r', encoding='utf-8') as f:
phone_data = json.load(f)
results = []
for phone_key, data in phone_data.items():
token = data.get('refresh_token')
if token:
results.append({
'phone_key': phone_key,
'refresh_token': token,
'user_name': data.get('user_name'),
'user_id': data.get('user_id')
})
return results
except FileNotFoundError:
print(f"文件 {file_path} 不存在!")
return []
except json.JSONDecodeError:
print(f"文件 {file_path} 格式错误!")
return []
def get_userdata(u):
user_phone = u.split('#')[0]
user_token = u.split('#')[1]
try:
with open('PPark_data.json', 'r', encoding='utf-8') as f:
cache_data = json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
cache_data = {}
if user_phone not in cache_data:
print(f'[{user_phone}] 不存在于缓存中,尝试初始化数据')
init_refresh_token(user_phone,user_token)
else:
print(f'[{user_phone}] 已存在于缓存中,直接读取数据')
refresh_token(user_phone,user_token,cache_data[user_phone]['refresh_token'])
old_user_token = cache_data[user_phone]['init_token']
if old_user_token != user_token:
print(f'[{user_phone}] token已更新尝试刷新')
init_refresh_token(user_phone,user_token)
def md5_encrypt(s: str):
return hashlib.md5(s.encode('utf-8')).hexdigest()
def get_user_info(phone: str, token: str):
headers = wx_headers.copy()
headers['authorization'] = f'Bearer {token}'
try:
response = requests.get('https://user-api.4pyun.com/rest/2.0/user/whoami',headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == '1001':
print(f"[{response_json['payload']['nickname']}] 获取用户信息:成功")
return response_json['payload']['nickname'], response_json['payload']['identity']
else:
print(f"[{phone}] 获取用户信息:失败:{response_json}")
return None
except requests.RequestException as e:
print(f"[{phone}] 获取用户信息_请求异常{e}")
except json.JSONDecodeError:
print(f"[{phone}] 获取用户信息_响应不是有效的JSON格式")
except Exception as e:
print(f"[{phone}] 获取用户信息_其他异常{e}")
def refresh_token(mobile: str, i_token: str, r_token: str):
headers = api_headers.copy()
headers['rest_api_token'] = r_token
try:
response = requests.put('https://api.660pp.com/rest/1.6/user/token', headers=headers)
response_json = response.json()
# print(response_json)
if response_json['code'] == '1001':
result = json.loads(decrypt(response_json['result']))
print(f"[{mobile}] 刷新token成功")
save_or_update_phone_data(mobile,{'init_token': i_token,'refresh_token': result['token']})
elif response_json['code'] == '401':
print(f"[{mobile}] 刷新token失败token已失效")
Log(f"[{mobile}] 刷新token失败token已失效")
else:
print(f"[{mobile}] 刷新token失败{response_json}")
except requests.RequestException as e:
print(f"[{mobile}] 刷新token_请求异常{e}")
except json.JSONDecodeError:
print(f"[{mobile}] 刷新token_响应不是有效的JSON格式")
except Exception as e:
print(f"[{mobile}] 刷新token_其他异常{e}")
def init_refresh_token(mobile: str, token: str):
headers = api_headers.copy()
headers['rest_api_token'] = token
try:
response = requests.put('https://api.660pp.com/rest/1.6/user/token', headers=headers)
response_json = response.json()
# print(response_json)
if response_json['code'] == '1001':
result = json.loads(decrypt(response_json['result']))
user_name, user_id = get_user_info(mobile, token)
save_or_update_phone_data(mobile,{'user_name': user_name, 'user_id': user_id, 'init_token': token, 'refresh_token': result['token']})
print(f"[{mobile}] 刷新token成功")
elif response_json['code'] == '401':
print(f"[{mobile}] 刷新token失败token已失效")
Log(f"[{mobile}] 刷新token失败token已失效")
else:
print(f"[{mobile}] 刷新token失败{response_json}")
except requests.RequestException as e:
print(f"[{mobile}] 刷新token_请求异常{e}")
except json.JSONDecodeError:
print(f"[{mobile}] 刷新token_响应不是有效的JSON格式")
except Exception as e:
print(f"[{mobile}] 刷新token_其他异常{e}")
def day_sign(nickname: str, token: str):
headers = api_headers.copy()
headers['rest_api_token'] = token
try:
response = requests.get('https://api.660pp.com/rest/1.6/reward/bonus?yc7OyqO6qQ%3D%3D=rL7JhL/NrriG2tPZ2aegog%3D%3D', headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == '1001':
result = json.loads(decrypt(response_json['result']))
message = result['message'].replace('\r\n', '')
if '签到获得' in result['message'] or '已连续签到'in result['message']:
print(f"[{nickname}] 签到成功:{message} 已累计获得:{result['combo']} 积分")
Log(f"[{nickname}] 签到成功:{message} 已累计获得:{result['combo']} 积分")
elif message == '您已签到成功' :
print(f"[{nickname}] 签到失败:已签到")
Log(f"[{nickname}] 已签到")
else:
print(f"[{nickname}] 签到失败:{message}")
Log(f"[{nickname}] 签到失败:{message}")
else:
print(f"[{nickname}] 获取签到数据失败:{response_json}")
except requests.RequestException as e:
print(f"[{nickname}] 签到_请求异常{e}")
except json.JSONDecodeError:
print(f"[{nickname}] 签到_响应不是有效的JSON格式")
except Exception as e:
print(f"[{nickname}] 签到_其他异常{e}")
def get_task(nickname: str, token: str):
headers = wx_headers.copy()
headers['authorization'] = f'Bearer {token}'
try:
response = requests.get('https://user-api.4pyun.com/rest/2.0/bonus/reward/task/list?%2B9Hnx%2FPy=7bL7p%2FqgoK77uPOi%2B8WjqP%2Fw', headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == '1001':
video_task = [task for task in response_json['payload']['row'] if task['name'] == '看视频得积分'][0]
referer_url = video_task['referer_url']
print(f'[{nickname}] 获取视频任务数据成功')
return referer_url.split('&voucher=')[1]
else:
print(f"[{nickname}] 获取任务_失败{response_json}")
Log(f"[{nickname}] 获取视频任务数据失败:{response_json}")
return None
except requests.RequestException as e:
print(f"[{nickname}] 获取任务_请求异常{e}")
except json.JSONDecodeError:
print(f"[{nickname}] 获取任务_响应不是有效的JSON格式")
except Exception as e:
print(f"[{nickname}] 获取任务_其他异常{e}")
def complete_task(nickname: str, token: str, task_id: str):
headers = wx_headers.copy()
headers['authorization'] = f'Bearer {token}'
headers['content-type'] = 'application/json;charset=utf-8'
try:
data = '{"app_id":"wxa204074068ad40ef","purpose":"reward:motivate:advertising","voucher":"voucher_data"}'.replace('voucher_data', task_id)
encrypt_data = encrypt(data,WX_ENCRYPT)
response = requests.post('https://user-api.4pyun.com/rest/2.0/bonus/reward/task/complete', headers=headers, data=encrypt_data)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == '1001':
print(f"[{nickname}] 看视频:任务完成")
headers['content-type'] = 'application/x-www-form-urlencoded'
response = requests.get('https://user-api.4pyun.com/rest/2.0/bonus/reward/acquire?%2B9Hnx%2FPy=7bL7p%2FqgoK77uPOi%2B8WjqP%2Fw&6u%2FT5%2Ffp8w%3D%3D=%2Fv%2Fp%2Fej%2BvsH17qPs9L7xqvir%2FqDo7sjk8fTx', headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == '1001':
print(f"[{nickname}] 看视频:任务奖励已领取,{response_json['payload']['message']}")
Log(f"[{nickname}] 看视频:任务奖励已领取,{response_json['payload']['message']}")
elif response_json['message'] == '已达积分领取次数上限':
print(f"[{nickname}] 看视频:积分已领取")
else:
print(f"[{nickname}] 看视频:{response_json['message']}")
Log(f"[{nickname}] 看视频:{response_json['message']}")
else:
print(f"[{nickname}] 看视频任务失败:{response_json}")
Log(f"[{nickname}] 看视频任务失败:{response_json}")
except requests.RequestException as e:
print(f"[{nickname}] 看视频任务_请求异常{e}")
except json.JSONDecodeError:
print(f"[{nickname}] 看视频任务_响应不是有效的JSON格式")
except Exception as e:
print(f"[{nickname}] 看视频任务_其他异常{e}")
def reward_balance(nickname: str, token: str, user_id: str):
headers = wx_headers.copy()
headers['authorization'] = f'Bearer {token}'
try:
response = requests.get(f'https://user-api.4pyun.com/rest/2.0/reward/balance?rP7%2Fz%2BPx7u8%3D={quote(encrypt(user_id,WX_ENCRYPT))}&7%2BnE5cfz8g%3D%3D={quote(encrypt(user_id,WX_ENCRYPT))}&%2Fbb%2F6P7j4erz=pw%3D%3D', headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == '1001':
print(f"[{nickname}] 积分余额:{response_json['payload']['balance']}")
Log(f"[{nickname}] 积分余额:{response_json['payload']['balance']}")
else:
print(f"[{nickname}] 获取积分余额_失败{response_json}")
Log(f"[{nickname}] 获取积分余额_失败{response_json}")
except requests.RequestException as e:
print(f"[{nickname}] 获取积分余额_请求异常{e}")
except json.JSONDecodeError:
print(f"[{nickname}] 获取积分余额_响应不是有效的JSON格式")
except Exception as e:
print(f"[{nickname}] 获取积分余额_其他异常{e}")
if __name__ == '__main__':
if 'pp_token' in os.environ:
pp_token = re.split("@|&", os.environ.get("pp_token"))
print(f'查找到{len(pp_token)}个账号')
else:
pp_token = []
print('请填入pp_token变量')
Log('请填入pp_token变量')
try:
if pp_token:
for pp_token_item in pp_token:
get_userdata(pp_token_item)
user_data = get_user_ids_and_tokens()
if user_data:
print(f"配置缓存中读取到{len(user_data)}个账号")
print('*' * 50)
z = 1
for item in user_data:
print('-' * 50)
print(f'登录第{z}个账号>>>>>>')
phone_key = item.get('phone_key')
new_token = item.get('refresh_token')
user_name = item.get('user_name')
user_id = item.get('user_id')
if new_token:
day_sign(user_name,new_token)
for _ in range(2):
voucher = get_task(user_name, new_token)
if voucher:
complete_task(user_name, new_token, voucher)
time.sleep(5)
reward_balance(user_name,new_token,user_id)
time.sleep(3)
Log('-'*30)
z += 1
else:
print("未读取到用户数据,程序退出")
exit(0)
except Exception as e:
print(f'程序异常:{e}')
try:
send_notification_message(title='PP停车') # 发送通知
except Exception as e:
print('推送失败:' + str(e))