|
|
|
@ -28,11 +28,39 @@ stripe.api_key = stripe_keys['secret_key'].strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
|
|
COUCHDB = Server(uri=CONFIG['couchdb']['uri']) ;
|
|
|
|
|
"""
|
|
|
|
|
This function will attempt to create an account for a user if the user does NOT exist
|
|
|
|
|
Then Setup the stage for initialization of {signup for, user-account}
|
|
|
|
|
This function will set the user information to the session and update the information
|
|
|
|
|
@header uid user email address
|
|
|
|
|
"""
|
|
|
|
|
COUCHDB = Server(uri=CONFIG['couchdb']['uri']) ;
|
|
|
|
|
@app.route("/init/<app_name>",methods=['POST'])
|
|
|
|
|
def init(app_name):
|
|
|
|
|
|
|
|
|
|
if 'uid' in request.headers:
|
|
|
|
|
uid = request.headers['uid']
|
|
|
|
|
couchdb = Couchdb(uri=CONFIG['couchdb']['uri'],dbname=app_name,uid=None)
|
|
|
|
|
DB = couchdb.dbase
|
|
|
|
|
handler = Domain.User(DB,stripe) ;
|
|
|
|
|
handler.init(uid,None)
|
|
|
|
|
|
|
|
|
|
id=handler.getId(uid)
|
|
|
|
|
session['customer.id'] = id
|
|
|
|
|
|
|
|
|
|
return ('',204)
|
|
|
|
|
"""
|
|
|
|
|
This function will update the user's email
|
|
|
|
|
"""
|
|
|
|
|
@app.route('/init/<app_name>',methods=['PUT'])
|
|
|
|
|
def init_update(app_name):
|
|
|
|
|
uid = request.headers['uid']
|
|
|
|
|
id = session['customer.id']
|
|
|
|
|
couchdb = Couchdb(uri=CONFIG['couchdb']['uri'],dbname=app_name,uid=None)
|
|
|
|
|
DB = couchdb.dbase
|
|
|
|
|
handler = Domain.User(DB,stripe)
|
|
|
|
|
handler.update_user(uid=uid,id=id)
|
|
|
|
|
|
|
|
|
|
return ('',204)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
This function subscribes a user to a given service for an application
|
|
|
|
@ -51,76 +79,68 @@ def subscribe(app_name):
|
|
|
|
|
uid = request.form['stripeEmail']
|
|
|
|
|
tokenType = request.form['stripeTokenType']
|
|
|
|
|
amount = request.form['amount']
|
|
|
|
|
key = request.form['plan']
|
|
|
|
|
pid = request.form['plan']
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
key = request.headers['key']
|
|
|
|
|
pid = request.headers['pid']
|
|
|
|
|
uid = request.headers['uid']
|
|
|
|
|
stripeToken = None
|
|
|
|
|
|
|
|
|
|
plans = stripe.Plan.list().data
|
|
|
|
|
plan = [item for item in plans if item.id == key]
|
|
|
|
|
plan = [item for item in plans if item.id == pid]
|
|
|
|
|
resp = "0"
|
|
|
|
|
|
|
|
|
|
couch_handler = Couchdb(uri=CONFIG['couchdb']['uri'],dbname=app_name,uid=uid)
|
|
|
|
|
DB = couch_handler.dbase
|
|
|
|
|
handler = Domain.User(DB,stripe,stripeToken) ;
|
|
|
|
|
|
|
|
|
|
if plan :
|
|
|
|
|
handler.init(uid,plan)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
resp = plan[0].id
|
|
|
|
|
|
|
|
|
|
return ('done',204)
|
|
|
|
|
return ('',204)
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
This function returns the meta data about a given plan or set of plans for a given application
|
|
|
|
|
@resource app_name application identifier
|
|
|
|
|
@header pid plan identifier (optional)
|
|
|
|
|
@header uid user identifier
|
|
|
|
|
This function returns the features of a user for a given application
|
|
|
|
|
The features are returned provided the plan is still valid i.e (end_date,status={active|trailing})
|
|
|
|
|
@header uid user's email
|
|
|
|
|
"""
|
|
|
|
|
@app.route('/get/info/<app_name>',methods=['GET'])
|
|
|
|
|
def get_plan_info(app_name) :
|
|
|
|
|
@app.route('/features/<app_name>')
|
|
|
|
|
def features(app_name):
|
|
|
|
|
plans = []
|
|
|
|
|
print ' *** ','uid' in request.headers
|
|
|
|
|
if 'uid' in request.headers :
|
|
|
|
|
uid = request.headers['uid']
|
|
|
|
|
pid = request.headers['pid'] if 'pid' in request.headers else None
|
|
|
|
|
|
|
|
|
|
couchdb = CouchdbReader(uri=CONFIG['couchdb']['uri'],dbname=app_name,uid=uid,create=False)
|
|
|
|
|
info = couchdb.read()
|
|
|
|
|
lsub = info['subscriptions']
|
|
|
|
|
handler = Domain.User(couchdb.dbase,stripe)
|
|
|
|
|
handler.initialize(uid)
|
|
|
|
|
lsub = handler.subscriptions()
|
|
|
|
|
|
|
|
|
|
plans = [ sub['plan'] for sub in lsub if sub['ended_at'] is None ]
|
|
|
|
|
if pid is not None :
|
|
|
|
|
plans = [item['metadata'] for item in plans if item['id'] == pid]
|
|
|
|
|
else:
|
|
|
|
|
#
|
|
|
|
|
# This function returns the plans for a given application
|
|
|
|
|
# We assume the application name is the prefix of the plan identifier in stripe
|
|
|
|
|
#
|
|
|
|
|
plans = stripe.Plan.list(limit=10)
|
|
|
|
|
handler = Domain.User(None)
|
|
|
|
|
plans = handler.cast(plans.data)
|
|
|
|
|
|
|
|
|
|
plans = [item for item in plans if re.match(app_name,item['name'])]
|
|
|
|
|
plans = [item['metadata'] for item in plans if item['id']]
|
|
|
|
|
|
|
|
|
|
return json.dumps(plans)
|
|
|
|
|
@app.route('/get/sub/<app_name>')
|
|
|
|
|
def get_sub_info(app_name):
|
|
|
|
|
"""
|
|
|
|
|
This function returns a user's plans/status for an application
|
|
|
|
|
@header uid user's email address
|
|
|
|
|
"""
|
|
|
|
|
@app.route('/status/<app_name>')
|
|
|
|
|
def status(app_name):
|
|
|
|
|
|
|
|
|
|
uid = request.headers['uid']
|
|
|
|
|
pid = request.headers['pid'] if 'pid' in request.headers else None
|
|
|
|
|
|
|
|
|
|
couchdb = CouchdbReader(uri=CONFIG['couchdb']['uri'],dbname=app_name,uid=uid,create=False)
|
|
|
|
|
info = couchdb.read()
|
|
|
|
|
lsub = info['subscriptions']
|
|
|
|
|
#
|
|
|
|
|
# @TODO: Return critical information only i.e:
|
|
|
|
|
# - subscription state (dates,status)
|
|
|
|
|
# - how much is owed
|
|
|
|
|
# - subscription id
|
|
|
|
|
#
|
|
|
|
|
if pid is not None:
|
|
|
|
|
subs = [ sub for sub in lsub if sub['plan']['id'] == pid ]
|
|
|
|
|
else:
|
|
|
|
|
subs = lsub
|
|
|
|
|
return json.dumps(subs)
|
|
|
|
|
@app.route('/get/plans/<app_name>')
|
|
|
|
|
handler = Domain.User(couchdb.dbase,stripe)
|
|
|
|
|
handler.initialize(uid)
|
|
|
|
|
#lsub = handler.subscriptions()
|
|
|
|
|
plans = handler.plans()
|
|
|
|
|
return json.dumps(plans)
|
|
|
|
|
"""
|
|
|
|
|
This endpoint is the signup form for a given application,
|
|
|
|
|
It will allow user's to be able to signup for various plans
|
|
|
|
|
@pre 'uid' in request.headers
|
|
|
|
|
"""
|
|
|
|
|
@app.route('/signup/<app_name>')
|
|
|
|
|
def get_plans(app_name) :
|
|
|
|
|
apikey = CONFIG['stripe']['pub'].strip()
|
|
|
|
|
#
|
|
|
|
@ -129,10 +149,22 @@ def get_plans(app_name) :
|
|
|
|
|
#
|
|
|
|
|
uid = session['uid'] if 'uid' in session else 'nyemba@gmail.com'
|
|
|
|
|
plans = stripe.Plan.list(limit=10)
|
|
|
|
|
handler = Domain.User(None)
|
|
|
|
|
plans = handler.cast(plans.data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# plans = handler.cast(plans.data)
|
|
|
|
|
plans = json.loads(json.dumps(plans.data, sort_keys=True, indent=2))
|
|
|
|
|
|
|
|
|
|
plans = [item for item in plans if re.match(app_name,item['name'])]
|
|
|
|
|
if uid is not None:
|
|
|
|
|
couchdb = Couchdb(uri=CONFIG['couchdb']['uri'],dbname=app_name,uid=uid,create=False)
|
|
|
|
|
handler = Domain.User(couchdb.dbase,stripe)
|
|
|
|
|
|
|
|
|
|
handler.init(uid,[])
|
|
|
|
|
subs = handler.subscriptions().data
|
|
|
|
|
ids = [item.id for item in subs]
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# @TODO: Mark the plans the current user is signed up for
|
|
|
|
|
#
|
|
|
|
|
return render_template('subscribe.html',uid=uid,app_name=app_name,plans=plans,apikey=apikey)
|
|
|
|
|
|
|
|
|
|
@app.route('/subscribe/<name>',methods=['DELETE'])
|
|
|
|
@ -191,132 +223,6 @@ def is_customer (app_name):
|
|
|
|
|
html = html.replace(":email",uid).replace(":amount",str(amount)).replace(":key",apikey).replace(":app_name",app_name)
|
|
|
|
|
amount = amount / 100
|
|
|
|
|
return render_template('bill.html',apikey=apikey,app_name=app_name.replace('-',' '),plans=plans,total_amount=amount,html=html)
|
|
|
|
|
"""
|
|
|
|
|
This function is intended to performa an actual payment
|
|
|
|
|
"""
|
|
|
|
|
@app.route('/pay/<app_name>',methods=['POST'])
|
|
|
|
|
def pay(app_name):
|
|
|
|
|
|
|
|
|
|
token = request.form['stripeToken']
|
|
|
|
|
uid = request.form['stripeEmail']
|
|
|
|
|
tokenType = request.form['stripeTokenType']
|
|
|
|
|
couchdb = CouchdbReader(uri=CONFIG['couchdb']['uri'],dbname=app_name,uid=uid,create=False)
|
|
|
|
|
|
|
|
|
|
DB = couchdb.dbase #COUCHDB.get_db(CONFIG['couchdb']['db']) ;
|
|
|
|
|
handler = Domain.User(DB,stripe) ;
|
|
|
|
|
plans = session['plans']
|
|
|
|
|
# Assuming all is fine, we must do the following at this point
|
|
|
|
|
# - create an invoice with the designated subscriptions
|
|
|
|
|
# - create a charge on the invoice
|
|
|
|
|
#
|
|
|
|
|
#items = handler.invoice(uid,plans)
|
|
|
|
|
|
|
|
|
|
handler.charge(uid,token,plans)
|
|
|
|
|
# Let's insure the preconditions are met i.e
|
|
|
|
|
# card,invoice
|
|
|
|
|
#info = session['user-info']
|
|
|
|
|
#uid = info['_id']
|
|
|
|
|
#if 'sources' not in info or token not in info['sources']:
|
|
|
|
|
#
|
|
|
|
|
# Let's create the card
|
|
|
|
|
# handler.save_card(uid,token)
|
|
|
|
|
#
|
|
|
|
|
# Let's create a charge here ...
|
|
|
|
|
#plans = session['user-plans']
|
|
|
|
|
|
|
|
|
|
#amount=[item['price'] for item in plans if item['status'] == 'past_due' ]
|
|
|
|
|
#if len(amount) == 0:
|
|
|
|
|
# amount = 0
|
|
|
|
|
#else:
|
|
|
|
|
# amount = sum(amount)
|
|
|
|
|
#handler.charge(uid,amount)
|
|
|
|
|
session['user-info'] = handler.user
|
|
|
|
|
return ('',204)
|
|
|
|
|
#return render_template("bill.html",plans=plans, total_amount=amount)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/bill',methods=['GET'])
|
|
|
|
|
def bill():
|
|
|
|
|
return render_template('bill.html')
|
|
|
|
|
@app.route('/buy',methods=['POST'])
|
|
|
|
|
def buy():
|
|
|
|
|
id = request.form['id'] ;
|
|
|
|
|
|
|
|
|
|
if id in ['subscribe','now']:
|
|
|
|
|
email = request.form['stripeEmail']
|
|
|
|
|
token = request.form['stripeToken']
|
|
|
|
|
user = Domain.User(DB,stripe,token) ;
|
|
|
|
|
user.init(email) ;
|
|
|
|
|
if user.exists() :
|
|
|
|
|
print "Update with anything if need be"
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
#
|
|
|
|
|
# Create the user with the associated plan/or payment method
|
|
|
|
|
#
|
|
|
|
|
user.save() ;
|
|
|
|
|
user.publish()
|
|
|
|
|
else:
|
|
|
|
|
pass
|
|
|
|
|
return "0"
|
|
|
|
|
"""
|
|
|
|
|
This function provides general information about service plans
|
|
|
|
|
@TODO: provide filtering criteria
|
|
|
|
|
"""
|
|
|
|
|
@app.route('/plans',methods=['GET'])
|
|
|
|
|
def plans():
|
|
|
|
|
plans = stripe.Plan.list().data
|
|
|
|
|
if 'filter' in request.headers:
|
|
|
|
|
filter = request.headers['filter']
|
|
|
|
|
|
|
|
|
|
plans = [ item for item in plans if re.match(filter,item.name)]
|
|
|
|
|
else:
|
|
|
|
|
#
|
|
|
|
|
# Let's get a user's subscription information
|
|
|
|
|
#
|
|
|
|
|
uid = request.headers['uid']
|
|
|
|
|
|
|
|
|
|
if 'uid' in request.headers and request.headers['uid'] != '':
|
|
|
|
|
uid = request.headers['uid']
|
|
|
|
|
DB = COUCHDB.get_db(CONFIG['couchdb']['db']) ;
|
|
|
|
|
handler = Domain.User(DB)
|
|
|
|
|
handler.init(uid)
|
|
|
|
|
myplans = [{"id":item.plan.id,"price":item.plan.amount/100,"feature":item.plan.metadata['info'],"status":item.status} for item in handler.subscriptions()]
|
|
|
|
|
keys = [plan['id'] for plan in myplans]
|
|
|
|
|
plans = [plan for plan in plans if plan['price'] > 0 and plan['id'] not in keys]
|
|
|
|
|
plans = {'myplans':myplans,"plans":plans}
|
|
|
|
|
session['user-plans'] = myplans
|
|
|
|
|
plans = json.dumps(plans)
|
|
|
|
|
return plans
|
|
|
|
|
"""
|
|
|
|
|
This function subscribes a user to a given plan(s)
|
|
|
|
|
If the plan is new, then we do NOT need a credit card info
|
|
|
|
|
|
|
|
|
|
@header app application/requesting service
|
|
|
|
|
@body info {user:_id,plan:[]}
|
|
|
|
|
"""
|
|
|
|
|
@app.route('/_subscribe',methods=['POST'])
|
|
|
|
|
def _subscribe():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if 'user-info' not in session:
|
|
|
|
|
info = request.get_json(silent=True)
|
|
|
|
|
user = info['user']
|
|
|
|
|
plans = info['plans']
|
|
|
|
|
else:
|
|
|
|
|
plans = [{"id":id} for id in request.get_json(silent=True)]
|
|
|
|
|
user = session['user-info']
|
|
|
|
|
app = request.headers['app']
|
|
|
|
|
#
|
|
|
|
|
# @TODO:
|
|
|
|
|
# This should be handled by transport layer ...
|
|
|
|
|
#
|
|
|
|
|
DB = COUCHDB.get_db(CONFIG['couchdb']['db']) ;
|
|
|
|
|
handler = Domain.User(DB,stripe)
|
|
|
|
|
r = handler.subscribe(user['id'],plans)
|
|
|
|
|
return json.dumps(r)
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__' :
|
|
|
|
|
app.debug = True ;
|
|
|
|
|