|
|
|
@ -10,6 +10,7 @@
|
|
|
|
|
<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>
|
|
|
|
|
<script src="{{context}}/static/js/payment.js"></script>
|
|
|
|
|
<style>
|
|
|
|
|
body {
|
|
|
|
|
font-family:sans-serif;
|
|
|
|
@ -120,7 +121,7 @@
|
|
|
|
|
} */
|
|
|
|
|
@media only screen and (max-device-width: 960px){
|
|
|
|
|
body {font-size:14px; font-family:sans-serif; font-weight:lighter; line-height: 20px;}
|
|
|
|
|
.pane {display:grid; justify-items:center; align-items:center; height:auto;}
|
|
|
|
|
.payment-pane {display:grid; justify-items:center; align-items:center; height:auto;}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.frame {
|
|
|
|
@ -159,7 +160,7 @@
|
|
|
|
|
|
|
|
|
|
@media only screen and (min-device-width: 1024px){
|
|
|
|
|
body {font-size:14px; font-family:sans-serif; font-weight:lighter; line-height: 28px;}
|
|
|
|
|
.pane {display:grid; justify-items:center; align-items:center; height:96%;}
|
|
|
|
|
.payment-pane {display:grid; justify-items:center; align-items:center; height:96%;}
|
|
|
|
|
.frame {
|
|
|
|
|
width:800px;
|
|
|
|
|
display:grid;
|
|
|
|
@ -193,162 +194,29 @@
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
</style>
|
|
|
|
|
<script>
|
|
|
|
|
sessionStorage.store_context = "{{context|safe}}"
|
|
|
|
|
<script >
|
|
|
|
|
$(document).ready(function(){
|
|
|
|
|
payment.dialog('','Loading ...','PROGRESS')
|
|
|
|
|
payment.setup("{{context|safe}}",{{pricing|tojson}})
|
|
|
|
|
|
|
|
|
|
setTimeout(function(){
|
|
|
|
|
jx.modal.close()
|
|
|
|
|
},1700)
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
/*sessionStorage.store_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.store_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-3x','PROGRESS':'fas fa-cog fa-spin'}
|
|
|
|
|
var uri = ([sessionStorage.store_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.store_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 = ''
|
|
|
|
|
jx.utils.patterns.visitor($('input'),function(_input){
|
|
|
|
|
$(_input).val('')
|
|
|
|
|
$(_input).attr('disabled',true)
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
sessionStorage.customer = JSON.stringify({info:{}})
|
|
|
|
|
|
|
|
|
|
}else{
|
|
|
|
|
TITLE='.::'
|
|
|
|
|
TYPE='WARN'
|
|
|
|
|
}
|
|
|
|
|
jx.modal.close()
|
|
|
|
|
checkout.dialog(TITLE,x.responseText,TYPE)
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$(document).ready(function(){
|
|
|
|
|
$(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)
|
|
|
|
|
payment.dialog('','Loading ...','PROGRESS')
|
|
|
|
|
payment.init(0)
|
|
|
|
|
// jx.dom.set.focus('amount')
|
|
|
|
|
var d = new Date()
|
|
|
|
|
$('#copyright').text(d.getFullYear())
|
|
|
|
@ -356,12 +224,17 @@
|
|
|
|
|
setTimeout(function(){
|
|
|
|
|
jx.modal.close()
|
|
|
|
|
},1700)
|
|
|
|
|
})
|
|
|
|
|
})*/
|
|
|
|
|
</script>
|
|
|
|
|
<div class="pane">
|
|
|
|
|
<div class="payment-pane">
|
|
|
|
|
|
|
|
|
|
<div class="frame">
|
|
|
|
|
<div class="caption title" align="center">{{product.name}}</div>
|
|
|
|
|
<div class="caption title" align="center" style="display:grid; gap:2px; grid-template-columns: auto 32px; align-items:center; justify-items:center">
|
|
|
|
|
|
|
|
|
|
<div>{{product.name}}</div>
|
|
|
|
|
|
|
|
|
|
<div class="active close-dialog" onclick="jx.modal.close()"><i class="fa fa-times"></i></div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="product-info" >
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -377,14 +250,14 @@
|
|
|
|
|
<div class="card" style="vertical-align:middle;">
|
|
|
|
|
|
|
|
|
|
<div style="margin-top:2px">
|
|
|
|
|
<input type="text" placeholder="Email@domain.com" class="email" data-pattern="^[-!#-'*+\/-9=?^-~]+(?:\.[-!#-'*+\/-9=?^-~]+)*@[-!#-'*+\/-9=?^-~]+(?:\.[-!#-'*+\/-9=?^-~]+)+$" onkeyup="checkout.validate(event)"/>
|
|
|
|
|
<input type="text" placeholder="Email@domain.com" class="email" data-pattern="^[-!#-'*+\/-9=?^-~]+(?:\.[-!#-'*+\/-9=?^-~]+)*@[-!#-'*+\/-9=?^-~]+(?:\.[-!#-'*+\/-9=?^-~]+)+$" onkeyup="payment.validate(event)"/>
|
|
|
|
|
</div>
|
|
|
|
|
<div style="display:grid; grid-template-columns:50% 50%; gap:2px; margin-top:2px;">
|
|
|
|
|
<div>
|
|
|
|
|
<input type="text" placeholder="First Name" class="fname" data-pattern="^[a-z,A-Z,-]{2,}$" onkeyup="checkout.validate(event)"/>
|
|
|
|
|
<input type="text" placeholder="First Name" class="fname" data-pattern="^[a-z,A-Z,-]{2,}$" onkeyup="payment.validate(event)"/>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<input type="text" placeholder="Last Name" class="lname" 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="payment.validate(event)"/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="card-info" style="margin-top:2px">
|
|
|
|
@ -393,11 +266,11 @@
|
|
|
|
|
|
|
|
|
|
<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"/>
|
|
|
|
|
<input type="text" id="amount" class="amount" readonly="true" title="Amount" placeholder="00.00" onchange="payment.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 }})">
|
|
|
|
|
<div class="item active" style="font-weight:lighter" onclick="payment.init({{loop.index -1 }})">
|
|
|
|
|
|
|
|
|
|
{{item.unit_amount/100}} <span style="text-transform: uppercase">{{item.currency}}</span>
|
|
|
|
|
|
|
|
|
@ -413,27 +286,27 @@
|
|
|
|
|
|
|
|
|
|
<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)"/>
|
|
|
|
|
<input type="text" placeholder="Card Number" class="number" data-pattern="card" onkeyup="payment.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)"/>
|
|
|
|
|
<input type="text" placeholder="MM/YYYY" class="exp" data-pattern="^(0[1-9]|1[0-2])/202[0-9]$" onkeyup="payment.validate(event)"/>
|
|
|
|
|
<input type="text" placeholder="CVC" class="cvc" data-pattern="[0-9]{3,}" onkeyup="payment.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)"/>
|
|
|
|
|
<_input type="text" placeholder="State" data-pattern="[A-Z]+" value="USA" onkeyup="payment.validate(event)"/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="zip">
|
|
|
|
|
<_input type="text" placeholder="Zip Code" data-pattern="[0-9]{5,}" onkeyup="checkout.validate(event)"/>
|
|
|
|
|
<_input type="text" placeholder="Zip Code" data-pattern="[0-9]{5,}" onkeyup="payment.validate(event)"/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="pay-frame">
|
|
|
|
|
<div class="active " align="center" style=" background-color:#f3f3f3; color:#4682b4; display:grid; ;align-items:center; height:48px; padding:4px;"
|
|
|
|
|
onclick="checkout.proceed()"
|
|
|
|
|
onclick="payment.proceed()"
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
<div style="font-size:18px">
|
|
|
|
@ -449,7 +322,7 @@
|
|
|
|
|
<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}} © <span id="copyright"></span>
|
|
|
|
|
- {{product.name}} © <span class="copyright"></span>
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|