import hashlib import json import re import time import execjs from curl_cffi import requests from observability.logging import get_logger_with_trace logger = get_logger_with_trace(__name__) class DeleteOrder: def __init__(self, cookie, order_id): self.cookie = cookie self.order_id = order_id self.timestamp = int(time.time() * 1000) self.h5st_ctx = self.get_js_obj("h5st4.2.js") self.ai = "8108f" self.version = "4.2" self.p1 = None self.fp = None self.tk = None self.mode = None self.rd = None self.sign = None self.timestamp_sha256 = None self.t_sha256 = None self.t_send_data = None def get_js_obj(self, js): with open(f"./js/{js}", "r", encoding="utf-8") as file: js_code = file.read() return execjs.compile(js_code, cwd="./node_modules") def encrypt_body(self): key = "e7c398ffcb2d4824b4d0a703e38eb0bb" str_to_hash = f"{self.order_id}1sx{self.timestamp}{key}" enc_str = hashlib.md5(str_to_hash.encode("utf-8")).hexdigest() body = { "orderId": self.order_id, "source": "1", "channelSource": "sx", "t": self.timestamp, "encStr": enc_str, } return json.dumps(body) def cancel_order(self): body = self.encrypt_body() url = "https://api.m.jd.com/api" headers = { "accept": "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9", "cache-control": "no-cache", "content-type": "application/x-www-form-urlencoded", "origin": "https://recharge.m.jd.com", "pragma": "no-cache", "priority": "u=1, i", "referer": "https://recharge.m.jd.com/", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-site", "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1", "x-referer-page": "https://recharge.m.jd.com/orderDetail", "x-rp-client": "h5_1.0.0", "cookie": self.cookie, } data = { "appid": "tsw-m", "functionId": "huafei_orderCancel", "t": f"{self.timestamp}", "body": body, "client": "iPhone", "uuid": "1735283651510338525254", "osVersion": "16.6", "screen": "828.0000123381615*1792.0000267028809", "x-api-eid-token": "jdd03MOMPSVKGBFF6WCM3KNQK34LGPGSCNKB2WACDOVKFUNXQWAWDEVXSHMGQEQLJ6EUKKXZ7ARQA4CPF6EMRRUP5P7ETLEAAAAMUC37NLWQAAAAADDQSI4QCFE6GAAX", } response = requests.post(url, headers=headers, data=data) print(response.text) def get_fp(self): self.fp = self.h5st_ctx.call("iC") def get_env(self): ctx = self.get_js_obj("h5st4.2.js") env = ctx.call("expandParams", self.fp, self.p1) return env def request_algo(self): env = self.get_env() url = "https://cactus.jd.com/request_algo" params = {"g_ty": "ajax"} timestamp_ms = int(time.time() * 1000) data = { "version": "4.2", "fp": self.fp, "appId": "8108f", "timestamp": timestamp_ms, "platform": "web", "expandParams": env, "fv": "h5_npm_v4.2.0", } headers = { "accept": "application/json", "accept-language": "zh-CN,zh;q=0.9", "cache-control": "no-cache", "content-type": "application/json", "origin": "https://txsm-m.jd.com", "pragma": "no-cache", "referer": "https://txsm-m.jd.com/", "sec-ch-ua": '"Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"Windows"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-site", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", } data = json.dumps(data, separators=(",", ":")) response = requests.post(url, headers=headers, params=params, data=data) return response.json().get("data") def get_algo(self): algo_data = self.request_algo() print(algo_data) algo = algo_data["result"]["algo"] self.tk = algo_data["result"]["tk"] self.mode = re.findall(r"algo\.(.*)\(", algo)[0] self.rd = re.findall(r"rd='(.*)';", algo)[0] def get_p1(self): self.p1 = re.findall(r"pin=(.*);", self.cookie)[0] def get_tm(self, timestamp): import datetime # 将13位时间戳转换为datetime对象 dt = datetime.datetime.fromtimestamp(timestamp / 1000) year = dt.year month = str(dt.month).zfill(2) day = str(dt.day).zfill(2) hour = str(dt.hour).zfill(2) minute = str(dt.minute).zfill(2) second = str(dt.second).zfill(2) # 将微秒转换为毫秒 microsecond = dt.microsecond // 1000 return f"{year}{month}{day}{hour}{minute}{second}{microsecond}" def get_oe(self, ts): oe = self.h5st_ctx.call( "test", self.mode, self.tk, self.fp, ts, self.ai, self.rd ) return oe def get_body(self): self.t_send_data = int(time.time() * 1000) self.t_sha256 = int(time.time() * 1000) self.timestamp_sha256 = self.get_tm(self.t_sha256) ts = self.timestamp_sha256 + "74" oe = self.get_oe(ts) body_hex = self.h5st_ctx.call("encrypt_body", self.order_id, "delete") t_string = f"{oe}appid:m_core&body:{body_hex}&client:Win32&clientVersion:&functionId:order_recycle_m&t:{self.t_send_data}{oe}" self.sign = self.h5st_ctx.call("__genSign", t_string) body = self.h5st_ctx.call("build_params", self.order_id, "delete") return body def get_h5st(self): h5st = f"{self.timestamp_sha256};{self.fp};{self.ai};{self.tk};{self.sign};{self.version};{self.t_sha256}" return h5st def request_jd_recycle(self, body, h5st): headers = { "accept": "*/*", "accept-language": "zh-CN,zh;q=0.9", "cache-control": "no-cache", "content-type": "application/x-www-form-urlencoded", "origin": "https://trade.m.jd.com", "pragma": "no-cache", "referer": "https://trade.m.jd.com/", "sec-ch-ua": '"Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"Windows"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-site", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", "x-referer-page": "https://trade.m.jd.com/order/orderlist_jdm.shtml", "x-rp-client": "h5_1.0.0", "cookie": self.cookie, } url = "https://api.m.jd.com/client.action" data = { "t": f"{self.t_send_data}", "loginType": "2", "loginWQBiz": "golden-trade", "appid": "m_core", "client": "Win32", "clientVersion": "", "build": "", "osVersion": "null", "screen": "1440*900", "networkType": "4g", "partner": "", "forcebot": "", "d_brand": "", "d_model": "", "lang": "zh-CN", "scope": "", "sdkVersion": "", "openudid": "", "uuid": "1658065822", "x-api-eid-token": "jdd03EZ4U2HD6OVXEWMTFQVIXNMASQWBFCYSPX37R7H6QIQDPWYYPIESUHF2YNEGTGXKWHGCH5VEWPMZA4PWPPKX6ZJOKWIAAAAMOR6CEGEIAAAAADWOVM6433SKKPAX", "functionId": "order_recycle_m", "body": body, "h5st": h5st, } response = requests.post(url, headers=headers, data=data) print(response.text) def recycle_order(self): self.get_p1() self.get_fp() self.get_algo() body = self.get_body() h5st = self.get_h5st() self.request_jd_recycle(body=body, h5st=h5st) def run(self): # 取消订单 self.cancel_order() # 删除订单 self.recycle_order()