指南

如何為應用程式加入付款功能:結帳、訂閱與 Webhook

在應用程式中加入付款功能,最簡單的方式是使用 Stripe:如果你只需要一個「購買」按鈕,並願意手動處理訂單,就用付款連結(Payment Link);如果你的應用程式需要知道是誰付款,並自動做出反應,就用 Stripe Checkout;如果是定期計費,則用訂閱模式的 Checkout,再搭配 Stripe 的客戶入口網站。除了最簡單的情況之外,其他方式都還需要一個 Webhook,也就是付款成功時 Stripe 會呼叫的伺服器端點。在切換到正式金鑰之前,請先用 Stripe 的測試金鑰和測試卡把所有功能測試一遍。

本指南會說明每一種選項、大多數教學會略過的 Webhook 部分,以及在收取真實款項之前需要檢查的事項。Stripe 的細節取自 Stripe 官方文件,時間為 2026 年 9 月。

為什麼要使用付款服務商

絕對不要在你自己的表單中收集信用卡號。直接處理原始卡片資料會讓你受到 PCI DSS(信用卡產業安全標準)的規範,並帶來嚴重的責任風險。像 Stripe 這樣的付款服務商會代管付款表單、儲存卡片、處理銀行驗證,並告訴你的應用程式結果。你的應用程式只會知道「客戶 X 為 Y 付了款」。

本指南使用 Stripe,因為它廣受使用、文件完整,而且大多數 AI 應用程式建置工具都支援它。其他服務商也存在,有些會以「商家代理人(merchant of record)」的身分替你處理銷售稅;如果稅務合規讓你擔心,這種模式值得比較。

使用 Stripe 收款的三種方式

選項是否需要寫程式你的應用程式是否知道誰付款最適合
付款連結(Payment Links)不需要只有在加上 Webhook 後才知道販售少數固定商品、捐款、測試需求
Checkout(單次付款)需要伺服器端程式碼建立工作階段是,透過 Webhook商店、付費下載、單次購買
Checkout(訂閱)需要伺服器端程式碼加上 Webhook 處理是,透過 WebhookSaaS、會員制、任何定期收費的情況

付款連結

付款連結是你在 Stripe 控制台中建立、由 Stripe 代管的付款頁面,不需要寫程式。你會得到一個網址,可以放在應用程式的按鈕後面、在電子郵件中分享,或製成 QR 碼。Stripe 的文件說明,付款連結可以販售一項商品、一項訂閱,或接受捐款;你可以讓顧客自行選擇要付的金額,或限制購買次數。

需要注意的是:你的應用程式不會自動得知某位已登入的使用者是否付了款。對於捐款頁面,或是依 Stripe 的電子郵件通知手動出貨的小型商店,這樣就夠了。但如果是「付費解鎖 Pro 功能」,這樣就不夠了。

Stripe Checkout

Checkout 是你的伺服器在需要時為特定購買建立的付款頁面。你的伺服器告訴 Stripe 要買什麼(也可以指定是哪位顧客在購買),Stripe 回傳一個網址,你再把顧客導向該網址。Stripe 的文件說明,它同時支援單次付款和訂閱付款,可以是 Stripe 代管的完整頁面、嵌入你網站的頁面,或嵌入式表單。

流程如下:

  1. 顧客在你的應用程式中點擊購買。
  2. 你的伺服器使用你的secret key建立 Checkout 工作階段,並包含可將其連結到你的使用者或訂單的 ID。
  3. 顧客被導向 Stripe 並完成付款。
  4. Stripe 把顧客導回你的成功頁面。
  5. Stripe 向你的 Webhook 發送 checkout.session.completed 事件,伺服器隨後把訂單標為已付款,或解鎖存取權限。

第 2 步必須在伺服器上進行,因為它使用你的 secret key。這也是 Checkout 需要後端的主要原因。

訂閱

訂閱使用 Checkout 的訂閱模式,搭配你在 Stripe 中設定的定期價格。第一次付款的流程與上述相同。之後,續約、信用卡失敗、升級和取消都會隨時間發生,而且通常發生在顧客根本不在你的應用程式中時,因此你的應用程式只能透過 Webhook 得知這些事件。

若要讓顧客自行管理訂閱,Stripe 提供代管的客戶入口網站。根據 Stripe 的文件,顧客可以在那裡更新付款方式和帳單資料、變更或取消訂閱,並檢視和下載發票。你可以在 Stripe 控制台中設定它,並加入「管理帳單」按鈕,將顧客導向該入口網站。這樣你就不必自行建置這些畫面。

Webhook:不能跳過的部分

Webhook 是 Stripe 在某件事發生時,送到你伺服器的 HTTP 請求。(關於這個概念,請參閱什麼是 Webhook。)Stripe 的履約指南說得很明確:不能只依賴成功頁面來完成訂單,因為顧客可能已經付款,卻在成功頁面載入前斷線。對於訂閱和延遲付款方式,Webhook 是必要的。

值得處理的事件

事件含義你的應用程式該做什麼
checkout.session.completedCheckout 已完成把訂單標為已付款,或開始提供存取權限
checkout.session.async_payment_succeeded延遲付款方式(例如銀行扣款)之後才完成立即履約
checkout.session.async_payment_failed該延遲付款失敗通知顧客;不要履約
invoice.paid訂閱付款成功,包括續約延長存取期限
invoice.payment_failed續約失敗警告使用者;Stripe 可能會重試
customer.subscription.updated方案已變更,或已排定取消更新使用者的方案
customer.subscription.deleted訂閱已結束移除付費存取權限

正確的 Webhook 處理器規則

以下規則直接取自 Stripe 的 Webhook 文件,而 AI 產生的處理器有時會漏掉其中一條:

  • **驗證簽章。**每個事件都包含 Stripe-Signature 標頭。你的處理器會使用該端點的簽署密鑰檢查它(開頭為 whsec_)。如果不驗證,任何人都可以偽造「付款成功」的訊息送到你的伺服器。
  • **使用原始請求內容。**如果框架在驗證前解析或修改了內容,簽章檢查就會失敗。
  • 快速回傳 2xx 回應,之後再進行較慢的工作。逾時會被視為失敗。
  • **處理重複事件。**Stripe 可能會把同一個事件送達不止一次。請記錄已處理的事件 ID,或讓履約即使執行兩次也是安全的。
  • **不要假設順序。**Stripe 不保證事件會依照實際發生的順序抵達。
  • **預期會有重試。**在正式模式下,Stripe 會在最多三天內重試失敗的傳送,因此短暫的停機不會遺失付款,但你的處理器必須能應付延遲到達的事件。

Webhook 需要公開的 HTTPS 位址,因此通常只有在應用程式發布後才能運作(Stripe 的 CLI 可以把事件轉送到本機,供開發者使用)。

涵蓋完整流程的提示詞

使用 Stripe Checkout 為「Pro 包」加入單次購買功能(價格 ID 放在 STRIPE_PRICE_ID)。在伺服器上使用 secrets 中的 STRIPE_SECRET_KEY 建立 Checkout 工作階段,並把已登入使用者的 ID 放入工作階段。新增 POST /api/stripe/webhook 端點,使用原始請求內容並以 STRIPE_WEBHOOK_SECRET 驗證 Stripe 簽章,處理 checkout.session.completed,並把該使用者標記為擁有 Pro 包。即使同一個事件送達兩次也要安全。加入成功與取消頁面。絕不要把 secret key 暴露給瀏覽器。

若是訂閱,可加入:「使用 STRIPE_PRICE_ID 的訂閱模式。處理 invoice.paid、invoice.payment_failed、customer.subscription.updated 和 customer.subscription.deleted。加入『管理帳單』按鈕,開啟 Stripe 客戶入口網站。」

測試模式

Stripe 有分開的沙盒(測試)和正式環境,各自使用不同的金鑰。沙盒金鑰以 pk_test_、sk_test_ 或 rk_test_ 開頭;正式金鑰以 pk_live_、sk_live_ 或 rk_live_ 開頭。測試交易不會移動金錢。

以下是 Stripe 測試文件中有用的測試卡(任何未來的到期日,任何三位數的 CVC):

卡號結果
4242 4242 4242 4242付款成功
4000 0000 0000 0002卡片被拒絕
4000 0000 0000 3220需要 3D Secure 驗證,然後成功

至少要測試以下項目:

  • 成功付款後,正確的使用者取得正確的功能
  • 被拒絕的卡片會顯示清楚的訊息,且不會解鎖任何東西
  • 付款後立即關閉瀏覽器分頁,仍然會取得存取權限(這證明 Webhook 有效,而不只是成功頁面)
  • 在 Stripe 頁面上取消後,會返回你的應用程式,且沒有任何扣款
  • 若是訂閱:在客戶入口網站中取消,並確認存取權限在應該結束時結束

正式上線

  1. 啟用你的 Stripe 帳戶,填寫你的公司與銀行資料。
  2. **在應用程式的 secrets 中換成正式金鑰。**Stripe 建議使用受限金鑰,只授予你的整合所需的權限,而不是不受限的 secret key。
  3. 建立正式環境的 Webhook 端點,指向你已發布的應用程式。它有自己的簽署密鑰,與測試用的不同,請記得更新。
  4. 在正式模式中重新建立商品和價格;測試模式的 ID 在正式模式中不存在。
  5. 進行一筆真實的小額購買,並退款。

所有金鑰都應保存在專案的 secrets 中,絕不要放在程式碼或對話中。我們的安全檢查清單更詳細地說明了金鑰與 Webhook 驗證。

稅務、退款與文件

付款會帶來程式碼無法解決的義務。以下內容不構成稅務建議;請諮詢會計師。

  • **銷售稅、增值稅與商品服務稅。**依你和你的顧客所在地,你可能需要登記、收稅並申報。Stripe Tax 可以在結帳時計算並收取稅金,監控你的銷售可能在哪些地方產生義務,並協助登記與申報,但責任仍在你身上。商家代理人服務商是替代方案,會承擔更多這方面的工作。
  • **退款與爭議。**在上線前決定你的退款政策,並把它放在你的網站上。爭議(拒付)會發生;請保留已購買與已交付內容的紀錄。
  • **收據與發票。**Stripe 可以透過電子郵件寄出收據;企業可能需要正式的發票。
  • **手續費。**每家服務商都會依每筆交易收費。請查看服務商目前的定價頁面,而不要依賴文章中的數字。

哪種設定適合你的應用程式

  • **捐款或少數幾項商品:**付款連結。請參閱如何建置非營利機構捐款網站。
  • **有購物車的商店:**使用含品項的 Checkout 加上 Webhook。請參閱如何建置線上商店。
  • **SaaS 或會員制:**訂閱模式的 Checkout、Webhook 與客戶入口網站。請參閱如何建置 SaaS MVP與如何為 SaaS 產品定價。
  • **向賣家付款的市集:**需要不同且更嚴格的設定(Stripe Connect 或類似服務)。請另外規劃。

在 Mythex 加入付款功能

在 Mythex 上建置的應用程式,付款使用的是你自己的 Stripe 帳戶和金鑰;你的應用程式沒有一鍵「連接 Stripe」的功能。一般流程如下:

  1. 取得 Stripe 測試金鑰。
  2. 把 STRIPE_SECRET_KEY(以及稍後的 Webhook 機密)加入專案 secrets,可透過 /secrets、專案設定,或代理人需要金鑰時顯示的 secrets 卡片。
  3. 請代理人依照上面類似的提示詞建立 Checkout。
  4. 在預覽中用測試卡測試。在註冊 Webhook 之前發布,因為它需要你的公開網址。
  5. 切換到正式金鑰後,再次發布,讓正式應用程式套用這些金鑰。

請參閱文件中的使用 Stripe 接受付款和在後端處理 Webhook。

常見問題

在應用程式中收款,最簡單的方法是什麼?

Stripe 付款連結不需要寫程式:你在 Stripe 控制台建立連結,再從應用程式連過去即可。如果你的應用程式需要知道是誰付款,並自動解鎖某些功能,則應改用 Stripe Checkout 加上 Webhook。

收款一定要用 Webhook 嗎?

如果應用程式必須對付款做出反應,例如解鎖帳號、把訂單標為已付款、處理續約,那就需要。Stripe 的文件指出,不能只依賴成功頁面,因為顧客可能已經付款,卻從未抵達該頁面。訂閱也必須使用 Webhook。

如何在不花真錢的情況下測試付款?

使用 Stripe 的沙盒(測試)API 金鑰,以及其測試卡號,例如 4242 4242 4242 4242,搭配任何未來的到期日和任何三位數的 CVC。測試交易不會移動真實的金錢。

Stripe 會替我處理銷售稅和增值稅嗎?

Stripe Tax 可以在結帳時計算並收取稅金,並監控你可能需要在哪些地方辦理登記,但你仍需自行負責你的稅務義務。請就你的情況諮詢會計師。

Mythex · Pricing · 用 AI 打造任何東西 · 網站與應用程式範本 · Mythex 比較 · AI 應用程式開發詞彙表 · 免費的 AI 應用程式開發工具 · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港)