Private
Public Access
1
0

buy now flow complete except email confirmation

This commit is contained in:
Sander Roosendaal
2018-12-19 17:23:34 +01:00
parent fa61957be7
commit d70725f2b3
12 changed files with 512 additions and 113 deletions

View File

@@ -1,4 +1,6 @@
import braintree import braintree
from django.utils import timezone
import datetime
from rowsandall_app.settings import ( from rowsandall_app.settings import (
BRAINTREE_MERCHANT_ID,BRAINTREE_PUBLIC_KEY,BRAINTREE_PRIVATE_KEY BRAINTREE_MERCHANT_ID,BRAINTREE_PUBLIC_KEY,BRAINTREE_PRIVATE_KEY
@@ -16,8 +18,8 @@ gateway = braintree.BraintreeGateway(
from rowers.models import Rower,PaidPlan from rowers.models import Rower,PaidPlan
from rowers.utils import ProcessorCustomerError from rowers.utils import ProcessorCustomerError
def create_customer(rower): def create_customer(rower,force=False):
if not rower.customer_id: if not rower.customer_id or force:
result = gateway.customer.create( result = gateway.customer.create(
{ {
'first_name':rower.user.first_name, 'first_name':rower.user.first_name,
@@ -28,14 +30,25 @@ def create_customer(rower):
raise ProcessorCustomerError raise ProcessorCustomerError
else: else:
rower.customer_id = result.customer.id rower.customer_id = result.customer.id
rower.paymentprocessor = 'braintree'
rower.save() rower.save()
return rower.customer_id
else: else:
return rower.customer_id return rower.customer_id
def get_client_token(rower): def get_client_token(rower):
client_token = gateway.client_token.generate({ try:
"customer_id":rower.customer_id, client_token = gateway.client_token.generate({
"customer_id":rower.customer_id,
}) })
except ValueError:
customer_id = create_customer(rower,force=True)
client_token = gateway.client_token.generate({
"customer_id": customer_id,
})
return client_token return client_token
@@ -51,3 +64,125 @@ def get_plans_costs():
plan.save() plan.save()
return plans return plans
def make_payment(rower,data):
nonce_from_the_client = data['payment_method_nonce']
amount = 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
return amount
else:
return 0,''
def create_subscription(rower,data):
planid = data['plan']
plan = PaidPlan.objects.get(id=planid)
nonce_from_the_client = data['payment_method_nonce']
amount = data['amount']
# create or find payment method
result = gateway.payment_method.create({
"customer_id": rower.customer_id,
"payment_method_nonce": nonce_from_the_client
})
if result.is_success:
payment_method_token = result.payment_method.token
else:
return False
result = gateway.subscription.create({
"payment_method_token": payment_method_token,
"plan_id": plan.external_id
})
if result.is_success:
rower.paidplan = plan
rower.planexpires = timezone.now()+datetime.timedelta(days=365)
rower.teamplanexpires = timezone.now()+datetime.timedelta(days=365)
rower.clubsize = plan.clubsize
rower.paymenttype = plan.paymenttype
rower.rowerplan = plan.shortname
rower.save()
return True
else:
return False
return False
def cancel_subscription(rower,id):
themessages = []
errormessages = []
try:
result = gateway.subscription.cancel(id)
messages.append("Subscription canceled")
except:
errormessages.append("We could not find the subscription record in our customer database")
return False, themessages, errormessages
rower.paidplan = None
rower.teamplanexpires = timezone.now()
rower.planexpires = timezone.now()
rower.clubsize = 0
rower.rowerplan = 'basic'
rower.save()
themessages.append("Your plan was reset to basic")
return True, themessages,errormessages
def find_subscriptions(rower):
try:
result = gateway.customer.find(rower.customer_id)
except:
raise ProcessorCustomerError("We could not find the customer in the database")
active_subscriptions = []
cards = result.credit_cards
for card in cards:
for subscription in card.subscriptions:
if subscription.status == 'Active':
active_subscriptions.append(subscription)
try:
paypal_accounts = result.paypal_accounts
for account in accuonts:
for subscription in account.subscriptions:
if subscription.status == 'Active':
active_subscriptions.append(subscription)
except AttributeError:
pass
result = []
for subscription in active_subscriptions:
plan = PaidPlan.objects.filter(paymentprocessor="braintree",
external_id=subscription.plan_id)[0]
thedict = {
'end_date': subscription.billing_period_end_date,
'plan_id': subscription.plan_id,
'price': subscription.price,
'id': subscription.id,
'plan': plan.name
}
result.append(thedict)
return result

View File

@@ -22,7 +22,8 @@ from metrics import axes
# BillingForm form # BillingForm form
class BillingForm(forms.Form): class BillingForm(forms.Form):
amount = forms.FloatField(required=True) amount = forms.FloatField(required=True)
payment_method_nonce = forms.CharField(max_length=255) plan = forms.IntegerField(widget=forms.HiddenInput())
payment_method_nonce = forms.CharField(max_length=255,required=True)
# login form # login form

View File

@@ -558,7 +558,7 @@ paymentprocessors = (
class PaidPlan(models.Model): class PaidPlan(models.Model):
shortname = models.CharField(max_length=50,choices=plans) shortname = models.CharField(max_length=50,choices=plans)
name = models.CharField(max_length=200) name = models.CharField(max_length=200)
external_id = models.IntegerField(blank=True,null=True,default=None) external_id = models.CharField(blank=True,null=True,default=None,max_length=200)
price = models.FloatField(blank=True,null=True,default=None) price = models.FloatField(blank=True,null=True,default=None)
paymentprocessor = models.CharField( paymentprocessor = models.CharField(
max_length=50,choices=paymentprocessors,default='braintree') max_length=50,choices=paymentprocessors,default='braintree')
@@ -633,7 +633,8 @@ class Rower(models.Model):
) )
paymentprocessor = models.CharField(max_length=50, paymentprocessor = models.CharField(max_length=50,
choices=paymentprocessors, choices=paymentprocessors,
default='braintree') null=True,blank=True,
default=None)
paidplan = models.ForeignKey(PaidPlan,null=True,default=None) paidplan = models.ForeignKey(PaidPlan,null=True,default=None)

View File

@@ -28,7 +28,7 @@ def setrowerplans():
print 'Could not set plan for ',r print 'Could not set plan for ',r
def is_existing_customer(rower): def is_existing_customer(rower):
if rower.country is not None and rower.customer_id is not None and r.country != '': if rower.country is not None and rower.customer_id is not None and rower.country != '':
return True return True
return False return False

View File

@@ -31,6 +31,6 @@
{% endblock %} {% endblock %}
{% block sidebar %} {% block sidebar %}
{% include 'menu_help.html' %} {% include 'menu_profile.html' %}
{% endblock %} {% endblock %}

View File

@@ -0,0 +1,26 @@
{% extends "newbase.html" %}
{% block title %}Rowsandall Paid Membership{% endblock title %}
{% load rowerfilters %}
{% block main %}
<h1>Your Payment was completed</h1>
<p>
Thank you for registering to {{ user.rower.paidplan.name }}. You have paid for 12 months
membership.
</p>
<p>
{% if user.rower.paymenttype == 'recurring' %}
Your next payment will be automatically processed on {{ user.rower.planexpires }}
{% else %}
Your plan will end automatically on {{ user.rower.planexpires }}
{% endif %}
</p>
{% endblock %}
{% block sidebar %}
{% include 'menu_profile.html' %}
{% endblock %}

View File

@@ -0,0 +1,113 @@
{% extends "newbase.html" %}
{% block title %}Rowsandall Paid Membership{% endblock title %}
{% load rowerfilters %}
{% block main %}
<h1>Confirm Your Payment</h1>
<h2>Order Overview</h2>
<ul class="main-content">
<li class="grid_2">
<p>
<table class="plantable shortpadded" width="80%">
<tbody>
<tr>
<th>Plan</th><td>{{ plan.name }}</td>
</tr>
<tr>
<th>Payment Type</th><td>{{ plan.paymenttype }}</td>
</tr>
<tr>
<th>Plan Duration</th><td>1 year starting today</td>
</tr>
<tr>
<th>Total</th><td>&euro; {{ plan.price|currency }}
{% if plan.paymenttype == 'recurring' %}
/year
{% endif %}
</td>
</tr>
</tbody>
</table>
</p>
<p>
<table class="plantable shortpadded" width="80%">
<tbody>
<tr>
<th>Street Address</th><td>{{ user.rower.street_address }}</td>
</tr>
<tr>
<th>City</th><td>{{ user.rower.city }}</td>
</tr>
<tr>
<th>Posstal Code</th><td>{{ user.rower.postal_code }}</td>
</tr>
<tr>
<th>Country</th><td>{{ user.rower.country }}
</td>
</tr>
</tbody>
</table>
</p>
</li>
<li class="grid_2">
<p>
<a href="/rowers/billing">Change Order</a>
</li>
<li class="grid_4">
<form id="payment-form" method="post" action="/rowers/checkouts"
autocomplete="off">
<section>
<label for="amount">
<div class="input-wrapper amount-wrapper">
<input id="amount" name="amount" type="hidden" min="1" placeholder="Amount"
value="{{ plan.price }}" readonly>
</div>
</label>
<div class="bt-drop-in-wrapper">
<div id="bt-dropin"></div>
</div>
</section>
<input type="hidden" id="nonce" name="payment_method_nonce" />
<input type="hidden" id="plan" name="plan" value="{{ plan.id }}">
{% csrf_token %}
<button type="submit" id="submit-button"><span>Pay &euro; {{ plan.price|currency }}</span></button>
</form>
</li>
</ul>
<script src="https://js.braintreegateway.com/web/dropin/1.14.1/js/dropin.min.js"></script>
<script>
var form = document.querySelector('#payment-form');
var client_token = '{{ client_token }}';
braintree.dropin.create({
authorization: client_token,
container: '#bt-dropin',
paypal: {
flow: 'checkout'
}
}, function (createErr, instance) {
form.addEventListener('submit', function (event) {
event.preventDefault();
instance.requestPaymentMethod(function (err, payload) {
if (err) {
console.log('Error', err);
return;
}
// Add the nonce to the form and submit
document.querySelector('#nonce').value = payload.nonce;
form.submit();
});
});
});
</script>
{% endblock %}
{% block sidebar %}
{% include 'menu_profile.html' %}
{% endblock %}

View File

@@ -14,7 +14,7 @@
<h2>Account Information</h2> <h2>Account Information</h2>
<p> <p>
{% if rower.user == user %} {% if rower.user == user %}
<a class="button blue small" href="/password_change/">Password Change</a> <a href="/password_change/">Password Change</a>
{% else %} {% else %}
&nbsp; &nbsp;
{% endif %} {% endif %}
@@ -34,29 +34,49 @@
{{ userform.as_table }} {{ userform.as_table }}
{{ accountform.as_table }} {{ accountform.as_table }}
<tr> <tr>
<th>Plan</th><td>{{ rower.rowerplan }}</td> <th>&nbsp;</th><td></td>
</tr> </tr>
<tr> <tr>
<th>Plan Expiry</th><td>{{ rower.planexpires }}</td> <th>Plan</th><td>{{ rower.paidplan.name }}</td>
</tr> </tr>
{% if rower.rowerplan != 'basic' %}
<tr>
<th>
{% if rower.paymenttype != 'recurring' %}
Plan Expiry
{% else %}
Next Payment Due
{% endif %}
</th><td>{{ rower.planexpires }}</td>
</tr>
{% endif %}
</table> </table>
{% csrf_token %} {% csrf_token %}
{% if rower.rowerplan == 'basic' and rower.user == user %} {% if rower.rowerplan != 'coach' and rower.user == user %}
<a class="button blue" href="/rowers/promembership">Upgrade</a> <p>
<a href="/rowers/paidplans">Upgrade</a>
</p>
{% else %} {% else %}
&nbsp; <p>
&nbsp;
</p>
{% endif %} {% endif %}
<input class="button green" type="submit" value="Save"> {% if rower.rowerplan != 'basic' and rower.user == user %}
<p>
<a href="/rowers/me/cancelsubscriptions">Cancel Subscription</a>
</p>
{% endif %}
<input type="submit" value="Save">
</form> </form>
</li> </li>
{% if rower.user == user %} {% if rower.user == user %}
<li class="grid_2"> <li class="grid_2">
<h2>GDPR - Data Protection</h2> <h2>GDPR - Data Protection</h2>
<p> <p>
<a class="button blue small" href="/rowers/exportallworkouts">Download your data</a> <a href="/rowers/exportallworkouts">Download your data</a>
</p> </p>
<p> <p>
<a class="button blue small" href="/rowers/me/deactivate">Deactivate Account</a> <a href="/rowers/me/deactivate">Deactivate Account</a>
</p> </p>
<p> <p>
<a class="button red small" href="/rowers/me/delete">Delete Account</a> <a class="button red small" href="/rowers/me/delete">Delete Account</a>
@@ -79,7 +99,7 @@
<td>{{ grant.application }}</td> <td>{{ grant.application }}</td>
<td>{{ grant.scope }}</td> <td>{{ grant.scope }}</td>
<td> <td>
<a class="button red small" href="/rowers/me/revokeapp/{{ grant.application.id }}">Revoke</a> <a href="/rowers/me/revokeapp/{{ grant.application.id }}">Revoke</a>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@@ -0,0 +1,64 @@
{% extends "newbase.html" %}
{% block title %}Rowsandall Paid Membership{% endblock title %}
{% load rowerfilters %}
{% block main %}
<h1>Cancel Subscriptions</h1>
<ul class="main-content">
<li class="grid_4">
{% if subscriptions %}
<p>
<table class="plantable shortpadded" width="80%">
<thead>
<tr>
<th>Subscription</th><th>Next Billing Date</th><th>Price</th><th>&nbsp;</th>
</tr>
</thead>
<tbody>
{% for subscription in subscriptions %}
<tr>
<td>
{{ subscription|lookup:"plan" }}
</td>
<td>
{{ subscription|lookup:"end_date" }}
</td>
<td>
{{ subscription|lookup:"price" }} &euro;
</td>
<td>
<a href="/rowers/me/cancelsubscription/{{ subscription|lookup:'id' }}">Stop this plan</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<p>
<p>
By clicking on the link to stop the plan, you will downgrade to the Basic plan.
Future payments will be stopped.
</p>
{% else %}
<p>
You don't have any subscriptions or your subscriptions cannot be automatically stopped
from the site.
</p>
<p>
If you have paid through PayPal, log in to your PayPal account and cancel the recurring payment
there. We will manually downgrade your subscription.
</p>
<p>
If you have questions, don't hesitate to contact us.
</p>
{% endif %}
</li>
</ul>
{% endblock %}
{% block sidebar %}
{% include 'menu_profile.html' %}
{% endblock %}

View File

@@ -125,7 +125,16 @@ def c2userid(user):
c2userid = c2stuff.get_userid(thetoken) c2userid = c2stuff.get_userid(thetoken)
return c2userid return c2userid
@register.filter
def currency(word):
try:
amount = float(word)
except ValueError:
return word
return '{amount:.2f}'.format(amount=amount)
@register.filter @register.filter
def rkuserid(user): def rkuserid(user):
try: try:

View File

@@ -438,10 +438,13 @@ urlpatterns = [
url(r'^analysis/$', views.analysis_view,name='analysis'), url(r'^analysis/$', views.analysis_view,name='analysis'),
url(r'^laboratory/$', views.laboratory_view,name='laboratory'), url(r'^laboratory/$', views.laboratory_view,name='laboratory'),
url(r'^promembership', TemplateView.as_view(template_name='promembership.html'),name='promembership'), url(r'^promembership', TemplateView.as_view(template_name='promembership.html'),name='promembership'),
url(r'^checkout/(?P<planid>\d+)$',views.payment_confirm_view),
url(r'^billing',views.billing_view,name='billing'), url(r'^billing',views.billing_view,name='billing'),
url(r'^paymentcompleted',views.payment_completed_view),
url(r'^paidplans',views.paidplans_view,name='paidplans'), url(r'^paidplans',views.paidplans_view,name='paidplans'),
url(r'^me/cancelsubscriptions',views.plan_stop_view),
url(r'^me/cancelsubscription/(?P<id>[\w\ ]+.*)$',views.plan_tobasic_view),
url(r'^checkouts',views.checkouts_view,name='checkouts'), url(r'^checkouts',views.checkouts_view,name='checkouts'),
url(r'^payments',views.payments_view,name='payments'),
url(r'^planrequired',views.planrequired_view), url(r'^planrequired',views.planrequired_view),
url(r'^starttrial$',views.start_trial_view), url(r'^starttrial$',views.start_trial_view),
url(r'^startplantrial$',views.start_plantrial_view), url(r'^startplantrial$',views.start_plantrial_view),

View File

@@ -84,7 +84,7 @@ from rowers.models import (
createmicrofillers, createmesofillers, createmicrofillers, createmesofillers,
microcyclecheckdates,mesocyclecheckdates,macrocyclecheckdates, microcyclecheckdates,mesocyclecheckdates,macrocyclecheckdates,
TrainingMesoCycleForm, TrainingMicroCycleForm, TrainingMesoCycleForm, TrainingMicroCycleForm,
RaceLogo,RowerBillingAddressForm, RaceLogo,RowerBillingAddressForm,PaidPlan,
) )
from rowers.models import ( from rowers.models import (
RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm, RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm,
@@ -738,8 +738,27 @@ def deactivate_user(request):
if request.method == "POST": if request.method == "POST":
user_form = DeactivateUserForm(request.POST, instance=user) user_form = DeactivateUserForm(request.POST, instance=user)
if user_form.is_valid(): if user_form.is_valid():
r = Rower.objects.get(user=user)
if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree':
try:
subscriptions = braintreestuff.find_subscriptions(r)
for subscription in subscriptions:
success, themessages,errormessages = braintreestuff.cancel_subscription(r,id)
for message in themessages:
messages.info(request,message)
except ProcessorCustomerError:
pass
r.paidplan = None
r.teamplanexpires = timezone.now()
r.planexpires = timezone.now()
r.clubsize = 0
r.rowerplan = 'basic'
r.save()
deactivate_user = user_form.save(commit=False) deactivate_user = user_form.save(commit=False)
user.is_active = False user.is_active = False
user.save()
deactivate_user.save() deactivate_user.save()
# url = reverse(auth_views.logout_then_login) # url = reverse(auth_views.logout_then_login)
url = '/logout/?next=/login' url = '/logout/?next=/login'
@@ -790,7 +809,17 @@ def remove_user(request):
name = user.first_name+' '+user.last_name name = user.first_name+' '+user.last_name
email = user.email email = user.email
r = Rower.objects.get(user=user)
if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree':
try:
subscriptions = braintreestuff.find_subscriptions(r)
for subscription in subscriptions:
success, themessages,errormessages = braintreestuff.cancel_subscription(r,id)
for message in themessages:
messages.info(request,message)
except ProcessorCustomerError:
pass
if cd['delete_user']: if cd['delete_user']:
user.delete() user.delete()
res = myqueue(queuehigh, res = myqueue(queuehigh,
@@ -998,7 +1027,7 @@ def hasplannedsessions(user):
return result return result
from rowers.utils import isprorower from rowers.utils import isprorower,ProcessorCustomerError
# Check if a user is a Pro member # Check if a user is a Pro member
def ispromember(user): def ispromember(user):
@@ -1056,6 +1085,19 @@ def billing_view(request):
if planselectform.is_valid(): if planselectform.is_valid():
plan = planselectform.cleaned_data['plan'] plan = planselectform.cleaned_data['plan']
if billingaddressform.is_valid():
try:
customer_id = braintreestuff.create_customer(r)
except ProcessorCustomerError:
messages.error(request,"Something went wrong registering you as a customer.")
url = reverse(billing_view)
return HttpResponseRedirect(url)
url = reverse(payment_confirm_view,
kwargs={
'planid':plan.id
})
return HttpResponseRedirect(url)
else: else:
billingaddressform = RowerBillingAddressForm(instance=r) billingaddressform = RowerBillingAddressForm(instance=r)
planselectform = PlanSelectForm(paymentprocessor='braintree') planselectform = PlanSelectForm(paymentprocessor='braintree')
@@ -1067,50 +1109,66 @@ def billing_view(request):
'planselectform':planselectform, 'planselectform':planselectform,
}) })
# Experimental - Payments
@login_required() @login_required()
def payments_view(request): def plan_stop_view(request):
r = getrequestrower(request)
subscriptions = []
if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree':
try:
subscriptions = braintreestuff.find_subscriptions(r)
except ProcessorCustomerError:
r.paymentprocessor = None
r.save()
return render(request,
'subscriptions_cancel.html',
{'rower':r,
'subscriptions':subscriptions
})
@login_required()
def plan_tobasic_view(request,id=0):
r = getrequestrower(request)
if r.paidplan.paymentprocessor == 'braintree':
success, themessages,errormessages = braintreestuff.cancel_subscription(r,id)
for message in themessages:
messages.info(request,message)
for message in errormessages:
messages.error(request,message)
url = reverse(plan_stop_view)
return HttpResponseRedirect(url)
@login_required()
def payment_confirm_view(request,planid = 0):
try:
plan = PaidPlan.objects.get(id=planid)
except PaidPlan.DoesNotExist:
messages.error(request,"Something went wrong. Please try again.")
url = reverse(billing_view)
return HttpResponseRedirect(url)
r = getrequestrower(request) r = getrequestrower(request)
gateway = braintree.BraintreeGateway( client_token = braintreestuff.get_client_token(r)
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
if not r.customer_id:
result = gateway.customer.create(
{
'first_name':r.user.first_name,
'last_name':r.user.last_name,
'email':r.user.email,
})
if not result.is_success:
messages.error(request,'Failed to create customer. Please try again later')
return render(request,
"payments.html")
else:
r.customer_id = result.customer.id
r.save()
client_token = gateway.client_token.generate({
"customer_id": r.customer_id,
})
return render(request, return render(request,
"payments.html", "paymentconfirm.html",
{ {
'plan':plan,
'client_token':client_token, 'client_token':client_token,
'rower':r,
}) })
@login_required() @login_required()
def checkouts_view(request): def checkouts_view(request):
@@ -1118,72 +1176,41 @@ def checkouts_view(request):
r = getrequestrower(request) r = getrequestrower(request)
if request.method != 'POST': if request.method != 'POST':
url = reverse(payments_view) url = reverse(paidplans_view)
return HttpResponseRedirect(url) 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 = BillingForm(request.POST) form = BillingForm(request.POST)
if form.is_valid(): if form.is_valid():
nonce_from_the_client = form.cleaned_data['payment_method_nonce'] data = form.cleaned_data
amount = form.cleaned_data['amount'] success = braintreestuff.create_subscription(r,data)
amount = str(amount) if success:
messages.info(request,"Your payment has succeeded and your plan has been updated")
#for testing url = reverse(payment_completed_view)
#nonce_from_the_client = 'fake-processor-declined-visa-none'
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
if transaction.payment_instrument_type == "credit_card":
country = transaction.credit_card_details.country_of_issuance
if country == 'Unknown':
bin = transaction.credit_card_details.bin
url = "https://lookup.binlist.net/"+str(bin)
headers = {
'Accept-Version':'3',
}
binresult = requests.get(url,headers=headers)
print binresult.status_code
if binresult.status_code == 200:
js = binresult.json()
country = js['country']['name']
print country
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) return HttpResponseRedirect(url)
else:
messages.error(request,"There was a problem with your payment")
url = reverse(billing_view)
return HttpResponseRedirect(url)
else: else:
messages.error(request,"There was an error in the payment form") messages.error(request,"There was an error in the payment form")
url = reverse(payments_view) url = reverse(billing_view)
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
url = reverse(payments_view) url = reverse(payments_view)
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
@login_required()
def payment_completed_view(request):
r = getrequestrower(request)
return render(request,
"payment_completed.html",
{
'rower':r
})
# User registration # User registration
def rower_register_view(request): def rower_register_view(request):