接下來的就是物流的應用,宅急便的技術文件請自己合法去跟黑貓技術客服要
*授權碼請至統一速達契約客戶專區登入頁面的「取得印單 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")