diff --git a/lib/Dojo/Controller/Proc.pm b/lib/Dojo/Controller/Proc.pm index 6986297..0bc4148 100644 --- a/lib/Dojo/Controller/Proc.pm +++ b/lib/Dojo/Controller/Proc.pm @@ -41,6 +41,7 @@ sub spay{ else { $c->stash(layout=> "defaultContact"); } + $c->stash(stripe_sk_public => Dojo::Conf::STRIPE_SK_PUBLIC ); $c->stash($data); } @@ -50,87 +51,76 @@ sub intentCreate{ unless (defined ($c->req->json)){ $c->stash(layout=>'clean'); $c->render(template=>'home/not_found', status=>404); - return 0; + return 0; } - my $data=$c->mproc->intentCreate($c->req->json->{'tid'}); - # if(!@$data){ intentError($c,"event not found",1); return;}; - - my $pmi=$c->req->json->{'payment_method_id'} // 0; - my $amount = $data->{'precio'} * $c->req->json->{'mq'} ; - my $description = $data->{'nombre'}; - my $max_time = 9; + my $json = $c->req->json; + my $data=$c->mproc->intentCreate($json->{'tid'}); + + if ($data==0){intentError($c,"store id error",1); return;} + if ( $c->mproc->userDataSanity($json) != 0) { + intentError($c,"data sanity error",1); return; + } + + my $max_time = $data->{'meses'}; + my @count = (0,3,6,9,12,18); #arregla esta atrocidad + + my $idisc= $data->{'desc_estado'}; #immediate payment discount + my $discount = $data->{'descuento'}; #disoutn % + my $pl = $json->{'pl'}; # 0 imediate. 1-5: 3,6,9,12,18 months installment + my $plan = $count[$pl]; + my $pmi=$json->{'payment_method_id'}; + + my $amount = $data->{'precio'} * $json->{'mq'} ; + $amount = $amount * (1 - ($discount/100 )) if($pl==0 && $idisc == 1 && $discount > 0); my $api_create_path='https://api.stripe.com/v1/payment_intents'; my $payment_info=[ 'payment_method'=>$pmi, - 'amount'=>$amount*100, + 'amount'=>int($amount*100), 'currency'=>'mxn', - 'description'=>$description, + 'description'=>$data->{'nombre'}, 'payment_method_options[card][installments][enabled]'=>'true' ]; my $r=stripeAppi($api_create_path,$payment_info); if ($r==0){intentError($c,"api create error",1); return;} - my $t->{intent_id}=$r->{id}; - foreach (@{$r->{payment_method_options}{card}{installments}{available_plans}}){ - push (@{$t->{available_plans}}, $_) unless ($_->{count} > $max_time); - } - $c->render(json=>$t); - return 0; -} -sub intentConfirm{ - my $c = shift; - my $max_time = 9; - - unless (defined ($c->req->json)){ - $c->stash(layout=>'clean'); - $c->render(template=>'home/not_found', status=>404); - return; + if ($pl > 0) { + + unless (defined( $r->{'payment_method_options'}->{'card'}->{'installments'}->{'available_plans'} ) ){ + intentError($c,"api can't accept installment",1); return; + } } - unless ($c->mproc->intentSanity($c->req->json) == 0 ){ - intentError($c,"sanity failed",0); return; } - my $data = $c->req->json; - my $pii = $data->{'payment_intent_id'}; - my $plan = $data->{'selected_plan'} // 0; + #===================================================== + #intent confirm ====================================== + + my $pii = $r->{'id'}; my $api_confirm_path = "https://api.stripe.com/v1/payment_intents/$pii/confirm"; - + my $cplan = 0; if ($plan != 0){ - if ($plan->{count} > $max_time) { - intentError($c,'max time installment attempt error',3); - return 0; - } $cplan = [ 'payment_method_options[card][installments][plan][type]'=>'fixed_count', 'payment_method_options[card][installments][plan][interval]'=>'month', - 'payment_method_options[card][installments][plan][count]'=>$plan->{count}, + 'payment_method_options[card][installments][plan][count]'=>$plan, ] } - - if ( - intentCheck( - $c, - $data->{'payment_intent_id'}, - $data->{'tid'}, - $data->{'mq'} - ) == -1) { - intentError($c,"api confirm error pre",2); return; - } - my $r = stripeAppi($api_confirm_path,$cplan); - if ($r==0){intentError($c,"api confirm error post",2); return;} - if ($r->{'status'} ne "succeeded" ){intentError($c,"payment not completed,2"); return;} - - $c->mproc->intentConfirm($data,$r); - map { send_mail(@$_) }$c->mproc->notify($data,$r); + my $rr = stripeAppi($api_confirm_path,$cplan); + if ($rr==0){intentError($c,"api confirm error post",2); return;} + if ($rr->{'status'} ne "succeeded" ){intentError($c,"payment not completed,2"); return;} + #====================================================== + # end and send messages ================================ + $c->mproc->intentConfirm($json,$rr); + + map { send_mail(@$_) }$c->mproc->notify($json,$rr); my $rtt = { - 'status'=>$r->{'status'}, - 'plan' => $r->{'payment_method_options'}{'card'}{'installments'}{'plan'}, + 'status'=>$rr->{'status'}, + 'pl' => $rr->{'payment_method_options'}{'card'}{'installments'}{'plan'}, }; $c->render(json=>$rtt); return 0; @@ -149,14 +139,6 @@ sub userCheck{ return 0; } -sub intentCheck{ - my ($c, $cid, $tid, $mq) = @_; - my $stripe = stripeAppi("https://api.stripe.com/v1/payment_intents/$cid",0); - my $data=$c->mproc->intentCreate($tid); - return -1 unless ( $stripe->{'amount'} == ($data->{'precio'} * $mq)*100); - return 0; -} - sub stripeAppi{ my ($path,$data) = @_; my $req; diff --git a/lib/Dojo/Model/Data/spay/qIdStore.q b/lib/Dojo/Model/Data/spay/qIdStore.q index 4ca0c12..1ea0725 100755 --- a/lib/Dojo/Model/Data/spay/qIdStore.q +++ b/lib/Dojo/Model/Data/spay/qIdStore.q @@ -17,6 +17,9 @@ select t.promo_estado as promo_estado, t.playera_estado as playera_estado, t.cupo as cupo, + t.meses as meses, + t.descuento_contado as descuento, + t.descuento_contado_estado as desc_estado, l.nombre as lnombre, l.federativa as federativa, l.pais as pais, diff --git a/lib/Dojo/Model/Data/spay/qIntentCreate.q b/lib/Dojo/Model/Data/spay/qIntentCreate.q index 8f0c74e..10f3b6c 100644 --- a/lib/Dojo/Model/Data/spay/qIntentCreate.q +++ b/lib/Dojo/Model/Data/spay/qIntentCreate.q @@ -1,6 +1,10 @@ + select t.precio as precio, - c.nombre as nombre + c.nombre as nombre, + t.meses as meses, + t.descuento_contado as descuento, + t.descuento_contado_estado as desc_estado from curso_tienda as t inner join diff --git a/lib/Dojo/Model/Vdgproc.pm b/lib/Dojo/Model/Vdgproc.pm index 3d09c80..7dbd41c 100644 --- a/lib/Dojo/Model/Vdgproc.pm +++ b/lib/Dojo/Model/Vdgproc.pm @@ -61,10 +61,7 @@ sub intentConfirm{ # cliente_nombre,cliente_correo,cliente_comentario,tienda_evento_id,talla_id,cantidad(1),monto,etapa_id(4),entrega(3),pago_clave,plazo,fecha_pago my $mq = $data->{'mq'}; my $students = $data->{'students'}; - my $plan = 0; - if (defined $data->{'selected_plan'}){ - $plan = $data->{'selected_plan'}->{'count'}; - } + my $plan = $r->{'payment_method_options'}->{'card'}->{'installments'}->{'plan'}->{'count'} // 0; for (1..$mq){ _write ( $data_path->child("/spay/qIntentConfirm.q")->slurp, @@ -88,19 +85,20 @@ sub notify{ my ($c,$d,$r) = @_; my $t =shift @{ _read ($data_path->child("spay/qNotify.q")->slurp,$d->{'tid'})}; my @ra; - my %h=qw/0 na 1 ch 2 m 3 g/; - my $plazo= defined( $d->{'selected_plan'})? - $d->{'selected_plan'}->{'count'} : "0"; + my %h=qw/0 na 1 CH 2 M 3 G/; + my $plazo = $r->{'payment_method_options'}->{'card'}->{'installments'}->{'plan'}->{'count'}; my $students = $d->{'students'}; - my $basetxta = "$t->{'cnombre'} - clave de pago stripe: $d->{'payment_intent_id'} + my $basetxta = "$t->{'cnombre'} + clave de pago stripe: $r->{'id'} plazo: $plazo meses cantidad: $t->{'cantidad'} "; - my $basetxtu = $t->{'cnombre'}//""." - ".$t->{'subnombre'}//""." - - "; + my $basetxtu = " + $t->{'cnombre'} +============================================ + ".$t->{'subnombre'}//""." +///////////////////////////////////////////// +"; foreach(1 .. $d->{'mq'}) { push (@ra, [" @@ -110,9 +108,9 @@ $$students[$_ -1][0] tu clave de pago es la sigiente. Tenla a la mano para cualquier aclaración -========================== - $d->{'payment_intent_id'} -=========================== +================================== + $r->{'id'} +================================== ", " Inscripción ", $$students[$_ -1][1]]); $basetxta .= " Nombre: $$students[$_ -1][0] @@ -125,6 +123,9 @@ $$students[$_ -1][0] } push (@ra, [$basetxta,"Inscripciones",'david@chaos.foundation']); + push (@ra, [$basetxta,"Inscripciones",'benjamuga@gmail.com']); + push (@ra, [$basetxta,"Inscripciones",'mmunoz@harvest.com']); + return @ra; } @@ -139,19 +140,6 @@ $$students[$_ -1][0] #'students' => [ [ 'User', 'me@me.com', 'obs', 'M' ], [ 'usr2', 'mail2', 'obs', 'G' ], undef, undef, undef, undef, undef, undef, undef, undef ] #arr(10) # =============== -sub intentSanity{ - my ($c,$d)=@_; - if (defined $d->{'selected_plan'} ){ - return -1 unless defined ($d->{'selected_plan'}{'type'}); - return -1 unless defined ($d->{'selected_plan'}{'count'}); - return -1 unless defined ($d->{'selected_plan'}{'interval'}); - } - return -1 unless defined ($d->{'tid'}) && $d->{'tid'} =~ /^\d+$/ ; - return -1 unless defined ($d->{'req'}) && $d->{'req'} eq 'check'; - return -1 unless defined ($d->{'payment_intent_id'}); - return userDataSanity($c,$d) ; -} - sub userDataSanity{ my ($c,$d) = @_; return -1 unless ( @@ -160,6 +148,7 @@ sub userDataSanity{ $d->{'mq'} =~/^\d+$/ && $d->{'mq'} < 10 ); + my %h=qw(n 0 CH 1 M 2 G 3); my $mq = $d->{'mq'}; my $students = $d->{'students'}; diff --git a/public/proc/spay/storep.css b/public/proc/spay/storep.css index 1bcf01a..7bf55e3 100755 --- a/public/proc/spay/storep.css +++ b/public/proc/spay/storep.css @@ -129,6 +129,12 @@ div#cover{ display:block; font-weight: bold; } +label.nobold { + margin:8px 0; + font-weight: normal; + font-size:1.1em; +} + .form-style-1 input[type=text], .form-style-1 input[type=date], .form-style-1 input[type=datetime], diff --git a/public/proc/spay/stripe.js b/public/proc/spay/stripe.js index 7a5beb2..19ce6f3 100644 --- a/public/proc/spay/stripe.js +++ b/public/proc/spay/stripe.js @@ -1,5 +1,6 @@ /* some format to numbers */ var it=1; +var pl = 0; //instalment plan index var students = new Array(10); /* price format (comas) */ @@ -22,6 +23,38 @@ var cform = document.getElementById('cform'); var ccard = document.getElementById('ccard'); /* ====================== */ +/* save form to array=== */ +function ftoa(){ + var rad; + if (document.getElementById('r2').checked) { rad = document.getElementById('r2').value; } + else if(document.getElementById('r1').checked) { rad = document.getElementById('r1').value; } + else { rad = document.getElementById('r3').value; } + + var x= [ + document.forms["cform"]["mname"].value, + document.forms["cform"]["mmail"].value, + document.getElementById('obs').value, + rad + ] + var tmp=mq.value; + document.getElementById("cform").reset(); + mq.value=tmp; + + return x; +} +/* ====================== */ + +/* load form from array=== */ +function atof(){ + document.forms["cform"]["mname"].value = students[it-1][0]; + document.forms["cform"]["mmail"].value = students[it-1][1]; + document.getElementById('obs').value = students[it-1][2]; + if(document.getElementById('r2').value == students[it-1][3]){ document.getElementById('r2').checked=true;} + if(document.getElementById('r1').value == students[it-1][3]){ document.getElementById('r1').checked=true;} + if(document.getElementById('r3').value == students[it-1][3]){ document.getElementById('r3').checked=true;} +} +/* ====================== */ + /* back button ========== */ cinfob.addEventListener('click', function(ev){ it --; @@ -51,13 +84,17 @@ cinfo.addEventListener('click', function(ev){ method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ students:students, req:"precheck", mq:mq.value}) - }) .then((response) => response.json()) .then((data) => { if(data.userst == "0"){ cform.hidden = true; - ccard.hidden = false; + if(meses==0){ ccard.hidden = false;} + else{ + cplan.hidden = false; + var multcc = calc_price(); + document.getElementById('gtc').innerHTML=multcc.toLocaleString(); + } } else{ alert("hay un error en los datos de alumnos"); } }) @@ -70,43 +107,41 @@ cinfo.addEventListener('click', function(ev){ } }); -/* ====================== */ +var pl = document.forms["plform"]["pl"]; +document.getElementById("timebutton").addEventListener('click', function(ev){ + cplan.hidden = true; + ccard.hidden = false; +}); -/* save form to array=== */ -function ftoa(){ - var rad; - if (document.getElementById('r2').checked) { rad = document.getElementById('r2').value; } - else if(document.getElementById('r1').checked) { rad = document.getElementById('r1').value; } - else { rad = document.getElementById('r3').value; } +function calc_price(){ + if(desc_estado == 1 && descuento > 0) { + return (mq.value*cu*(1 - (descuento/100) ) ); + } + else{ return cu*mq.value;} +}; - var x= [ - document.forms["cform"]["mname"].value, - document.forms["cform"]["mmail"].value, - document.getElementById('obs').value, - rad - ] - var tmp=mq.value; - document.getElementById("cform").reset(); - mq.value=tmp; - return x; -} -/* ====================== */ +var multc; +for (var i = 0; i < pl.length; i++) { + pl[i].addEventListener('change', function() { + if (this.value == 0 ) { + multc = calc_price(); + document.getElementById('gtc').innerHTML=multc.toLocaleString(); + } + else { + multc = cu*mq.value; + document.getElementById('gtc').innerHTML=multc.toLocaleString(); + } + }); +}; -/* load form from array=== */ -function atof(){ - document.forms["cform"]["mname"].value = students[it-1][0]; - document.forms["cform"]["mmail"].value = students[it-1][1]; - document.getElementById('obs').value = students[it-1][2]; - if(document.getElementById('r2').value == students[it-1][3]){ document.getElementById('r2').checked=true;} - if(document.getElementById('r1').value == students[it-1][3]){ document.getElementById('r1').checked=true;} - if(document.getElementById('r3').value == students[it-1][3]){ document.getElementById('r3').checked=true;} -} /* ====================== */ /* stripe magic begins here */ /* ====================================================== */ -var stripe = Stripe('pk_test_wxFt0GhsUK2YsprkLXa2iFrQ00nfjAeucu'); +let availablePlans = [0,3,6,9]; + +//var stripe = Stripe('publc_key'); var elements = stripe.elements(); var cardElement = elements.create('card', { style: { @@ -148,95 +183,61 @@ cardButton.addEventListener('click', function(ev) { .then(function(result) { // Show error in payment form if (result.error) { - document.getElementById("cover").style.opacity = "0"; - setTimeout(function(){ document.getElementById('cover').hidden = true;},500); - console.log("network error"); + errorh("connection to stripe failed"); } // Otherwise send paymentMethod.id to your server (see Step 2) else { fetch('/spay/intentCreate', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ payment_method_id: result.paymentMethod.id, req:"precheck", mq:mq.value, tid:tid}) + body: JSON.stringify({ + payment_method_id: result.paymentMethod.id, + req:"precheck", + mq:mq.value, + tid:tid, + students:students, + pl:pl.value + }) }) .then(function(result) { - // Handle server response (see Step 3) - result.json().then(function(json) { handleInstallmentPlans(json); }) + result.json().then(function(json) { end_message(json); }) }); } }); }); -///*presenta los planes de pago */ -const selectPlanForm = document.getElementById('installment-plan-form'); -let availablePlans = []; - -const handleInstallmentPlans = async (response) => { - if (response.error) { // Show error from server on payment form - console.log("preauth response error"); - } - else { - // si avaliable plans es indefinido, se queda alli con el cover - // Store the payment intent ID. - document.getElementById('payment-intent-id').value = response.intent_id; - availablePlans = response.available_plans; - // Show available installment options - availablePlans.forEach((plan, idx) => { - const newInput = document.getElementById('immediate-plan').cloneNode(); - newInput.setAttribute('value', idx); - newInput.setAttribute('id', ''); - const label = document.createElement('label'); - label.appendChild(newInput); - label.appendChild( - document.createTextNode(`${plan.count} meses`), - ); - selectPlanForm.appendChild(label); - }); - document.getElementById('ccard').hidden = true; - document.getElementById('cplan').hidden = false; - } - document.getElementById("cover").style.opacity = "0"; - setTimeout(function(){ document.getElementById('cover').hidden = true;},500); -}; - -// termina la transacción -const confirmButton = document.getElementById('confirm-button'); -confirmButton.addEventListener('click', async (ev) => { - document.getElementById('cover').hidden = false; - document.getElementById("cover").style.opacity = "0.8"; - const selectedPlanIdx = selectPlanForm.installment_plan.value; - const selectedPlan = availablePlans[selectedPlanIdx]; - const intentId = document.getElementById('payment-intent-id').value; - const response = await fetch('/spay/intentConfirm', { - method: 'POST', - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({ - payment_intent_id: intentId, - selected_plan: selectedPlan, - req:"check", - students:students, - mq:mq.value, - tid:tid - }), - }); - const responseJson = await response.json(); - // Show success / error response. +const end_message = async (response) => { document.getElementById("cover").style.opacity = "0"; setTimeout(function(){ document.getElementById('cover').hidden = true;},500); document.getElementById('cmsg').hidden = false; - document.getElementById('cplan').hidden = true; + document.getElementById('ccard').hidden = true; var message; - if (responseJson.status === "succeeded" && selectedPlan !== undefined) { - message = `¡Tu compra a ${ - selectedPlan.count + if (response.status === "succeeded" && response.pl !== null ) { + message = `¡Tu compra a ${ + response.pl.count } meses sin intereses se ha realizado con éxito! `; } else if (responseJson.status === "succeeded") { message = "¡Tu compra se ha realizado con éxito!"; } else { message = `Tenemos un problema para verificar tus datos. - Por favor intenta de nuevo o comunícate con nosotros`; + Por favor intenta de nuevo o comunícate con nosotros`; } document.getElementById("status-message").innerText = message; -}); +}; + +function errorh(msg){ + document.getElementById("cover").style.opacity = "0"; + setTimeout(function(){ document.getElementById('cover').hidden = true;},500); + cform.hidden = true; + cplan.hidden = true; + cform.hidden = true; + document.getElementById('cmsg').hidden = false; + console.log(msg); + var message = `Tenemos un problema para verificar tus datos. + Por favor intenta de nuevo o comunícate con nosotros`; + document.getElementById("status-message").innerText = message; + tid=0; + +} diff --git a/templates/proc/spay.html.ep b/templates/proc/spay.html.ep index c15c6f3..9222e37 100755 --- a/templates/proc/spay.html.ep +++ b/templates/proc/spay.html.ep @@ -1,7 +1,7 @@ %stash css=>["/proc/spay/storep.css"]; %stash js => ["/proc/spay/stripe.js"]; - +

<%= $nombre %>

<%= $municipio %>, <%= $federativa %>

@@ -25,12 +25,12 @@ <% elsif ($cupo == 0) { =%>

¡Agotado!

<% } =%>
-

Costo por asistente: $ pesos

+ + - -
+ + +