import hashlib import json from logging import LoggerAdapter import platform import re import time import fake_useragent from curl_cffi import ProxySpec, requests from apps.jd.schemas.models import QueryCardResponseData from apps.shared.proxy_pool.proxy_pool import ProxyPoolFactory from core.config import ProxyPoolType from core.exceptions import JDServiceException from core.responses import BusinessCode from observability.logging import get_logger_with_trace logger: LoggerAdapter = get_logger_with_trace(__name__) class XiechengCardSpider: """ 携程 100元:10140177420168 200元:10148161391225 300元:10148163028307 500元:10148178960836 1000元:10148179392280 """ def __init__(self, cookies, order_num, sku_id): self.eid = None self.x_token = None self._session = requests.Session() self._order_num = order_num self.cookies = cookies self.time_stamp = int(time.time() * 1000) self.current_os = platform.system() self.sku_id = sku_id self.submit_order_url = "https://api.m.jd.com/appstore/submitorder" self.ticket_url = "https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkcaptcha" self.jd_api = "https://api.m.jd.com/api" self.action_url = "https://api.m.jd.com/client.action" self.check_captcha_url = ( "https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkcaptcha" ) self._expiring_pool = ProxyPoolFactory.get_proxy_pool( ProxyPoolType.EXPIRING, expire_time=60 ) self.user_agent = fake_useragent.FakeUserAgent().chrome def _get_proxy(self): proxy = self._expiring_pool.get_proxy(order_id=self._order_num) return ProxySpec(all=proxy) if proxy else None # def get_ticket_res(self): # for i in range(1): # try: # headers = { # "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", # "Accept-Language": "zh-CN,zh;q=0.9", # "Cache-Control": "no-cache", # "Connection": "keep-alive", # "Pragma": "no-cache", # "Upgrade-Insecure-Requests": "1", # "User-Agent": self.user_agent, # } # url = f"http://119.23.175.61:8877/captcha/tx?aid=2093769752&ip={self.proxy}&host=https://t.captcha.qq.com" # logger.info(f"获取ticket请求代理:{self.proxy}") # logger.info(f"获取ticket请求:{url}") # response = self._session.get( # url, headers=headers, verify=False, timeout=60 # ) # logger.info(f"获取ticket结果:{response.text}") # if response.json().get("msg_code") != 200: # continue # if response.json().get("result", {}).get( # "ticket" # ) and response.json().get("result", {}).get("randstr"): # return { # "ticket": response.json().get("result", {}).get("ticket"), # "randstr": response.json().get("result", {}).get("randstr"), # } # except Exception as e: # logger.error(e) # raise Exception("获取ticket失败") def get_pay_res(self, order_id): headers = { "accept": "*/*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "content-type": "application/json;charset=UTF-8", "origin": "https://trade.m.jd.com", "priority": "u=1, i", "referer": "https://trade.m.jd.com/", "sec-ch-ua": '"Chromium";v="130", "Microsoft Edge";v="130", "Not?A_Brand";v="99"', "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": self.user_agent, "x-referer-page": "https://trade.m.jd.com/order/orderlist_jdm.shtml", "x-rp-client": "h5_1.0.0", "cookie": self.cookies, } body = ( '{"appType":3,"bizType":"2","deviceUUId":"","platform":3,"sceneval":"2","source":"m_inner_myJd.orderFloor_orderlist","systemBaseInfo":"{\\"pixelRatio\\":1.25,\\"screenWidth\\":2048,\\"screenHeight\\":1152,\\"windowWidth\\":414,\\"windowHeight\\":1034,\\"statusBarHeight\\":null,\\"safeArea\\":{\\"bottom\\":0,\\"height\\":0,\\"left\\":0,\\"right\\":0,\\"top\\":0,\\"width\\":0},\\"bluetoothEnabled\\":false,\\"locationEnabled\\":false,\\"wifiEnabled\\":false,\\"deviceOrientation\\":\\"landscape\\",\\"benchmarkLevel\\":-1,\\"brand\\":\\"\\",\\"model\\":\\"\\",\\"system\\":null,\\"platform\\":\\"Win32\\",\\"SDKVersion\\":\\"\\",\\"enableDebug\\":false,\\"language\\":\\"zh-CN\\",\\"version\\":\\"\\",\\"theme\\":\\"light\\",\\"fontSizeSetting\\":null,\\"albumAuthorized\\":false,\\"cameraAuthorized\\":false,\\"locationAuthorized\\":false,\\"microphoneAuthorized\\":false,\\"notificationAuthorized\\":false,\\"notificationAlertAuthorized\\":false,\\"notificationBadgeAuthorized\\":false,\\"notificationSoundAuthorized\\":false,\\"phoneCalendarAuthorized\\":false,\\"locationReducedAccuracy\\":false,\\"environment\\":\\"\\"}","orderId":"%s","origin":10,"tenantCode":"jgm","bizModelCode":"2","bizModeClientType":"M","bizModeFramework":"Taro","externalLoginType":1,"token":"3852b12f8c4d869b7ed3e2b3c68c9436","appId":"m91d27dbf599dff74"}' % order_id ) encrypt_body = self.sha256_hash(body) timestamp = f"{int(time.time() * 1000)}" object_id = "9b070" function_id = "pay_info_m" h5st = self.get_h5st(timestamp, encrypt_body, object_id, function_id) params = { "t": f"{self.time_stamp}", "loginType": "2", "loginWQBiz": "golden-trade", "appid": "m_core", "client": "Win32", "clientVersion": "", "build": "", "osVersion": "null", "screen": "2048*1152", "networkType": "4g", "partner": "", "forcebot": "", "d_brand": "", "d_model": "", "lang": "zh-CN", "scope": "", "sdkVersion": "", "openudid": "", "uuid": "17295878824571442265187", "x-api-eid-token": self.x_token, "functionId": "pay_info_m", "body": body, "h5st": h5st, } proxy = self._get_proxy() response = self._session.get( self.action_url, headers=headers, params=params, verify=False, proxies=proxy, ) return response.json() def plat_pay_channel_res(self, pay_id): headers = { "accept": "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "content-type": "application/x-www-form-urlencoded", "origin": "https://mpay.m.jd.com", "priority": "u=1, i", "referer": "https://mpay.m.jd.com/", "sec-ch-ua": '"Chromium";v="130", "Microsoft Edge";v="130", "Not?A_Brand";v="99"', "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": self.user_agent, "x-referer-page": "https://mpay.m.jd.com/mpay.623f9498223cf9b9de9f.html", "x-rp-client": "h5_1.0.0", "cookie": self.cookies, } params = {"functionId": "platPayChannel", "appid": "mcashier", "scval": "mpay"} body = ( '{"appId":"m_D1vmUq63","payId":"%s","source":"mcashier","origin":"h5","mcashierTraceId":1729842386189}' % pay_id ) encrypt_body = self.sha256_hash(body) timestamp = f"{int(time.time() * 1000)}" object_id = "303a7" function_id = "plat_pay_channel" proxy = self._get_proxy() h5st = self.get_h5st(timestamp, encrypt_body, object_id, function_id) data = {"body": body, "x-api-eid-token": self.x_token, "h5st": h5st} response = self._session.post( self.action_url, headers=headers, params=params, data=data, verify=False, proxies=proxy, ) return response.json() def get_locdetails(self, order_id): url = "https://api.m.jd.com/" data = { "appid": "loc", "loginType": "2", "cthr": "1", "loginWQBiz": "locdetails", "t": f"{int(time.time() * 1000)}", "functionId": "queryLocOrderDetail", "body": '{"version":"1.0.0","source":"","requestId":1757908327795,"orderId":"%s","oldHttp2Color":true}' % order_id, } headers = { "accept": "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "cache-control": "no-cache", "content-type": "application/x-www-form-urlencoded", "origin": "https://locdetails.jd.com", "pragma": "no-cache", "priority": "u=1, i", "referer": "https://locdetails.jd.com/", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-site", "user-agent": self.user_agent, "x-referer-page": "https://locdetails.jd.com/h5/index.html", "x-rp-client": "h5_1.0.0", "cookie": self.cookies, } # proxy = self._get_proxy() response = self._session.post( url, headers=headers, data=data, verify=False, # proxies={ # "http": proxy, # "https": proxy, # }, ) res = response.json() if res.get("code") == 20001: return BusinessCode.JD_ORDER_CK_ERR, QueryCardResponseData( order_status="", card_num="", card_pwd="", remark=str(res), ) if res and res.get("code") == 0: logger.info(f"请求结果 {response.json()}") data = res.get("data", {}) order_status_data = data.get("orderStatusData", {}) shop_sku_info_list = data.get("shopSkuInfoList", []) card_num = "" card_pwd = "" if shop_sku_info_list and len(shop_sku_info_list) > 0: sku_infos = shop_sku_info_list[0].get("skuInfos", []) if sku_infos and len(sku_infos) > 0: code_info = sku_infos[0].get("codeInfo", []) if code_info and len(code_info) > 0: card_num = code_info[0].get("cardNum", "") card_pwd = code_info[0].get("pwdNum", "") return BusinessCode.SUCCESS, QueryCardResponseData( order_status=order_status_data.get("statusName", ""), card_num=card_num, card_pwd=card_pwd, ) else: return BusinessCode.JD_ORDER_NORMAL_ERR, QueryCardResponseData( order_status="", card_num="", card_pwd="", remark=str(res) ) def plat_wx_pay_res(self, pay_id): headers = { "accept": "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "content-type": "application/x-www-form-urlencoded", "origin": "https://mpay.m.jd.com", "priority": "u=1, i", "referer": "https://mpay.m.jd.com/", "sec-ch-ua": '"Chromium";v="130", "Microsoft Edge";v="130", "Not?A_Brand";v="99"', "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": self.user_agent, "x-referer-page": "https://mpay.m.jd.com/mpay.623f9498223cf9b9de9f.html", "x-rp-client": "h5_1.0.0", "cookie": self.cookies, } params = {"functionId": "platWapWXPay", "appid": "mcashier", "scval": "mpay"} body = ( '{"appId":"m_D1vmUq63","payId":"%s","eid":"%s","source":"mcashier","origin":"h5","mcashierTraceId":1729837716957}' % (pay_id, self.eid) ) encrypt_body = self.sha256_hash(body) timestamp = f"{int(time.time() * 1000)}" object_id = "303a7" function_id = "plat_wx_pay" h5st = self.get_h5st(timestamp, encrypt_body, object_id, function_id) data = {"body": body, "x-api-eid-token": self.x_token, "h5st": h5st} proxy = self._get_proxy() response = self._session.post( self.action_url, headers=headers, params=params, data=data, verify=False, proxies=proxy, ) return response.json() # def get_deep_link_res(self, mweb_url): # headers = { # "Host": "wx.tenpay.com", # "sec-ch-ua-platform": '"Windows"', # "User-Agent": self.user_agent, # "sec-ch-ua": '"Chromium";v="130", "Microsoft Edge";v="130", "Not?A_Brand";v="99"', # "sec-ch-ua-mobile": "?0", # "Accept": "*/*", # "Sec-Fetch-Site": "same-origin", # "Sec-Fetch-Mode": "cors", # "Sec-Fetch-Dest": "empty", # "Referer": mweb_url, # "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", # } # prepay_id = re.search(r"prepay_id=(wx\w+)", mweb_url).group(1) # package = re.search(r"package=(\d+)", mweb_url).group(1) # ticket_res = self.get_ticket_res() # logger.info(f"订单号:{self._order_num},获取ticket返回:{ticket_res}") # ticket = ticket_res["ticket"] # randstr = ticket_res["randstr"] # params = { # "ticket": ticket, # "randstr": randstr, # "prepayid": prepay_id, # "package": package, # } # proxy = self._get_proxy() # response = self._session.get( # self.check_captcha_url, # headers=headers, # params=params, # verify=False, # proxies=proxy, # ) # return response.json() @staticmethod def sha256_hash(text): # 创建 SHA-256 哈希对象 sha256 = hashlib.sha256() # 更新哈希对象(输入必须为字节类型) sha256.update(text.encode("utf-8")) # 返回 16 进制格式的哈希值 return sha256.hexdigest() def _get_pt_pin(self, cookie_str): cookies = {} for item in cookie_str.strip(";").split(";"): if "=" in item: key, value = item.strip().split("=", 1) cookies[key] = value pt_pin = cookies.get("pt_pin") return pt_pin def get_h5st(self, timestamp, body, object_id, function_id): sua = "Windows NT 10.0; Win64; x64" pt_pin = self._get_pt_pin(self.cookies) params_str = f"ai={object_id}&sua={sua}&pin={pt_pin}&appid=m_core&functionId={function_id}&body={body}&client=Win32&clientVersion=2.5.2&t={timestamp}" h5st = requests.get(f"http://127.0.0.1:8887/jd/h5st?{params_str}").text return h5st def get_x_token(self): proxy = None _proxy = self._get_proxy() if _proxy: proxy = _proxy.get("all") data = {"type": "1", "str": self.user_agent} if proxy: data["proxy"] = proxy response = requests.post( "http://127.0.0.1:8887/api/stash/algorithm", data=data, ) logger.info(f"获取x-api-eid-token返回:{response.text}") res = response.json() token = res["data"]["token"] eid = res["data"]["eid"] return token, eid def get_current_order(self, retry_count: int = 3): if not retry_count: return JDServiceException(BusinessCode.JD_ORDER_RISK_ERR) body = ( '{"deviceUUID":"6785593751540242498","appId":"wxae3e8056daea8727","appVersion":"2.5.2","tenantCode":"jgm","bizModelCode":"3","bizModeClientType":"M","token":"3852b12f8c4d869b7ed3e2b3c68c9436","externalLoginType":1,"referer":"https://item.m.jd.com/","resetGsd":true,"useBestCoupon":"1","locationId":"1-72-2819-0","packageStyle":true,"sceneval":"2","balanceCommonOrderForm":{"supportTransport":false,"action":1,"overseaMerge":false,"international":false,"netBuySourceType":0,"appVersion":"2.5.2","tradeShort":false},"balanceDeviceInfo":{"resolution":"2048*1152"},"cartParam":{"skuItem":{"skuId":"%s","num":"1","orderCashBack":false,"extFlag":{}}}}' % self.sku_id ) encrypt_body = self.sha256_hash(body) timestamp = f"{int(time.time() * 1000)}" object_id = "bd265" function_id = "balance_getCurrentOrder_m" h5st = self.get_h5st(timestamp, encrypt_body, object_id, function_id) headers = { "accept": "*/*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "cache-control": "no-cache", "content-type": "application/x-www-form-urlencoded", "origin": "https://trade.m.jd.com", "pragma": "no-cache", "priority": "u=1, i", "referer": "https://trade.m.jd.com/", "sec-ch-ua": '"Chromium";v="140", "Not=A?Brand";v="24", "Microsoft Edge";v="140"', "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": self.user_agent, "x-referer-page": "https://trade.m.jd.com/pay", "x-rp-client": "h5_1.0.0", "cookie": self.cookies, } url = "https://api.m.jd.com/client.action" data = { "t": timestamp, "body": body, "h5st": h5st, "scval": self.sku_id, "client": "Win32", "clientVersion": "2.5.2", "osVersion": "other", "screen": "2048*1152", "networkType": "false", "d_brand": "", "d_model": "", "lang": "zh-CN", "sdkVersion": "2.5.2", "appid": "m_core", "openudid": "", "x-api-eid-token": self.x_token, "functionId": "balance_getCurrentOrder_m", "uuid": "17573259367521124301157", "loginType": "2", "xAPIScval3": "unknown", } proxy = self._get_proxy() response = self._session.post( url, headers=headers, data=data, impersonate="chrome", verify=False, proxies=proxy, ) if ( response.ok and response.json() and response.json().get("body", {}).get("errorCode") == "601" ): return self.get_current_order(retry_count - 1) def submit_order(self): body = { "deviceUUID": "6279258698405299736", "appId": "wxae3e8056daea8727", "tenantCode": "jgm", "bizModelCode": "3", "bizModeClientType": "M", "token": "3852b12f8c4d869b7ed3e2b3c68c9436", "externalLoginType": 1, "appVersion": "2.5.2", "referer": "https://item.m.jd.com/", "checkPayPassport": False, "checkpwdV2": False, "isEncryptionMobile": True, "outStockVendorIdList": [12514479], "mainSkuIdList": [int(self.sku_id)], "balanceDataServerSkuVOList": [ { "id": int(self.sku_id), "jdPrice": "499.00", "buyNum": 1, "firstCategoryId": 4938, "secondCategoryId": 11760, "thirdCategoryId": 22501, "promoId": 305236894242, "venderId": 12514479, "type": 1, } ], "balanceTableWareVoList": [{}], "cashierDeskBackUrl": f"https://trade.m.jd.com/buy/done.shtml?dealId=%24%7BorderId%7D&sceneval=2&fromPay=1&ptag=7039.27.14&gift_skuid={self.sku_id}&gift_venderid=12514479&gift_cid=22501&normal=1", "payType": "4", "subPayType": "", "licenseList": [], "balanceCommonOrderForm": { "action": 1, "overseaMerge": False, "international": False, "netBuySourceType": 0, "appVersion": "2.5.2", "supportTransport": False, "tradeShort": False, "useChannelFlag": "10000000", "hasSingleOrderGovSubsidy": False, "unionPayCouponEffective": False, "oldAgeStyle": False, "balanceRefreshByAction": "1", "supportUserPrivacy": True, "userPrivacyChecked": True, }, "balanceExt": { "baiDuJumpButtonSwitch": False, "bubbleTips": {"enable": True, "num": 1, "time": 3, "useNum": 0}, "cashierDeskEnable": True, "cashierPayFlag": "0", "checkIdInfo": False, "couponRedText": "", "hasBackupStorage": False, "hasCwbg": False, "hasFreightInsurance": False, "isInternational": False, "isSupportTranport": False, "jdCombineType": 0, "knowledgeServiceStatus": 0, "noAddressMatchDegradeSwitch": True, "overseaMerge": False, "plusFloorStr": '{"addressType":0,"area":"19-1601-3633-63243","freightInfoList":[],"invoiceType":1,"payWay":4,"plusPromotionRequest":{"couponTotalAmount":0.00,"fareCouponTotalAmount":0.00,"officialDiscountTotalDiscount":0.00,"promotionReduceTotalAmount":0.00,"promotionTotalPrice":499.00,"redBagTotalAmount":0.00,"totalCashGiftDiscount":0,"totalCashGiftNew":0,"totalCashGiftOld":0,"totalParallelDiscount":0.00},"plusStatus":"203","requestConditionList":[105,106,305,529,523,521,522,351],"skuInfoRequestList":[{"col_type":"0","companyType":0,"factoryShip":0,"firstCategory":4938,"isCanUseDongCoupon":1,"isCanUseJingCoupon":1,"isJxzy":0,"isLoc":1,"isOverseaPurchase":0,"jdPrice":"499.00","number":"1","secondCategory":11760,"shopId":12204479,"skuExtension":{"fields":{"fare":"2849262","saler":"","saleAttributes":"[{\\"saleName\\":\\"颜色\\",\\"dim\\":1},{\\"saleName\\":\\"尺码\\",\\"dim\\":2}]","maxBuyNum":"19","is7ToReturn":"0","features":"consumptionVAT:0,inputVAT:0,outputVAT:0","vender_attribute":"","isHitGovSubsidy":"0","selectedGBCZGovConsumerCoupon":"false","yn":"1","vender_name":"易点生活电子商务有限公司","product_id":"10028314345641","sale_atts":"","warranty":"","timeliness_id":"0","sku_name":"【谨防刷单诈骗】沃尔玛大卖场卡500元 官方卡密 卡号8688 不支持山姆 本店不刷单 谨防诈骗 不支持退换","supply_unit":"","model":"","shopId":"12204479","cn_sku_name":"【谨防刷单诈骗】沃尔玛大卖场卡500元 官方卡密 卡号8688 不支持山姆 本店不刷单 谨防诈骗 不支持退换","height":"0","MN":"19","first_buyer_post":"4541","unLimit_cid":"22501","isCanVAT":"0","pay_first":"1","tsfw":"p8,","ms":"0","weight":"0","sku_id":"%s","tax":"consumptionVAT:0,inputVAT:0,outputVAT:0","shop_name":"沃尔玛礼品卡专卖店","product_name":"【谨防刷单诈骗】沃尔玛大卖场卡500元 官方卡密 卡号8688 不支持山姆","brand_id":"250870","shop_id":"12204479","size":"不支持退换","brandId":"250870","col_type":"0","color":"本店不刷单 谨防诈骗","cn_color":"本店不刷单 谨防诈骗","isLOC":"2","img_dfs_url":"jfs/t1/225028/24/16896/94540/6667fb55Fad484540/4069fd317318e9da.jpg","outer_id":"DSwemmck0500","platform":"1","vender_id":"12514479","jc_buyer":"","category_id":"22501","fxg":"0","isQdh":"0","venderAttribute":"","sku_tag":"0","category_id1":"4938","sku_mark":"0","template_type_attributes":"[{\\"attrid\\":\\"1001050620\\",\\"dim\\":1,\\"saleName\\":\\"颜色\\",\\"saleValue\\":\\"本店不刷单 谨防诈骗\\",\\"sequenceNo\\":1,\\"valueId\\":\\"2916524754\\"},{\\"attrid\\":\\"1001051741\\",\\"dim\\":2,\\"saleName\\":\\"尺码\\",\\"saleValue\\":\\"不支持退换\\",\\"sequenceNo\\":1,\\"valueId\\":\\"3924738280\\"}]","category_id2":"11760","sale_template_id":"POP_MODEL","jc_saler":"","day_limited_sales":"19","length":"0","locGroupId":"-100","vender_col_type":"0","sku_status":"1","allnum":"0","containsGovConsumerCoupon":"false","width":"0"},"fresh":false,"num":1,"parallelPromo":false,"samShop":false,"selfSupport":false,"shoppingMalls":false,"skuPriceAfterSinglePromotion":"499.00","skuUuid":"1012_F2t2t3H1499005262095200256","spuId":"-1","storeId":"-1","vendor":"12514479","vendorType":2},"skuId":%s,"skuMark":"","spuId":"-1","thirdCategory":22501,"uuid":"1012_F2t2t3H1499005262095200256","venderId":12514479,"vender_bizid":",popsop,","vender_col_type":"0","vendorType":0}],"totalPrice":"499.00"}' % (self.sku_id, self.sku_id), "selectedCouponNum": 0, "sellLargeDay": "7", "supportPaymentSkuList": [self.sku_id], "useBestCoupon": True, }, "actualPayment": "499.00", "sendGift": {}, "dsList": [ {"paramName": "report_time", "paramVal": ""}, {"paramName": "deal_id", "paramVal": ""}, {"paramName": "buyer_uin"}, {"paramName": "pin", "paramVal": ""}, { "paramName": "cookie_pprd_p", "paramVal": "UUID.17512753463451844059233-LOGID.1751857899901.1014192400", }, { "paramName": "cookie_pprd_s", "paramVal": "76161171.17512753463451844059233.1751275346.1751856681.1751857862.11", }, {"paramName": "cookie_pprd_t"}, {"paramName": "ip", "paramVal": ""}, {"paramName": "visitkey", "paramVal": "6279258698405299736"}, {"paramName": "gen_entrance", "paramVal": ""}, {"paramName": "deal_src", "paramVal": "7"}, {"paramName": "item_type", "paramVal": "1"}, {"paramName": "fav_unixtime", "paramVal": ""}, {"paramName": "pay_type", "paramVal": "0"}, {"paramName": "ab_test", "paramVal": ""}, {"paramName": "serilize_type", "paramVal": "0"}, {"paramName": "property1", "paramVal": "0"}, {"paramName": "property2", "paramVal": "0"}, {"paramName": "property3", "paramVal": "0"}, {"paramName": "property4", "paramVal": "0"}, {"paramName": "seller_uin", "paramVal": "0"}, {"paramName": "pp_item_id", "paramVal": ""}, {"paramName": "openid"}, {"paramName": "orderprice", "paramVal": ""}, {"paramName": "actiontype", "paramVal": ""}, {"paramName": "extinfo", "paramVal": ""}, {"paramName": "ext1", "paramVal": self.sku_id}, {"paramName": "ext2", "paramVal": ""}, {"paramName": "ext3", "paramVal": ""}, {"paramName": "ext4", "paramVal": ""}, {"paramName": "ext5", "paramVal": ""}, {"paramName": "ext6"}, {"paramName": "ext7", "paramVal": ""}, {"paramName": "ext8", "paramVal": "0"}, {"paramName": "ext9", "paramVal": "0|0|0|0|0||0|0"}, {"paramName": "ext10", "paramVal": "|||"}, { "paramName": "ext11", "paramVal": "http://wq.jd.com/wxapp/pages/pay/index/index", }, {"paramName": "ext12", "paramVal": "1"}, {"paramName": "ext13", "paramVal": ""}, {"paramName": "ext14", "paramVal": ""}, {"paramName": "ext15", "paramVal": ""}, {"paramName": "ext16", "paramVal": ""}, { "paramName": "ext17", "paramVal": "76161171%7Ciosapp%7Ct_335139774%7Cappshare%7CCopyURL_shareidde4fa5e467a1fbe323b52ed0fa61777f5ce3e1fe17503293501852_shangxiang_none%7C1751857899902", }, {"paramName": "ext18"}, {"paramName": "ext19", "paramVal": ""}, {"paramName": "ext20"}, { "paramName": "fpa", "paramVal": "7f07f4e1-6ac2-2918-ff9a-18320538d8b2-1743129927", }, { "paramName": "fpb", "paramVal": "BApXSBoHW4fJA8VrxmIXHrE1TcUW-_mloBgFTnghK9xJ1MvE2-4G2", }, {"paramName": "ext21", "paramVal": ""}, {"paramName": "ext22", "paramVal": ""}, {"paramName": "ext23", "paramVal": "NULL"}, {"paramName": "ext24", "paramVal": "NULL"}, {"paramName": "ext25", "paramVal": "NULL"}, {"paramName": "ext26", "paramVal": "NULL"}, {"paramName": "ext27", "paramVal": "NULL"}, {"paramName": "ext28", "paramVal": "NULL"}, {"paramName": "ext29", "paramVal": "NULL"}, {"paramName": "ext30", "paramVal": "NULL"}, {"paramName": "ext31", "paramVal": "NULL"}, {"paramName": "ext32", "paramVal": "NULL"}, {"paramName": "ext33", "paramVal": "NULL"}, {"paramName": "ext34", "paramVal": "NULL"}, {"paramName": "ext35", "paramVal": "NULL"}, {"paramName": "ext36", "paramVal": "NULL"}, {"paramName": "ext37", "paramVal": "NULL"}, {"paramName": "ext38", "paramVal": "NULL"}, {"paramName": "dt", "paramVal": ""}, ], "govUseGisLocation": False, "packageStyle": True, "sceneval": "2", "balanceDeviceInfo": {"resolution": "2048*1152"}, "balanceId": "5351641558031892481751857904612", } encrypt_body = self.sha256_hash(json.dumps(body)) timestamp = f"{int(time.time() * 1000)}" object_id = "cc85b" function_id = "balance_submitOrder_m" h5st = self.get_h5st(timestamp, encrypt_body, object_id, function_id) headers = { "accept": "application/json, text/plain, */*", "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "cache-control": "no-cache", "content-type": "application/x-www-form-urlencoded", "origin": "https://trade.m.jd.com", "pragma": "no-cache", "priority": "u=1, i", "referer": "https://trade.m.jd.com/", "sec-ch-ua": '"Chromium";v="140", "Not=A?Brand";v="24", "Microsoft Edge";v="140"', "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": self.user_agent, "x-referer-page": "https://trade.m.jd.com/pay", "x-rp-client": "h5_1.0.0", "cookie": self.cookies, } data = { "scval": self.sku_id, "body": json.dumps(body), "t": timestamp, "h5st": h5st, "appid": "m_core", "client": "Win32", "clientVersion": "2.5.2", "d_brand": "", "d_model": "", "functionId": "balance_submitOrder_m", "lang": "zh-CN", "loginType": "2", "networkType": "false", "osVersion": "", "screen": "1152*2048", "sdkVersion": "", "uuid": "17573259367521124301157", "x-api-eid-token": self.x_token, "xAPIScval2": "wx", "xAPIScval3": "unknown", } url = "https://api.m.jd.com/client.action" proxy = self._get_proxy() response = self._session.post( url, headers=headers, data=data, verify=False, proxies=proxy, ) logger.info( f"订单号:{self._order_num},app_store提交订单返回:{response.json()}" ) return response.json() def run(self): self.x_token, self.eid = self.get_x_token() # 提交预付款订单 self.get_current_order() order_res = self.submit_order() logger.info( f"订单号:{self._order_num},app_store提交预付款订单返回:{order_res}" ) # 火爆 if order_res.get("body", {}).get("errorCode") == "7201": return BusinessCode.JD_ORDER_RISK_ERR, { "deeplink": "", "order_id": "", "pay_id": "", "remark": str(order_res), } # 未登录 if order_res.get("body", {}).get("errorCode") == "302": return BusinessCode.JD_ORDER_CK_ERR, { "deeplink": "", "order_id": "", "pay_id": "", "remark": order_res.get("body", {}).get("errorReason"), } # 无货 if order_res.get("body", {}).get("errorCode") == "722": return BusinessCode.JD_ORDER_STOCK_ERR, { "deeplink": "", "order_id": "", "pay_id": "", "remark": order_res.get("body", {}) .get("submitOrderPromptVO", {}) .get("title"), } # 火爆 if order_res.get("body", {}).get("errorCode") == "601": return BusinessCode.JD_ORDER_RISK_ERR, { "deeplink": "", "order_id": "", "pay_id": "", "remark": str(order_res), } if order_res.get("code") != "0": return BusinessCode.JD_ORDER_NORMAL_ERR, { "deeplink": "", "order_id": "", "pay_id": "", "remark": str(order_res), } if order_res.get("body", {}).get("errorCode") == "601": return BusinessCode.JD_ORDER_NORMAL_ERR, { "deeplink": "", "order_id": "", "pay_id": "", "remark": str(order_res), } order_id = order_res.get("body", {}).get("order", {}).get("orderId") # 获取支付信息 pay_res = self.get_pay_res(order_id) logger.info(f"订单号:{self._order_num},app_store获取支付信息返回:{pay_res}") if ( order_res.get("body", {}).get("errorCode") == "302" and order_res.get("body", {}).get("errorReason") == "未登录" ): return BusinessCode.JD_ORDER_CK_ERR, { "deeplink": "", "order_id": "", "pay_id": "", "remark": str(order_res), } if pay_res.get("code") != "0": return BusinessCode.JD_ORDER_NORMAL_ERR, { "deeplink": "", "order_id": "", "pay_id": "", "remark": str(pay_res), } pay_id = pay_res["body"]["payId"] # 获取微信支付信息 return self.refresh_payment_url(pay_id, order_id) def refresh_payment_url(self, pay_id: str, order_id: int): logger.info(f"订单号:{pay_id},app_store刷新支付链接 {order_id}") pay_channel_res = self.plat_pay_channel_res(pay_id) logger.info( f"订单号:{self._order_num},app_store请求微信渠道返回:{pay_channel_res}" ) if pay_channel_res.get("code") == "601": return BusinessCode.JD_ORDER_RISK_ERR, { "deeplink": "", "order_id": "", "pay_id": "", "remark": str(pay_channel_res), } if pay_channel_res.get("code") != "0": return BusinessCode.JD_ORDER_NORMAL_ERR, { "deeplink": "", "order_id": "", "pay_id": "", "remark": str(pay_channel_res), } wx_pay_res = self.plat_wx_pay_res(pay_id) logger.info( f"订单号:{self._order_num},app_store获取微信支付信息返回:{wx_pay_res}" ) if wx_pay_res.get("code") != "0": return BusinessCode.JD_ORDER_NORMAL_ERR, { "deeplink": "", "order_id": "", "pay_id": "", "remark": str(wx_pay_res), } if wx_pay_res.get("errorCode") == "-1": return BusinessCode.JD_ORDER_CK_ERR, { "deeplink": "", "order_id": "", "pay_id": "", "remark": str(wx_pay_res), } return BusinessCode.SUCCESS, { "deeplink": wx_pay_res.get("payInfo", {}).get("mweb_url"), "order_id": str(order_id), "pay_id": str(pay_id), }