forked from GithubBackups/healthchecks
Braintree integration WIP.
This commit is contained in:
parent
53edb555dc
commit
263f50058e
@ -16,6 +16,13 @@ class Subscription(models.Model):
|
||||
|
||||
return self._sub
|
||||
|
||||
def _get_braintree_payment_method(self):
|
||||
if not hasattr(self, "_pm"):
|
||||
print("getting payment method over network")
|
||||
self._pm = braintree.PaymentMethod.find(self.payment_method_token)
|
||||
|
||||
return self._pm
|
||||
|
||||
def is_active(self):
|
||||
if not self.subscription_id:
|
||||
return False
|
||||
@ -30,3 +37,23 @@ class Subscription(models.Model):
|
||||
def next_billing_date(self):
|
||||
o = self._get_braintree_sub()
|
||||
return o.next_billing_date
|
||||
|
||||
def pm_is_credit_card(self):
|
||||
return isinstance(self._get_braintree_payment_method(),
|
||||
braintree.credit_card.CreditCard)
|
||||
|
||||
def pm_is_paypal(self):
|
||||
return isinstance(self._get_braintree_payment_method(),
|
||||
braintree.paypal_account.PayPalAccount)
|
||||
|
||||
def card_type(self):
|
||||
o = self._get_braintree_payment_method()
|
||||
return o.card_type
|
||||
|
||||
def last_4(self):
|
||||
o = self._get_braintree_payment_method()
|
||||
return o.last_4
|
||||
|
||||
def paypal_email(self):
|
||||
o = self._get_braintree_payment_method()
|
||||
return o.email
|
||||
|
@ -19,4 +19,8 @@ urlpatterns = [
|
||||
views.cancel_plan,
|
||||
name="hc-cancel-plan"),
|
||||
|
||||
url(r'^pricing/get_client_token/$',
|
||||
views.get_client_token,
|
||||
name="hc-get-client-token"),
|
||||
|
||||
]
|
||||
|
@ -1,6 +1,8 @@
|
||||
import braintree
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib import messages
|
||||
from django.http import JsonResponse
|
||||
from django.shortcuts import redirect, render
|
||||
from django.views.decorators.http import require_POST
|
||||
|
||||
@ -17,32 +19,55 @@ def setup_braintree():
|
||||
braintree.Configuration.configure(settings.BRAINTREE_ENV, **kw)
|
||||
|
||||
|
||||
@login_required
|
||||
def get_client_token(request):
|
||||
sub = Subscription.objects.get(user=request.user)
|
||||
client_token = braintree.ClientToken.generate({
|
||||
"customer_id": sub.customer_id
|
||||
})
|
||||
|
||||
return JsonResponse({"client_token": client_token})
|
||||
|
||||
|
||||
def pricing(request):
|
||||
setup_braintree()
|
||||
|
||||
try:
|
||||
sub = Subscription.objects.get(user=request.user)
|
||||
except Subscription.DoesNotExist:
|
||||
sub = Subscription(user=request.user)
|
||||
sub.save()
|
||||
sub = None
|
||||
if request.user.is_authenticated():
|
||||
try:
|
||||
sub = Subscription.objects.get(user=request.user)
|
||||
except Subscription.DoesNotExist:
|
||||
sub = Subscription(user=request.user)
|
||||
sub.save()
|
||||
|
||||
ctx = {
|
||||
"page": "pricing",
|
||||
"sub": sub,
|
||||
"client_token": braintree.ClientToken.generate()
|
||||
"sub": sub
|
||||
}
|
||||
|
||||
return render(request, "payments/pricing.html", ctx)
|
||||
|
||||
|
||||
def log_and_bail(request, result):
|
||||
for error in result.errors.deep_errors:
|
||||
messages.error(request, error.message)
|
||||
|
||||
return redirect("hc-pricing")
|
||||
|
||||
|
||||
@login_required
|
||||
@require_POST
|
||||
def create_plan(request):
|
||||
price = int(request.POST["price"])
|
||||
assert price in (2, 5, 10, 15, 20, 25, 50, 100)
|
||||
|
||||
setup_braintree()
|
||||
sub = Subscription.objects.get(user=request.user)
|
||||
if not sub.customer_id:
|
||||
result = braintree.Customer.create({})
|
||||
assert result.is_success
|
||||
if not result.is_success:
|
||||
return log_and_bail(request, result)
|
||||
|
||||
sub.customer_id = result.customer.id
|
||||
sub.save()
|
||||
|
||||
@ -51,19 +76,22 @@ def create_plan(request):
|
||||
"customer_id": sub.customer_id,
|
||||
"payment_method_nonce": request.POST["payment_method_nonce"]
|
||||
})
|
||||
assert result.is_success
|
||||
|
||||
if not result.is_success:
|
||||
return log_and_bail(request, result)
|
||||
|
||||
sub.payment_method_token = result.payment_method.token
|
||||
sub.save()
|
||||
|
||||
price = int(request.POST["price"])
|
||||
assert price in (2, 5, 10, 15, 20, 25, 50, 100)
|
||||
|
||||
result = braintree.Subscription.create({
|
||||
"payment_method_token": sub.payment_method_token,
|
||||
"plan_id": "P%d" % price,
|
||||
"price": price
|
||||
})
|
||||
|
||||
if not result.is_success:
|
||||
return log_and_bail(request, result)
|
||||
|
||||
sub.subscription_id = result.subscription.id
|
||||
sub.save()
|
||||
|
||||
|
@ -107,4 +107,19 @@
|
||||
|
||||
#subscription-status form {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
#payment-method-modal .modal-header {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
#payment-method-modal .modal-footer {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
|
||||
.error-message {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,15 +43,14 @@ $(function () {
|
||||
|
||||
});
|
||||
|
||||
$("#pww-create-payment-method").click(function(){
|
||||
var $modal = $("#payment-method-modal");
|
||||
var clientToken = $modal.attr("data-client-token");
|
||||
|
||||
braintree.setup(clientToken, "dropin", {
|
||||
container: "payment-form"
|
||||
});
|
||||
|
||||
$modal.modal("show");
|
||||
$("#pww-create-payment-method").click(function() {
|
||||
$.getJSON("/pricing/get_client_token/", function(data) {
|
||||
var $modal = $("#payment-method-modal");
|
||||
braintree.setup(data.client_token, "dropin", {
|
||||
container: "payment-form"
|
||||
});
|
||||
$modal.modal("show");
|
||||
})
|
||||
});
|
||||
|
||||
});
|
@ -8,17 +8,38 @@
|
||||
<!-- Plans -->
|
||||
<section id="plans">
|
||||
<div class="container">
|
||||
{% if messages %}
|
||||
<div class="alert alert-danger">
|
||||
<p>
|
||||
<strong>We're sorry!</strong> There was a problem setting
|
||||
up the subscription. Response from payment processor:</p>
|
||||
|
||||
{% for message in messages %}
|
||||
<p class="error-message">{{ message }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if sub.is_active %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="subscription-status" class="jumbotron">
|
||||
<p>
|
||||
You are currently paying <strong>${{ sub.price }}/month</strong>.
|
||||
Next billing date will be {{ sub.next_billing_date }}.</p>
|
||||
You are currently paying <strong>${{ sub.price }}/month</strong>
|
||||
|
||||
{% if sub.pm_is_credit_card %}
|
||||
using {{ sub.card_type }} card
|
||||
ending with {{ sub.last_4 }}.
|
||||
{% endif %}
|
||||
|
||||
{% if sub.pm_is_paypal %}
|
||||
using PayPal account {{ sub.paypal_email }}.
|
||||
{% endif %}
|
||||
</p>
|
||||
<p>
|
||||
Next billing date will be {{ sub.next_billing_date }}.
|
||||
Thank you for supporting healthchecks.io!
|
||||
</p>
|
||||
<a class="btn btn-default" href="#">Update Payment Method</a>
|
||||
<form method="post" action="{% url 'hc-cancel-plan' %}">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-default">
|
||||
@ -125,22 +146,9 @@
|
||||
</button>
|
||||
</form>
|
||||
{% else %}
|
||||
{% if sub.payment_method_token %}
|
||||
<form method="post" action="{% url 'hc-create-plan' %}">
|
||||
{% csrf_token %}
|
||||
<input class="selected-price" type="hidden" name="price" value="10" />
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-lg btn-default">
|
||||
Select (direct)
|
||||
</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<button
|
||||
id="pww-create-payment-method"
|
||||
class="btn btn-lg btn-default">Select (form)</button>
|
||||
{% endif %}
|
||||
|
||||
class="btn btn-lg btn-default">Select</button>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<a class="btn btn-lg btn-primary" href="{% url 'hc-login' %}">Get Started</a>
|
||||
|
Loading…
x
Reference in New Issue
Block a user