// uniCenta oPOS - Touch Friendly Point Of Sale // Copyright (C) 2008-2009 Openbravo, S.L. // http://www.unicenta.net/unicentaopos // // 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 <http://www.gnu.org/licenses/>. package com.openbravo.pos.payment; import com.openbravo.pos.forms.AppLocal; import com.openbravo.pos.forms.AppProperties; import com.openbravo.pos.util.AltEncrypter; import java.io.*; import java.net.*; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; /** * * @author Mikel Irurita */ public class PaymentGatewayPGNET implements PaymentGateway { private static String ENDPOINTADDRESS; private static final String SALE = "10"; private static final String REFUND = "13"; private static final String APPROVED = "A"; private String m_sCommerceID; private String m_sCommercePassword; private boolean m_bTestMode; public PaymentGatewayPGNET(AppProperties props) { // Grab some configuration variables m_sCommerceID = props.getProperty("payment.commerceid"); AltEncrypter cypher = new AltEncrypter("cypherkey" + props.getProperty("payment.commerceid")); this.m_sCommercePassword = cypher.decrypt(props.getProperty("payment.commercepassword").substring(6)); m_bTestMode = Boolean.valueOf(props.getProperty("payment.testmode")).booleanValue(); ENDPOINTADDRESS = (m_bTestMode) ? "https://www.paymentsgateway.net/cgi-bin/posttest.pl" : "https://www.paymentsgateway.net/cgi-bin/postauth.pl"; } public PaymentGatewayPGNET(){ } @Override public void execute(PaymentInfoMagcard payinfo) { // JG 16 May 12 use StringBuilder in place of StringBuilder StringBuilder sb = new StringBuilder(); try { sb.append("pg_merchant_id="); sb.append(m_sCommerceID); sb.append("&pg_password="); sb.append(m_sCommercePassword); sb.append("&pg_total_amount="); NumberFormat formatter = new DecimalFormat("0000.00"); String amount = formatter.format(Math.abs(payinfo.getTotal())); sb.append(URLEncoder.encode(amount.replace(',', '.'), "UTF-8")); if (payinfo.getTrack1(true) != null){ sb.append("&pg_cc_swipe_data="); sb.append(URLEncoder.encode(payinfo.getTrack1(true), "UTF-8")); } else { sb.append("&ecom_payment_card_type="); sb.append(getCardType(payinfo.getCardNumber())); sb.append("&ecom_payment_card_number="); sb.append(URLEncoder.encode(payinfo.getCardNumber(), "UTF-8")); sb.append("&ecom_payment_card_expdate_month="); String tmp = payinfo.getExpirationDate(); sb.append(tmp.substring(0, 2)); sb.append("&ecom_payment_card_expdate_year="); sb.append(tmp.substring(2, tmp.length())); String[] cc_name = payinfo.getHolderName().split(" "); sb.append("&ecom_billto_postal_name_first="); if (cc_name.length > 0) { sb.append(URLEncoder.encode(cc_name[0], "UTF-8")); } sb.append("&ecom_billto_postal_name_last="); if (cc_name.length > 1) { sb.append(URLEncoder.encode(cc_name[1], "UTF-8")); } sb.append("&ecom_payment_card_name="); sb.append(payinfo.getHolderName()); } //PAYMENT if (payinfo.getTotal() >= 0.0) { sb.append("&pg_transaction_type="); sb.append(SALE); //sb.append("&x_card_code=340"); } //REFUND else { sb.append("&pg_transaction_type="); sb.append(REFUND); } sb.append("&endofdata"); // open secure connection URL url = new URL(ENDPOINTADDRESS); URLConnection connection = url.openConnection(); connection.setDoOutput(true); connection.setUseCaches(false); // not necessarily required but fixes a bug with some servers // JG 16 May 12 use try-with-resources connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); try (DataOutputStream out = new DataOutputStream(connection.getOutputStream())) { out.write(sb.toString().getBytes()); out.flush(); } // process and read the gateway response BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String returned="", aux; while ((aux = in.readLine()) != null) { returned += "&" + aux; } payinfo.setReturnMessage(returned); in.close(); // fin Map props = new HashMap(); StringTokenizer tk = new java.util.StringTokenizer(returned, "&"); while(tk.hasMoreTokens()) { String sToken = tk.nextToken(); int i = sToken.indexOf('='); if (i >= 0) { props.put(URLDecoder.decode(sToken.substring(0, i), "UTF-8"), URLDecoder.decode(sToken.substring(i + 1), "UTF-8")); } else { props.put(URLDecoder.decode(sToken, "UTF-8"), null); } } if (APPROVED.equals(props.get("pg_response_type"))) { payinfo.paymentOK((String)props.get("pg_authorization_code"), (String)props.get("pg_trace_number"), returned); } else { String sCode = (String)props.get("pg_response_description"); sCode = sCode.replace("F01", "\nMANDITORY FIELD MISSING"); sCode = sCode.replace("F03", "\nINVALID FIELD NAME"); sCode = sCode.replace("F04", "\nINVALID FIELD VALUE"); sCode = sCode.replace("F05", "\nDUPLICATE FIELD"); sCode = sCode.replace("F07", "\nCONFLICTING FIELD"); payinfo.paymentError(AppLocal.getIntString("message.paymenterror"), sCode); } // JG 16 May 12 use multicatch } catch (UnsupportedEncodingException | MalformedURLException eUE) { payinfo.paymentError(AppLocal.getIntString("message.paymentexceptionservice"), eUE.getMessage()); } catch(IOException e){ payinfo.paymentError(AppLocal.getIntString("message.paymenterror"), e.getMessage()); } } private String getCardType(String sCardNumber){ String c = "UNKNOWN"; if (sCardNumber.startsWith("4")) { c = "VISA"; } else if (sCardNumber.startsWith("6")) { c = "DISC"; } else if (sCardNumber.startsWith("5")) { c = "MAST"; } else if (sCardNumber.startsWith("34") || sCardNumber.startsWith("37")) { c = "AMER"; } else if (sCardNumber.startsWith("3528") || sCardNumber.startsWith("3589")) { c = "JCB"; } else if (sCardNumber.startsWith("3")) { c = "DINE"; } return c; } }