故事要從上禮拜說起。原本我們在趕一個重要專案,也因為這個專案讓我好幾個禮拜沒辦法抽空寫文章(抱怨一下),結果我接到一位同事的詢問。他說供應商使用我們的API時出現了統一編號驗證錯誤。
這位同事James,他一臉困惑地走進來,手裡拿著一疊文件。他說:「R,你能幫我看看這個嗎?我們的供應商在使用API時,系統一直顯示統一編號驗證錯誤。」我放下手中的工作,仔細查看問題。James接著說:「我們的有問題的系統是Laravel框架。
我查了幾遍程式碼,邏輯看起來沒問題啊,為什麼會驗證失敗?」一開始,我也感到一頭霧水。這個檢查程式我們已經用了很久,之前從來沒有出過這種問題。我決定跟James一起深入調查,找出問題的根源。
首先,我們重新跑過一遍相關的單元測試。然後,我們回顧了檢查邏輯,確定Git的主分支沒有相關的改動過。然而,所有的檢查都顯示程式碼應該是正確的,但為什麼會出現錯誤呢?
private function isValidChecksum(int $sum): bool
{
return ($sum - round($sum / 10) * 10) == 0;
}
我們把目光轉向了最近的公告。沒錯,就是那則財政部關於統一編號檢查程式邏輯更改的公告。新的規則要求統一編號從「可被10整除」改為「可被5整除」。我恍然大悟,這應該就是問題的癥結點!
「James,我們的檢查邏輯需要更新了!」我說。「根據財政部的公告,現在的統一編號檢查邏輯改成可被5整除,我們的程式還在用舊的檢查規則。」
我們馬上開始修改程式碼,將檢查邏輯從「可被10整除」改為「可被5整除」。更新後,並且把供應商提供的統一編號加入單元測試的檢查點,我們重新測試了系統,這次供應商的統一編號終於通過了驗證。
private function isValidChecksum(int $sum): bool
{
return ($sum - round($sum / 5) * 5) == 0;
}
這個小插曲提醒我們,即使是看似不起眼的規則變更,也會對系統造成重大影響。幸好我們及時發現並修正了錯誤,讓專案得以順利進行。在解開這個謎團後,我不禁感嘆,技術的世界總是充滿挑戰,但這正是讓我們成長和進步的動力。現在,我終於可以安心地繼續趕專案,期待下次再跟大家分享更多的故事。
後記:這次把驗證段特別提取出來,在單元測試的驗證上再補上不足的地方,以下為完整的程式碼。
<?php
class InvoiceValidator
{
/**
* 檢查發票號碼是否合法
*
* @param string $invoiceId 發票號碼
* @return bool
*/
public function chkInvoiceId(string $invoiceId): bool
{
$checkKey = [1, 2, 1, 2, 1, 2, 4, 1];
$isum = 0;
// 計算加權和
for ($i = 0; $i < 8; $i++) {
$currentDigit = (int)substr($invoiceId, $i, 1);
$product = $checkKey[$i] * $currentDigit;
$a = (int)substr($product, 0, 1);
$b = (int)substr($product, 1, 1) ?: 0;
if ($i == 6 && substr($invoiceId, -2, 1) == '7') {
$isum1 = $isum + 1;
$isum2 = $isum;
} else {
$isum += $a + $b;
}
}
// 處理發票號碼倒數第二位為7的情況
if (substr($invoiceId, -2, 1) == '7') {
$isum1 += $a + $b;
$isum2 += $a + $b;
return $this->isValidChecksum($isum1) || $this->isValidChecksum($isum2);
}
// 檢查加權和的驗證碼
return $this->isValidChecksum($isum);
}
/**
* 檢查加權和的驗證碼
*
* @param int $sum 加權和
* @return bool
*/
private function isValidChecksum(int $sum): bool
{
return ($sum - round($sum / 5) * 5) == 0;
}
}
參考來源:
(營利事業統一編號檢查碼邏輯修正說明) https://www.fia.gov.tw/singlehtml/3?cntId=c4d9cff38c8642ef8872774ee9987283