payment app
This commit is contained in:
		
					parent
					
						
							
								3ca9ef5900
							
						
					
				
			
			
				commit
				
					
						e5d2d74450
					
				
			
		
					 15 changed files with 379 additions and 101 deletions
				
			
		| 
						 | 
					@ -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,11 +1,53 @@
 | 
				
			||||||
<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>
 | 
				
			||||||
 | 
					    <script type="text/javascript">
 | 
				
			||||||
 | 
					        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="section">
 | 
				
			||||||
    <div class="container">
 | 
					    <div class="container">
 | 
				
			||||||
        <div class="row">
 | 
					        <div class="row">
 | 
				
			||||||
| 
						 | 
					@ -14,35 +56,29 @@
 | 
				
			||||||
                <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">
 | 
					                    <div class="page-header text-muted">
 | 
				
			||||||
                        <h5>Valid 01.01.2016 - 31.12.2016 </h5>
 | 
					                        <h5>Valid 01.01.2016 - 31.12.2016 </h5>
 | 
				
			||||||
                <h5>Coworker Name : Nico Schottelius </h5>
 | 
					                        <h5>Coworker Name : {{ name }} </h5>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                <div class="page-header text-muted">
 | 
					                <div class="page-header text-muted">
 | 
				
			||||||
              <h3 class="text-right">Total : 360 CHF</h3>
 | 
					                    <h3 class="text-right">Total : {{ price }} CHF</h3>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            <form role="form">
 | 
					                <form id="payment-form" role="form" method="post">
 | 
				
			||||||
 | 
					                    <div class="payment-error"></div>
 | 
				
			||||||
 | 
					                    {% csrf_token %}
 | 
				
			||||||
 | 
					                    {% for field in  form %}
 | 
				
			||||||
                        <div class="form-group">
 | 
					                        <div class="form-group">
 | 
				
			||||||
                <label class="control-label" for="exampleInputEmail1">Name*</label>
 | 
					                            <label class="control-label">{{ field.label }}*</label>
 | 
				
			||||||
                <input class="form-control" id="exampleInputEmail1" placeholder="Enter name on card" type="email">
 | 
					                            {{ field }}
 | 
				
			||||||
              </div>
 | 
					                            {% for error in field.errors %}
 | 
				
			||||||
              <div class="form-group">
 | 
					                                {{ error|striptags }}
 | 
				
			||||||
                <label class="control-label" for="exampleInputPassword1">Card Number*</label>
 | 
					                            {% endfor %}
 | 
				
			||||||
                <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>
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    {% endfor %}
 | 
				
			||||||
                    <button type="submit" class="btn btn-block btn-primary">Submit</button>
 | 
					                    <button type="submit" class="btn btn-block btn-primary">Submit</button>
 | 
				
			||||||
                </form>
 | 
					                </form>
 | 
				
			||||||
                <a class="btn btn-block btn-info">Cancel</a>
 | 
					                <a class="btn btn-block btn-info">Cancel</a>
 | 
				
			||||||
| 
						 | 
					@ -52,6 +88,7 @@
 | 
				
			||||||
        <div class="row">
 | 
					        <div class="row">
 | 
				
			||||||
            <div class="col-md-11">
 | 
					            <div class="col-md-11">
 | 
				
			||||||
                <br>
 | 
					                <br>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <p class="text-center text-muted">Have probelm? Contact
 | 
					                <p class="text-center text-muted">Have probelm? Contact
 | 
				
			||||||
                    <a href="">help@digitalglarus.ch.</a>
 | 
					                    <a href="">help@digitalglarus.ch.</a>
 | 
				
			||||||
                    <br>
 | 
					                    <br>
 | 
				
			||||||
| 
						 | 
					@ -63,4 +100,5 @@
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</body></html>
 | 
					</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">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,27 +1,87 @@
 | 
				
			||||||
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')
 | 
				
			||||||
| 
						 | 
					@ -40,8 +100,14 @@ class LoginRegistrationView(View):
 | 
				
			||||||
                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):
 | 
				
			||||||
 | 
					        #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')
 | 
					        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…
	
	Add table
		Add a link
		
	
		Reference in a new issue