From e301b34cdae7b15e8b1459c50e831fb5e777c74e Mon Sep 17 00:00:00 2001 From: bsimpson63 Date: Mon, 7 Jan 2013 09:42:03 -0500 Subject: [PATCH] Coinbase payments for reddit gold. --- r2/example.ini | 16 ++++++++++++++++ r2/r2/config/routing.py | 2 ++ r2/r2/controllers/__init__.py | 1 + r2/r2/controllers/front.py | 7 ++++++- r2/r2/controllers/ipn.py | 20 ++++++++++++++++++++ r2/r2/lib/pages/pages.py | 12 +++++++++++- r2/r2/public/static/css/reddit.css | 1 + r2/r2/public/static/js/gold.js | 4 +++- r2/r2/templates/goldpayment.html | 14 ++++++++++++++ 9 files changed, 74 insertions(+), 3 deletions(-) diff --git a/r2/example.ini b/r2/example.ini index 6af2df94c..1692fc6b0 100644 --- a/r2/example.ini +++ b/r2/example.ini @@ -77,6 +77,22 @@ STRIPE_WEBHOOK_SECRET = STRIPE_PUBLIC_KEY = STRIPE_SECRET_KEY = +COINBASE_WEBHOOK_SECRET = +COINBASE_BUTTONID_ONETIME_1MO = +COINBASE_BUTTONID_ONETIME_2MO = +COINBASE_BUTTONID_ONETIME_3MO = +COINBASE_BUTTONID_ONETIME_4MO = +COINBASE_BUTTONID_ONETIME_5MO = +COINBASE_BUTTONID_ONETIME_6MO = +COINBASE_BUTTONID_ONETIME_7MO = +COINBASE_BUTTONID_ONETIME_8MO = +COINBASE_BUTTONID_ONETIME_9MO = +COINBASE_BUTTONID_ONETIME_10MO = +COINBASE_BUTTONID_ONETIME_11MO = +COINBASE_BUTTONID_ONETIME_1YR = +COINBASE_BUTTONID_ONETIME_2YR = +COINBASE_BUTTONID_ONETIME_3YR = + # -- feature toggles -- disable_ads = false disable_captcha = false diff --git a/r2/r2/config/routing.py b/r2/r2/config/routing.py index 045029f18..d97873764 100644 --- a/r2/r2/config/routing.py +++ b/r2/r2/config/routing.py @@ -264,6 +264,8 @@ def make_map(): mc('/api/stripecharge/gold', controller='stripe', action='goldcharge') mc('/api/stripewebhook/gold/:secret', controller='stripe', action='goldwebhook') + mc('/api/coinbasewebhook/gold/:secret', controller='coinbase', + action='goldwebhook') mc('/api/ipn/:secret', controller='ipn', action='ipn') mc('/ipn/:secret', controller='ipn', action='ipn') mc('/api/:action/:url_user', controller='api', diff --git a/r2/r2/controllers/__init__.py b/r2/r2/controllers/__init__.py index eab7a2dd2..8eabd0f8a 100644 --- a/r2/r2/controllers/__init__.py +++ b/r2/r2/controllers/__init__.py @@ -82,5 +82,6 @@ def load_controllers(): from redirect import RedirectController from ipn import IpnController from ipn import StripeController + from ipn import CoinbaseController _reddit_controllers.update((name.lower(), obj) for name, obj in locals().iteritems()) diff --git a/r2/r2/controllers/front.py b/r2/r2/controllers/front.py index 5e4bd74ff..ef7f84f26 100755 --- a/r2/r2/controllers/front.py +++ b/r2/r2/controllers/front.py @@ -1041,7 +1041,7 @@ class FrontController(RedditController, OAuth2ResourceController): ).render() @validate(vendor=VOneOf("v", ("claimed-gold", "claimed-creddits", - "paypal", "google-checkout"), + "paypal", "google-checkout", "coinbase"), default="claimed-gold")) def GET_goldthanks(self, vendor): vendor_url = None @@ -1062,6 +1062,11 @@ class FrontController(RedditController, OAuth2ResourceController): elif vendor == "google-checkout": claim_msg = vendor_claim_msg vendor_url = "https://wallet.google.com/manage" + elif vendor == "coinbase": + claim_msg = _("thanks for buying reddit gold! your transaction is " + "being processed. if you have any questions please " + "email us at %(gold_email)s") + claim_msg = claim_msg % {'gold_email': g.goldthanks_email} else: abort(404) diff --git a/r2/r2/controllers/ipn.py b/r2/r2/controllers/ipn.py index bbe2c045a..7e02777ce 100644 --- a/r2/r2/controllers/ipn.py +++ b/r2/r2/controllers/ipn.py @@ -765,6 +765,26 @@ class StripeController(GoldPaymentController): send_system_message(c.user, subject, msg) +class CoinbaseController(GoldPaymentController): + name = 'coinbase' + webhook_secret = g.COINBASE_WEBHOOK_SECRET + event_type_mappings = { + 'completed': 'succeeded', + 'cancelled': 'cancelled', + } + + @classmethod + def process_response(cls): + event_dict = json.loads(request.body) + g.log.debug('event_dict: %s' % event_dict) + order = event_dict['order'] + transaction_id = 'C%s' % order['id'] + status = order['status'] # new/completed/cancelled + pennies = int(order['total_native']['cents']) + passthrough = order['custom'] + return status, passthrough, transaction_id, pennies + + class GoldException(Exception): pass diff --git a/r2/r2/lib/pages/pages.py b/r2/r2/lib/pages/pages.py index 6d4928828..dfc74725d 100755 --- a/r2/r2/lib/pages/pages.py +++ b/r2/r2/lib/pages/pages.py @@ -1860,15 +1860,20 @@ class GoldPayment(Templated): quantity = None google_id = None stripe_key = None + coinbase_button_id = None elif goldtype == "onetime": if months < 12: paypal_buttonid = g.PAYPAL_BUTTONID_ONETIME_BYMONTH quantity = months + coinbase_name = 'COINBASE_BUTTONID_ONETIME_%sMO' % quantity + coinbase_button_id = getattr(g, coinbase_name, None) else: paypal_buttonid = g.PAYPAL_BUTTONID_ONETIME_BYYEAR quantity = months / 12 months = quantity * 12 + coinbase_name = 'COINBASE_BUTTONID_ONETIME_%sYR' % quantity + coinbase_button_id = getattr(g, coinbase_name, None) summary = strings.gold_summary_onetime % dict(user=c.user.name, amount=Score.somethings(months, "month")) @@ -1880,9 +1885,13 @@ class GoldPayment(Templated): if months < 12: paypal_buttonid = g.PAYPAL_BUTTONID_CREDDITS_BYMONTH quantity = months + coinbase_name = 'COINBASE_BUTTONID_ONETIME_%sMO' % quantity + coinbase_button_id = getattr(g, coinbase_name, None) else: paypal_buttonid = g.PAYPAL_BUTTONID_CREDDITS_BYYEAR quantity = months / 12 + coinbase_name = 'COINBASE_BUTTONID_ONETIME_%sYR' % quantity + coinbase_button_id = getattr(g, coinbase_name, None) if goldtype == "creddits": summary = strings.gold_summary_creddits % dict( @@ -1927,7 +1936,8 @@ class GoldPayment(Templated): google_id=google_id, comment=comment, clone_template=clone_template, paypal_buttonid=paypal_buttonid, - stripe_key=stripe_key) + stripe_key=stripe_key, + coinbase_button_id=coinbase_button_id) class CreditGild(Templated): diff --git a/r2/r2/public/static/css/reddit.css b/r2/r2/public/static/css/reddit.css index cbf722550..a79747f82 100755 --- a/r2/r2/public/static/css/reddit.css +++ b/r2/r2/public/static/css/reddit.css @@ -5337,6 +5337,7 @@ body:not(.gold) .allminus-link { border: 1px solid #E1B000; background-color: #fffdcc; color: #6a4d00; + width: 510px; } .gold-form .note { diff --git a/r2/r2/public/static/js/gold.js b/r2/r2/public/static/js/gold.js index 9f62b79c9..ab4ea0f69 100644 --- a/r2/r2/public/static/js/gold.js +++ b/r2/r2/public/static/js/gold.js @@ -44,7 +44,8 @@ r.gold = { var form = $('.gold-form.cloneable:first').clone(), authorName = $link.thing().find('.entry .author:first').text(), message = r.strings.gold_summary_comment_gift.replace('%(recipient)s', authorName), - passthroughs = form.find('.passthrough') + passthroughs = form.find('.passthrough'), + cbBaseUrl = form.find('[name="cbbaseurl"]').val() form.removeClass('cloneable') .attr('id', formId) @@ -65,6 +66,7 @@ r.gold = { form.removeClass('working') passthroughs.val(token) form.find('.stripe-gold').on('click', function() { window.open('/gold/creditgild/' + token) }) + form.find('.coinbase-gold').on('click', function() { window.open(cbBaseUrl + "?c=" + token) }) form.find('button').removeAttr('disabled').removeClass('disabled') }) diff --git a/r2/r2/templates/goldpayment.html b/r2/r2/templates/goldpayment.html index 3541a0d40..b623edb2f 100644 --- a/r2/r2/templates/goldpayment.html +++ b/r2/r2/templates/goldpayment.html @@ -61,6 +61,10 @@ ${self.paypal_button()} %endif + %if thing.coinbase_button_id: + ${self.coinbase_button()} + %endif + %if thing.stripe_key: ${self.stripe_button()} %endif @@ -224,6 +228,16 @@ +<%def name="coinbase_button()"> + + + + % if not thing.clone_template: