在本系列的第一部分中,我們使用 htmx 建立了一個 Django 線上商店。
在第二部分中,我們將使用 Stripe 處理訂單。
我們會做什麼
我們將整合 Stripe 以安全地處理付款。這就是我們想要實現的目標:
- 在購買視圖中,我們首先建立 Stripe 結帳工作階段並將客戶重新導向到對應的 URL。我們在這裡告訴 Stripe 我們正在銷售的產品、數量以及成功購買後客戶應重定向到的位置(success_url)。
- 客戶在 Stripe 結帳頁面填寫付款詳細資料並完成付款。然後,Stripe 向我們網站上的 Webhook 端點發出 POST 請求,我們在其中監聽事件並進行相應的處理。如果付款成功,我們會將訂單保存在資料庫中,並通知客戶(以及我們的員工用戶)有關購買的資訊。
- 最後,如果 webhook 傳回帶有 200 OK HTTP 狀態碼的回應,Stripe 會重新導向到第一步驟中建立的 success_url。
為我們的 Django Python 商店設定 Stripe
我們首先需要跳到 Stripe 並執行以下操作:
- 建立一個 Stripe 帳戶。
- 建立產品(帶有付款 ID)。
- 建立一個 webhook。
1:建立 Stripe 帳戶
先建立一個 Stripe 帳戶。目前,您實際上不需要啟動您的帳戶。您可以只在測試模式下工作,這將阻止您在測試時進行真正的付款。前往 API 金鑰頁面並檢索可發布金鑰和秘密金鑰。將它們保存在專案環境變數中(STRIPE_PUBLISHABLE_KEY 和 STRIPE_SECRET_KEY)。我們將使用這些金鑰來驗證您的 Stripe 請求。
2:創建您的產品
在產品頁面上建立新產品。填寫詳細資料並將付款類型設定為一次性。您的產品應如下所示:
按下新增產品後,您應該能夠在產品清單中看到您的產品。如果您點擊它並向下捲動到定價部分,您可以找到您建立的價格項目的API ID - 它應該類似於price_3ODP5…。將其保存在環境變數 (STRIPE_PRICE_ID) 中:建立 Stripe 結帳會話時將需要它。
3:創建網路鉤子
我們需要建立一個 Webhook 端點,以便 Stripe 在付款完成時呼叫。在webhooks頁面,選擇在本地環境進行測試。這將允許您將請求轉發到本機 URL,例如 http://127.0.0.1:8000。首先下載 Stripe CLI。然後,您可以:
- 登入 Stripe
stripe login
- 將事件轉送到您將要建立的 Webhook 端點:
stripe listen --forward-to http://127.0.0.1:8000/webhook > Ready! Your webhook signing secret is whsec_06531a7ba22363ac038f284ac547906b89e5c939f8d55dfd03a3619f9adc590a (^C to quit)
這可確保一旦進行購買,Stripe 會將 Webhook 呼叫轉發到您的本地端點。該命令將記錄一個 Webhook 簽章金鑰,您也應該將其儲存為專案環境變數 (STRIPE_WEBHOOK_SECRET)。這對於驗證請求確實來自 Stripe 並且您正在處理正確的 Webhook 非常有用。
在本節結束時,您應該有四個 Stripe 環境變數。現在您可以將它們載入到 ecommerce_site/settings.py 中:
# ecommerce_site/settings.py import os from dotenv import load_dotenv load_dotenv() STRIPE_PUBLISHABLE_KEY = os.environ.get("STRIPE_PUBLISHABLE_KEY") STRIPE_SECRET_KEY = os.environ.get("STRIPE_SECRET_KEY") STRIPE_PRICE_ID = os.environ.get("STRIPE_PRICE_ID") STRIPE_WEBHOOK_SECRET = os.environ.get("STRIPE_WEBHOOK_SECRET")
注意:我們使用 python-dotenv 來載入環境變數。
拓展視野
我們現在需要透過建立結帳會話、成功購買視圖和 Webhook 視圖來擴展視圖以整合 Stripe。
1:建立 Stripe 結帳會話
在購買檢視中,如果購買表單有效,我們將建立一個 Stripe 結帳會話:
# ecommerce/views.py from django_htmx import HttpResponseClientRedirect from django.conf import settings import stripe @require_POST def purchase(request): form = OrderForm(request.POST) if form.is_valid(): quantity = form.cleaned_data["quantity"] # replace time.sleep(2) with the following code ⬇️ # 1 - set stripe api key stripe.api_key = settings.STRIPE_SECRET_KEY # 2 - create success url success_url = ( request.build_absolute_uri( reverse("purchase_success") ) + "?session_id={CHECKOUT_SESSION_ID}" ) # 3 - create cancel url cancel_url = request.build_absolute_uri(reverse("home")) # 4 - create checkout session checkout_session = stripe.checkout.Session.create( line_items=[ { "price": settings.STRIPE_PRICE_ID, "quantity": quantity, } ], mode="payment", success_url=success_url, cancel_url=cancel_url ) # 5 - redirect to checkout session url return HttpResponseClientRedirect(checkout_session.url) return render(request, "product.html", {"form": form})
讓我們分解一下:
- We first set the Stripe API key.
- We then create a successful purchase URL pointing to the purchase_success view (which we'll create in the next step). Stripe should automatically populate the CHECKOUT_SESSION_ID.
- We create a URL for when a purchase is canceled — for example, when the customer changes their mind. In this case, it’s just the home view.
- We create a Stripe checkout session with our price ID (the product identifier) and the quantity the customer wants to purchase.
- Stripe returns a session object from which we can extract the URL and redirect the customer. Since this request is coming from htmx, we can’t really use the standard Django redirect function. Instead, we use the django-htmx package, which provides this HttpResponseClientRedirect class.
2: Create the Successful Purchase View
After completing the purchase, Stripe will redirect the customer to our specified success_url. Here, we can handle the post-purchase logic:
from django.shortcuts import redirect def purchase_success(request): session_id = request.GET.get("session_id") if session_id is None: return redirect("home") stripe.api_key = settings.STRIPE_SECRET_KEY try: stripe.checkout.Session.retrieve(session_id) except stripe.error.InvalidRequestError: messages.error(request, "There was a problem while buying your product. Please try again.") return redirect("home") return render(request, "purchase_success.html")
In this view, we first check if the session_id query parameter is present. If it is, we retrieve the corresponding session from Stripe using the secret key and the session_id. We then render the successful purchase template, which looks like this:
# ecommerce/templates/purchase_success.html {% extends "base.html" %} {% block content %} <section> <header> <h2 id="Thank-you-for-your-purchase">Thank you for your purchase</h2> <p> Your purchase was successful. You will receive an email with the details of your purchase soon. </p> </header> </section> {% endblock %}
You should also add it to the urlpatterns:
# ecommerce_site/urls.py # ... same imports as before urlpatterns = [ # ... same urls as before path("purchase_success", views.purchase_success, name="purchase_success"), # ⬅️ new ]
3: Create the Webhook View
While the customer is in the purchase process, and before they are redirected to the success view, Stripe will call our webhook endpoint (remember to have the webhook listener running, as explained in the earlier 'Create the Webhook' section of this post):
from django.views.decorators.csrf import csrf_exempt from django.http import HttpResponse @csrf_exempt def webhook(request): stripe.api_key = settings.STRIPE_SECRET_KEY sig_header = request.headers.get('stripe-signature') payload = request.body event = None try: event = stripe.Webhook.construct_event( payload, sig_header, settings.STRIPE_WEBHOOK_SECRET ) except stripe.error.SignatureVerificationError: # Invalid signature return HttpResponse(status=400) # Handle the checkout.session.completed event if event.type == "checkout.session.completed": # TODO: create line orders return HttpResponse(status=200) return HttpResponse(status=400)
Let’s break this down:
- We try to construct a Stripe event from the payload, the signature header, and the webhook secret: the first is used to build the actual event, and the last two variables are relevant to validate the authenticity of the request.
- If the signature verification fails, we return a 400 HTTP response. Remember that Stripe is actually calling this endpoint, not our customer, so Stripe will know what to do in this scenario.
- We check if the event type is checkout.session.completed, i.e., if a customer successfully paid for our product. For now, we don’t do much else here, but we will process the order in the next step.
Note: A Stripe event can have multiple types but we will only handle completed sessions in this post. However, you can (and should) extend a webhook by following the docs.
You should also add this view to urlpatterns:
# ecommerce_site/urls.py # ... same imports as before urlpatterns = [ # ... same urls as before path("webhook", views.webhook, name="webhook"), # ⬅️ new ]
If everything works well, once you click “buy”, you should be redirected to a Stripe payment page. Since we are in test mode, we can fill in the payment details with dummy data, like a 4242 4242 4242 4242 card:
Once you press Pay, Stripe should call the webhook view and redirect you to the purchase_success view. Congratulations, you have successfully processed a payment with Stripe!
Create the Orders and Notify Users
Once a purchase is completed, we need to do a few things in the webhook view:
- Save the order information in our database.
- Notify staff users about the recent purchase.
- Send a confirmation email to the customer.
Let’s create a LineOrder database model in ecommerce/models.py to store some of the order information:
# ecommerce/models.py from django.db import models class LineOrder(models.Model): quantity = models.IntegerField() name = models.CharField(max_length=255, null=True, blank=True) email = models.EmailField(null=True, blank=True) shipping_details = models.TextField(null=True, blank=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"Order {self.id} - {self.quantity} units"
Remember to create and run the migrations:
python manage.py makemigrations # ⬅️ creates the migration files python manage.py migrate # ⬅️ applies the migrations in the database
We can now create a function to process the orders and call it from the webhook view:
# ecommerce/views.py @csrf_exempt def webhook(request): # ...same code as before if event.type == "checkout.session.completed": create_line_orders(event.data.object) # ⬅️ new return HttpResponse(status=200) return HttpResponse(status=400) # new ⬇️ def create_line_orders(session: stripe.checkout.Session): line_items = stripe.checkout.Session.list_line_items(session.id) for line_item in line_items.data: LineOrder.objects.create( name=session.customer_details.name, email=session.customer_details.email, shipping_details=session.shipping_details, quantity=line_item.quantity, ) mail.send_mail( "Your order has been placed", f""" Hi {session.customer_details.name}, Your order has been placed. Thank you for shopping with us! You will receive an email with tracking information shortly. Best, The one product e-commerce Team """, "from@example.com", [session.customer_details.email], ) staff_users = User.objects.filter(is_staff=True) mail.send_mail( "You have a new order!", """ Hi team! You have a new order in your shop! go to the admin page to see it. Best, The one product e-commerce Team """, "from@example.com", [user.email for user in staff_users], )
Let’s break this down:
- We first create line order instances from the Stripe session and send a confirmation email to the customer about their purchase.
- We then send an email to all staff users telling them to check the admin panel.
You can now register the LineOrder model in the admin panel, so it’s accessible to staff users:
# ecommerce/admin.py from django.contrib import admin from ecommerce.models import LineOrder # Register your models here. admin.site.register(LineOrder)
When staff users log in to the admin page, they will now be able to check new orders and process them accordingly — in this case, pack and ship mugs to the customer!
Some Tips to Optimize Your Django Store
Here are some tips to further improve on the store you've built:
- 編寫測試 - 您可以在 GitHub 儲存庫中查看一些範例。
- 如果您有更多產品要銷售,請為它們建立資料庫模型,並透過ForeignKey連接LineOrder。
- 根據 Django 的電子郵件文件配置電子郵件設定。您也可以使用 django-post-office 等函式庫來管理您的電子郵件範本和佇列。
- 部署網站後,建立一個實際的 Webhook(不是本機偵聽器)。
- 查看 Stripe 文檔,以了解我們概述的結帳流程的替代方案,包括嵌入式結帳表單。
總結
在這個由兩部分組成的系列中,我們使用 Django、htmx 和 Stripe 成功建立了一個單一產品的電子商務網站。本指南引導您完成 Django 專案的設定、整合 htmx 以實現無縫用戶交互,以及將安全支付與 Stripe 結合。
我們也介紹如何處理訂單處理,包括將訂單資訊儲存到您的資料庫、通知員工使用者新購買的商品以及向您的客戶發送確認電子郵件。有了這些基礎,您可以進一步客製化和擴展您的電子商務網站以滿足您的特定需求。
編碼愉快!
P.S.如果您想在 Python 文章發布後立即閱讀,請訂閱我們的 Python Wizardry 時事通訊,不錯過任何一篇文章!
以上是將 Stripe 整合到單一產品 Django Python 商店中的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Tomergelistsinpython,YouCanusethe操作員,estextMethod,ListComprehension,Oritertools

在Python3中,可以通過多種方法連接兩個列表:1)使用 運算符,適用於小列表,但對大列表效率低;2)使用extend方法,適用於大列表,內存效率高,但會修改原列表;3)使用*運算符,適用於合併多個列表,不修改原列表;4)使用itertools.chain,適用於大數據集,內存效率高。

使用join()方法是Python中從列表連接字符串最有效的方法。 1)使用join()方法高效且易讀。 2)循環使用 運算符對大列表效率低。 3)列表推導式與join()結合適用於需要轉換的場景。 4)reduce()方法適用於其他類型歸約,但對字符串連接效率低。完整句子結束。

pythonexecutionistheprocessoftransformingpypythoncodeintoExecutablestructions.1)InternterPreterReadSthecode,ConvertingTingitIntObyTecode,whepythonvirtualmachine(pvm)theglobalinterpreterpreterpreterpreterlock(gil)the thepythonvirtualmachine(pvm)

Python的關鍵特性包括:1.語法簡潔易懂,適合初學者;2.動態類型系統,提高開發速度;3.豐富的標準庫,支持多種任務;4.強大的社區和生態系統,提供廣泛支持;5.解釋性,適合腳本和快速原型開發;6.多範式支持,適用於各種編程風格。

Python是解釋型語言,但也包含編譯過程。 1)Python代碼先編譯成字節碼。 2)字節碼由Python虛擬機解釋執行。 3)這種混合機制使Python既靈活又高效,但執行速度不如完全編譯型語言。

UseeAforloopWheniteratingOveraseQuenceOrforAspecificnumberoftimes; useAwhiLeLoopWhenconTinuingUntilAcIntiment.forloopsareIdealForkNownsences,而WhileLeleLeleLeleLeleLoopSituationSituationsItuationsItuationSuationSituationswithUndEtermentersitations。

pythonloopscanleadtoerrorslikeinfiniteloops,modifyingListsDuringteritation,逐個偏置,零indexingissues,andnestedloopineflinefficiencies


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

禪工作室 13.0.1
強大的PHP整合開發環境

SublimeText3 Linux新版
SublimeText3 Linux最新版

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中