From d095908e42212e1f1767a2e8967fd4cf9447eb9b Mon Sep 17 00:00:00 2001 From: Hugh Date: Mon, 15 Jun 2026 16:48:30 +0100 Subject: [PATCH] Squash merge 5.5.0-development into main --- .gitignore | 1 + pom.xml | 17 +- .../pos/config/JPanelConfigPayment.java | 43 ++- .../unicenta/pos/payment/JPaymentVoucher.form | 54 ++-- .../unicenta/pos/payment/JPaymentVoucher.java | 274 ++++++++---------- .../pos/payment/PaymentGatewayFac.java | 2 + .../payment/PaymentGatewayMediaPayments.java | 97 +++++++ .../com/unicenta/pos/voucher/VoucherInfo.java | 220 +++++++------- test.jpg | Bin 0 -> 12606 bytes 9 files changed, 405 insertions(+), 303 deletions(-) create mode 100644 src/main/java/com/unicenta/pos/payment/PaymentGatewayMediaPayments.java create mode 100644 test.jpg diff --git a/.gitignore b/.gitignore index a33ed9d..71b25b6 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ docker.sock .factorypath .settings/ .project +AGENTS.md diff --git a/pom.xml b/pom.xml index 18698e6..a152445 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,6 @@ 4.0.0 - com.unicenta unicentaopos 5.4.0 @@ -116,7 +115,6 @@ poi 3.17 - org.apache.poi poi-ooxml @@ -181,7 +179,6 @@ slf4j-api - org.swinglabs.swingx @@ -255,11 +252,11 @@ derbytools ${derby.version} - - - - - + + + + + xml-apis xml-apis @@ -293,7 +290,6 @@ DynamicJasper-core-fonts 2.0 - org.eclipse.jdt.core.compiler ecj @@ -361,7 +357,7 @@ com.unicenta unicenta-plugins - 1.3.1 + 1.3.2-SNAPSHOT com.gluonhq @@ -450,7 +446,6 @@ 4.2.0 test - diff --git a/src/main/java/com/unicenta/pos/config/JPanelConfigPayment.java b/src/main/java/com/unicenta/pos/config/JPanelConfigPayment.java index dfd6084..ea12ec6 100644 --- a/src/main/java/com/unicenta/pos/config/JPanelConfigPayment.java +++ b/src/main/java/com/unicenta/pos/config/JPanelConfigPayment.java @@ -53,6 +53,7 @@ public class JPanelConfigPayment extends javax.swing.JPanel implements PanelConf initPayments("external", new ConfigPaymentPanelEmpty()); initPayments("PaymentSense", new ConfigPaymentPanelEmpty()); initPayments("Teya", new ConfigPaymentPanelEmpty()); + initPayments("MediaPayments", new ConfigPaymentPanelEmpty()); // Lector de tarjetas. jcboCardReader.addItem("Not defined"); @@ -91,9 +92,17 @@ public class JPanelConfigPayment extends javax.swing.JPanel implements PanelConf jcboCardReader.setSelectedItem(config.getProperty("payment.magcardreader")); jcboPaymentGateway.setSelectedItem(config.getProperty("payment.gateway")); - urlValue.setText(config.getProperty("payment.URL")); - deviceIdValue.setText(config.getProperty("payment.device-id")); - securityKeyValue.setText(config.getProperty("payment.security-key")); + + String gateway = comboValue(jcboPaymentGateway.getSelectedItem()); + if ("MediaPayments".equals(gateway)) { + urlValue.setText(config.getProperty("media-payments.pdq")); + deviceIdValue.setText(config.getProperty("media-payments.api-key")); + securityKeyValue.setText(config.getProperty("media-payments.secret")); + } else { + urlValue.setText(config.getProperty("payment.URL")); + deviceIdValue.setText(config.getProperty("payment.device-id")); + securityKeyValue.setText(config.getProperty("payment.security-key")); + } paymentConfiguration.loadProperties(config); dirty.setDirty(false); } @@ -107,9 +116,17 @@ public class JPanelConfigPayment extends javax.swing.JPanel implements PanelConf config.setProperty("payment.magcardreader", comboValue(jcboCardReader.getSelectedItem())); config.setProperty("payment.gateway", comboValue(jcboPaymentGateway.getSelectedItem())); - config.setProperty("payment.URL", urlValue.getText()); - config.setProperty("payment.device-id", deviceIdValue.getText()); - config.setProperty("payment.security-key", securityKeyValue.getText()); + + String gateway = comboValue(jcboPaymentGateway.getSelectedItem()); + if ("MediaPayments".equals(gateway)) { + config.setProperty("media-payments.pdq", urlValue.getText()); + config.setProperty("media-payments.api-key", deviceIdValue.getText()); + config.setProperty("media-payments.secret", securityKeyValue.getText()); + } else { + config.setProperty("payment.URL", urlValue.getText()); + config.setProperty("payment.device-id", deviceIdValue.getText()); + config.setProperty("payment.security-key", securityKeyValue.getText()); + } paymentConfiguration.saveProperties(config); dirty.setDirty(false); } @@ -275,6 +292,9 @@ public class JPanelConfigPayment extends javax.swing.JPanel implements PanelConf paymentConfiguration = paymentsName.get(comboValue(jcboPaymentGateway.getSelectedItem())); if (comboValue(jcboPaymentGateway.getSelectedItem()).equals("PaymentSense")) { + urlLabel.setText("URL"); + deviceIdLabel.setText("Device ID"); + securityKeyLabel.setText("Security Key"); emvConfigPanel.setVisible(Boolean.TRUE); jcboCardReader.setSelectedItem("EMV"); jcboCardReader.setEnabled(Boolean.FALSE); @@ -285,7 +305,18 @@ public class JPanelConfigPayment extends javax.swing.JPanel implements PanelConf jcboCardReader.setSelectedItem("EMV"); jcboCardReader.setEnabled(Boolean.FALSE); } + else if (comboValue(jcboPaymentGateway.getSelectedItem()).equals("MediaPayments")) { + urlLabel.setText("Terminal ID"); + deviceIdLabel.setText("API Key"); + securityKeyLabel.setText("Security Key"); + emvConfigPanel.setVisible(Boolean.TRUE); + jcboCardReader.setSelectedItem("EMV"); + jcboCardReader.setEnabled(Boolean.FALSE); + } else { + urlLabel.setText("URL"); + deviceIdLabel.setText("Device ID"); + securityKeyLabel.setText("Security Key"); emvConfigPanel.setVisible(Boolean.FALSE); jcboCardReader.setEnabled(Boolean.TRUE); } diff --git a/src/main/java/com/unicenta/pos/payment/JPaymentVoucher.form b/src/main/java/com/unicenta/pos/payment/JPaymentVoucher.form index 5188710..6b4807a 100644 --- a/src/main/java/com/unicenta/pos/payment/JPaymentVoucher.form +++ b/src/main/java/com/unicenta/pos/payment/JPaymentVoucher.form @@ -40,10 +40,6 @@ - - - - @@ -87,9 +83,7 @@ - - - + @@ -166,43 +160,43 @@ - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - @@ -224,14 +218,6 @@ - - - - - - - - diff --git a/src/main/java/com/unicenta/pos/payment/JPaymentVoucher.java b/src/main/java/com/unicenta/pos/payment/JPaymentVoucher.java index ff1895e..4b03ae0 100644 --- a/src/main/java/com/unicenta/pos/payment/JPaymentVoucher.java +++ b/src/main/java/com/unicenta/pos/payment/JPaymentVoucher.java @@ -183,154 +183,141 @@ public class JPaymentVoucher extends javax.swing.JPanel implements JPaymentInter * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ - // //GEN-BEGIN:initComponents - private void initComponents() { + // //GEN-BEGIN:initComponents + private void initComponents() { - jPanel4 = new javax.swing.JPanel(); - jLabel5 = new javax.swing.JLabel(); - m_jVoucher = new javax.swing.JComboBox(); - jLabel1 = new javax.swing.JLabel(); - m_jMoneyEuros = new javax.swing.JLabel(); - webLblCustomer = new com.alee.laf.label.WebLabel(); - webLblcustomerName = new com.alee.laf.label.WebLabel(); - voucherStatus = new com.alee.laf.label.WebLabel(); - jLabel6 = new javax.swing.JLabel(); - jButton1 = new javax.swing.JButton(); - jPanel11 = new javax.swing.JPanel(); - jPanel12 = new javax.swing.JPanel(); - m_jKeys = new com.unicenta.editor.JEditorKeys(); - jPanel1 = new javax.swing.JPanel(); - m_jTendered = new com.unicenta.editor.JEditorCurrencyPositive(); + jPanel4 = new javax.swing.JPanel(); + jLabel5 = new javax.swing.JLabel(); + m_jVoucher = new javax.swing.JComboBox(); + jLabel1 = new javax.swing.JLabel(); + m_jMoneyEuros = new javax.swing.JLabel(); + webLblCustomer = new javax.swing.JLabel(); + webLblcustomerName = new javax.swing.JLabel(); + voucherStatus = new javax.swing.JLabel(); + jLabel6 = new javax.swing.JLabel(); + jPanel11 = new javax.swing.JPanel(); + jPanel12 = new javax.swing.JPanel(); + m_jKeys = new com.unicenta.editor.JEditorKeys(); + jPanel1 = new javax.swing.JPanel(); + m_jTendered = new com.unicenta.editor.JEditorCurrencyPositive(); - setLayout(new java.awt.BorderLayout()); + setLayout(new java.awt.BorderLayout()); - jLabel5.setFont(new java.awt.Font("Arial", 1, 18)); // NOI18N - jLabel5.setLabelFor(m_jVoucher); - jLabel5.setText(AppLocal.getIntString("label.voucher")); // NOI18N - jLabel5.setPreferredSize(new java.awt.Dimension(100, 30)); + jLabel5.setFont(new java.awt.Font("Arial", 1, 18)); // NOI18N + jLabel5.setLabelFor(m_jVoucher); + jLabel5.setText(AppLocal.getIntString("label.voucher")); // NOI18N + jLabel5.setPreferredSize(new java.awt.Dimension(100, 30)); - m_jVoucher.setFont(new java.awt.Font("Arial", 0, 14)); // NOI18N - m_jVoucher.setPreferredSize(new java.awt.Dimension(180, 30)); - m_jVoucher.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - m_jVoucherActionPerformed(evt); - } - }); + m_jVoucher.setFont(new java.awt.Font("Arial", 0, 14)); // NOI18N + m_jVoucher.setPreferredSize(new java.awt.Dimension(180, 30)); + m_jVoucher.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + m_jVoucherActionPerformed(evt); + } + }); - jLabel1.setFont(new java.awt.Font("Arial", 1, 18)); // NOI18N - jLabel1.setText(AppLocal.getIntString("label.voucherValue")); // NOI18N - jLabel1.setPreferredSize(new java.awt.Dimension(100, 30)); + jLabel1.setFont(new java.awt.Font("Arial", 1, 18)); // NOI18N + jLabel1.setText(AppLocal.getIntString("label.voucherValue")); // NOI18N + jLabel1.setPreferredSize(new java.awt.Dimension(100, 30)); - m_jMoneyEuros.setBackground(new java.awt.Color(204, 255, 51)); - m_jMoneyEuros.setFont(new java.awt.Font("Arial", 1, 18)); // NOI18N - m_jMoneyEuros.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); - m_jMoneyEuros.setBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createLineBorder(javax.swing.UIManager.getDefaults().getColor("Button.darkShadow")), javax.swing.BorderFactory.createEmptyBorder(1, 4, 1, 4))); - m_jMoneyEuros.setOpaque(true); - m_jMoneyEuros.setPreferredSize(new java.awt.Dimension(180, 30)); + m_jMoneyEuros.setBackground(new java.awt.Color(204, 255, 51)); + m_jMoneyEuros.setFont(new java.awt.Font("Arial", 1, 18)); // NOI18N + m_jMoneyEuros.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); + m_jMoneyEuros.setBorder(javax.swing.BorderFactory.createCompoundBorder(javax.swing.BorderFactory.createLineBorder(javax.swing.UIManager.getDefaults().getColor("Button.darkShadow")), javax.swing.BorderFactory.createEmptyBorder(1, 4, 1, 4))); + m_jMoneyEuros.setOpaque(true); + m_jMoneyEuros.setPreferredSize(new java.awt.Dimension(180, 30)); - webLblCustomer.setText(AppLocal.getIntString("label.customer")); // NOI18N - webLblCustomer.setToolTipText(""); - webLblCustomer.setFont(new java.awt.Font("Arial", 1, 18)); // NOI18N - webLblCustomer.setPreferredSize(new java.awt.Dimension(100, 30)); + webLblCustomer.setText(AppLocal.getIntString("label.customer")); // NOI18N + webLblCustomer.setToolTipText(""); + webLblCustomer.setFont(new java.awt.Font("Arial", 1, 18)); // NOI18N + webLblCustomer.setPreferredSize(new java.awt.Dimension(100, 30)); - webLblcustomerName.setText(AppLocal.getIntString("label.customer")); // NOI18N - webLblcustomerName.setToolTipText(""); - webLblcustomerName.setFont(new java.awt.Font("Arial", 0, 14)); // NOI18N - webLblcustomerName.setPreferredSize(new java.awt.Dimension(100, 30)); + webLblcustomerName.setText(AppLocal.getIntString("label.customer")); // NOI18N + webLblcustomerName.setToolTipText(""); + webLblcustomerName.setFont(new java.awt.Font("Arial", 0, 14)); // NOI18N + webLblcustomerName.setPreferredSize(new java.awt.Dimension(100, 30)); - voucherStatus.setText(AppLocal.getIntString("label.voucherStatus")); // NOI18N - voucherStatus.setToolTipText(""); - voucherStatus.setFont(new java.awt.Font("Arial", 0, 14)); // NOI18N - voucherStatus.setPreferredSize(new java.awt.Dimension(100, 30)); + voucherStatus.setText(AppLocal.getIntString("label.voucherStatus")); // NOI18N + voucherStatus.setToolTipText(""); + voucherStatus.setFont(new java.awt.Font("Arial", 0, 14)); // NOI18N + voucherStatus.setPreferredSize(new java.awt.Dimension(100, 30)); - jLabel6.setFont(new java.awt.Font("Arial", 1, 18)); // NOI18N - jLabel6.setLabelFor(m_jVoucher); - jLabel6.setText(AppLocal.getIntString("label.voucherStatus")); // NOI18N - jLabel6.setPreferredSize(new java.awt.Dimension(100, 30)); + jLabel6.setFont(new java.awt.Font("Arial", 1, 18)); // NOI18N + jLabel6.setLabelFor(m_jVoucher); + jLabel6.setText(AppLocal.getIntString("label.voucherStatus")); // NOI18N + jLabel6.setPreferredSize(new java.awt.Dimension(100, 30)); - jButton1.setText("jButton1"); - jButton1.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton1ActionPerformed(evt); - } - }); - - javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); - jPanel4.setLayout(jPanel4Layout); - jPanel4Layout.setHorizontalGroup( + javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); + jPanel4.setLayout(jPanel4Layout); + jPanel4Layout.setHorizontalGroup( jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel4Layout.createSequentialGroup() - .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel4Layout.createSequentialGroup() - .addGap(10, 10, 10) - .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(m_jMoneyEuros, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(jPanel4Layout.createSequentialGroup() - .addContainerGap() - .addComponent(jLabel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(m_jVoucher, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(jPanel4Layout.createSequentialGroup() - .addContainerGap() - .addComponent(jButton1))) - .addGap(0, 0, Short.MAX_VALUE)) + .addGap(10, 10, 10) + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(m_jMoneyEuros, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel4Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel4Layout.createSequentialGroup() - .addComponent(webLblCustomer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(webLblcustomerName, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGroup(jPanel4Layout.createSequentialGroup() - .addComponent(jLabel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(voucherStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) - ); - jPanel4Layout.setVerticalGroup( + .addContainerGap() + .addComponent(jLabel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(m_jVoucher, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(jPanel4Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addComponent(webLblCustomer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(webLblcustomerName, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(jPanel4Layout.createSequentialGroup() + .addComponent(jLabel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(voucherStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) + ); + jPanel4Layout.setVerticalGroup( jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel4Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(m_jVoucher, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(jLabel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(voucherStatus, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(m_jMoneyEuros, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(webLblCustomer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(webLblcustomerName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(33, 33, 33) - .addComponent(jButton1) - .addContainerGap()) - ); + .addGroup(jPanel4Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(m_jVoucher, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jLabel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(voucherStatus, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(m_jMoneyEuros, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(webLblCustomer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(webLblcustomerName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(241, 241, 241)) + ); - add(jPanel4, java.awt.BorderLayout.CENTER); + add(jPanel4, java.awt.BorderLayout.CENTER); - jPanel11.setLayout(new java.awt.BorderLayout()); + jPanel11.setLayout(new java.awt.BorderLayout()); - jPanel12.setLayout(new javax.swing.BoxLayout(jPanel12, javax.swing.BoxLayout.Y_AXIS)); - jPanel12.add(m_jKeys); + jPanel12.setLayout(new javax.swing.BoxLayout(jPanel12, javax.swing.BoxLayout.Y_AXIS)); + jPanel12.add(m_jKeys); - jPanel1.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5)); - jPanel1.setLayout(new java.awt.BorderLayout()); + jPanel1.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5)); + jPanel1.setLayout(new java.awt.BorderLayout()); - m_jTendered.setFont(new java.awt.Font("Arial", 0, 12)); // NOI18N - m_jTendered.setPreferredSize(new java.awt.Dimension(130, 30)); - jPanel1.add(m_jTendered, java.awt.BorderLayout.CENTER); + m_jTendered.setFont(new java.awt.Font("Arial", 0, 12)); // NOI18N + m_jTendered.setPreferredSize(new java.awt.Dimension(130, 30)); + jPanel1.add(m_jTendered, java.awt.BorderLayout.CENTER); - jPanel12.add(jPanel1); + jPanel12.add(jPanel1); - jPanel11.add(jPanel12, java.awt.BorderLayout.NORTH); + jPanel11.add(jPanel12, java.awt.BorderLayout.NORTH); - add(jPanel11, java.awt.BorderLayout.EAST); - }// //GEN-END:initComponents + add(jPanel11, java.awt.BorderLayout.EAST); + }// //GEN-END:initComponents private void m_jVoucherActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_m_jVoucherActionPerformed @@ -365,27 +352,22 @@ public class JPaymentVoucher extends javax.swing.JPanel implements JPaymentInter } }//GEN-LAST:event_m_jVoucherActionPerformed - private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed - }//GEN-LAST:event_jButton1ActionPerformed - - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton jButton1; - private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel5; - private javax.swing.JLabel jLabel6; - private javax.swing.JPanel jPanel1; - private javax.swing.JPanel jPanel11; - private javax.swing.JPanel jPanel12; - private javax.swing.JPanel jPanel4; - private com.unicenta.editor.JEditorKeys m_jKeys; - private javax.swing.JLabel m_jMoneyEuros; - private com.unicenta.editor.JEditorCurrencyPositive m_jTendered; - private javax.swing.JComboBox m_jVoucher; - private com.alee.laf.label.WebLabel voucherStatus; - private com.alee.laf.label.WebLabel webLblCustomer; - private com.alee.laf.label.WebLabel webLblcustomerName; - // End of variables declaration//GEN-END:variables + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel11; + private javax.swing.JPanel jPanel12; + private javax.swing.JPanel jPanel4; + private com.unicenta.editor.JEditorKeys m_jKeys; + private javax.swing.JLabel m_jMoneyEuros; + private com.unicenta.editor.JEditorCurrencyPositive m_jTendered; + private javax.swing.JComboBox m_jVoucher; + private javax.swing.JLabel voucherStatus; + private javax.swing.JLabel webLblCustomer; + private javax.swing.JLabel webLblcustomerName; + // End of variables declaration//GEN-END:variables } diff --git a/src/main/java/com/unicenta/pos/payment/PaymentGatewayFac.java b/src/main/java/com/unicenta/pos/payment/PaymentGatewayFac.java index c0a8f55..2c27bf7 100644 --- a/src/main/java/com/unicenta/pos/payment/PaymentGatewayFac.java +++ b/src/main/java/com/unicenta/pos/payment/PaymentGatewayFac.java @@ -41,6 +41,8 @@ public class PaymentGatewayFac { return new PaymentGatewayPaymentSense(); case "Teya": return new PaymentGatewayTeya(); + case "MediaPayments": + return new PaymentGatewayMediaPayments(); default: return null; } diff --git a/src/main/java/com/unicenta/pos/payment/PaymentGatewayMediaPayments.java b/src/main/java/com/unicenta/pos/payment/PaymentGatewayMediaPayments.java new file mode 100644 index 0000000..80fd497 --- /dev/null +++ b/src/main/java/com/unicenta/pos/payment/PaymentGatewayMediaPayments.java @@ -0,0 +1,97 @@ +// uniCenta oPOS - Touch Friendly Point Of Sale +// Copyright (c) 2009-2018 uniCenta & previous Openbravo POS works +// https://unicenta.com +// +// This file is part of uniCenta oPOS +// +// uniCenta oPOS is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// uniCenta oPOS is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with uniCenta oPOS. If not, see . + +package com.unicenta.pos.payment; + +import com.unicenta.plugins.Application; +import com.unicenta.plugins.common.AppContext; +import com.unicenta.pos.util.RoundUtils; +import lombok.extern.slf4j.Slf4j; + +import java.awt.*; +import java.util.ArrayList; + +@Slf4j +public class PaymentGatewayMediaPayments implements PaymentGateway { + + public PaymentGatewayMediaPayments() { + } + + Window getPaymentWindow(double amount) { + if (amount > 0) { + ArrayList paymentWindows = new ArrayList<>(); + for (Window window : Window.getWindows()) { + if (window instanceof JPaymentSelectReceipt) { + paymentWindows.add((JPaymentSelectReceipt) window); + } + } + return paymentWindows.get(paymentWindows.size() - 1); + } else { + ArrayList paymentWindows = new ArrayList<>(); + for (Window window : Window.getWindows()) { + if (window instanceof JPaymentSelectRefund) { + paymentWindows.add((JPaymentSelectRefund) window); + } + } + return paymentWindows.get(paymentWindows.size() - 1); + } + } + + @Override + public void execute(PaymentInfoMagcard payinfo) { + + int timer = 0; + int timeout = 180; + + double roundedValue = RoundUtils.round(payinfo.getTotal()); + new Application().mediaPaymentsTransaction(roundedValue, getPaymentWindow(roundedValue), + payinfo.getTransactionID().length() > 12 ? payinfo.getTransactionID() : null); + + while (AppContext.getIsProcessing() == null || AppContext.getIsProcessing()) { + try { + log.info("uniCenta-oPos: waiting for payment to complete ...."); + Thread.sleep(1000); + timer += 1; + if (timer > timeout) + break; + } catch (InterruptedException e) { + log.error(e.getMessage()); + } + } + + if (AppContext.getMediaPaymentsPaymentResult() == null) { + payinfo.paymentError("Transaction Error! Please try again", "No Response"); + } else if ("APPROVED".equals(AppContext.getMediaPaymentsPaymentResult().getProcessingDetails().getStatus())) { + payinfo.setCardName(AppContext.getMediaPaymentsPaymentResult().getProcessingDetails().getCard().getType()); + payinfo + .setVerification(AppContext.getMediaPaymentsPaymentResult().getProcessingDetails().getVerificationMethod()); + payinfo.setChipAndPin(true); + payinfo.paymentOK( + AppContext.getMediaPaymentsPaymentResult().getAdditionalInformation().getRequestId(), + AppContext.getMediaPaymentsPaymentResult().getTransactionDetails().getId(), + AppContext.getMediaPaymentsPaymentResult().getProcessingDetails().getStatus()); + } else { + String errorMsg = AppContext.getMediaPaymentsPaymentResult().getErrorMessage(); + if (errorMsg == null) { + errorMsg = AppContext.getMediaPaymentsPaymentResult().getMessage(); + } + payinfo.paymentError("Transaction Error! Please try again", errorMsg); + } + } +} diff --git a/src/main/java/com/unicenta/pos/voucher/VoucherInfo.java b/src/main/java/com/unicenta/pos/voucher/VoucherInfo.java index b5deec0..136e380 100644 --- a/src/main/java/com/unicenta/pos/voucher/VoucherInfo.java +++ b/src/main/java/com/unicenta/pos/voucher/VoucherInfo.java @@ -24,124 +24,132 @@ import com.unicenta.data.loader.DataRead; import com.unicenta.data.loader.IKeyed; import com.unicenta.data.loader.SerializerRead; +import lombok.extern.slf4j.Slf4j; +@Slf4j public class VoucherInfo implements IKeyed { - private String id; - private String voucherNumber; - private String customerName; - private double amount; - private String status; + private String id; + private String voucherNumber; + private String customerName; + private double amount; + private String status; - public VoucherInfo() { - } + public VoucherInfo() { + } - public VoucherInfo( - String id, - String voucherNumber, - String customerName, - double amount, - String status) - { - this.id = id; - this.voucherNumber = voucherNumber; - this.customerName = customerName; - this.amount = amount; - this.status = status; - } - + public VoucherInfo( + String id, + String voucherNumber, + String customerName, + double amount, + String status) { + this.id = id; + this.voucherNumber = voucherNumber; + this.customerName = customerName; + this.amount = amount; + this.status = status; + } - @Override - public Object getKey() { - return getId(); - } + @Override + public Object getKey() { + return getId(); + } - /** - * @return the id - */ - public String getId() { - return id; - } + /** + * @return the id + */ + public String getId() { + return id; + } - /** - * @param id the id to set - */ - public void setId(String id) { - this.id = id; - } + /** + * @param id the id to set + */ + public void setId(String id) { + this.id = id; + } - /** - * @return the voucherNumber - */ - public String getVoucherNumber() { - return voucherNumber; - } + /** + * @return the voucherNumber + */ + public String getVoucherNumber() { + return voucherNumber; + } - /** - * @param voucherNumber the voucherNumber to set - */ - public void setVoucherNumber(String voucherNumber) { - this.voucherNumber = voucherNumber; - } - - /** - * @return the customerName - */ - public String getCustomerName() { - return customerName; - } + /** + * @param voucherNumber the voucherNumber to set + */ + public void setVoucherNumber(String voucherNumber) { + this.voucherNumber = voucherNumber; + } - /** - * @param customerName the customerName to set - */ - public void setCustomerName(String customerName) { - this.customerName = customerName; - } + /** + * @return the customerName + */ + public String getCustomerName() { + return customerName; + } - /** - * @return the amount - */ - public double getAmount() { - return amount; - } + /** + * @param customerName the customerName to set + */ + public void setCustomerName(String customerName) { + this.customerName = customerName; + } - /** - * @param amount the amount to set - */ - public void setAmount(double amount) { - this.amount = amount; - } - - - @Override - public String toString() { - return voucherNumber; - } - - /** - * @return the status - */ - public String getStatus() { - return status; - } + /** + * @return the amount + */ + public double getAmount() { + return amount; + } - /** - * @param status the status to set - */ - public void setStatus(String status) { - this.status = status; - } + /** + * @param amount the amount to set + */ + public void setAmount(double amount) { + this.amount = amount; + } - public static SerializerRead getSerializerRead() { - return new SerializerRead() - { - @Override - public Object readValues(DataRead dr) throws BasicException { - return new VoucherInfo( - dr.getString(1), - dr.getString(2), - dr.getString(3), - dr.getDouble(4), - dr.getString(5)); - }}; - } + @Override + public String toString() { + return voucherNumber; + } + + /** + * @return the status + */ + public String getStatus() { + return status; + } + + /** + * @param status the status to set + */ + public void setStatus(String status) { + this.status = status; + } + + public static SerializerRead getSerializerRead() { + return new SerializerRead() { + @Override + public Object readValues(DataRead dr) throws BasicException { + VoucherInfo voucherInfo = null; + + try { + voucherInfo = new VoucherInfo( + dr.getString(1), + dr.getString(2), + dr.getString(3), + dr.getDouble(4), + dr.getString(5)); + } catch (Exception e) { + log.error("Error reading voucher info: {}", e.getMessage()); + log.error(dr.getString(2)); + } + + return voucherInfo; + } + }; + } } diff --git a/test.jpg b/test.jpg new file mode 100644 index 0000000000000000000000000000000000000000..13f36189b1fbf3bbbd3237672d6022e81934a1e4 GIT binary patch literal 12606 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 literal 0 HcmV?d00001