""" 虎牙充值相关 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 def to_dict(self) -> dict: return { "shop_name": self.shopName, } 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 def to_dict(self) -> dict: return { "spu_id": self.spuId, "sku_id": self.skuId, "buyer_uid": self.buyerUid, "virtual_type": self.virtualType, "quantity": self.quantity, "shop_info": self.shopInfo.to_dict() if self.shopInfo else None, "points": self.points, } 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 def to_dict(self) -> dict: return { "biz_order_id": self.bizOrderId, "app_id": self.appId, "order_id": self.orderId, "pid": self.pid, "shop_name": self.shopName, "order_status": self.orderStatus, "item_name": self.itemName, "unit_price": self.unitPrice, "quantity": self.quantity, "total_price": self.totalPrice, "create_time": self.createTime, "pay_time": self.payTime, "goods_detail": self.goodsDetail.to_dict() if self.goodsDetail else None, } 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 def to_dict(self) -> dict: return { "code": self.code, "message": self.message, "total_count": self.totalCount, "orders": [item.to_dict() for item in self.orders], } # ============================================================ # 下单 # ============================================================ 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 为 0,tag2 为 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 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 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 self.sourceId: str = "" # tag 16 self.env: Dict[str, str] = {} # tag 17 Map 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 风控跳转URL(code!=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, }