You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
5.2 KiB
Python

"""
This class is designed to handle Clients
"""
import stripe
from couchdbkit import Server, Document
import json
from sets import Set
class User:
def __init__(self,db,stripe=None,stripeToken=None) :
self.db = db
self.stripe = stripe;
self.stripeToken= stripeToken
self.user = None
"""
This function will cast an object to JSON,
It is designed to address an inherent limitation of stripe object hierarchy
"""
def cast(self,object) :
return json.loads(json.dumps(object, sort_keys=True, indent=2))
"""
This function creates a stripe customer, and saves a copy with us for internal use
We use couchdb as a cache of sorts
"""
def init (self,uid,plans):
customer = {}
if self.db.doc_exist(uid) :
self.user = self.db.get(uid)
# self.hasPlan(uid,plan)
has_plan = True
if self.user is None and plans and stripe :
#
# First time customer, register them and sign them up for the first plan
#
customer['source'] = str(self.stripeToken)
customer = self.stripe.Customer.create(
source=self.stripeToken,
email=uid
) ;
has_plan = False
id = customer['id']
self.user = {"_id":uid,"id":id}
else:
#
# The user exists but let's see if the user is subscribed to this plan
# If she is and the plan is still live then there is nothing to do
#
self.user = self.db.get(uid) ;
id = self.user['id']
lsub = self.subscriptions()
lplans = [str(item['plan']['id']) for item in lsub.data if item.ended_at in [None,""]]
x_plans = [item['id'] for item in plans]
if lplans and not set(x_plans) - set(lplans) :
has_plans = False
x = list(set(x_plans) - set(lplans))
plans = [ item for item in plans if item.id in x]
else:
has_plan = False
if has_plan == False :
r = self.subscribe(id,plans)
lsub.data.append(r[0])
#
# Backing up the information to be processed later
# - We assume any interaction with the payment classes will start by updating information associated operation
lsub = self.cast(lsub.data)
self.user['subscriptions'] = lsub
self.db.save_doc(self.user)
def subscriptions(self):
#
# call stripe to retrieve subscriptions for this user ...
#
if self.user :
r = stripe.Customer.retrieve(self.user['id'])
return r.subscriptions
else:
return []
"""
This function subscribes a customer to n-plans
@pre isinstance(plans,list)
"""
def subscribe(self,id,plans):
r = []
for plan in plans:
x = self.stripe.Subscription.create(
customer=id,
plan=plan['id']
) ;
#
# We need to create an invoiced item out of this plan
# We will attach it later to an invoice ...
#
r.append(x)
return r
"""
This function will save card information
"""
def save_card(self,uid,token):
user = self.db.get(uid)
if 'sources' not in user or (token not in user['sources']):
#
# In this case we don't have a card
#
id = user['id']
customer = stripe.Customer.retrieve(id)
card = customer.sources.create(source = token)
if 'sources' not in user:
user['sources'] = []
user['sources'].append(card['id'])
self.db.save_doc(user) ;
self.user = user
def invoice(self,uid,plans,iid):
self.user = self.db.get(uid)
id = self.user['id']
r = [ stripe.InvoiceItem.create(customer=id,amount=item['amount'],currency=item['currency'],description=item['statement_descriptor'],subscription=item['subscription'],invoice=iid) for item in plans]
return r
"""
This function creates an invoice
@pre : an item with amount > 0 and status past_due
"""
def get_invoices(self,uid):
info = self.db.get(uid)
id = info['id']
#return stripe.Invoice.list(customer=id)
"""
This function will clear a particular invoice (hopefully). No partial payments should be accepted
@pre : card,invoice
"""
def charge(self,uid,token,plans):
info = self.db.get(uid)
id = info['id']
sid = plans[0]['subscription']
user = stripe.Customer.retrieve(id)
user.source = token
user.save()
for plan in plans:
sid = plan['subscription']
if plan['amount'] > 0 :
print [' *** ',plan['amount']]
_invoice= stripe.Invoice.create(customer=id,subscription=sid)
r = _invoice.pay()
print r
"""
This function is designed to determine if the user exists or not
We will check the couchdb and the stripe backend
"""
def exists(self,uid):
return self.db.doc_exist(uid)
# return self.user is not None ;
"""
This function will store the user within our system
"""
def attach(self,attachment,name,mime):
self.db.put_attachment(self.user,attachment,name,mime) ;
def save(self,uid=None):
if self.exists() == False:
self.init(uid) ;
else:
#perform an update
pass
"""
This function updates/creates a user remotely
@pre:
"""
def publish(self,info={}):
# We need to figure out whether to create or update;
#
if self.user is not None and info is not None:
customer = self.stripe.Customer.retrieve(self.user['id']) ;
customer.metadata = info ;
customer.save() ;
#f = open('config.json')
#conf = json.loads(f.read())
#f.close()
#server = Server(uri=conf['couchdb']['uri']) ;
#db = server.get_db(conf['couchdb']['db']) ;
#print db.doc_exist('steve@gmail.com')
#doc = db.get('steve@gmail.com')
#doc['type'] = 'business'
#db.save_doc(doc) ;