AutoRpa/rpa_cart/cart_yaoex.py

107 lines
3.6 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.

# 1 号药城加入购物车。
from __future__ import annotations
import time
from typing import Any
import requests
import urllib3
from cart_add import KIND_OK, KIND_SYSTEM, AddOutcome, classify_mall_message
from cart_match import CartOffer
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
GATEWAY = "https://gateway-b2b.fangkuaiyi.com"
YAOEX_ADD_URL = f"{GATEWAY}/small/shopCart/addShopCart"
# 按再搜到的 sku 把数量加入 1 号药城购物车。没有 sku 当系统失败,不改业务原因。
def add_yaoex_cart(auth, offer: CartOffer, qty: int, *, session: requests.Session | None = None) -> AddOutcome:
ids = _ids(offer)
if not ids["skuId"] and not ids["spuCode"]:
return AddOutcome(kind=KIND_SYSTEM, reason="缺少 sku")
payload = _form(
auth,
{
"skuId": ids["skuId"],
"spuCode": ids["spuCode"],
"sellerCode": ids["sellerCode"],
"amount": int(qty),
},
)
own = session is None
client = session or requests.Session()
try:
response = client.post(
YAOEX_ADD_URL,
data=payload,
headers=_headers(),
timeout=30,
verify=False,
)
response.raise_for_status()
return _outcome_from_json(response.json())
except Exception as exc:
return AddOutcome(kind=KIND_SYSTEM, reason=str(exc))
finally:
if own:
client.close()
# 从报价里取出加车要的 sku、spu 和商家编码。
def _ids(offer: CartOffer) -> dict[str, str]:
raw = offer.extra.get("raw") if isinstance(offer.extra.get("raw"), dict) else offer.extra
if not isinstance(raw, dict):
raw = {}
sku = str(raw.get("skuId") or raw.get("id") or offer.sku_id or "")
spu = str(raw.get("spuCode") or offer.sku_id or "")
seller = str(raw.get("sellerCode") or raw.get("vendorCode") or raw.get("shopCode") or "")
return {"skuId": sku, "spuCode": spu, "sellerCode": seller}
# 拼 1 号药城表单:带上登录 token,再叠上加车字段。
def _form(auth, extra: dict[str, Any]) -> dict[str, Any]:
payload = {
"traderName": "yaoex_pc",
"trader": "pc",
"closesignature": "yes",
"signature_method": "md5",
"signature": "****",
"timestamp": str(int(time.time() * 1000)),
"token": auth.token,
"userToken": auth.token,
"userId": getattr(auth, "user_id", ""),
"buyerCode": getattr(auth, "buyer_code", ""),
}
payload.update(extra)
return payload
# 1 号药城加车请求头。来源页是购物车。
def _headers() -> dict[str, str]:
return {
"Content-Type": "application/x-www-form-urlencoded",
"X-Requested-With": "XMLHttpRequest",
"X-Request-Agent": "Axios",
"traderName": "yaoex_pc",
"trader": "pc",
"Origin": "https://mall.yaoex.com",
"Referer": "https://mall.yaoex.com/v2/cart/",
}
# 把加车回包收成成功、业务失败或系统失败。看不懂的回包当系统失败。
def _outcome_from_json(payload: object) -> AddOutcome:
if not isinstance(payload, dict):
return AddOutcome(kind=KIND_SYSTEM, reason="加购返回异常")
msg = str(payload.get("msg") or payload.get("message") or payload.get("errorMsg") or "")
code = payload.get("code")
success = payload.get("success")
if success is True or code in (0, "0", 200, "200"):
return AddOutcome(kind=KIND_OK)
if msg:
return classify_mall_message(msg)
return AddOutcome(kind=KIND_SYSTEM, reason="加购失败")