changes required ... @TODO: Finish identity federation with views

legacy
Steve L. Nyemba 8 years ago
parent 384c4e3aa1
commit ad400e6646

100
.gitignore vendored

@ -1,94 +1,6 @@
# ---> Python sandbox
# Byte-compiled / optimized / DLL files *.pyc
__pycache__/ *.swp
*.py[cod] *.swo
*$py.class .gitignore
config.json
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# ---> Android
# Built application files
*.apk
*.ap_
# Files for the Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/

@ -14,5 +14,15 @@ start(){
stop(){ stop(){
ps -eo pid,command |grep python |grep $PWD |grep -E "^ {0,}[0-9]+" -o |xargs kill -9 ps -eo pid,command |grep python |grep $PWD |grep -E "^ {0,}[0-9]+" -o |xargs kill -9
} }
check(){
pid=`ps -eo pid,command |grep python |grep $PWD |grep -E "^ {0,}[0-9]+" -o`
if [ "$pid" ]; then
echo "*** Online $pid"
else
echo "*** Offline"
fi
}
status(){
check
}
$1 $1

@ -1,5 +1,10 @@
""" """
This class is designed to handle Clients This class is designed to handle Customers in coordination with stripes.
Identity Federation
A user with several emails should not have to pay for a service more than once because she has several email/cloud accounts.
We have therefore decided to tie several emails to a stripe customer identity
""" """
import stripe import stripe
from couchdbkit import Server, Document from couchdbkit import Server, Document
@ -23,27 +28,47 @@ class User:
""" """
This function creates a stripe customer, and saves a copy with us for internal use This function creates a stripe customer, and saves a copy with us for internal use
We use couchdb as a cache of sorts We use couchdb as a cache of sorts
""" @param uid customer's email
@param plans list of plans the user is subscribing
"""
def getId(self,uid):
r = self.db.view('federation/ids',key=uid)
if r.count() > 0 :
r = r.first()
return r['value']
else:
None
def init (self,uid,plans): def init (self,uid,plans):
customer = {} customer = {}
if self.db.doc_exist(uid) : id = self.getId(uid)
self.user = self.db.get(uid) if id is not None:
self.user = self.db.get(id)
# if self.db.doc_exist(uid) :
# self.user = self.db.get(uid)
if self.stripeToken is not None:
if 'sources' not in self.user or self.user['sources'] is None:
#@TODO: get the appropriate id
customer = stripe.Customer.retrieve(self.user['id'])
customer.source=self.stripeToken
customer.save()
# self.hasPlan(uid,plan) # self.hasPlan(uid,plan)
has_plan = True has_plan = True
if self.user is None and plans and stripe : if self.user is None and plans and stripe :
# #
# First time customer, register them and sign them up for the first plan # First time customer, register them and sign them up for the first plan
# #
customer['source'] = str(self.stripeToken) customer['sources'] = str(self.stripeToken)
customer = self.stripe.Customer.create( customer = self.stripe.Customer.create(
source=self.stripeToken, source=self.stripeToken,
email=uid email=uid
) ; ) ;
has_plan = False has_plan = False
id = customer['id'] id = customer['id']
self.user = {"_id":uid,"id":id} self.user = {"_id":uid,"id":id,"source":self.stripeToken}
else: else:
# #
# The user exists but let's see if the user is subscribed to this plan # The user exists but let's see if the user is subscribed to this plan
@ -52,7 +77,10 @@ class User:
self.user = self.db.get(uid) ; self.user = self.db.get(uid) ;
id = self.user['id'] id = self.user['id']
#
# If this user's isn't already subscribed we should subscribe her
# We perform a set operation to determine if she is alread susbscribed
#
lsub = self.subscriptions() lsub = self.subscriptions()
lplans = [str(item['plan']['id']) for item in lsub.data if item.ended_at in [None,""]] lplans = [str(item['plan']['id']) for item in lsub.data if item.ended_at in [None,""]]
x_plans = [item['id'] for item in plans] x_plans = [item['id'] for item in plans]
@ -62,7 +90,9 @@ class User:
x = list(set(x_plans) - set(lplans)) x = list(set(x_plans) - set(lplans))
plans = [ item for item in plans if item.id in x] plans = [ item for item in plans if item.id in x]
else: else:
#
# In case the user doesn't have any plans with us
#
has_plan = False has_plan = False
if has_plan == False : if has_plan == False :
@ -93,15 +123,28 @@ class User:
def subscribe(self,id,plans): def subscribe(self,id,plans):
r = [] r = []
for plan in plans: for plan in plans:
x = self.stripe.Subscription.create( if self.stripeToken is None:
customer=id, sub = self.stripe.Subscription.create(
plan=plan['id'] customer=id,
) ; plan=plan['id']
) ;
else:
customer = stripe.Customer.retrieve(id)
self.user['sources'] = self.cast(customer.sources)
sub = self.stripe.Subscription.create(
customer=id,
plan=plan['id'],
source=self.stripeToken
) ;
r.append(sub)
# #
# We need to create an invoiced item out of this plan # We need to create an invoiced item out of this plan
# We will attach it later to an invoice ... # We will attach it later to an invoice ...
# #
r.append(x) #r.append(x)
return r return r
""" """
This function will save card information This function will save card information
@ -122,7 +165,9 @@ class User:
self.db.save_doc(user) ; self.db.save_doc(user) ;
self.user = user self.user = user
def invoice(self,uid,plans,iid): #
# Creating an invoice for this user
def invoice(self,uid,sid):
self.user = self.db.get(uid) self.user = self.db.get(uid)
id = self.user['id'] 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] 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]

@ -45,19 +45,32 @@ def subscribe(app_name):
# #
# The name is the full name of the service # The name is the full name of the service
# #
resp = "0"
if 'stripeToken' in request.form :
stripeToken = request.form['stripeToken']
uid = request.form['stripeEmail']
tokenType = request.form['stripeTokenType']
amount = request.form['amount']
key = request.form['plan']
key = request.headers['key'] else:
uid = request.headers['uid'] key = request.headers['key']
uid = request.headers['uid']
stripeToken = None
plans = stripe.Plan.list().data plans = stripe.Plan.list().data
plan = [item for item in plans if item.id == key] plan = [item for item in plans if item.id == key]
resp = "0" 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 : if plan :
couch_handler = Couchdb(uri=CONFIG['couchdb']['uri'],dbname=app_name,uid=uid)
DB = couch_handler.dbase
handler = Domain.User(DB,stripe) ;
handler.init(uid,plan) handler.init(uid,plan)
resp = plan[0].id
return resp
resp = plan[0].id
return ('done',204)
""" """
This function returns the meta data about a given plan or set of plans for a given application This function returns the meta data about a given plan or set of plans for a given application
@resource app_name application identifier @resource app_name application identifier

@ -2,6 +2,7 @@
<meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="cache-control" content="no-cache">
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1">
<link rel="shortcut icon" href="/static/img/logo-0.png"> <link rel="shortcut icon" href="/static/img/logo-0.png">
<title style="text-transform: capitalize">{{app_name.replace('-',' ')}}</title>
<style> <style>
body{ body{
font-family:sans-serif; font-family:sans-serif;
@ -87,12 +88,12 @@
<div class="small">Available Plans, Charges will apply after trial period</div> <div class="small">Available Plans, Charges will apply after trial period</div>
</td> </td>
</tr> </tr>
<tr class="default"> <tr class="default" valign="top">
{% for item in plans%} {% for item in plans%}
{% if loop.index0 > 0 %} {% if loop.index0 > 0 %}
<td align="center" style="border-left:1px solid #CAD5E0"> <td align="center" style="border-left:1px solid #CAD5E0">
{% else %} {% else %}
<td align="center"> <td align="center" >
{% endif %} {% endif %}
<div class="medium-caption">{{ item.name.replace('-',' ') }}</div> <div class="medium-caption">{{ item.name.replace('-',' ') }}</div>
@ -106,19 +107,23 @@
</div> </div>
<br> <br>
<div> <div>
<form action="/pay/{{app_name|safe}}" method="POST"> <form action="/subscribe/{{app_name|safe}}" method="POST">
<script <script
src="https://checkout.stripe.com/checkout.js" class="stripe-button" src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{apikey|safe}}" data-key="{{apikey|safe}}"
data-email="{{uid|safe}}" data-email="{{uid|safe}}"
data-amount={{item.amount|safe}} data-amount={{item.amount|safe}}
data-name="The Phi Technology LLC" data-name="{{item.metadata.info}}"
data-description="" data-description=""
data-image="https://s3.amazonaws.com/stripe-uploads/acct_15kiA1EUWsmgY81Amerchant-icon-1443577505909-the-phi-logo.png" data-label="Signup Now"
data-image="https://s3.amazonaws.com/stripe-uploads/acct_15kiA1EUWsmgY81Amerchant-icon-1493912370912-logo-0.png"
data-locale="auto"> data-locale="auto">
</script> </script>
<input type="hidden" name="amount" value="{{item.amount|safe}}"/>
<input type="hidden" name="plan" value="{{item.id|safe}}"/>
</form> </form>
</div> </div>
{% else %} {% else %}

Loading…
Cancel
Save