Completely losing my mind with this...
I am creating a ecommerce website with django. I use Stripe as Payment Gateway Provider. I don't understand ...Stripe 'card-element' is not displaying. Why ?
For information, the card-element used to be displayed correclty in the previous days. I could simulate payments which were recorded in my Stripe account... The thing is, I have checked with older versions of my code which used to work (in case I did a mistake since). But none of them is working... It's driving me crazy.
Anything wrong with my code ? Any idea ?
checkout.html
{% extends 'main.html' %}
{% load static %}
{% block content %}
<script src="https://js.stripe.com/v3/"></script>
<div class="container">
<div class="row">
<div class="col d-flex justify-content-center align-items-center">
<h3 class="text-primary fw-bold">PAIEMENT PAR CARTE</h3>
</div>
</div>
<div class="row ">
<div class="col d-flex justify-content-center align-items-center">
<form id="payment-form" method='POST' class="col">
{% csrf_token %}
<div class="form-control" id="card-element"></div>
<div class="sr-field-error" id="card-errors" role="alert"></div>
<button id="payer-submit" class="btn btn-primary">
<div class="spinner-border spinner-border-sm text-light d-none" id="spinner" role="status"></div>
<span class="text-white" id="button-text">Pay</span>
<span class="text-white" id="order-amount"></span>
</button>
</form>
</div>
</div>
<div class="row ">
<div class="col d-flex justify-content-center align-items-center">
<form id="payload" method='POST' class="col" action="/payment/payment-bycard-complete">
{% csrf_token %}
<input id ="data-payload" type="hidden" name="payload"/>
</form>
</div>
</div>
</div>
<script type="text/javascript" src="{% static '/js/stripe.js' %}"></script>
{% endblock content %}
stripe.js
document.getElementById("payer-submit").disabled = true;
fetch("/payment/bycard", {
method: "POST",
headers: {
"Content-Type": "application/json",
}
})
.then(function(result) {
return result.json();
})
.then(function(data) {
return setupElements(data);
})
.then(function({ stripe, card, clientSecret }) {
document.getElementById("payer-submit").disabled = false;
// Handle form submission.
var form = document.getElementById("payment-form");
form.addEventListener("submit", function(event) {
event.preventDefault();
// Initiate payment when the submit button is clicked
pay(stripe, card, clientSecret);
});
});
// Set up Stripe.js and Elements to use in checkout form
var setupElements = function(data) {
stripe = Stripe(data.publishableKey);
var elements = stripe.elements();
var style = {
base: {
color: "#32325d",
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: "antialiased",
fontSize: "16px",
"::placeholder": {
color: "#aab7c4"
}
},
invalid: {
color: "#fa755a",
iconColor: "#fa755a"
}
};
var card = elements.create("card", { style: style });
card.mount("#card-element");
return {
stripe: stripe,
card: card,
clientSecret: data.clientSecret
};
};
/*
* Calls stripe.confirmCardPayment which creates a pop-up modal to
* prompt the user to enter extra authentication details without leaving your page
*/
var pay = function(stripe, card, clientSecret) {
changeLoadingState(true);
// Initiate the payment.
// If authentication is required, confirmCardPayment will automatically display a modal
stripe
.confirmCardPayment(clientSecret, {
payment_method: {
card: card
}
})
.then(function(result) {
if (result.error) {
// Show error to your customer
showError(result.error.message);
} else {
// The payment has been processed!
orderComplete(clientSecret);
}
});
};
/* ------- Post-payment helpers ------- */
/* Shows a success / error message when the payment is complete */
var orderComplete = function(clientSecret) {
//// Just for the purpose of the sample, show the PaymentIntent response object
stripe.retrievePaymentIntent(clientSecret).then(function(result) {
// var paymentIntent = result.paymentIntent;
// var paymentIntentJson = JSON.stringify(paymentIntent, null, 2);
// post data and show new page
// var input = document.getElementById("data-payload");
// input.value = paymentIntentJson;
var form2 =document.getElementById("payload");
form2.submit();
changeLoadingState(false);
});
};
var showError = function(errorMsgText) {
changeLoadingState(false);
var errorMsg = document.querySelector(".sr-field-error");
errorMsg.textContent = errorMsgText;
setTimeout(function() {
errorMsg.textContent = "";
}, 4000);
};
// Show a spinner on payment submission
var changeLoadingState = function(isLoading) {
if (isLoading) {
document.getElementById("payer-submit").disabled = true;
document.querySelector("#spinner").classList.remove("d-none");
document.querySelector("#button-text").classList.add("d-none");
} else {
document.getElementById("payer-submit").disabled = false;
document.querySelector("#spinner").classList.add("d-none");
document.querySelector("#button-text").classList.remove("d-none");
}
};
views.py
import stripe
from django.shortcuts import render, redirect
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
from django.contrib import messages
from core.settings import STRIPE_SECRET_KEY, STRIPE_PUBLISHABLE_KEY
from core.utils import display_price_in_euro_string
from basket.basket import Basket
from payment.checkout import calculate_order
from payment.save_order import create_invoice_xls, save_order_in_db, save_ordered_items_in_db, save_stripe_payment_in_db
from payment.send_mail import send_order_confirmation
def checkout(request):
if not request.session.get('cart', None):
return redirect('store:all_products')
elif not request.session.get('shipping-form', None):
return redirect('address:create_shipping_address')
else:
calculate_order(request)
context = {
'shipping_fees_in_euros': display_price_in_euro_string(request.session['order']['shipping_fees_in_cent']),
'cart_price_with_discount_in_euros': display_price_in_euro_string(request.session['order']['cart_price_in_cent_with_discount']),
'cart_price_without_discount_in_euros': display_price_in_euro_string(request.session['order']['cart_price_in_cent_without_discount']),
'order_total_in_euros': display_price_in_euro_string(request.session['order']['order_total_in_cent']),
'cart_discount_in_euros': display_price_in_euro_string(request.session['order']['cart_discount_in_cent']),
}
return render(request, 'payment/checkout.html', context)
#csrf_exempt
def create_stripe_payment_intent(request):
try:
total_to_pay = request.session['order']['order_total_in_cent']
stripe.api_key = STRIPE_SECRET_KEY
if request.method == "POST":
# Create a PaymentIntent with the order amount and currency
# https://stripe.com/docs/api/payment_intents/create
intent = stripe.PaymentIntent.create(
amount = total_to_pay,
currency = "eur",
metadata = {
"Adresse de livraison": request.session['shipping-form']['id'],
"Adresse de facturation": request.session['billing-form']['id'],
"Montant commande TTC (centimes)": request.session['order']['order_total_in_cent'],
"Panier avant réduction TTC (centimes)": request.session['order']['cart_price_in_cent_without_discount'],
"Panier après réduction TTC (centimes)": request.session['order']['cart_price_in_cent_with_discount'],
"Frais de livraison TTC (centimes)": request.session['order']['shipping_fees_in_cent'],
"TVA (centimes)": request.session['order']['tva_in_cent'],
"Montant commande HT (centimes)": request.session['order']['order_total_in_cent_HT'],
"SESSION KEY": request.session.session_key,
"PANIER": str(request.session['cart']),
},
receipt_email = 'monoi#laposte.net',
)
request.session['order']['stripe-intent'] = {}
request.session['order']['stripe-intent']['client-secret'] = intent.client_secret
request.session['order']['stripe-intent']['id'] = intent.id
request.session.modified = True
try:
return JsonResponse({
'publishableKey': STRIPE_PUBLISHABLE_KEY,
'clientSecret': intent.client_secret
})
except Exception as e:
return JsonResponse({'error': str(e)}, status = 403)
else:
return redirect('payment:checkout')
except:
return redirect('payment:checkout')
def payment_bycard_complete(request):
stripe.api_key = STRIPE_SECRET_KEY
payment_intent = stripe.PaymentIntent.retrieve(
request.session['order']['stripe-intent']['id'],
)
if payment_intent.status == "succeeded":
save_order_in_db(request, "STRIPE")
save_ordered_items_in_db(request)
save_stripe_payment_in_db(request)
is_invoice = create_invoice_xls(request)
is_mail = send_order_confirmation(request)
basket = Basket(request)
basket.clear()
request.session.flush()
messages.success(request, 'Merci pour votre achat')
return redirect('home_page:home')
else:
return redirect('home_page:error')
Versions :
Django 3.1.6
stripe 2.60.0
EDIT
Console
Promise { <state>: "pending" }
<state>: "fulfilled"
<value>: Object { publishableKey: "pk_test_51Ia5dlE8XikcpErQEGGuA56itbGvPLmnZSNALSKvVGK2syFR21CvPoYMCJtOjb2DArvAKT1hd1z2KSS4wZmpDqre00ZppDWLLl", clientSecret: "pi_3JPkJfE8XikcpErQ0NuBgyfq_secret_C94xiK71RDMFaZImXYc12c1rn" }
Uncaught (in promise) TypeError: Response.json: Body has already been consumed.
<anonymous> http://127.0.0.1:8000/static/js/stripe.js:16
promise callback* http://127.0.0.1:8000/static/js/stripe.js:13
stripe.js:16:21
According to debugger :
In
.then(function(result) {
return result.json();
})
return result.json() bugs
EDIT 2
I had console.log(result.json()) before return result.json(), which I think is not allowed with fetch. I have removed this console.log(result.json()).
There is still something I don't understand ... My code works well in Chrome (I am able to fill credit card number etc.) but not with Firefox. Any ideas ?
I had console.log(result.json()) before return result.json(), which is not allowed with fetch. I have removed this console.log(result.json()) and it works now.
Related
I got problem with 'live' like unlike button in Django and JavaScript DOM
after button is clicked I got an error
POST http://127.0.0.1:8000/like/24 404 (Not Found)
likePost # javascripts.js:24
(anonymous) # javascripts.js:40
javascripts.js:7
I don't know if the problem is in the 'await fetch' function or maybe I used the wrong class or id somewhere.
Where to start?
javascript.js
const reloadPostHTML = async (postId) => {
const homePageResponse = await fetch(window.location.href);
const newHTML = await homePageResponse.text();
const newDocument = new DOMParser().parseFromString(newHTML, "text/html");
console.log(newDocument)
const newPostElem = newDocument
.querySelector(`[data-post-id='${postId}']`)
.closest(".post");
const oldPostElem = document
.querySelector(`[data-post-id='${postId}']`)
.closest(".post");
oldPostElem.innerHTML = newPostElem.innerHTML;
makeLikeButton(oldPostElem.querySelector(".like-button-wrapper"));
};
const likePost = async (postId, csrfToken) => {
await fetch(`/like/${postId}`, {
method: 'POST',
credentials: 'include',
headers: {
"X-CSRFToken": csrfToken
}
});
reloadPostHTML(postId);
};
const makeLikeButton = (elem) => {
elem.querySelector('button').addEventListener("click", (event) => {
event.preventDefault();
const postId = elem.dataset.postId;
const csrfToken = elem.dataset.csrfToken;
likePost(postId, csrfToken);
});
};
const makeLikeButtons = () => {
for (let elem of document.getElementsByClassName("like-button-wrapper")) {
makeLikeButton(elem);
}
};
makeLikeButtons();
urls.py
path(
'article_detail/<int:pk>/',
login_required(
ArticleDetail.as_view(template_name = "web/article_detail_view.html")
),
name='article_detail'
),
path('like/<int:pk>', views.like, name='like'),
In the views should I also use "if request.method == "POST":" ?
views.py
def like(request, pk):
article = get_object_or_404(Article, id=request.POST.get("article_id"))
if article.likes.filter(id=request.user.id).exists():
article.likes.remove(request.user)
liked = False
else:
article.likes.add(request.user)
liked = True
return HttpResponseRedirect(reverse("article_detail", args=[int(pk)]))
and detail_view.py
class .post is in thats why i used .closest(".post") in javascript.js
<div class="card post"> ........
<div class="like-button-wrapper"
data-post-id='{{ article.pk }}'
data-csrf-token='{{ csrf_token }}'>
{% if liked %}
<button class="btn btn-danger position-relative" type="submit" id="like" name="article_id"
value="{{article.id}}">
<i class="bi bi-hand-thumbs-down">
</i>
</button>
{% else %}
<button class="btn btn-primary position-relative" type="submit" id="like" name="article_id"
value="{{article.id}}">
<i class="bi bi-hand-thumbs-up">
</i>
<span
class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
{{ likes }}
</span>
</button>
{% endif %}
</div>
Ok I got it it was a error 404 came from views.py get_or_404
Now I just rebuild the like function in views and its working as should
def like(request, pk):
if request.method == "POST":
#article = get_object_or_404(Article, id=request.POST.get("article_id"))
article = Article.objects.get(id=pk)
if article.likes.filter(id=request.user.id).exists():
article.likes.remove(request.user)
liked = False
else:
article.likes.add(request.user)
liked = True
return HttpResponseRedirect(reverse("article_detail", args=[int(pk)]))
I have a simple django search functionality using js/ajax. I want to add functionality so that when the queryset is greater than 5 a 'Show all' href will appear in the search results and it will redirect to a page with all the queryset.
This is for the case when a queryset returns a large number of results, rather than have them in one big box.
I thought I could just add a dictionary to my queryset, e.g. data.append({'pk': <add number to querset>, 'name': 'Show all results'}) but then I think this will mess around with the js logic with the forEach loop.
I'd want each search result up to 5 to link to the detail view, but then the last one should link to a completely different view.
I'm not sure what the best option is here.
My search in views.py:
def search_results(request):
"""
Handles search logic
"""
if request.is_ajax():
res = None
quote = request.POST.get('quote')
qs = Quote.objects.filter(name__icontains=quote)
if len(qs) > 0 and len(quote) > 0:
data = []
for pos in qs:
item = {
'pk': pos.pk,
'name': pos.name,
'image': str(pos.image.url)
}
data.append(item)
res = data
else:
res = 'No quotes found...'
return JsonResponse({'data': res})
return JsonResponse({})
and main.js that handles loading the search results:
const url = window.location.href
const searchForm = document.getElementById('search-form')
const searchInput = document.getElementById('search-input')
const resultsBox = document.getElementById('results-box')
const csrf = document.getElementsByName('csrfmiddlewaretoken')[0].value
const sendSearchData = (quote) => {
$.ajax({
type: 'POST',
url: 'search/',
data: {
'csrfmiddlewaretoken': csrf,
'quote': quote,
},
success: (res)=> {
console.log(res.data)
const data = res.data
let length = data.length
console.log(length)
if (Array.isArray(data)) {
resultsBox.innerHTML = ""
data.forEach(quote=> {
resultsBox.innerHTML += `
<a href="${url}${quote.pk}" class="item">
<div class="row mt-2 mb-2">
<div class="col-2">
<img src="${quote.image}" class="quote-img">
</div>
<div class="col-10">
<h5>${quote.name}</h5>
<p class="text-muted">${quote.seller}</p>
</div>
</div>
</a>
`
})
} else {
if (searchInput.value.length > 0) {
resultsBox.innerHTML = `<b>${data}</b>`
} else {
resultsBox.classList.add('not-visible')
}
}
error: (err)=> {
console.log(err)
}
}
})
}
searchInput.addEventListener('keyup', e=>{
console.log(e.target.value)
if (resultsBox.classList.contains('not-visible')){
resultsBox.classList.remove('not-visible')
}
sendSearchData(e.target.value)
})
I’m a beginner. I have tried everything in the Django E-commerce website course, but it does not work for me. I also tried documentation but I didn’t get any solution. I have this error when I go to /update_item/ and the data is not showing up in the terminal:
Expecting value: line 1 column 1 (char 0)
error screenshot
tutorial link
tutorial link
https://youtu.be/woORrr3QNh8
cart.js
var updateBtns = document.getElementsByClassName('update-cart')
for (i = 0; i < updateBtns.length; i++) {
updateBtns[i].addEventListener('click', function(){
var productId = this.dataset.product
var action = this.dataset.action
console.log('productId:', productId, 'Action:', action)
console.log('USER:', user)
})
}
function updateUserOrder(productId, action){
console.log('User is authenticated, sending data...')
var url = '/update_item/'
fetch(url, {
method:'POST',
headers:{
'Content-Type':'application/json',
'X-CSRFToken':csrftoken,
},
body:JSON.stringify({'productId':productId, 'action':action})
})
.then((response) => {
return response.json();
})
.then((data) => {
location.reload()
});
}
views.py
def updateItem(request):
data = json.loads(request.body)
productId = data['productId']
action = data['action']
print("Action",action)
print("Pordutcs:",productId)
customer = request.user.customer
product = Product.objects.get(id=productId)
order, created = Order.objects.get_or_create(customer=customer , complete=False)
orderitem, created = Orderitem.objects.get_or_create(order= order,product=product)
if action == 'add':
orderitem.quantity = (orderitem.quantitiy +1)
elif action == 'remove':
orderitem.quantity = (orderitem.quantity -1)
orderitem.save()
if orderitem.quantity <= 0:
orderitem.delete()
return JsonResponse("Item was added", safe=False)
store.html
{% extends 'store/main.html' %}
{% load static %}
{% block content %}
<div class="row">
{%for i in products %}
<!-- {{i.image.url}} -->
<div class="col-lg-4">
<!-- <img class="thumbnail" src="{{i.image.url}}" alt="sorry"> -->
<img class="thumbnail" src="static{{i.imageURL}}">
<!-- {% static 'my_app/example.jpg' %} -->
<div class="box-element product">
<h6><strong>{{i.name}}</strong></h6>
<hr>
<button data-product="{{i.id}}" data-action='add' class="btn btn-outline-secondary add-btn updatecart">Add
to Cart</button>
<a class="btn btn-outline-success" href="#">View</a>
<h4 style="display: inline-block; float:right"><strong>Rs {{i.price|floatformat:2}}</strong></h4>
</div>
</div>
{% endfor %}
<!-- <img src="static/images/robot.jpg"> -->
</div>
{% endblock content %}
I tried making a dummy django project with the code you provided to see if I counter such error.
Following JS code I used:
function updateUserOrder(){
console.log('User is authenticated, sending data...')
var url = '/update_item/'
fetch(url, {
method:'POST',
headers:{
'Content-Type':'application/json',
},
body:JSON.stringify({'productId':5, 'action':'Add'})
})
.then((response) => {
return response.json();
})
.then((data) => {
location.reload()
});
}
I gave dummy data to productId and action.
Then my views.py goes like this:
from django.shortcuts import render
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def updateItem(request):
data = json.loads(request.body)
productId = data['productId']
action = data['action']
print("Action",action)
print("Pordutcs:",productId)
return JsonResponse("Item was added", safe=False)
Not much with html part, it was just a click button to call the js code.
<button onclick="updateUserOrder()">Add</button>
And worked like a charm, following is the screenshot of my output in django server:
I would suggest you to try running with the same code.
If error is still there, try giving dummy data to productId and action in js code to make sure if there is a problem with the data in productId and action.
I assume you've solved this issue otherwise,...
if you're using Django version 4.0
change the url for the cart.js to update_item, cart.js should look like this
cart.js:
var updateBtns = document.getElementsByClassName('update-cart')
for (i = 0; i < updateBtns.length; i++) {
updateBtns[i].addEventListener('click', function(){
var productId = this.dataset.product
var action = this.dataset.action
console.log('productId:', productId, 'Action:', action)
console.log('USER:', user)
})
}
function updateUserOrder(productId, action){
console.log('User is authenticated, sending data...')
var url = 'update_item/'
fetch(url, {
method:'POST',
headers:{
'Content-Type':'application/json',
'X-CSRFToken':csrftoken,
},
body:JSON.stringify({'productId':productId, 'action':action})
})
.then((response) => {
return response.json();
})
.then((data) => {
location.reload()
});
}
then import csrf_exempt decorator , your views should look like this
views.py(after adding "from django.views.decorators.csrf import csrf_exempt" to the top of your file)
#csrf_exempt
def updateItem(request):
data = json.loads(request.body)
productId = data['productId']
action = data['action']
print("Action",action)
print("Pordutcs:",productId)
customer = request.user.customer
product = Product.objects.get(id=productId)
order, created = Order.objects.get_or_create(customer=customer , complete=False)
orderitem, created = Orderitem.objects.get_or_create(order= order,product=product)
if action == 'add':
orderitem.quantity = (orderitem.quantitiy +1)
elif action == 'remove':
orderitem.quantity = (orderitem.quantity -1)
orderitem.save()
if orderitem.quantity <= 0:
orderitem.delete()
return JsonResponse("Item was added", safe=False)
Then Clear Your Cache and try adding the item to cart again...it should work this time
I am struggling for a long period of time to implement Stripe in my Laravel app, but I've encountered a lot of problems. I did somehow implemented the logic but I cannot or I don't know how I can send the current order total to create the paymentIntent, all of the payments are stored with a default amount of 500, set up in the Controller. I have to mention that after the success response from stripe, the current order should be stored in the database with user shipping details which are found in the first form and all the products ordered, stored in session. Let me show you for a better understanding.
This is the view (revieworder.blade.php) where I have a 2 forms, one with the user's shipping details, and the Stripe payment form, and a list of cart products from the session:
<ul class="list-group mb-3">
<?php $total = 0 ?>
#if(session('cart'))
#foreach(session('cart') as $id => $details)
<?php $total += $details['price'] * $details['quantity'] ?>
<li class="list-group-item d-flex justify-content-between lh-condensed">
<img src="../img/{{ $details['image'] }}" alt="{{ $details['name'] }}" width="60" height="60">
<div>
<h6 class="my-0">{{ $details['name'] }}</h6>
<small class="text-muted">{{ __('Quantity') }}: {{ $details['quantity'] }}</small><br>
<small class="text-muted">{{ __('Unit price') }}: {{ $details['price'] }} RON</small>
</div>
<span class="text-muted">{{ $details['price'] * $details['quantity'] }} RON</span>
</li>
#endforeach
#endif
<li class="list-group-item d-flex justify-content-between">
<span>Total (RON)</span>
<strong id="total">{{ $total.' RON' }}</strong>
</li>
</ul>
<form id="payment-form">
#csrf
<div id="card-element"><!--Stripe.js injects the Card Element--></div>
<button id="submit" class="submit-id">
<div class="spinner hidden" id="spinner"></div>
<span id="button-text">Pay now</span>
</button>
<p id="card-error" role="alert"></p>
<p class="result-message hidden">
</p>
</form>
<script>
//Stripe script
var stripe = Stripe("pk_test_XXX");
// The items the customer wants to buy
var purchase = {
items: [{id: "prod"}] //sessions cart
};
console.log(purchase);
var elements = stripe.elements();
var style = {
base: { //some styling },
invalid: {
fontFamily: 'Arial, sans-serif',
color: "#fa755a"
}
};
var card = elements.create("card", { style: style });
// Stripe injects an iframe into the DOM
card.mount("#card-element");
card.on("change", function (event) {
// Disable the Pay button if there are no card details in the Element
document.querySelector("button").disabled = event.empty;
document.querySelector("#card-error").textContent = event.error ? event.error.message : "";
});
// Disable the button until we have Stripe set up on the page
document.getElementsByClassName("submit-id").disabled = true;
$('#payment-form').submit(function(){
fetch("{{ url(app()->getLocale().'/revieworder') }}", {
method: "POST",
headers: {
"Content-Type": "application/json",
'X-CSRF-TOKEN': "{{ csrf_token() }}"
},
body: JSON.stringify(purchase)
})
.then(function(data) {
$('#payment-form').submit(function(event) {
event.preventDefault();
// Complete payment when the submit button is clicked
payWithCard(stripe, card, data.clientSecret);
});
});
// Calls stripe.confirmCardPayment
var payWithCard = function(stripe, card, clientSecret) {
loading(true);
stripe
.confirmCardPayment(clientSecret, {
payment_method: {
card: card
}
})
.then(function(result) {
if (result.error) {
// Show error to your customer
showError(result.error.message);
} else {
// The payment succeeded!
// The order should be stored in the database
orderComplete(result.paymentIntent.id);
}
});
};
// Shows a success message when the payment is complete
var orderComplete = function(paymentIntentId) {
loading(false);
document
.querySelector(".result-message a")
.setAttribute(
"href",
"https://dashboard.stripe.com/test/payments/" + paymentIntentId
);
document.querySelector(".result-message").classList.remove("hidden");
document.getElementsByClassName("submit-id").disabled = true;
};
// Show the customer the error from Stripe if their card fails to charge
var showError = function(errorMsgText) {
loading(false);
var errorMsg = document.querySelector("#card-error");
errorMsg.textContent = errorMsgText;
setTimeout(function() {
errorMsg.textContent = "";
}, 4000);
};
// Show a spinner on payment submission
var loading = function(isLoading) {
if (isLoading) {
// Disable the button and show a spinner
document.getElementsByClassName("submit-id").disabled = true;
document.querySelector("#spinner").classList.remove("hidden");
document.querySelector("#button-text").classList.add("hidden");
} else {
document.getElementsByClassName("submit-id").disabled = false;
document.querySelector("#spinner").classList.add("hidden");
document.querySelector("#button-text").classList.remove("hidden");
}
};
});
</script>
And then this is the controller which handles the secret client key and the paymentIntent (CheckoutController.php):
public function create(){
\Stripe\Stripe::setApiKey('sk_test_XXX');
header('Content-Type: application/json');
try {
$json_str = file_get_contents('php://input');
$json_obj = json_decode($json_str);
$paymentIntent = \Stripe\PaymentIntent::create([
'amount' => "500",
'currency' => 'ron',
]);
$output = [
'clientSecret' => $paymentIntent->client_secret,
];
echo json_encode($output);
} catch (Error $e) {
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
}
So, one of the problems is that whenever I get to pay for an order, no matter what credit card number I pass, it always succeeds, and that is a major bug. The second one, I need to pass the total of the current order, otherwise all orders will get a total amount of 500, the default value. I tried to pass the session cart items to the fetch but it didn't work. Even though I cannot send all the items from the cart to the intent, at least the total price should correspond.
If I wasn't clear enough with anything, please let me know. I would really appreciate any piece of advice. Thank you !
**Edit:
You can update the PaymentIntent amount via the API (reference) before you confirm it (either on the server or client side. If you're encountering errors sending this, please share the details of that error.
You need to say more about the "it always succeeds" and exactly what request you are making. You did not show how you are using Stripe.js. You should use the test cards that Stripe provides to test success and failure cases. If you are getting different results than specified you will need to provide more detail about what exactly you're doing and what you expect the result to be.
I am new to Django and Javascript - I am making a project that has posts on a site, and I want to create a 'like' button on each post. So far here is my code - I am not getting any errors at all. No console errors in the browser either. But nothing happens. When you click the heart image, if it is liked, it should be a red image. When it is not liked, it is the white heart image. Currently when I click the image, it just stays white. It is always defaulting to that white image. The code doesn't work. Any help is appreciated.
views.py for the like button:
#csrf_exempt
def like(request):
if request.method == "POST":
post_id = request.POST.get('id')
is_liked = request.POST.get('is_liked')
try:
post = Post.objects.get(id=post_id)
if is_liked == 'no':
post.like.add(request.user)
is_liked = 'yes'
elif is_liked == 'yes':
post.like.remove(request.user)
is_liked = 'no'
post.save()
return JsonResponse({'like_count': post.like.count(), 'is_liked': is_liked,
"status": 201})
except:
return JsonResponse({'error': "Post not found", "status": 404})
return JsonResponse({}, status=400)
views.py for the page to show all the posts:
def index(request):
list_of_posts = Post.objects.all().order_by('id').reverse()
paginator = Paginator(list_of_posts, 10)
page_number = request.GET.get('page', 1)
page_obj = paginator.get_page(page_number)
return render(request, "network/index.html", {
"list_of_posts": list_of_posts,
"page_obj": page_obj
})
Javascript file:
like = document.querySelectorAll(".liked");
edit = document.querySelectorAll(".edit");
text_area = document.querySelectorAll(".textarea");
like.forEach((element) => {
like_handeler(element);
});
function like_handeler(element) {
element.addEventListener("click", () => {
id = element.getAttribute("data-id");
is_liked = element.getAttribute("data-is_liked");
icon = document.querySelector(`#post-like-${id}`);
count = document.querySelector(`#post-count-${id}`);
form = new FormData();
form.append("id", id);
form.append("is_liked", is_liked);
fetch("/like/", {
method: "POST",
body: form,
})
.then((res) => res.json())
.then((res) => {
if (res.status == 201) {
if (res.is_liked === "yes") {
icon.src = "https://img.icons8.com/plasticine/100/000000/like.png";
element.setAttribute("data-is_liked", "yes");
} else {
icon.src =
"https://img.icons8.com/carbon-copy/100/000000/like--v2.png";
element.setAttribute("data-is_liked", "no");
}
count.textContent = res.like_count;
}
})
.catch(function (res) {
alert("Network Error. Please Check your connection.");
});
});
}
html file for each post: index.html:
{% extends "network/layout.html" %}
{% load static %}
{% block body %}
<h3> Welcome. Here is your news feed: </h3>
{% for i in page_obj %}
<div class='card mb-3' style="max-width: 530px;" id="card-posts">
<div class="row no-gutters">
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title"><a href="{% url 'profile' username=i.username
%}">{{i.username}}</a></h5>
<p class="card-text">{{i.text}}</p>
<div class="like mt-3">
<img
data-id="{{i.id}}"
id="post-like-{{i.id}}"
class="liked"
{% if not request.user in i.like.all %}
data-is_liked="no"
src="https://img.icons8.com/carbon-copy/100/000000/like--v2.png"
{%else%}
data-is_liked="yes"
src="https://img.icons8.com/plasticine/100/000000/like.png"
{%endif%}
/>
<span id="post-count-{{post.id}}">{{i.like.count}}</span>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
{% block script %}
<script src="{% static 'network/network.js'%}"></script>
{% endblock %}
When I click the 'like' heart button on the page this is what I get. Each instance of 2, happens when I click it once. So this image is from clicking the heart button 3 times: