[英]Django and stripe handle successful payment
我正在嘗試使用條紋 webhook 處理成功付款,在我的條紋儀表板中,我看到事件已觸發並且 payment_intent 成功但未創建訂單
視圖.py:
from django.shortcuts import render
from django.http import JsonResponse
from django.http import HttpResponse
import stripe
import json
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.views.decorators.http import require_POST
from article.models import Order
endpoint_secret = '1wwww'
@require_POST
@csrf_exempt
def my_webhook_view(request):
payload = request.body
sig_header = request.META['HTTP_STRIPE_SIGNATURE']
event = None
# Try to validate and create a local instance of the event
try:
event = stripe.Webhook.construct_event(payload, sig_header, endpoint_secret)
except ValueError as e:
# Invalid payload
return HttpResponse(status=400)
except stripe.error.SignatureVerificationError as e:
# Invalid signature
return HttpResponse(status=400)
# Handle the checkout.session.completed event
if event['type'] == 'payment_intent.succeeded':
checkout_session = event['data']['object']
# Make sure is already paid and not delayed
_handle_successful_payment(checkout_session)
# Passed signature verification
return HttpResponse(status=200)
def _handle_successful_payment(checkout_session):
payed_order = Order.objects.create(order_id='test22')
return payed_order
據 Stripe 稱,他們建議監聽事件而不是 webhook,以確保跟蹤付款狀態。
“Stripe 建議處理 payment_intent.succeeded、payment_intent.processing 和 payment_intent.payment_failed 事件。
監聽這些事件而不是等待來自客戶端的回調。 在客戶端,客戶可以在回調執行之前關閉瀏覽器 window 或退出應用程序。 設置集成以偵聽異步事件使您能夠通過單個集成接受不同類型的付款方式。” https://stripe.com/docs/payments/quickstart
我稍微修改了stripe提供的checkout.js。 我的情況是,我禁用了 return_url 並等待成功付款並提交隱藏表單以下訂單。
這是我的解決方法。 如果有人有更好的東西,那將不勝感激。
// This is your test publishable API key.
const stripe = Stripe("YOUR_KEY");
let theSecret;
let elements;
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
const csrftoken = getCookie('csrftoken');
initialize();
// checkStatus();
document
.querySelector("#payment-form")
.addEventListener("submit", handleSubmit);
// Fetches a payment intent and captures the client secret
async function initialize() {
const response = await fetch("/api/create-payment-intent", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"X-CSRFToken": csrftoken
},
body: JSON.stringify({
// These values are passed at the template.
amount: order_amount,
currency: order_currency
}),
});
const {
clientSecret
} = await response.json();
theSecret = clientSecret
const appearance = {
theme: 'stripe',
};
elements = stripe.elements({
appearance,
clientSecret
});
const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");
}
async function handleSubmit(e) {
e.preventDefault();
setLoading(true);
const {
error
} = await stripe.confirmPayment({
elements,
confirmParams: {
// I stopped the redirect.
// Make sure to change this to your payment completion page
return_url: "",
},
redirect: "if_required"
});
// Here I check the status of the event instead of the redirect.
checkStatus();
setLoading(false);
}
// Fetches the payment intent status after payment submission
async function checkStatus() {
const {
paymentIntent
} = await stripe.retrievePaymentIntent(theSecret);
switch (paymentIntent.status) {
case "succeeded":
document.getElementById("place_order_form").submit();
showMessage("Payment succeeded!");
break;
case "processing":
showMessage("Your payment is processing.");
break;
case "requires_payment_method":
showMessage("Your payment was not successful, please try again.");
break;
default:
showMessage("Something went wrong.");
break;
}
}
// ------- UI helpers -------
function showMessage(messageText) {
const messageContainer = document.querySelector("#payment-message");
messageContainer.classList.remove("hidden");
messageContainer.textContent = messageText;
setTimeout(function () {
messageContainer.classList.add("hidden");
messageText.textContent = "";
}, 4000);
}
// Show a spinner on payment submission
function setLoading(isLoading) {
if (isLoading) {
// Disable the button and show a spinner
document.querySelector("#submit").disabled = true;
document.querySelector("#spinner").classList.remove("hidden");
document.querySelector("#button-text").classList.add("hidden");
} else {
document.querySelector("#submit").disabled = false;
document.querySelector("#spinner").classList.add("hidden");
document.querySelector("#button-text").classList.remove("hidden");
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.