接下來的就是物流的應用,宅急便的技術文件請自己合法去跟黑貓技術客服要
*授權碼請至統一速達契約客戶專區登入頁面的「取得印單 API授權碼」點選連結查詢 。
https://www.takkyubin.com.tw/YMTContract/aspx/Login.aspx
本服務網址如
後 說明:
測試 環境 https://egs.suda.com.tw:8443/api/Egs/{服務名稱 }
正式 環境 https://api.suda.com.tw/api/Egs/{服務名稱 }
json格式
[
{
"訂單編號": 81209,
"下單時間": "2025-02-25T09:16:55",
"姓名": "陳大頭",
"聯絡電話": "0911212151",
"Email": "your@mail.com",
"地址": "709 台南市 安南區 1234567",
"消費金額": "4956",
"付款方式": "LINE Pay",
"訂單備註": "",
"處理訂單備註": [
{
"id": 1435511,
"key": "is_vat_exempt",
"value": "no"
},
{
"id": 1435512,
"key": "additional_temp",
"value": "冷凍"
},
{
"id": 1435513,
"key": "cpreftrack_woocommerce_referrer",
"value": ""
},
{
"id": 1435514,
"key": "_wc_cancel_key",
"value": "df41de84581d148c1174b1e0beabb804"
},
{
"id": 1435516,
"key": "billing_phone",
"value": "0932894722"
},
{
"id": 1435517,
"key": "additional_deliver_date",
"value": "不指定"
},
{
"id": 1435518,
"key": "additional_shipping_receive_time",
"value": "不指定"
},
{
"id": 1435519,
"key": "additional_gift2",
"value": "無送禮需求"
},
{
"id": 1435520,
"key": "smilepayei_donate",
"value": ""
},
{
"id": 1435521,
"key": "smilepayei_lovekey",
"value": ""
},
{
"id": 1435522,
"key": "smilepayei_carrier_type",
"value": "EJ0113"
},
{
"id": 1435523,
"key": "smilepayei_carrier_id",
"value": ""
},
{
"id": 1435524,
"key": "smilepayei_buyer_id",
"value": ""
},
{
"id": 1435526,
"key": "ywot_tracking_code",
"value": ""
},
{
"id": 1435527,
"key": "ywot_tracking_postcode",
"value": ""
},
{
"id": 1435528,
"key": "ywot_carrier_id",
"value": "UNKNOWN"
},
{
"id": 1435529,
"key": "ywot_pick_up_date",
"value": ""
},
{
"id": 1435530,
"key": "ywot_picked_up",
"value": ""
},
{
"id": 1435531,
"key": "_linepay_payment_status",
"value": "confirmed"
},
{
"id": 1435532,
"key": "_linepay_reserved_transaction_id",
"value": "2025022562005572410"
},
{
"id": 1435551,
"key": "_new_order_email_sent",
"value": "true"
},
{
"id": 1435563,
"key": "_linepay_transaction_balanced_amount",
"value": "4956"
},
{
"id": 1435564,
"key": "_ga_tracked",
"value": "1"
},
{
"id": 1435789,
"key": "oshwoo_aggregated",
"value": "3"
}
],
"商品": [
{
"商品名稱": "商品1",
"SKU": "P01234512",
"數量": 1,
"單價": 1180
},
{
"商品名稱": "商品2",
"SKU": "P02112121",
"數量": 1,
"單價": 0
}
],
"收件人姓名": "陳小明",
"收件人電話": "0912112111",
"收件人地址": "台南市中西區12313212號"
}
import json import requests from datetime import datetime # ------------------------------- # 1. 列印託運單 (PrintOBT) # ------------------------------- # 讀取 export_order.json 中的訂單資料 with open("export_order.json", "r", encoding="utf-8") as f: orders = json.load(f) # 測試環境與認證資料 customer_id = "95525512" customer_token = "11231151" # 寄件人資訊(更新後) sender_info = { "SenderName": "寄件者姓名", "SenderTel": "寄件者電話", "SenderMobile": "0952691828", # 更新後 "SenderZipCode": "70523K", # 更新後 "SenderAddress": "台南市安南區1234567號" } # 組合 API 所需訂單資料 api_orders = [] for order in orders: order_id = str(order.get("訂單編號")) recipient_name = order.get("收件人姓名", order.get("姓名")) recipient_tel = order.get("收件人電話", order.get("聯絡電話")) recipient_mobile = order.get("聯絡電話") recipient_address = order.get("收件人地址", order.get("地址")) # 以下單時間轉換為 yyyyMMdd 格式作為出貨與配達日期 order_date = datetime.fromisoformat(order.get("下單時間")).strftime("%Y%m%d") # 根據 API 規格組合每筆訂單資料,ProductName 固定使用 "食品" api_order = { "OBTNumber": "", # 採用系統分配時,此欄留空 "OrderId": order_id, "Thermosphere": "0001", # 例如:0001 表示常溫 "Spec": "0001", # 例如:0001 表示 60cm "ReceiptLocation": "01", # 01 表示到宅 "ReceiptStationNo": "", "RecipientName": recipient_name, "RecipientTel": recipient_tel, "RecipientMobile": recipient_mobile, "RecipientAddress": recipient_address, "SenderName": sender_info["SenderName"], "SenderTel": sender_info["SenderTel"], "SenderMobile": sender_info["SenderMobile"], "SenderZipCode": sender_info["SenderZipCode"], "SenderAddress": sender_info["SenderAddress"], "ShipmentDate": order_date, "DeliveryDate": order_date, # 這裡暫以下單日作為出貨及配達日期,可根據需求調整 "DeliveryTime": "04", # 04 表示不指定 "IsFreight": "N", "IsCollection": "N", "CollectionAmount": 0, "IsSwipe": "Y", "IsDeclare": "N", "DeclareAmount": 0, "ProductTypeId": "0015", # 例如:0015 表示其他類別 "ProductName": "食品", # 固定使用 "食品" "Memo": order.get("訂單備註", "") } api_orders.append(api_order) # 組合最終的印單 API 請求內容 print_payload = { "CustomerId": customer_id, "CustomerToken": customer_token, "PrintType": "01", # 01 表示使用系統分配託運單號 "PrintOBTType": "01", # 例如:01 代表 A4 二模宅配 "Orders": api_orders } # 測試環境印單 API URL print_api_url = "https://egs.suda.com.tw:8443/api/Egs/PrintOBT" headers = {"Content-Type": "application/json"} # 呼叫印單 API response_print = requests.post(print_api_url, json=print_payload, headers=headers, verify=False) # 組合印單交換資訊 print_exchange = { "request": print_payload, "response": response_print.json() if response_print.status_code == 200 else {"error": response_print.text} } # 保存印單交換資訊至 tcat.json with open("tcat.json", "w", encoding="utf-8") as f: json.dump(print_exchange, f, ensure_ascii=False, indent=4) print("PrintOBT API 交換資訊已存檔至 tcat.json") # ------------------------------- # 2. 下載 PDF (DownloadOBT) # ------------------------------- # 從印單交換資訊中取得 FileNo file_no = print_exchange.get("response", {}).get("Data", {}).get("FileNo", "") if not file_no: print("找不到 FileNo,請確認 tcat.json 中有正確回傳 FileNo。") exit(1) # 組合下載 PDF 請求內容 download_payload = { "CustomerId": customer_id, "CustomerToken": customer_token, "FileNo": file_no # 若需要補印特定託運單,可加入 "Orders" 欄位 } # 測試環境下載 API URL download_api_url = "https://egs.suda.com.tw:8443/api/Egs/DownloadOBT" # 呼叫下載 API (回傳內容為二進位資料流) response_download = requests.post(download_api_url, json=download_payload, headers=headers, verify=False) # 組合下載交換資訊 download_exchange = { "request": download_payload, "response": { "status_code": response_download.status_code, "headers": dict(response_download.headers) } } if response_download.status_code == 200: pdf_data = response_download.content # 保存 PDF 檔案 with open("consignment.pdf", "wb") as f: f.write(pdf_data) download_exchange["response"]["content_length"] = len(pdf_data) print("託運單 PDF 已下載並保存為 consignment.pdf") else: download_exchange["response"]["error"] = response_download.text print("下載 PDF 失敗,錯誤資訊:", response_download.text) # 保存下載交換資訊至 tcat_download.json with open("tcat_download.json", "w", encoding="utf-8") as f: json.dump(download_exchange, f, ensure_ascii=False, indent=4) print("DownloadOBT API 交換資訊已存檔至 tcat_download.json")
PS.這個版本的python目前還沒對應完全,像溫層,貨到付款的判定...等等
底下則是另一個再更進階的版本,上半部是託運單,下半部是撿貨單
import json import requests from datetime import datetime # ------------------------------- # 1. 列印託運單 (採用撿貨明細版型:PrintOBTByPickingList) # ------------------------------- # 讀取 export_order.json 中的訂單資料 with open("export_order.json", "r", encoding="utf-8") as f: orders = json.load(f) # 認證資料與寄件人資訊(更新後) customer_id = "89502222" customer_token = "2na2211" sender_info = { "SenderName": "寄件者姓名", "SenderTel": "寄件者電話", "SenderMobile": "0952232112", # 更新後 "SenderZipCode": "70523K", # 更新後 "SenderAddress": "台南市安南區1234567號" } # 組合 API 所需訂單資料,每筆訂單同時帶入 Detail(商品明細) api_orders = [] for order in orders: order_id = str(order.get("訂單編號")) recipient_name = order.get("收件人姓名", order.get("姓名")) recipient_tel = order.get("收件人電話", order.get("聯絡電話")) recipient_mobile = order.get("聯絡電話") recipient_address = order.get("收件人地址", order.get("地址")) # 以下單時間轉換為 yyyyMMdd 格式作為出貨及配達日期 order_date = datetime.fromisoformat(order.get("下單時間")).strftime("%Y%m%d") # 建立 Detail 資料,從訂單中的 "商品" 陣列帶入商品明細 products = order.get("商品", []) detail_body = [] total_quantity = 0 total_amount = 0 for product in products: qty = product.get("數量", 0) unit_price = product.get("單價", 0) # 若單價為負,則用 0 計算 if unit_price < 0: unit_price = 0 amount = qty * unit_price total_quantity += qty total_amount += amount detail_body.append({ "OrderId": order_id, "ProductTypeId": "0015", # 固定使用 0015(其他),可依需求調整 "ProductName": product.get("商品名稱", ""), # 使用原本商品名稱 "Quantity": qty, "Price": unit_price, "Amount": amount, "Column01": "", "Column02": "", "Column03": "", "Column04": "" }) # 將 export_order.json 中的「訂單備註」加入頁尾 Row01, # 並在 Row02 寫入 "感謝訂購,客服專線061234521" detail = { "Title": { "Column01": "品項", "Column02": "數量", "Column03": "單價", "Column04": "合計" }, "Body": detail_body, "TotalQuantity": total_quantity, "TotalAmount": total_amount, "Footer": { "Row01": order.get("訂單備註", ""), "Row02": "感謝訂購,客服專線061234521", "Row03": "", "Row04": "" } } # 組合單筆訂單資料 api_order = { "OBTNumber": "", # 採用系統分配託運單號,此欄留空 "OrderId": order_id, "Thermosphere": "0001", # 例如:0001 表示常溫 "Spec": "0001", # 例如:0001 表示 60cm "ReceiptLocation": "01", # 01 表示到宅 "ReceiptStationNo": "", "RecipientName": recipient_name, "RecipientTel": recipient_tel, "RecipientMobile": recipient_mobile, "RecipientAddress": recipient_address, "SenderName": sender_info["SenderName"], "SenderTel": sender_info["SenderTel"], "SenderMobile": sender_info["SenderMobile"], "SenderZipCode": sender_info["SenderZipCode"], "SenderAddress": sender_info["SenderAddress"], "ShipmentDate": order_date, "DeliveryDate": order_date, # 依需求調整出貨與配達日期 "DeliveryTime": "04", # 04 表示不指定 "IsFreight": "N", "IsCollection": "N", "CollectionAmount": 0, "IsSwipe": "Y", "IsDeclare": "N", "DeclareAmount": 0, "ProductTypeId": "0015", # 固定使用 0015(其他) "ProductName": "食品", # 此欄固定使用 "食品" "Memo": order.get("訂單備註", ""), # 主單備註也可保留 "Detail": detail # 將 Detail 帶入 } api_orders.append(api_order) # 組合最終的請求內容,使用 A4 二模撿貨單 (PrintOBTType 設為 "02") print_payload = { "CustomerId": customer_id, "CustomerToken": customer_token, "PrintType": "01", # 01 表示使用系統分配託運單號 "PrintOBTType": "02", # 02 代表 A4 二模撿貨單 "Orders": api_orders } # 使用撿貨明細版型的 API URL print_api_url = "https://egs.suda.com.tw:8443/api/Egs/PrintOBTByPickingList" headers = {"Content-Type": "application/json"} # 呼叫印單 API response_print = requests.post(print_api_url, json=print_payload, headers=headers, verify=False) # 組合印單交換資訊 print_exchange = { "request": print_payload, "response": response_print.json() if response_print.status_code == 200 else {"error": response_print.text} } # 將印單交換資訊存檔至 tcat.json with open("tcat.json", "w", encoding="utf-8") as f: json.dump(print_exchange, f, ensure_ascii=False, indent=4) print("PrintOBTByPickingList API 交換資訊已存檔至 tcat.json") # ------------------------------- # 2. 下載 PDF (DownloadOBT) # ------------------------------- # 從印單回應中取得 FileNo file_no = print_exchange.get("response", {}).get("Data", {}).get("FileNo", "") if not file_no: print("找不到 FileNo,請確認 tcat.json 中有正確回傳 FileNo。") exit(1) # 組合下載 PDF 請求內容 download_payload = { "CustomerId": customer_id, "CustomerToken": customer_token, "FileNo": file_no } download_api_url = "https://egs.suda.com.tw:8443/api/Egs/DownloadOBT" response_download = requests.post(download_api_url, json=download_payload, headers=headers, verify=False) download_exchange = { "request": download_payload, "response": { "status_code": response_download.status_code, "headers": dict(response_download.headers) } } if response_download.status_code == 200: pdf_data = response_download.content # 將 PDF 存檔 with open("consignment.pdf", "wb") as f: f.write(pdf_data) download_exchange["response"]["content_length"] = len(pdf_data) print("託運單 PDF 已下載並保存為 consignment.pdf") else: download_exchange["response"]["error"] = response_download.text print("下載 PDF 失敗,錯誤資訊:", response_download.text) # 將下載 API 的交換資訊保存成 tcat_download.json with open("tcat_download.json", "w", encoding="utf-8") as f: json.dump(download_exchange, f, ensure_ascii=False, indent=4) print("DownloadOBT API 交換資訊已存檔至 tcat_download.json")