card charge for donations

legacy
Steve L. Nyemba 4 years ago
parent 2acf10f7d7
commit 073b105c21

@ -9,7 +9,7 @@ from utils.params import PARAMS as SYS_ARGS
from utils import void from utils import void
import json import json
class User : class User :
def __init__(self,email,plans): def __init__(self,email,plans=None):
self.plans = plans self.plans = plans
self.me = {"plan":[],"customer":{},"payments":[],"plan2sub":{}} self.me = {"plan":[],"customer":{},"payments":[],"plan2sub":{}}
self.init(email) self.init(email)
@ -17,41 +17,94 @@ class User :
pass pass
def info(self): def info(self):
return self.me['customer'] return self.me['customer']
def _add_card(self,card): def _add_card(self,**_args):
"""
creating a card token, we do not have to save this it could just be used as a one-time thing,
This will automatically add a card to the users session profile (if she has not specified to save the card)
:number
:cvc
:exp mm/yyyy
"""
try: try:
stripe.token.Token.create(customer=self.me["customer"]['id'],card=card) card = dict(_args['card'] )
for field in ['name','email'] :
if field in card :
del card[field]
#
# address information should be added to the card
#
# save_card = _args['save'] if 'save' in _args else 0
# if save_card :
# r = stripe.token.Token.create(card=card)
# else:
#
# Links the customer to the source ..
if 'currency' in card :
currency = card['currency']
del card['currency']
else:
currency = 'usd'
r = stripe.source.Source.create(type='card',currency=currency,card=card)
self.me['payments'] = [r.card.to_dict_recursive()]+self.me['payments']
self.init(self.me["customer"]['email']) self.init(self.me["customer"]['email'])
return 1 return r
except Exception as error : except Exception as error :
print (error) print (error)
return 0 return 0
def charge(self,**args) : def charge(self,**args) :
""" """
This function will charge a user for a service (given a plan id) This function will charge a user for a service (given a plan id)
:plan_id plan identifier for the current product :card|token {number,cvc,exp_month,exp_year,[address_1,city,zip,state]}
:card_index provide a token (otherwise will use a valid card) :amount
:email
:
""" """
plan_id = args['plan_id'] # plan_id = args['plan_id']
if len(self.me["payments"]) == 1 : # if len(self.me["payments"]) == 1 :
card_index = 0 # card_index = 0
else: # else:
card_index = args['card_index'] # card_index = args['card_index']
plan = [item[plan_id] for item in self.plans if item['id'] == plan_id] # plan = [item[plan_id] for item in self.plans if item['id'] == plan_id]
card = {} if plan['amount'] == 0 else self.me["payments"][card_index] # card = {} if plan['amount'] == 0 else self.me["payments"][card_index]
params = {} # params = {}
params['customer'] = self.me["customer"]['id'] # params['customer'] = self.me["customer"]['id']
params ['amount'] = plan['amount'] # params ['amount'] = plan['amount']
params ['currency'] = plan['currency'] # params ['currency'] = plan['currency']
params ['description'] = " ".join([self.product['statement_descriptor'],plan['nickname']]) # params ['description'] = " ".join([self.product['statement_descriptor'],plan['nickname']])
if 'source' in card : # if 'source' in card :
params ['source'] = card['source'] # params ['source'] = card['source']
stripe.charge.Charge.create(params) #
del params['amount'], params['currency'] # Lets create a token for the card
#
stripe.invoice.Invoice.create(**params) token = self.card.add(card = args['card'])
if token != 0 :
_args = {"customer":self.me["customer"]["id"], "receipt_email":self.me['customer']['email'],"amount":args['amount'],"currency":"usd"}
_args["source"] = token["id"]
if 'metadata' in args :
_args['metadata'] = args['metadata']
# stripe.customer.Customer.update(self.me['customer']['id'],source=token['id'])
_args['description'] = args['description']
stripe.charge.Charge.create(**_args)
# if 'save' not in args :
# #
# # drop the card ...
# stripe.customer.Customer.delete_source(self.me['customer']['id'],token['id'])
# del params['amount'], params['currency']
# stripe.invoice.Invoice.create(**params)
return 1
else:
#
# An invalid card number or cvc we returned
return 0
pass pass
def format(self): def format(self):
@ -228,13 +281,27 @@ class Plans(Store) :
This function will retrieve plan information associated with the given product id This function will retrieve plan information associated with the given product id
""" """
Store.__init__(self,**args) Store.__init__(self,**args)
self.plans = stripe.plan.Plan.list(product=self.product['id']).to_dict_recursive()['data']
for item in self.plans : info = stripe.price.Price.list(product=self.product['id']).data
index = self.plans.index(item) self.plans = []
self.plans[index] = item.to_dict_recursive() self.checkout = []
if 'features' in self.plans[index]['metadata'] : for item in info :
self.plans[index]['metadata']['features'] = json.loads(self.plans[index]['metadata']['features']) setattr(item,'amount',item.unit_amount)
self.plans.sort(key=lambda item: item['amount']) _item = item.to_dict_recursive()
_item['amount'] = item['unit_amount']
if item.recurring == None :
self.checkout.append(_item)
elif 'features' in item.metadata :
_item['metadata']['features'] = json.loads(item.metadata['features'])
self.plans.append(_item)
# index = self.plans.index(item)
# self.plans[index] = item.to_dict_recursive()
# if 'features' in self.plans[index]['metadata'] :
# self.plans[index]['metadata']['features'] = json.loads(self.plans[index]['metadata']['features'])
# elif self.plans
self.plans.sort(key=lambda item: item['unit_amount'])
self.checkout.sort(key=lambda item:item['unit_amount'])
if 'email' in args : if 'email' in args :
self.user = User(args['email'],self.plans) self.user = User(args['email'],self.plans)
else: else:
@ -243,8 +310,9 @@ class Plans(Store) :
self.format() self.format()
def format(self): def format(self):
self.get = void() self.get = void()
self.get.plans = lambda:self.plans self.get.plans = lambda:self.plans
self.get.products = lambda:self.products self.get.checkout = lambda: self.checkout
self.get.products = lambda:self.products
self.plan = void() self.plan = void()
self.plan.upgrade = self.upgrade self.plan.upgrade = self.upgrade
self.plan.cancel = self.cancel self.plan.cancel = self.cancel
@ -326,236 +394,4 @@ class factory:
# p.user.subscribe = p.subscribe # p.user.subscribe = p.subscribe
return p return p
# if 'email' in args :
# store = Plans(**args)
# else:
# store = Plans(**args)
# return store
# class _Store :
# # stripe_keys = {
# # "secret_key":SYS_ARGS['stripe']['secret'].strip(),
# # "publishable_key":SYS_ARGS['stripe']['pub'].strip()
# # }
# # stripe.api_key = self.stripe_keys['secret_key']
# def __init__(saelf,**args):
# self.payment = []
# self.user_plan = {}
# self.customer = {}
# self.get = void()
# # self.get.user = void()
# # self.get.user.info = self._get_user
# # self.get.user.plan = lambda: self.user_plan if self.user_plan else None
# # self.add = void()
# # self.add.user = self.init
# # self.add.card = lambda card: stripe.token.Token.create(customer=customer['id'],card=card)
# self.user = void()
# self.user.init = self.init
# self.user.info = self._get_user
# self.user.plan = void()
# self.user.plan.info = lambda: self.user_plan if self.user_plan else None
# # self.user.plan.cancel = lambda id: stripe.subscription.Subscription.delete(self.customer['id'],prorate=True,invoice_now=True)
# self.user.card = void ()
# self.user.card.exists = lambda: len(self.payment) > 0
# self.user.card.add = self._add_card
# self.user.card.charge = self._apply_charge
# self.user.card.html = lambda: [{} for card in self.payment]
# self.user.card.delete = lambda index: stripe.customer.Customer.delete_source(self.customer['id'],self.payment[index])
# self.get.plans = self._get_plans
# self.has = void ()
# product_name = args['product']
# stripe.api_key = args['secret'] if 'secret' in args else stripe.api_key
# if stripe.api_key :
# self.__init_product(product_name)
# else:
# print (['secret' in args, stripe.api_key is None])
# self.plan = void()
# self.plan.cancel = self.__cancel_plan
# self.plan.subscribe = self.__subscribe_plan
# self.plan.upgrade = self.__upgrade_plan
# def _apply_charge(self,**args) :
# """
# This function will charge a user for a service (given a plan id)
# :plan_id plan identifier for the current product
# :card_index provide a token (otherwise will use a valid card)
# """
# plan_id = args['plan_id']
# if len(self.payment) == 1 :
# card_index = 0
# else:
# card_index = args['card_index']
# plan = [item[plan_id] for item in self.plans if item['id'] == plan_id]
# card = {} if plan['amount'] == 0 else self.payment[card_index]
# params = {}
# params['customer'] = self.customer['id']
# params ['amount'] = plan['amount']
# params ['currency'] = plan['currency']
# params ['description'] = " ".join([self.product['statement_descriptor'],plan['nickname']])
# if 'source' in card :
# params ['source'] = card['source']
# stripe.charge.Charge.create(params)
# del params['amount'], params['currency']
# stripe.invoice.Invoice.create(**params )
# pass
# def __init_product(self,product_name):
# PRODUCT_INDEX = 2
# DATA_TYPE_INDEX = 1
# STATUS_INDEX = 0
# resp = stripe.product.Product.list().to_dict_recursive()['data']
# self.product = []
# self.plan = []
# if resp :
# if resp :
# self.product = [p.to_dict_recursive() for p in resp if p['name'] == product_name]
# self.product = self.product[0] if self.product else []
# else:
# self.product = resp[0]
# if 'id' in self.product :
# self.__init_plan(self.product['id'])
# def __init_plan(self,id):
# """
# This function will retrieve plan information associated with the given product id
# """
# self.plans = stripe.plan.Plan.list(product=id).to_dict_recursive()['data']
# for item in self.plans :
# index = self.plans.index(item)
# self.plans[index] = item.to_dict_recursive()
# if 'features' in self.plans[index]['metadata'] :
# self.plans[index]['metadata']['features'] = json.loads(self.plans[index]['metadata']['features'])
# #
# # sort items by amounts
# #
# self.plans.sort(key=lambda item: item['amount'])
# # self.plans = [item.to_dict_recursive() for item in self.plans]
# def init(self,email):
# #
# # get customer information
# # email = args['email']
# self.user_plan = []
# self.customer = {}
# customers = stripe.customer.Customer.list(email=email).to_dict_recursive()['data']
# if customers :
# customers = customers[0]
# else:
# #
# # The user doesn't exist, we must create the user (without payment initially)
# # We can probably assign the user to a free plan if available
# #
# customers = stripe.customer.Customer.Create(email=email)
# free_plan = [item for item in self.plans if item['amount'] == 0]
# if free_plan :
# free_plan = free_plan[0]
# self.plan.subscribe(free_plan['id'],email)
# self.customer = {"email":email,"id":customers['id']}
# #
# # extract payments available,
# if 'sources' in customers and 'data' in customers['sources'] :
# if customers['sources']['data'] :
# self.payment = [ card.to_dict_recursive() for card in customers['sources']['data'] ]
# #
# # user plans
# info = customers
# subscriptions = info['subscriptions']['data']
# ids = [plan['id'] for plan in self.plans ]
# _found = None
# for sub in subscriptions :
# aplan = sub['plan']
# if set([aplan['id']]) & set(ids):
# _found = sub.to_dict_recursive()
# break
# self.user_plan = _found if _found else None
# def _get_user(self,**args):
# """
# This function will return a customer information and associated plan (hopefully)
# :email
# """
# return self.customer
# def __cancel_plan(self,id) :
# """
# This function will cancel a subscription given a user's email/or a subscription for the given product/user
# We are assuming one subscription one plan, no complex billing is involved (not good for startups)
# :email,subscription
# """
# stripe.subscription.Subscription.delete(id,prorate=True,invoice_now=True)
# pass
# def __upgrade_plan(self,id,email=None):
# """
# A change of plan suggests cancelling the current plan and assigning a new one.
# If it's a paid plan, the calling code must insure the user has an active token
# """
# email = self.customer['email'] if email is None else email
# sub_id = self.user.plan.info()['id']
# try:
# self.plan.cancel(sub_id)
# self.plan.subscribe(id,email)
# #
# # We need to reload everything
# self.user.init(email)
# except Exception as error :
# print (error) ;
# return 0
# return 1
# pass
# def __subscribe_plan(self,id,email):
# """
# Subscribe a user to a given plan assuming the user has already been initialized
# The responsibility falls upon the calling code to perform the cancellatioin of the existing plan and perform an upgrade
# """
# plan = {"plan": id}
# amount = sum([item['amount'] for item in self.plans if item['id'] == 0])
# if 'email' in self.customer and email == self.customer['email'] :
# email = self.customer['email']
# else:
# self.init(email)
# #
# # We must insure the user is one of our customers i.e perhaps
# if amount == 0 or self.payment :
# stripe.subscription.Subscription.create(
# customer=self.customer['id'], #if not email else email,
# items=[plan]
# )
# return 1
# else:
# return 0
# def _add_card(self,card):
# try:
# stripe.token.Token.create(customer=customer['id'],card=card)
# self.user.init(self.customer['email'])
# return 1
# except Exception as error :
# print (error)
# return 0
# def _get_plans(self,**args) :
# """
# This function will provide an plan for a given user given an email or the list of plans
# :email user email
# """
# return self.user_plan if 'email' in args else self.plans

@ -1,10 +1,364 @@
<body> <meta charset="UTF-8">
<input type="text" disabled/> <meta http-equiv="cache-control" content="no-cache">
<input type="text" placeholder="card number"/> <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1">
<div> <link rel="shortcut icon" href="{{product.images[0]}}">
<div> <link rel="stylesheet" href="{{context}}/static/css/default.css" type="text/css">
{% for i in range(12) %} <link rel="stylesheet" href="{{context}}/static/css/fa/css/all.css" type="text/css">
{% endfor %} <script type="text/javascript" src="{{ context }}/static/css/fa/js/all.js"></script>
<script type="text/javascript" src="{{ context }}/static/js/jquery/jquery.min.js"></script>
<script src="{{context}}/static/js/jx/utils.js"></script>
<script src="{{context}}/static/js/jx/dom.js"></script>
<script src="{{context}}/static/js/jx/rpc.js"></script>
<script src="{{context}}/static/js/jx/ext/modal.js"></script>
<style>
body {
font-family:sans-serif;
margin:0px;
}
.frame {
font-size:16px;
font-weight:lighter;
width:800px;
display:grid;
grid-template-columns: 50% 50%;
gap:2px;
align-items:center;
justify-content: center;
}
.product-info {
display:grid;
grid-template-rows: 48px 250px auto;
gap:2px;
align-items:center;
border-right:1px solid #CAD5E0;
padding:32px;
}
.product-info .description {
padding:4px;
}
.product-info .caption {
font-size:28px;
padding:8px;
text-align:center;
}
.product-info img {
width:150px;
margin:4px; }
.card-info {
padding:4px;
}
.card-info .amount {text-align:right;}
.payment-amount .menu {display:none; position:absolute; z-index:9; background-color:#ffffff; padding:4px;}
.menu .item {padding:4px}
.card-info input {width:100%;}
.email { width:100%;}
.fname { width:100% }
.lname {width:100%}
input {
height:48px;
border:2px solid transparent;
padding:6px;
font-weight:lighter;
background-color:#f3f3f3;
}
.fa-exclamation-triangle{
color:#ff6500 ;
}
input:focus {
/*border-left: 2px solid #ff6500 ;*/
border-left: 2px solid #4682B4;
}
.error {
border-color: maroon;
}
.location{padding:4px; display:none; grid-template-columns:50% 50%; gap:2px;}
.location input {width:100%}
.gray {color:#d3d3d3}
.steel-blue{color:#4682B4;}
.dialog-frame {
min-width:320px;
min-height:125px;
}
/*
.dialog {
display:grid;
padding:4px;
display:grid;
grid-template-columns: 25% auto;
gap:2px;
}
.dialog-frame .close {display:grid; gap:2px; grid-template-columns:auto 32px;
text-align:right; ;
background-color:#f3f3f3;
}
.dialog .icon { font-size:42px;justify-items:center; display:grid; align-items:center}
.dialog .message {
display:grid;
align-items:center;
padding:8px;
font-weight:bold ;
color:#4682B4 ;
} */
</style>
<script>
sessionStorage.context = "{{context|safe}}"
sessionStorage.pricing = JSON.stringify({{pricing|tojson}})
sessionStorage.customer = JSON.stringify({info:{}})
var cards = {
"^3[47]\\d{1,2}(| |-)\\d{6}\\1\\d{6}$":"amex","^5[1-5]\\d{2}(| |-)(?:\\d{4}\\1){2}\\d{4}$":"mastercard",
"^4\\d{3}(| |-)(?:\\d{4}\\1){2}\\d{4}$":"visa","^6(?:011|5\\d\\d)(| |-)(?:\\d{4}\\1){2}\\d{4}$":"discover"}
var checkout = {}
checkout.init = function(index){
var p = JSON.parse(sessionStorage.pricing)
var _item = p[index]
var amount = (_item.unit_amount/100).toFixed(2)
$('.amount').val( amount)
//$('.amount-value').text(amount)
$('.currency').text(_item.currency.toUpperCase())
$('.amount').change()
sessionStorage.product = JSON.parse(sessionStorage.customer)
}
checkout.validate = function(e){
var id = e.target
customer = JSON.parse(sessionStorage.customer)
$(id).removeClass('error')
var pattern = $(id).attr('data-pattern')
var field = $(id).attr('class')
var value = $(id).val().trim()
$(id).val(value)
if (customer.info[field] != null){
delete customer.info[field]
}
if (pattern == 'card'){
var r = jx.utils.patterns.visitor(jx.utils.keys(cards),function(key){
if(value.match(key)){
return cards[key]
}
})
if(r.length > 0){
//
// @TODO: Generalize this to a function call (poor programming)
customer.info[field] = value
sessionStorage.customer = JSON.stringify(customer)
var link = ([sessionStorage.context,'/static/img/cards/',r[0]+'.svg']).join('')
jx.dom.set.attribute('pay-icon','src',link)
return 1
}else{
jx.dom.set.attribute('pay-icon','src','')
$(id).addClass('error')
return 0
}
}else{
if(value.match(pattern)){
customer.info[field] = value
sessionStorage.customer = JSON.stringify(customer)
return 1
}else{
$(id).addClass('error')
return 0
}
}
}
checkout.dialog = function(title,message,type){
ICONS = {'WARN':'fas fa-exclamation-triangle','CHECK':'fas fa-check fa-2x','PROGRESS':'fas fa-cog fa-spin'}
var uri = ([sessionStorage.context,'/ui/dialog']).join('')
var info = {title:title,message:message,icon:ICONS[type],type:type}
var httpclient = HttpClient.instance()
httpclient.setData( JSON.stringify(info))
httpclient.setHeader('content-type','application/json')
httpclient.post(uri,function(x){
jx.modal.show({html:x.responseText,id:'dialog'})
})
}
checkout.proceed = function(){
checkout.dialog('Preparing payment','Please wait ...','PROGRESS')
jx.utils.patterns.visitor($('input'),function(_input){
//
// re-running validation
if ($(_input).attr('class') != 'amount'){
$(_input).keyup()
}else {
$(_input).change()
}
})
var N = $('input').length
info = JSON.parse(sessionStorage.customer).info
var n = jx.utils.keys(info).length
if (n != N){
//
// We can not submit this (trash)
/*jx.utils.patterns.visitor(['fa fa-cog fa-3x fa-spin gray','fa fa-cog fa-5x fa-spin steel-blue','fa fa-cog fa-2x fa-spin gray'],function(name){
var i = jx.dom.get.instance('I')
i.className = name
$('.dialog > .icon').append(i)
})
*/
setTimeout( function(){
jx.modal.close()
},2000)
/*$('.card').slideUp( function(){
$('.dialog-frame').show()
var icon = jx.dom.get.instance('I')
icon.className = 'fas fa-exclamation-triangle'
$('.dialog > .icon').append(icon)
$('.dialog > .message').text('Invalid entries founds')
console.log(info)
})*/
}else{
//
// Submit the charge to be processed
//
info.amount = info.amount * 100
$('.dialog > .message').text('Processing card, please wait ...')
var uri = ([sessionStorage.context,'/{{product.name|safe}}/pay']).join('/')
var http = HttpClient.instance()
http.setData(JSON.stringify(info))
http.setHeader('content-type','application/json')
http.post(uri,function(x){
if(x.status == 200){
TYPE='CHECK'
TITLE = ''
}else{
TITLE='.::'
TYPE='WARN'
}
jx.modal.close()
checkout.dialog(TITLE,x.responseText,TYPE)
})
}
}
$(document).ready(function(){
$('.payment-amount > input').on('focusin',function(){
$('.payment-amount > .menu').slideDown('fast')
})
$('.payment-amount > input').on('focusout',function(){
$('.payment-amount > .menu').slideUp('slow')
})
checkout.dialog('','Loading ...','PROGRESS')
checkout.init(0)
// jx.dom.set.focus('amount')
var d = new Date()
$('#copyright').text(d.getFullYear())
setTimeout(function(){
jx.modal.close()
},1700)
})
</script>
<div style="display:grid; justify-items:center; align-items:center; height:99%;">
<div class="frame">
<div class="product-info">
<div class="caption">{{product.name}}</div>
<div align="center">
<div class="border-round border" style="background-color: #f3f3f3; padding:32px; width:256px;">
<img src="{{product.images[0]}}">
</div>
</div>
<div class="description">
{{product.metadata.about}}
</div>
</div> </div>
</div> <div class="card" style="vertical-align:middle; padding:4px;">
</body>
<div style="margin:4px;">
<input type="text" placeholder="Email@domain.com" class="email" data-pattern="^[-!#-'*+\/-9=?^-~]+(?:\.[-!#-'*+\/-9=?^-~]+)*@[-!#-'*+\/-9=?^-~]+(?:\.[-!#-'*+\/-9=?^-~]+)+$" onkeyup="checkout.validate(event)"/>
</div>
<div style="margin:4px; display:grid; grid-template-columns:50% auto; gap:2px;">
<input type="text" placeholder="First Name" class="fname" data-pattern="^[a-z,A-Z,-]{2,}$" onkeyup="checkout.validate(event)"/>
<input type="text" placeholder="Last Name" class="lname" data-pattern="^[a-z,A-Z,-]{2,}$" onkeyup="checkout.validate(event)"/>
</div>
<div class="card-info">
<div class="" style="display:grid; grid-template-columns:50% auto; gap:2px">
<div class="payment-amount">
<input type="text" id="amount" class="amount" readonly="true" title="Amount" placeholder="00.00" onchange="checkout.validate(event)" style="text-align:right"/>
<div class="border menu" style="margin:4px">
<div style="margin:4px;">Choose an amount</div>
{%for item in pricing %}
<div class="item active" style="font-weight:lighter" onclick="checkout.init({{loop.index -1 }})">
{{item.unit_amount/100}} <span style="text-transform: uppercase">{{item.currency}}</span>
</div>
{% endfor %}
<div style="margin:4px"></div>
</div>
</div>
<div class="currency" style="display:grid; align-items:center" align="left"></div>
</div>
<div class="number" style="margin-top:2px; margin-bottom:2px; display:grid; gap:2px; grid-template-columns:64px auto;">
<div class="" style="background:#f3f3f3; display:grid; align-items:center; justify-items:center"><img id="pay-icon" src="" style="width:32px; vertical-align:middle"/></div>
<input type="text" placeholder="Card Number" class="number" data-pattern="card" onkeyup="checkout.validate(event)"/>
</div>
<div class="expire" style="display:grid; grid-template-columns:50% auto; gap:2px;">
<input type="text" placeholder="MM/YYYY" class="exp" data-pattern="^(0[1-9]|1[0-2])/202[0-9]$" onkeyup="checkout.validate(event)"/>
<input type="text" placeholder="CVC" class="cvc" data-pattern="[0-9]{3,}" onkeyup="checkout.validate(event)"/>
</div>
</div>
<div class="location">
<div class="state">
<_input type="text" placeholder="State" data-pattern="[A-Z]+" value="USA" onkeyup="checkout.validate(event)"/>
</div>
<div class="zip">
<_input type="text" placeholder="Zip Code" data-pattern="[0-9]{5,}" onkeyup="checkout.validate(event)"/>
</div>
</div>
<div style="padding:4px; margin-top:48px">
<div class="active " align="center" style=" background-color:#f3f3f3; color:#4682b4; display:grid; ;align-items:center; height:48px; padding:4px;"
onclick="checkout.proceed()"
>
<div style="font-size:18px">
Pay Now</div>
</div>
</div>
</div>
<div class="small border-top" align="center" style="margin-top:32px; grid-column: 1 / span 2; font-weight:lighter; font-family:sans-serif">
<p>The Phi Technology
- {{product.name}} &copy; <span id="copyright"></span>
</p>
</div>
</div>
</div>

@ -0,0 +1,2 @@
{"email": "nyemba@gmail.com", "fname": "steve", "lname": "nyemba", "amount": 2500, "number": "5555555555554444", "exp": "02/2024", "cvc": "666"}

@ -0,0 +1,71 @@
<!--
*
* This page is intended to perform a donate operation against payment backend
-->
<meta charset="UTF-8">
<meta http-equiv="cache-control" content="no-cache">
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1">
<link rel="stylesheet" href="{{context}}/static/css/default.css" type="text/css">
<script src="https://kit.fontawesome.com/ab15160345.js" crossorigin="anonymous"></script>
<script type="text/javascript" src="{{ context }}/static/js/jquery/jquery.min.js"></script>
<script type="text/javascript" src="{{ context }}/static/js/jx/rpc.js"></script>
<script type="text/javascript" src="{{ context }}/static/js/jx/utils.js"></script>
<script type="text/javascript" src="{{ context }}/static/js/jx/dom.js"></script>
<script type="text/javascript" src="{{ context }}/static/js/jx/ext/modal.js"></script>
<style>
.dialog {
display:grid;
padding:4px;
display:grid;
grid-template-columns: 25% auto;
gap:2px;
}
.dialog-frame .title {display:grid; gap:2px; grid-template-columns:auto 32px;
min-height:32px;
border-top-left-radius: 6px;;
border-top-right-radius: 6px;;
color:#4682b4;
align-items: center;
padding:4px;
}
.dialog { margin-top:4px;}
.dialog .icon { font-size:42px;justify-items:center; display:grid; align-items:center}
.dialog .message {
display:grid;
align-items:center;
padding:8px;
font-weight:normal ;
color:#4682B4 ;
}
.fa-exclamation-triangle{color:#ff6500 ;}
.fa-cog {color:gray}
.gray {color:#d3d3d3}
.steel-blue{color:#4682B4;}
</style>
<div class="dialog-frame ">
<div class="">
<div class="title">
<div class="bold" style="padding:4px; display:grid; align-items:center;">{{title}}</div>
{% if type != 'PROGRESS' %}
<div class="active" align="center" onclick="jx.modal.close()">
<i class="fas fa-times"></i>
</div>
{% else %}
<div></div>
{% endif %}
</div>
<div class="dialog">
<div class="icon">
<i class="{{icon|safe}}"></i>
</div>
<div class="message">{{message|safe}}</div>
</div>
</div>
<br>
</div>

@ -34,11 +34,11 @@
jx.modal.show({html:html,id:'dialog'}) jx.modal.show({html:html,id:'dialog'})
jx.dom.set.value('signup-plan',data.nickname) jx.dom.set.value('signup-plan',data.nickname)
if(data.amount == 0){ if(data.unit_amount == 0){
var price = 'Free' var price = 'Free'
}else{ }else{
var price = parseFloat(data.amount / 100 ).toFixed(2) var price = parseFloat(data.unit_amount / 100 ).toFixed(2)
price = ([price, data.interval]).join(' / ') price = ([price, data.recurring.interval]).join(' / ')
} }
jx.dom.set.value('plan-price',price) jx.dom.set.value('plan-price',price)
//jx.dom.set.focus('email') //jx.dom.set.focus('email')
@ -82,7 +82,7 @@
httpclient.setHeader("Content-Type","application/json") httpclient.setHeader("Content-Type","application/json")
httpclient.setData(JSON.stringify(info) ) httpclient.setData(JSON.stringify(info) )
httpclient.post('{{context|safe}}/store',function(x){}) httpclient.post('{{context|safe}}/store',function(x){})
if (data.amount == 0){ if (data.unit_amount == 0){
// //
// We should not be prompting the user but automatically logging her into her session // We should not be prompting the user but automatically logging her into her session
// //
@ -105,13 +105,13 @@
script.setAttribute('data-key', x['data-key'].trim()) script.setAttribute('data-key', x['data-key'].trim())
script.setAttribute('data-email', p.user.uid) script.setAttribute('data-email', p.user.uid)
script.setAttribute('data-name', data.nickname) script.setAttribute('data-name', data.nickname)
script.setAttribute('data-amount', data.amount) script.setAttribute('data-amount', data.unit_amount)
script.setAttribute('data-description','{{description|safe}} ' + data.nickname) script.setAttribute('data-description','{{description|safe}} ' + data.nickname)
script.src = 'https://checkout.stripe.com/checkout.js' script.src = 'https://checkout.stripe.com/checkout.js'
script.setAttribute('data-amount',data.amount) script.setAttribute('data-amount',data.unit_amount)
script.setAttribute('data-image','https://s3.amazonaws.com/stripe-uploads/acct_15kiA1EUWsmgY81Amerchant-icon-1493912370912-logo-0.png') script.setAttribute('data-image','https://s3.amazonaws.com/stripe-uploads/acct_15kiA1EUWsmgY81Amerchant-icon-1493912370912-logo-0.png')
script.setAttribute('data-label',(['Pay $',data.amount,data.interval]).join(' ')) script.setAttribute('data-label',(['Pay $',data.unit_amount,data.interval]).join(' '))
script.className = 'stripe-button' script.className = 'stripe-button'
form.appendChild(script) form.appendChild(script)
@ -159,13 +159,13 @@ var pay_now = function(auth,plan){
script.setAttribute('data-key', x['data-key'].trim()) script.setAttribute('data-key', x['data-key'].trim())
script.setAttribute('data-email', auth.user.uid) script.setAttribute('data-email', auth.user.uid)
script.setAttribute('data-name', plan.nickname) script.setAttribute('data-name', plan.nickname)
script.setAttribute('data-amount', plan.amount) script.setAttribute('data-amount', plan.unit_amount)
script.setAttribute('data-description','{{description|safe}} ' + plan.nickname) script.setAttribute('data-description','{{description|safe}} ' + plan.nickname)
script.src = 'https://checkout.stripe.com/checkout.js' script.src = 'https://checkout.stripe.com/checkout.js'
script.setAttribute('data-amount',plan.amount) script.setAttribute('data-amount',plan.unit_amount)
script.setAttribute('data-image','https://s3.amazonaws.com/stripe-uploads/acct_15kiA1EUWsmgY81Amerchant-icon-1493912370912-logo-0.png') script.setAttribute('data-image','https://s3.amazonaws.com/stripe-uploads/acct_15kiA1EUWsmgY81Amerchant-icon-1493912370912-logo-0.png')
script.setAttribute('data-label',(['Pay $',plan.amount,plan.interval]).join(' ')) script.setAttribute('data-label',(['Pay $',plan.unit_amount,plan.recurring.interval]).join(' '))
script.className = 'stripe-button' script.className = 'stripe-button'
form.appendChild(script) form.appendChild(script)
@ -266,15 +266,15 @@ var redirect_now = function(auth,plan){
{% else %} {% else %}
<div></div> <div></div>
{% endif %} {% endif %}
{% if item.amount == 0%} {% if item.unit_amount == 0%}
<div class="default"> <div class="default">
<span class="bold">Free</span> <span class="bold">Free</span>
</div> </div>
{%else%} {%else%}
<div class="default" > <div class="default" >
<span class="bold">$ {{ item.amount/100 }}</span> <span class="bold">$ {{ item.unit_amount/100 }}</span>
/ <span class="small">{{item.interval[:]}}</span> / <span class="small">{{item.recurring.interval[:]}}</span>
</div> </div>
{% endif %} {% endif %}
@ -301,15 +301,15 @@ var redirect_now = function(auth,plan){
<div class="button " data='{{item|tojson|safe}}' onclick="signup_form( {{loop.index-1}} , this )"> <div class="button " data='{{item|tojson|safe}}' onclick="signup_form( {{loop.index-1}} , this )">
<div>Signup Now</div> <div>Signup Now</div>
{% if item.amount == 0%} {% if item.unit_amount == 0%}
<div class="small text"> <div class="small text">
<span class="bold">Free</span> <span class="bold">Free</span>
</div> </div>
{%else%} {%else%}
<div class="small text" > <div class="small text" >
<span class="bold">$ {{ item.amount/100 }}</span> <span class="bold">$ {{ item.unit_amount/100 }}</span>
/ <span >{{item.interval[:]}}</span> / <span >{{item.recurring.interval[:]}}</span>
</div> </div>
{% endif %} {% endif %}

@ -264,7 +264,7 @@
data-name="{{item.nickname}}" data-name="{{item.nickname}}"
data-description="{{alias }}" data-description="{{alias }}"
data-label="Signup $ {{item.amount/100 }} / {{item.interval[:2]}}" data-label="Signup $ {{item.amount/100 }} / {{item.recurring.interval[:2]}}"
data-image="https://s3.amazonaws.com/stripe-uploads/acct_15kiA1EUWsmgY81Amerchant-icon-1493912370912-logo-0.png" data-image="https://s3.amazonaws.com/stripe-uploads/acct_15kiA1EUWsmgY81Amerchant-icon-1493912370912-logo-0.png"
data-locale="auto"> data-locale="auto">

Loading…
Cancel
Save