Files
pankkimaksu/index.html
Ville Rantanen 876bd8fc74 maksu so scool
2023-06-05 12:26:12 +03:00

416 lines
14 KiB
HTML

<html>
<head>
<TITLE>Banqqo</TITLE>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="lightcyan">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<STYLE type="text/css">
BODY {
font-family: sans-serif;
background-color: lightcyan;
width: 100%;
}
TEXTAREA { font-family: sans-serif; width: 100%;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
padding: 5px;
background: transparent;
}
#block {
margin-left: auto;
margin-right: auto;
width: 69%;
min-width: 69%;
max-width: 100%; }
LABEL {
width: 10ex;
display: inline-block;
}
.error {
color: salmon;
}
#barcode {
margin-top: 0em;
margin-bottom: 0em;
width: 80%;
opacity: 1;
transition: opacity 0.2s;
}
#barcodePNG {
margin-top: 1em;
margin-bottom: 1em;
width: 25%;
opacity: 1;
transition: opacity 0.2s;
display:block;
margin-left:auto;
margin-right:auto;
}
#barcodeBW {
display: none;
}
#barcodes {
margin-top: 1em;
margin-bottom: 1em;
width: 100%;
opacity: 1;
transition: opacity 0.2s;
}
#barcodes.fade {
opacity: 0;
}
/* Lasku */
#lasku {
border: 1px solid;
border-collapse: collapse;
width: 100%;
}
#lasku th, #lasku td {
border: 1px solid;
padding: 1ex;
vertical-align: top;
}
#lasku .col1 { width: 10%; }
#lasku .col2 { width: 40%; }
#lasku .col3 { width: 10%; }
#lasku .col4 { width: 20%; }
#lasku .col5 { width: 20%; }
#lasku_summa {
text-align: right;
}
#lasku_summa::after {
content: " €";
padding-right: 8px;
}
#lasku_barcode {
text-align:center;
}
.print_help {
display: none;
}
@media print {
.no-print, .no-print * {
display: none !important;
}
#block {
width: 90vw;
min-width: 90vw;
max-width: 90vw;
}
.kayttaja {
display: none;
}
.print_help {
display: block;
overflow: visible;
white-space: pre;
white-space: pre-wrap;
}
}
</STYLE>
<script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.5/dist/barcodes/JsBarcode.code128.min.js"></script>
<script>
function clear_barcode() {
//document.getElementById('barcode').innerHTML = "";
document.getElementById('barcodes').classList.add("fade");
setTimeout(function() {
document.getElementById('barcode').innerHTML = "";
}, 200);
}
function flash_generate() {
clear_barcode();
setTimeout(function() { generate() }, 200);
}
function generate(final = true) {
let code = validate(final = final);
if (!code) {
clear_barcode();
clear_lasku();
return
}
document.getElementById('virtuaali').value = code;
JsBarcode("#barcode", code, {
format: "CODE128",
lineColor: "#404",
background: "transparent",
width: 2,
height: 80,
displayValue: true
});
JsBarcode("#barcodeBW", code, {
format: "CODE128",
lineColor: "black",
background: "transparent",
width: 2,
height: 80,
displayValue: true
});
document.getElementById('barcodes').classList.remove("fade");
convertSVGAsPNG(true);
modify_lasku();
return;
}
function make_error(id, text) {
document.getElementById(id).innerHTML = text;
return false
}
function clear_error() {
document.getElementById('iban_error').innerHTML = '';
document.getElementById('summa_error').innerHTML = '';
document.getElementById('viite_error').innerHTML = '';
document.getElementById('paiva_error').innerHTML = '';
}
function modify_request(iban,summa,viite,paiva) {
let URL = window.location.href.split('?')[0]
const nextURL = `${URL}?FI${iban},${summa},${viite},${paiva}`;
window.history.replaceState({}, document.title, nextURL);
}
function calculate_viite_tarkiste(ilman_tarkiste) {
let kertoimet = Array(7, 3, 1);
let tulosumma = 0;
for (const [index, element] of ilman_tarkiste.entries()) {
tulosumma += kertoimet[index % 3] * parseInt(element);
}
let tarkiste = (10 - (tulosumma % 10)) % 10;
return tarkiste
}
function validate_viite(viite) {
if (! /^\d+$/.test(viite)) {
return Array(false, "Joukossa muutakin kun numeroita!");
}
let nurin = reversed(viite);
if (nurin.length < 3) return Array(false, "Liian lyhyt")
let ilman_tarkiste = nurin.substring(1).split('');
let tarkiste = calculate_viite_tarkiste(ilman_tarkiste);
if (tarkiste != parseInt(nurin.substring(0,1))) return Array(false, "Tarkiste ei täsmää, viite väärin, tai jos olet luomassa omaa, lisää tarkiste: " + calculate_viite_tarkiste(nurin.split('')).toString());
return Array(true, String(viite).padStart(20,'0'));
}
function validate(final = true) {
clear_error();
// IBAN
let iban = document.getElementById('iban').value.replaceAll(' ','').replace(/^FI/,"");
if (iban.length != 16) return make_error('iban_error',"Vaatii 16 numeroa ja pitää alkaa FI!");
if (! /^\d+$/.test(iban)) return make_error('iban_error',"Joukossa muutakin kun numeroita!");
// SUMMA
let summa = parseFloat(
document.getElementById('summa').value.replaceAll(' ','').replace(',','.')
);
if (isNaN(summa)) {
return make_error('summa_error', "Ei numero");
}
if ( summa <= 0 ) {
return make_error('summa_error', "Summan pitää olla positiivinen");
}
let sumsplit = summa.toFixed(2).split(".");
let euro = String(sumsplit[0]).padStart(6,'0');
let cents = String(sumsplit[1]).padStart(2,'0');
// VIITE
let viite = document.getElementById('viite').value.replaceAll(/[^\d]/g,'').replace(/^0+/,"");
let viite_valid = validate_viite(viite);
if (! viite_valid[0]) return make_error("viite_error", viite_valid[1]);
// PAIVA
if (! /^[\d-]+$/.test(document.getElementById('paiva').value)) {
return make_error('paiva_error',"Joukossa muutakin kun numeroita ja - !");
}
let paiva_obj = new Date(Date.parse(document.getElementById('paiva').value));
if (isNaN(paiva_obj)) return make_error('paiva_error', "Eräpäivä muotoa VVVV-KK-PP");
let lyhyt_paiva = paiva_obj.getFullYear().toString().slice(-2) + String(paiva_obj.getMonth() + 1).padStart(2,'0') + String(paiva_obj.getDate()).padStart(2,'0');
let oikea_paiva = Array(
paiva_obj.getFullYear().toString(),
String(paiva_obj.getMonth() + 1).padStart(2,'0'),
String(paiva_obj.getDate()).padStart(2,'0')
).join("-");
// Modify form values when validation is final
if (final) {
document.getElementById('iban').value = (('FI' + iban).match(/.{1,4}/g)).join(" ");
document.getElementById('summa').value = summa.toFixed(2);
document.getElementById('viite').value = reversed(reversed(viite).match(/.{1,5}/g).join(" "));
document.getElementById('paiva').value = oikea_paiva;
modify_request(iban,document.getElementById('summa').value,viite, oikea_paiva);
}
// Yhdistely
let fin = '4';
let spare = '000';
let code = fin + iban + euro + cents + spare + viite_valid[1] + lyhyt_paiva;
return code;
}
function parse_virtual() {
document.getElementById('virtuaali_error').innerHTML = "";
let vkoodi = document.getElementById('virtuaali').value.replaceAll(" ","");
if (vkoodi.length != 54) return make_error('virtuaali_error', 'Koodi väärän mittainen');
if (! /^\d+$/.test(vkoodi)) {
return make_error('virtuaali_error',"Joukossa muutakin kun numeroita!");
}
if (vkoodi.substring(0,1) != '4') {
return make_error('virtuaali_error',"Ei kotimainen maksukoodi!");
}
let iban = "FI" + vkoodi.substring(1,17);
let summa = (parseFloat(vkoodi.substring(17,25))/100).toFixed(2);
let viite = vkoodi.substring(28,48).replace(/^0+/,'');
let vuosisata = (new Date()).getFullYear().toString().substring(0,2);
let vuosi = vkoodi.substring(48,50);
let kuu = vkoodi.substring(50,52);
let paiva = vkoodi.substring(52,54);
let paivays = `${vuosisata}${vuosi}-${kuu}-${paiva}`;
document.getElementById('iban').value = iban;
document.getElementById('summa').value = summa;
document.getElementById('viite').value = viite;
document.getElementById('paiva').value = paivays;
flash_generate();
}
function convertSVGAsPNG(e){
//const canvas = document.createElement("canvas");
//const svg = document.querySelector('svg');
const svg = document.getElementById('barcodeBW');
const base64doc = btoa(unescape(encodeURIComponent(svg.outerHTML)));
const w = parseInt(svg.getAttribute('width'));
const h = parseInt(svg.getAttribute('height'));
/*const img_to_download = document.createElement('img');*/
const img_to_download = document.getElementById('barcodePNG');
img_to_download.src = 'data:image/svg+xml;base64,' + base64doc;
/*img_to_download.onload = function () {
console.log('img loaded');
canvas.setAttribute('width', w);
canvas.setAttribute('height', h);
const context = canvas.getContext("2d");
//context.clearRect(0, 0, w, h);
context.drawImage(img_to_download,0,0,w,h);
const dataURL = canvas.toDataURL('image/png');
const filename = 'maksu-' + document.getElementById('paiva').value + '.png';
if (window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(canvas.msToBlob(), filename);
e.preventDefault();
} else {
const a = document.createElement('a');
const my_evt = new MouseEvent('click');
a.download = filename;
a.href = dataURL;
a.dispatchEvent(my_evt);
}
//canvas.parentNode.removeChild(canvas);
}*/
}
function print_help() {
let fields = ['saaja','maksaja','laskun_tiedot'];
for (let i = 0; i < fields.length; i++) {
let source = document.getElementById(fields[i]);
let target = document.getElementById('print_' + fields[i]);
target.innerHTML = source.value;
}
}
function modify_lasku() {
let fields = ['iban','summa','viite','paiva'];
for (let i = 0; i < fields.length; i++) {
try {
document.getElementById('lasku_' + fields[i]).innerHTML = document.getElementById(fields[i]).value;
} catch {}
}
print_help();
}
function clear_lasku() {
let fields = ['iban','summa','viite','paiva'];
for (let i = 0; i < fields.length; i++) {
try {
document.getElementById('lasku_' + fields[i]).innerHTML = "";
} catch {}
}
}
function init() {
const date = new Date();
document.getElementById('paiva').value = date.toISOString().substring(0,10);
let request = window.location.search.substring(1);
let vars = request.split(',');
for (let i = 0; i < vars.length; i++) {
if (vars[i].length == 0) continue
if (i==0) document.getElementById('iban').value = vars[i];
if (i==1) document.getElementById('summa').value = vars[i];
if (i==2) document.getElementById('viite').value = vars[i];
if (i==3) document.getElementById('paiva').value = vars[i];
}
flash_generate();
}
function reversed(str) {
return str.split("").reverse().join("");
}
</script>
</head>
<body onload="init()">
<div id=block>
<div class="no-print">
<p>Maksun virtuaali viivakoodi / viivakoodi <small>Nothing ever leaves this page.</small></p>
<label>IBAN: </label><br><input id="iban" size=18 value="FI12 3456 7890 1234 56" onblur="generate()" onkeyup="generate(false)" /><br>
<label>&nbsp;</label><span id="iban_error" class="error" ></span><br>
<label>Summa: </label><br><input id="summa" size=10 value=10 onblur="generate()" onkeyup="generate(false)" />&euro;<br>
<label>&nbsp;</label><span id="summa_error" class="error" ></span><br>
<label>Viite: </label><br><input id="viite" size=20 value=1054 onblur="generate()" onkeyup="generate(false)" />&nbsp;Viite pakollinen, esim 1054 jos et keksi<br>
<label>&nbsp;</label><span id="viite_error" class="error" ></span><br>
<label>Eräpäivä: </label><br><input id="paiva" size=10 onblur="generate()" onkeyup="generate(false)" /><br>
<label>&nbsp;</label><span id="paiva_error" class="error" ></span><br>
<input type="submit" onclick="flash_generate()" value="Generoi"/>
<br>
</div>
<div id="barcodes">
<table id="lasku">
<tbody>
<tr>
<td class=col1>Saajan tilinumero</td><td class=col2 id="lasku_iban">[tilinro]</td><td colspan=3 rowspan=2><textarea class=kayttaja rows=10 id=laskun_tiedot placeholder="Laskun tiedot" onblur="print_help()" onkeyup="print_help()"></textarea><div class="print_help" id="print_laskun_tiedot"></div></td>
</tr>
<tr>
<td class=col1>Saaja</td><td class=col2><textarea id=saaja class=kayttaja rows=3 placeholder="Saajan tiedot" onblur="print_help()" onkeyup="print_help()"></textarea><div class="print_help" id="print_saaja"></div></td>
</tr>
<tr>
<td class=col1 rowspan=2>Maksaja</td><td class=col2 rowspan=2><textarea id=maksaja class=kayttaja rows=3 placeholder="Maksajan tiedot" onblur="print_help()" onkeyup="print_help()"></textarea><div class="print_help" id="print_maksaja"></div></td>
<td class=col3>Viite</td><td colspan=2 id="lasku_viite">[viite]</td>
</tr>
<tr>
<td class=col3>Eräpäivä</td><td class=col4 id="lasku_paiva">[paiva]</td><td class=col5 id="lasku_summa">[summa]</td>
</tr>
<tr>
<td colspan=5 id=lasku_barcode><svg id="barcode"></svg></td>
</tr>
</tbody>
</table>
</div>
<br>
<div class="no-print">
<label>Virtuaaliviivakoodi:</label><br>
<input id="virtuaali" size=54 /><br>
<label>&nbsp;</label><span id="virtuaali_error" class="error" ></span><br>
<input type="submit" onclick="parse_virtual()" value="Muunna virtuaalikoodi kenttiin"/>
<br>
<svg id="barcodeBW"></svg>
<p>Talleta kuvamuodossa:</p>
<img id="barcodePNG" alt="Talleta kuvana" title="Talleta kuvana"></img>
</div>
</div>
</body>
</html>