當您的組織已連接電子發票服務(Amego 或 ezPay,可在後台「設定 → 整合 → 電子發票」設定)並開啟自動開立時,Recur 會在付款完成後自動為訂單開立電子發票。本頁說明如何在各種結帳整合方式中收集買家的發票選擇。
沒有啟用電子發票? 一切照舊——所有 einvoice 相關欄位都是選填。未啟用時,合法的 einvoice 值不會影響結帳或觸發任何開立;但欄位格式仍會被驗證,格式錯誤(如統編檢查碼不符)無論是否啟用都會回 422。
發票選擇的格式(EinvoicePrefs)
買家的發票選擇是一個帶 type 的物件,四種類型:
| type | 額外欄位 | 說明 |
|---|---|---|
personal | — | 個人雲端發票,寄送至買家 Email |
mobile_barcode | carrier_code | 手機條碼載具,/ 開頭共 8 碼(如 /ABC1234) |
ubn | ubn、buyer_name | 公司統編三聯式;統編 8 位數字(驗證檢查碼)+ 公司抬頭 |
donation | donation_code | 捐贈發票,愛心碼 3–7 位數字(如 25885) |
請求本文接受 snake_case(建議)與 camelCase(如 carrierCode)兩種寫法;回應一律為 snake_case。格式錯誤(統編檢查碼不符、手機條碼格式錯誤等)會在建立/付款當下回 422 validation_error,不會等到開立發票時才失敗。
Hosted Checkout(最簡單)
託管結帳頁會在組織啟用電子發票時自動顯示發票資訊區塊,買家自行選擇,無需任何額外整合。
若您已在自己的系統收集過買家的發票偏好,可在建立 Session 時帶入 einvoice 作為預填(買家在結帳頁仍可修改):
curl -X POST https://api.recur.tw/v1/checkout/sessions \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"product_id": "prod_abc123",
"success_url": "https://example.com/success",
"cancel_url": "https://example.com/pricing",
"einvoice": { "type": "ubn", "ubn": "04595252", "buyer_name": "恆吉股份有限公司" }
}'
SDK 的 redirectToCheckout / createCheckoutSession 也接受同一個選項(camelCase):
await recur.redirectToCheckout({
productId: 'prod_abc123',
successUrl: 'https://example.com/success',
cancelUrl: 'https://example.com/cancel',
einvoice: { type: 'mobile_barcode', carrierCode: '/ABC1234' },
});
Embedded / Modal Checkout(SDK 內建 UI)
使用 recur.checkout({ mode: 'modal' }) 或 mode: 'iframe' 時,SDK 的支付表單會在組織啟用電子發票時自動渲染發票資訊區塊(與託管結帳頁相同的四個選項與驗證),並在買家送出付款時一併帶上發票選擇——您不需要寫任何程式碼。
預填順序:您在 checkout() 傳入的 einvoice 選項 → 買家先前的發票偏好(客戶記憶)→ 個人雲端發票。
// 可選:帶入您系統中已知的偏好作為預填
recur.checkout({
productId: 'prod_abc123',
mode: 'modal',
einvoice: { type: 'donation', donationCode: '25885' },
});
自行組裝 UI(進階)
若您使用低階 API 自行渲染結帳流程,有兩個掛載點:
建立時傳入(POST /v1/checkouts):
{ "product_id": "prod_abc123", "einvoice": { "type": "personal" } }
付款時傳入(POST /v1/checkouts/{id}/pay),適合在自己的表單收集後才確定選擇。付款時的值會覆蓋建立時的值:
{ "creditToken": "...", "timestamp": 1234567890, "einvoice": { "type": "ubn", "ubn": "04595252", "buyer_name": "恆吉股份有限公司" } }
判斷是否需要顯示發票欄位:POST /v1/checkouts 與 GET /v1/checkouts/{id} 的回應都帶有 einvoice_enabled,且附上 einvoice_defaults 預填值(此結帳已儲存的選擇 → 客戶記憶 → { "type": "personal" })。
SDK 也匯出驗證工具供您在前端即時驗證:
import { validateEinvoicePrefs, isValidTaiwanUbn } from 'recur-tw';
validateEinvoicePrefs({ type: 'ubn', ubn: '04595252', buyerName: '恆吉股份有限公司' }); // null = 合法
isValidTaiwanUbn('12345678'); // false(檢查碼不符)
查詢開立結果(API 讀回)
GET /v1/orders/{id} 與 GET /v1/invoices/{id}(及 list)的回應帶有 einvoice 物件(未開立或未啟用時為 null):
{
"id": "ord_abc123",
"einvoice": {
"status": "ISSUED",
"invoice_number": "ZA12345678",
"random_code": "5417",
"invoice_date": "2026-07-22",
"sales_amount": 762,
"tax_amount": 38,
"total_amount": 800,
"tax_type": "TAXABLE",
"buyer": { "type": "mobile_barcode", "carrier_code": "/ABC1234" },
"voided_at": null,
"void_reason": null,
"allowances": []
}
}
status 為 PENDING(開立中,系統會自動重試)/ ISSUED / FAILED(附 failure_message)/ VOIDED。發票號碼與隨機碼為對獎資訊,只在 Secret Key 認證下回傳。
Webhook 事件
開立/作廢/折讓會發送 einvoice.issued、einvoice.issue_failed(僅最終失敗)、einvoice.voided、einvoice.allowance_created 事件,SANDBOX 也會發送方便測試。完整 payload 見 Webhook 事件。
開立與記憶
- 付款完成(含 3D 驗證後經 webhook 完成)後,發票依買家選擇自動開立;未提供選擇時,依買家先前記憶的偏好,最後回落為個人雲端發票。
- 買家明確選擇過的偏好會記憶在客戶資料上,下次結帳自動預填。
- 退款時自動作廢或開立折讓,無需額外處理。
開立結果可在後台訂單詳情頁查看(發票號碼、狀態、作廢/折讓紀錄)。