Browse Source

Payments with Braintree, WIP

pull/14/head
Pēteris Caune 9 years ago
parent
commit
7039188482
17 changed files with 220 additions and 7 deletions
  1. +0
    -1
      hc/front/urls.py
  2. +0
    -4
      hc/front/views.py
  3. +0
    -0
      hc/payments/__init__.py
  4. +8
    -0
      hc/payments/admin.py
  5. +5
    -0
      hc/payments/context_processors.py
  6. +25
    -0
      hc/payments/migrations/0001_initial.py
  7. +0
    -0
      hc/payments/migrations/__init__.py
  8. +9
    -0
      hc/payments/models.py
  9. +3
    -0
      hc/payments/tests.py
  10. +18
    -0
      hc/payments/urls.py
  11. +81
    -0
      hc/payments/views.py
  12. +4
    -1
      hc/settings.py
  13. +1
    -0
      hc/urls.py
  14. +4
    -0
      templates/base.html
  15. +23
    -0
      templates/payments/create_subscription.html
  16. +0
    -1
      templates/payments/pricing.html
  17. +39
    -0
      templates/payments/status.html

+ 0
- 1
hc/front/urls.py View File

@ -11,7 +11,6 @@ urlpatterns = [
url(r'^checks/([\w-]+)/email/$', views.email_preview),
url(r'^checks/([\w-]+)/remove/$', views.remove_check, name="hc-remove-check"),
url(r'^checks/([\w-]+)/log/$', views.log, name="hc-log"),
url(r'^pricing/$', views.pricing, name="hc-pricing"),
url(r'^docs/$', views.docs, name="hc-docs"),
url(r'^about/$', views.about, name="hc-about"),
url(r'^integrations/$', views.channels, name="hc-channels"),


+ 0
- 4
hc/front/views.py View File

@ -47,10 +47,6 @@ def index(request):
return render(request, "front/welcome.html", ctx)
def pricing(request):
return render(request, "front/pricing.html", {"page": "pricing"})
def docs(request):
if "welcome_code" in request.session:
code = request.session["welcome_code"]


+ 0
- 0
hc/payments/__init__.py View File


+ 8
- 0
hc/payments/admin.py View File

@ -0,0 +1,8 @@
from django.contrib import admin
from .models import Subscription
@admin.register(Subscription)
class SubsAdmin(admin.ModelAdmin):
list_display = ("id", "user")

+ 5
- 0
hc/payments/context_processors.py View File

@ -0,0 +1,5 @@
from django.conf import settings
def payments(request):
return {'USE_PAYMENTS': settings.USE_PAYMENTS}

+ 25
- 0
hc/payments/migrations/0001_initial.py View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Subscription',
fields=[
('id', models.AutoField(serialize=False, primary_key=True, auto_created=True, verbose_name='ID')),
('customer_id', models.CharField(blank=True, max_length=36)),
('payment_method_token', models.CharField(blank=True, max_length=35)),
('subscription_id', models.CharField(blank=True, max_length=10)),
('user', models.OneToOneField(blank=True, null=True, to=settings.AUTH_USER_MODEL)),
],
),
]

+ 0
- 0
hc/payments/migrations/__init__.py View File


+ 9
- 0
hc/payments/models.py View File

@ -0,0 +1,9 @@
from django.contrib.auth.models import User
from django.db import models
class Subscription(models.Model):
user = models.OneToOneField(User, blank=True, null=True)
customer_id = models.CharField(max_length=36, blank=True)
payment_method_token = models.CharField(max_length=35, blank=True)
subscription_id = models.CharField(max_length=10, blank=True)

+ 3
- 0
hc/payments/tests.py View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

+ 18
- 0
hc/payments/urls.py View File

@ -0,0 +1,18 @@
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^pricing/$',
views.pricing,
name="hc-pricing"),
url(r'^create_subscription/$',
views.create,
name="hc-create-subscription"),
url(r'^subscription_status/$',
views.status,
name="hc-subscription-status"),
]

+ 81
- 0
hc/payments/views.py View File

@ -0,0 +1,81 @@
import braintree
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect, render
from .models import Subscription
def setup_braintree():
kw = {
"merchant_id": settings.BRAINTREE_MERCHANT_ID,
"public_key": settings.BRAINTREE_PUBLIC_KEY,
"private_key": settings.BRAINTREE_PRIVATE_KEY
}
braintree.Configuration.configure(settings.BRAINTREE_ENV, **kw)
def pricing(request):
ctx = {
"page": "pricing",
}
return render(request, "payments/pricing.html", ctx)
@login_required
def create(request):
setup_braintree()
try:
sub = Subscription.objects.get(user=request.user)
except Subscription.DoesNotExist:
sub = Subscription(user=request.user)
sub.save()
if request.method == "POST":
if not sub.customer_id:
result = braintree.Customer.create({})
assert result.is_success
sub.customer_id = result.customer.id
sub.save()
result = braintree.PaymentMethod.create({
"customer_id": sub.customer_id,
"payment_method_nonce": request.POST["payment_method_nonce"]
})
assert result.is_success
sub.payment_method_token = result.payment_method.token
sub.save()
result = braintree.Subscription.create({
"payment_method_token": sub.payment_method_token,
"plan_id": "pww",
"price": 5
})
sub.subscription_id = result.subscription.id
sub.save()
return redirect("hc-subscription-status")
ctx = {
"page": "pricing",
"client_token": braintree.ClientToken.generate()
}
return render(request, "payments/create_subscription.html", ctx)
@login_required
def status(request):
setup_braintree()
sub = Subscription.objects.get(user=request.user)
subscription = braintree.Subscription.find(sub.subscription_id)
ctx = {
"page": "pricing",
"subscription": subscription
}
return render(request, "payments/status.html", ctx)

+ 4
- 1
hc/settings.py View File

@ -20,6 +20,7 @@ SECRET_KEY = "---"
DEBUG = True
ALLOWED_HOSTS = []
DEFAULT_FROM_EMAIL = '[email protected]'
USE_PAYMENTS = False
INSTALLED_APPS = (
@ -35,7 +36,8 @@ INSTALLED_APPS = (
'hc.accounts',
'hc.api',
'hc.front'
'hc.front',
'hc.payments'
)
MIDDLEWARE_CLASSES = (
@ -62,6 +64,7 @@ TEMPLATES = [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'hc.payments.context_processors.payments'
],
},
},


+ 1
- 0
hc/urls.py View File

@ -6,4 +6,5 @@ urlpatterns = [
url(r'^accounts/', include('hc.accounts.urls')),
url(r'^', include('hc.api.urls')),
url(r'^', include('hc.front.urls')),
url(r'^', include('hc.payments.urls')),
]

+ 4
- 0
templates/base.html View File

@ -20,7 +20,9 @@
<link rel="stylesheet" href="{% static 'css/my_checks.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/my_checks_mobile.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/my_checks_desktop.css' %}" type="text/css">
{% if USE_PAYMENTS %}
<link rel="stylesheet" href="{% static 'css/pricing.css' %}" type="text/css">
{% endif %}
<link rel="stylesheet" href="{% static 'css/syntax.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/channels.css' %}" type="text/css">
<link rel="stylesheet" href="{% static 'css/channel_checks.css' %}" type="text/css">
@ -80,9 +82,11 @@
{% endif %}
{% if USE_PAYMENTS %}
<li {% if page == 'pricing' %} class="active" {% endif %}>
<a href="{% url 'hc-pricing' %}">Pricing</a>
</li>
{% endif %}
<li {% if page == 'docs' %} class="active" {% endif %}>
<a href="{% url 'hc-docs' %}">Docs</a>


+ 23
- 0
templates/payments/create_subscription.html View File

@ -0,0 +1,23 @@
{% extends "base.html" %}
{% load staticfiles %}
{% block title %}Pricing - It's Free! - healthchecks.io{% endblock %}
{% block content %}
<form id="checkout" method="post" action="{% url 'hc-create-subscription' %}">
{% csrf_token %}
<div id="payment-form"></div>
<input class="btn" type="submit" value="Set Up Subscription">
</form>
<script src="https://js.braintreegateway.com/v2/braintree.js"></script>
<script>
var clientToken = "{{ client_token }}";
braintree.setup(clientToken, "dropin", {
container: "payment-form"
});
</script>
{% endblock %}

templates/front/pricing.html → templates/payments/pricing.html View File


+ 39
- 0
templates/payments/status.html View File

@ -0,0 +1,39 @@
{% extends "base.html" %}
{% load staticfiles %}
{% block title %}Pricing - It's Free! - healthchecks.io{% endblock %}
{% block content %}
<h1>Subscription Status</h1>
<dl>
<dt>Status</dt>
<dd>{{ subscription.status }}</dd>
<dt>Next Billing Date:</dt>
<dd>{{ subscription.next_billing_date }}</dd>
<dt>Amount</dt>
<dd>{{ subscription.price }} / Month</dd>
</dl>
<h2>Transactions</h2>
<table class="table">
<tr>
<th>Date</th>
<th>Amount</th>
</tr>
{% for tx in subscription.transactions %}
<tr>
<td>???</td>
<td>{{ tx.amount }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}

Loading…
Cancel
Save