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>
+<%def name="coinbase_button()">
+
+
+%def>
+
% if not thing.clone_template: