Support for yearly subscriptions.
This commit is contained in:
parent
a4eecfaa65
commit
269c28983d
3
NEWS
3
NEWS
|
@ -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.
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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(
|
||||
|
|
Reference in New Issue