Files
live-hub-py/core/huya/shop_structs.py
T

804 lines
30 KiB
Python
Raw 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.
"""
虎牙充值相关 JCE 结构定义
字段顺序 = TAF tag 顺序(从 JS 逆向所得)
来源:m-shop.yaoguo.com 的 jce/ShopFacade.js、api/orderui.ts、api/mall/PlayMallNewHome.ts
"""
from typing import List, Dict, Optional
from .taf_protocol import TafOutputStream, TafInputStream, TafStruct, TafType
class OrderType:
HUYA_PHYSICAL = 1
TENCENT_VIRTUAL = 2
MAGIC_BOX = 3
MAGIC_BOX_DELIVERY = 4
PAID_COURSE = 5
HUYA_VIRTUAL = 6
LOTTERY_PICKUP = 7
DELIVERY_WORKBENCH = 11
GAME_ACCOUNT = 12
SHELF_GOODS = 17
class OrderStatus:
DEPOSIT_WAIT_PAY = 10
DEPOSIT_PAID = 20
WAIT_DELIVER = 30
WAIT_RECEIVE = 40
FINISHED = 50
FINISHED_CLOSED = 60
CANCELLED = 90
BALANCE_WAIT_PAY = 1000
CANCELLED_BALANCE_EXPIRED = 1001
def _opt_str(os: TafOutputStream, tag: int, val: str):
"""非空才写字符串(与浏览器一致,省默认值)"""
if val:
os.write_string(tag, val)
def _opt_int(os: TafOutputStream, tag: int, val):
"""非 0 才写整数"""
if val:
os.write_int64(tag, val)
def _opt_struct(os: TafOutputStream, tag: int, val):
"""非 None 才写结构体"""
if val is not None:
os.write_struct(tag, val)
def _opt_list(os: TafOutputStream, tag: int, val):
"""非空才写 list"""
if val:
os.write_list(tag, val)
def _opt_map(os: TafOutputStream, tag: int, val):
"""非空才写 map"""
if val:
os.write_map(tag, val)
def _skip_to_struct_end(ins: TafInputStream):
"""跳过当前结构里未解析的尾部字段,停在 STRUCT_END 前。"""
while True:
pos = ins.buf.tell()
tag, dtype = ins.read_head()
if dtype == TafType.STRUCT_END:
ins.buf.seek(pos)
return
ins.skip_field(dtype)
# ============================================================
# 基础结构
# ============================================================
class UserId(TafStruct):
"""用户标识(cookie 在这里)"""
def __init__(self):
self.lUid: int = 0 # tag 0
self.sGuid: str = "" # tag 1
self.sToken: str = "" # tag 2
self.sHuYaUA: str = "" # tag 3 "webh5&0.0.1&websocket&&diypc_52775"
self.sCookie: str = "" # tag 4 完整 cookie
self.iTokenType: int = 0 # tag 5
self.sDeviceInfo: str = "" # tag 6
self.sQIMEI: str = "" # tag 7
def write_to(self, os: TafOutputStream):
# HAR2 实证: 浏览器不优化空串/0值, 全写字段
os.write_int64(0, self.lUid)
os.write_string(1, self.sGuid)
os.write_string(2, self.sToken)
os.write_string(3, self.sHuYaUA)
os.write_string(4, self.sCookie)
os.write_int32(5, self.iTokenType)
os.write_string(6, self.sDeviceInfo)
os.write_string(7, self.sQIMEI)
def read_from(self, ins: TafInputStream):
self.lUid = ins.read_int64(0, default=self.lUid)
self.sGuid = ins.read_string(1, default=self.sGuid)
self.sToken = ins.read_string(2, default=self.sToken)
self.sHuYaUA = ins.read_string(3, default=self.sHuYaUA)
self.sCookie = ins.read_string(4, default=self.sCookie)
self.iTokenType = ins.read_int32(5, default=self.iTokenType)
self.sDeviceInfo = ins.read_string(6, default=self.sDeviceInfo)
self.sQIMEI = ins.read_string(7, default=self.sQIMEI)
class ShopAppInfo(TafStruct):
"""应用信息(HAR2 实证字段顺序: tag0 sAppId, tag1 sBizType, tag4 scene, tag5 sourceId"""
def __init__(self):
self.sAppId: str = "huya" # tag 0
self.sBizType: str = "" # tag 1
self.scene: int = 0 # tag 4
self.sourceId: str = "" # tag 5
def write_to(self, os: TafOutputStream):
# HAR2 实证: 全写字段(含空串/0)
os.write_string(0, self.sAppId)
os.write_string(1, self.sBizType)
os.write_int32(4, self.scene)
os.write_string(5, self.sourceId)
def read_from(self, ins: TafInputStream):
self.sAppId = ins.read_string(0, default=self.sAppId)
self.sBizType = ins.read_string(1, default=self.sBizType)
self.scene = ins.read_int32(4, default=self.scene)
self.sourceId = ins.read_string(5, default=self.sourceId)
# ============================================================
# wsLaunch 初始化
# ============================================================
class WsLaunchSubStruct(TafStruct):
"""wsLaunch tag4 子结构(5个空字符串字段,浏览器强制写)"""
def __init__(self):
self.s0: str = "" # tag 0
self.s1: str = "" # tag 1
self.s2: str = "" # tag 2
self.s3: str = "" # tag 3
self.s4: str = "" # tag 4
def write_to(self, os: TafOutputStream):
# 浏览器写空字符串(STRING1 length0),这里强制写以精确匹配
os.write_string(0, self.s0)
os.write_string(1, self.s1)
os.write_string(2, self.s2)
os.write_string(3, self.s3)
os.write_string(4, self.s4)
def read_from(self, ins: TafInputStream):
pass
class WsLaunchReq(TafStruct):
"""launch.wsLaunch 请求(tReq 是 STRUCT,不是 list
从 HAR 逆向:
tag0: lUid (int64)
tag1: string ""
tag2: sHuYaUA "webh5&1.0.0&huya"
tag3: appSrc "HUYA&ZH&2052"
tag4: 子struct (5个空字符串)
"""
def __init__(self):
self.lUid: int = 0 # tag 0
self.s1: str = "" # tag 1
self.sHuYaUA: str = "webh5&1.0.0&huya" # tag 2
self.appSrc: str = "HUYA&ZH&2052" # tag 3
self.sub: WsLaunchSubStruct = WsLaunchSubStruct() # tag 4
def write_to(self, os: TafOutputStream):
# 注意: 浏览器不优化空字符串,tag1 强制写(HAR 实证)
_opt_int(os, 0, self.lUid)
os.write_string(1, self.s1) # 强制写空字符串
_opt_str(os, 2, self.sHuYaUA)
_opt_str(os, 3, self.appSrc)
_opt_struct(os, 4, self.sub)
def read_from(self, ins: TafInputStream):
pass
# ============================================================
# 商品查询
# ============================================================
class GetGoodsInfoReqV5(TafStruct):
"""商品查询请求 (shopMiddleUI.getGoodsInfoV5)"""
def __init__(self):
self.userId = UserId() # tag 0
self.shopAppInfo = ShopAppInfo() # tag 1
self.pid: int = 0 # tag 2
self.gameId: str = "" # tag 3
self.spuId: str = "" # tag 4
self.channelStockCode: str = "" # tag 5
self.skuId: int = 0 # tag 6
self.inviterUid: int = 0 # tag 7
self.userModifyPriceId: int = 0 # tag 8
def write_to(self, os: TafOutputStream):
# HAR2 实证: 全写字段
os.write_struct(0, self.userId)
os.write_struct(1, self.shopAppInfo)
os.write_int64(2, self.pid)
os.write_string(3, self.gameId)
os.write_string(4, self.spuId)
os.write_string(5, self.channelStockCode)
os.write_int64(6, self.skuId)
os.write_int64(7, self.inviterUid)
os.write_int64(8, self.userModifyPriceId)
def read_from(self, ins: TafInputStream):
# 请求结构体一般不需要读,但保留
pass
class GoodsInfoRsp(TafStruct):
"""商品查询响应。"""
def __init__(self):
self.code: int = 0 # tag 0
self.message: str = "" # tag 1
self.goodsInfo = None # tag 2
self.selfGoods: int = 0 # tag 3
self.marketStatus: int = 0 # tag 5
self.timestamp: int = 0 # tag 6
def read_from(self, ins: TafInputStream):
self.code = ins.read_int32(0, default=self.code)
self.message = ins.read_string(1, default=self.message)
self.goodsInfo = ins.read_struct(2, GoodsInfoDetail)
self.selfGoods = ins.read_int32(3, default=self.selfGoods)
self.marketStatus = ins.read_int32(5, default=self.marketStatus)
self.timestamp = ins.read_int64(6, default=self.timestamp)
def write_to(self, os: TafOutputStream):
pass
@property
def spu_id(self) -> str:
return self.goodsInfo.baseInfo.spuId if self.goodsInfo else ""
@property
def sku_id(self) -> int:
return self.goodsInfo.priceInfo.first_sku_id if self.goodsInfo else 0
@property
def name(self) -> str:
return self.goodsInfo.baseInfo.name if self.goodsInfo else ""
@property
def price(self) -> int:
return self.goodsInfo.priceInfo.price if self.goodsInfo else 0
@property
def stock(self) -> int:
return self.goodsInfo.priceInfo.stock if self.goodsInfo else 0
@property
def buy_limit(self) -> int:
return self.goodsInfo.priceInfo.buyLimit if self.goodsInfo else 0
def to_dict(self) -> dict:
goods = self.goodsInfo.to_dict() if self.goodsInfo else {}
return {
"code": self.code,
"message": self.message,
"spu_id": goods.get("spu_id", ""),
"sku_id": goods.get("sku_id", 0),
"name": goods.get("name", ""),
"description": goods.get("description", ""),
"icon": goods.get("icon", ""),
"detail_url": goods.get("detail_url", ""),
"price": goods.get("price", 0),
"min_price": goods.get("min_price", 0),
"max_price": goods.get("max_price", 0),
"stock": goods.get("stock", 0),
"buy_limit": goods.get("buy_limit", 0),
"sku_list": goods.get("sku_list", []),
"self_goods": self.selfGoods,
"market_status": self.marketStatus,
"timestamp": self.timestamp,
"goods": goods,
}
class GoodsBaseInfo(TafStruct):
"""商品基础信息(getGoodsInfoV5 tag2.tag0)。"""
def __init__(self):
self.spuId: str = ""
self.appId: str = ""
self.name: str = ""
self.description: str = ""
self.icon: str = ""
self.detailUrl: str = ""
self.detailHtml: str = ""
def read_from(self, ins: TafInputStream):
self.spuId = ins.read_string(0, default=self.spuId)
self.appId = ins.read_string(1, default=self.appId)
self.name = ins.read_string(2, default=self.name)
self.description = ins.read_string(4, default=self.description)
self.icon = ins.read_string(5, default=self.icon)
self.detailUrl = ins.read_string(6, default=self.detailUrl)
self.detailHtml = ins.read_string(7, default=self.detailHtml)
_skip_to_struct_end(ins)
def write_to(self, os: TafOutputStream):
pass
def to_dict(self) -> dict:
return {
"spu_id": self.spuId,
"app_id": self.appId,
"name": self.name,
"description": self.description,
"icon": self.icon,
"detail_url": self.detailUrl,
}
class GoodsSkuItem(TafStruct):
"""商品 SKU 信息(getGoodsInfoV5 tag2.tag4.tag3 map value)。"""
def __init__(self):
self.skuId: int = 0
self.spuId: str = ""
self.price: int = 0
self.stock: int = 0
self.status: int = 0
def read_from(self, ins: TafInputStream):
self.skuId = ins.read_int64(0, default=self.skuId)
self.spuId = ins.read_string(1, default=self.spuId)
self.price = ins.read_int64(2, default=self.price)
self.stock = ins.read_int64(3, default=self.stock)
self.status = ins.read_int32(4, default=self.status)
_skip_to_struct_end(ins)
def write_to(self, os: TafOutputStream):
pass
@staticmethod
def read_map_value(ins: TafInputStream, dtype: int):
if dtype != TafType.STRUCT_BEGIN:
ins.skip_field(dtype)
return None
item = GoodsSkuItem()
item.read_from(ins)
_end_tag, end_type = ins.read_head()
if end_type != TafType.STRUCT_END:
raise ValueError(f"期望 SKU STRUCT_END,实际 0x{end_type:02x}")
return item
def to_dict(self) -> dict:
return {
"sku_id": self.skuId,
"spu_id": self.spuId,
"price": self.price,
"stock": self.stock,
"status": self.status,
}
class GoodsPriceInfo(TafStruct):
"""商品价格与 SKU 信息(getGoodsInfoV5 tag2.tag4)。"""
def __init__(self):
self.spuId: str = ""
self.minPrice: int = 0
self.maxPrice: int = 0
self.skuMap: Dict[int, GoodsSkuItem] = {}
self.stock: int = 0
self.buyLimit: int = 0
self.price: int = 0
def _read_sku_map(self, ins: TafInputStream):
found = ins._find_tag(3, required=False)
if not found:
return {}
if found[1] != TafType.MAP:
ins.skip_field(found[1])
return {}
count = ins._read_int_len()
result = {}
for _ in range(count):
_, key_type = ins.read_head()
key = ins._read_int_value(key_type)
_, value_type = ins.read_head()
item = GoodsSkuItem.read_map_value(ins, value_type)
if item is not None:
result[int(key)] = item
return result
def read_from(self, ins: TafInputStream):
self.spuId = ins.read_string(0, default=self.spuId)
self.minPrice = ins.read_int64(1, default=self.minPrice)
self.maxPrice = ins.read_int64(2, default=self.maxPrice)
self.skuMap = self._read_sku_map(ins)
self.stock = ins.read_int64(4, default=self.stock)
self.buyLimit = ins.read_int64(5, default=self.buyLimit)
self.price = ins.read_int64(7, default=self.price)
_skip_to_struct_end(ins)
def write_to(self, os: TafOutputStream):
pass
@property
def first_sku_id(self) -> int:
if not self.skuMap:
return 0
return sorted(self.skuMap.keys())[0]
@property
def sku_list(self) -> list[dict]:
return [self.skuMap[key].to_dict() for key in sorted(self.skuMap.keys())]
def to_dict(self) -> dict:
return {
"spu_id": self.spuId,
"sku_id": self.first_sku_id,
"price": self.price or self.minPrice,
"min_price": self.minPrice,
"max_price": self.maxPrice,
"stock": self.stock,
"buy_limit": self.buyLimit,
"sku_list": self.sku_list,
}
class GoodsInfoDetail(TafStruct):
"""getGoodsInfoV5 响应里的 goodsInfo 主体。"""
def __init__(self):
self.baseInfo = GoodsBaseInfo()
self.priceInfo = GoodsPriceInfo()
def read_from(self, ins: TafInputStream):
self.baseInfo = ins.read_struct(0, GoodsBaseInfo) or self.baseInfo
self.priceInfo = ins.read_struct(4, GoodsPriceInfo) or self.priceInfo
_skip_to_struct_end(ins)
def write_to(self, os: TafOutputStream):
pass
def to_dict(self) -> dict:
data = self.baseInfo.to_dict()
data.update(self.priceInfo.to_dict())
return data
# ============================================================
# 订单历史
# ============================================================
class OrderListShopInfo(TafStruct):
"""订单明细里的店铺信息(只取展示需要的字段)"""
def __init__(self):
self.shopName: str = "" # tag 0
def read_from(self, ins: TafInputStream):
self.shopName = ins.read_string(0, default=self.shopName)
_skip_to_struct_end(ins)
def write_to(self, os: TafOutputStream):
pass
class OrderListGoodsDetail(TafStruct):
"""订单明细(queryUserOrderList 响应 tag16"""
def __init__(self):
self.spuId: str = "" # tag 4
self.skuId: int = 0 # tag 16
self.buyerUid: int = 0 # tag 18
self.virtualType: int = 0 # tag 19
self.quantity: int = 0 # tag 20
self.shopInfo: Optional[OrderListShopInfo] = None # tag 21
self.points: int = 0 # tag 23
def read_from(self, ins: TafInputStream):
self.spuId = ins.read_string(4, default=self.spuId)
self.skuId = ins.read_int64(16, default=self.skuId)
self.buyerUid = ins.read_int64(18, default=self.buyerUid)
self.virtualType = ins.read_int32(19, default=self.virtualType)
self.quantity = ins.read_int64(20, default=self.quantity)
self.shopInfo = ins.read_struct(21, OrderListShopInfo)
self.points = ins.read_int64(23, default=self.points)
_skip_to_struct_end(ins)
def write_to(self, os: TafOutputStream):
pass
class OrderListItem(TafStruct):
"""订单列表项(queryUserOrderList 响应 tag3 的 list 元素)"""
def __init__(self):
self.bizOrderId: str = "" # tag 0 shop10148750
self.appId: str = "" # tag 1 shop
self.orderId: str = "" # tag 2
self.pid: int = 0 # tag 3
self.shopName: str = "" # tag 4
self.orderStatus: int = 0 # tag 5
self.itemName: str = "" # tag 8
self.unitPrice: int = 0 # tag 9 分
self.quantity: int = 0 # tag 10
self.totalPrice: int = 0 # tag 12 分
self.createTime: int = 0 # tag 14 毫秒时间戳
self.payTime: int = 0 # tag 15 毫秒时间戳
self.goodsDetail: Optional[OrderListGoodsDetail] = None # tag 16
def read_from(self, ins: TafInputStream):
self.bizOrderId = ins.read_string(0, default=self.bizOrderId)
self.appId = ins.read_string(1, default=self.appId)
self.orderId = ins.read_string(2, default=self.orderId)
self.pid = ins.read_int64(3, default=self.pid)
self.shopName = ins.read_string(4, default=self.shopName)
self.orderStatus = ins.read_int32(5, default=self.orderStatus)
self.itemName = ins.read_string(8, default=self.itemName)
self.unitPrice = ins.read_int64(9, default=self.unitPrice)
self.quantity = ins.read_int64(10, default=self.quantity)
self.totalPrice = ins.read_int64(12, default=self.totalPrice)
self.createTime = ins.read_int64(14, default=self.createTime)
self.payTime = ins.read_int64(15, default=self.payTime)
self.goodsDetail = ins.read_struct(16, OrderListGoodsDetail)
_skip_to_struct_end(ins)
def write_to(self, os: TafOutputStream):
pass
class QueryUserOrderListReq(TafStruct):
"""查询购买历史订单 (revenueWebUI.queryUserOrderList)"""
def __init__(self):
self.userId = UserId() # tag 0
self.offset: int = 0 # tag 1
self.orderType: int = 1 # tag 2
self.pageSize: int = 10 # tag 3
self.status: int = 0 # tag 4
def write_to(self, os: TafOutputStream):
os.write_struct(0, self.userId)
os.write_int32(1, self.offset)
os.write_int32(2, self.orderType)
os.write_int32(3, self.pageSize)
os.write_int32(4, self.status)
def read_from(self, ins: TafInputStream):
pass
class QueryUserOrderListRsp(TafStruct):
"""购买历史订单响应"""
def __init__(self):
self.code: int = 0
self.message: str = ""
self.totalCount: int = 0
self.orders: List[OrderListItem] = []
@staticmethod
def _read_order_item(ins: TafInputStream, _tag: int):
item = OrderListItem()
item.read_from(ins)
_end_tag, dtype = ins.read_head()
if dtype != TafType.STRUCT_END:
raise ValueError(f"期望订单 STRUCT_END,实际 0x{dtype:02x}")
return item
def read_from(self, ins: TafInputStream):
self.code = ins.read_int32(0, default=self.code)
self.message = ins.read_string(1, default=self.message)
self.totalCount = ins.read_int64(2, default=self.totalCount)
self.orders = ins.read_list(3, item_reader=self._read_order_item)
def write_to(self, os: TafOutputStream):
pass
# ============================================================
# 下单
# ============================================================
class CreateOrderExtraParam(TafStruct):
def __init__(self):
self.freight: int = 0 # tag 0
self.channelStockType: str = "" # tag 1
self.channelStockCode: str = "" # tag 2
self.relatedBizId: str = "" # tag 3
self.bizParams: str = "" # tag 4
self.popupTraceId: str = "" # tag 5
self.supplierUid: int = 0 # tag 6
self.categoryId: str = "" # tag 7
self.ext: str = "" # tag 8
def write_to(self, os: TafOutputStream):
# HAR 实证:下单 extraParam 会强制写默认 0/空串字段
os.write_int64(0, self.freight)
os.write_string(1, self.channelStockType)
os.write_string(2, self.channelStockCode)
os.write_string(3, self.relatedBizId)
os.write_string(4, self.bizParams)
os.write_string(5, self.popupTraceId)
os.write_int64(6, self.supplierUid)
if self.categoryId:
os.write_string(7, self.categoryId)
os.write_string(8, self.ext)
def read_from(self, ins: TafInputStream):
pass
class CreateOrderPromotionParam(TafStruct):
def __init__(self):
self.yxjDeductPrice: int = 0 # tag 0
self.userModifyPriceId: int = 0 # tag 1
self.enablePromotion: int = 1 # tag 2
def write_to(self, os: TafOutputStream):
# HAR 实证:tag0/tag1 为 0tag2 为 1
os.write_int64(0, self.yxjDeductPrice)
os.write_int64(1, self.userModifyPriceId)
os.write_int32(2, self.enablePromotion)
def read_from(self, ins: TafInputStream):
pass
class CreateOrderAccountParam(TafStruct):
def __init__(self):
self.payoutTypeList: List[int] = [] # tag 0 Vector<INT32>
self.payoutChargeAmount: int = 0 # tag 1
self.cancelPayoutTypeList: List[int] = [] # tag 2
self.recycleSupplierId: int = 0 # tag 3
self.claimPrice: int = 0 # tag 4
def write_to(self, os: TafOutputStream):
# HAR 实证:空 list/0 值也会写出
os.write_list(0, self.payoutTypeList)
os.write_int64(1, self.payoutChargeAmount)
os.write_list(2, self.cancelPayoutTypeList)
os.write_int64(3, self.recycleSupplierId)
os.write_int64(4, self.claimPrice)
def read_from(self, ins: TafInputStream):
pass
class PromotionItem(TafStruct):
def __init__(self):
self.promotionId: int = 0 # tag 0
self.promotionType: int = 0 # tag 1
def write_to(self, os: TafOutputStream):
_opt_int(os, 0, self.promotionId)
_opt_int(os, 1, self.promotionType)
def read_from(self, ins: TafInputStream):
self.promotionId = ins.read_int64(0, default=self.promotionId)
self.promotionType = ins.read_int32(1, default=self.promotionType)
class CreateOrderReqV5(TafStruct):
"""下单请求 (shopMiddleUI.createOrderV5)"""
def __init__(self):
self.userId = UserId() # tag 0
self.shopAppInfo = ShopAppInfo() # tag 1
self.receiveId: int = 0 # tag 2
self.pid: int = 0 # tag 3
self.skuId: int = 0 # tag 4
self.itemCount: int = 1 # tag 5
self.remark: str = "" # tag 6
self.spuId: str = "" # tag 7
self.gameId: str = "" # tag 8
self.orderId: int = 0 # tag 9
self.src: int = 0 # tag 10
self.couponUserIds: List[int] = [] # tag 11 Vector<INT64>
self.orderType: int = 0 # tag 12
self.extraParam: Optional[CreateOrderExtraParam] = None # tag 13
self.scene: int = 0 # tag 14
self.promotionItems: List = [] # tag 15 Vector<PromotionItem>
self.sourceId: str = "" # tag 16
self.env: Dict[str, str] = {} # tag 17 Map<STRING,STRING>
self.orderScene: int = 0 # tag 18
self.watchWord: str = "" # tag 19
self.marketingChannel: str = "" # tag 20
self.promotionParam: Optional[CreateOrderPromotionParam] = None # tag 21
self.externalTraceKey: str = "" # tag 22
self.kefuUid: int = 0 # tag 23
self.accountParam: Optional[CreateOrderAccountParam] = None # tag 24
self.parentOrderId: int = 0 # tag 25
self.vendorAccountType: str = "" # tag 26
self.vendorAccountVal: str = "" # tag 27
self.vendorSubAccountVal: str = "" # tag 28
self.vendorSubAccountType: str = "" # tag 29
self.bizType: int = 0 # tag 30
self.gameCategoryId: int = 0 # tag 31
self.ext: str = "" # tag 32
def write_to(self, os: TafOutputStream):
# HAR 实证:createOrderV5 会写出完整字段,即使值为 0/空串/空 list
os.write_struct(0, self.userId)
os.write_struct(1, self.shopAppInfo)
os.write_int64(2, self.receiveId)
os.write_int64(3, self.pid)
os.write_int64(4, self.skuId)
os.write_int64(5, self.itemCount)
os.write_string(6, self.remark)
os.write_string(7, self.spuId)
os.write_string(8, self.gameId)
os.write_int64(9, self.orderId)
os.write_int32(10, self.src)
os.write_list(11, self.couponUserIds)
os.write_int32(12, self.orderType)
os.write_struct(13, self.extraParam or CreateOrderExtraParam())
os.write_int32(14, self.scene)
os.write_list(15, self.promotionItems)
os.write_string(16, self.sourceId)
os.write_map(17, self.env)
os.write_int32(18, self.orderScene)
os.write_string(19, self.watchWord)
os.write_string(20, self.marketingChannel)
os.write_struct(21, self.promotionParam or CreateOrderPromotionParam())
os.write_string(22, self.externalTraceKey)
os.write_int64(23, self.kefuUid)
os.write_struct(24, self.accountParam or CreateOrderAccountParam())
os.write_int64(25, self.parentOrderId)
os.write_string(26, self.vendorAccountType)
os.write_string(27, self.vendorAccountVal)
os.write_string(28, self.vendorSubAccountVal)
os.write_string(29, self.vendorSubAccountType)
os.write_int32(30, self.bizType)
os.write_int32(31, self.gameCategoryId)
os.write_string(32, self.ext)
def read_from(self, ins: TafInputStream):
pass
class CreateOrderRsp(TafStruct):
"""下单响应 (shopMiddleUI.createOrderV5)"""
def __init__(self):
self.code: int = 0 # tag 0
self.message: str = "" # tag 1
self.orderId: int = 0 # tag 2 虎牙订单号
self.subOrderId: int = 0 # tag 4
self.orderStatus: int = 0 # tag 5
self.riskUrl: str = "" # tag 8 风控跳转URLcode!=200时可能有)
def read_from(self, ins: TafInputStream):
self.code = ins.read_int32(0, default=self.code)
self.message = ins.read_string(1, default=self.message)
self.orderId = ins.read_int64(2, default=self.orderId)
self.subOrderId = ins.read_int64(4, default=self.subOrderId)
self.orderStatus = ins.read_int32(5, default=self.orderStatus)
self.riskUrl = ins.read_string(8, default=self.riskUrl)
def write_to(self, os: TafOutputStream):
pass
# ============================================================
# 支付(payOrderSubmitV5
# ============================================================
class PayOrderRes(TafStruct):
"""
发起支付响应 (shopMiddleUI.payOrderSubmitV5)
结构从 state_shop_ts.js 的 payOrderRes 推断,tag 顺序按出现顺序
"""
def __init__(self):
self.code: int = 0 # tag 0
self.message: str = "" # tag 1
self.orderId: int = 0 # tag 2 虎牙订单号
self.appOrderId: str = "" # tag 3
self.payOrderId: str = "" # tag 4 支付宝 payOrderId
self.payUrl: str = "" # tag 5 支付宝下单URL(含sign)
self.amount: int = 0 # tag 6
def read_from(self, ins: TafInputStream):
self.code = ins.read_int32(0, default=self.code)
self.message = ins.read_string(1, default=self.message)
self.orderId = ins.read_int64(2, default=self.orderId)
self.appOrderId = ins.read_string(3, default=self.appOrderId)
self.payOrderId = ins.read_string(4, default=self.payOrderId)
self.payUrl = ins.read_string(5, default=self.payUrl)
self.amount = ins.read_int64(6, default=self.amount)
def write_to(self, os: TafOutputStream):
pass
def to_dict(self) -> dict:
return {
"code": self.code,
"message": self.message,
"order_id": self.orderId,
"app_order_id": self.appOrderId,
"pay_order_id": self.payOrderId,
"pay_url": self.payUrl,
"amount": self.amount,
}