一、目前架構分析
| 項目 | 目前選型 |
| 後端 | Python FastAPI |
| 前端 | Jinja2 + Vanilla JS(Web UI) |
| 資料庫 | SQLite(本地檔案) |
| OCR | Google Gemini Vision API |
| 打包 | PyInstaller → .app |
| 個資處理 | 身分證字號 AES 加密,全部本地儲存 |
| 授權機制 | 離線序號驗證 + 硬體綁定 |
二、PyInstaller 能不能上 App Store?
結論:極度困難,實務上幾乎不可行。
具體限制
| 問題 | 說明 |
| App Sandbox | Mac App Store 強制要求沙盒環境,PyInstaller 的 bundle 結構不符合 Apple 的沙盒 entitlements 規範 |
| 代碼簽名 | PyInstaller bundle 內含大量 .so/.dylib,每一個都必須逐檔簽名(codesign --deep 不被 App Store 接受) |
| Bundle 結構 | Apple 對 .app 內部結構有嚴格規範(Frameworks/、Resources/),PyInstaller 輸出不符合 |
| 動態載入 | Python 的 importlib、動態 import 可能被審核拒絕(禁止執行非 bundle 內的程式碼) |
| 私有 API | Python 的部分 C extension 可能觸碰 Apple 認定的私有 API |
| 架構支援 | 必須支援 Apple Silicon (arm64),PyInstaller 需特別處理 Universal Binary |
社群中極少有人成功用 PyInstaller 上架 Mac App Store,多數嘗試者最終放棄。
三、替代方案比較
方案 A:Tauri 推薦度:高
Rust 後端 + 系統 WebView(macOS 上是 WKWebView)顯示前端 UI。
| 優點 | 缺點 |
- 打包體積小(5-15 MB)
- 原生支援 App Sandbox 和代碼簽名
- 官方文件有 App Store 上架教學
- 可直接用現有的 Web UI 前端
- Tauri v2 支援 sidecar(可嵌入 Python)
|
- 需要學 Rust(但基本配置不用寫太多)
- 後端需要改寫或適配
- 沙盒下 sidecar Python 可能有限制
|
方案 B:Electron 推薦度:中
Chromium + Node.js 運行環境。VS Code、Slack、Notion 都用 Electron。
| 優點 | 缺點 |
- 生態成熟,大量 App Store 上架案例
- electron-builder 內建 App Store 打包
- 可用現有 Web UI
|
- 打包體積大(150-300 MB)
- 記憶體消耗高
- 後端需改寫成 Node.js
- Apple 近年對 Electron 審核趨嚴
|
方案 C:SwiftUI + WKWebView 推薦度:中高
原生 Swift App 用 WKWebView 載入 Web UI。
| 優點 | 缺點 |
- 最符合 Apple 審核偏好
- 原生支援 Sandbox、簽名、公證
- 打包體積小
- Xcode 直接管理
|
- 需要學 Swift/SwiftUI
- 後端必須改寫成 Swift
- 工作量最大
|
方案 D:不上 App Store,公證後直接分發 推薦度:高
保持 PyInstaller 打包,做 Apple Notarization 後用 DMG 分發。
| 優點 | 缺點 |
- 不需要改架構,繼續用 PyInstaller
- 公證後 Gatekeeper 不會阻擋
- 不受 App Sandbox 限制
|
- 沒有 App Store 曝光和自動更新
- 使用者安裝流程較複雜
- 需自己處理更新機制
- 仍需 Developer 年費 $99
|
四、App Store 上架完整流程
費用
Apple Developer Program 年費:USD $99/年(約 NTD $3,100),需要 Apple ID 且必須開啟雙重認證。
流程步驟
1. 註冊 Apple Developer Program
└ developer.apple.com 申請,個人需身份驗證
2. 在 App Store Connect 建立 App 記錄
└ 填寫 App 名稱、Bundle ID、SKU、定價
3. 準備 App
└ 確保符合 App Sandbox、代碼簽名、公證要求
4. 用 Xcode 或 Transporter 上傳 Build
└ .app 包在 .pkg 裡,用 productbuild 打包
5. 填寫 App Store 資訊
└ 截圖、描述、分類、隱私政策 URL、年齡分級
6. 送審
└ Apple 審核,通常 24-48 小時
7. 上架
└ 審核通過後選擇立即或手動發布
五、審核重點與常見拒審原因
必要條件
| 項目 | 要求 |
| App Sandbox | Mac App Store 強制要求。SQLite 必須放在 App container 內,Gemini API 需宣告 network.client entitlement |
| 代碼簽名 | 必須用 Apple Distribution 憑證,所有 framework/dylib/executable 逐檔簽名,hardened runtime 必須開啟 |
| 隱私政策 | 強制提供 URL,必須在 App Store Connect 填寫「App 隱私」問卷 |
| 加密宣告 | 使用 AES 加密需回答 ECCN/出口合規問題(資料保護用途通常屬於豁免) |
常見拒審原因
- App 功能太簡單(Apple 可能認為應該是網站而非 App)
- 使用過時 API 或 deprecated framework
- 崩潰或明顯 bug
- UI 不符合 macOS Human Interface Guidelines
- 未正確處理離線行為(你的 App 依賴 Gemini API,離線時要有提示)
- 個資收集未充分告知使用者
六、個資處理的額外要求
Apple 端要求
- App 隱私標籤:精確填寫收集的資料類型 — 聯絡資訊(姓名、電話)、身份識別資訊(身分證字號)
- 資料加密宣告:AES 用於資料保護(非通訊加密),通常選「屬於豁免」
- 資料最小化原則:只收集 App 功能所需的最少資料
台灣個資法要求
你的 App 處理客戶身分證字號,屬於台灣《個人資料保護法》規範的「個人資料」,需特別注意。
- 告知使用者:收集目的、利用範圍、使用期間
- 取得當事人同意
- 提供查詢、更正、刪除的權利
- 採取適當安全措施(你已做 AES 加密)
- 保險業務員管理客戶資料,適用「非公務機關」條款
- 建議加入 App 內隱私政策頁面和資料管理功能(匯出、刪除)
七、台灣開發者稅務注意事項
Apple 抽成
- 付費 App 或 IAP:Apple 抽 30%
- 小型開發者計畫(年營收低於 100 萬美元):降為 15%
- 免費 App 不涉及抽成
美國預扣稅
- 台灣與美國沒有全面性租稅協定
- 來自美國的銷售收入會被預扣 30% 聯邦稅
- 其他國家/地區的收入不受影響
- 需在 App Store Connect 填寫 W-8BEN 表格
台灣端
| 項目 | 說明 |
| 所得稅 | App Store 收入屬「海外所得」,全年超過 NTD 100 萬需計入基本所得額 |
| 營業稅 | 月營收超過 NTD 8 萬起徵點,需辦理營業登記開發票 |
| 銀行帳戶 | 需能收外幣的帳戶(大部分台灣銀行可以) |
如果 App 是免費的,稅務問題大幅簡化 — 無收入 = 無抽成 = 無預扣稅。
八、建議方案
針對你的車險管理工具,建議排序:
1. 如果不堅持 App Store → 公證後直接分發(最省事)
保持現有 PyInstaller 架構,做 Apple Notarization 後用 DMG 分發。不需要改程式碼,只需要:
codesign 簽名所有二進位
xcrun notarytool submit 送公證
xcrun stapler staple 釘選公證結果
- 包成 DMG 分發
仍需 Developer 年費 $99,但省去所有 App Store 限制。
2. 如果一定要 App Store → Tauri(前端幾乎不改)
用 Tauri 包裝你的 Web UI,後端邏輯改寫或用 sidecar 嵌入。官方有完整的 App Store 上架文件。
3. 如果願意大改 → SwiftUI 原生 App(最符合 Apple 標準)
完全改寫成 Swift,最不會被 Apple 審核刁難,但工作量最大。
實務建議:你的使用者是保險業務員,主要透過你直接提供 App,不太需要 App Store 的曝光效果。方案 D(公證 + DMG 分發)可能是投入產出比最高的選擇。如果未來使用者量成長需要 App Store 通路,再考慮用 Tauri 重新包裝。