Skip to content

Commit 125eb3c

Browse files
committed
Merge pull request #12 from mhluongo/master
Add Payment Button Support
2 parents ad8d836 + db3fcfb commit 125eb3c

5 files changed

Lines changed: 75 additions & 4 deletions

File tree

coinbase/__init__.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
#from decimal import Decimal
4646

4747
from coinbase.config import COINBASE_ENDPOINT
48-
from coinbase.models import CoinbaseAmount, CoinbaseTransaction, CoinbaseUser, CoinbaseTransfer, CoinbaseError
48+
from coinbase.models import CoinbaseAmount, CoinbaseTransaction, CoinbaseUser, CoinbaseTransfer, CoinbaseError, CoinbasePaymentButton
4949

5050

5151
class CoinbaseAccount(object):
@@ -465,4 +465,49 @@ def generate_receive_address(self, callback_url=None):
465465
return response.json()['address']
466466

467467

468+
def create_button(self, name, price, price_currency='BTC',
469+
button_type='buy_now', callback_url=None,
470+
**kwargs):
471+
"""
472+
Create a new payment button, page, or iframe.
473+
474+
Some required parameters are documented, but the rest are supported
475+
as keyword-arguments.
476+
477+
See https://coinbase.com/api/doc/1.0/buttons/create.html for details.
468478
479+
:param name: The name of the item to be purchased, donated for, or
480+
subscribed.
481+
:param price: The price, in whatever currency specified. Preferably a
482+
string or Decimal.
483+
:param price_currency: The ISO currency in which the price is listed.
484+
Eg, BTC or USD.
485+
:param button_type: Choices are 'buy_now', 'donation', and
486+
'subscription'
487+
:param callback_url: The URL to receive instant payment notifications
488+
489+
:return: The embeddable HTML string
490+
"""
491+
url = COINBASE_ENDPOINT + '/buttons'
492+
request_data = {
493+
"button": {
494+
"name":name,
495+
"price_string":unicode(price),
496+
"price_currency_iso":price_currency,
497+
"button_type":button_type
498+
}
499+
}
500+
if callback_url is not None:
501+
request_data['button']['callback_url'] = callback_url
502+
request_data['button'].update(kwargs)
503+
response = self.session.post(url=url, data=json.dumps(request_data),
504+
params=self.global_request_params)
505+
resp_data = response.json()
506+
if not resp_data['success'] or 'button' not in resp_data:
507+
error_msg = 'Error creating button'
508+
if 'errors' in resp_data:
509+
error_msg += ':' + u'\n'.join(resp_data)
510+
else:
511+
error_msg += '.'
512+
raise RuntimeError(error_msg)
513+
return CoinbasePaymentButton(**resp_data['button'])

coinbase/models/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
from transfer import CoinbaseTransfer
66
from contact import CoinbaseContact
77
from user import CoinbaseUser
8-
from error import CoinbaseError
8+
from error import CoinbaseError
9+
from button import CoinbasePaymentButton

coinbase/models/button.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
__author__ = 'mhluongo'
2+
3+
class CoinbasePaymentButton(object):
4+
5+
def __init__(self, *args, **kwargs):
6+
for key, value in kwargs.iteritems():
7+
setattr(self, key, value)
8+

coinbase/tests.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,17 @@ def test_getting_user_details(self):
183183
user = self.account.get_user_details()
184184

185185
this(user.id).should.equal("509f01da12837e0201100212")
186-
this(user.balance).should.equal(1225.86084181)
186+
this(user.balance).should.equal(1225.86084181)
187+
188+
@httprettified
189+
def test_creating_a_button(self):
190+
191+
HTTPretty.register_uri(HTTPretty.POST, "https://coinbase.com/api/v1/buttons",
192+
body='''{"button": {"style": "buy_now_large", "code": "b123456783q812e381cd9d39a5783277", "name": "Test Button", "info_url": null, "text": "Pay With Bitcoin", "price": {"cents": 2000, "currency_iso": "USD"}, "include_email": false, "custom": "", "cancel_url": null, "auto_redirect": false, "success_url": null, "variable_price": false, "include_address": false, "callback_url": null, "type": "buy_now", "choose_price": false, "description": ""}, "success": true}''',
193+
content_type='text/json')
194+
195+
button = self.account.create_button('Test Button', '20.00', 'USD')
196+
197+
this(button.code).should.equal('b123456783q812e381cd9d39a5783277')
198+
this(button.name).should.equal('Test Button')
199+
this(button.price['cents']).should.equal(2000)

setup.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,9 @@
2525
'httplib2>=0.8',
2626
'requests>=1.1.0',
2727
'oauth2client>=1.1'
28-
]
28+
],
29+
tests_require=[
30+
'sure>=1.2.5',
31+
'httpretty>=0.8.0',
32+
],
2933
)

0 commit comments

Comments
 (0)