From 6223f4a1ef868c042a2ecca84d4e35d0545fa06f Mon Sep 17 00:00:00 2001
From: Tomislav R
Date: Fri, 11 Mar 2016 19:42:45 +0100
Subject: [PATCH] payment app
---
dynamicweb/settings/base.py | 20 +++-
membership/forms.py | 42 ++++++-
membership/migrations/0001_initial.py | 42 +++++++
membership/migrations/__init__.py | 0
membership/models.py | 15 ++-
membership/payment.py | 46 ++++++++
membership/templates/confirm.html | 20 +++-
membership/templates/creditcard.html | 162 ++++++++++++++++----------
membership/templates/error.html | 12 +-
membership/templates/membership.html | 4 +-
membership/templates/success.html | 2 +-
membership/templates/validated.html | 16 ++-
membership/urls.py | 7 +-
membership/views.py | 88 ++++++++++++--
requirements.txt | 4 +-
15 files changed, 379 insertions(+), 101 deletions(-)
create mode 100644 membership/migrations/0001_initial.py
create mode 100644 membership/migrations/__init__.py
create mode 100644 membership/payment.py
diff --git a/dynamicweb/settings/base.py b/dynamicweb/settings/base.py
index 5d9af85a..89aad881 100644
--- a/dynamicweb/settings/base.py
+++ b/dynamicweb/settings/base.py
@@ -120,10 +120,10 @@ TEMPLATES = [
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(PROJECT_DIR, 'membership/'), # membership template
- os.path.join(PROJECT_DIR,'templates/'),
- os.path.join(PROJECT_DIR,'templates/digitalglarus/partials'),
- os.path.join(PROJECT_DIR,'templates/cms'),
- os.path.join(PROJECT_DIR,'templates/digitalglarus'),
+ os.path.join(PROJECT_DIR, 'templates/'),
+ os.path.join(PROJECT_DIR, 'templates/digitalglarus/partials'),
+ os.path.join(PROJECT_DIR, 'templates/cms'),
+ os.path.join(PROJECT_DIR, 'templates/digitalglarus'),
],
'APP_DIRS': True,
'OPTIONS': {
@@ -412,3 +412,15 @@ META_USE_SITES = True
PARLER_LANGUAGES = {1: ({'code': 'en-us'}, {'code': 'de'},)}
AUTH_USER_MODEL = 'membership.CustomUser'
+
+
+# PAYMENT
+
+STRIPE_API_PUBLIC_KEY = 'pk_test_uvWyHNJgVL2IB8kjfgJkGjg4' # used in frontend to call from user browser
+STRIPE_API_PRIVATE_KEY = 'sk_test_uIPMdgXoRGydrcD7fkwcn7dj' # used in backend payment
+STRIPE_DESCRIPTION_ON_PAYMENT = "Payment for ungleich GmbH services"
+
+# EMAIL MESSAGES
+REGISTRATION_MESSAGE = {'subject': "Validation mail",
+ 'message': 'Please validate Your account under this link http://localhost:8000/en-us/validate/{}',
+ 'from': 'test@test.com'}
diff --git a/membership/forms.py b/membership/forms.py
index 04827be1..7ce2a1d4 100644
--- a/membership/forms.py
+++ b/membership/forms.py
@@ -1,14 +1,50 @@
__author__ = 'tomislav'
from django import forms
+from django.utils.translation import ugettext_lazy as _
+import six
+
+from .models import CreditCards
class LoginForm(forms.Form):
email = forms.EmailField(label="Email address", max_length=50,
- widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter email'}))
+ widget=forms.TextInput(
+ attrs={'class': 'form-control', 'placeholder': 'Enter email'}))
password = forms.CharField(label='Password', max_length=50,
- widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Password','type':'password'}))
+ widget=forms.TextInput(
+ attrs={'class': 'form-control', 'placeholder': 'Password',
+ 'type': 'password'}))
class RegisterForm(LoginForm):
name = forms.CharField(label='Name', max_length=50,
- widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder':'Enter name'}))
+ widget=forms.TextInput(
+ attrs={'class': 'form-control', 'placeholder': 'Enter name'}))
+
+
+class PaymentForm(forms.ModelForm):
+ class Meta:
+ model = CreditCards
+ fields = ('name', 'card_number', 'expiry_date', 'ccv', 'user_id')
+ labels = {'name': _('Name'), 'card_number': _('Card number'), 'expiry_date': _('Expiry date'),
+ 'ccv': _('CCV')}
+ exclude = ('user_id','payment_type')
+ widgets = {
+ 'name': forms.TextInput(
+ attrs={'class': 'form-control', "placeholder": "Enter name on card",
+ 'placeholder': 'Enter name on card'}),
+ 'card_number': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Card Number','data-stripe':'number'}),
+ 'expiry_date': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'MM/YYYY'}),
+ 'ccv': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'CCV','data-stripe':'cvc'})}
+
+ def clean(self):
+ data = self.cleaned_data
+
+ # if CreditCards.objects.filter(card_number=data.get("card_number")):
+ # raise forms.ValidationError({'card_number': _('Credit card is used before.')})
+ return self.cleaned_data
+
+ def save(self, user_id):
+ self.instance.user_id = user_id
+ self.instance.user_id_id = user_id.id
+ super(PaymentForm, self).save()
diff --git a/membership/migrations/0001_initial.py b/membership/migrations/0001_initial.py
new file mode 100644
index 00000000..1704515c
--- /dev/null
+++ b/membership/migrations/0001_initial.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+from django.conf import settings
+import django.core.validators
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='CustomUser',
+ fields=[
+ ('id', models.AutoField(auto_created=True, serialize=False, verbose_name='ID', primary_key=True)),
+ ('password', models.CharField(verbose_name='password', max_length=128)),
+ ('last_login', models.DateTimeField(null=True, verbose_name='last login', blank=True)),
+ ('name', models.CharField(max_length=50)),
+ ('email', models.EmailField(unique=True, max_length=254)),
+ ('validated', models.IntegerField(default=0, choices=[(0, 'Not validated'), (1, 'Validated')])),
+ ('validation_slug', models.CharField(unique=True, max_length=50, db_index=True)),
+ ],
+ options={
+ 'abstract': False,
+ },
+ ),
+ migrations.CreateModel(
+ name='CreditCards',
+ fields=[
+ ('id', models.AutoField(auto_created=True, serialize=False, verbose_name='ID', primary_key=True)),
+ ('name', models.CharField(max_length=50)),
+ ('card_number', models.CharField(max_length=50)),
+ ('expiry_date', models.CharField(validators=[django.core.validators.RegexValidator('\\d{2}\\/\\d{4}', 'Use this pattern(MM/YYYY).')], max_length=50)),
+ ('ccv', models.CharField(validators=[django.core.validators.RegexValidator('\\d{3,4}', 'Wrong CCV number.')], max_length=4)),
+ ('payment_type', models.CharField(max_length=5, default='N')),
+ ('user_id', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ ]
diff --git a/membership/migrations/__init__.py b/membership/migrations/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/membership/models.py b/membership/models.py
index 273b764b..349c56a0 100644
--- a/membership/models.py
+++ b/membership/models.py
@@ -1,7 +1,9 @@
from django.db import models
+from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User, AbstractBaseUser, BaseUserManager
from django.contrib.auth.hashers import make_password
from django.core.mail import send_mail
+from django.core.validators import RegexValidator
REGISTRATION_MESSAGE = {'subject': "Validation mail",
'message': 'Please validate Your account under this link http://localhost:8000/en-us/validate/{}',
@@ -110,7 +112,12 @@ class CustomUser(AbstractBaseUser):
# Simplest possible answer: All admins are staff
return self.is_admin
-# class CreditCards(models.Model):
-# id = models.IntegerField(primary_key=True)
-# user_id = models.ForeignKey(User, on_delete=models.CASCADE)
-# number = models.CharField(max_length=400)
+
+class CreditCards(models.Model):
+ name = models.CharField(max_length=50)
+ user_id = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
+ card_number = models.CharField(max_length=50)
+ expiry_date = models.CharField(max_length=50, validators=[RegexValidator(r'\d{2}\/\d{4}', _(
+ 'Use this pattern(MM/YYYY).'))])
+ ccv = models.CharField(max_length=4,validators=[RegexValidator(r'\d{3,4}',_('Wrong CCV number.'))])
+ payment_type = models.CharField(max_length=5,default='N')
diff --git a/membership/payment.py b/membership/payment.py
new file mode 100644
index 00000000..31e2ce73
--- /dev/null
+++ b/membership/payment.py
@@ -0,0 +1,46 @@
+__author__ = 'tomislav'
+from django.conf import settings
+from .models import CreditCards
+import stripe
+stripe.api_key = settings.STRIPE_API_PRIVATE_KEY
+
+
+class StripePayment(object):
+
+ @classmethod
+ def make_payment(cls,user,amount,token,time):
+ try:
+ # Use Stripe's library to make requests...
+ charge = stripe.Charge.create(
+ amount=amount,
+ currency='chf',
+ source=token,
+ description=settings.STRIPE_DESCRIPTION_ON_PAYMENT
+ )
+ if charge['status'] =='succeeded':
+ obj = CreditCards.objects.filter(user_id=user.id).first()
+ obj.payment_type = time
+ obj.save()
+ return charge['status']
+
+ except stripe.error.CardError as e:
+ # Since it's a decline, stripe.error.CardError will be caught
+ body = e.json_body
+ err = body['error']
+ return err['message']
+ except stripe.error.RateLimitError as e:
+ return "Too many requests made to the API too quickly"
+ except stripe.error.InvalidRequestError as e:
+ return "Invalid parameters"
+ except stripe.error.AuthenticationError as e:
+ # Authentication with Stripe's API failed
+ # (maybe you changed API keys recently)
+ pass
+ except stripe.error.APIConnectionError as e:
+ return "Currently its not possible to make payments."
+ except stripe.error.StripeError as e:
+ return "Currently its not possible to make payments."
+ #maybe send email
+ except Exception as e:
+ return "Currently its not possible to make payments."
+ #maybe send email
diff --git a/membership/templates/confirm.html b/membership/templates/confirm.html
index 3623d8dc..9ca82b0b 100644
--- a/membership/templates/confirm.html
+++ b/membership/templates/confirm.html
@@ -4,7 +4,8 @@
-
+ {% load static %}
+
@@ -19,8 +20,15 @@
Your membership is almost ready!
If this is correct information, click CONFIRM
- Name: Nico Schottelius
- Email: nico.schottelius@digitalglarus.ch
+ Name: {{ name }}
+
+ {% if email %}
+ Email: {{ email }}
+ {% else %}
+
+ {% endif %}
Membership requested for:
01.01.2016-31.12.2016
@@ -30,12 +38,12 @@
diff --git a/membership/templates/creditcard.html b/membership/templates/creditcard.html
index 7c704187..bb8801c3 100644
--- a/membership/templates/creditcard.html
+++ b/membership/templates/creditcard.html
@@ -1,66 +1,104 @@
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+ {% load static %}
+
+
+
+
+
-
-
-
Payment details
-
-
-
-
-
-
Cancel
-
-
-
-
-
-
-
+
+
+
Payment details
+
+
+
+
+
Cancel
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/membership/templates/error.html b/membership/templates/error.html
index 2fe974e6..f5206a59 100644
--- a/membership/templates/error.html
+++ b/membership/templates/error.html
@@ -2,12 +2,16 @@
-
-
-
+
+
{% load static %}
+
diff --git a/membership/templates/membership.html b/membership/templates/membership.html
index 41b44f0c..a0c5468c 100644
--- a/membership/templates/membership.html
+++ b/membership/templates/membership.html
@@ -79,7 +79,7 @@
for coworking. It is a perfect try-out package!
- Buy Now
+ Buy Now
@@ -98,7 +98,7 @@
membership.
- Buy Now
+ Buy Now
diff --git a/membership/templates/success.html b/membership/templates/success.html
index 26ef30cf..d55cf1e1 100644
--- a/membership/templates/success.html
+++ b/membership/templates/success.html
@@ -21,6 +21,6 @@
-
+
\ No newline at end of file
diff --git a/membership/templates/validated.html b/membership/templates/validated.html
index c05d9c19..bd1a3c90 100644
--- a/membership/templates/validated.html
+++ b/membership/templates/validated.html
@@ -8,13 +8,27 @@
type="text/css">
+ {% if request.session.next == None %}
+
+ {% endif %}
-
You're successfully validated!
+
+ {% if msg == 'succeeded' %}
+ Thank You for Your payment!
redirecting...
+ {% else %}
+ Your payment was not processed correctly.
Reason: {{ msg }}
+ {% endif %}
+
diff --git a/membership/urls.py b/membership/urls.py
index 6df168f6..4fca7607 100644
--- a/membership/urls.py
+++ b/membership/urls.py
@@ -1,10 +1,13 @@
__author__ = 'tomislav'
from django.conf.urls import url
+from django.contrib.auth.decorators import login_required
from . import views
urlpatterns = (
- url(r"^/$", views.LoginRegistrationView.as_view()),
+ url(r"^/$", views.LoginRegistrationView.as_view(), name='login'),
url(r"^/validate/(?P
.*)/$", views.validate_email),
- url(r"^/membership/$",views.MembershipView.as_view(),name='membership')
+ url(r"^/membership/$", login_required(views.MembershipView.as_view()), name='membership'),
+ url(r"^/buy/(?P