I have an e-commerce application that I'm working on. The app is currently hosted on Heroku free account. At the moment I can select a product, add it on the cart and can get up to the stripe form and type in the card details, but when I click the 'Submit Payment' button nothing happens. I don't even get an error message. I'm using Stripe test keys and 4242 four times as my card number. Can anyone help me to find out what's going on pliz. I have been stuck on it for days.
Here is the relevant code below:
Settings.py code:
from .base import *
import dj_database_url
DEBUG = (os.environ.get('DEBUG_VALUE') == 'True')
ALLOWED_HOSTS = ['.herokuapp.com', '127.0.0.1']
AUTH_PASSWORD_VALIDATORS = [
{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'},
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'},
{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'}
]
""" DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': config('DB_NAME'),
'USER': config('DB_USER'),
'PASSWORD': config('DB_PASSWORD'),
'HOST': config('DB_HOST'),
'PORT': ''
}
}
"""
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
STRIPE_PUBLIC_KEY = os.environ.get('STRIPE_LIVE_PUBLIC_KEY')
STRIPE_SECRET_KEY = os.environ.get('STRIPE_LIVE_SECRET_KEY')
AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME')
AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = None
AWS_S3_REGION_NAME = "us-east-2"
AWS_S3_SIGNATURE_VERSION = "s3v4"
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.environ.get('EMAIL_USER')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_PASSWORD')
# Heroku: Update database configuration from $DATABASE_URL.
db_from_env = dj_database_url.config(conn_max_age=500)
DATABASES['default'].update(db_from_env)
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
# The absolute path to the directory where collectstatic will collect static files for deployment.
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static_in_env')]
# The URL to use when referring to static files (where they will be served from)
STATIC_URL = '/static/'
# Simplified static file serving.
# https://warehouse.python.org/project/whitenoise/
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
views.py (Specifically the class PaymentView(View)):
from django.conf import settings
from django.contrib import messages
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render, get_object_or_404
from django.views.generic import ListView, DetailView, View
from django.shortcuts import redirect
from django.utils import timezone
from django.db.models import Q
from .forms import CheckoutForm, CouponForm, RefundForm, PaymentForm
from .models import Item, OrderItem, Order, Address, Payment, Coupon, Refund, UserProfile
import random
import string
import stripe
stripe.api_key = settings.STRIPE_SECRET_KEY
class PaymentView(View):
def get(self, *args, **kwargs):
order = Order.objects.get(user=self.request.user, ordered=False)
if order.billing_address:
context = {
'order': order,
'DISPLAY_COUPON_FORM': False
}
userprofile = self.request.user.userprofile
if userprofile.one_click_purchasing:
# fetch the users card list
cards = stripe.Customer.list_sources(
userprofile.stripe_customer_id,
limit=3,
object='card'
)
card_list = cards['data']
if len(card_list) > 0:
# update the context with the default card
context.update({
'card': card_list[0]
})
return render(self.request, "payment.html", context)
else:
messages.warning(
self.request, "You have not added a billing address")
return redirect("core:checkout")
def post(self, *args, **kwargs):
order = Order.objects.get(user=self.request.user, ordered=False)
form = PaymentForm(self.request.POST)
print('form')
userprofile = UserProfile.objects.get(user=self.request.user)
if form.is_valid():
token = form.cleaned_data.get('stripeToken')
# print('token')
save = form.cleaned_data.get('save')
use_default = form.cleaned_data.get('use_default')
if save:
if userprofile.stripe_customer_id != '' and userprofile.stripe_customer_id is not None:
customer = stripe.Customer.retrieve(
userprofile.stripe_customer_id)
customer.sources.create(source=token)
else:
customer = stripe.Customer.create(
email=self.request.user.email,
)
customer.sources.create(source=token)
userprofile.stripe_customer_id = customer['id']
userprofile.one_click_purchasing = True
userprofile.save()
amount = order.get_total() * 100
try:
if use_default or save:
# charge the customer because we cannot charge the token more than once
charge = stripe.Charge.create(
amount=amount, # cents
currency="usd",
customer=userprofile.stripe_customer_id
)
else:
# charge once off on the token
charge = stripe.Charge.create(
amount=amount, # cents
currency="usd",
source=token
)
# create the payment
payment = Payment()
payment.stripe_charge_id = charge['id']
payment.user = self.request.user
payment.amount = order.get_total()
payment.save()
# assign the payment to the order
order_items = order.items.all()
order_items.update(ordered=True)
for item in order_items:
item.save()
order.ordered = True
order.payment = payment
order.ref_code = create_ref_code()
order.save()
messages.success(self.request, "Your order was successful!")
return redirect("/")
except stripe.error.CardError as e:
body = e.json_body
err = body.get('error', {})
messages.warning(self.request, f"{err.get('message')}")
return redirect("/")
except stripe.error.RateLimitError as e:
# Too many requests made to the API too quickly
print(e)
messages.warning(self.request, "Rate limit error")
return redirect("/")
except stripe.error.InvalidRequestError as e:
# Invalid parameters were supplied to Stripe's API
print(e)
messages.warning(self.request, "Invalid parameters")
return redirect("/")
except stripe.error.AuthenticationError as e:
# Authentication with Stripe's API failed
# (maybe you changed API keys recently)
print(e)
messages.warning(self.request, "Not authenticated")
return redirect("/")
except stripe.error.APIConnectionError as e:
# Network communication with Stripe failed
print(e)
messages.warning(self.request, "Network error")
return redirect("/")
except stripe.error.StripeError as e:
# Display a very generic error to the user, and maybe send
# yourself an email
print(e)
messages.warning(
self.request, "Something went wrong. You were not charged. Please try again.")
return redirect("/")
except Exception as e:
# send an email to ourselves
print(e)
messages.warning(
self.request, "A serious error occurred. We have been notifed.")
return redirect("/")
messages.warning(self.request, "Invalid data received")
return redirect("/payment/stripe/")
payment.html:
{% extends "base.html" %}
{% block extra_head %}
<style>
#stripeBtnLabel {
font-family: "Helvetica Neue", Helvetica, sans-serif;
font-size: 16px;
font-variant: normal;
padding: 0;
margin: 0;
-webkit-font-smoothing: antialiased;
font-weight: 500;
display: block;
}
#stripeBtn {
border: none;
border-radius: 4px;
outline: none;
text-decoration: none;
color: #fff;
background: #32325d;
white-space: nowrap;
display: inline-block;
height: 40px;
line-height: 40px;
box-shadow: 0 4px 6px rgba(50, 50, 93, .11), 0 1px 3px rgba(0, 0, 0, .08);
border-radius: 4px;
font-size: 15px;
font-weight: 600;
letter-spacing: 0.025em;
text-decoration: none;
-webkit-transition: all 150ms ease;
transition: all 150ms ease;
float: left;
width: 100%
}
button:hover {
transform: translateY(-1px);
box-shadow: 0 7px 14px rgba(50, 50, 93, .10), 0 3px 6px rgba(0, 0, 0, .08);
background-color: #43458b;
}
.stripe-form {
padding: 5px 30px;
}
#card-errors {
height: 20px;
padding: 4px 0;
color: #fa755a;
}
.stripe-form-row {
width: 100%;
float: left;
margin-top: 5px;
margin-bottom: 5px;
}
/**
* The CSS shown here will not be introduced in the Quickstart guide, but shows
* how you can use CSS to style your Element's container.
*/
.StripeElement {
box-sizing: border-box;
height: 40px;
padding: 10px 12px;
border: 1px solid transparent;
border-radius: 4px;
background-color: white;
box-shadow: 0 1px 3px 0 #e6ebf1;
-webkit-transition: box-shadow 150ms ease;
transition: box-shadow 150ms ease;
}
.StripeElement--focus {
box-shadow: 0 1px 3px 0 #cfd7df;
}
.StripeElement--invalid {
border-color: #fa755a;
}
.StripeElement--webkit-autofill {
background-color: #fefde5 !important;
}
.current-card-form {
display: none;
}
</style>
{% endblock extra_head %}
{% block content %}
<main>
<div class="container wow fadeIn">
<h2 class="m