Merge branch 'master' of https://github.com/Gluejar/regluit
commit
cf3351d84b
|
@ -18,7 +18,10 @@ import regluit.core.isbn
|
|||
from regluit.core.signals import successful_campaign, unsuccessful_campaign
|
||||
import binascii
|
||||
|
||||
from regluit.payment.parameters import TRANSACTION_STATUS_ACTIVE
|
||||
from regluit.payment.parameters import TRANSACTION_STATUS_ACTIVE, TRANSACTION_STATUS_COMPLETE, TRANSACTION_STATUS_CANCELED, TRANSACTION_STATUS_ERROR, TRANSACTION_STATUS_FAILED, TRANSACTION_STATUS_INCOMPLETE
|
||||
|
||||
from django.db.models import Q
|
||||
|
||||
|
||||
class UnglueitError(RuntimeError):
|
||||
pass
|
||||
|
@ -323,7 +326,26 @@ class Campaign(models.Model):
|
|||
def supporters_count(self):
|
||||
# avoid transmitting the whole list if you don't need to; let the db do the count.
|
||||
return self.transactions().filter(status=TRANSACTION_STATUS_ACTIVE).values_list('user', flat=True).distinct().count()
|
||||
|
||||
def transaction_to_recharge(self, user):
|
||||
"""given a user, return the transaction to be recharged if there is one -- None otherwise"""
|
||||
|
||||
# only if a campaign is SUCCESSFUL, we allow for recharged
|
||||
|
||||
if self.status == 'SUCCESSFUL':
|
||||
if self.transaction_set.filter(Q(user=user) & (Q(status=TRANSACTION_STATUS_COMPLETE) | Q(status=TRANSACTION_STATUS_ACTIVE))).count():
|
||||
# presence of an active or complete transaction means no transaction to recharge
|
||||
return None
|
||||
else:
|
||||
transactions = self.transaction_set.filter(Q(user=user) & (Q(status=TRANSACTION_STATUS_ERROR) | Q(status=TRANSACTION_STATUS_FAILED)))
|
||||
# assumption --that the first failed/errored transaction has the amount we need to recharge
|
||||
if transactions.count():
|
||||
return transactions[0]
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
|
||||
def ungluers(self):
|
||||
p = PaymentManager()
|
||||
ungluers={"all":[],"supporters":[], "patrons":[], "bibliophiles":[]}
|
||||
|
@ -804,7 +826,21 @@ class UserProfile(models.Model):
|
|||
goodreads_auth_token = models.TextField(null=True, blank=True)
|
||||
goodreads_auth_secret = models.TextField(null=True, blank=True)
|
||||
goodreads_user_link = models.CharField(max_length=200, null=True, blank=True)
|
||||
|
||||
|
||||
#class CampaignSurveyResponse(models.Model):
|
||||
# # generic
|
||||
# campaign = models.ForeignKey("Campaign", related_name="surveyresponse", null=False)
|
||||
# user = models.OneToOneField(User, related_name='surveyresponse')
|
||||
# transaction = models.ForeignKey("payment.Transaction", null=True)
|
||||
# # for OLA only
|
||||
# premium = models.ForeignKey("Premium", null=True)
|
||||
# anonymous = models.BooleanField(null=False)
|
||||
# # relevant to all campaigns since these arise from acknowledgement requirements from generic premiums
|
||||
# name = models.CharField(max_length=140, blank=True)
|
||||
# url = models.URLField(blank=True)
|
||||
# tagline = models.CharField(max_length=140, blank=True)
|
||||
# # do we need to collect address for Rupert or will he do that once he has emails?
|
||||
|
||||
# this was causing a circular import problem and we do not seem to be using
|
||||
# anything from regluit.core.signals after this line
|
||||
# from regluit.core import signals
|
||||
|
|
|
@ -87,7 +87,9 @@ def public_key_from_private_key():
|
|||
def email_addresses():
|
||||
"""list email addresses in unglue.it"""
|
||||
with cd("/opt/regluit"):
|
||||
run("""source ENV/bin/activate; echo "import django; print ' \\n'.join([u.email for u in django.contrib.auth.models.User.objects.all() ]); quit()" | django-admin.py shell_plus --settings=regluit.settings.me""")
|
||||
run("""source ENV/bin/activate; echo "import django; print ' \\n'.join([u.email for u in django.contrib.auth.models.User.objects.all() ]); quit()" | django-admin.py shell_plus --settings=regluit.settings.me > /home/ubuntu/emails.txt""")
|
||||
local("scp web1:/home/ubuntu/emails.txt .")
|
||||
run("""rm /home/ubuntu/emails.txt""")
|
||||
|
||||
def selenium():
|
||||
"""setting up selenium to run in the background on RY's laptop"""
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
</div>
|
||||
|
||||
<div class="launch_top">
|
||||
The <a href="/work/81724/">first unglued book</a> is on the way! Please consider supporting our <a href="/campaigns/ending#2">three active campaigns</a>.
|
||||
The <a href="/work/81724/">first unglued book</a> is on the way! Please consider supporting our <a href="/campaigns/ending#2">four active campaigns</a>.
|
||||
</div>
|
||||
{% block topsection %}{% endblock %}
|
||||
{% block content %}{% endblock %}
|
||||
|
|
|
@ -7,7 +7,7 @@ from django.conf import settings
|
|||
|
||||
from regluit.core.feeds import SupporterWishlistFeed
|
||||
from regluit.core.models import Campaign
|
||||
from regluit.frontend.views import GoodreadsDisplayView, LibraryThingView, PledgeView, PledgeCompleteView, PledgeModifyView, PledgeCancelView, PledgeNeverMindView, FAQView
|
||||
from regluit.frontend.views import GoodreadsDisplayView, LibraryThingView, PledgeView, PledgeCompleteView, PledgeModifyView, PledgeCancelView, PledgeNeverMindView, PledgeRechargeView, FAQView
|
||||
from regluit.frontend.views import CampaignListView, DonateView, WorkListView, UngluedListView, InfoPageView
|
||||
|
||||
urlpatterns = patterns(
|
||||
|
@ -55,6 +55,7 @@ urlpatterns = patterns(
|
|||
url(r"^pledge/complete/$", login_required(PledgeCompleteView.as_view()), name="pledge_complete"),
|
||||
url(r"^pledge/nevermind/$", login_required(PledgeNeverMindView.as_view()), name="pledge_nevermind"),
|
||||
url(r"^pledge/modify/(?P<work_id>\d+)$", login_required(PledgeModifyView.as_view()), name="pledge_modify"),
|
||||
url(r"^pledge/recharge/(?P<work_id>\d+)$", login_required(PledgeRechargeView.as_view()), name="pledge_recharge"),
|
||||
url(r"^subjects/$", "subjects", name="subjects"),
|
||||
url(r"^librarything/$", LibraryThingView.as_view(), name="librarything"),
|
||||
url(r"^librarything/load/$","librarything_load", name="librarything_load"),
|
||||
|
|
|
@ -674,7 +674,8 @@ class PledgeView(FormView):
|
|||
class PledgeModifyView(FormView):
|
||||
"""
|
||||
A view to handle request to change an existing pledge
|
||||
"""
|
||||
"""
|
||||
|
||||
template_name="pledge.html"
|
||||
form_class = CampaignPledgeForm
|
||||
embedded = False
|
||||
|
@ -798,6 +799,58 @@ class PledgeModifyView(FormView):
|
|||
return HttpResponse("No modification made")
|
||||
|
||||
|
||||
|
||||
class PledgeRechargeView(TemplateView):
|
||||
"""
|
||||
a view to allow for recharge of a transaction for failed transactions or ones with errors
|
||||
"""
|
||||
template_name="pledge_recharge.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super(PledgeRechargeView, self).get_context_data(**kwargs)
|
||||
|
||||
# the following should be true since PledgeModifyView.as_view is wrapped in login_required
|
||||
assert self.request.user.is_authenticated()
|
||||
user = self.request.user
|
||||
|
||||
work = get_object_or_404(models.Work, id=self.kwargs["work_id"])
|
||||
campaign = work.last_campaign()
|
||||
|
||||
if campaign is None:
|
||||
return Http404
|
||||
|
||||
transaction = campaign.transaction_to_recharge(user)
|
||||
|
||||
# calculate a URL to do a preapproval -- in the future, we may want to do a straight up payment
|
||||
|
||||
return_url = None
|
||||
nevermind_url = None
|
||||
|
||||
if transaction is not None:
|
||||
# the recipients of this authorization is not specified here but rather by the PaymentManager.
|
||||
# set the expiry date based on the campaign deadline
|
||||
expiry = campaign.deadline + timedelta( days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN )
|
||||
|
||||
paymentReason = "Unglue.it Recharge for {0}".format(campaign.name)
|
||||
|
||||
p = PaymentManager(embedded=False)
|
||||
t, url = p.authorize('USD', TARGET_TYPE_CAMPAIGN, transaction.amount, expiry=expiry, campaign=campaign, list=None, user=user,
|
||||
return_url=return_url, nevermind_url=nevermind_url, anonymous=transaction.anonymous, premium=transaction.premium,
|
||||
paymentReason=paymentReason)
|
||||
logger.info("Recharge url: {0}".format(url))
|
||||
else:
|
||||
url = None
|
||||
|
||||
context.update({
|
||||
'work':work,
|
||||
'transaction':transaction,
|
||||
'payment_processor':transaction.host if transaction is not None else None,
|
||||
'recharge_url': url
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
class PledgeCompleteView(TemplateView):
|
||||
"""A callback for PayPal to tell unglue.it that a payment transaction has completed successfully.
|
||||
|
||||
|
|
|
@ -220,14 +220,36 @@ def amazonPaymentReturn(request):
|
|||
status = request.GET['status']
|
||||
reference = request.GET['callerReference']
|
||||
token = request.GET['tokenID']
|
||||
|
||||
|
||||
# BUGUBG - Should we verify the signature here?
|
||||
#
|
||||
# validate the signature
|
||||
|
||||
uri = request.build_absolute_uri()
|
||||
parsed_url = urlparse.urlparse(uri)
|
||||
|
||||
connection = FPSConnection(FPS_ACCESS_KEY, FPS_SECRET_KEY, host=settings.AMAZON_FPS_HOST)
|
||||
|
||||
# Check the validity of the IPN
|
||||
resp = connection.verify_signature("%s://%s%s" %(parsed_url.scheme,
|
||||
parsed_url.netloc,
|
||||
parsed_url.path),
|
||||
urllib.urlencode(request.GET))
|
||||
|
||||
if not resp[0].VerificationStatus == "Success":
|
||||
# Error, ignore this
|
||||
logging.error("amazonPaymentReturn cannot be verified with get data: ")
|
||||
logging.error(request.GET)
|
||||
return HttpResponseForbidden()
|
||||
|
||||
logging.debug("amazonPaymentReturn sig verified:")
|
||||
logging.debug(request.GET)
|
||||
|
||||
# validation of signature ok
|
||||
# Find the transaction by reference, there should only be one
|
||||
# We will catch the exception if it does not exist
|
||||
#
|
||||
transaction = Transaction.objects.get(secret=reference)
|
||||
try:
|
||||
transaction = Transaction.objects.get(secret=reference)
|
||||
except:
|
||||
logging.info("transaction with secret {0}".format(reference))
|
||||
return HttpResponseForbidden()
|
||||
|
||||
logging.info("Amazon Co-branded Return URL called for transaction id: %d" % transaction.id)
|
||||
logging.info(request.GET)
|
||||
|
|
Loading…
Reference in New Issue