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
		
	
			
		
		
	
	
			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) ;
 |