PHP code example of dennykuo / invoice-porter
1. Go to this page and download the library: Download dennykuo/invoice-porter library . Choose the download type require .
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
dennykuo / invoice-porter example snippets
use InvoicePorter\Ezpay\Environment;
use InvoicePorter\Ezpay\EzpayConfig;
new EzpayConfig(
merchantId: 'YOUR_MERCHANT_ID',
hashKey: 'YOUR_HASH_KEY_32_CHARS_xxxxxxxxxxx', // 必須 32 字元
hashIv: 'YOUR_IV_16_CHARS', // 必須 16 字元
environment: Environment::Sandbox, // 或 Environment::Production
timeoutSeconds: 10.0, // 預設 10 秒
connectTimeoutSeconds: 5.0, // 預設 5 秒
);
EzpayConfig::fromEnv(); // 讀 EZPAY_MERCHANT_ID / HASH_KEY / HASH_IV / ENVIRONMENT
EzpayConfig::fromEnv('VENDOR_A_'); // 讀 VENDOR_A_MERCHANT_ID …(適合一個系統多個藍新帳號)
// config/ezpay.php
return [
'merchant_id' => env('EZPAY_MERCHANT_ID'),
'hash_key' => env('EZPAY_HASH_KEY'),
'hash_iv' => env('EZPAY_HASH_IV'),
'environment' => env('EZPAY_ENVIRONMENT', 'sandbox'),
'timeout_seconds' => 10.0,
'connect_timeout_seconds' => 5.0,
// 以下三欄為字軌 API 才需要
'company_id' => env('EZPAY_COMPANY_ID'),
'company_hash_key' => env('EZPAY_COMPANY_HASH_KEY'),
'company_hash_iv' => env('EZPAY_COMPANY_HASH_IV'),
];
// AppServiceProvider 之類
$config = EzpayConfig::fromArray(config('ezpay'));
use InvoicePorter\Ezpay\EzpayInvoiceClient;
use InvoicePorter\Ezpay\Enums\Category;
use InvoicePorter\Ezpay\Enums\InvoiceStatus;
use InvoicePorter\Ezpay\Enums\TaxType;
use InvoicePorter\Ezpay\Requests\InvoiceIssueRequest;
use InvoicePorter\Ezpay\Requests\Items\InvoiceItem;
$client = new EzpayInvoiceClient(EzpayConfig::fromEnv());
$response = $client->issue(new InvoiceIssueRequest(
status: InvoiceStatus::Immediate,
merchantOrderNo: 'ORD_' . date('YmdHis'),
category: Category::B2C,
taxType: TaxType::Taxable,
amount: 476,
taxAmount: 24,
totalAmount: 500,
items: [
new InvoiceItem(name: '商品一', count: 1, unit: '個', price: 500, amount: 500),
],
));
echo $response->invoiceNumber();
use InvoicePorter\Ezpay\Enums\InvoiceTerm;
use InvoicePorter\Ezpay\EzpayConfig;
use InvoicePorter\Ezpay\EzpayTrackClient;
use InvoicePorter\Ezpay\Requests\Track\TrackCreateRequest;
$config = new EzpayConfig(
merchantId: 'YOUR_MERCHANT_ID',
hashKey: 'YOUR_HASH_KEY_32_CHARS_xxxxxxxxxxx',
hashIv: 'YOUR_IV_16_CHARS',
companyId: 'YOUR_COMPANY_ID', // 字軌專用
companyHashKey: 'YOUR_COMPANY_HASH_KEY_32_xxxxxxxxxxxxx', // 字軌專用
companyHashIv: 'YOUR_COMPANY_IV', // 字軌專用
);
$client = new EzpayTrackClient($config);
$response = $client->trackCreate(new TrackCreateRequest(
year: '115', // 民國年三碼
term: InvoiceTerm::JanFeb, // 1=一二月、2=三四月、…
aphabeticLetter: 'AB', // 字軌字母(兩碼大寫)
startNumber: '00000000', // 起號 8 碼
endNumber: '00000049', // 訖號 8 碼
));
echo $response->managementNo(); // 新增成功後的字軌管理編號
// 觸發開立(先以 InvoiceStatus::Pending 建單後,呼叫此 API 才實際開立)
$client->touchIssue(new InvoiceTouchIssueRequest(
merchantOrderNo: 'ORD_20260504_001',
totalAmount: 500,
));
// 作廢發票(最小欄位)
$client->invalid(new InvoiceInvalidRequest(
invoiceNumber: 'AA00000076',
invalidReason: '訂單取消',
));
// 開立折讓
$client->issueAllowance(new AllowanceIssueRequest(
invoiceNo: 'AA00000076',
merchantOrderNo: 'ORD_20260504_001',
totalAmount: 100,
taxAmount: 5,
items: [new AllowanceItem(name: '商品一', count: 1, unit: '個', price: 95, amount: 95, taxAmount: 5)],
));
// 確認 / 取消折讓
$client->touchAllowance(new AllowanceTouchIssueRequest(
allowanceNo: 'A001',
status: AllowanceTouchStatus::Confirm, // 或 ::Deny(取消)
));
// 作廢折讓
$client->invalidAllowance(new AllowanceInvalidRequest(
allowanceNo: 'A001',
invalidReason: '客戶取消',
));
// 用發票號碼查詢(必須帶 randomNum)
$response = $client->search(new InvoiceSearchRequest(
searchType: SearchType::ByInvoiceNumber,
merchantOrderNo: 'ORD_20260504_001',
invoiceNumber: 'AA00000076',
randomNum: '0991',
));
echo $response->lifecycleStatus()?->value; // 1=已開立、2=已作廢
new InvoiceIssueRequest(
status: InvoiceStatus::Immediate,
merchantOrderNo: 'ORD_...',
category: Category::B2B,
taxType: TaxType::Taxable,
amount: 476, taxAmount: 24, totalAmount: 500,
buyerName: '王大公司',
buyerUbn: '12345678', // B2B 必填,否則 EzpayValidationException
items: [new InvoiceItem(...)],
);
new InvoiceIssueRequest(
// ...
carrierType: CarrierType::Mobile, // 或 ::CitizenDigitalCertificate / ::Member
carrierNum: '/ABC1234', // 手機條碼以 / 開頭
);
new InvoiceIssueRequest(
// ...
loveCode: '13994', // 不可與 carrierType 同時使用
);
new InvoiceIssueRequest(
status: InvoiceStatus::Scheduled,
createStatusTime: '2026-06-01', // YYYY-MM-DD,必填
// ...
);
// 混合稅率時,每個 item 必須給 taxType('1' 應稅、'2' 零稅、'3' 免稅)
new InvoiceIssueRequest(
taxType: TaxType::Mixed,
items: [
new InvoiceItem(name: '應稅商品', count: 1, unit: '個', price: 100, amount: 100, taxType: '1'),
new InvoiceItem(name: '免稅商品', count: 1, unit: '個', price: 50, amount: 50, taxType: '3'),
],
// ...
);
$response->isSuccess(); // bool — 等同 status() === 'SUCCESS'
$response->status(); // string — 'SUCCESS' 或業務錯誤碼
$response->message(); // string — 藍新原始訊息
$response->rawResponse(); // array — 完整 envelope,方便寫 log
$response->createTime(); // ?string — 藍新原始 'Y-m-d H:i:s'
$response->createTimeAt(); // ?DateTimeImmutable — 解析後物件,省去自行 parse
use InvoicePorter\Ezpay\Exceptions\EzpayApiException;
use InvoicePorter\Ezpay\Exceptions\EzpayException;
try {
$response = $client->issue($request);
} catch (EzpayApiException $e) {
// 業務錯誤:可拿到 errorCode / message / rawResponse
log_business_error($e->errorCode, $e->getMessage());
} catch (EzpayException $e) {
// 其餘 SDK 錯誤
log_sdk_error($e);
}
try {
$response = $client->issue($request);
} catch (EzpayApiException $e) {
if ($e->isDuplicateOrderNo()) {
// NOR10001 / LIB10003 → 產生新訂單編號後重新建 Request 重試
return retry_with_new_order_no();
}
if ($e->isAuthError()) {
// INV900xx / KEY100xx → 憑證或解密問題,告警 ops 修設定
alert_ops($e);
throw $e;
}
if ($e->isFieldFormatError()) {
// INV100xx / INV700xx → 欄位格式錯,引導使用者修正
return show_validation_error($e);
}
throw $e;
}
// 作廢發票 — 帶齊 4 個欄位即啟用 CheckCode 驗證
$client->invalid(new InvoiceInvalidRequest(
invoiceNumber: 'AA00000076',
invalidReason: '訂單取消',
randomNum: '0991',
invoiceTransNo: '24050414461511234',
merchantOrderNo: 'ORD_20260504_001',
totalAmount: 500,
));
// 折讓系列 — 明確開啟驗證
$client->issueAllowance(new AllowanceIssueRequest(
// ...
expectCheckCode: true,
));
echo $client->searchRedirectHtml($request);
$response = $client->search($request);
$url = $response->searchResultUrl();
// A:直接給四個欄位,不必先組 Request
echo $client->publicQueryRedirectHtml(
invoiceNumber: 'AA00000076',
randomNum: '0991',
merchantOrderNo: 'ORD_20260504_001',
totalAmount: 500,
);
// B:剛 issue 完,直接從 Response 產生 Request 再丟回 searchRedirectHtml()
$response = $client->issue($issueRequest);
echo $client->searchRedirectHtml($response->toSearchRequest());
use InvoicePorter\Exceptions\InvoiceException;
try {
$response = $client->issue($request);
} catch (InvoiceException $e) {
// 不論藍新或未來其他廠商,這裡都會接到
}
bash
cp examples/.env.example examples/.env
# 編輯 examples/.env 填入您自己的測試憑證
php examples/01-issue.php