payment app
This commit is contained in:
parent
b14b3d2803
commit
6223f4a1ef
15 changed files with 379 additions and 101 deletions
|
@ -120,10 +120,10 @@ TEMPLATES = [
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
'DIRS': [
|
'DIRS': [
|
||||||
os.path.join(PROJECT_DIR, 'membership/'), # membership template
|
os.path.join(PROJECT_DIR, 'membership/'), # membership template
|
||||||
os.path.join(PROJECT_DIR,'templates/'),
|
os.path.join(PROJECT_DIR, 'templates/'),
|
||||||
os.path.join(PROJECT_DIR,'templates/digitalglarus/partials'),
|
os.path.join(PROJECT_DIR, 'templates/digitalglarus/partials'),
|
||||||
os.path.join(PROJECT_DIR,'templates/cms'),
|
os.path.join(PROJECT_DIR, 'templates/cms'),
|
||||||
os.path.join(PROJECT_DIR,'templates/digitalglarus'),
|
os.path.join(PROJECT_DIR, 'templates/digitalglarus'),
|
||||||
],
|
],
|
||||||
'APP_DIRS': True,
|
'APP_DIRS': True,
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
|
@ -412,3 +412,15 @@ META_USE_SITES = True
|
||||||
|
|
||||||
PARLER_LANGUAGES = {1: ({'code': 'en-us'}, {'code': 'de'},)}
|
PARLER_LANGUAGES = {1: ({'code': 'en-us'}, {'code': 'de'},)}
|
||||||
AUTH_USER_MODEL = 'membership.CustomUser'
|
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'}
|
||||||
|
|
|
@ -1,14 +1,50 @@
|
||||||
__author__ = 'tomislav'
|
__author__ = 'tomislav'
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
import six
|
||||||
|
|
||||||
|
from .models import CreditCards
|
||||||
|
|
||||||
|
|
||||||
class LoginForm(forms.Form):
|
class LoginForm(forms.Form):
|
||||||
email = forms.EmailField(label="Email address", max_length=50,
|
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,
|
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):
|
class RegisterForm(LoginForm):
|
||||||
name = forms.CharField(label='Name', max_length=50,
|
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()
|
||||||
|
|
42
membership/migrations/0001_initial.py
Normal file
42
membership/migrations/0001_initial.py
Normal file
|
@ -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)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
0
membership/migrations/__init__.py
Normal file
0
membership/migrations/__init__.py
Normal file
|
@ -1,7 +1,9 @@
|
||||||
from django.db import models
|
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.models import User, AbstractBaseUser, BaseUserManager
|
||||||
from django.contrib.auth.hashers import make_password
|
from django.contrib.auth.hashers import make_password
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
|
from django.core.validators import RegexValidator
|
||||||
|
|
||||||
REGISTRATION_MESSAGE = {'subject': "Validation mail",
|
REGISTRATION_MESSAGE = {'subject': "Validation mail",
|
||||||
'message': 'Please validate Your account under this link http://localhost:8000/en-us/validate/{}',
|
'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
|
# Simplest possible answer: All admins are staff
|
||||||
return self.is_admin
|
return self.is_admin
|
||||||
|
|
||||||
# class CreditCards(models.Model):
|
|
||||||
# id = models.IntegerField(primary_key=True)
|
class CreditCards(models.Model):
|
||||||
# user_id = models.ForeignKey(User, on_delete=models.CASCADE)
|
name = models.CharField(max_length=50)
|
||||||
# number = models.CharField(max_length=400)
|
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')
|
||||||
|
|
46
membership/payment.py
Normal file
46
membership/payment.py
Normal file
|
@ -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
|
|
@ -4,7 +4,8 @@
|
||||||
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
|
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
|
||||||
<script type="text/javascript" src="http://netdna.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
<script type="text/javascript" src="http://netdna.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
||||||
<link href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
|
<link href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
|
||||||
<link href="membership.css" rel="stylesheet" type="text/css">
|
{% load static %}
|
||||||
|
<link href="{% get_static_prefix %}membership.css" rel="stylesheet" type="text/css">
|
||||||
</head><body>
|
</head><body>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
@ -19,8 +20,15 @@
|
||||||
<h2 class="text-center text-muted">Your membership is almost ready!</h2>
|
<h2 class="text-center text-muted">Your membership is almost ready!</h2>
|
||||||
<h5 class="text-center text-muted">If this is correct information, click CONFIRM</h5>
|
<h5 class="text-center text-muted">If this is correct information, click CONFIRM</h5>
|
||||||
<br>
|
<br>
|
||||||
<h4 class="text-center text-muted">Name: Nico Schottelius</h4>
|
<h4 class="text-center text-muted">Name: {{ name }}</h4>
|
||||||
<h4 class="text-center text-muted">Email: nico.schottelius@digitalglarus.ch</h4>
|
|
||||||
|
{% if email %}
|
||||||
|
<h4 class="text-center text-muted">Email: {{ email }}</h4>
|
||||||
|
{% else %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
<h4 class="text-center text-muted">Membership requested for:
|
<h4 class="text-center text-muted">Membership requested for:
|
||||||
<br><br>01.01.2016-31.12.2016</h4>
|
<br><br>01.01.2016-31.12.2016</h4>
|
||||||
<br>
|
<br>
|
||||||
|
@ -30,12 +38,12 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12 text-center">
|
<div class="col-md-12 text-center">
|
||||||
<p class="text-center text-muted">Have probelm? Contact
|
<p class="text-center text-muted">Have problem? Contact
|
||||||
<a href="">help@digitalglarus.ch.</a>
|
<a href="">help@digitalglarus.ch.</a>
|
||||||
<br>
|
<br>
|
||||||
</p>
|
</p>
|
||||||
<a class="btn btn-primary">GO BACK</a>
|
<a class="btn btn-primary" href="{% url 'reset' time=request.session.time %}">GO BACK</a>
|
||||||
<a class="btn btn-primary">CONFIRM</a>
|
<a class="btn btn-primary" href='.'>CONFIRM</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,66 +1,104 @@
|
||||||
<html><head>
|
<html>
|
||||||
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
|
<script type="text/javascript"
|
||||||
<script type="text/javascript" src="http://netdna.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
|
||||||
<link href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
|
<script type="text/javascript"
|
||||||
<link href="membership.css" rel="stylesheet" type="text/css">
|
src="http://netdna.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
||||||
</head><body>
|
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
|
||||||
<div class="section">
|
<script type="text/javascript">
|
||||||
<div class="container">
|
Stripe.setPublishableKey('{{ stripe_key }}');
|
||||||
|
var stripeResponseHandler = function (status, response) {
|
||||||
|
var $form = $('#payment-form');
|
||||||
|
if (response.error) {
|
||||||
|
debugger;
|
||||||
|
// Show the errors on the form
|
||||||
|
$form.find('.payment-errors').text(response.error.message);
|
||||||
|
$form.find('button').prop('disabled', false);
|
||||||
|
} else {
|
||||||
|
// token contains id, last4, and card type
|
||||||
|
var token = response.id;
|
||||||
|
// Insert the token into the form so it gets submitted to the server
|
||||||
|
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
|
||||||
|
// and re-submit
|
||||||
|
$form.get(0).submit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
jQuery(function ($) {
|
||||||
|
$('#payment-form').submit(function (e) {
|
||||||
|
var $form = $(this);
|
||||||
|
m_y = $("#id_expiry_date").val().split("/")
|
||||||
|
// Disable the submit button to prevent repeated clicks
|
||||||
|
$form.find('button').prop('disabled', true);
|
||||||
|
Stripe.card.createToken({
|
||||||
|
number: $("#id_card_number").val(),
|
||||||
|
cvc: $("#id_ccv").val(),
|
||||||
|
exp_month:m_y[0],
|
||||||
|
exp_year:m_y[1]
|
||||||
|
}, stripeResponseHandler);
|
||||||
|
// Prevent the form from submitting with the default action
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<link href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css"
|
||||||
|
rel="stylesheet" type="text/css">
|
||||||
|
{% load static %}
|
||||||
|
<link href="{% get_static_prefix %}membership.css" rel="stylesheet" type="text/css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="section">
|
||||||
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2"></div>
|
<div class="col-md-2"></div>
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<h3 class="text-left text-muted">Payment details</h3>
|
<h3 class="text-left text-muted">Payment details</h3>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="page-header text-muted" contenteditable="true">
|
<div class="page-header text-muted" contenteditable="true">
|
||||||
<h5>1 Year coworking membership (360 CHF)</h5>
|
<h5>{{ time }} coworking membership ({{ price }} CHF)</h5>
|
||||||
<h5> +2 free working days included (0 CHF)</h5>
|
<h5> +{{ free }} free working days included (0 CHF)</h5>
|
||||||
<div class="page-header text-muted">
|
|
||||||
<h5>Valid 01.01.2016 - 31.12.2016 </h5>
|
|
||||||
<h5>Coworker Name : Nico Schottelius </h5>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="page-header text-muted">
|
|
||||||
<h3 class="text-right">Total : 360 CHF</h3>
|
|
||||||
</div>
|
|
||||||
<form role="form">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="control-label" for="exampleInputEmail1">Name*</label>
|
|
||||||
<input class="form-control" id="exampleInputEmail1" placeholder="Enter name on card" type="email">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="control-label" for="exampleInputPassword1">Card Number*</label>
|
|
||||||
<input class="form-control" id="exampleInputPassword1" placeholder="Card Number" type="text">
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<form role="form">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="control-label" for="exampleInputEmail1">Expiry Date*</label>
|
|
||||||
<input class="form-control" id="exampleInputEmail1" placeholder="MM/YY" type="email">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="control-label" for="exampleInputPassword1">CCV*</label>
|
|
||||||
<input class="form-control" id="exampleInputPassword1" placeholder="CVV" type="password">
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-block btn-primary">Submit</button>
|
|
||||||
</form>
|
|
||||||
<a class="btn btn-block btn-info">Cancel</a>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-2"></div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-11">
|
|
||||||
<br>
|
|
||||||
<p class="text-center text-muted">Have probelm? Contact
|
|
||||||
<a href="">help@digitalglarus.ch.</a>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</body></html>
|
<div class="page-header text-muted">
|
||||||
|
<h5>Valid 01.01.2016 - 31.12.2016 </h5>
|
||||||
|
<h5>Coworker Name : {{ name }} </h5>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="page-header text-muted">
|
||||||
|
<h3 class="text-right">Total : {{ price }} CHF</h3>
|
||||||
|
</div>
|
||||||
|
<form id="payment-form" role="form" method="post">
|
||||||
|
<div class="payment-error"></div>
|
||||||
|
{% csrf_token %}
|
||||||
|
{% for field in form %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label">{{ field.label }}*</label>
|
||||||
|
{{ field }}
|
||||||
|
{% for error in field.errors %}
|
||||||
|
{{ error|striptags }}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
<button type="submit" class="btn btn-block btn-primary">Submit</button>
|
||||||
|
</form>
|
||||||
|
<a class="btn btn-block btn-info">Cancel</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2"></div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-11">
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<p class="text-center text-muted">Have probelm? Contact
|
||||||
|
<a href="">help@digitalglarus.ch.</a>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -2,12 +2,16 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
|
<script type="text/javascript"
|
||||||
<script type="text/javascript" src="http://netdna.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
|
||||||
<link href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet"
|
<script type="text/javascript"
|
||||||
|
src="http://netdna.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
||||||
|
<link href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css"
|
||||||
|
rel="stylesheet"
|
||||||
type="text/css">
|
type="text/css">
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<link href="{% get_static_prefix %}membership.css" rel="stylesheet" type="text/css">
|
<link href="{% get_static_prefix %}membership.css" rel="stylesheet" type="text/css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
|
@ -24,6 +28,8 @@
|
||||||
<a href="">help@digitalglarus.ch</a>
|
<a href="">help@digitalglarus.ch</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>{{ msg }}</p>
|
||||||
|
|
||||||
<p></p>
|
<p></p>
|
||||||
</div>
|
</div>
|
||||||
<a hrefhelp@digitalglarus.ch<="" p="">
|
<a hrefhelp@digitalglarus.ch<="" p="">
|
||||||
|
|
|
@ -79,7 +79,7 @@
|
||||||
for coworking. It is a perfect try-out package!
|
for coworking. It is a perfect try-out package!
|
||||||
<br>
|
<br>
|
||||||
</p>
|
</p>
|
||||||
<a class="btn btn-primary">Buy Now</a>
|
<a class="btn btn-primary" href="/login/buy/month/">Buy Now</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -98,7 +98,7 @@
|
||||||
membership.
|
membership.
|
||||||
<br>
|
<br>
|
||||||
</p>
|
</p>
|
||||||
<a class="btn btn-primary">Buy Now</a>
|
<a class="btn btn-primary" href="/login/buy/year/">Buy Now</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<img src="https://unsplash.imgix.net/photo-1413834932717-29e7d4714192?w=1024&q=50&fm=jpg&s=d9d6cbc32dd4968d0c21e331436a6af6" class="img-responsive">
|
<img src="https://unsplash.imgix.net/photo-1413834932717-29e7d4714192?w=1024&q=50&fm=jpg&s=d9d6cbc32dd4968d0c21e331436a6af6" class="img-responsive">
|
||||||
|
|
|
@ -21,6 +21,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</body></html>
|
</body></html>
|
|
@ -8,13 +8,27 @@
|
||||||
type="text/css">
|
type="text/css">
|
||||||
<link href="http://pingendo.github.io/pingendo-bootstrap/themes/default/bootstrap.css" rel="stylesheet"
|
<link href="http://pingendo.github.io/pingendo-bootstrap/themes/default/bootstrap.css" rel="stylesheet"
|
||||||
type="text/css">
|
type="text/css">
|
||||||
|
{% if request.session.next == None %}
|
||||||
|
<script>
|
||||||
|
type = "text/javascript" >
|
||||||
|
setTimeout(function () {
|
||||||
|
window.location.href = "/";
|
||||||
|
}, 5000);
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<h1 class="text-center text-muted">You're successfully validated!</h1>
|
<h3 class="text-center text-muted">
|
||||||
|
{% if msg == 'succeeded' %}
|
||||||
|
Thank You for Your payment!<br> <p>redirecting...</p>
|
||||||
|
{% else %}
|
||||||
|
Your payment was not processed correctly.<br> Reason: {{ msg }}
|
||||||
|
{% endif %}
|
||||||
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
__author__ = 'tomislav'
|
__author__ = 'tomislav'
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = (
|
urlpatterns = (
|
||||||
url(r"^/$", views.LoginRegistrationView.as_view()),
|
url(r"^/$", views.LoginRegistrationView.as_view(), name='login'),
|
||||||
url(r"^/validate/(?P<validate_slug>.*)/$", views.validate_email),
|
url(r"^/validate/(?P<validate_slug>.*)/$", 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<time>\w+)/$", login_required(views.CreditCardView.as_view()), name='payment'),
|
||||||
|
url(r'^/buy/(?P<time>\w+)/reset',login_required(views.reset),name='reset')
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,34 +1,94 @@
|
||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import render, redirect
|
||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
|
from django.contrib.auth import authenticate, login
|
||||||
|
from django.views.decorators.cache import cache_control
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
from .models import CustomUser
|
from .models import CustomUser
|
||||||
from .forms import LoginForm, RegisterForm
|
from .forms import (LoginForm, RegisterForm, PaymentForm)
|
||||||
from django.contrib.auth import authenticate,login
|
from .payment import StripePayment
|
||||||
|
|
||||||
|
|
||||||
def validate_email(request, validate_slug):
|
def validate_email(request, validate_slug):
|
||||||
validated = User.validate_url(validate_slug)
|
validated = CustomUser.validate_url(validate_slug)
|
||||||
if validated:
|
if validated:
|
||||||
return render(request,'templates/validated.html')
|
return render(request, 'templates/validated.html')
|
||||||
else:
|
else:
|
||||||
return render(request,'templates/error.html')
|
return render(request, 'templates/error.html')
|
||||||
|
|
||||||
|
def reset(request,time):
|
||||||
|
request.session['next']=0
|
||||||
|
return redirect('payment',time=time)
|
||||||
|
|
||||||
|
class CreditCardView(View):
|
||||||
|
def _get_context(self, request, time):
|
||||||
|
request.session['time'] = time
|
||||||
|
context = {}
|
||||||
|
context['name'] = request.user.name
|
||||||
|
if time == 'month':
|
||||||
|
context['time'] = "1 month"
|
||||||
|
context['price'] = "35"
|
||||||
|
context['free'] = "1"
|
||||||
|
elif time == 'year':
|
||||||
|
context['time'] = '1 year'
|
||||||
|
context['price'] = '360'
|
||||||
|
context['free'] = "2"
|
||||||
|
context['stripe_key'] = settings.STRIPE_API_PUBLIC_KEY
|
||||||
|
context['form'] = PaymentForm()
|
||||||
|
return context
|
||||||
|
|
||||||
|
@cache_control(no_cache=True,must_revalidate=True)
|
||||||
|
def get(self, request, time=None):
|
||||||
|
context = self._get_context(request, time)
|
||||||
|
next = request.session.get('next')
|
||||||
|
if next == 1 or next ==0:
|
||||||
|
template = 'templates/creditcard.html'
|
||||||
|
request.session['next'] +=1
|
||||||
|
elif next == 2:
|
||||||
|
msg = StripePayment.make_payment(request.user, request.session['amount'],
|
||||||
|
request.session['token'],request.session['time'])
|
||||||
|
template = 'templates/validated.html'
|
||||||
|
context['msg'] = msg
|
||||||
|
request.session['next'] = None
|
||||||
|
return render(request, template, context)
|
||||||
|
|
||||||
|
def post(self, request, time=None):
|
||||||
|
form = PaymentForm(request.POST)
|
||||||
|
stripe_token = request.POST['stripeToken']
|
||||||
|
|
||||||
|
if form.is_valid():
|
||||||
|
ret = form.save(request.user)
|
||||||
|
amount = 35 if time == 'month' else 360
|
||||||
|
amount = amount * 100 # payments are in 'cents'
|
||||||
|
request.session['token'] = stripe_token
|
||||||
|
request.session['amount'] = amount
|
||||||
|
request.session['next'] +=1
|
||||||
|
return render(request, 'templates/confirm.html',
|
||||||
|
context={'name': request.user.name, 'email': request.user.email})
|
||||||
|
else:
|
||||||
|
context = self._get_context(request, time)
|
||||||
|
context['form'] = form
|
||||||
|
return render(request, 'templates/creditcard.html', context=context)
|
||||||
|
|
||||||
|
|
||||||
class LoginRegistrationView(View):
|
class LoginRegistrationView(View):
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
login_form = LoginForm()
|
login_form = LoginForm()
|
||||||
register_form = RegisterForm()
|
register_form = RegisterForm()
|
||||||
|
request.session['next'] = None
|
||||||
if request.user.is_authenticated():
|
if request.user.is_authenticated():
|
||||||
return redirect("membership")
|
return redirect("membership")
|
||||||
else:
|
else:
|
||||||
return render(request, 'templates/login.html', {'login_form': login_form, 'register_form': register_form})
|
return render(request, 'templates/login.html',
|
||||||
|
{'login_form': login_form, 'register_form': register_form})
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
email = request.POST.get('email')
|
email = request.POST.get('email')
|
||||||
password = request.POST.get('password')
|
password = request.POST.get('password')
|
||||||
name = request.POST.get('name')
|
name = request.POST.get('name')
|
||||||
if name and email and password:
|
if name and email and password:
|
||||||
user = CustomUser.register(name, password,email)
|
user = CustomUser.register(name, password, email)
|
||||||
if user:
|
if user:
|
||||||
return render(request, 'templates/success.html')
|
return render(request, 'templates/success.html')
|
||||||
else:
|
else:
|
||||||
|
@ -37,11 +97,17 @@ class LoginRegistrationView(View):
|
||||||
elif email and password and not name:
|
elif email and password and not name:
|
||||||
user = authenticate(email=email, password=password)
|
user = authenticate(email=email, password=password)
|
||||||
if user:
|
if user:
|
||||||
login(request,user)
|
login(request, user)
|
||||||
return redirect('membership')
|
return redirect('membership')
|
||||||
else:
|
else:
|
||||||
return render(request, 'templates/login', {'msg': 'Wrong username or password'})
|
return redirect('login')
|
||||||
|
|
||||||
|
|
||||||
class MembershipView(View):
|
class MembershipView(View):
|
||||||
def get(self,request):
|
def get(self, request):
|
||||||
return render(request,'templates/membership.html')
|
#if the user has payed allready
|
||||||
|
member_payed = request.user.creditcards_set.filter(Q(payment_type='month') | Q(payment_type='year'))
|
||||||
|
if member_payed:
|
||||||
|
return redirect('/')
|
||||||
|
request.session['next'] = 0
|
||||||
|
return render(request, 'templates/membership.html')
|
||||||
|
|
|
@ -89,11 +89,11 @@ pyquery==1.2.9
|
||||||
python-memcached==1.57
|
python-memcached==1.57
|
||||||
pytz==2015.6
|
pytz==2015.6
|
||||||
pyzmq==14.7.0
|
pyzmq==14.7.0
|
||||||
requests==2.7.0
|
requests==2.9.1
|
||||||
simplejson==3.8.0
|
simplejson==3.8.0
|
||||||
six==1.10.0
|
six==1.10.0
|
||||||
sqlparse==0.1.15
|
sqlparse==0.1.15
|
||||||
stripe==1.22.3
|
stripe==1.30.0
|
||||||
tomako==0.1.0
|
tomako==0.1.0
|
||||||
TornadIO2==0.0.3
|
TornadIO2==0.0.3
|
||||||
tornado==4.2.1
|
tornado==4.2.1
|
||||||
|
|
Loading…
Reference in a new issue