modifica timeout lettura
ridotto per velocizzare il processo di lettura di qr code. la classe qrscanner è utilizzata solo a fini di test per la lettura di qr code con webcam. nel frmcerca aggiunto campo nascosto per gestire la lettura del qr code senza mostrarlo a video, viene inserito il numero di tessera solo se i controlli vanno a buon fine nel form principale (puntocassa) non è stato necessario, in quanto ci sono thread in ascolto che leggono i caratteri (emulazione tastiera), validi sia per il qr code che per rfid. nella classe qrcryptoservice.java è inserito il timer del qr code (CLOCK_SKEW) a 60 secondi, nonchè la chiave AES per la decriptazione (AES_KEY): dovrà essere modificata quando si andrà in produzione. L'algoritmo di decriptazione usato per il qr code è AES-256 con CBC.
This commit is contained in:
parent
92995d5658
commit
f8fba1fec3
@ -73,6 +73,8 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="lblCF" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="61" max="-2" attributes="0"/>
|
||||
<Component id="jtxtNumTesseraHidden" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
@ -98,14 +100,22 @@
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="jLblTitolo" min="-2" pref="25" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lblCognome" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblNome" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblCF" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="jLblTitolo" min="-2" pref="25" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lblCognome" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblNome" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblCF" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
|
||||
<Component id="jtxtNumTesseraHidden" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="jtxtNumTessera" alignment="3" min="-2" pref="40" max="-2" attributes="0"/>
|
||||
@ -263,6 +273,13 @@
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jbtnGiuActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="jtxtNumTesseraHidden">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[0, 0]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
|
@ -6,24 +6,38 @@
|
||||
|
||||
package puntocassa;
|
||||
|
||||
import com.github.sarxos.webcam.Webcam;
|
||||
import com.google.zxing.BinaryBitmap;
|
||||
import com.google.zxing.LuminanceSource;
|
||||
import com.google.zxing.MultiFormatReader;
|
||||
import com.google.zxing.NotFoundException;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.FocusAdapter;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.table.TableColumn;
|
||||
import puntocassa.utils.QrCryptoService;
|
||||
import puntocassa.utils.Utils;
|
||||
|
||||
/**
|
||||
@ -43,6 +57,7 @@ private JTextField jtxtTessera;
|
||||
private Boolean FlagMostraDataNascita=true;
|
||||
private Boolean DisabilitaPerBuono=false;
|
||||
|
||||
|
||||
/**
|
||||
* Creates new form frm
|
||||
*/
|
||||
@ -100,7 +115,44 @@ private JTextField jtxtTessera;
|
||||
jtxtCognome.setText(BuoniPasto);
|
||||
Cerca();
|
||||
Disabilita();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
jtxtNumTesseraHidden.addActionListener(e -> {
|
||||
System.out.println("QR letto: " + jtxtNumTesseraHidden.getText().trim());
|
||||
String valueRead = jtxtNumTesseraHidden.getText().trim();
|
||||
//decripting
|
||||
List<String> dataResult = QrCryptoService.decryptAndValidate(valueRead);
|
||||
//System.out.println("QR code decriptato: " + r);
|
||||
if(dataResult.get(0).equals("VALID")){
|
||||
//verifica che il codice fiscale corrisponda ad una tessera
|
||||
String numTessera = Utils.mySelect("select numero from tessere where id_utente = (select id from utenti where codice_fiscale = '" +
|
||||
dataResult.get(1) +
|
||||
"')", "numero", frmPuntoCassa);
|
||||
if(numTessera == null || "".equals(numTessera)){
|
||||
//mostra un popup di errore UTENTE NON COLLEGATO AD UNA TESSERA
|
||||
System.out.println("nessuna tessera collegata all'utente " + dataResult.get(1));
|
||||
JOptionPane.showOptionDialog(this, "Nessuna tessera collegata all'utente " + dataResult.get(1) , "Attenzione",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, null, null);
|
||||
jtxtNumTesseraHidden.setText("");
|
||||
jtxtNumTessera.setText("");
|
||||
return;
|
||||
}
|
||||
//scrivi il numero della tessera nel campo input
|
||||
jtxtNumTessera.setText(numTessera);
|
||||
jtxtNumTesseraHidden.setText("");
|
||||
Cerca();
|
||||
}
|
||||
else {
|
||||
System.out.println("QR non valido: "+ dataResult.get(1));
|
||||
JOptionPane.showOptionDialog(this, dataResult.get(1) , "Attenzione",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, null, null);
|
||||
jtxtNumTesseraHidden.setText("");
|
||||
jtxtNumTessera.setText("");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -128,6 +180,7 @@ private JTextField jtxtTessera;
|
||||
jBtnOK = new javax.swing.JButton();
|
||||
jbtnSu = new javax.swing.JButton();
|
||||
jbtnGiu = new javax.swing.JButton();
|
||||
jtxtNumTesseraHidden = new javax.swing.JTextField();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
setTitle("Cerca Tessera Attiva");
|
||||
@ -237,6 +290,8 @@ private JTextField jtxtTessera;
|
||||
}
|
||||
});
|
||||
|
||||
jtxtNumTesseraHidden.setPreferredSize(new java.awt.Dimension(0, 0));
|
||||
|
||||
javax.swing.GroupLayout pnl1Layout = new javax.swing.GroupLayout(pnl1);
|
||||
pnl1.setLayout(pnl1Layout);
|
||||
pnl1Layout.setHorizontalGroup(
|
||||
@ -256,6 +311,8 @@ private JTextField jtxtTessera;
|
||||
.addGroup(pnl1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(pnl1Layout.createSequentialGroup()
|
||||
.addComponent(lblCF)
|
||||
.addGap(61, 61, 61)
|
||||
.addComponent(jtxtNumTesseraHidden, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
.addGroup(pnl1Layout.createSequentialGroup()
|
||||
.addComponent(jtxtNumTessera, javax.swing.GroupLayout.PREFERRED_SIZE, 176, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
@ -274,12 +331,17 @@ private JTextField jtxtTessera;
|
||||
pnl1Layout.setVerticalGroup(
|
||||
pnl1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnl1Layout.createSequentialGroup()
|
||||
.addComponent(jLblTitolo, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(pnl1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblCognome)
|
||||
.addComponent(lblNome)
|
||||
.addComponent(lblCF))
|
||||
.addGroup(pnl1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(pnl1Layout.createSequentialGroup()
|
||||
.addComponent(jLblTitolo, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(pnl1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblCognome)
|
||||
.addComponent(lblNome)
|
||||
.addComponent(lblCF)))
|
||||
.addGroup(pnl1Layout.createSequentialGroup()
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(jtxtNumTesseraHidden, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(pnl1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addGroup(pnl1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
@ -330,6 +392,9 @@ private JTextField jtxtTessera;
|
||||
jtxtNome.setBackground(Color.white);
|
||||
jtxtCognome.setBackground(Color.white);
|
||||
}
|
||||
|
||||
jtxtNumTesseraHidden.requestFocusInWindow();
|
||||
|
||||
// MyApplication MyA = new MyApplication();
|
||||
// if (MyA.TastieraVideo) {
|
||||
// if (MyA.UltimoTxt.equalsIgnoreCase(evt.getComponent().toString())) {
|
||||
@ -478,6 +543,54 @@ private JTextField jtxtTessera;
|
||||
|
||||
private void jtxtNumTesseraMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jtxtNumTesseraMouseClicked
|
||||
Tastiera(evt);
|
||||
|
||||
// //attivazione webcam per lettura qr
|
||||
// Webcam webcam = Webcam.getDefault();
|
||||
// //webcam.setViewSize(new Dimension(1280, 720));
|
||||
// Dimension hd = new Dimension(1280, 720);
|
||||
// webcam.setCustomViewSizes(new Dimension[] { hd });
|
||||
// webcam.setViewSize(hd);
|
||||
//
|
||||
// webcam.open();
|
||||
//
|
||||
// while (true) {
|
||||
// BufferedImage image = webcam.getImage();
|
||||
// if (image == null) continue;
|
||||
//
|
||||
// LuminanceSource source = new BufferedImageLuminanceSource(image);
|
||||
// BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||
//
|
||||
// try {
|
||||
// Result result = new MultiFormatReader().decode(bitmap);
|
||||
// System.out.println("QR Code trovato: " + result.getText());
|
||||
// //decripting
|
||||
// List<String> dataResult = QrCryptoService.decryptAndValidate(result.getText());
|
||||
// //System.out.println("QR code decriptato: " + r);
|
||||
// if(dataResult.get(0).equals("VALID")){
|
||||
// //verifica che il codice fiscale corrisponda ad una tessera
|
||||
// String numTessera = Utils.mySelect("select numero from tessere where id_utente = (select id from utenti where codice_fiscale = '" +
|
||||
// dataResult.get(1) +
|
||||
// "')", "numero", frmPuntoCassa);
|
||||
// if(numTessera == null || "".equals(numTessera)){
|
||||
// //mostra un popup di errore UTENTE NON COLLEGATO AD UNA TESSERA
|
||||
// System.out.println("nessuna tessera collegata all'utente " + dataResult.get(1));
|
||||
// return;
|
||||
// }
|
||||
// //scrivi il numero della tessera nel campo input
|
||||
// jtxtNumTessera.setText(numTessera);
|
||||
// Cerca();
|
||||
// }
|
||||
// else {
|
||||
// System.out.println("QR non valido: "+ dataResult.get(1));
|
||||
// }
|
||||
// break;
|
||||
// } catch (NotFoundException e) {
|
||||
// // Nessun QR code trovato nel frame
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// webcam.close();
|
||||
|
||||
}//GEN-LAST:event_jtxtNumTesseraMouseClicked
|
||||
private void Tastiera(java.awt.event.MouseEvent evt) {
|
||||
MyApplication MyA = new MyApplication();
|
||||
@ -753,6 +866,7 @@ private JTextField jtxtTessera;
|
||||
private javax.swing.JTextField jtxtCognome;
|
||||
private javax.swing.JTextField jtxtNome;
|
||||
private javax.swing.JTextField jtxtNumTessera;
|
||||
private javax.swing.JTextField jtxtNumTesseraHidden;
|
||||
private javax.swing.JLabel lblCF;
|
||||
private javax.swing.JLabel lblCognome;
|
||||
private javax.swing.JLabel lblNome;
|
||||
|
@ -27,10 +27,13 @@ import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
@ -49,6 +52,7 @@ import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import puntocassa.utils.QrCryptoService;
|
||||
import puntocassa.utils.Utils;
|
||||
|
||||
//******************************************************************************
|
||||
@ -223,20 +227,18 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
//adatto panel login
|
||||
pnlLogin.setSize(calcolaLarghezzaAltezza(pnlLogin.getWidth(), largControlli), calcolaLarghezzaAltezza(pnlLogin.getHeight(), altControlli));
|
||||
jBtnReadCard.setVisible(false);
|
||||
|
||||
|
||||
settingFontsInterfaccia();
|
||||
|
||||
|
||||
jcmbSmartCard.setVisible(false);
|
||||
|
||||
visualizzaMessaggiDisplay = document.getElementsByTagName("Visualizza_Messaggi_Display").item(0).getFirstChild().getNodeValue()
|
||||
.equalsIgnoreCase("SI");
|
||||
.equalsIgnoreCase("SI");
|
||||
//visualizzaMessaggiDisplay = VMD.equalsIgnoreCase("SI");
|
||||
messageDisplay = document.getElementsByTagName("Messaggio_Display").item(0).getFirstChild().getNodeValue();
|
||||
|
||||
aggiornaSmartCardReaderCombo(myApp);
|
||||
|
||||
|
||||
String ultimiMovimenti = Utils.mySelect("SELECT valore FROM parametri WHERE chiave = 'FlagVisualizzaUltimiPassaggi'",
|
||||
"valore",
|
||||
this);
|
||||
@ -313,8 +315,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
txtPassword.setFont(f);
|
||||
jTxtTessera.setFont(f);
|
||||
jChLogin.setFont(f);
|
||||
|
||||
|
||||
|
||||
Font newFontBtnAnnulla = new Font(jbtnAnnulla.getFont().getName(), jbtnAnnulla.getFont().getStyle(), hFont);
|
||||
jbtnAnnulla.setFont(newFontBtnAnnulla);
|
||||
Font newFontBtnDuplica = new Font(jbtnDuplica.getFont().getName(), jbtnDuplica.getFont().getStyle(), hFont);
|
||||
@ -331,10 +332,11 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
|
||||
/**
|
||||
* Lettura del nodo 'display' del file di configurazione
|
||||
*
|
||||
* @param document
|
||||
* @param myApp
|
||||
* @throws NumberFormatException
|
||||
* @throws DOMException
|
||||
* @throws DOMException
|
||||
*/
|
||||
private void leggiNodoDisplay(Document document, MyApplication myApp) throws NumberFormatException, DOMException {
|
||||
// --------------------------------------------------------------------
|
||||
@ -353,7 +355,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
largControlli = Integer.parseInt(p.getElementsByTagName("larghezzaControlli").item(0).getFirstChild().getNodeValue());
|
||||
String tastiera = p.getElementsByTagName("TastieraVideo").item(0).getFirstChild().getNodeValue();
|
||||
myApp.tastieraVideo = !tastiera.equals("NO");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -410,7 +412,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
* @throws DOMException
|
||||
*/
|
||||
private void leggiNodoDatabase(Document document) throws DOMException {
|
||||
NodeList database = document.getElementsByTagName("database");
|
||||
NodeList database = document.getElementsByTagName("database");
|
||||
for (int i = 0; i < database.getLength(); i++) {
|
||||
Node nodo = database.item(i);
|
||||
|
||||
@ -508,8 +510,10 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
//29-10-18------------------------------------------------------
|
||||
if (timerUnaVolta == false) {
|
||||
timerUnaVolta = true;
|
||||
|
||||
final Timer timer = new Timer();
|
||||
final TimerTask task = new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@ -526,12 +530,11 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
}
|
||||
};
|
||||
|
||||
timer.schedule(task, 5000);
|
||||
timer.schedule(task, 4000);
|
||||
}
|
||||
//fine 29-10-18------------------------------------------------------
|
||||
//fine 29-10-18------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -553,73 +556,241 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
@Override
|
||||
public void run() {
|
||||
String tessera = "";
|
||||
boolean isQrCode = false;
|
||||
//se abbiamo uno \n e la lunghezza è > 200 caratteri, è un qr code
|
||||
if (testoSwipCard.toString().contains("\n") && testoSwipCard.length() > 200) {
|
||||
recuperaNumeroTesseraQrCode();
|
||||
isQrCode = true;
|
||||
|
||||
}
|
||||
//per tessere tipo 8 e 9
|
||||
if (testoSwipCard.toString().contains("ì")) {
|
||||
String[] txt = testoSwipCard.toString().split("ì");
|
||||
if (!isQrCode) {
|
||||
if (testoSwipCard.toString().contains("ì")) {
|
||||
String[] txt = testoSwipCard.toString().split("ì");
|
||||
|
||||
// per tessera MASTERCARD CARDHOLDER
|
||||
if (testoSwipCard.toString().length() > 30) {
|
||||
// per tessera MASTERCARD CARDHOLDER
|
||||
if (testoSwipCard.toString().length() > 30) {
|
||||
|
||||
tessera = txt[0].trim().replace("_", "");
|
||||
} else {
|
||||
tessera = txt[1].trim().replace("_", "");
|
||||
}
|
||||
} else if (testoSwipCard.toString().contains("&")) {
|
||||
// per tessera MASTERCARD CARDHOLDER
|
||||
String[] txt = testoSwipCard.toString().split("&");
|
||||
|
||||
tessera = txt[0].trim().replace("%B", "");
|
||||
|
||||
} else {
|
||||
tessera = testoSwipCard.toString().trim().replace("_", "");
|
||||
}
|
||||
|
||||
//per tessera tipo 3
|
||||
if (tessera.length() >= 17 && tessera.length() <= 19) {
|
||||
tessera = tessera.substring(0, 7);
|
||||
}
|
||||
|
||||
//per tessere tipo 6 e 7
|
||||
if (tessera.length() == 21) {
|
||||
tessera = tessera.substring(0, 10);
|
||||
int posI = 0;
|
||||
for (int i = 0; i <= tessera.length(); i++) {
|
||||
if (tessera.substring(i, i + 1).equalsIgnoreCase("0") == false) {
|
||||
posI = i;
|
||||
break;
|
||||
tessera = txt[0].trim().replace("_", "");
|
||||
} else {
|
||||
tessera = txt[1].trim().replace("_", "");
|
||||
}
|
||||
} else if (testoSwipCard.toString().contains("&")) {
|
||||
// per tessera MASTERCARD CARDHOLDER
|
||||
String[] txt = testoSwipCard.toString().split("&");
|
||||
|
||||
tessera = txt[0].trim().replace("%B", "");
|
||||
|
||||
} else {
|
||||
tessera = testoSwipCard.toString().trim().replace("_", "");
|
||||
}
|
||||
|
||||
tessera = tessera.substring(posI);
|
||||
}
|
||||
//per tessera tipo 3
|
||||
if (tessera.length() >= 17 && tessera.length() <= 19) {
|
||||
tessera = tessera.substring(0, 7);
|
||||
}
|
||||
|
||||
spiaAltreCarte = false;
|
||||
swip = false;
|
||||
if (pnlLogin.isVisible()) {
|
||||
controllaLogInCarta(tessera);
|
||||
} else {
|
||||
//05/11/2018 le nuove tessere con CF a volte leggono solo la matricola
|
||||
jTxtTessera.setText(tessera);
|
||||
passaggioTessera = true;
|
||||
logNumeroTessera = tessera;
|
||||
cercaTessera();
|
||||
}
|
||||
//per tessere tipo 6 e 7
|
||||
if (tessera.length() == 21) {
|
||||
tessera = tessera.substring(0, 10);
|
||||
int posI = 0;
|
||||
for (int i = 0; i <= tessera.length(); i++) {
|
||||
if (tessera.substring(i, i + 1).equalsIgnoreCase("0") == false) {
|
||||
posI = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
testoSwipCard = new StringBuilder();
|
||||
tessera = tessera.substring(posI);
|
||||
}
|
||||
|
||||
spiaAltreCarte = false;
|
||||
swip = false;
|
||||
if (pnlLogin.isVisible()) {
|
||||
controllaLogInCarta(tessera);
|
||||
} else {
|
||||
//05/11/2018 le nuove tessere con CF a volte leggono solo la matricola
|
||||
jTxtTessera.setText(tessera);
|
||||
passaggioTessera = true;
|
||||
logNumeroTessera = tessera;
|
||||
cercaTessera();
|
||||
}
|
||||
|
||||
testoSwipCard = new StringBuilder();
|
||||
|
||||
}
|
||||
|
||||
timer.cancel();
|
||||
timer.purge();
|
||||
statoCardLettore = false;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
timer.schedule(task, delaySwipCard);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
// public KeyEventDispatcher creaKeyEventDispatcher() {
|
||||
// return new KeyEventDispatcher() {
|
||||
// Boolean timerUnaVolta = false;
|
||||
// MyApplication myApp = new MyApplication();
|
||||
//
|
||||
// public boolean dispatchKeyEvent(KeyEvent e) {
|
||||
// int id = e.getID();
|
||||
//
|
||||
// if (jbtnChiudi.isEnabled() && !pnlLogin.isVisible() && jTxtTessera.getText().length() > 0) {
|
||||
// e.consume();
|
||||
// if (!myApp.unaVolta) {
|
||||
// myApp.unaVolta = true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
// myApp.unaVolta = false;
|
||||
//
|
||||
// int keyCode = e.getKeyCode();
|
||||
// if (id == KeyEvent.KEY_RELEASED) {
|
||||
// String tasto = "" + e.getKeyChar();
|
||||
// System.out.println(keyCode + " - " + tasto);
|
||||
//
|
||||
// logTestoTessera.append(e.getKeyChar());
|
||||
//
|
||||
// // RFID input
|
||||
// if (keyCode != KeyEvent.VK_SHIFT) {
|
||||
// testoRFIDCard.append(tasto);
|
||||
// }
|
||||
//
|
||||
// // Invio: fine lettura RFID
|
||||
// if (keyCode == KeyEvent.VK_ENTER) {
|
||||
// System.out.println(testoRFIDCard.toString());
|
||||
// warn();
|
||||
// }
|
||||
//
|
||||
// // Timer per letture incomplete
|
||||
// if (!timerUnaVolta) {
|
||||
// timerUnaVolta = true;
|
||||
//
|
||||
// final Timer timer = new Timer();
|
||||
// final TimerTask task = new TimerTask() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// if (testoRFIDCard.toString().length() > 2) {
|
||||
// System.out.println("Timer: " + testoRFIDCard.toString());
|
||||
// warn();
|
||||
// testoRFIDCard = new StringBuilder();
|
||||
// }
|
||||
//
|
||||
// timer.cancel();
|
||||
// timer.purge();
|
||||
// timerUnaVolta = false;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// timer.schedule(task, 4000);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// public void warn() {
|
||||
// if (statoCardLettore) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// //testoRFIDCard = new StringBuilder();
|
||||
//
|
||||
// if (testoRFIDCard.toString().length() > 0) {
|
||||
// statoCardLettore = true;
|
||||
//
|
||||
// final Timer timer = new Timer();
|
||||
// final TimerTask task = new TimerTask() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// String tessera = "";
|
||||
// boolean isQrCode = false;
|
||||
//
|
||||
// if (testoRFIDCard.toString().contains("\n") && testoRFIDCard.length() > 200) {
|
||||
// recuperaNumeroTesseraQrCode();
|
||||
// isQrCode = true;
|
||||
// }
|
||||
//
|
||||
// if (!isQrCode) {
|
||||
// tessera = testoRFIDCard.toString().trim().replace("_", "");
|
||||
//
|
||||
// if (tessera.length() >= 17 && tessera.length() <= 19) {
|
||||
// tessera = tessera.substring(0, 7);
|
||||
// }
|
||||
//
|
||||
// if (tessera.length() == 21) {
|
||||
// tessera = tessera.substring(0, 10);
|
||||
// int posI = 0;
|
||||
// for (int i = 0; i <= tessera.length(); i++) {
|
||||
// if (!tessera.substring(i, i + 1).equalsIgnoreCase("0")) {
|
||||
// posI = i;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// tessera = tessera.substring(posI);
|
||||
// }
|
||||
//
|
||||
// if (pnlLogin.isVisible()) {
|
||||
// controllaLogInCarta(tessera);
|
||||
// } else {
|
||||
// jTxtTessera.setText(tessera);
|
||||
// passaggioTessera = true;
|
||||
// logNumeroTessera = tessera;
|
||||
// cercaTessera();
|
||||
// }
|
||||
//
|
||||
// testoRFIDCard = new StringBuilder();
|
||||
// }
|
||||
//
|
||||
// timer.cancel();
|
||||
// timer.purge();
|
||||
// statoCardLettore = false;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// timer.schedule(task, delaySwipCard);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
public void recuperaNumeroTesseraQrCode() {
|
||||
//controllo sul qr code prima di lanciare la ricerca della tessera
|
||||
String valueRead = testoSwipCard.toString().trim();
|
||||
//String valueRead = testoRFIDCard.toString().trim();
|
||||
//decripting
|
||||
java.util.List<String> dataResult = QrCryptoService.decryptAndValidate(valueRead);
|
||||
if (dataResult.get(0).equals("VALID")) {
|
||||
//verifica che il codice fiscale corrisponda ad una tessera
|
||||
String numTessera = Utils.mySelect("select seleziona_tessera ('" + dataResult.get(1) + "') as numero from dual", "numero", this);
|
||||
System.out.println("Dopo select numero from tessere");
|
||||
if (numTessera == null || "".equals(numTessera)) {
|
||||
//mostra un popup di errore UTENTE NON COLLEGATO AD UNA TESSERA
|
||||
System.out.println("nessuna tessera collegata all'utente " + dataResult.get(1));
|
||||
JOptionPane.showOptionDialog(this, "Nessuna tessera collegata all'utente " + dataResult.get(1), "Attenzione",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, null, null);
|
||||
jTxtTessera.setText("");
|
||||
}
|
||||
//scrivi il numero della tessera nel campo input
|
||||
jTxtTessera.setText(numTessera);
|
||||
cercaTessera();
|
||||
} else {
|
||||
System.out.println("Errore validazione QR code: " + dataResult.get(1));
|
||||
JOptionPane.showOptionDialog(this, dataResult.get(1), "Attenzione",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, null, null);
|
||||
//jtxtNumTesseraHidden.setText("");
|
||||
jTxtTessera.setText("");
|
||||
//reset del logTestoTessera in quanto non viene richiamata la cercaTessera() che contiene logTessera() che effettua la stessa istruzione
|
||||
logTestoTessera = new StringBuilder();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -701,7 +872,8 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
|
||||
/**
|
||||
* Aggiorna la lista di lettori smartcard disponibili
|
||||
* @param myApp
|
||||
*
|
||||
* @param myApp
|
||||
*/
|
||||
private void aggiornaSmartCardReaderCombo(MyApplication myApp) {
|
||||
try {
|
||||
@ -1796,7 +1968,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
// ==========================================================================
|
||||
// *** Metodo per gestire gli eventi sui button dinamici
|
||||
// ==========================================================================
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String cmd = e.getActionCommand();
|
||||
String tipo;
|
||||
String id;
|
||||
@ -1818,7 +1990,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
case "PRODOTTO" -> {
|
||||
//boolean prenotazionePagata = false;
|
||||
String idPrenDettaglio = "null";
|
||||
|
||||
|
||||
Object src = e.getSource();
|
||||
if (src instanceof EventParameters evtParams) {
|
||||
flagPrenotazionePagata = evtParams.flagPrenotazionePagata;
|
||||
@ -1827,8 +1999,8 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
//inserisci i prodotti se la cassa è aperta e
|
||||
//non c'è una prenotazione da gestire oppure
|
||||
//c'è una prenotazione e si stanno inserendo i prodotti in lista (idPrenDettaglio viene valorizzato in inserisciPrenotazioni())
|
||||
if (isCassaAperta &&
|
||||
(idPrenotazione == 0 || !idPrenDettaglio.equals("null"))) {
|
||||
if (isCassaAperta
|
||||
&& (idPrenotazione == 0 || !idPrenDettaglio.equals("null"))) {
|
||||
sql = "SELECT "
|
||||
+ "prodotti.id as idProdotto,"
|
||||
+ "prodotti.nome, "
|
||||
@ -1841,8 +2013,6 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
+ "left join tariffe on prodotti.id=tariffe.id_prodotto "
|
||||
+ "where prodotti.id = " + id + " and Tariffe.id_fascia=" + idProfiloTariffario;
|
||||
try {
|
||||
|
||||
|
||||
|
||||
//spengo altri togglebutton
|
||||
for (Integer y = 0; y < this.pnlProdotti.getComponentCount(); y++) {
|
||||
@ -1896,13 +2066,14 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
}
|
||||
tblListaProdotti.setModel(model);
|
||||
|
||||
if(idPrenotazione == 0)
|
||||
if (idPrenotazione == 0) {
|
||||
controllaCompleti(model, "null");
|
||||
else
|
||||
} else {
|
||||
controllaCompleti(model, idPrenotazione.toString());
|
||||
}
|
||||
controllaExtra(model);
|
||||
sommaColonne(model, flagPrenotazionePagata);
|
||||
|
||||
|
||||
//inizio 21-12-18<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
if (jbtnChiudi.isEnabled()) {
|
||||
if (saldoAcquisti(0.0) == false
|
||||
@ -1911,7 +2082,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
&& (bonusResidui <= 0 || flagBonus == 0)
|
||||
&& consentiCredito == false) {
|
||||
JOptionPane.showOptionDialog(this, "Saldo tessera insufficiente!", "Attenzione",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, null, null);
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, null, null);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -1928,8 +2099,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
} catch (Exception ex) {
|
||||
System.out.println(ex.getMessage());
|
||||
}
|
||||
}
|
||||
else if(idPrenotazione > 0 && idPrenDettaglio.equals("null")){
|
||||
} else if (idPrenotazione > 0 && idPrenDettaglio.equals("null")) {
|
||||
JOptionPane.showMessageDialog(this, "Non è possibile modificare prodotti e composizioni se è presente una prenotazione collegata alla tessera");
|
||||
}
|
||||
}
|
||||
@ -1995,10 +2165,10 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
|
||||
/**
|
||||
* funzione che calcola i prezzi dei prodotti e il totale in base alla
|
||||
* fascia dello studente oppure utilizza la fascia di default.
|
||||
* Se flagPrenotazionePagata = true vuol dire che non va modificato il saldo
|
||||
* residuo della tessera perchè la somma delle colonne viene richiamata
|
||||
* a seguito della verifica di una prenotazione pagata
|
||||
* fascia dello studente oppure utilizza la fascia di default. Se
|
||||
* flagPrenotazionePagata = true vuol dire che non va modificato il saldo
|
||||
* residuo della tessera perchè la somma delle colonne viene richiamata a
|
||||
* seguito della verifica di una prenotazione pagata
|
||||
*
|
||||
* @param model
|
||||
* @param flagPrenotazionePagata
|
||||
@ -2011,8 +2181,9 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
}
|
||||
|
||||
DecimalFormat df2 = new DecimalFormat("#,###,###,##0.00");
|
||||
if(!flagPrenotazionePagata)
|
||||
if (!flagPrenotazionePagata) {
|
||||
txtTotaleCassa.setText("€ " + df2.format(t));
|
||||
}
|
||||
|
||||
int p = model.sommaInt(2);
|
||||
txtTotalePunti.setText("Punti " + p);
|
||||
@ -2413,7 +2584,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
// ** Quando viene chiusa la form esce dall'applicazione
|
||||
// ==========================================================================
|
||||
private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
|
||||
|
||||
|
||||
Object selectedValue = JOptionPane.showOptionDialog(this, "Confermi chiusura programma?", "Attenzione",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, siNoOptions, siNoOptions[1]);
|
||||
|
||||
@ -2704,7 +2875,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
this);
|
||||
progressivoDifferito = Double.valueOf(progDI);
|
||||
aggiornaLabelInfo();
|
||||
|
||||
|
||||
if (cercaTestoModoPagamento().equalsIgnoreCase("A scalare") && jTxtTessera.getText().length() > 0) {
|
||||
verificaSaldo(jTxtTessera.getText());
|
||||
|
||||
@ -2834,10 +3005,9 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
}
|
||||
}
|
||||
private void jbtnEliminaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jbtnEliminaActionPerformed
|
||||
if(idPrenotazione > 0){
|
||||
if (idPrenotazione > 0) {
|
||||
JOptionPane.showMessageDialog(this, "Non è possibile modificare prodotti e composizioni se è presente una prenotazione collegata alla tessera");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
cancellaComposizioni();
|
||||
MyTableModel model = (MyTableModel) tblListaProdotti.getModel();
|
||||
Integer riga = tblListaProdotti.getSelectedRow();
|
||||
@ -2875,7 +3045,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
}
|
||||
doLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
}//GEN-LAST:event_jbtnEliminaActionPerformed
|
||||
|
||||
private void jbtnChiudiActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jbtnChiudiActionPerformed
|
||||
@ -2972,7 +3142,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
|
||||
|
||||
private void jbtnEsciActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jbtnEsciActionPerformed
|
||||
|
||||
|
||||
Object selectedValue = JOptionPane.showOptionDialog(this, "Confermi chiusura sessione?", "Attenzione",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, siNoOptions, siNoOptions[0]);
|
||||
if (Integer.parseInt(selectedValue.toString()) == 0) {
|
||||
@ -3065,7 +3235,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
private void aggiornaDB(Boolean messaggio) {
|
||||
try {
|
||||
Boolean aggiorna = false;
|
||||
if (messaggio) {
|
||||
if (messaggio) {
|
||||
Object selectedValue = JOptionPane.showOptionDialog(this, "Confermi aggiornamento del database locale?", "Attenzione",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, siNoOptions, siNoOptions[0]);
|
||||
if (Integer.parseInt(selectedValue.toString()) != 0) {
|
||||
@ -3164,8 +3334,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
}//GEN-LAST:event_btnImpostaClienteActionPerformed
|
||||
|
||||
private void jbtnAnnullaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jbtnAnnullaActionPerformed
|
||||
if(idPrenotazione > 0)
|
||||
{
|
||||
if (idPrenotazione > 0) {
|
||||
Object selectedValue = JOptionPane.showOptionDialog(this, "Desideri bypassare la prenotazione?", "Attenzione",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, siNoOptions, siNoOptions[0]);
|
||||
if (Integer.parseInt(selectedValue.toString()) == 0) {
|
||||
@ -3175,11 +3344,9 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
flagPrenotazionePagata = false;
|
||||
}
|
||||
//JOptionPane.showMessageDialog(this, "Non è possibile modificare prodotti e composizioni se è presente una prenotazione collegata alla tessera");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
MyTableModel model = (MyTableModel) tblListaProdotti.getModel();
|
||||
if (model.getRowCount() > 0) {
|
||||
if (model.getRowCount() > 0) {
|
||||
Object selectedValue = JOptionPane.showOptionDialog(this, "Desideri annullare tutte le righe?", "Attenzione",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, siNoOptions, siNoOptions[0]);
|
||||
if (Integer.parseInt(selectedValue.toString()) == 0) {
|
||||
@ -3193,7 +3360,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
try {
|
||||
MyTableModel model = (MyTableModel) tblListaProdotti.getModel();
|
||||
MyTableModel model1 = (MyTableModel) tblListaComposizioni.getModel();
|
||||
|
||||
|
||||
model.clearTable();
|
||||
model1.clearTable();
|
||||
jbtnSu.setEnabled(false);
|
||||
@ -3484,7 +3651,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
//l'aggiornamento del residuo va fatto solo se non c'è una prenotazione in corso
|
||||
//oppure se la prenotazione in corso non risulta pagata, altrimenti il residuo
|
||||
//resta pari al saldo della tessera
|
||||
if(idPrenotazione == 0 || !flagPrenotazionePagata){
|
||||
if (idPrenotazione == 0 || !flagPrenotazionePagata) {
|
||||
MyTableModel model = (MyTableModel) tblListaProdotti.getModel();
|
||||
Double t = model.somma(colImporto);
|
||||
MyTableModel model2 = (MyTableModel) tblListaComposizioni.getModel();
|
||||
@ -3493,11 +3660,10 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
}
|
||||
//---------------------------
|
||||
lblResiduo.setText("€ " + df2.format(saldo - t));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
lblResiduo.setText("€ " + df2.format(saldo));
|
||||
}
|
||||
|
||||
|
||||
lblPunti.setText(punti);
|
||||
String tipo = cercaTestoModoPagamento();
|
||||
lblTipoPagamento.setText(tipo);
|
||||
@ -3623,7 +3789,6 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void chiudi() {
|
||||
|
||||
//04-02-2019---------------------------------------------
|
||||
@ -3664,8 +3829,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
//mostra messaggio ma non cancella i piatti
|
||||
JOptionPane.showMessageDialog(this, "Saldo insufficiente!", "Saldo", JOptionPane.OK_OPTION);
|
||||
return;
|
||||
@ -3794,8 +3958,8 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
+ "id_Turno,flag_gratuita,flag_bonus,flag_asporto,flag_passaggio_tessera, id_pren_dettaglio)"
|
||||
+ "values(-1," + tessera + "," + model2.getValueAt(i, 2) + "," + idPuntoCassa + ","
|
||||
+ //formattaDataOra(adesso) + "," + model2.getValueAt(i, 1) + ",0," + progressivo + "," +
|
||||
formatLocalDateTime(adesso) + ","
|
||||
+ model2.getValueAt(i, 1)
|
||||
formatLocalDateTime(adesso) + ","
|
||||
+ model2.getValueAt(i, 1)
|
||||
+ ",0," + progressivo + ","
|
||||
+ idModoPagamento + "," + idTurno + "," + flagGratuita + "," + flagBonus + ","
|
||||
+ flagAsporto + "," + flagPassaggioTessera + "," + model2.getValueAt(i, colIdPrenotazione) + ")",
|
||||
@ -3805,7 +3969,8 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
spiaProgressivo = true;
|
||||
}
|
||||
|
||||
} /*else {
|
||||
}
|
||||
/*else {
|
||||
StringBuilder elencoIdProdotti = new StringBuilder();
|
||||
for (int i = model.getRowCount() - 1; i >= 0; i--) {
|
||||
Long idCateg = Long.valueOf(model.getValueAt(i, colCategoria).toString());
|
||||
@ -3906,11 +4071,12 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifica se i prodotti selezionati differiscono da quelli presenti
|
||||
* nella prenotazione collegata alla tessera. L'utente può scegliere di
|
||||
* modificare i prodotti, oppure di azzerare la lista
|
||||
* Verifica se i prodotti selezionati differiscono da quelli presenti nella
|
||||
* prenotazione collegata alla tessera. L'utente può scegliere di modificare
|
||||
* i prodotti, oppure di azzerare la lista
|
||||
*
|
||||
* @param elencoIdProdotto
|
||||
* @return
|
||||
* @return
|
||||
*/
|
||||
private boolean controllaDiscrepanzePrenotazioni(String elencoIdProdotto) {
|
||||
boolean ok = true;
|
||||
@ -3938,7 +4104,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Object selectedValue = JOptionPane.showOptionDialog(this,
|
||||
"I prodotti selezionati sono diversi dai prenotati!\nVuoi proseguire?", "Prenotazione",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, siNoOptions, null);
|
||||
@ -3946,7 +4112,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
azzeraDopoStorno();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
@ -4229,7 +4395,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
}
|
||||
|
||||
lblScadTessera.setText("" + bonusResidui);
|
||||
|
||||
|
||||
if (flagPrecaricaLista) {
|
||||
forzaPrezzi(model);
|
||||
}
|
||||
@ -4264,8 +4430,6 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
jBtnAsportoActionPerformed(null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (abilitatoPassaggi != 0L) {
|
||||
controllaPrenotazioni();
|
||||
}
|
||||
@ -4301,7 +4465,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
String queryPassaggi = "select count(*) as NRec from st_acquisti a inner join prodotti p on a.id_prodotto=p.id inner join Tipi_Pagamenti tp on a.id_tipo_pagamento=tp.id where TRUNC(data) = TRUNC(SYSDATE) and id_tessera=" + idTessera + " and flag_in_vassoio=0 and id_punto_cassa=" + idPuntoCassa;
|
||||
Long numeroPassaggi = Utils.mySelectInteger(queryPassaggi, "NRec", this);
|
||||
//fine----
|
||||
if (flagEsegueStorni && numeroPassaggi > 0) {
|
||||
if (flagEsegueStorni && numeroPassaggi > 0) {
|
||||
Object selectedValue = JOptionPane.showOptionDialog(this, "N° passaggi giornalieri esauriti. Non è possibile usufruire del pasto!\nSi desidera effettuare uno storno per un pasto erroneamente addebitato?", "Attenzione",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, siNoOptions, siNoOptions[1]);
|
||||
if (Integer.parseInt(selectedValue.toString()) == 0) {
|
||||
@ -4323,7 +4487,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
// controllo abilitazione tessera
|
||||
String controlloPunto = "Select controlla_abilitazione('" + numeroTessera + "'," + idPuntoCassa + ") as T from dual";
|
||||
Long abilitato = Utils.mySelectInteger(controlloPunto, "T", this);
|
||||
if (abilitato == 0) {
|
||||
if (abilitato == 0) {
|
||||
Object selectedValue = JOptionPane.showOptionDialog(this, "Tessera non abilitata per questo punto di distribuzione!\nConsenti passaggio?", "Attenzione",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, siNoOptions, siNoOptions[0]);
|
||||
if (Integer.parseInt(selectedValue.toString()) != 0) {
|
||||
@ -4348,7 +4512,7 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
+ "order by id_prenotazione) "
|
||||
+ "where rownum = 1";
|
||||
String idP = Utils.mySelect(query, "nr", this);
|
||||
if (idP.length() > 0) {
|
||||
if (idP.length() > 0) {
|
||||
idPrenotazione = Long.valueOf(idP);
|
||||
if (idPrenotazione > 0L) {
|
||||
query = "SELECT Distinct Nome FROM VIEW_PRENOTAZIONI_TURNO v join prodotti p on v.ID_PRODOTTO=p.ID "
|
||||
@ -4407,14 +4571,14 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
while (rs.next()) {
|
||||
//l'ID nella VIEW_PRENOTAZIONI_TURNO corrisponde all'ID della tabella SIR.PRENOTAZIONI_PASTI_DETTAGLIO
|
||||
//idPrenDettaglio = Long.valueOf(rs.getString("ID"));
|
||||
|
||||
boolean flagPagato = Double.parseDouble(rs.getString("IMPORTO_PAGATO")) > 0.0;
|
||||
EventParameters evtParams = new EventParameters(rs.getString("ID_PRODOTTO"),
|
||||
null,
|
||||
flagPagato,
|
||||
rs.getString("ID"));
|
||||
|
||||
java.awt.event.ActionEvent evt;
|
||||
|
||||
boolean flagPagato = Double.parseDouble(rs.getString("IMPORTO_PAGATO")) > 0.0;
|
||||
EventParameters evtParams = new EventParameters(rs.getString("ID_PRODOTTO"),
|
||||
null,
|
||||
flagPagato,
|
||||
rs.getString("ID"));
|
||||
|
||||
java.awt.event.ActionEvent evt;
|
||||
evt = new java.awt.event.ActionEvent(evtParams, 0, "PRODOTTO[" + rs.getString("ID_PRODOTTO") + "]");
|
||||
actionPerformed(evt);
|
||||
|
||||
@ -4457,8 +4621,10 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcolo dei prezzi dei prodotti sulla base del profilo tariffario corrente
|
||||
* @param model
|
||||
* Calcolo dei prezzi dei prodotti sulla base del profilo tariffario
|
||||
* corrente
|
||||
*
|
||||
* @param model
|
||||
*/
|
||||
private void forzaPrezzi(MyTableModel model) {
|
||||
for (int y = 0; y < model.getRowCount(); y++) {
|
||||
@ -4840,13 +5006,14 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Metodo che stampa un messaggio sul POS
|
||||
* Se il POS è chiuso, stampa a prescindere, altrimenti stampa solo se non è stata letta una tessera
|
||||
* @param flagAperto
|
||||
* Metodo che stampa un messaggio sul POS Se il POS è chiuso, stampa a
|
||||
* prescindere, altrimenti stampa solo se non è stata letta una tessera
|
||||
*
|
||||
* @param flagAperto
|
||||
*/
|
||||
private void stampaSuPos(boolean flagAperto){
|
||||
private void stampaSuPos(boolean flagAperto) {
|
||||
String idPuntoCassaString = idPuntoCassa.toString();
|
||||
if (idPuntoCassaString.length() >= 5) {
|
||||
idPuntoCassaString = idPuntoCassaString.substring(idPuntoCassaString.length() - 5, idPuntoCassaString.length());
|
||||
@ -4854,11 +5021,10 @@ public class PuntoCassa extends JFrame implements ActionListener {
|
||||
idPuntoCassaString = Utils.spaziBianchi(idPuntoCassaString, 5, false);
|
||||
}
|
||||
|
||||
if(flagAperto && jTxtTessera.getText().trim().length() <= 0){
|
||||
if (flagAperto && jTxtTessera.getText().trim().length() <= 0) {
|
||||
String riga = Utils.spaziBianchi(messageDisplay, 20, true) + "POS " + idPuntoCassaString + " APERTO";
|
||||
display(riga, null);
|
||||
}
|
||||
else if (!flagAperto){
|
||||
} else if (!flagAperto) {
|
||||
String riga = Utils.spaziBianchi(messageDisplay, 20, true) + "POS " + idPuntoCassaString + " CHIUSO";
|
||||
display(riga, null);
|
||||
}
|
||||
|
51
src/puntocassa/utils/QRScanner.java
Normal file
51
src/puntocassa/utils/QRScanner.java
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
|
||||
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
|
||||
*/
|
||||
package puntocassa.utils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author assis
|
||||
*/
|
||||
import com.github.sarxos.webcam.Webcam;
|
||||
import com.google.zxing.*;
|
||||
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class QRScanner {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Webcam webcam = Webcam.getDefault();
|
||||
webcam.setViewSize(new Dimension(1280, 720));
|
||||
webcam.open();
|
||||
|
||||
while (true) {
|
||||
BufferedImage image = webcam.getImage();
|
||||
if (image == null) continue;
|
||||
|
||||
LuminanceSource source = new BufferedImageLuminanceSource(image);
|
||||
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||
|
||||
try {
|
||||
List<String> dataResult = new ArrayList<>();
|
||||
Result result = new MultiFormatReader().decode(bitmap);
|
||||
System.out.println("QR Code trovato: " + result.getText());
|
||||
//decripting
|
||||
dataResult = QrCryptoService.decryptAndValidate(result.getText());
|
||||
System.out.println("QR code decriptato: " + dataResult);
|
||||
break;
|
||||
} catch (NotFoundException e) {
|
||||
// Nessun QR code trovato nel frame
|
||||
}
|
||||
}
|
||||
|
||||
webcam.close();
|
||||
}
|
||||
}
|
||||
|
@ -9,97 +9,171 @@ package puntocassa.utils;
|
||||
* @author assis
|
||||
*/
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.SecureRandom;
|
||||
import java.time.Duration;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Base64;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.*;
|
||||
import java.time.*;
|
||||
import java.util.*;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class QrCryptoService {
|
||||
|
||||
// Chiave AES 256-bit (32 byte) - hardcoded per test
|
||||
private static final byte[] AES_KEY = "0123456789ABCDEF0123456789ABCDEF".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
// Crea il JSON cifrato da inserire nel QR
|
||||
public static String createEncryptedQr(String uid, OffsetDateTime issuedAt, OffsetDateTime expiresAt) throws Exception {
|
||||
// Crea il payload JSON con i dati utente
|
||||
String payloadJson = new JSONObject()
|
||||
private static final byte[] AES_KEY = hexToBytes("3031323334353637383961626364656630313233343536373839616263646566");
|
||||
private static final Duration CLOCK_SKEW = Duration.ofSeconds(60);
|
||||
|
||||
public static String createEncryptedQr(String uid, OffsetDateTime issuedAt, OffsetDateTime expiresAt) throws GeneralSecurityException, JSONException {
|
||||
JSONObject payload = new JSONObject()
|
||||
.put("uid", uid)
|
||||
.put("issued_at", issuedAt.toString())
|
||||
.put("expires_at", expiresAt.toString())
|
||||
.toString();
|
||||
.put("expires_at", expiresAt.toString());
|
||||
|
||||
// Genera un Initialization Vector (IV) da 96 bit
|
||||
byte[] iv = new byte[12];
|
||||
new SecureRandom().nextBytes(iv);
|
||||
byte[] iv = SecureRandom.getInstanceStrong().generateSeed(16);
|
||||
|
||||
// Cifra il payload con AES-GCM
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
SecretKeySpec keySpec = new SecretKeySpec(AES_KEY, "AES");
|
||||
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmSpec);
|
||||
byte[] encrypted = cipher.doFinal(payloadJson.getBytes(StandardCharsets.UTF_8));
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(AES_KEY, "AES"), new IvParameterSpec(iv));
|
||||
byte[] encrypted = cipher.doFinal(payload.toString().getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
// Codifica IV e dati cifrati in Base64
|
||||
String ivBase64 = Base64.getEncoder().encodeToString(iv);
|
||||
String encryptedBase64 = Base64.getEncoder().encodeToString(encrypted);
|
||||
// Concatenazione IV + encrypted
|
||||
ByteBuffer buffer = ByteBuffer.allocate(iv.length + encrypted.length);
|
||||
buffer.put(iv);
|
||||
buffer.put(encrypted);
|
||||
byte[] combined = buffer.array();
|
||||
|
||||
// Costruisce il JSON finale con iv e data
|
||||
JSONObject qrJson = new JSONObject()
|
||||
.put("iv", ivBase64)
|
||||
.put("data", encryptedBase64);
|
||||
// Codifica tutto in Base64
|
||||
return Base64.getEncoder().encodeToString(combined);
|
||||
}
|
||||
|
||||
|
||||
public static List<String> decryptAndValidate(String base64Qr) {
|
||||
List<String> resultData = new ArrayList<>();
|
||||
try {
|
||||
// Step 1: Decodifica base64 del QR
|
||||
byte[] decoded = Base64.getDecoder().decode(base64Qr);
|
||||
String jsonString = new String(decoded, StandardCharsets.UTF_8);
|
||||
|
||||
return qrJson.toString(2); // con indentazione
|
||||
// Step 2: Parsing JSON
|
||||
JSONObject qrObject = new JSONObject(jsonString);
|
||||
String ivBase64 = qrObject.getString("iv");
|
||||
String dataBase64 = qrObject.getString("data");
|
||||
|
||||
// Step 3: Decodifica separata di IV e data
|
||||
byte[] iv = Base64.getDecoder().decode(ivBase64);
|
||||
byte[] ciphertext = Base64.getDecoder().decode(dataBase64);
|
||||
|
||||
// Step 4: Decrittazione AES
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(AES_KEY, "AES"), new IvParameterSpec(iv));
|
||||
byte[] decrypted = cipher.doFinal(ciphertext);
|
||||
|
||||
// Step 5: Parsing del payload decifrato
|
||||
JSONObject payload = new JSONObject(new String(decrypted, StandardCharsets.UTF_8));
|
||||
ValidationResult result = validatePayload(payload);
|
||||
|
||||
if (result.valid()) {
|
||||
resultData.add("VALID");
|
||||
resultData.add(result.uid());
|
||||
} else {
|
||||
resultData.add("NOT VALID");
|
||||
resultData.add("Errore validazione QR code: " + result.reason());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
resultData.add("NOT VALID");
|
||||
resultData.add("Errore di decifratura o struttura non valida. QR letto: " + base64Qr);
|
||||
}
|
||||
|
||||
return resultData;
|
||||
}
|
||||
|
||||
// Decifra il JSON e verifica se è ancora valido
|
||||
public static String decryptAndValidate(String qrJson) throws Exception {
|
||||
JSONObject obj = new JSONObject(qrJson);
|
||||
byte[] iv = Base64.getDecoder().decode(obj.getString("iv"));
|
||||
byte[] encryptedData = Base64.getDecoder().decode(obj.getString("data"));
|
||||
|
||||
// Decrittazione con AES-GCM
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
SecretKeySpec keySpec = new SecretKeySpec(AES_KEY, "AES");
|
||||
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
|
||||
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmSpec);
|
||||
byte[] decryptedBytes = cipher.doFinal(encryptedData);
|
||||
|
||||
// Parsing del payload decifrato
|
||||
JSONObject payload = new JSONObject(new String(decryptedBytes, StandardCharsets.UTF_8));
|
||||
String uid = payload.getString("uid");
|
||||
OffsetDateTime issuedAt = OffsetDateTime.parse(payload.getString("issued_at"));
|
||||
OffsetDateTime expiresAt = OffsetDateTime.parse(payload.getString("expires_at"));
|
||||
boolean isExpired = OffsetDateTime.now(expiresAt.getOffset()).isAfter(expiresAt);
|
||||
private static ValidationResult validatePayload(JSONObject payload) {
|
||||
try {
|
||||
String uid = payload.getString("uid");
|
||||
|
||||
//con timezone esplicito
|
||||
OffsetDateTime issuedAt = OffsetDateTime.parse(payload.getString("issued_at"));
|
||||
OffsetDateTime expiresAt = OffsetDateTime.parse(payload.getString("expires_at"));
|
||||
Instant now = Instant.now();
|
||||
Instant iat = issuedAt.toInstant();
|
||||
Instant exp = expiresAt.toInstant();
|
||||
|
||||
return String.format(
|
||||
"Dati decifrati:\n" +
|
||||
"- UID: %s\n" +
|
||||
"- Emesso: %s\n" +
|
||||
"- Scadenza: %s\n" +
|
||||
"- Stato: %s\n",
|
||||
uid,
|
||||
issuedAt,
|
||||
expiresAt,
|
||||
isExpired ? "SCADUTO" : "VALIDO"
|
||||
);
|
||||
if (!uid.matches("[A-Z0-9]{16}"))
|
||||
return ValidationResult.invalid("Formato UID non valido");
|
||||
if (exp.isBefore(iat))
|
||||
return ValidationResult.invalid("Scadenza antecedente all'emissione");
|
||||
if (now.plus(CLOCK_SKEW).isBefore(iat))
|
||||
return ValidationResult.invalid("QR non ancora valido");
|
||||
if (now.minus(CLOCK_SKEW).isAfter(exp))
|
||||
return ValidationResult.invalid("QR scaduto");
|
||||
|
||||
//senza timezone esplicito
|
||||
/*LocalDateTime issuedAt = LocalDateTime.parse(payload.getString("issued_at"));
|
||||
LocalDateTime expiresAt = LocalDateTime.parse(payload.getString("expires_at"));
|
||||
|
||||
ZoneId zone = ZoneId.systemDefault(); // oppure un valore fisso come ZoneId.of("Europe/Rome")
|
||||
|
||||
Instant now = Instant.now();
|
||||
Instant iat = issuedAt.atZone(zone).toInstant();
|
||||
Instant exp = expiresAt.atZone(zone).toInstant();
|
||||
|
||||
if (!uid.matches("[A-Z0-9]{16}"))
|
||||
return ValidationResult.invalid("Formato UID non valido");
|
||||
|
||||
if (exp.isBefore(iat))
|
||||
return ValidationResult.invalid("Scadenza antecedente all'emissione");
|
||||
|
||||
if (now.plus(CLOCK_SKEW).isBefore(iat))
|
||||
return ValidationResult.invalid("QR non ancora valido");
|
||||
|
||||
if (now.minus(CLOCK_SKEW).isAfter(exp))
|
||||
return ValidationResult.invalid("QR scaduto");*/
|
||||
|
||||
|
||||
return ValidationResult.valid(uid, iat, exp);
|
||||
|
||||
} catch (Exception e) {
|
||||
return ValidationResult.invalid("Errore di validazione QR Code: Payload malformato o incompleto");
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] hexToBytes(String hex) {
|
||||
return new BigInteger(hex, 16).toByteArray().length == 33
|
||||
? Arrays.copyOfRange(new BigInteger(hex, 16).toByteArray(), 1, 33)
|
||||
: new BigInteger(hex, 16).toByteArray();
|
||||
}
|
||||
|
||||
public record ValidationResult(boolean valid, String reason, String uid, Instant issuedAt, Instant expiresAt) {
|
||||
public static ValidationResult valid(String uid, Instant issuedAt, Instant expiresAt) {
|
||||
return new ValidationResult(true, null, uid, issuedAt, expiresAt);
|
||||
}
|
||||
|
||||
public static ValidationResult invalid(String reason) {
|
||||
return new ValidationResult(false, reason, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
// Test completo della generazione e verifica
|
||||
public static void main(String[] args) throws Exception {
|
||||
//data valida
|
||||
OffsetDateTime issuedAt = OffsetDateTime.now().withNano(0);
|
||||
//data scaduta
|
||||
//OffsetDateTime issuedAt = OffsetDateTime.now().minusMinutes(5).withNano(0);
|
||||
OffsetDateTime expiresAt = issuedAt.plusSeconds(60);
|
||||
String qrJson = createEncryptedQr("TSTTST91A48A271O", issuedAt, expiresAt);
|
||||
List<String> dataResult = new ArrayList<>();
|
||||
OffsetDateTime now = OffsetDateTime.now().withNano(0);
|
||||
OffsetDateTime expiration = now.plusSeconds(CLOCK_SKEW.getSeconds());
|
||||
|
||||
System.out.println("QR JSON simulato:");
|
||||
System.out.println(qrJson);
|
||||
//String qr = createEncryptedQr("TSTTST91A48A271O", now, expiration);
|
||||
String qr = "eyJpdiI6Ik0xTVJvR3dMbm40UGFMalFEVUh5M1E9PSIsImRhdGEiOiJSVERTTkFURi8wK0lrekFGVVRaSkMrb1Y5QWVZcFRnMFFVKzgzY25QUVgrM2ZMVkRMV3kyOFRsMnBIQTlBRWVGTFQvK0pxSWNtblBYRnBjMys5T0tVWHJpc3FQc1VHazUxRzFpSERSOFJ1eEFCSWhPaTZlamlkdHU4d090WmRzY2F2Y0FRbmNESTd3bGxJNWgvOFFmZnc9PSJ9";
|
||||
System.out.println("QR generato:\n" + qr + "\n");
|
||||
|
||||
System.out.println("\nVerifica decifratura:");
|
||||
System.out.println(decryptAndValidate(qrJson));
|
||||
dataResult = decryptAndValidate(qr);
|
||||
System.out.println("Verifica:\n" + dataResult);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user