agriweather / laravel-ezpay-invoice
適用於 Laravel 的 ezPay 電子發票 API 套件
Requires
- php: >=8.1
- guzzlehttp/guzzle: ^7.5
- illuminate/conditionable: >=9.0
- illuminate/http: >=9.0
- illuminate/support: >=9.0
- nesbot/carbon: ^2.67 || ^3.0
Requires (Dev)
- laravel/pint: ^1.20
- mockery/mockery: ^1.4
- orchestra/testbench: >=7.0
- pestphp/pest: ^1.23 || ^2.36 || ^3.8.2 || ^4.0
- pestphp/pest-plugin-laravel: ^1.0 || ^2.0 || ^3.0 || ^4.0
- phpstan/phpstan: ^2.1
- rector/rector: ^2.1
This package is auto-updated.
Last update: 2025-09-26 10:08:26 UTC
README
Laravel ezPay Invoice 是適用於 Laravel 的 ezPay 電子發票 API 套件。由 Lucas Yang 創建,並由 阿龜微氣候天眼通 團隊維護。
套件功能
- 🧾 電子發票 API
- 🌏 電子發票 API (境外電商版)
- 🅰 字軌管理 API
- 📱 手機條碼與捐證碼驗證 API
目錄
版本需求
版本 | PHP 版本 | Laravel 版本 |
---|---|---|
1.x | >=8.1 | >=9.x |
開始使用
使用 Composer 安裝套件:
composer require agriweather/laravel-ezpay-invoice
發布設置檔案:
php artisan vendor:publish --tag=ezpay-invoice-config
前往 ezPay 電子發票官方網站註冊帳號(測試時需在測試環境註冊測試帳號)並建立商店。
在 ezPay 電子發票平台開立發票需要購買額度,如果額度不足,請前往「發票管理」>「管理設定」>「使用狀況」進行購買(測試環境同樣需要點擊購買,但不會實際收費)。
進入 ezPay 電子發票的「商店管理」頁面,找到對應的商店,複製商店串接 API 的商店代號、HashKey
和 HashIV
,然後將這些資訊設定到 .env
檔案中的 EZPAY_INVOICE_MERCHANT_ID
等參數:
EZPAY_INVOICE_ENV=test EZPAY_INVOICE_MERCHANT_ID=your-merchant-id EZPAY_INVOICE_MERCHANT_HASH_KEY=your-merchant-hash-key EZPAY_INVOICE_MERCHANT_HASH_IV=your-merchant-hash-iv
EZPAY_INVOICE_ENV
可以設定為 test
(測試環境)或 production
(正式環境)。
完成設定後,即可開始測試電子發票的開立:
use Agriweather\EzPayInvoice\Enums\Invoice\TaxType; use Agriweather\EzPayInvoice\Facades\EzPayInvoice; $result = EzPayInvoice::invoice() ->create() ->withOrder('Order'.time()) ->forConsumer('John Doe') ->withEmail('customer@example.com') ->withAddress('台北市信義區信義路五段7號') ->withItem('測試商品', quantity: 1, unit: '個', price: 1000, amount: 1000) ->withTax(TaxType::TAXABLE, 5) ->withAmount(1000, 50, 1050) ->issue(); $result->invoiceNumber() // 發票號碼:'AB12345678' $result->randomNumber() // 發票隨機碼:'1234'
電子發票 API
開立電子發票
開立 B2C 電子發票的基本範例:
use Agriweather\EzPayInvoice\Facades\EzPayInvoice; $result = EzPayInvoice::invoice() ->create() ->withOrder('Order001') // 訂單編號 ->forConsumer('John Doe') // 消費者姓名 ->withEmail('customer@example.com') // 消費者電子信箱 ->withAddress('台北市信義區信義路五段7號') // 消費者地址 ->withItem('測試商品', quantity: 1, unit: '個', price: 1000, amount: 1000) // 商品名稱、數量、單位、單價和金額 ->withTax(TaxType::TAXABLE, 5) // 稅別:應稅稅別,稅率:5% ->withAmount(1000, 50, 1050) // 未稅銷售額、稅額、含稅銷售額 ->issue();
開立 B2C 電子發票時,可以選擇使用不同的載具,如果設定了載具,會自動設定不索取紙本發票:
use Agriweather\EzPayInvoice\Enums\Invoice\CarrierType; EzPayInvoice::invoice() ->create() ->forConsumer('John Doe') // 手機條碼載具: 第1碼 / + 7碼英、數字 ->withCarrier(CarrierType::MOBILE, '/ABC.123') // 自然人憑證: 2碼大寫英文 + 14碼數字 ->withCarrier(CarrierType::CITIZEN_CERT, 'AB12345678901234') // ezPay 電子發票載具 ->withCarrier(CarrierType::EZPAY_CARRIER, '1234567890') ->withEmail('customer@example.com') // 當選擇 ezPay 電子發票載具時,需提供電子信箱
或者是可以提供捐贈碼,但不能與載具一起使用:
EzPayInvoice::invoice() ->create() ->forConsumer('John Doe') // 捐贈碼: 3~7 碼純數字 ->withLoveCode('1234567')
開立 B2B 電子發票的基本範例:
$result = EzPayInvoice::invoice() ->create() ->withOrder('Order002') ->forBusiness('測試公司有限公司', '12345678') // 公司名稱、統一編號 ->withEmail('business@company.com') // 公司電子信箱 ->withAddress('台北市信義區信義路五段7號') // 公司地址 ->withItem('商品A', quantity: 2, unit: '個', price: 300, amount: 600) // 商品名稱、數量、單位、單價和金額 ->withItem('商品B', quantity: 1, unit: '個', price: 400, amount: 400) // 商品名稱、數量、單位、單價和金額 ->withTax(TaxType::TAXABLE, 5) // 稅別:應稅稅別,稅率:5% ->withAmount(1000, 50, 1050) // 未稅銷售額、稅額、含稅銷售額 ->issue();
如果開立了 B2B 電子發票,會自動設定索取紙本發票。
設定電子發票稅別和稅率:
use Agriweather\EzPayInvoice\Enums\Invoice\CustomsClearance; use Agriweather\EzPayInvoice\Enums\Invoice\TaxType; EzPayInvoice::invoice() ->create() // 應稅稅別,稅率:5% ->withTax(TaxType::TAXABLE, 5) // 零稅率 ->withTax(TaxType::ZERO_RATE) // 當設定零稅率時,必須提供報關標記選項: ->withCustomsClearance(CustomsClearance::NON_CUSTOMS) // 非經海關 ->withCustomsClearance(CustomsClearance::CUSTOMS) // 經海關 // 免稅 ->withTax(TaxType::TAX_FREE) // 混合應稅與免稅或零稅率 (例如:商品A應稅,商品B免稅) // 當開立 B2B 電子發票才能使用 ->withTax(TaxType::MIXED)
設定電子發票的商品項目和銷售額:
Important
銷售額計算方式,請務必與公司財會人員進行確認。
EzPayInvoice::invoice() ->create() // 增加商品項目 ->withItem('測試商品', quantity: 1, unit: '個', price: 1000, amount: 1000) ->withItem('Test Product', quantity: 2, unit: 'EA', price: 600, amount: 1200) // 批次增加商品項目 ->withItems([ [ 'name' => '測試商品', 'quantity' => 1, 'unit' => '個', 'price' => 1000, 'amount' => 1000, ], [ 'name' => 'Test Product', 'quantity' => 2, 'unit' => 'EA', 'price' => 600, 'amount' => 1200, ], ]) // 未稅銷售額、稅額、含稅銷售額 ->withAmount(2200, 110, 2310)
「混合應稅與免稅或零稅率」的銷售額設定範例:
Important
銷售額計算方式,請務必與公司財會人員進行確認。
use Agriweather\EzPayInvoice\Enums\Invoice\ItemTaxType; use Agriweather\EzPayInvoice\Enums\Invoice\TaxType; EzPayInvoice::invoice() ->create() ->forBusiness('測試公司有限公司', '12345678') // 設定稅別為混合應稅與免稅或零稅率 ->withTax(TaxType::MIXED) // 為每個商品設定不同的稅別 ->withItem('測試商品', quantity: 1, unit: '個', price: 1000, amount: 1000, taxType: ItemTaxType::TAXABLE) ->withItem('測試商品', quantity: 1, unit: '個', price: 600, amount: 600, taxType: ItemTaxType::ZERO_RATE) // 混合稅率銷售額: 銷售額(課稅別應稅)、銷售額(課稅別零稅率)、銷售額(課稅別免稅) ->withMixedTaxAmount(1000, 600, 0) // 銷售額為上面三個 混合稅率銷售額 的總和 ->withAmount(1600, 0, 1600)
設定發票備註:
EzPayInvoice::invoice() ->create() ->withComment('發票備註'); // 發票備註,字數限 200 字,如有難字則再縮短
套件同時提供條件式語法,可以在開立發票時根據需要選擇性地添加參數:
use Agriweather\EzPayInvoice\Builders\Invoice\CreateBuilder; EzPayInvoice::invoice() ->create() ->when($request->input('carrier_type') === 'mobile', function (CreateBuilder $builder) use ($mobileCarrier) { $builder->withCarrier(CarrierType::MOBILE, $mobileCarrier); }) ->when($request->input('carrier_type') === 'lovecode', function (CreateBuilder $builder) use ($loveCode) { $builder->withLoveCode($loveCode); })
立即開立發票:
// 立即開立發票 $result = EzPayInvoice::invoice() ->create() ... ->issue(); $result->invoiceNumber() // 發票號碼:'AB12345678' $result->randomNumber() // 發票隨機碼:'1234' $result->orderNo() // 訂單編號:'Order001' $result->totalAmount() // 含稅銷售額:1050
等待觸發開立發票:
// 等待觸發開立發票 // 當選擇此開立發票方式時,發票資料僅暫存於平台,需手動呼叫「觸發電子發票 API」來完成開立。 $result = EzPayInvoice::invoice() ->create() ... ->deferIssue(); // 預約自動開立發票 // 當選擇此開立發票方式時,發票會在設定時間自動開立,如需提前開立,可手動呼叫「觸發電子發票 API」。 $result = EzPayInvoice::invoice() ->create() ... ->scheduleAt('2025-03-01'); // 設定開立發票的時間 // 保存這些資料用於觸發開立發票 $result->invoiceTransNo() // ezPay 電子發票開立序號:'25072515224376654' $result->orderNo() // 訂單編號:'Order001' $result->totalAmount() // 含稅銷售額:1050
觸發開立電子發票
若使用了 等待觸發開立發票 (deferIssue()
) 方式,需呼叫觸發電子發票 API 來完成開立。若使用 預約自動開立發票 (scheduleAt()
) 方式,則可透過呼叫觸發 API 來提前開立發票:
$result = EzPayInvoice::invoice() ->pending() ->withInvoiceTransNo('25072515224376654') ->withOrder('Order004') ->withTotalAmount(210) ->trigger();
查詢電子發票
使用發票號碼和隨機碼查詢電子發票:
$invoiceResult = EzPayInvoice::invoice() ->query() ->withInvoice('GG72002017') ->withRandomNumber('1234') ->get();
或者也可使用訂單編號及發票金額查詢電子發票:
$invoiceResult = EzPayInvoice::invoice() ->query() ->withOrder('Order001') ->withTotalAmount(1050) ->get();
電子發票查詢結果包含以下資訊:
$invoiceResult->invoiceNumber() // 發票號碼:'GG72002017' $invoiceResult->randomNumber() // 發票隨機碼:'1234' $invoiceResult->orderNo() // 訂單編號:'Order001' $invoiceResult->invoiceTransNo() // ezPay 電子發票開立序號:'25072515224376654' $invoiceResult->invoiceStatus() // 發票狀態:`InvoiceStatus::ISSUED` (已開立) $invoiceResult->invoiceUploadStatus() // 發票上傳財政部之狀態:`InvoiceUploadStatus::UPLOADED` (已上傳) $invoiceResult->buyerName() // 買受人名稱:'John Doe' $invoiceResult->buyerTaxIdNumber() // 買受人統一編號:'12345678' $invoiceResult->buyerAddress() // 買受人地址:'台北市信義區信義路五段7號' $invoiceResult->buyerPhone() // 買受人電話:'02-12345678' $invoiceResult->buyerEmail() // 買受人電子信箱:'customer@example.com' $invoiceResult->invoiceType() // 發票類別:`InvoiceType::GENERAL` (07: 一般稅額計算) $invoiceResult->category() // 發票種類:`InvoiceCategory::B2C` (B2C電子發票) $invoiceResult->taxType() // 課稅別:`TaxType::TAXABLE` (應稅) $invoiceResult->taxRate() // 稅率:5.0 (5%) $invoiceResult->amount() // 發票銷售額合計 (未稅):1000 $invoiceResult->salesAmount() // 銷售額 (課稅別應稅的未稅金額):300 $invoiceResult->zeroAmount() // 銷售額 (課稅別零稅率的未稅金額):350 $invoiceResult->freeAmount() // 銷售額 (課稅別免稅的未稅金額):300 $invoiceResult->taxAmount() // 稅額:50 $invoiceResult->totalAmount() // 含稅銷售額:1050 $invoiceResult->carrierType() // 載具類型:`CarrierType::MOBILE` (手機條碼載具) $invoiceResult->carrierNumber() // 載具編號:'/ABC.123' $invoiceResult->loveCode() // 捐贈碼:'1234567' $invoiceResult->printFlag() // 是否索取紙本發票:true (索取紙本發票) $invoiceResult->kioskPrintFlag() // 是否開放至合作超商 Kiosk 列印:true (開放列印) $items = $invoiceResult->items() // 商品項目陣列 // [ // [ // 'number' => 1, // 'name' => '測試商品', // 'quantity' => 1, // 'unit' => '個', // 'price' => 1000, // 'amount' => 1000, // 'taxType' => TaxType::TAXABLE, // 應稅 // ], // [ // 'number' => 2, // 'name' => 'Test Product', // 'quantity' => 2, // 'unit' => 'EA', // 'price' => 600, // 'amount' => 1200, // 'taxType' => TaxType::ZERO_RATE, // 零稅率 // ], // ]
除了透過 API 查詢電子發票外,也可以直接跳轉到 ezPay 平台的查詢發票頁面:
Route::get('/invoice/search', function () { return EzPayInvoice::invoice() ->query() ->withInvoice('GG72002017') ->withRandomNumber('1234') ->redirectToEzPay(); });
或者是取得表單資料,並自行撰寫前端表單進行跳轉:
Tip
HTML 表單可以參考 src/Transporters/FormRedirectTransporter.php
$requestData = EzPayInvoice::invoice() ->query() ->withInvoice('GG72002017') ->withRandomNumber('1234') ->toRedirectRequestData(); // [ // 'url' => 'https://cinv.ezpay.com.tw/Api/invoice_issue', // 'formData' => [ // 'MerchantID_' => 'your-merchant-id', // 'PostData' => 'xxxxxx', // ], // ]
或者是單純取得 ezPay 平台的查詢發票網址:
$url = EzPayInvoice::invoice() ->query() ->withInvoice('GG72002017') ->withRandomNumber('1234') ->getEzPaySearchUrl(); // 'https://inv.ezpay.com.tw/Invoice_index/search_platform?PostData=xxxxxx'
作廢電子發票
作廢電子發票需要傳入發票號碼和作廢原因:
EzPayInvoice::invoice() ->voidable() ->withInvoice('GG72002017') ->because('客戶取消訂單') ->invalidate();
開立折讓
當需要對已開立的電子發票進行部分或全部退貨時,可以立即開立發票折讓 (同時會立即確認折讓):
$result = EzPayInvoice::allowance() ->create() ->withInvoice('GG72002018') ->withOrder('Order001') ->withItem('退貨商品', quantity: 2, unit: '個', price: 300, amount: 600, taxAmount: 30) ->withTotalAmount(630) ->withNotification('customer@example.com') ->issue(); $result->allowanceNo() // 折讓號:'A250725235346456' $result->orderNo() // 訂單編號:'Order001' $result->invoiceNumber() // 發票號碼:'GG72002018' $result->allowanceAmount() // 折讓金額:630 $result->remainingAmount() // 折讓後剩餘發票金額:420
開立並延遲確認折讓
開立延遲確認的折讓,待買受人確認折讓後,再向 ezPay 平台發動確認折讓:
$result = EzPayInvoice::allowance() ->create() ... ->issuePendingConfirmation();
買受人發動確認折讓:
EzPayInvoice::allowance() ->pending() ->withAllowance('A250726001830959') ->withOrder('Order001') ->withTotalAmount(420) ->confirm();
買受人發動取消折讓:
EzPayInvoice::allowance() ->pending() ->withAllowance('A250726001830959') ->withOrder('Order001') ->withTotalAmount(420) ->cancel();
作廢折讓
作廢已開立的折讓,需傳入折讓號和作廢原因:
EzPayInvoice::allowance() ->voidable() ->withAllowance('A250726001830959') ->because('作廢原因') ->invalidate();
電子發票 API (境外電商版)
境外電商版的電子發票 API 主要差異在於部分欄位不同,不支援載具和捐贈碼,但增加了外幣、匯率等欄位,因此可在金額中輸入最多兩位小數。
境外電商開立電子發票
開立 B2C 電子發票的基本範例:
use Agriweather\EzPayInvoice\Enums\Invoice\CurrencyType; use Agriweather\EzPayInvoice\Facades\EzPayInvoice; $result = EzPayInvoice::crossBorder() ->invoice() ->create() ->withOrder('Order001') // 訂單編號 ->withCustomer('John Doe') // 買受人姓名 ->withEmail('customer@example.com') // 買受人電子信箱 ->withAddress('台北市信義區信義路五段7號') // 買受人地址 ->withCurrency(CurrencyType::USD) // 幣別:USD 美元 ->withItem('國際商品', quantity: 1, unit: 'EA', price: 105.5, amount: 105.5) // 商品名稱、數量、單位、單價和金額 ->withAmount(100.0, 5.5, 105.5) // 未稅銷售額、稅額、含稅銷售額 ->withOriginalCurrencyAmount(100.0) // 營業人備註之原幣金額 ->withExchangeRate(30.5) // 營業人備註之匯率 ->issue();
設定電子發票使用幣別、原幣金額和匯率:
use Agriweather\EzPayInvoice\Enums\Invoice\CurrencyType; $result = EzPayInvoice::crossBorder() ->invoice() ->create() ->withCurrency(CurrencyType::USD) // 幣別:USD 美元 ->withOriginalCurrencyAmount(100.0) // 營業人備註之原幣金額 ->withExchangeRate(30.5) // 營業人備註之匯率
ezPay 電子發票的幣別支援:
- USD
- HKD
- GBP
- AUD
- CAD
- SGD
- CHF
- JPY
- ZAR
- SEK
- NZD
- THB
- PHP
- IDR
- EUR
- KRW
- VND
- MYR
- CNY
- TWD
設定電子發票的商品項目和銷售額:
Important
銷售額計算方式,請務必與公司財會人員進行確認。
EzPayInvoice::crossBorder() ->invoice() ->create() // 增加商品項目 ->withItem('測試商品', quantity: 1, unit: '個', price: 105.5, amount: 105.5) ->withItem('Test Product', quantity: 2, unit: 'EA', price: 217.5, amount: 435) // 批次增加商品項目 ->withItems([ [ 'name' => '測試商品', 'quantity' => 1, 'unit' => '個', 'price' => 105.5, 'amount' => 105.5, ], [ 'name' => 'Test Product', 'quantity' => 2, 'unit' => 'EA', 'price' => 217.5, 'amount' => 435, ], ]) // 未稅銷售額、稅額、含稅銷售額 ->withAmount(520.0, 20.5, 540.5)
設定發票備註:
EzPayInvoice::crossBorder() ->invoice() ->create() ->withComment('發票備註'); // 發票備註,字數限 200 字,如有難字則再縮短
立即開立發票:
// 立即開立發票 $result = EzPayInvoice::crossBorder() ->invoice() ->create() ... ->issue(); $result->invoiceNumber() // 發票號碼:'AB12345678' $result->randomNumber() // 發票隨機碼:'1234' $result->orderNo() // 訂單編號:'Order001' $result->totalAmount() // 含稅銷售額:105.5
等待觸發開立發票:
// 等待觸發開立發票 // 當選擇此開立發票方式時,發票資料僅暫存於平台,需手動呼叫「觸發電子發票 API」來完成開立。 $result = EzPayInvoice::crossBorder() ->invoice() ->create() ... ->deferIssue(); // 預約自動開立發票 // 當選擇此開立發票方式時,發票會在設定時間自動開立,如需提前開立,可手動呼叫「觸發電子發票 API」。 $result = EzPayInvoice::crossBorder() ->invoice() ->create() ... ->scheduleAt('2025-03-01'); // 設定開立發票的時間 // 保存這些資料用於觸發開立發票 $result->invoiceTransNo() // ezPay 電子發票開立序號:'25072515224376654' $result->orderNo() // 訂單編號:'Order001' $result->totalAmount() // 含稅銷售額:105.5
境外電商觸發開立電子發票
若使用了 等待觸發開立發票 (deferIssue()
) 方式,需呼叫觸發電子發票 API 來完成開立。若使用 預約自動開立發票 (scheduleAt()
) 方式,則可透過呼叫觸發 API 來提前開立發票:
$result = EzPayInvoice::crossBorder() ->invoice() ->pending() ->withInvoiceTransNo('25072515224376654') ->withOrder('Order004') ->withTotalAmount(217.5) ->trigger();
境外電商查詢電子發票
使用發票號碼和隨機碼查詢電子發票:
$invoiceResult = EzPayInvoice::crossBorder() ->invoice() ->query() ->withInvoice('GG72002017') ->withRandomNumber('1234') ->get();
或者也可使用訂單編號及發票金額查詢電子發票:
$invoiceResult = EzPayInvoice::crossBorder() ->invoice() ->query() ->withOrder('Order001') ->withTotalAmount(105.5) ->get();
電子發票查詢結果包含以下資訊:
$invoiceResult->invoiceNumber() // 發票號碼:'GG72002017' $invoiceResult->randomNumber() // 發票隨機碼:'1234' $invoiceResult->orderNo() // 訂單編號:'Order001' $invoiceResult->invoiceTransNo() // ezPay 電子發票開立序號:'25072515224376654' $invoiceResult->invoiceStatus() // 發票狀態:`InvoiceStatus::ISSUED` (已開立) $invoiceResult->invoiceUploadStatus() // 發票上傳財政部之狀態:`InvoiceUploadStatus::UPLOADED` (已上傳) $invoiceResult->buyerName() // 買受人名稱:'John Doe' $invoiceResult->buyerAddress() // 買受人地址:'台北市信義區信義路五段7號' $invoiceResult->buyerEmail() // 買受人電子信箱:'customer@example.com' $invoiceResult->invoiceType() // 發票類別:`InvoiceType::GENERAL` (07: 一般稅額計算) $invoiceResult->currency() // 幣別:`CurrencyType::USD` (USD 美元) $invoiceResult->originalCurrencyAmount() // 營業人備註之原幣金額:100.0 $invoiceResult->exchangeRate() // 營業人備註之匯率:30.5 $invoiceResult->amount() // 發票銷售額合計 (未稅):100.0 $invoiceResult->taxAmount() // 稅額:5.5 $invoiceResult->totalAmount() // 含稅銷售額:105.5 $items = $invoiceResult->items() // 商品項目陣列 // [ // [ // 'number' => 1, // 'name' => '測試商品', // 'quantity' => 1, // 'unit' => '個', // 'price' => 105.5, // 'amount' => 105.5, // ], // [ // 'number' => 2, // 'name' => 'Test Product', // 'quantity' => 2, // 'unit' => 'EA', // 'price' => 217.5, // 'amount' => 435, // ], // ]
除了透過 API 查詢電子發票外,也可以直接跳轉到 ezPay 平台的查詢發票頁面:
Route::get('/invoice/search', function () { return EzPayInvoice::crossBorder() ->invoice() ->query() ->withInvoice('GG72002017') ->withRandomNumber('1234') ->redirectToEzPay(); });
或者是取得表單資料,並自行撰寫前端表單進行跳轉:
Tip
HTML 表單可以參考 src/Transporters/FormRedirectTransporter.php
$requestData = EzPayInvoice::invoice() ->query() ->withInvoice('GG72002017') ->withRandomNumber('1234') ->toRedirectRequestData(); // [ // 'url' => 'https://cinv.ezpay.com.tw/Api/invoice_issue', // 'formData' => [ // 'MerchantID_' => 'your-merchant-id', // 'PostData' => 'xxxxxx', // ], // ]
或者是單純取得 ezPay 平台的查詢發票網址:
$url = EzPayInvoice::crossBorder() ->invoice() ->query() ->withInvoice('GG72002017') ->withRandomNumber('1234') ->getEzPaySearchUrl(); // 'https://inv.ezpay.com.tw/Invoice_index/search_platform?PostData=xxxxxx'
境外電商作廢電子發票
作廢電子發票需要傳入發票號碼和作廢原因:
EzPayInvoice::crossBorder() ->invoice() ->voidable() ->withInvoice('GG72002017') ->because('客戶取消訂單') ->invalidate();
境外電商開立折讓
當需要對已開立的電子發票進行部分或全部退貨時,可以立即開立發票折讓 (同時會立即確認折讓):
$result = EzPayInvoice::crossBorder() ->allowance() ->create() ->withInvoice('GG72002018') ->withOrder('Order001') ->withItem('退貨商品', quantity: 2, unit: '個', price: 217.5, amount: 435) ->withTotalAmount(435) ->withNotification('customer@example.com') ->issue(); $result->allowanceNo() // 折讓號:'A250725235346456' $result->orderNo() // 訂單編號:'Order001' $result->invoiceNumber() // 發票號碼:'GG72002018' $result->allowanceAmount() // 折讓金額:435 $result->remainingAmount() // 折讓後剩餘發票金額:105.5
境外電商開立並延遲確認折讓
開立延遲確認的折讓,待買受人確認折讓後,再向 ezPay 平台發動確認折讓:
$result = EzPayInvoice::crossBorder() ->allowance() ->create() ... ->issuePendingConfirmation();
買受人發動確認折讓:
EzPayInvoice::crossBorder() ->allowance() ->pending() ->withAllowance('A250726001830959') ->withOrder('Order001') ->withTotalAmount(435) ->confirm();
買受人發動取消折讓:
EzPayInvoice::crossBorder() ->allowance() ->pending() ->withAllowance('A250726001830959') ->withOrder('Order001') ->withTotalAmount(435) ->cancel();
境外電商作廢折讓
作廢已開立的折讓,需傳入折讓號和作廢原因:
EzPayInvoice::crossBorder() ->allowance() ->voidable() ->withAllowance('A250726001830959') ->because('作廢原因') ->invalidate();
字軌管理 API
準備帳號代號和金鑰
字軌管理和開立電子發票需要不同的帳號代號和金鑰。首先前往 ezPay 電子發票平台的「會員管理」頁面,找到並複製會員編號、會員 API 串接金鑰的 HashKey
和 HashIV
,然後將這些資訊設定到 .env
檔案中的 EZPAY_INVOICE_COMPANY_ID
等參數:
EZPAY_INVOICE_COMPANY_ID=your-company-id EZPAY_INVOICE_COMPANY_HASH_KEY=your-company-hash-key EZPAY_INVOICE_COMPANY_HASH_IV=your-company-hash-iv
申請新字軌
使用新增字軌 API 申請新字軌:
use Agriweather\EzPayInvoice\Enums\Invoice\InvoiceTerm; use Agriweather\EzPayInvoice\Enums\Invoice\InvoiceType; use Agriweather\EzPayInvoice\Facades\EzPayInvoice; $result = EzPayInvoice::alphanumericCode() ->create() ->withYear(113) // 民國年,只可輸入今年與明年。 ->withTerm(InvoiceTerm::JUL_AUG) // 發票期別:07-08月 ->withCode('AA') // 字軌英文代碼 ->withRange('24000100', '24000199') // 發票號碼範圍 ->withType(InvoiceType::GENERAL) // 發票類別:`InvoiceType::GENERAL` (07: 一般稅額計算) ->save(); $result->managementNo() // 字軌管理編號:'0t0ghr0fyv' $result->lastNumber() // 該組字軌剩餘張數:100 $result->status() // 字軌狀態: `AlphanumericCodeStatus::ACTIVE` (啟用)
查詢字軌
使用發票年度和期別來查詢字軌資訊:
$alphanumericCodeResults = EzPayInvoice::alphanumericCode() ->query() ->withYear(113) ->withTerm(InvoiceTerm::JUL_AUG) ->get(); foreach ($alphanumericCodeResults as $result) { $result->managementNo() // 字軌管理編號:'0t0ghr0fyv' $result->year() // 發票年度:113 $result->term() // 發票期別:`InvoiceTerm::JUL_AUG` (07-08月) $result->alphanumericCode() // 字軌英文代碼:'AA' $result->startNumber() // 字軌起號:'24000100' $result->endNumber() // 字軌迄號:'24000199' $result->lastNumber() // 該組字軌剩餘張數:100 $result->type() // 發票類別:`InvoiceType::GENERAL` (07: 一般稅額計算) $result->status() // 字軌狀態: `AlphanumericCodeStatus::ACTIVE` (啟用) }
啟用字軌
如果字軌是暫停狀態,可以啟用字軌。需要傳入字軌管理編號和發票年度:
EzPayInvoice::alphanumericCode() ->query() ->withNo('0t0ghr0fyv') ->withYear(113) ->enable();
暫停字軌
如果字軌是啟用狀態,可以暫停字軌。需要傳入字軌管理編號和發票年度:
$result = EzPayInvoice::alphanumericCode() ->query() ->withNo('0t0ghr0fyv') ->withYear(113) ->pause();
停用字軌
可以停用字軌,但請注意,停用後將無法再啟用該字軌。需要傳入字軌管理編號和發票年度:
EzPayInvoice::alphanumericCode() ->query() ->withNo('0t0ghr0fyv') ->withYear(113) ->disable();
手機條碼與捐證碼驗證 API
驗證手機條碼
驗證手機條碼是否存在於財政部電子發票整合服務平台:
use Agriweather\EzPayInvoice\Facades\EzPayInvoice; $result = EzPayInvoice::codeValidation() ->withBarcode('/ABC.123') ->check(); $result->isValid() // 手機條碼是否有效:true
驗證捐證碼
驗證捐證碼是否存在於財政部電子發票整合服務平台:
use Agriweather\EzPayInvoice\Facades\EzPayInvoice; $result = EzPayInvoice::codeValidation() ->withLoveCode('123') ->check(); $result->isValid() // 捐證碼是否有效:true
錯誤處理
當 ezPay API 回傳失敗的回應時,會拋出 EzPayInvoiceException
例外,可以取得 ezPay 的錯誤代碼和錯誤訊息進行進一步處理:
use Agriweather\EzPayInvoice\Exceptions\EzPayInvoiceException; try { $result = EzPayInvoice::invoice() ->create() ... ->issue(); } catch (EzPayInvoiceException $e) { $status = $e->getApiStatus(); // 'KEY10013' $message = $e->getApiMessage(); // '資料不可空白MerchantOrderNo' // 記錄錯誤日誌... logger()->error($e->getMessage(), $e->context()); // 顯示錯誤訊息給使用者... return response()->json([ 'error' => $message, ], 400); }
單元測試
在單元測試中,可以使用 EzPayInvoice::fake()
模擬 API 回應,這邊要模擬開立發票回應,因此使用 CreateResult
來建立模擬回應資料:
<?php use Agriweather\EzPayInvoice\Enums\Invoice\InvoiceCategory; use Agriweather\EzPayInvoice\Enums\Invoice\TaxType; use Agriweather\EzPayInvoice\Facades\EzPayInvoice; use Agriweather\EzPayInvoice\Resources\Invoice; use Agriweather\EzPayInvoice\Results\Invoice\CreateResult; test('can create invoice', function () { // 模擬發票開立 API 回應 EzPayInvoice::fake([ // 模擬開立發票回應 // 需要使用實際呼叫的 Result 類別來建立模擬回應 // // 因為下面使用 EzPayInvoice::invoice()->create()->issue() 來開立發票 // 因此模擬的回應類別需要使用 CreateResult 類別 CreateResult::make([ 'Status' => 'SUCCESS', 'Message' => '發票開立成功', 'Result' => [ 'CheckCode' => '123456789', 'MerchantID' => '111335678', 'MerchantOrderNo' => 'Order001', 'InvoiceNumber' => 'GG72002017', 'TotalAmt' => 1050, 'InvoiceTransNo' => '25072515224376654', 'RandomNum' => '1234', 'CreateTime' => '2025-01-01 00:00:00', ], ]), ]); // 測試發送開立發票請求 $response = $this->post('/invoice/create', [ 'category' => 'B2C', 'name' => 'John Doe', 'email' => 'customer@example.com', 'items' => [ [ 'name' => '測試商品', 'quantity' => 1, 'unit' => '個', 'price' => 1000, 'amount' => 1000, ], ], 'total_amount' => 1050, ]); // 斷言發送參數 // // 因為上面是呼叫 EzPayInvoice::invoice()->create() // // 因此斷言的資源類別和方法名稱分別是: // - Invoice::class 是 invoice() 方法回傳的資源類別 // - 'create' 是呼叫的方法名稱 EzPayInvoice::assertSent(Invoice::class, 'create', function (CreateOptions $options) { return $options->orderNo === 'Order001' && $options->category === InvoiceCategory::B2C && $options->buyerName === 'John Doe' && $options->buyerEmail === 'customer@example.com' && $options->hasItem('測試商品', quantity: 1, unit: '個', price: 1000, amount: 1000) && $options->taxType === TaxType::TAXABLE && $options->taxRate === 5.0 && $options->totalAmount === 1050; }); });
Warning
不支援模擬查詢發票的 redirectToEzPay()
和 toRedirectRequestData()
方法,因為這兩個方法是直接產生跳轉表單資料,實際上不會發送 API 請求。
除錯支援
當發生錯誤時,請協助提供請求與回應的除錯資料,以便更快速地定位問題:
use Agriweather\EzPayInvoice\Options\Options; $result = EzPayInvoice::invoice() ->create() ->withOrder('Order001') ... ->onPreparedOptions(function (Options $options) { dd($options->toArray()); // 查看請求參數資料 }) ->issue(); dd($result->toArray()); // 查看回應資料
- 使用
$options->toArray()
方法可檢視發送至 API 的請求資料 - 透過
$result->toArray()
可檢視 API 的回應資料內容 - 當發生錯誤時,請在提交 issue 時一併提供請求與回應的除錯資料
API 參考文件
當前參考文件版本:
- 電子發票API v1.2.2 (2024/05/09)
- 電子發票API_境外電商版 v1.0.0 (2021/02/02)
- 字軌管理API v1.0.0 (2018/10/08)
- 手機條碼與捐證碼驗證技術串接手冊 v1.0.0 (2021/03/03)
貢獻專案
歡迎參與貢獻專案,請參考 貢獻指南 文件。
License
基於 MIT LICENSE 釋出