Visitar URL original
Integrate Impressive Changes by sibblegp · Pull Request #9 · sibblegp/coinbase_python · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Initial code and tests for Button and API support
  • Loading branch information
sdobz committed Jan 5, 2014
commit 4b38c33013fc667bde4205c34518ed089534de3e
128 changes: 126 additions & 2 deletions coinbase/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
#TODO: Switch to decimals from floats
#from decimal import Decimal

from coinbase.config import COINBASE_ENDPOINT
from coinbase.models import CoinbaseAmount, CoinbaseTransaction, CoinbaseUser, CoinbaseTransfer, CoinbaseError
from .config import COINBASE_ENDPOINT, COINBASE_ITEMS_PER_PAGE
from .models import CoinbaseAmount, CoinbaseTransaction, CoinbaseUser, CoinbaseTransfer, CoinbaseError, CoinbaseButton, CoinbaseOrder


class CoinbaseAccount(object):
Expand Down Expand Up @@ -464,5 +464,129 @@ def generate_receive_address(self, callback_url=None):
response = self.session.post(url=url, data=json.dumps(request_data), params=self.global_request_params)
return response.json()['address']

def create_button(self, name,
price,
currency='BTC',
type=None,
style=None,
text=None,
description=None,
custom=None,
callback_url=None,
success_url=None,
cancel_url=None,
info_url=None,
variable_price=None,
choose_price=None,
include_address=None,
include_email=None,
price1=None, price2=None, price3=None, price4=None, price5=None):
"""
Create a new button
:param name: The name of the item for which you are collecting bitcoin.
:param price: The price of the item
:param currency: The currency to charge
:param type: One of buy_now, donation, and subscription. Default is buy_now.
:param style: One of buy_now_large, buy_now_small, donation_large, donation_small, subscription_large, subscription_small, custom_large, custom_small, and none. Default is buy_now_large. none is used if you plan on triggering the payment modal yourself using your own button or link.
:param text: Allows you to customize the button text on custom_large and custom_small styles. Default is Pay With Bitcoin.
:param description: Longer description of the item in case you want it added to the user's transaction notes.
:param custom: An optional custom parameter. Usually an Order, User, or Product ID corresponding to a record in your database.
:param callback_url: A custom callback URL specific to this button.
:param success_url: A custom success URL specific to this button. The user will be redirected to this URL after a successful payment.
:param cancel_url: A custom cancel URL specific to this button. The user will be redirected to this URL after a canceled order.
:param info_url: A custom info URL specific to this button. Displayed to the user after a successful purchase for sharing.
:param variable_price: Allow users to change the price on the generated button.
:param choose_price: Show some suggested prices
:param include_address: Collect shipping address from customer (not for use with inline iframes).
:param include_email: Collect email address from customer (not for use with inline iframes).
:param price1: Suggested price 1
:param price2: Suggested price 2
:param price3: Suggested price 3
:param price4: Suggested price 4
:param price5: Suggested price 5
:return: A CoinbaseButton object
"""
url = COINBASE_ENDPOINT + '/buttons'
price = str(price)

request_data = {
"button": {
"name": name,
"price": price,
"currency": currency,
"type": type,
"style": style,
"text": text,
"description": description,
"custom": custom,
"callback_url": callback_url,
"success_url": success_url,
"cancel_url": cancel_url,
"info_url": info_url,
"variable_price": variable_price,
"choose_price": choose_price,
"include_address": include_address,
"include_email": include_email,
"price1": price1,
"price2": price2,
"price3": price3,
"price4": price4,
"price5": price5
}
}
none_keys = [key for key in request_data['button'].keys() if request_data['button'][key] is None]
for key in none_keys:
del request_data['button'][key]

response = self.session.post(url=url, data=json.dumps(request_data), params=self.global_request_params)
return CoinbaseButton(response.json()['button'])

def create_order(self, code):
"""
Generate a new order from a button
:param code: The code of the button for which you wish to create an order
:return: A CoinbaseOrder object
"""
url = COINBASE_ENDPOINT + '/buttons/{code}/create_order'.format(code=code)

response = self.session.post(url=url, params=self.global_request_params)
return CoinbaseOrder(response.json()['order'])

def get_order(self, order_id):
"""
Get an order by id
:param order_id: The order id to be retrieved
:return: A CoinbaseOrder object
"""
url = COINBASE_ENDPOINT + '/orders/{id}'.format(id=order_id)

response = self.session.get(url=url, params=self.global_request_params)
return CoinbaseOrder(response.json()['order'])

def orders(self, count=30):
"""
Retrieve the list of orders for the current account
:param count: How many orders to retrieve
:return: List of CoinbaseOrder objects
"""
url = COINBASE_ENDPOINT + '/orders'
pages = count / 30 + 1
orders = []

reached_final_page = False

for page in xrange(1, pages + 1):

if not reached_final_page:
params = {'page': page}
params.update(self.global_request_params)
response = self.session.get(url=url, params=params)
parsed_orders = response.json()

if parsed_orders['num_pages'] == page:
reached_final_page = True

for order in parsed_orders['orders']:
orders.append(CoinbaseOrder(order['order']))

return orders
6 changes: 5 additions & 1 deletion coinbase/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@


TEMP_CREDENTIALS = '''
{"_module": "oauth2client.client", "token_expiry": "2013-03-24T02:37:50Z", "access_token": "2a02d1fc82b1c42d4ea94d6866b5a232b53a3a50ad4ee899ead9afa6144c2ca3", "token_uri": "https://www.coinbase.com/oauth/token", "invalid": false, "token_response": {"access_token": "2a02d1fc82b1c42d4ea94d6866b5a232b53a3a50ad4ee899ead9afa6144c2ca3", "token_type": "bearer", "expires_in": 7200, "refresh_token": "ffec0153da773468c8cb418d07ced54c13ca8deceae813c9be0b90d25e7c3d71", "scope": "all"}, "client_id": "2df06cb383f4ffffac20e257244708c78a1150d128f37d420f11fdc069a914fc", "id_token": null, "client_secret": "7caedd79052d7e29aa0f2700980247e499ce85381e70e4a44de0c08f25bded8a", "revoke_uri": "https://accounts.google.com/o/oauth2/revoke", "_class": "OAuth2Credentials", "refresh_token": "ffec0153da773468c8cb418d07ced54c13ca8deceae813c9be0b90d25e7c3d71", "user_agent": null}'''
{"_module": "oauth2client.client", "token_expiry": "2013-03-24T02:37:50Z", "access_token": "2a02d1fc82b1c42d4ea94d6866b5a232b53a3a50ad4ee899ead9afa6144c2ca3", "token_uri": "https://www.coinbase.com/oauth/token", "invalid": false, "token_response": {"access_token": "2a02d1fc82b1c42d4ea94d6866b5a232b53a3a50ad4ee899ead9afa6144c2ca3", "token_type": "bearer", "expires_in": 7200, "refresh_token": "ffec0153da773468c8cb418d07ced54c13ca8deceae813c9be0b90d25e7c3d71", "scope": "all"}, "client_id": "2df06cb383f4ffffac20e257244708c78a1150d128f37d420f11fdc069a914fc", "id_token": null, "client_secret": "7caedd79052d7e29aa0f2700980247e499ce85381e70e4a44de0c08f25bded8a", "revoke_uri": "https://accounts.google.com/o/oauth2/revoke", "_class": "OAuth2Credentials", "refresh_token": "ffec0153da773468c8cb418d07ced54c13ca8deceae813c9be0b90d25e7c3d71", "user_agent": null}'''

CENTS_PER_BITCOIN = 100000000
CENTS_PER_OTHER = 100
COINBASE_ITEMS_PER_PAGE = 30
4 changes: 3 additions & 1 deletion coinbase/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@
from transfer import CoinbaseTransfer
from contact import CoinbaseContact
from user import CoinbaseUser
from error import CoinbaseError
from error import CoinbaseError
from button import CoinbaseButton
from order import CoinbaseOrder
46 changes: 46 additions & 0 deletions coinbase/models/button.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
__author__ = 'vkhougaz'

from amount import CoinbaseAmount
from decimal import Decimal
from coinbase.config import CENTS_PER_BITCOIN, CENTS_PER_OTHER

class CoinbaseButton(object):

def __init__(self, button):
# Sometimes it's called code (create button) and sometimes id (sub item of create button)
# so we map them together
if 'id' in button:
self.button_id = button['id']
if 'code' in button:
self.button_id = button['code']
self.code = self.button_id

self.name = button['name']
if 'price' in button:
price = Decimal(button['price']['cents'])
price_currency_iso = button['price']['currency_iso']
if price_currency_iso == 'BTC':
price /= CENTS_PER_BITCOIN
else:
price /= CENTS_PER_OTHER
self.price = CoinbaseAmount(price, price_currency_iso)
else:
self.price = None
self.type = button.get('type', None)
self.style = button.get('style', None)
self.text = button.get('text', None)
self.description = button.get('description', None)
self.custom = button.get('custom', None)
self.callback_url = button.get('callback_url', None)
self.success_url = button.get('success_url', None)
self.cancel_url = button.get('cancel_url', None)
self.info_url = button.get('info_url', None)
self.variable_price = button.get('variable_price', None)
self.choose_price = button.get('choose_price', None)
self.include_address = button.get('include_address', None)
self.include_email = button.get('include_email', None)
self.price1 = button.get('price1', None)
self.price2 = button.get('price2', None)
self.price3 = button.get('price3', None)
self.price4 = button.get('price4', None)
self.price5 = button.get('price4', None)
38 changes: 38 additions & 0 deletions coinbase/models/order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
__author__ = 'vkhougaz'

from amount import CoinbaseAmount
from button import CoinbaseButton
from transaction import CoinbaseTransaction
from decimal import Decimal
from coinbase.config import CENTS_PER_BITCOIN, CENTS_PER_OTHER
# from datetime import datetime

class CoinbaseOrder(object):
def __init__(self, order):
self.id = order['id']
# TODO: Account for timezone properly
#self.created_at = datetime.strptime(order['created_at'], '%Y-%m-%dT%H:%M:%S-08:00')
self.created_at = order['created_at']
self.status = order['status']

btc_cents = Decimal(order['total_btc']['cents'])
btc_currency_iso = order['total_btc']['currency_iso']
if btc_currency_iso == 'BTC':
btc_cents /= CENTS_PER_BITCOIN
else:
btc_cents /= CENTS_PER_OTHER
self.total_btc = CoinbaseAmount(btc_cents, btc_currency_iso)

native_cents = order['total_native']['cents']
native_currency_iso = order['total_native']['currency_iso']
if native_currency_iso == 'BTC':
native_cents /= CENTS_PER_BITCOIN
else:
native_cents /= CENTS_PER_OTHER
self.total_native = CoinbaseAmount(native_cents, native_currency_iso)

self.button = CoinbaseButton(order['button'])
if 'transaction' in order and order['transaction'] is not None:
self.transaction = CoinbaseTransaction(order['transaction'])
else:
self.transaction = None
18 changes: 10 additions & 8 deletions coinbase/models/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@ class CoinbaseTransaction(object):
def __init__(self, transaction):

self.transaction_id = transaction['id']
self.created_at = transaction['created_at']
self.notes = transaction['notes']
self.created_at = transaction.get('created_at', None)
self.notes = transaction.get('notes', '')

transaction_amount = transaction['amount']['amount']
transaction_currency = transaction['amount']['currency']

self.amount = CoinbaseAmount(transaction_amount, transaction_currency)
if 'amount' in transaction:
transaction_amount = transaction['amount']['amount']
transaction_currency = transaction['amount']['currency']
self.amount = CoinbaseAmount(transaction_amount, transaction_currency)
else:
self.amount = None

self.status = transaction['status']
self.request = transaction['request']
self.status = transaction.get('status', None)
self.request = transaction.get('request', None)


#Sender Information
Expand Down
Loading