"""回单/上报接口 Mixin — step17-20(管理端)。 所有方法签名/返回值/默认值与旧 yun8_sync/client.py 逐字一致, 仅将原始 requests.Session 调用替换为 BaseHttpClient(self.admin_http)。 Usage: from tests.apis.yun8.receipt_api import ReceiptApi class Yun8ApiClient(ReceiptApi, ...): ... """ import re class ReceiptApi: """回单/上报接口(挂载于 Yun8ApiClient,依赖 admin_http / ac 属性)。""" # ================================================================== # Step 17: 查询运单上传 → 提取 payNo # ================================================================== def step17_query_upload_for_payno(self, order_code: str, page_size: int = 20, page_num: int = 1) -> dict: """ Postman Test Script: var sendMsg = jsonData.data.records[0].sendMsg || ""; var match = sendMsg.match(/【([^】]+)】/); var result = match ? match[1] : ""; pm.collectionVariables.set("payNo", result); Returns: {"payNo": str, "raw_records": list} """ params = { "gmtCreatedRange[]": ["", ""], "lastLoadingTimeRange": "", "fillTimeRange": "", "lastUnloadingTimeRange": "", "signTimeRange": "", "settleTimeRange": "", "gmtModifiedRange": "", "pageNum": page_num, "pageSize": page_size, "status": "5", # <-- 注意:status=5 "payerReceiverLinkMan": self.ac.get("payer_receiver_link_man", ""), "sortField": "", "sortType": "", "gmtCreatedStart": "", "gmtCreatedEnd": "", "orderCode": order_code, } data = self.admin_http.get("/ntocc-basic-api/dytBusiness/orderDetail", params) records = data.get("data", {}).get("records", []) pay_no = "" if records: send_msg = records[0].get("sendMsg", "") match = re.search(r"【([^】]+)】", send_msg) if match: pay_no = match.group(1) return {"payNo": pay_no, "raw_records": records} # ================================================================== # Step 18: 查询打款记录 → 提取所有 code # ================================================================== def step18_query_remit_records(self, order_code: str, page_size: int = 20) -> list[dict]: """ Postman Test Script: pm.collectionVariables.set("remitCode", jsonData.data.records[0].code); 分页获取全部打款记录。Returns: [{code, ...}, ...] """ all_records = [] page_num = 1 while True: params = { "pageNum": page_num, "pageSize": page_size, "pageForm": "arpa_2", "orderDetailNumber": order_code, "sortField": "", "sortType": "", "isPayAdvance": "", "platPayType": "", "gmtModifiedStart": "", "gmtModifiedEnd": "", } data = self.admin_http.get("/ntocc-tms-api/remitDefinite", params) # code 可能是 0 (成功) 或 None/null (也是成功) resp_code = data.get("code") if resp_code is not None and resp_code != 0: raise RuntimeError(f"查询打款记录失败: {data.get('msg')}") page_data = data.get("data", {}) records = page_data.get("records", []) all_records.extend(records) total = page_data.get("total", 0) if page_num * page_size >= total: break page_num += 1 return all_records # ================================================================== # Step 19: 查询文件名前缀 → 提取 filePrefix # ================================================================== def step19_query_file_prefix(self, remit_code: str) -> str: """ Postman Test Script: const msg = jsonData.msg || ''; const prefix = '文件名前缀:'; const index = msg.indexOf(prefix); const filePrefix = index !== -1 ? msg.substring(index + prefix.length).trim() : ''; pm.collectionVariables.set('filePrefix', filePrefix); Returns: filePrefix string """ params = {"code": remit_code} data = self.admin_http.get( "/ntocc-tms-api/centralizedPayment/downLoadElectronicReceipt", params) msg = data.get("msg", "") prefix_marker = "文件名前缀:" idx = msg.find(prefix_marker) if idx != -1: return msg[idx + len(prefix_marker):].strip() return "" # ================================================================== # Step 20: 上报运单 (reportOrderDetail) # ================================================================== def step20_report_order_detail(self, codes: str, report_type: int = 1) -> dict: """ POST /ntocc-basic-api/dytBusiness/reportOrderDetail Content-Type: application/json;charset=UTF-8 Body: {"codes": "...", "type": 1} 在打款完成后上报运单,完成整个流程闭环。 """ body = {"codes": codes, "type": report_type} return self.admin_http.post_json( "/ntocc-basic-api/dytBusiness/reportOrderDetail", body)