Unglue.it would like to process your donation credit, but you are currently logged in as {{request.user.username}}. Your donation credit from {{nonprofit.name}} for ${{ envelope.amount }}.{{ envelope.cents }} is designated for {{ envelope.username }}. Do record your credit, you need to log out, and then log in as {{ envelope.username }}. If you have any problem, don't hesitate to contact unglue.it support.
+
Unglue.it would like to process your donation credit, but you are currently logged in as {{request.user.username}}. Your donation credit from {{nonprofit.name}} for ${{ envelope.amount }}.{{ envelope.cents }} is designated for {{ envelope.username }}. To record your credit, you need to log out, and then log in as {{ envelope.username }}. If you have any problem, don't hesitate to contact unglue.it support.
From dbacb5a96d58361e59db826c190ad7a3e2a58328 Mon Sep 17 00:00:00 2001
From: eric
Date: Sat, 13 Oct 2012 13:38:39 -0400
Subject: [PATCH 2/5] max_amount, not amount before the authorization
---
frontend/views.py | 2 +-
payment/manager.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/frontend/views.py b/frontend/views.py
index cc96ee37..75ad8337 100755
--- a/frontend/views.py
+++ b/frontend/views.py
@@ -798,8 +798,8 @@ class FundPledgeView(FormView):
# GOAL: deactivate any older accounts associated with user
# with the Account in hand, now authorize transaction
- transaction.amount = preapproval_amount
t, url = p.authorize(transaction)
+ self.transaction.max_amount = preapproval_amount
logger.info("t, url: {0} {1}".format(t, url))
# redirecting user to pledge_complete on successful preapproval (in the case of stripe)
diff --git a/payment/manager.py b/payment/manager.py
index c5d83f5d..b1b6e0fd 100644
--- a/payment/manager.py
+++ b/payment/manager.py
@@ -567,7 +567,7 @@ class PaymentManager( object ):
urllib.urlencode({'tid':transaction.id}))
return_url = urlparse.urljoin(settings.BASE_URL, return_path)
- p = transaction.get_payment_class().Preapproval(transaction, transaction.amount, expiry, return_url=return_url, paymentReason=paymentReason)
+ p = transaction.get_payment_class().Preapproval(transaction, transaction.max_amount, expiry, return_url=return_url, paymentReason=paymentReason)
# Create a response for this
envelope = p.envelope()
From 674637f61672f6d9196f0cff23f9d8f1b90fcc66 Mon Sep 17 00:00:00 2001
From: eric
Date: Sat, 13 Oct 2012 13:40:36 -0400
Subject: [PATCH 3/5] we weren't checking that request.user==transaction.user
---
frontend/templates/pledge_user_error.html | 29 +++++++++++++++++++++++
frontend/views.py | 4 ++++
2 files changed, 33 insertions(+)
create mode 100644 frontend/templates/pledge_user_error.html
diff --git a/frontend/templates/pledge_user_error.html b/frontend/templates/pledge_user_error.html
new file mode 100644
index 00000000..ae060302
--- /dev/null
+++ b/frontend/templates/pledge_user_error.html
@@ -0,0 +1,29 @@
+{% extends "basepledge.html" %}
+{% load humanize %}
+
+{% block title %}Please Log in as...{% endblock %}
+
+{% block extra_extra_head %}
+
+
+
+{% endblock %}
+
+{% block doccontent %}
+
+
+
+
+
+
Error: Wrong user for a pledge transaction
+
+
Unglue.it would like to process your pledge, but you are currently logged in as {{request.user.username}}. To complete your pledge, you need to log out, and then log in as {{ transaction.user.username }}. If you have any problem, don't hesitate to contact unglue.it support.
+
+
+
+
+
+
+{% endblock %}
+
+
diff --git a/frontend/views.py b/frontend/views.py
index 75ad8337..ada67560 100755
--- a/frontend/views.py
+++ b/frontend/views.py
@@ -783,6 +783,10 @@ class FundPledgeView(FormView):
logger.info('stripe_token:{0}, preapproval_amount:{1}'.format(stripe_token, preapproval_amount))
+ if self.transaction.user.id != self.request.user.id:
+ # trouble!
+ return render(request, "pledge_user_error.html", {'transaction': self.transaction })
+
p = PaymentManager()
# if we get a stripe_token, create a new stripe account
From 5bde0da8caf352254e44f070d0c283ea099e8fb4 Mon Sep 17 00:00:00 2001
From: eric
Date: Sat, 13 Oct 2012 13:45:46 -0400
Subject: [PATCH 4/5] [#37716025] reuse a user's credit card
---
core/models.py | 9 ++++
frontend/templates/fund_the_pledge.html | 14 +++++-
frontend/templates/pledge_card_error.html | 29 ++++++++++++
frontend/views.py | 50 +++++++-------------
payment/manager.py | 10 ----
payment/stripelib.py | 56 ++++++++++-------------
6 files changed, 93 insertions(+), 75 deletions(-)
create mode 100644 frontend/templates/pledge_card_error.html
diff --git a/core/models.py b/core/models.py
index 1d7a4c8b..2ea6b8af 100755
--- a/core/models.py
+++ b/core/models.py
@@ -1008,6 +1008,15 @@ class UserProfile(models.Model):
def pledge_count(self):
return self.user.transaction_set.exclude(status='NONE').exclude(status='Canceled',reason=None).exclude(anonymous=True).count()
+ @property
+ def account(self):
+ # there should be only one active account per user
+ accounts = self.user.account_set.filter(date_deactivated__isnull=True)
+ if accounts.count()==0:
+ return None
+ else:
+ return accounts[0]
+
#class CampaignSurveyResponse(models.Model):
# # generic
# campaign = models.ForeignKey("Campaign", related_name="surveyresponse", null=False)
diff --git a/frontend/templates/fund_the_pledge.html b/frontend/templates/fund_the_pledge.html
index c2fa5696..397a3217 100644
--- a/frontend/templates/fund_the_pledge.html
+++ b/frontend/templates/fund_the_pledge.html
@@ -193,7 +193,18 @@ $j().ready(function() {
{% endif %}
Pledge by Credit Card
-
Unglue.it uses Stripe to securely manage your Credit Card information.
+ {% if request.user.profile.account %}
+
Unglue.it has a {{ request.user.profile.account.card_type }} credit card on file for you (we use Stripe to keep your information secure).
+ The last four digits of the card are {{ request.user.profile.account.card_last4 }}.
+
+
+ {% else %}
+
Unglue.it uses Stripe to securely manage your credit card information.
Error: Card authorization for a pledge transaction
+
+
Unglue.it would like to process your pledge, but there's some problem with our credit card processeng. We'd appreciate it if you'd contact unglue.it support.
+
+
+
+
+
+
+{% endblock %}
+
+
diff --git a/frontend/views.py b/frontend/views.py
index ada67560..2c3da6ab 100755
--- a/frontend/views.py
+++ b/frontend/views.py
@@ -728,7 +728,7 @@ class FundPledgeView(FormView):
assert self.request.user.is_authenticated()
if self.transaction is None:
self.transaction = get_object_or_404(Transaction, id=self.kwargs["t_id"])
-
+
if kwargs.has_key('data'):
data = kwargs['data'].copy()
else:
@@ -765,53 +765,37 @@ class FundPledgeView(FormView):
def form_valid(self, form):
""" note desire to pledge; make sure there is a credit card to charge"""
-
- # first pass -- we have a token -- also do more direct coupling to stripelib -- then move to
- # abstraction of payment.manager / payment.baseprocessor
-
- # we should getting a stripe_token only if we had asked for CC data
-
- # BUGBUG -- don't know whether transaction.host should be None -- but if it is, set to the
- # default processor
-
- transaction = self.transaction
- if transaction.host is None or transaction.host == PAYMENT_HOST_NONE:
- transaction.host = settings.PAYMENT_PROCESSOR
-
- stripe_token = form.cleaned_data["stripe_token"]
- preapproval_amount = form.cleaned_data["preapproval_amount"]
-
- logger.info('stripe_token:{0}, preapproval_amount:{1}'.format(stripe_token, preapproval_amount))
if self.transaction.user.id != self.request.user.id:
# trouble!
return render(request, "pledge_user_error.html", {'transaction': self.transaction })
p = PaymentManager()
-
- # if we get a stripe_token, create a new stripe account
-
- try:
- (accounts, created) = p.retrieve_or_make_accounts(user=transaction.user, host=transaction.host, token=stripe_token)
- assert len(accounts) == 1 # only one active account/user at the moment
- account = accounts[0]
- logger.info('account.id: {0}'.format(account.id))
- except baseprocessor.ProcessorError as e:
- return HttpResponse("baseprocessor.ProcessorError: {0}".format(e))
-
- # GOAL: deactivate any older accounts associated with user
+
+ # if the user has active account, use it. Otherwise...
+ if not self.request.user.profile.account:
+ stripe_token = form.cleaned_data["stripe_token"]
+ # if we get a stripe_token, create a new stripe account for the user
+ if stripe_token:
+ try:
+ p.make_account(user=self.request.user, host=settings.PAYMENT_PROCESSOR, token=stripe_token)
+ except baseprocessor.ProcessorError as e:
+ return HttpResponse("There was an error processing your credit card")
+
+ self.transaction.host = settings.PAYMENT_PROCESSOR
+
+ preapproval_amount = form.cleaned_data["preapproval_amount"]
# with the Account in hand, now authorize transaction
- t, url = p.authorize(transaction)
self.transaction.max_amount = preapproval_amount
+ t, url = p.authorize(self.transaction)
logger.info("t, url: {0} {1}".format(t, url))
# redirecting user to pledge_complete on successful preapproval (in the case of stripe)
- # BUGBUG: Make sure we are testing properly for successful authorization properly here
if url is not None:
return HttpResponseRedirect(url)
else:
- return HttpResponse("preapproval_key: {0}".format(transaction.preapproval_key))
+ return render(request, "pledge_card_error.html", {'transaction': self.transaction })
class NonprofitCampaign(FormView):
diff --git a/payment/manager.py b/payment/manager.py
index b1b6e0fd..dec2022a 100644
--- a/payment/manager.py
+++ b/payment/manager.py
@@ -953,16 +953,6 @@ class PaymentManager( object ):
else:
return Account.objects.filter(user=user, host=host, date_deactivated__isnull=True)
- def retrieve_or_make_accounts(self, user, host, token=None, include_deactivated=False):
- accounts = self.retrieve_accounts(user=user, host=host, include_deactivated=include_deactivated)
- num_acct=len(accounts)
- if num_acct == 1:
- return (accounts, False)
- elif num_acct > 1:
- return ((accounts[num_acct-1],), False)
- else:
- account = self.make_account(user=user, host=host, token=token)
- return ((account,), True)
diff --git a/payment/stripelib.py b/payment/stripelib.py
index 8e55ebdd..9685d820 100644
--- a/payment/stripelib.py
+++ b/payment/stripelib.py
@@ -448,35 +448,31 @@ class Processor(baseprocessor.Processor):
def make_account(self, user, token=None):
"""returns a payment.models.Account based on stripe token and user"""
+ if token == None:
+ # shouldn't happen
+ return None
+
sc = StripeClient()
- # allow for the possibility that if token is None, just create a placeholder Account
-
- if token is not None:
-
- # create customer and charge id and then charge the customer
- try:
- customer = sc.create_customer(card=token, description=user.username,
- email=user.email)
- except stripe.StripeError as e:
- raise StripelibError(e.message, e)
-
- account = Account(host = PAYMENT_HOST_STRIPE,
- account_id = customer.id,
- card_last4 = customer.active_card.last4,
- card_type = customer.active_card.type,
- card_exp_month = customer.active_card.exp_month,
- card_exp_year = customer.active_card.exp_year,
- card_fingerprint = customer.active_card.fingerprint,
- card_country = customer.active_card.country,
- user = user
- )
-
- account.save()
-
- else:
- account = Account(host = PAYMENT_HOST_STRIPE, user= user)
- account.save()
+ # create customer and charge id and then charge the customer
+ try:
+ customer = sc.create_customer(card=token, description=user.username,
+ email=user.email)
+ except stripe.StripeError as e:
+ raise StripelibError(e.message, e)
+
+ account = Account(host = PAYMENT_HOST_STRIPE,
+ account_id = customer.id,
+ card_last4 = customer.active_card.last4,
+ card_type = customer.active_card.type,
+ card_exp_month = customer.active_card.exp_month,
+ card_exp_year = customer.active_card.exp_year,
+ card_fingerprint = customer.active_card.fingerprint,
+ card_country = customer.active_card.country,
+ user = user
+ )
+
+ account.save()
return account
@@ -507,13 +503,11 @@ class Processor(baseprocessor.Processor):
# ASSUMPTION: a user has any given moment one and only one active payment Account
- if transaction.user.account_set.filter(date_deactivated__isnull=True).count() > 1:
- logger.warning("user {0} has more than one active payment account".format(transaction.user))
- elif transaction.user.account_set.filter(date_deactivated__isnull=True).count() == 0:
+ account = transaction.user.profile.account
+ if not account:
logger.warning("user {0} has no active payment account".format(transaction.user))
raise StripelibError("user {0} has no active payment account".format(transaction.user))
- account = transaction.user.account_set.filter(date_deactivated__isnull=True)[0]
logger.info("user: {0} customer.id is {1}".format(transaction.user, account.account_id))
# settings to apply to transaction for TRANSACTION_STATUS_ACTIVE
From 8d6cc6f4c9d2b0b3a015bf18438cb96a73819d34 Mon Sep 17 00:00:00 2001
From: eric
Date: Sat, 13 Oct 2012 14:12:34 -0400
Subject: [PATCH 5/5] this makes the boder of the preapproval amount white
---
frontend/templates/fund_the_pledge.html | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/frontend/templates/fund_the_pledge.html b/frontend/templates/fund_the_pledge.html
index 397a3217..fd4becdd 100644
--- a/frontend/templates/fund_the_pledge.html
+++ b/frontend/templates/fund_the_pledge.html
@@ -198,10 +198,12 @@ $j().ready(function() {
The last four digits of the card are {{ request.user.profile.account.card_last4 }}.
{% else %}
Unglue.it uses Stripe to securely manage your credit card information.