witten
/
luminotes
Archived
1
0
Fork 0

Support for yearly subscriptions.

This commit is contained in:
Dan Helfman 2008-05-08 18:39:46 +00:00
parent a4eecfaa65
commit 269c28983d
6 changed files with 155 additions and 8 deletions

3
NEWS
View File

@ -1,3 +1,6 @@
1.3.19: May 8, 2008
* Support for yearly subscriptions.
1.3.18: May 7, 2008
* No longer showing "settings" link unless you're viewing your wiki.
* In account settings note, now showing link to upgrade/downgrade/cancel.

View File

@ -30,24 +30,33 @@ settings = {
"storage_quota_bytes": 30 * MEGABYTE,
"notebook_collaboration": False,
"fee": None,
"yearly_fee": None,
},
{
"name": "basic",
"storage_quota_bytes": 250 * MEGABYTE,
"notebook_collaboration": True,
"fee": 5,
"yearly_fee": 50,
"button":
"""
""",
"yearly_button":
"""
""",
},
{
"name": "standard",
"storage_quota_bytes": 500 * MEGABYTE,
"notebook_collaboration": True,
"fee": 9,
"yearly_fee": 90,
"button":
"""
""",
"yearly_button":
"""
""",
},
# {
# "name": "premium",

View File

@ -1082,6 +1082,9 @@ class Users( object ):
# verify item_number
plan_index = params.get( u"item_number" )
if plan_index == None:
return dict() # ignore this transaction if there's no item number
try:
plan_index = int( plan_index )
except ValueError:
@ -1092,13 +1095,14 @@ class Users( object ):
# verify mc_gross
rate_plan = self.__rate_plans[ plan_index ]
fee = u"%0.2f" % rate_plan[ u"fee" ]
yearly_fee = u"%0.2f" % rate_plan[ u"yearly_fee" ]
mc_gross = params.get( u"mc_gross" )
if mc_gross and mc_gross != fee:
if mc_gross and mc_gross not in ( fee, yearly_fee ):
raise Payment_error( u"invalid mc_gross", params )
# verify mc_amount3
mc_amount3 = params.get( u"mc_amount3" )
if mc_amount3 and mc_amount3 != fee:
if mc_amount3 and mc_amount3 not in ( fee, yearly_fee ):
raise Payment_error( u"invalid mc_amount3", params )
# verify item_name
@ -1112,8 +1116,12 @@ class Users( object ):
# verify period3
period3 = params.get( u"period3" )
if period3 and period3 != u"1 M": # one-month subscription
raise Payment_error( u"invalid period3", params )
if mc_amount3 == yearly_fee:
if period3 and period3 != u"12 M": # one-year subscription
raise Payment_error( u"invalid period3", params )
else:
if period3 and period3 != u"1 M": # one-month subscription
raise Payment_error( u"invalid period3", params )
params[ u"cmd" ] = u"_notify-validate"
encoded_params = urllib.urlencode( params )

View File

@ -405,14 +405,18 @@ class Test_controller( object ):
u"storage_quota_bytes": 1337 * 10,
u"notebook_collaboration": True,
u"fee": 1.99,
u"yearly_fee": 19.90,
u"button": u"[subscribe here user %s!] button",
u"yearly_button": u"[yearly subscribe here user %s!] button",
},
{
u"name": "extra super",
u"storage_quota_bytes": 31337 * 1000,
u"notebook_collaboration": True,
u"fee": 9.00,
u"yearly_fee": 90.00,
u"button": u"[or here user %s!] button",
u"yearly_button": u"[yearly or here user %s!] button",
},
],
},

View File

@ -2501,6 +2501,25 @@ class Test_users( Test_controller ):
user = self.database.load( User, self.user.object_id )
assert user.rate_plan == 0
def test_paypal_notify_payment_yearly( self ):
data = dict( self.PAYMENT_DATA )
data[ u"custom" ] = self.user.object_id
data[ u"payment_gross" ] = u"90.00"
data[ u"mc_gross" ] = u"90.00"
result = self.http_post( "/users/paypal_notify", data );
assert len( result ) == 1
assert result.get( u"session_id" )
assert Stub_urllib2.result == u"VERIFIED"
assert Stub_urllib2.headers.get( u"Content-type" ) == u"application/x-www-form-urlencoded"
assert Stub_urllib2.url.startswith( "https://" )
assert u"paypal.com" in Stub_urllib2.url
assert Stub_urllib2.encoded_params
# being notified of a mere payment should not change the user's rate plan
user = self.database.load( User, self.user.object_id )
assert user.rate_plan == 0
def test_paypal_notify_payment_invalid( self ):
data = dict( self.PAYMENT_DATA )
data[ u"custom" ] = self.user.object_id
@ -2544,6 +2563,14 @@ class Test_users( Test_controller ):
assert result.get( u"error" )
def test_paypal_notify_payment_missing_item_number( self ):
data = dict( self.PAYMENT_DATA )
data[ u"custom" ] = self.user.object_id
result = self.http_post( "/users/paypal_notify", data );
assert len( result ) == 1
assert result.get( u"session_id" )
def test_paypal_notify_payment_incorrect_gross( self ):
data = dict( self.PAYMENT_DATA )
data[ u"custom" ] = self.user.object_id
@ -2785,6 +2812,25 @@ class Test_users( Test_controller ):
user = self.database.load( User, self.user.object_id )
assert user.rate_plan == 1
def test_paypal_notify_signup_yearly( self ):
data = dict( self.SUBSCRIPTION_DATA )
data[ u"custom" ] = self.user.object_id
data[ u"amount3" ] = u"90.00"
data[ u"mc_amount3" ] = u"90.00"
data[ u"period3" ] = u"12 M"
result = self.http_post( "/users/paypal_notify", data );
assert len( result ) == 1
assert result.get( u"session_id" )
assert Stub_urllib2.result == u"VERIFIED"
assert Stub_urllib2.headers.get( u"Content-type" ) == u"application/x-www-form-urlencoded"
assert Stub_urllib2.url.startswith( "https://" )
assert u"paypal.com" in Stub_urllib2.url
assert Stub_urllib2.encoded_params
user = self.database.load( User, self.user.object_id )
assert user.rate_plan == 1
def test_paypal_notify_signup_invalid( self ):
data = dict( self.SUBSCRIPTION_DATA )
data[ u"custom" ] = self.user.object_id
@ -2888,6 +2934,26 @@ class Test_users( Test_controller ):
user = self.database.load( User, self.user.object_id )
assert user.rate_plan == 0
def test_paypal_notify_signup_yearly_period3_with_monthly_amount( self ):
data = dict( self.SUBSCRIPTION_DATA )
data[ u"custom" ] = self.user.object_id
data[ u"period3" ] = u"12 M"
result = self.http_post( "/users/paypal_notify", data );
assert result.get( u"error" )
user = self.database.load( User, self.user.object_id )
assert user.rate_plan == 0
def test_paypal_notify_signup_yearly_amount_with_monthly_period3( self ):
data = dict( self.SUBSCRIPTION_DATA )
data[ u"custom" ] = self.user.object_id
data[ u"mc_amount3" ] = u"19.90"
result = self.http_post( "/users/paypal_notify", data );
assert result.get( u"error" )
user = self.database.load( User, self.user.object_id )
assert user.rate_plan == 0
def test_paypal_notify_signup_missing_custom( self ):
data = dict( self.SUBSCRIPTION_DATA )
result = self.http_post( "/users/paypal_notify", data );
@ -2952,6 +3018,29 @@ class Test_users( Test_controller ):
user = self.database.load( User, self.user.object_id )
assert user.rate_plan == 1
def test_paypal_notify_modify_yearly( self ):
self.user.rate_plan = 2
user = self.database.save( self.user )
data = dict( self.SUBSCRIPTION_DATA )
data[ u"txn_type" ] = u"subscr_modify"
data[ u"custom" ] = self.user.object_id
data[ u"amount3" ] = u"90.00"
data[ u"mc_amount3" ] = u"90.00"
data[ u"period3" ] = u"12 M"
result = self.http_post( "/users/paypal_notify", data );
assert len( result ) == 1
assert result.get( u"session_id" )
assert Stub_urllib2.result == u"VERIFIED"
assert Stub_urllib2.headers.get( u"Content-type" ) == u"application/x-www-form-urlencoded"
assert Stub_urllib2.url.startswith( "https://" )
assert u"paypal.com" in Stub_urllib2.url
assert Stub_urllib2.encoded_params
user = self.database.load( User, self.user.object_id )
assert user.rate_plan == 1
def test_paypal_notify_modify_invalid( self ):
self.user.rate_plan = 2
user = self.database.save( self.user )
@ -3179,6 +3268,29 @@ class Test_users( Test_controller ):
user = self.database.load( User, self.user.object_id )
assert user.rate_plan == 0
def test_paypal_notify_cancel_yearly( self ):
self.user.rate_plan = 1
user = self.database.save( self.user )
data = dict( self.SUBSCRIPTION_DATA )
data[ u"txn_type" ] = u"subscr_cancel"
data[ u"custom" ] = self.user.object_id
data[ u"amount3" ] = u"90.00"
data[ u"mc_amount3" ] = u"90.00"
data[ u"period3" ] = u"12 M"
result = self.http_post( "/users/paypal_notify", data );
assert len( result ) == 1
assert result.get( u"session_id" )
assert Stub_urllib2.result == u"VERIFIED"
assert Stub_urllib2.headers.get( u"Content-type" ) == u"application/x-www-form-urlencoded"
assert Stub_urllib2.url.startswith( "https://" )
assert u"paypal.com" in Stub_urllib2.url
assert Stub_urllib2.encoded_params
user = self.database.load( User, self.user.object_id )
assert user.rate_plan == 0
def test_paypal_notify_cancel_invalid( self ):
self.user.rate_plan = 1
user = self.database.save( self.user )

View File

@ -137,7 +137,12 @@ class Upgrade_page( Product_page ):
P(
Table(
self.fee_row( rate_plans, user, include_blank = False ),
Tr( Td(
u"Get two months free with a yearly subscription!",
class_ = u"upgrade_subtitle",
colspan = u"3",
), colspan = u"3" ),
self.fee_row( rate_plans, user, include_blank = False, yearly = True ),
Tr(
[ Td(
plan[ u"storage_quota_bytes" ] // MEGABYTE, " MB",
@ -164,20 +169,26 @@ class Upgrade_page( Product_page ):
),
)
def fee_row( self, rate_plans, user, include_blank = True ):
def fee_row( self, rate_plans, user, include_blank = True, yearly = False ):
return Tr(
include_blank and Th( u" " ) or None,
[ Th(
plan[ u"name" ].capitalize(),
plan[ u"fee" ] and Div(
Span(
yearly and Span(
u"$%s" % plan[ u"yearly_fee" ],
Span( u"/year", class_ = u"month_text" ),
class_ = u"price_text",
separator = u"",
) or Span(
u"$%s" % plan[ u"fee" ],
Span( u"/month", class_ = u"month_text" ),
class_ = u"price_text",
separator = u"",
),
user and user.username not in ( u"anonymous", None ) and user.rate_plan != index \
and plan.get( u"button" ).strip() and plan.get( u"button" ) % user.object_id or None,
and yearly and ( plan.get( u"yearly_button" ).strip() and plan.get( u"yearly_button" ) % user.object_id or None ) or \
( plan.get( u"button" ).strip() and plan.get( u"button" ) % user.object_id or None ),
) or None,
( not user or user.username in ( u"anonymous", None ) ) and Div(
A(