commit
f152bc97b1
|
@ -1008,6 +1008,15 @@ class UserProfile(models.Model):
|
||||||
def pledge_count(self):
|
def pledge_count(self):
|
||||||
return self.user.transaction_set.exclude(status='NONE').exclude(status='Canceled',reason=None).exclude(anonymous=True).count()
|
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):
|
#class CampaignSurveyResponse(models.Model):
|
||||||
# # generic
|
# # generic
|
||||||
# campaign = models.ForeignKey("Campaign", related_name="surveyresponse", null=False)
|
# campaign = models.ForeignKey("Campaign", related_name="surveyresponse", null=False)
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
<div><h2>Wrong user for donation credit</h2>
|
<div><h2>Wrong user for donation credit</h2>
|
||||||
<div>
|
<div>
|
||||||
<p>Unglue.it would like to process your donation credit, but you are currently logged in as <code>{{request.user.username}}</code>. Your donation credit from {{nonprofit.name}} for ${{ envelope.amount }}.{{ envelope.cents }} is designated for <code>{{ envelope.username }}</code>. Do record your credit, you need to <a href='{% url auth_logout %}?next={{ request.get_full_path|urlencode }}'>log out</a>, and then <a href='{% url auth_login %}?next={{ request.get_full_path|urlencode }}'>log in</a> as <code>{{ envelope.username }}</code>. If you have any problem, don't hesitate to contact <a href="mailto:support@gluejar.com?subject={{ request.get_full_path|urlencode }}">unglue.it support</a>.
|
<p>Unglue.it would like to process your donation credit, but you are currently logged in as <code>{{request.user.username}}</code>. Your donation credit from {{nonprofit.name}} for ${{ envelope.amount }}.{{ envelope.cents }} is designated for <code>{{ envelope.username }}</code>. To record your credit, you need to <a href='{% url auth_logout %}?next={{ request.get_full_path|urlencode }}'>log out</a>, and then <a href='{% url auth_login %}?next={{ request.get_full_path|urlencode }}'>log in</a> as <code>{{ envelope.username }}</code>. If you have any problem, don't hesitate to contact <a href="mailto:support@gluejar.com?subject={{ request.get_full_path|urlencode }}">unglue.it support</a>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -193,7 +193,20 @@ $j().ready(function() {
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div id="authorize" {% if nonprofit.is_on %}class="off clearfix"{% else %}class="clearfix"{% endif %}>
|
<div id="authorize" {% if nonprofit.is_on %}class="off clearfix"{% else %}class="clearfix"{% endif %}>
|
||||||
<h3>Pledge by Credit Card</h3>
|
<h3>Pledge by Credit Card</h3>
|
||||||
<p>Unglue.it uses Stripe to securely manage your Credit Card information.
|
{% if request.user.profile.account %}
|
||||||
|
<p>Unglue.it has a {{ request.user.profile.account.card_type }} credit card on file for you (we use <a href="https://stripe.com/">Stripe</a> to keep your information secure).
|
||||||
|
The last four digits of the card are {{ request.user.profile.account.card_last4 }}.
|
||||||
|
</p>
|
||||||
|
<form action="#" method="POST" id="use-account-form">
|
||||||
|
<div class="innards">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.non_field_errors }}
|
||||||
|
{{ form.as_p }}
|
||||||
|
<input id="use_account_submit" name="use_account" type="submit" class="submit-button" value="Complete Pledge" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<p>Unglue.it uses <a href="https://stripe.com/">Stripe</a> to securely manage your credit card information.
|
||||||
</p>
|
</p>
|
||||||
<div id="cc_pledge">
|
<div id="cc_pledge">
|
||||||
<form action="" method="POST" id="payment-form">
|
<form action="" method="POST" id="payment-form">
|
||||||
|
@ -252,6 +265,7 @@ $j().ready(function() {
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
{% extends "basepledge.html" %}
|
||||||
|
{% load humanize %}
|
||||||
|
|
||||||
|
{% block title %}Credit card processing Error{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_extra_head %}
|
||||||
|
<link type="text/css" rel="stylesheet" href="/static/css/campaign.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="/static/css/pledge.css" />
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block doccontent %}
|
||||||
|
<div style="height:15px"></div>
|
||||||
|
|
||||||
|
<div class="jsmodule rounded clearfix">
|
||||||
|
<div class="jsmod-content">
|
||||||
|
|
||||||
|
<div><h2>Error: Card authorization for a pledge transaction</h2>
|
||||||
|
<div>
|
||||||
|
<p>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 <a href="mailto:support@gluejar.com?subject={{ request.get_full_path|urlencode }}">unglue.it support</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
{% extends "basepledge.html" %}
|
||||||
|
{% load humanize %}
|
||||||
|
|
||||||
|
{% block title %}Please Log in as...{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_extra_head %}
|
||||||
|
<link type="text/css" rel="stylesheet" href="/static/css/campaign.css" />
|
||||||
|
<link type="text/css" rel="stylesheet" href="/static/css/pledge.css" />
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block doccontent %}
|
||||||
|
<div style="height:15px"></div>
|
||||||
|
|
||||||
|
<div class="jsmodule rounded clearfix">
|
||||||
|
<div class="jsmod-content">
|
||||||
|
|
||||||
|
<div><h2>Error: Wrong user for a pledge transaction</h2>
|
||||||
|
<div>
|
||||||
|
<p>Unglue.it would like to process your pledge, but you are currently logged in as <code>{{request.user.username}}</code>. To complete your pledge, you need to <a href='{% url auth_logout %}?next={{ request.get_full_path|urlencode }}'>log out</a>, and then <a href='{% url auth_login %}?next={{ request.get_full_path|urlencode }}'>log in</a> as <code>{{ transaction.user.username }}</code>. If you have any problem, don't hesitate to contact <a href="mailto:support@gluejar.com?subject={{ request.get_full_path|urlencode }}">unglue.it support</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -734,7 +734,7 @@ class FundPledgeView(FormView):
|
||||||
assert self.request.user.is_authenticated()
|
assert self.request.user.is_authenticated()
|
||||||
if self.transaction is None:
|
if self.transaction is None:
|
||||||
self.transaction = get_object_or_404(Transaction, id=self.kwargs["t_id"])
|
self.transaction = get_object_or_404(Transaction, id=self.kwargs["t_id"])
|
||||||
|
|
||||||
if kwargs.has_key('data'):
|
if kwargs.has_key('data'):
|
||||||
data = kwargs['data'].copy()
|
data = kwargs['data'].copy()
|
||||||
else:
|
else:
|
||||||
|
@ -771,52 +771,37 @@ class FundPledgeView(FormView):
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
""" note desire to pledge; make sure there is a credit card to charge"""
|
""" 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
|
if self.transaction.user.id != self.request.user.id:
|
||||||
# abstraction of payment.manager / payment.baseprocessor
|
# trouble!
|
||||||
|
return render(request, "pledge_user_error.html", {'transaction': self.transaction })
|
||||||
# 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))
|
|
||||||
|
|
||||||
p = PaymentManager()
|
p = PaymentManager()
|
||||||
|
|
||||||
# if we get a stripe_token, create a new stripe account
|
# if the user has active account, use it. Otherwise...
|
||||||
|
if not self.request.user.profile.account:
|
||||||
try:
|
stripe_token = form.cleaned_data["stripe_token"]
|
||||||
(accounts, created) = p.retrieve_or_make_accounts(user=transaction.user, host=transaction.host, token=stripe_token)
|
# if we get a stripe_token, create a new stripe account for the user
|
||||||
assert len(accounts) == 1 # only one active account/user at the moment
|
if stripe_token:
|
||||||
account = accounts[0]
|
try:
|
||||||
logger.info('account.id: {0}'.format(account.id))
|
p.make_account(user=self.request.user, host=settings.PAYMENT_PROCESSOR, token=stripe_token)
|
||||||
except baseprocessor.ProcessorError as e:
|
except baseprocessor.ProcessorError as e:
|
||||||
return HttpResponse("baseprocessor.ProcessorError: {0}".format(e))
|
return HttpResponse("There was an error processing your credit card")
|
||||||
|
|
||||||
# GOAL: deactivate any older accounts associated with user
|
self.transaction.host = settings.PAYMENT_PROCESSOR
|
||||||
|
|
||||||
|
preapproval_amount = form.cleaned_data["preapproval_amount"]
|
||||||
|
|
||||||
# with the Account in hand, now authorize transaction
|
# with the Account in hand, now authorize transaction
|
||||||
transaction.amount = preapproval_amount
|
self.transaction.max_amount = preapproval_amount
|
||||||
t, url = p.authorize(transaction)
|
t, url = p.authorize(self.transaction)
|
||||||
logger.info("t, url: {0} {1}".format(t, url))
|
logger.info("t, url: {0} {1}".format(t, url))
|
||||||
|
|
||||||
# redirecting user to pledge_complete on successful preapproval (in the case of stripe)
|
# 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:
|
if url is not None:
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
elif settings.DEBUG:
|
|
||||||
return HttpResponse("preapproval_key: {0}".format(transaction.preapproval_key))
|
|
||||||
else:
|
else:
|
||||||
raise Http404
|
return render(request, "pledge_card_error.html", {'transaction': self.transaction })
|
||||||
|
|
||||||
|
|
||||||
class NonprofitCampaign(FormView):
|
class NonprofitCampaign(FormView):
|
||||||
template_name="nonprofit.html"
|
template_name="nonprofit.html"
|
||||||
|
|
|
@ -567,7 +567,7 @@ class PaymentManager( object ):
|
||||||
urllib.urlencode({'tid':transaction.id}))
|
urllib.urlencode({'tid':transaction.id}))
|
||||||
return_url = urlparse.urljoin(settings.BASE_URL, return_path)
|
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
|
# Create a response for this
|
||||||
envelope = p.envelope()
|
envelope = p.envelope()
|
||||||
|
@ -960,16 +960,6 @@ class PaymentManager( object ):
|
||||||
else:
|
else:
|
||||||
return Account.objects.filter(user=user, host=host, date_deactivated__isnull=True)
|
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)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -448,35 +448,31 @@ class Processor(baseprocessor.Processor):
|
||||||
def make_account(self, user, token=None):
|
def make_account(self, user, token=None):
|
||||||
"""returns a payment.models.Account based on stripe token and user"""
|
"""returns a payment.models.Account based on stripe token and user"""
|
||||||
|
|
||||||
|
if token == None:
|
||||||
|
# shouldn't happen
|
||||||
|
return None
|
||||||
|
|
||||||
sc = StripeClient()
|
sc = StripeClient()
|
||||||
|
|
||||||
# allow for the possibility that if token is None, just create a placeholder Account
|
# create customer and charge id and then charge the customer
|
||||||
|
try:
|
||||||
if token is not None:
|
customer = sc.create_customer(card=token, description=user.username,
|
||||||
|
email=user.email)
|
||||||
# create customer and charge id and then charge the customer
|
except stripe.StripeError as e:
|
||||||
try:
|
raise StripelibError(e.message, e)
|
||||||
customer = sc.create_customer(card=token, description=user.username,
|
|
||||||
email=user.email)
|
account = Account(host = PAYMENT_HOST_STRIPE,
|
||||||
except stripe.StripeError as e:
|
account_id = customer.id,
|
||||||
raise StripelibError(e.message, e)
|
card_last4 = customer.active_card.last4,
|
||||||
|
card_type = customer.active_card.type,
|
||||||
account = Account(host = PAYMENT_HOST_STRIPE,
|
card_exp_month = customer.active_card.exp_month,
|
||||||
account_id = customer.id,
|
card_exp_year = customer.active_card.exp_year,
|
||||||
card_last4 = customer.active_card.last4,
|
card_fingerprint = customer.active_card.fingerprint,
|
||||||
card_type = customer.active_card.type,
|
card_country = customer.active_card.country,
|
||||||
card_exp_month = customer.active_card.exp_month,
|
user = user
|
||||||
card_exp_year = customer.active_card.exp_year,
|
)
|
||||||
card_fingerprint = customer.active_card.fingerprint,
|
|
||||||
card_country = customer.active_card.country,
|
account.save()
|
||||||
user = user
|
|
||||||
)
|
|
||||||
|
|
||||||
account.save()
|
|
||||||
|
|
||||||
else:
|
|
||||||
account = Account(host = PAYMENT_HOST_STRIPE, user= user)
|
|
||||||
account.save()
|
|
||||||
|
|
||||||
return account
|
return account
|
||||||
|
|
||||||
|
@ -507,13 +503,11 @@ class Processor(baseprocessor.Processor):
|
||||||
|
|
||||||
# ASSUMPTION: a user has any given moment one and only one active payment Account
|
# 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:
|
account = transaction.user.profile.account
|
||||||
logger.warning("user {0} has more than one active payment account".format(transaction.user))
|
if not account:
|
||||||
elif transaction.user.account_set.filter(date_deactivated__isnull=True).count() == 0:
|
|
||||||
logger.warning("user {0} has no active payment account".format(transaction.user))
|
logger.warning("user {0} has no active payment account".format(transaction.user))
|
||||||
raise StripelibError("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))
|
logger.info("user: {0} customer.id is {1}".format(transaction.user, account.account_id))
|
||||||
|
|
||||||
# settings to apply to transaction for TRANSACTION_STATUS_ACTIVE
|
# settings to apply to transaction for TRANSACTION_STATUS_ACTIVE
|
||||||
|
|
Loading…
Reference in New Issue