Skip to content

Commit

Permalink
Merge branch 'paypal-redirect'
Browse files Browse the repository at this point in the history
  • Loading branch information
samkeen-blog committed Jul 1, 2010
2 parents 21ad257 + cb29e6b commit 803143f
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 6 deletions.
101 changes: 101 additions & 0 deletions apps/addons/tests/test_views.py
Expand Up @@ -18,6 +18,8 @@
from users.models import UserProfile
from translations.query import order_by_translation

import re


class TestHomepage(amo.test_utils.ExtraSetup, test_utils.TestCase):
fixtures = ['base/fixtures', 'base/global-stats', 'base/featured']
Expand Down Expand Up @@ -116,6 +118,105 @@ def test_title(self):
eq_(title[:37], 'Thank you for installing Gmail S/MIME')


class TestContribute(test_utils.TestCase):
fixtures = ['base/fixtures']

def test_invalid_is_404(self):
"""we get a 404 in case of invalid addon id"""
response = self.client.get(reverse('addons.contribute', args=[1]))
eq_(response.status_code, 404)

def test_redirect_params_no_type(self):
"""Test that we have the required ppal params when no type is given"""
response = self.client.get(reverse('addons.contribute',
args=[592]), follow=True)
redirect_url = response.redirect_chain[0][0]
required_params = ['bn', 'business', 'charset', 'cmd', 'item_name',
'no_shipping', 'notify_url',
'return', 'item_number']
for param in required_params:
assert(redirect_url.find(param + '=') > -1), \
"param [%s] not found" % param

def test_redirect_params_common(self):
"""Test for the common values that do not change based on type,
Check that they have expected values"""
response = self.client.get(reverse('addons.contribute',
args=[592]), follow=True)
redirect_url = response.redirect_chain[0][0]
assert(re.search('business=([^&]+)', redirect_url))
common_params = {'bn': r'-AddonID592',
'business': r'gmailsmime%40seantek.com',
'charset': r'utf-8',
'cmd': r'_donations',
'item_name': r'Contribution\+for\+Gmail\+S%2FMIME',
'no_shipping': r'1',
'notify_url': r'%2Fservices%2Fpaypal',
'return': r'x',
'item_number': r'[a-f\d]{32}'}

message = 'param [%s] unexpected value: given [%s], ' \
+ 'expected pattern [%s]'
for param, value_pattern in common_params.items():
match = re.search(r'%s=([^&]+)' % param, redirect_url)
assert(match and re.search(value_pattern, match.group(1))), \
message % (param, match.group(1), value_pattern)

def test_redirect_params_type_suggested(self):
"""Test that we have the required ppal param when type
suggested is given"""
request_params = '?type=suggested'
response = self.client.get(reverse('addons.contribute',
args=[592]) + request_params,
follow=True)
redirect_url = response.redirect_chain[0][0]
required_params = ['amount', 'bn', 'business', 'charset',
'cmd', 'item_name', 'no_shipping', 'notify_url',
'return', 'item_number']
for param in required_params:
assert(redirect_url.find(param + '=') > -1), \
"param [%s] not found" % param

def test_redirect_params_type_onetime(self):
"""Test that we have the required ppal param when
type onetime is given"""
request_params = '?type=onetime&onetime-amount=42'
response = self.client.get(reverse('addons.contribute',
args=[592]) + request_params,
follow=True)
redirect_url = response.redirect_chain[0][0]
required_params = ['amount', 'bn', 'business', 'charset', 'cmd',
'item_name', 'no_shipping', 'notify_url',
'return', 'item_number']
for param in required_params:
assert(redirect_url.find(param + '=') > -1), \
"param [%s] not found" % param

assert(redirect_url.find('amount=42') > -1)

def test_redirect_params_type_monthly(self):
"""Test that we have the required ppal param when
type monthly is given"""
request_params = '?type=monthly&monthly-amount=42'
response = self.client.get(reverse('addons.contribute',
args=[592]) + request_params,
follow=True)
redirect_url = response.redirect_chain[0][0]
required_params = ['no_note', 'a3', 't3', 'p3', 'bn', 'business',
'charset', 'cmd', 'item_name', 'no_shipping',
'notify_url', 'return', 'item_number']
for param in required_params:
assert(redirect_url.find(param + '=') > -1), \
"param [%s] not found" % param

assert(redirect_url.find('cmd=_xclick-subscriptions') > -1), \
'param a3 was not 42'
assert(redirect_url.find('p3=12') > -1), 'param p3 was not 12'
assert(redirect_url.find('t3=M') > -1), 'param t3 was not M'
assert(redirect_url.find('a3=42') > -1), 'param a3 was not 42'
assert(redirect_url.find('no_note=1') > -1), 'param no_note was not 1'


class TestDeveloperPages(test_utils.TestCase):
fixtures = ['base/fixtures', 'addons/eula+contrib-addon']

Expand Down
7 changes: 4 additions & 3 deletions apps/addons/urls.py
Expand Up @@ -15,9 +15,10 @@
{'page': 'roadblock'}, name='addons.roadblock'),
url('^contribute/installed/', views.developers,
{'page': 'installed'}, name='addons.installed'),
('^contribute/thanks$', lambda r, addon_id: redirect('addons.detail',
addon_id)),

url('^contribute/thanks', lambda r,
addon_id: redirect('addons.detail', addon_id),
name='addons.thanks'),
url('^contribute/', views.contribute, name='addons.contribute'),
('^about$', lambda r, addon_id: redirect('addons.installed',
addon_id, permanent=True)),

Expand Down
85 changes: 84 additions & 1 deletion apps/addons/views.py
Expand Up @@ -13,11 +13,15 @@
from amo import urlresolvers
from amo.urlresolvers import reverse
from bandwagon.models import Collection, CollectionFeature, CollectionPromo
from stats.models import GlobalStat
from stats.models import GlobalStat, Contribution
from tags.models import Tag
from translations.query import order_by_translation
from .models import Addon

import hashlib
import urllib
import uuid


def author_addon_clicked(f):
"""Decorator redirecting clicks on "Other add-ons by author"."""
Expand Down Expand Up @@ -397,3 +401,82 @@ def developers(request, addon_id, page):
return jingo.render(request, 'addons/developers.html',
{'addon': addon, 'author_addons': author_addons,
'page': page})


def contribute(request, addon_id):

addon = get_object_or_404(Addon.objects.valid(), id=addon_id)

contrib_type = request.GET.get('type', '')
is_suggested = contrib_type == 'suggested'
source = request.GET.get('source', '')
comment = request.GET.get('comment', '')

amount = {
'suggested': addon.suggested_amount,
'onetime': request.GET.get('onetime-amount', ''),
'monthly': request.GET.get('monthly-amount', '')}.get(contrib_type, '')

contribution_uuid = hashlib.md5(str(uuid.uuid4())).hexdigest()

contrib = Contribution(addon_id=addon.id,
amount=amount,
source=source,
source_locale=request.LANG,
annoying=addon.annoying,
uuid=str(contribution_uuid),
is_suggested=is_suggested,
suggested_amount=addon.suggested_amount,
comment=comment)
contrib.save()

return_url = "%s?%s" % (reverse('addons.thanks', args=[addon.id]),
urllib.urlencode({'uuid': contribution_uuid}))

redirect_url_params = contribute_url_params(
addon.paypal_id,
addon.id,
'Contribution for %s' % addon.name,
return_url,
amount,
contribution_uuid,
contrib_type == 'monthly',
comment)

return http.HttpResponseRedirect(settings.PAYPAL_CGI_URL
+ '?'
+ urllib.urlencode(redirect_url_params))


def contribute_url_params(business, addon_id, item_name, return_url,
amount='', item_number='',
monthly=False, comment=''):

"""Get all the data elements that will be URL params
on the Paypal redirect URL"""

data = {'business': business,
'item_name': item_name,
'item_number': item_number,
'bn': settings.PAYPAL_BN + '-AddonID' + str(addon_id),
'no_shipping': '1',
'return': return_url,
'charset': 'utf-8',
'notify_url': reverse('amo.paypal')}

if (not monthly):
data['cmd'] = '_donations'
if (amount):
data['amount'] = amount
else:
data.update({
'cmd': '_xclick-subscriptions',
'p3': '12', # duration: for 12 months
't3': 'M', # time unit, 'M' for month
'a3': amount, # recurring contribution amount
'no_note': '1'}) # required: no "note" text field for user

if (comment):
data['custom'] = comment

return data
13 changes: 11 additions & 2 deletions apps/amo/tests/test_redirects.py
Expand Up @@ -25,9 +25,18 @@ def test_persona(self):
assert r.redirect_chain[-1][0].endswith('/en-US/firefox/addon/4/')

def test_contribute_installed(self):
"""`/addon/\d+/about` should go to `/addon/\d+/contribute/installed`."""
"""`/addon/\d+/about` should go to
`/addon/\d+/contribute/installed`."""
r = self.client.get(u'addon/5326/about', follow=True)
assert r.redirect_chain[-1][0].endswith('/en-US/firefox/addon/5326/contribute/installed/')
redirect = r.redirect_chain[-1][0]
assert redirect.endswith(
'/en-US/firefox/addon/5326/contribute/installed/')

def test_contribute(self):
"""`/addons/contribute/$id` should go to `/addon/$id/contribute`."""
response = self.client.get(u'addon/5326/contribute', follow=True)
redirect = response.redirect_chain[-1][0]
assert redirect.endswith('/en-US/firefox/addon/5326/contribute/')

def test_utf8(self):
"""Without proper unicode handling this will fail."""
Expand Down
1 change: 1 addition & 0 deletions settings.py
Expand Up @@ -448,6 +448,7 @@ def JINJA_CONFIG():

# PayPal Settings
PAYPAL_CGI_URL = 'https://www.paypal.com/cgi-bin/webscr'
PAYPAL_BN = ''

# Email settings
DEFAULT_FROM_EMAIL = "Mozilla Add-ons <nobody@mozilla.org>"
Expand Down
3 changes: 3 additions & 0 deletions urls.py
Expand Up @@ -77,6 +77,9 @@
('^search-engines.*$',
lambda r: redirect('browse.search-tools', permanent=True)),

('^addons/contribute/(\d+)/?$',
lambda r, id: redirect('addons.contribute', id, permanent=True)),

# Firefox Cup page, /firefoxcup
('^firefoxcup/', include('firefoxcup.urls'))
)
Expand Down

0 comments on commit 803143f

Please sign in to comment.