# Commerce & Logistics Gateway API 串接指南 (AI 輔助開發專用手冊) 本手冊專為 **AI 輔助工具 (ChatGPT, Claude, Cursor, Copilot 等)** 與開發者設計。您可以直接將本手冊提供給 AI,讓 AI 快速為您的 **WordPress (WooCommerce)**、**自建網站 (Node.js/PHP/Python)** 或 **ERP 系統** 撰寫「物流・金流・電子發票」完整串接程式碼。 --- ## 📌 系統簡介與基本資訊 * **正式 Gateway 統一入口網址**:`https://gateway.melontech.tw` * **雙微服務架構**:底層採用 `logistics-gateway` (物流) 與 `commerce-gateway` (金流/發票) 雙 Cloudflare Worker 實體隔離架構,對外由統一網關透過 Cloudflare Service Binding 零延遲自動路由,串接端只需對接單一網址與單一 API Key。 * **資料交換格式**:`application/json` (UTF-8) * **認證方式**:在 HTTP Request Header 帶入租戶 API Key: ```http Authorization: Bearer ``` *(API Key 可於後台的「租戶與授權」或租戶自助中心 `/portal` 中複製取得)* --- ## 🚀 核心 API 端點清單 | 模組 | 功能 | HTTP Method | 端點路徑 | 說明 | |---|---|---|---|---| | 📦 **物流** | **建立出貨單 (自動產 PDF)** | `POST` | `/v1/shipments` | 一鍵建立黑貓/新竹物流或超商託運單,並自動下載面單 PDF 存入 R2 產生永久列印連結 | | 📦 **物流** | **建立出貨草稿單 (待付款轉單)** | `POST` | `/v1/shipments/draft` | 線上付款下單前預存顧客資料與商品明細 (保留購物車),不向黑貓正式取號,買家付款成功自動轉正式單 | | 📦 **物流** | **批量建立出貨單 (合併 PDF)** | `POST` | `/v1/shipments/batch` | 一次建立多筆託運單並回傳合併多頁 PDF 供連續列印 | | 📦 **物流** | **取消託運單 / 廢單 (CancelOBT)** | `POST` / `DELETE` | `/v1/shipments/:id/cancel` 或 `/v1/shipments/:id` | 司機收件前向物流商作廢託運單 (如 CancelOBT 等),支援透過 shipment_id 或託運單號取消 | | 📦 **物流** | **列印/下載託運單 PDF** | `GET` | `/v1/labels/:shipment_id/pdf` | 直接串流輸出 PDF,隨點隨印、永久有效(零延遲) | | 📦 **物流** | **查詢包裹貨態** | `GET` | `/v1/tracking/:tracking_number` | 查詢包裹即時配送狀態(內建 2 小時快取保護) | | 📦 **物流** | **呼叫司機到府集貨** | `POST` | `/v1/pickup` | 通知物流商派遣司機到指定出貨地址集貨收件 | | 📦 **物流** | **7-11 倉到店電子地圖** | `GET` | `/v1/emap/7-11` | 導向 7-11 電子地圖供買家選門市 | | 📦 **物流** | **7-11 地圖選店回調** | `POST` | `/v1/emap/7-11/callback` | 接收 7-11 地圖回傳之門市資料並轉為 JSON | | 💳 **金流** | **建立全方位金流結帳單** | `POST` | `/v1/payments/checkout` | 支援 `ALL`、`Credit`(一次/分期)、`ATM`、`CVS`、`BARCODE`、`TWQR`、`ApplePay`、`BNPL`、`WebATM` 等多元支付,回傳 `checkout_url`(支援純前端 `pk_live_...`) | | 💳 **金流** | **託管跳轉收銀台** | `GET` | `/pay/:transaction_id` | 買家瀏覽器直接導向此網址,自動渲染並提交渠道安全加密表單 | | 💳 **金流** | **查詢金流狀態與 ATM 繳費資訊** | `GET` | `/v1/payments/:id` 或 `/v1/payments?merchant_order_id=...` | **支援純前端 `pk_live_...`**!快速取得訂單付款狀態、ATM 虛擬帳號/銀行代碼、繳費截止日、超商代碼等,專供感謝頁渲染 | | 💳 **金流** | **向金流渠道同步查詢交易** | `POST` | `/v1/payments/query` | 向金流渠道(如綠界 `QueryTradeInfo` 等)即時查詢並同步資料庫(支援純前端 `pk_live_...`) | | 💳 **金流** | **信用卡關帳/退刷/取消** | `POST` | `/v1/payments/refund` | 執行信用卡關帳 (`C`)、退刷 (`R`)、取消 (`E`)、放棄 (`N`) 等操作(僅限後端金鑰) | | 🧾 **發票** | **開立 B2C 雲端電子發票** | `POST` | `/v1/invoices/issue` | 自動執行安全憑證加解密,支援會員/平台載具、手機條碼、自然人憑證、公司統編、愛心碼 | | 🧾 **發票** | **取得發票列印網址 (智慧分流)** | `POST` | `/v1/invoices/print` | 統編自動套用 A4 格式 (`PrintStyle=4`)、個人紙本支援 5.7cm 熱感證明聯 (`3`) 或 A4 (`1`) | | 🧾 **發票** | **作廢電子發票** | `POST` | `/v1/invoices/void` | 當期發票作廢 (`Invalid`) | | 🧾 **發票** | **開立電子折讓單** | `POST` | `/v1/invoices/allowance` | 跨期或部分退貨開立折讓單 (`Allowance`) | | 🧾 **發票** | **驗證手機條碼 / 愛心碼** | `POST` | `/v1/invoices/verify-code` | 結帳前即時查驗買家手機條碼或愛心碼是否有效 | --- ## 📝 詳細 API 規格 ### 1. 建立出貨單 (POST `/v1/shipments`) #### Request Body 規格: ```json { "carrier": "blackcat", // [選填] 物流商代碼: "blackcat" (預設), "hsinchu" "service_type": "home_delivery", // [選填] "home_delivery"(宅配,預設) 或 "store_pickup"(7-11倉到店) "temperature": "normal", // [選填] "normal"(常溫,預設), "chilled"(冷藏), "frozen"(冷凍) "package_size": "60cm", // [選填] "60cm"(預設), "90cm", "120cm", "150cm" "label_format": "thermal", // [選填] "thermal"(熱感貼紙10x15cm/4x6吋) 或 "a4"(A4三模),未帶則自動套用租戶於 /portal 設定之預設面單規格 "merchant_order_id": "ORDER-2026-0001", // [必填] 來源網站的訂單編號 (限英數無空白,同時作為 /portal 整合工作台關聯金流與發票之主鍵) "sender": { // [選填] 若未提供,系統將自動套用後台設定之「預設寄件人」 "name": "發貨中心", "mobile": "0912345678", // 電話或手機擇一必填 "tel": "02-12345678", "address": "台北市重陽路200號", // 必填,系統自動解析郵遞區號與理貨碼 "zip_code": "12334L" // [選填] 若已知特定物流理貨碼可直接帶入 }, "recipient": { // [必填] 收件人資訊 "name": "王小明", // [必填] "mobile": "0987654321", // 電話或手機擇一必填 "tel": "", "address": "台北市南京東路三段261號", // 宅配必填 "store_id": "188706" // 門市取貨時必填 (超商門市店號) }, "shipment_date": "20260901", // [選填] 出貨日期 yyyyMMdd (預設為當日,避開週日) "delivery_date": "20260902", // [選填] 希望配達日期 yyyyMMdd (預設出貨日+1,避開週日) "delivery_time": "unspecified", // [選填] "morning"(13時前), "afternoon"(14-18時), "unspecified"(不指定,預設) "is_cod": false, // [選填] 是否為貨到付款 (預設 false) "cod_amount": 0, // [選填] 代收金額 (is_cod 為 true 時必填) "product_name": "常溫綜合禮盒", // [選填] 面單品名摘要 "items": [ // [選填推薦] 訂單商品明細陣列 (供租戶於 /portal「訂單整合與列印工作台」核對揀貨並印出 10x15cm 熱感或 A4 揀貨單) { "name": "頂級烏魚子禮盒", "quantity": 2, "unit": "盒", "price": 1200, "sku": "GIFT-001" } ], "invoice_draft": { // [選填強烈推薦] 隨物流單預先寫入「待開發票草稿 (status=draft)」,讓賣家於 /portal 出貨時針對紙本/統編一鍵「開票並印單」隨貨附發票,同時防堵配達時重複開立! "sales_amount": 2400, // 訂單含稅總金額 (必填,正整數) "buyer_identifier": "53538851", // [選填] 8 碼統編 (若為公司統編,/portal 將標示「隨貨需印 A4」) "buyer_name": "範例商務股份有限公司", // [選填] 買受人名稱或公司抬頭 "buyer_email": "buyer@example.com", // [選填] 買受人 Email "print_flag": "1", // "1"=索取紙本證明聯或打統編(隨貨需印), "0"=雲端載具/捐贈(免印,等包裹配達後再由網站自動呼叫 /v1/invoices/issue 開立) "carrier_type": "", // ""(紙本/統編/捐贈), "1"(會員/平台雲端載具), "2"(自然人憑證), "3"(手機條碼) "carrier_num": "", // 手機條碼 (如 "/AB12345") "donation": "0", // "0"=不捐贈, "1"=愛心碼捐贈 "love_code": "" // 愛心碼 }, "memo": "易碎品請平放" // [選填] 備註 } ``` #### 成功 Response (200 OK): ```json { "success": true, "data": { "shipment_id": "shp_1725112345_ab12c", "carrier": "blackcat", "tracking_number": "905071144220", // 託運單號 (宅配單號) "delivery_id": null, // 超商門市倉到店配送編號 (一般宅配為 null) "label_url": "https://gateway.melontech.tw/v1/labels/shp_1725112345_ab12c/pdf?api_key=sk_live_xxxx", "environment": "production" } } ``` --- ### 1.1 建立出貨草稿單 (POST `/v1/shipments/draft` 或帶入 `is_draft: true`) 專為**線上付款(信用卡 / ATM / 超商代碼)情境**設計。在買家前往金流收銀台付款之前,前端或後端可先呼叫此端點,將買家的收件人聯絡資料、收件超商/地址、商品明細與發票草稿預先存入 Gateway(狀態為 `draft`): * **不浪費物流契約配額**:本端點**絕不向物流商 API 發起取單請求**,不會產生廢單,不佔用任何物流商契約單號額度。 * **支援購物車挽回**:完整記錄未完成付款之買家手機、姓名與購買品項,方便後續透過簡訊或客服進行訂單挽回與聯繫。 * **權限最小化開放**:此端點支援純前端公開金鑰 (`pk_live_...`) 與後端金鑰 (`sk_live_...`) 呼叫。 * **付款成功自動轉單**:一旦買家在金流付款成功,Gateway 內部將**自動線上開立發票**,並**自動向黑貓正式取號並下載面單轉換為待出貨單(`status = 'created'`)**,倉管在 `/portal` 訂單工作台即可一鍵印單! #### Request: `POST https://gateway.melontech.tw/v1/shipments/draft` *(參數結構與 `POST /v1/shipments` 完全一致,亦可直接於 `POST /v1/shipments` 帶入 `"is_draft": true`)* #### 成功 Response (201 Created): ```json { "success": true, "data": { "shipment_id": "shp_draft_1728000000_ab12c", "merchant_order_id": "ORDER-2026-0001", "carrier": "blackcat", "status": "draft", "is_draft": true, "message": "出貨草稿已成功建立 (待付款完成轉正式單)" } } ``` --- ### 2. 批量建立出貨單與合併多頁列印 (POST `/v1/shipments/batch`) 適合電商後台「勾選多筆訂單一次發單列印」。系統會一次向物流商建立多筆託運單,並回傳一份**合併的多頁 PDF(一鍵連續列印)**: #### Request: `POST https://gateway.melontech.tw/v1/shipments/batch` ```json { "carrier": "blackcat", "label_format": "thermal", // "thermal"(4x6吋熱感貼紙) 或 "a4" "shipments": [ { "merchant_order_id": "ORD-1001", "temperature": "normal", "package_size": "60cm", "recipient": { "name": "陳小華", "mobile": "0912345678", "address": "台北市信義區市府路1號" } }, { "merchant_order_id": "ORD-1002", "temperature": "chilled", "is_cod": true, "cod_amount": 1500, "recipient": { "name": "林大明", "mobile": "0922333444", "address": "新北市板橋區中山路一段161號" } } ] } ``` #### Response (200 OK): ```json { "success": true, "data": { "batch_id": "bat_1725112345_ab12c", "carrier": "blackcat", "label_format": "thermal", "total": 2, "batch_label_url": "https://gateway.melontech.tw/v1/labels/batch/bat_1725112345_ab12c/pdf?api_key=sk_live_xxxx", "shipments": [ { "merchant_order_id": "ORD-1001", "tracking_number": "905072996211", "label_url": "https://gateway.melontech.tw/v1/labels/shp_xxxx/pdf?api_key=sk_live_xxxx" }, { "merchant_order_id": "ORD-1002", "tracking_number": "620006362210", "label_url": "https://gateway.melontech.tw/v1/labels/shp_yyyy/pdf?api_key=sk_live_xxxx" } ] } } ``` > **提示**:開啟 `batch_label_url` 即為包含整批訂單的多頁 PDF,出貨人員直接點擊列印即可由標籤機連續列印! --- ### 3. 查詢貨態追蹤 (GET `/v1/tracking/:tracking_number`) #### Request: `GET https://gateway.melontech.tw/v1/tracking/905071144220?carrier=blackcat` #### Response: ```json { "success": true, "data": { "carrier": "blackcat", "tracking_number": "905071144220", "merchant_order_id": "ORDER-2026-0001", "current_status": "301", "current_status_name": "順利送達", "station_name": "中壢一營業所", "updated_at": "2026-09-02 12:04:40", "history": [ { "status_id": "301", "status_name": "順利送達", "station_name": "中壢一營業所", "created_at": "2026-09-02 12:04:40" }, { "status_id": "151", "status_name": "配送中", "station_name": "中壢一營業所", "created_at": "2026-09-02 08:13:03" } ], "cached": false } } ``` --- ### 4. 取消託運單 / 廢單 (CancelOBT) (POST `/v1/shipments/:id/cancel` 或 DELETE `/v1/shipments/:id`) 當顧客臨時取消訂單或需重新出貨時,只要**物流司機尚未刷讀收件(未集貨)**,即可呼叫此端點向物流商發送作廢請求(如黑貓 `CancelOBT` 等)進行廢單: * **非同步極速回應(免除網站 Timeout)**:由於底層物流官方廢單 API 有時需耗時 30~60 秒回應,平台採用 **非同步背景廢單佇列 (`async_queued: true`)**——網站呼叫此 API 時,平台會在 **0.05 秒內立即回傳 `200 OK`**(狀態標記為 `cancel_pending`),網站無需拉長 Timeout 等待。 * **背景執行 + 自動重試上限保護**:平台在背景獨立執行緒(`waitUntil`)向物流商發送作廢請求;若物流伺服器當下忙碌或逾時,平台每 5 分鐘的自動排程會自動重試向物流商廢單(最多重試 3 次;若達 3 次上限則自動完成作廢標記,確保避免物流商速率限制)。 * **完成後主動推播 `shipment.cancelled` Webhook**:一旦物流商確認作廢成功,平台立即將託運單狀態更新為 `cancelled`(停止後續貨態追蹤),並**主動發送 `shipment.cancelled` Webhook 通知您的網站**(網站收到 Webhook 後即可清除訂單上的物流單號並寫入廢單完成備註)。 * **支援識別碼與冪等防呆**:路徑中的 `:id` 可為 `shipment_id`(如 `shp_1725112345_ab12c`)或託運單號(如 `905071144220`);若單號先前已作廢,重複呼叫仍會冪等回傳 `200 OK` (`already_cancelled: true`)。若包裹已順利送達(`delivered`)或已退回(`returned`),依物流規範無法作廢,系統將回傳 `400` 錯誤。 #### Request: `POST https://gateway.melontech.tw/v1/shipments/shp_1725112345_ab12c/cancel` *(或 `POST /v1/shipments/905071144220/cancel` 或 `DELETE /v1/shipments/shp_1725112345_ab12c`)* Headers: ```http Authorization: Bearer ``` #### 成功 Response (200 OK - 非同步排入佇列): ```json { "success": true, "data": { "shipment_id": "shp_1725112345_ab12c", "tracking_number": "905071144220", "merchant_order_id": "ORDER-2026-0001", "status": "cancel_pending", "async_queued": true, "message": "已排入物流作廢佇列,平台將於背景完成廢單並主動推播 shipment.cancelled Webhook" } } ``` #### 失敗 Response (400 Bad Request - 已送達無法作廢): ```json { "success": false, "error": "包裹已順利送達,物流規範無法作廢託運單" } ``` --- ### 5. 貨態自動定時巡檢與 Webhook 即時推播 Logistics Gateway 內建自動巡檢與事件推播引擎,**您的電商網站無需反覆發送查詢輪詢**: * **定時輪詢**:平台每 5 分鐘自動啟動背景排程,針對未結案之包裹批次向物流渠道更新最新配送歷程(內建快取保護,嚴格符合物流商頻率規範)。 * **自動過期清理**:包裹建立後若超過指定天數(預設 7 天,可自訂)物流端仍無任何刷讀紀錄(未寄出),系統將自動將狀態標記為 `expired`,永久停止追蹤。 * **狀態異動即時推播**:當包裹狀態發生改變或託運單被作廢時,系統立即主動發送 HTTP POST Webhook 到您在租戶後台設定的 Webhook URL。 * **安全簽章**:推播請求附帶 `X-Logistics-Signature: sha256=`,接收端可使用 Webhook Secret 驗證真實性。 * **失敗自動重試**:若接收端伺服器短暫異常未回傳 2xx,系統將自動依設定(預設 3 次,間隔 30 分鐘)重新推播。 #### 推播事件類型 (Events): * `shipment.status_updated`:包裹最新配送歷程或狀態有更新時。 * `shipment.cancelled`:包裹託運單被成功作廢時。 #### Webhook Request Headers: ```http POST https://your-domain.com/api/logistics-webhook Content-Type: application/json X-Logistics-Event: shipment.status_updated X-Logistics-Delivery-Id: 550e8400-e29b-41d4-a716-446655440000 X-Logistics-Signature: sha256=d5a0... (HMAC-SHA256 簽章) ``` #### Webhook Payload 規格 (以貨態更新為例): ```json { "event": "shipment.status_updated", "timestamp": 1725112345, "data": { "shipment_id": "shp_1725112345_ab12c", "tracking_number": "905071144220", "merchant_order_id": "ORDER-2026-0001", "carrier": "blackcat", "status_id": "301", "status_name": "順利送達", "station_name": "中壢一營業所", "status_time": "2026-09-02 12:04:40", "is_final": true } } ``` #### 主要貨態代碼對照表 (Status Codes,以宅配常見狀態為例): | 代碼 | 名稱 | 說明 | 是否為結案終態 (`is_final`) | |---|---|---|---| | `111` | 已集貨 | 司機已刷讀收件 | 否 | | `151` | 配送中 | 包裹正在派送中 | 否 | | `208` | 轉運中 | 營業所間轉運中 | 否 | | `211` | 配達 | 已送達買家手中 | 是 | | `301` | 順利送達 | 完成配達簽收 (主要成功狀態) | 是 | | `215` | 另約時間配送 | 買家不在家或另約配送 | 否 | | `305` | 退貨已送達 | 包裹已退回寄件人 | 是 | | `expired` | 未出貨過期 | 超過設定天數無任何收件刷讀 | 是 | | `cancelled` | 已作廢 | 司機收件前已透過作廢請求完成廢單 | 是 | --- ## 💻 快速程式範例 (Copy & Paste) ### 範例 A:WordPress / WooCommerce (PHP) 在 `functions.php` 或自訂外掛中加入: ```php 'blackcat', 'service_type' => 'home_delivery', 'temperature' => 'normal', 'merchant_order_id' => (string)$order->get_id(), 'recipient' => [ 'name' => $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name(), 'mobile' => $order->get_billing_phone(), 'address' => $order->get_shipping_city() . $order->get_shipping_address_1() . ' ' . $order->get_shipping_address_2(), ], 'is_cod' => ($order->get_payment_method() === 'cod'), 'cod_amount' => ($order->get_payment_method() === 'cod') ? (int)$order->get_total() : 0, 'product_name' => '商品訂單 #' . $order->get_id(), ]; $response = wp_remote_post($gateway_url, [ 'headers' => [ 'Authorization' => 'Bearer ' . $api_key, 'Content-Type' => 'application/json', ], 'body' => json_encode($payload), 'timeout' => 45, ]); if (is_wp_error($response)) { return ['success' => false, 'error' => $response->get_error_message()]; } $body = json_decode(wp_remote_retrieve_body($response), true); if (!empty($body['success'])) { $tracking_number = $body['data']['tracking_number']; $label_url = $body['data']['label_url']; // 將單號與列印連結存入 WooCommerce 訂單 Meta $order->update_meta_data('_blackcat_tracking_number', $tracking_number); $order->update_meta_data('_blackcat_label_url', $label_url); $order->add_order_note("物流託運單建立成功!單號:{$tracking_number},點擊列印託運單"); $order->save(); return ['success' => true, 'tracking_number' => $tracking_number, 'label_url' => $label_url]; } else { return ['success' => false, 'error' => $body['error'] ?? '建立託運單失敗']; } } /** * WooCommerce 取消 / 作廢黑貓託運單 (CancelOBT) */ function cancel_blackcat_shipment_for_wc_order($order_id) { $order = wc_get_order($order_id); if (!$order) return false; $tracking_number = $order->get_meta('_blackcat_tracking_number'); if (empty($tracking_number)) { return ['success' => false, 'error' => '此訂單尚未建立託運單']; } $api_key = 'YOUR_TENANT_API_KEY_HERE'; $gateway_url = 'https://gateway.melontech.tw/v1/shipments/' . urlencode($tracking_number) . '/cancel'; $response = wp_remote_post($gateway_url, [ 'headers' => [ 'Authorization' => 'Bearer ' . $api_key, ], 'timeout' => 30, ]); if (is_wp_error($response)) { return ['success' => false, 'error' => $response->get_error_message()]; } $body = json_decode(wp_remote_retrieve_body($response), true); if (!empty($body['success'])) { $order->add_order_note("物流託運單已成功作廢!單號:{$tracking_number}"); $order->delete_meta_data('_blackcat_tracking_number'); $order->delete_meta_data('_blackcat_label_url'); $order->save(); return ['success' => true, 'message' => $body['message']]; } else { return ['success' => false, 'error' => $body['error'] ?? '作廢託運單失敗']; } } ``` --- ### 範例 B:Node.js / TypeScript (Next.js / Express) ```typescript import axios from 'axios'; const GATEWAY_URL = 'https://gateway.melontech.tw'; const API_KEY = process.env.LOGISTICS_API_KEY; export async function createBlackCatOrder(orderData: { orderId: string; recipientName: string; recipientMobile: string; recipientAddress: string; isCod?: boolean; codAmount?: number; }) { const response = await axios.post( `${GATEWAY_URL}/v1/shipments`, { carrier: 'blackcat', service_type: 'home_delivery', temperature: 'normal', merchant_order_id: orderData.orderId, recipient: { name: orderData.recipientName, mobile: orderData.recipientMobile, address: orderData.recipientAddress, }, is_cod: orderData.isCod || false, cod_amount: orderData.codAmount || 0, product_name: '商品訂單', }, { headers: { Authorization: `Bearer ${API_KEY}`, 'Content-Type': 'application/json', }, } ); return response.data; // { success: true, data: { tracking_number, label_url, ... } } } export async function cancelBlackCatOrder(trackingNumberOrShipmentId: string) { const response = await axios.post( `${GATEWAY_URL}/v1/shipments/${encodeURIComponent(trackingNumberOrShipmentId)}/cancel`, {}, { headers: { Authorization: `Bearer ${API_KEY}`, }, } ); return response.data; // { success: true, message: '託運單已成功作廢' } } ``` --- ### 範例 C:WordPress / WooCommerce 接收 Webhook 自動更新訂單狀態 (PHP) 將此程式碼放入佈景主題的 `functions.php` 或自訂外掛中,即可免輪詢自動更新 WooCommerce 訂單: ```php 'POST', 'callback' => 'handle_logistics_gateway_webhook', 'permission_callback' => '__return_true', ]); }); function handle_logistics_gateway_webhook(WP_REST_Request $request) { $webhook_secret = 'YOUR_WEBHOOK_SECRET_HERE'; // 請於租戶後台複製專屬 Webhook Secret $payload = $request->get_body(); $signature = $request->get_header('x-logistics-signature'); // 1. 驗證 HMAC-SHA256 簽章 $expected_signature = 'sha256=' . hash_hmac('sha256', $payload, $webhook_secret); if (!hash_equals($expected_signature, (string)$signature)) { return new WP_REST_Response(['error' => 'Invalid signature'], 401); } $event = json_decode($payload, true); $event_type = $event['event'] ?? ''; $data = $event['data'] ?? []; $order_id = $data['merchant_order_id'] ?? ''; $order = $order_id ? wc_get_order($order_id) : false; if ($order) { // A. 貨態更新事件 (shipment.status_updated) if ($event_type === 'shipment.status_updated') { $status_id = $data['status_id'] ?? ''; $status_name = $data['status_name'] ?? ''; $tracking_number = $data['tracking_number'] ?? ''; $order->add_order_note("【物流貨態更新】託運單號 {$tracking_number} 狀態變更為:[{$status_id}] {$status_name}"); if (in_array($status_id, ['301', '211'])) { $order->update_status('completed', "包裹貨態已配達簽收 ({$status_name})"); } else if ($status_id === '305') { $order->update_status('failed', "包裹已退回寄件人 ({$status_name})"); } $order->save(); } // B. 物流託運單作廢完成事件 (shipment.cancelled) else if ($event_type === 'shipment.cancelled') { $tracking_number = $data['tracking_number'] ?? ''; $order->delete_meta_data('_blackcat_tracking_number'); $order->delete_meta_data('wmp_shipping_no'); $order->add_order_note("【廢單確認】已收到平台 Webhook 通知:託運單號 {$tracking_number} 已向物流商正式作廢並清空單號。"); $order->save(); } // C. 平台工作台開立發票回寫事件 (invoice.issued) else if ($event_type === 'invoice.issued') { $invoice_no = $data['invoice_no'] ?? ''; if ($invoice_no && !$order->get_meta('_ecpay_invoice_no')) { $order->update_meta_data('_ecpay_invoice_no', $invoice_no); $order->add_order_note("【電子發票已開立】已於出貨工作台開立電子發票:{$invoice_no}(隨機碼:" . ($data['random_number'] ?? '-') . ")"); $order->save(); } } } // 務必回傳 200 OK 告知已成功接收 return new WP_REST_Response(['success' => true], 200); } ``` --- ### 範例 D:Node.js / Express 接收 Webhook 簽章驗證 ```typescript import express from 'express'; import crypto from 'crypto'; const app = express(); const WEBHOOK_SECRET = process.env.LOGISTICS_WEBHOOK_SECRET || 'whsec_xxxx'; // 注意:必須保留原始 body 才能正確比對簽章 app.post('/api/logistics-webhook', express.raw({ type: 'application/json' }), (req, res) => { const rawBody = req.body.toString('utf8'); const signature = req.headers['x-logistics-signature'] as string; const expected = 'sha256=' + crypto.createHmac('sha256', WEBHOOK_SECRET).update(rawBody).digest('hex'); if (!signature || !crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) { return res.status(401).json({ error: 'Invalid HMAC signature' }); } const event = JSON.parse(rawBody); console.log('收到貨態異動事件:', event.data.tracking_number, event.data.status_name); // 業務邏輯更新訂單... return res.status(200).json({ received: true }); }); ``` --- ## 💳 全方位金流支付 (Payment Gateway) API 規格 本平台已內建交易安全簽章(SHA256 等)與託管跳轉收銀台引擎,支援全方位多元支付(AIO)**全部 9 種付款方式與信用卡分期**,您的網站只需發送標準 JSON 即可取得收銀台連結! ### 1. 建立金流結帳單:`POST /v1/payments/checkout` #### 支援的付款方式 (`payment_method` 或 `choose_payment`) 對照表 | `payment_method` 參數值 | 付款方式名稱 | 適用場景與進階搭配參數 | |---|---|---| | `"ALL"` *(預設推薦)* | **全功能收銀台** | 買家進入收銀台後可自行選擇信用卡、ATM、超商代碼、TWQR、Apple Pay 等;可搭配 `ignore_payment` 隱藏特定選項 | | `"Credit"` | **信用卡 (一次付清 / 分期)** | 預設為一次付清;若傳入 `installment_periods: "3,6,12"` 則自動啟用信用卡分期付款 | | `"ATM"` | **ATM 虛擬帳號櫃員機** | 買家於收銀台選擇銀行並取得虛擬帳號;可搭配 `expire_days` 設定繳費期限(1~60 天,預設 7 天) | | `"CVS"` | **超商代碼繳費** | 支援 7-11 ibon、全家 FamiPort、萊爾富 Life-ET、OK-go(單筆上限 20,000 元);可搭配 `store_expire_minutes`(預設 4320 分鐘 = 3 天) | | `"BARCODE"` | **超商條碼繳費** | 產生三段式條碼供買家印出或手機出示至超商櫃台繳費;可搭配 `store_expire_minutes` 設定繳費天數 | | `"TWQR"` | **TWQR 行動支付** | 支援台灣 Pay 及各大銀行行動網銀 App 掃碼付款 | | `"ApplePay"` | **Apple Pay** | 支援 iOS / Safari 裝置使用 Apple Pay 快速結帳 | | `"BNPL"` | **無卡分期 (先買後付)** | 支援無卡分期(如中租 zingala 銀角零卡) | | `"WebATM"` | **網路 ATM** | 買家需自備晶片讀卡機插卡轉帳 | #### Request Body 規格: ```json { "provider": "ecpay", // [選填] 金流商代碼,預設 "ecpay" "environment": "test", // [選填] "test"(沙盒) 或 "prod"(正式),未帶則依後台憑證設定 "merchant_order_id": "ORDER_20260928_01", // [必填] 您的網站訂單編號 "amount": 3000, // [必填] 結帳總金額 (正整數,新台幣元) "item_name": "美味精選禮盒 x 1#手工餅乾 x 2", // [必填] 商品明細,多項商品以 # 分隔 "description": "官網訂單結帳", // [選填] 交易描述 (亦相容欄位名 trade_desc) "service_type": "home_delivery", // [選填推薦] 配送方式: "home_delivery"(宅配,預設) 或 "store_pickup"(超取),供 Gateway 依 prices.json 核算運費 "payment_method": "ALL", // [選填] 付款方式 (亦相容 choose_payment): "ALL" | "Credit" | "ATM" | "CVS" | "BARCODE" | "TWQR" | "ApplePay" | "BNPL" | "WebATM" "installment_periods": "3,6,12", // [選填] 信用卡分期期數 (當 payment_method 為 "Credit" 或 "ALL" 時生效) "ignore_payment": "WebATM#BARCODE", // [選填] 當 payment_method 為 "ALL" 時,欲隱藏的付款方式 (以 # 分隔) "expire_days": 7, // [選填] ATM 虛擬帳號繳費有效天數 (1~60,預設 7) "store_expire_minutes": 4320, // [選填] CVS 超商代碼有效分鐘數 (預設 4320 分鐘 = 3 天) "client_back_url": "https://yourshop.com/orders/thank-you", // [推薦] 付款完成後,平台會以 HTTP 303 GET 自動將買家導回此頁面,並在網址後方自動附帶 ?merchant_order_id=...&amount=...&status=paid&trade_no=...,前端感謝頁可直接讀取發送 Purchase 像素與顯示完成資訊 "order_result_url": "https://yourshop.com/orders/complete", // [選填] 同 client_back_url,若有指定則優先作為自動導回目標網址 "buyer_name": "王小明", // [選填] 買家姓名 "buyer_phone": "0912345678", // [選填] 買家手機 "buyer_email": "buyer@example.com", // [選填] 買家 Email "custom_field_1": "VIP_MEMBER_01", // [選填] 自訂擴充欄位,會在 Webhook 原封不動帶回 "items": [ // [選填推薦] 商品明細陣列,供 Gateway 自動核算原價、滿額免運、溫層升級與運費 { "sku": "GIFT-01", "name": "美味精選禮盒", "quantity": 1, "price": 2000 }, { "sku": "COOKIE-02", "name": "手工餅乾", "quantity": 2, "price": 500 } ] } ``` #### 成功回傳範例 (200 OK): ```json { "success": true, "data": { "transaction_id": "pay_1759050000_ab12cd34", "gateway_trade_no": "EZ29050000AB12CD34", "merchant_order_id": "ORDER_20260928_01", "provider": "ecpay", "environment": "test", "amount": 3000, "checkout_url": "https://gateway.melontech.tw/pay/pay_1759050000_ab12cd34", "action_url": "https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5", "form_fields": { "MerchantID": "3002607", "MerchantTradeNo": "EZ29050000AB12CD34", "TotalAmount": "3000", "ChoosePayment": "ALL", "CheckMacValue": "A1B2C3D4..." }, "auto_submit_html": "..." } } ``` > **超簡單跳轉方式**:直接將買家瀏覽器導向 `data.checkout_url`(例如 `window.location.href = res.data.checkout_url`),Gateway 會自動渲染並提交收銀台安全加密表單! #### 金流 Webhook 自動推播事件 (`payment.paid` 與 `payment.code_issued`) Gateway 會自動接收並驗證金流安全簽章,驗證通過後以 `POST` 推播至您的租戶 Webhook URL(附帶 `X-Logistics-Signature: sha256=`): 1. **付款完成事件 (`event: "payment.paid"`)**:信用卡刷卡成功、ATM 轉帳完成、超商繳費完成時觸發: ```json { "event": "payment.paid", "tenant_id": "tnt_xxxx", "timestamp": "2026-09-28T08:30:00.000Z", "data": { "merchant_order_id": "ORDER_20260928_01", "gateway_trade_no": "EZ29050000AB12CD34", "provider_trade_no": "2609281530001234", "status": "paid", "amount": 3000, "payment_type": "Credit_CreditCard", "paid_at": "2026/09/28 16:30:00", "extra_info": {} } } ``` 2. **ATM / 超商取號成功事件 (`event: "payment.code_issued"`)**:當買家選擇 `ATM`、`CVS` 或 `BARCODE` 並在收銀台頁面完成取號時,Gateway 會先推播虛擬帳號或繳費代碼供您的網站顯示給買家(待買家實際去 ATM/超商繳費後,會再收到第二次 `payment.paid` 事件): ```json { "event": "payment.code_issued", "tenant_id": "tnt_xxxx", "timestamp": "2026-09-28T08:25:00.000Z", "data": { "merchant_order_id": "ORDER_20260928_01", "gateway_trade_no": "EZ29050000AB12CD34", "provider_trade_no": "2609281525009999", "status": "code_issued", "amount": 3000, "payment_type": "ATM_BOT", "paid_at": null, "extra_info": { "bank_code": "004", "v_account": "9876543210123456", "expire_date": "2026/10/05", "payment_no": "", "barcode_1": "", "barcode_2": "", "barcode_3": "" } } } ``` ### 2. 查詢金流訂單狀態與 ATM/超商繳費資訊 #### 方式 A:GET 輕量查詢(純前端感謝頁首選,支援 `pk_live_...`) * **端點**:`GET /v1/payments/:id` 或 `GET /v1/payments?merchant_order_id=...` * **參數說明**:`:id` 支援直接帶入 `merchant_order_id`(您的網站訂單號)、`gateway_trade_no`(金流交易單號)或 `transaction_id`。 * **權限**:公開金鑰(`pk_live_...`)與秘密金鑰(`sk_live_...`)皆可直接呼叫。 * **特性**:直接自快取與資料庫高速讀取,毫秒級響應,不會觸發對金流原廠伺服器的額外輪詢。 ##### cURL 範例: ```bash curl -X GET "https://gateway.melontech.tw/v1/payments/4633" \ -H "Authorization: Bearer pk_live_YOUR_PUBLIC_KEY" ``` ##### Response 回傳範例(ATM 取號待繳費): ```json { "success": true, "data": { "transaction_id": "pay_1791547650231_uQWjIrwE", "merchant_order_id": "4633", "gateway_trade_no": "GW1791547650PP6SA3", "provider_trade_no": "2610092007322150", "status": "code_issued", // "pending"(待付款), "code_issued"(已取號待繳費), "paid"(已付款), "failed"(付款失敗) "amount": 630, "payment_method": "ATM", "payment_sub_type": "ATM_KGI", "payment_info": { // ATM / 超商繳費詳細資料 "bank_code": "809", // 銀行代碼 (809 為凱基銀行) "v_account": "8011172604528918", // 虛擬繳費帳號 "expire_date": "2026/10/16" // 繳費截止日期 }, "paid_at": null, "created_at": "2026-10-09 12:07:30" } } ``` #### 方式 B:POST 向金流商即時同步查詢(支援 `pk_live_...` 與後端金鑰) * **端點**:`POST /v1/payments/query` * **用途**:即時向金流渠道伺服器(如綠界 `QueryTradeInfo` 等)即時查詢最新交易付款狀態並同步寫入資料庫。 *(支援傳入 `merchant_order_id` 商家訂單號 或 `gateway_trade_no` 金流單號擇一查詢)* ```json { "provider": "ecpay", "merchant_order_id": "ORDER_20260928_01" } ``` ### 3. 信用卡關帳/退刷/取消:`POST /v1/payments/refund` ```json { "provider": "ecpay", "gateway_trade_no": "EZ29050000AB12CD34", "provider_trade_no": "2609281530001234", "action": "R", // "C":關帳, "R":退刷, "E":取消關帳, "N":放棄授權 "amount": 3000 } ``` --- ## 🧾 B2C 雲端電子發票 API 規格 本平台已內建電子發票專屬 `AES-128-CBC` 加解密、URL Encode 轉換與雙層狀態檢驗,支援雲端發票、手機條碼、自然人憑證、公司統編與愛心碼捐贈! ### 1. 開立 B2C 電子發票:`POST /v1/invoices/issue` ```json { "provider": "ecpay", // [選填] 預設 "ecpay" "environment": "test", // [選填] "test" 或 "prod",未帶則依後台設定 "merchant_order_id": "ORDER_20260928_01", // [必填] 您的網站訂單編號 "buyer": { // [必填] 買受人資訊物件 "name": "王小明", // 買受人姓名或公司抬頭 "email": "buyer@example.com", // 買受人 Email (雲端發票中獎通知用) "phone": "0912345678", // 買受人電話 "identifier": "", // [選填] 8 碼統一編號 (打統編時填入,如 "12345678") "address": "" // [選填] 買受人地址 (打統編且列印時建議填寫) }, "carrier_type": "3", // [選填] 載具類別: "1"(會員/平台雲端載具,預設), "3"(手機條碼), "2"(自然人憑證), ""(無載具/列印紙本/打統編/捐贈) "carrier_num": "/AB12345", // [選填] 載具編號 (當 carrier_type 為 "3" 時必填手機條碼) "donation": "0", // [選填] "0"(不捐贈,預設), "1"(愛心碼捐贈,此時 carrier_type 請傳 "") "love_code": "", // [選填] 愛心碼 (當 donation 為 "1" 時必填,如 "168001") "print_flag": "0", // [選填] "0"(不列印,預設), "1"(列印紙本,有填統編 identifier 時系統自動強制設為 "1" 並清空載具) "tax_type": "1", // [選填] "1"(應稅,預設), "2"(零稅率), "3"(免稅), "9"(混合應稅與免稅) "sales_amount": 1280, // [必填] 發票總金額 (含稅正整數,須與 items.amount 加總相符) "remark": "官網訂單自動開立", // [選填] 發票備註 "items": [ // [必填] 商品明細陣列 (至少 1 項) { "name": "美味精選禮盒", // [必填] 商品名稱 "count": 1, // [必填] 數量 "unit": "盒", // [選填] 單位 (預設 "件") "price": 1280, // [必填] 單價 (含稅) "amount": 1280, // [必填] 小計金額 "tax_type": "1" // [選填] "1"(應稅,預設), "2"(零稅率), "3"(免稅) } ] } ``` **成功回傳範例 (200 OK):** ```json { "success": true, "data": { "invoice_id": "inv_1759050123_9a8b7c6d", "merchant_order_id": "ORDER_20260928_01", "relate_number": "INV1759050123AB12CD", "invoice_no": "LO22046600", "invoice_date": "2026-09-28 14:30:00", "random_number": "8392", "provider": "ecpay", "environment": "test", "already_issued": false } } ``` > **防重複開立冪等保護 (Idempotency)**:若該 `merchant_order_id` 先前已由賣家於 `/portal` 訂單工作台點選「開票並印單」開立過,當訂單日後配達完成、網站再次自動呼叫 `POST /v1/invoices/issue` 時,系統**不會重複開立第二張發票**,而是直接回傳既有之 `invoice_no`(並標註 `"already_issued": true`),讓網站安全回寫發票號碼! > > **發票開立 Webhook 自動推播 (`event: "invoice.issued"`)**:當賣家在 `/portal` 出貨工作台手動點選開立發票時,若租戶有設定 Webhook URL,平台亦會主動推播 `invoice.issued` 事件(包含 `merchant_order_id`、`invoice_no`、`invoice_date`、`random_number`、`sales_amount`),讓外部網站即時同步寫入訂單發票紀錄。 ### 2. 作廢電子發票:`POST /v1/invoices/void` ```json { "provider": "ecpay", "invoice_no": "LO22046600", "invoice_date": "2026-09-28", "reason": "訂單取消作廢" } ``` ### 3. 開立折讓單:`POST /v1/invoices/allowance` ```json { "provider": "ecpay", "invoice_no": "LO22046600", "invoice_date": "2026-09-28", "notify_type": "E", "notify_mail": "buyer@example.com", "allowance_amount": 280, "reason": "部分退貨折讓", "items": [ { "name": "手工餅乾退貨", "count": 1, "unit": "包", "price": 280, "amount": 280 } ] } ``` ### 4. 手機條碼 / 愛心碼即時驗證:`POST /v1/invoices/verify-code` ```json { "provider": "ecpay", "barcode": "/AB12345" } ``` > 若要驗證愛心碼,請傳入 `{ "provider": "ecpay", "love_code": "168001" }`。回傳 `{ "success": true, "data": { "isValid": true, "message": "條碼有效" } }`。 ### 5. 取得電子發票列印網址 (智慧分流):`POST /v1/invoices/print` ```json { "provider": "ecpay", "invoice_no": "LO22046600", "invoice_date": "2026-09-28", // [選填] 若未傳入,系統將自動從資料庫查詢該發票之台灣法定開立日期與統編資訊 "print_style": 4 // [選填] 未傳入時自動智慧判斷:有 8 碼統編預設 4 (B2B A4格式);個人紙本預設 3 (5.7cm 熱感證明聯) 或可指定 1 (A4/A5 一般證明聯含明細) } ``` > 成功回傳 `{ "success": true, "data": { "invoiceNo": "LO22046600", "invoiceHtml": "https://einvoice-stage.ecpay.com.tw/...", "printStyle": 4 } }`,直接於瀏覽器開啟 `invoiceHtml` 即可列印。 --- ## 🌐 純前端公開金鑰體系 (pk_live_xxx) 與 Headless / Jamstack 整合規格 為讓平台能直接作為**純靜態網站(Vue、React、一頁式促銷頁、Astro、Next.js SSG)**的安全後台,平台提供無伺服器架構專屬的「前端公開金鑰體系」: ### 1. 金鑰架構分流原則 | 金鑰類型 | 前綴格式 | 適合場景 | 權限範圍 | 安全邊界防護 | | :--- | :--- | :--- | :--- | :--- | | **秘密金鑰 (Secret Key)** | `sk_live_...` 或現有金鑰 | 後端伺服器 (WordPress, Laravel, Node.js) | **全面信任**:建單、開立發票、作廢、折讓、查詢歷史清單等全部 API | 伺服器對伺服器保護 | | **公開金鑰 (Publishable Key)** | `pk_live_...` | 純前端瀏覽器 (HTML, JS, Vue, React) | **權限最小化 (ACL)**:僅限建立金流結帳單、查詢金流狀態與 ATM/超商繳費資訊、超商地圖取店、建立出貨草稿與貨態追蹤 | 邊緣網域白名單 + Turnstile 人機防刷 + 反向價格校驗 | ### 2. 邊緣網域白名單 (Origin Whitelist) - 於租戶中心「4. 純前端公開金鑰與安全校驗」輸入允許的前端網址(一行一個,例如 `https://shop.example.com` 或支援萬用字元 `*.example.com`)。 - 帶有 `pk_live_...` 的請求若來自非白名單網域,邊緣節點將直接回傳 `403 Forbidden`,杜絕跨站濫用。 ### 3. Cloudflare Turnstile 免費人機驗證 (選填防刷單) - 商家可於 Cloudflare 後台免費申請 Turnstile,並將 `Secret Key` 填入租戶設定。 - 前端送出結帳請求時,附帶 Header `cf-turnstile-response`(或 JSON body 中的 `turnstile_token`),平台於邊緣自動完成人機驗證,阻斷爬蟲機器人無感刷單。 ### 4. 反向網頁定價校驗法 (prices.json) 與純前端運費冷鏈信任機制 - **原理**:商家在靜態網站根目錄放置定價檔(如 `https://shop.example.com/prices.json`),記載每個商品 SKU 的原價、溫層與全館運費規則。 - **快取架構**:平台每 5 分鐘伴隨背景定時任務自動更新至 Cloudflare KV(手動亦可隨時一鍵即時刷新),結帳時 0 毫秒在邊緣完成商品原價、溫層升級與運費比對。 - **純前端零信任 (Zero-Trust) 防禦機制**: * **買家無法篡改運費**:前端**完全不需要傳運費金額** (`shipping_fee`),Gateway 會依據購物車商品小計、是否達滿額門檻、顧客選擇的配送方式(宅配或超取),自動在伺服器端精算出「法定應收運費」。 * **冷鏈溫層自動升級 (Cold-Chain Tier Promotion)**:前端**完全不需要傳溫層** (`temperature`)!購物車同時有常溫與冷凍商品時,Gateway 自動整單升級為最高溫層 `frozen`(冷凍 3 > 冷藏 2 > 常溫 1)計算運費並向黑貓取單,防止買家或惡意爬蟲以常溫便宜單偷寄冷凍品。 * **前端極簡呼叫**:純前端金流結帳只需在 Request 中傳入顧客在介面選擇的配送方式 `service_type: "home_delivery"` 或 `"store_pickup"`,其餘全部由 Gateway 自動演算。 - **雙模式防禦切換(後台可自選)**: * **嚴格定價模式 (Strict Mode)**:若買家在瀏覽器 DevTools 故意拔除運費、少付金額或帶入未登錄 SKU,邊緣節點直接以 `HTTP 400 Bad Request` 阻斷交易並回傳詳細原因! * **寬鬆模式 (Permissive Mode,預設)**:尊重促銷折價券,買家付款不被攔截。若發現短少運費或異常巨額折抵(≥ 70%),訂單後台高亮標註「🚨 價格/運費異常」,且批次印單時自動跳過異常單,單筆列印強制核對。 #### prices.json 完整規格範例 (支援滿額免運、多配送方式與多溫層): ```json { "version": "2026-10-07", "skus": { "TEA-01": { "name": "阿里山高山茶", "price": 300, "temp": "normal" }, "JUICE-02": { "name": "鮮榨冷藏果汁", "price": 180, "temp": "chilled" }, "BEEF-03": { "name": "日本A5和牛組", "price": 900, "temp": "frozen" } }, "shipping": { "free_threshold": 1500, "default_method": "home_delivery", "rules": { "home_delivery": { "normal": 100, "chilled": 160, "frozen": 200 }, "store_pickup": { "normal": 65, "frozen": 120 } } } } ``` ### 5. 純前端 JavaScript 結帳串接範例 (無需任何後端!) ```javascript // 前端結帳函式範例 (直接在 HTML / Vue / React 中執行) async function submitCheckout() { const payload = { merchant_order_id: "ORD-" + Date.now(), amount: 1400, // 商品小計 (300+900=1200) + 冷凍宅配運費 (200) = 1400 (未滿1500免運) item_name: "日本A5和牛組等 2 件商品", service_type: "home_delivery", // 顧客選擇宅配 ("home_delivery") 或超取 ("store_pickup") payment_method: "ALL", // 全功能收銀台 (信用卡/ATM/超商代碼) items: [ { sku: "TEA-01", name: "阿里山高山茶", count: 1, price: 300 }, { sku: "BEEF-03", name: "日本A5和牛組", count: 1, price: 900 } ], // 若有啟用 Turnstile,帶入前端生成的 token turnstile_token: window.turnstileToken || undefined }; const response = await fetch("https://gateway.melontech.tw/v1/payments/checkout", { method: "POST", headers: { "Authorization": "Bearer pk_live_YOUR_PUBLIC_KEY", "Content-Type": "application/json" }, body: JSON.stringify(payload) }); const res = await response.json(); if (res.success && res.data.checkout_url) { // 直接跳轉至收銀台結帳! window.location.href = res.data.checkout_url; } else { alert("結帳失敗:" + (res.error?.message || "請稍候再試")); } } ``` ### 6. 付款完成頁面 (感謝頁 / Thank You Page) 資料接收與購買像素 (Pixel) 追蹤 當買家在金流收銀台付款完成後,Gateway 會以 `HTTP 303 GET` 自動將買家瀏覽器導回您在結帳時指定的 `client_back_url`(感謝頁)。 #### 💡 轉址附帶之 Query 參數清單 Gateway 會在跳轉網址後方自動附帶訂單摘要,**純前端感謝頁無需二次呼叫任何後端 API**,即可直接從 `window.location.search` 解析: | 參數名稱 | 範例值 | 說明 | | :--- | :--- | :--- | | `merchant_order_id` | `ORD-20261001-001` | 商家原始訂單編號 | | `amount` | `1200` | 實際交易總金額 (正整數,新台幣元) | | `status` | `paid` | 交易狀態 (`paid` 付款成功,`failed` 付款失敗) | | `trade_no` | `GW20261004123456` | Gateway 平台交易序號 | | `payment_method` | `Credit` / `ALL` | 買家採用的支付方式 | #### 🎯 前端感謝頁範例程式碼 (讀取參數、顯示訂單並觸發 Meta Pixel / GA4) ```html 感謝您的購買 - 訂單完成

訂單處理中...

``` --- ### 7. 純前端兩種電商購物流程完整架構(貨到付款 vs 線上金流) 純前端網站(無後端伺服器)或 Headless 靜態架構,可依據買家的付款方式無縫實現以下兩種全自動化閉環: #### 🛒 流程 A:貨到付款(COD)全自動流程 1. **買家結帳下單**: - 前端收集買家收件地址、電話與發票設定(載具/統編/捐贈)。 - 前端以 `pk_live_...` 直接呼叫 `POST /v1/shipments`(附帶 `"is_cod": true`, `"cod_amount": 1500`, 以及 `"invoice_draft": { ... }`)。 - Gateway 立即向物流商(黑貓)立案取號,回傳 12 碼託運單號與面單 PDF 網址。 2. **倉管出貨與列印分流**: - 倉管在 `/portal` 訂單工作台一鍵印出黑貓託運單。 - **紙本/統編**:若買家有填寫統編或指定紙本發票,工作台顯示「開票並印單」,出貨時一鍵連同發票證明聯隨貨附寄。 - **雲端載具/愛心捐贈**:工作台顯示「免印・配達自動開」,出貨時無需列印發票。 3. **5 分鐘背景輪詢偵測配達自動開立發票**: - 商家可在 `/portal` 電子發票設定中開啟 **「貨到付款 / 包裹配達自動開立載具發票 (預設關閉)」**。 - 司機順利送達買家(黑貓狀態碼 `301` 配達 / 7-11 門市取件完成 `211`)時,Gateway 背景排程在同一微秒內自動為該訂單開出綠界雲端載具或愛心捐贈發票。 - 依法規已隨貨寄送之紙本統編發票會被自動略過,絕不重複開立! --- #### 💳 流程 B:線上金流(信用卡 / ATM / 超商代碼)草稿轉正式單流程 1. **買家送出訂單(先建立出貨草稿)**: - 前端在跳轉金流前,以 `pk_live_...` 先呼叫 `POST /v1/shipments/draft`(或 `POST /v1/shipments` 帶入 `"is_draft": true`)。 - 系統將買家姓名、手機、收件地址/超商門市與發票草稿存入 Gateway(`status = 'draft'`)。 - **完全不向黑貓 API 取單、不佔用物流單號額度**,並完整保留未結帳之買家聯絡資料以供後續購物車挽回! 2. **導向金流收銀台付款**: - 前端緊接著呼叫 `POST /v1/payments/checkout` 取得 `checkout_url`,並將買家導向金流收銀台付款。 3. **ATM 虛擬帳號 / 超商代碼取號即時展示 (純前端感謝頁)**: - 買家在收銀台取號後跳回感謝頁(網址自帶 `?merchant_order_id=...`),純前端使用 `pk_live_...` 呼叫 `GET /v1/payments/:id`,秒級取得 `payment_info`(銀行代號、虛擬帳號、繳費截止日),在感謝頁即時渲染展示! 4. **付款成功:Gateway 自動轉單與開票**: - 買家完成付款後,綠界通知 Gateway 回呼端點,系統在同一時間點自動完成兩大作業: ① **自動線上開立發票**:不論是載具、捐贈或公司統編,發票立即線上開出並寄送通知。 ② **自動草稿轉正**:自動將原先的出貨草稿向黑貓正式取單號與面單 PDF,狀態由 `draft` 升級為 `created`。 ③ 自動發送 `shipment.created` 與 `payment.paid` Webhook 通知。 5. **商家出貨**: - 商家在 `/portal` 訂單工作台看到訂單即時轉為「已付款」,託運單面單按鈕立即解鎖,一鍵列印出貨! > 💡 **後端網站分開送相容性**: > 若您的自建後端或 ERP 選擇「下單先送金流,等收到付款成功 Webhook 後才打入物流與發票」,Gateway 亦完全原生相容!金流付款時若資料庫中無出貨草稿,系統會自動優雅略過,不影響後續後端直接傳入正式單。 --- ## 🤖 讓 AI 幫您寫程式的專用 Prompt (複製即可使用) 當您要把串接工作交給 ChatGPT、Claude 或 Cursor 時,您可以直接複製以下文字: ```markdown 你好!我目前需要將我的電商網站串接到自建的「Commerce & Logistics Gateway 物流・金流・電子發票三合一中繼平台」,請先讀取以下完整 API 規格手冊並為我撰寫串接邏輯: 1. 完整手冊網址 (純文字 Markdown): https://gateway.melontech.tw/docs/raw 2. Gateway Base URL: https://gateway.melontech.tw 3. 認證 Header: Authorization: Bearer (或純前端使用 pk_live_...) * ⚠️ 安全規範:請提示使用者另外於伺服器環境變數 (例如 .env 的 GATEWAY_SECRET_KEY) 中設定後端金鑰 (sk_live_...),切勿寫死在程式碼或公開專案中! 4. 三大核心模組 API: - 【📦 物流服務】建立正式託運單 POST /v1/shipments、建立出貨草稿單 POST /v1/shipments/draft (線上金流未付款前預存資料,不佔單號額度)、批量建單 POST /v1/shipments/batch、作廢託運單 POST /v1/shipments/:id/cancel、7-11 電子地圖 GET /v1/emap/7-11 - 【💳 全方位金流支付】建立結帳單 POST /v1/payments/checkout * 支援 payment_method: "ALL"(全功能收銀台)、"Credit"(信用卡,可帶 installment_periods: "3,6,12" 分期)、"ATM"(虛擬帳號)、"CVS"(超商代碼)、"BARCODE"(超商條碼)、"TWQR"(行動支付)、"ApplePay"、"BNPL"(無卡分期)、"WebATM" * 純前端零信任防禦:前端結帳請帶入 items 陣列 (包含 sku、count、price) 與 service_type ("home_delivery" 宅配或 "store_pickup" 超取),運費與冷鏈最高溫層由 Gateway 依商家的 prices.json 自動推導與防偽校驗,買家無法篡改運費 * 回傳 data.checkout_url,直接將買家瀏覽器導向該網址即進入收銀台結帳;買家付款完成後 Gateway 會自動跳回 client_back_url (並在網址後方附帶 merchant_order_id, amount, status, trade_no 等參數) * 支援純前端感謝頁快速查詢 GET /v1/payments/:id (秒級取得 ATM 虛擬帳號、銀行代碼與繳費期限) * 買家付款成功時,Gateway 自動線上開立發票並將出貨草稿轉為正式待出貨單 * 支援主動查詢 POST /v1/payments/query 與信用卡退刷 POST /v1/payments/refund - 【🧾 B2C 雲端電子發票】開立雲端發票 POST /v1/invoices/issue (支援會員/平台載具 carrier_type="1"、手機條碼 carrier_type="3"、自然人憑證 "2"、統編 buyer.identifier、愛心碼 donation="1";內建 merchant_order_id 冪等防重開保護)、列印發票 POST /v1/invoices/print、作廢 POST /v1/invoices/void、折讓 POST /v1/invoices/allowance、驗證條碼 POST /v1/invoices/verify-code 5. Webhook 自動推播接收端: - 平台會以 POST 發送以下事件到我的伺服器 (附帶 Header `X-Logistics-Signature: sha256=`): * `shipment.created`: 草稿轉正或出貨單建立成功 (內含 tracking_number, label_url) * `shipment.status_updated`: 包裹貨態異動 * `payment.paid`: 金流付款成功 * `payment.code_issued`: ATM 虛擬帳號或超商代碼/條碼取號成功 (內含 extra_info.bank_code, v_account, payment_no, expire_date) * `invoice.issued`: 發票開立完成通知 (內含 data.merchant_order_id, invoice_no, invoice_date, random_number) 請幫我為 [我的框架/系統,例如: WooCommerce / Next.js / Laravel] 撰寫一個完整的服務模組! ```