Checkout 託管頁
Checkout Session 是現在最推薦的寫法:你的網站只負責「這一筆要賣什麼、收多少錢」,付款畫面由 Stripe 託管(或嵌入你的頁面)。顧客卡號不會碰到你的伺服器。
官方文件:Build a Stripe-hosted checkout page。對應影片見 官方影音。
流程
- 顧客在你的網站按「購買」。
- Flask 用 Secret key 建立
checkout.Session,帶入 line items、成功與取消網址。 - 回應 303,把瀏覽器導向
session.url。 - 顧客在 Stripe 頁面付款。
- Stripe 呼叫你的 webhook,同時可能把人導回
success_url。
Flask 完整範例
import os
import stripe
from flask import Flask, redirect, request, render_template_string
app = Flask(__name__)
stripe.api_key = os.environ["STRIPE_SECRET_KEY"]
DOMAIN = os.environ.get("DOMAIN", "http://localhost:4242")
INDEX = """
<form action="/create-checkout-session" method="POST">
<button type="submit">購買電子書 NT$350</button>
</form>
"""
@app.get("/")
def index():
return render_template_string(INDEX)
@app.post("/create-checkout-session")
def create_checkout_session():
session = stripe.checkout.Session.create(
mode="payment",
line_items=[{
"price_data": {
"currency": "twd",
"product_data": {"name": "電子書"},
"unit_amount": 350,
},
"quantity": 1,
}],
success_url=DOMAIN + "/success?session_id={CHECKOUT_SESSION_ID}",
cancel_url=DOMAIN + "/cancel",
metadata={"sku": "ebook-001"}, # 之後 webhook 用來對訂單
)
return redirect(session.url, code=303)
@app.get("/success")
def success():
return "付款流程已完成。出貨請等 webhook。"
@app.get("/cancel")
def cancel():
return "已取消。"
{CHECKOUT_SESSION_ID} 是 Stripe 會替換的佔位字串,成功頁可用它向 API 再查一次 Session,僅供顯示。出貨仍以 webhook 為準。
參數在做什麼
| 參數 | 意義 |
|---|---|
mode="payment" |
一次付清。訂閱改 "subscription" |
line_items |
品名、單價、數量。價格來自伺服器 |
success_url / cancel_url |
付完或按返回後的網址 |
metadata |
你自己的訂單編號,webhook 會原樣帶回 |
customer_email |
可預填 email,非必填 |
固定商品更建議在 Dashboard 建好 Product / Price,程式只傳 price="price_xxx",避免售價散落在程式各處。
嵌入自己的網站
不想把人帶走,可改 ui_mode 為嵌入式 Checkout,伺服器改回 client_secret,前端用 Stripe.js mount。觀念與 PaymentIntent 類似,但商品列、稅、折扣仍走 Checkout Session API。見 Embedded Checkout。
下一步
沒有 webhook,這支程式只能「看起來付完了」。請接 Webhook 履約。