diff --git a/rowers/forms.py b/rowers/forms.py index 05fc77a8..0994a61e 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -18,7 +18,11 @@ from django.forms import formset_factory from utils import landingpages from metrics import axes - +# Braintree form +class BrainTreeForm(forms.Form): + amount = forms.FloatField(required=True) + payment_method_nonce = forms.CharField(max_length=255) + # login form class LoginForm(forms.Form): diff --git a/rowers/templates/payments.html b/rowers/templates/payments.html new file mode 100644 index 00000000..4cc0b8f1 --- /dev/null +++ b/rowers/templates/payments.html @@ -0,0 +1,295 @@ + +{% extends "newbase.html" %} +{% block title %}Rowsandall Pro Membership{% endblock title %} +{% block main %} +{% load rowerfilters %} + +

Payments

+ +
    +
  • +

    Donations are welcome to keep this web site going. To help cover the hosting + costs, I have created several paid plans offering advanced functionality. + Once I process your + donation, I will give you access to some special features on this + website.

    + +

    The following table gives an overview of the different plans. As we are + constantly developing new functionality, the table might be slightly outdated. Don't + hesitate to contact us.

    + +

    The Pro membership is open for a free 14 day trial

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     BASICPROSELF-COACHCOACH
    Basic rowing metrics (spm, time, distance, heart rate, power)✔✔✔✔
    Manual Import, Export, Synchronization and download of all your data✔✔✔✔
    Automatic Synchronization with other fitness sites ✔✔✔
    Heart rate and power zones✔✔✔✔
    Ranking Pieces, Stroke Analysis✔✔✔✔
    Advanced Analysis (Critical Power, Stats, Box Chart, Trend Flex) ✔✔✔
    Compare Workouts ✔✔✔
    Empower Stroke Profile ✔✔✔
    Sensor Fusion, Split Workout, In-stroke metrics ✔✔✔
    Create Training plans, tests and challenges for yourself. Track your performance + against plan.  ✔✔
    Create Training plans, tests and challenges for your athletes. Track their performance + against plan.    ✔
    Create and manage teams.   ✔
    Manage your athlete's workouts   ✔
    +

    +

    Coach and Self-Coach Membership

    + +

    The Coach plan functionality listed is available to the coach only. Individual athletes + can purchase upgrades to "Pro" and "Self-Coach" plans. +

    + +

    Rowsandall.com's Training Planning functionality + is part of the paid "Self-Coach" and "Coach" plans.

    + +

    On the "Self-Coach" plan, you can plan your own sessions.

    + +

    On the "Coach" plan, you can establish teams, see workouts done by + athletes on your team, and plan individual and group sessions for your + athletes. +

    + +

    If you would like to find a coach who helps you plan your training + through rowsandall.com, contact me throught the contact form.

    + + {% if user.rower.rowerplan == 'basic' and user.rower.protrialexpires|date_dif == 1 %} +

    Free Trial

    +

    + You qualify for a 14 day free trial. No credit card needed. + Try out Pro or Self-Coach membership for two weeks. Click the button below to + sign up for the trial. After your trial period expires, you will be + automatically reset to the Basic plan, unless you upgrade to Pro. +

    +

    Yes, I want to try Pro membership for 14 days for free. No strings attached.

    +

    Yes, I want to try Self-Coach membership for 14 days for free. No strings attached.

    + {% endif %} +
  • +
  • +

    Click on the PayPal button to pay for your Pro membership. Before you pay, please register for the free Basic membership and add your user name to the form. + Your payment will be valid for one year. + You will be taken to the secure PayPal payment site. +

    +

    Recurring Payment

    +

    You need a Paypal account for this. This is plan will automatically renew each year.

    +

    +

    + + + + + + + + + + + + + + + +
    + Plans +
    + +
    + Your User Name +
    + +
    + + + +
    +

    +

    One Year Subscription

    +

    Only a credit card needed. Will not automatically renew

    + +

    +

    + + + + + +
    Plans
    Your User Name
    + + + +
    +

    +

    Payment Processing

    +

    After you do the payment, we will manually change your membership to + "Pro". Depending on our availability, this may take some time + (typically one working day). Don't hesitate to contact us + if you have any questions at this stage.

    + +

    If, for any reason, you are not happy with your Pro membership, please let me know through the contact form. I will contact you as soon as possible to discuss how we can make things better.

    + +

    BrainTree Experimental Corner

    + +
    +
    + + +
    +
    +
    +
    + + + {% csrf_token %} + +
    + + + + +
  • +
+ + +{% endblock %} + +{% block sidebar %} +{% include 'menu_help.html' %} +{% endblock %} + +{% block scripts %} +{% endblock %} + diff --git a/rowers/templates/promembership.html b/rowers/templates/promembership.html index 201d3044..391d9f51 100644 --- a/rowers/templates/promembership.html +++ b/rowers/templates/promembership.html @@ -232,6 +232,7 @@ if you have any questions at this stage.

If, for any reason, you are not happy with your Pro membership, please let me know through the contact form. I will contact you as soon as possible to discuss how we can make things better.

+ diff --git a/rowers/urls.py b/rowers/urls.py index 242c07b4..ee3aa1ce 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -437,6 +437,8 @@ urlpatterns = [ url(r'^analysis/$', views.analysis_view,name='analysis'), url(r'^laboratory/$', views.laboratory_view,name='laboratory'), url(r'^promembership', TemplateView.as_view(template_name='promembership.html'),name='promembership'), + url(r'^checkouts',views.checkouts_view,name='checkouts'), + url(r'^payments',views.payments_view,name='payments'), url(r'^planrequired',views.planrequired_view), url(r'^starttrial$',views.start_trial_view), url(r'^startplantrial$',views.start_plantrial_view), diff --git a/rowers/views.py b/rowers/views.py index 8a32085c..de29e3f2 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -28,6 +28,7 @@ import isodate import re import cgi from icalendar import Calendar, Event +import braintree from django.shortcuts import render from django.template.loader import render_to_string @@ -50,7 +51,7 @@ from rowers.forms import ( RaceResultFilterForm,PowerIntervalUpdateForm,FlexAxesForm, FlexOptionsForm,DataFrameColumnsForm,OteWorkoutTypeForm, MetricsForm,DisqualificationForm,disqualificationreasons, - disqualifiers,SearchForm, + disqualifiers,SearchForm,BrainTreeForm ) from django.core.urlresolvers import reverse, reverse_lazy @@ -139,6 +140,7 @@ from rowsandall_app.settings import ( UNDERARMOUR_CLIENT_SECRET,UNDERARMOUR_CLIENT_KEY, RUNKEEPER_CLIENT_ID,RUNKEEPER_REDIRECT_URI,RUNKEEPER_CLIENT_SECRET, TP_CLIENT_ID,TP_REDIRECT_URI,TP_CLIENT_KEY,TP_CLIENT_SECRET, + BRAINTREE_MERCHANT_ID,BRAINTREE_PUBLIC_KEY,BRAINTREE_PRIVATE_KEY ) from rowers.tasks_standalone import addcomment2 @@ -1027,6 +1029,87 @@ def add_defaultfavorites(r): f.save() return 1 +# Experimental - Payments +@login_required() +def payments_view(request): + + r = getrequestrower(request) + + gateway = braintree.BraintreeGateway( + braintree.Configuration( + braintree.Environment.Sandbox, + merchant_id=BRAINTREE_MERCHANT_ID, + public_key=BRAINTREE_PUBLIC_KEY, + private_key=BRAINTREE_PRIVATE_KEY, + ) + ) + + # add code to store customer_id + + client_token = gateway.client_token.generate({ + "customer_id": r.id, + }) + + return render(request, + "payments.html", + { + 'client_token':client_token, + }) + + +@login_required() +def checkouts_view(request): + + r = getrequestrower(request) + + if request.method != 'POST': + url = reverse(payments_view) + return HttpResponseRedirect(url) + + # we're still here + gateway = braintree.BraintreeGateway( + braintree.Configuration( + braintree.Environment.Sandbox, + merchant_id=BRAINTREE_MERCHANT_ID, + public_key=BRAINTREE_PUBLIC_KEY, + private_key=BRAINTREE_PRIVATE_KEY, + ) + ) + + form = BrainTreeForm(request.POST) + if form.is_valid(): + nonce_from_the_client = form.cleaned_data['payment_method_nonce'] + amount = form.cleaned_data['amount'] + amount = str(amount) + + result = gateway.transaction.sale({ + "amount": amount, + "payment_method_nonce": nonce_from_the_client, + "options": { + "submit_for_settlement": True + } + }) + if result.is_success: + transaction = result.transaction + amount = transaction.amount + messages.info(request, + "We have successfully received your payment of {amount} Euro".format( + amount=amount + ) + ) + else: + messages.error(request,"We are sorry but there was an error with the payment") + url = reverse(payments_view) + return HttpResponseRedirect(url) + + else: + messages.error(request,"There was an error in the payment form") + url = reverse(payments_view) + return HttpResponseRedirect(url) + + url = reverse(payments_view) + return HttpResponseRedirect(url) + # User registration def rower_register_view(request): diff --git a/rowsandall_app/settings.py b/rowsandall_app/settings.py index 93bfb4a4..61484bbf 100644 --- a/rowsandall_app/settings.py +++ b/rowsandall_app/settings.py @@ -421,3 +421,20 @@ try: except KeyError: workoutemailbox = 'workouts@rowsandall.com' + +# payments + +try: + BRAINTREE_MERCHANT_ID = CFG['braintree_merchant_id'] +except KeyError: + BRAINTREE_MERCHANT_ID = '' + +try: + BRAINTREE_PUBLIC_KEY = CFG['braintree_public_key'] +except KeyError: + BRAINTREE_PUBLIC_KEY = '' + +try: + BRAINTREE_PRIVATE_KEY = CFG['braintree_private_key'] +except KeyError: + BRAINTREE_PRIVATE_KEY = ''