IDEMPIERE-462 Ticket #1001503: Credit Cards Online - Fix the database transaction used to save payment transaction and online trx history records, encrpyt credit card number and cvv, fix the allocation when perform credit payment transaction for AR credit memo.

This commit is contained in:
Elaine Tan 2012-12-04 12:42:01 +08:00
parent b6fd81b23c
commit 778d4ba228
6 changed files with 188 additions and 51 deletions

View File

@ -20,6 +20,7 @@ import java.sql.ResultSet;
import java.util.List;
import java.util.Properties;
import org.adempiere.util.PaymentUtil;
import org.compiere.util.CLogger;
/**
@ -178,7 +179,10 @@ public class MBPBankAccount extends X_C_BP_BankAccount
// maintain routing on bank level
if (isACH() && getBank() != null)
setRoutingNo(null);
//
//
if (getCreditCardVV() != null)
setCreditCardVV(PaymentUtil.encrpytCvv(getCreditCardVV()));
return true;
} // beforeSave

View File

@ -29,6 +29,7 @@ import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.util.IProcessUI;
import org.adempiere.util.PaymentUtil;
import org.compiere.process.DocAction;
import org.compiere.process.DocumentEngine;
import org.compiere.process.ProcessCall;
@ -506,10 +507,10 @@ public final class MPayment extends X_C_Payment
else
{
// Validate before trying to process
String msg = pp.validate();
if (msg!=null && msg.trim().length()>0) {
setErrorMessage(Msg.getMsg(getCtx(), msg));
} else {
// String msg = pp.validate();
// if (msg!=null && msg.trim().length()>0) {
// setErrorMessage(Msg.getMsg(getCtx(), msg));
// } else {
// Process if validation succeeds
approved = pp.processCC ();
@ -522,7 +523,7 @@ public final class MPayment extends X_C_Payment
else
setErrorMessage("From " + getCreditCardName() + ": " + getR_RespMsg());
}
}
// }
}
}
catch (Exception e)
@ -540,7 +541,9 @@ public final class MPayment extends X_C_Payment
setIsApproved(approved);
MPaymentTransaction m_mPaymentTransaction = createPaymentTransaction();
Trx trx = Trx.get(Trx.createTrxName("ppt-"), true);
MPaymentTransaction m_mPaymentTransaction = createPaymentTransaction(trx.getTrxName());
m_mPaymentTransaction.setIsApproved(approved);
if(getTrxType().equals(TRXTYPE_Void) || getTrxType().equals(TRXTYPE_CreditPayment))
m_mPaymentTransaction.setIsVoided(approved);
@ -548,7 +551,7 @@ public final class MPayment extends X_C_Payment
m_mPaymentTransaction.setC_Payment_ID(getC_Payment_ID());
m_mPaymentTransaction.saveEx();
MOnlineTrxHistory history = new MOnlineTrxHistory(getCtx(), 0, get_TrxName());
MOnlineTrxHistory history = new MOnlineTrxHistory(getCtx(), 0, trx.getTrxName());
history.setAD_Table_ID(MPaymentTransaction.Table_ID);
history.setRecord_ID(m_mPaymentTransaction.getC_PaymentTransaction_ID());
history.setIsError(!approved);
@ -574,6 +577,12 @@ public final class MPayment extends X_C_Payment
history.saveEx();
if (trx != null)
{
trx.commit();
trx.close();
}
if(getTrxType().equals(TRXTYPE_Void) || getTrxType().equals(TRXTYPE_CreditPayment))
setIsVoided(approved);
@ -2761,9 +2770,9 @@ public final class MPayment extends X_C_Payment
m_processUI = processMonitor;
}
public MPaymentTransaction createPaymentTransaction()
public MPaymentTransaction createPaymentTransaction(String trxName)
{
MPaymentTransaction paymentTransaction = new MPaymentTransaction(getCtx(), 0, get_TrxName());
MPaymentTransaction paymentTransaction = new MPaymentTransaction(getCtx(), 0, trxName);
paymentTransaction.setA_City(getA_City());
paymentTransaction.setA_Country(getA_Country());
paymentTransaction.setA_EMail(getA_EMail());
@ -2846,8 +2855,8 @@ public final class MPayment extends X_C_Payment
// clear out the cc data when a Void happens since at that point we won't need the card information any longer
if (getTenderType().equals(TENDERTYPE_CreditCard))
{
// setCreditCardNumber(PaymentUtil.encrpytCreditCard(getCreditCardNumber()));
// setCreditCardVV(PaymentUtil.encrpytCvv(getCreditCardVV()));
setCreditCardNumber(PaymentUtil.encrpytCreditCard(getCreditCardNumber()));
setCreditCardVV(PaymentUtil.encrpytCvv(getCreditCardVV()));
}
if (getC_Invoice_ID() != 0)
@ -2871,4 +2880,23 @@ public final class MPayment extends X_C_Payment
return this;
}
public static int[] getCompletedPaymentIDs(int C_Order_ID, int C_Invoice_ID, String trxName)
{
StringBuilder whereClause = new StringBuilder();
whereClause.append("TenderType='").append(MPayment.TENDERTYPE_CreditCard).append("' ");
whereClause.append("AND TrxType IN ('").append(MPayment.TRXTYPE_DelayedCapture).append("', ");
whereClause.append("'").append(MPayment.TRXTYPE_Sales).append("', ");
whereClause.append("'").append(MPayment.TRXTYPE_CreditPayment).append("') ");
if (C_Order_ID > 0 && C_Invoice_ID > 0)
whereClause.append(" AND (C_Order_ID=").append(C_Order_ID).append(" OR C_Invoice_ID=").append(C_Invoice_ID).append(")");
else if (C_Order_ID > 0)
whereClause.append(" AND C_Order_ID=").append(C_Order_ID);
else if (C_Invoice_ID > 0)
whereClause.append(" AND C_Invoice_ID=").append(C_Invoice_ID);
whereClause.append(" AND IsApproved='Y' AND DocStatus IN ('CO','CL') ");
whereClause.append("ORDER BY DateTrx DESC");
return MPaymentTransaction.getAllIDs(Table_Name, whereClause.toString(), trxName);
}
} // MPayment

View File

@ -21,6 +21,7 @@ import java.util.Properties;
import java.util.logging.Level;
import org.adempiere.util.IProcessUI;
import org.adempiere.util.PaymentUtil;
import org.compiere.process.DocAction;
import org.compiere.process.ProcessCall;
import org.compiere.process.ProcessInfo;
@ -73,6 +74,8 @@ public class MPaymentTransaction extends X_C_PaymentTransaction implements Proce
@Override
protected boolean beforeSave(boolean newRecord)
{
if (getCreditCardVV() != null)
setCreditCardVV(PaymentUtil.encrpytCvv(getCreditCardVV()));
return true;
}
@ -159,6 +162,11 @@ public class MPaymentTransaction extends X_C_PaymentTransaction implements Proce
* @return true if approved
*/
public boolean processOnline()
{
return processOnline(get_TrxName());
}
public boolean processOnline(String trxName)
{
log.info ("Amt=" + getPayAmt());
//
@ -213,10 +221,10 @@ public class MPaymentTransaction extends X_C_PaymentTransaction implements Proce
else
{
// Validate before trying to process
String msg = pp.validate();
if (msg!=null && msg.trim().length()>0) {
setErrorMessage(Msg.getMsg(getCtx(), msg));
} else {
// String msg = pp.validate();
// if (msg!=null && msg.trim().length()>0) {
// setErrorMessage(Msg.getMsg(getCtx(), msg));
// } else {
// Process if validation succeeds
approved = pp.processCC ();
setIsApproved(approved);
@ -234,7 +242,7 @@ public class MPaymentTransaction extends X_C_PaymentTransaction implements Proce
&& !getTrxType().equals(MPaymentTransaction.TRXTYPE_VoiceAuthorization)
&& !getTrxType().equals(MPaymentTransaction.TRXTYPE_Void))
{
MPayment m_mPayment = createPayment();
MPayment m_mPayment = createPayment(trxName);
m_mPayment.saveEx();
setC_Payment_ID(m_mPayment.getC_Payment_ID());
processed = m_mPayment.processIt(DocAction.ACTION_Complete);
@ -247,8 +255,13 @@ public class MPaymentTransaction extends X_C_PaymentTransaction implements Proce
processed = true;
}
else
setErrorMessage("From " + getCreditCardName() + ": " + getR_RespMsg());
}
{
if(getTrxType().equals(TRXTYPE_Void) || getTrxType().equals(TRXTYPE_CreditPayment))
setErrorMessage("From " + getCreditCardName() + ": " + getR_VoidMsg());
else
setErrorMessage("From " + getCreditCardName() + ": " + getR_RespMsg());
}
// }
}
}
catch (Exception e)
@ -298,16 +311,24 @@ public class MPaymentTransaction extends X_C_PaymentTransaction implements Proce
{
if (getTenderType().equals(TENDERTYPE_CreditCard) && isOnline() && getTrxType().equals(TRXTYPE_Authorization) && !isVoided() && !isDelayedCapture())
{
MPaymentTransaction m_mPaymentTransaction = copyFrom(this, new Timestamp(System.currentTimeMillis()), TRXTYPE_Void, getR_PnRef(), get_TrxName());
Trx trx = Trx.get(Trx.createTrxName("ppt-"), true);
MPaymentTransaction m_mPaymentTransaction = copyFrom(this, new Timestamp(System.currentTimeMillis()), TRXTYPE_Void, getR_PnRef(), trx.getTrxName());
m_mPaymentTransaction.setIsApproved(false);
m_mPaymentTransaction.setIsVoided(false);
m_mPaymentTransaction.setIsDelayedCapture(false);
boolean ok = m_mPaymentTransaction.processOnline();
boolean ok = m_mPaymentTransaction.processOnline(get_TrxName());
m_mPaymentTransaction.setRef_PaymentTransaction_ID(getC_PaymentTransaction_ID());
// m_mPaymentTransaction.setCreditCardNumber(PaymentUtil.encrpytCreditCard(getCreditCardNumber()));
// m_mPaymentTransaction.setCreditCardVV(PaymentUtil.encrpytCvv(getCreditCardVV()));
m_mPaymentTransaction.saveEx();
if (trx != null)
{
trx.commit();
trx.close();
}
if (ok)
{
setIsVoided(true);
@ -330,7 +351,9 @@ public class MPaymentTransaction extends X_C_PaymentTransaction implements Proce
{
if (getTenderType().equals(TENDERTYPE_CreditCard) && isOnline() && getTrxType().equals(TRXTYPE_Authorization) && !isVoided() && !isDelayedCapture())
{
MPaymentTransaction m_mPaymentTransaction = copyFrom(this, new Timestamp(System.currentTimeMillis()), TRXTYPE_DelayedCapture, getR_PnRef(), get_TrxName());
Trx trx = Trx.get(Trx.createTrxName("ppt-"), true);
MPaymentTransaction m_mPaymentTransaction = copyFrom(this, new Timestamp(System.currentTimeMillis()), TRXTYPE_DelayedCapture, getR_PnRef(), trx.getTrxName());
m_mPaymentTransaction.setIsApproved(false);
m_mPaymentTransaction.setIsVoided(false);
m_mPaymentTransaction.setIsDelayedCapture(false);
@ -338,10 +361,16 @@ public class MPaymentTransaction extends X_C_PaymentTransaction implements Proce
if (C_Invoice_ID != 0)
m_mPaymentTransaction.setC_Invoice_ID(C_Invoice_ID);
boolean ok = m_mPaymentTransaction.processOnline();
boolean ok = m_mPaymentTransaction.processOnline(get_TrxName());
m_mPaymentTransaction.setRef_PaymentTransaction_ID(getC_PaymentTransaction_ID());
m_mPaymentTransaction.saveEx();
if (trx != null)
{
trx.commit();
trx.close();
}
if (ok)
{
if (C_Invoice_ID != 0)
@ -397,9 +426,9 @@ public class MPaymentTransaction extends X_C_PaymentTransaction implements Proce
return m_errorMessage;
}
public MPayment createPayment()
public MPayment createPayment(String trxName)
{
MPayment payment = new MPayment(getCtx(), 0, get_TrxName());
MPayment payment = new MPayment(getCtx(), 0, trxName);
payment.setA_City(getA_City());
payment.setA_Country(getA_Country());
payment.setA_EMail(getA_EMail());

View File

@ -29,7 +29,6 @@ import org.compiere.grid.ed.VNumber;
import org.compiere.model.GridTab;
import org.compiere.model.MBankAccountProcessor;
import org.compiere.model.MInvoice;
import org.compiere.model.MPaymentProcessor;
import org.compiere.swing.CButton;
import org.compiere.swing.CComboBox;
import org.compiere.swing.CLabel;
@ -124,6 +123,7 @@ public class VPaymentFormCreditCard extends PaymentFormCreditCard implements Act
if (m_C_Payment_ID != 0)
{
m_CCType = m_mPayment.getCreditCardType();
kNumberField.setText(m_mPayment.getCreditCardNumber());
kNameField.setText(m_mPayment.getA_Name());
kExpField.setText(m_mPayment.getCreditCardExp(null));
@ -142,6 +142,7 @@ public class VPaymentFormCreditCard extends PaymentFormCreditCard implements Act
}
else if (m_mPaymentTransaction != null)
{
m_CCType = m_mPaymentTransaction.getCreditCardType();
kNumberField.setText(m_mPaymentTransaction.getCreditCardNumber());
kNameField.setText(m_mPaymentTransaction.getA_Name());
kExpField.setText(PaymentUtil.getCreditCardExp(m_mPaymentTransaction.getCreditCardExpMM(), m_mPaymentTransaction.getCreditCardExpYY(), null));
@ -231,8 +232,10 @@ public class VPaymentFormCreditCard extends PaymentFormCreditCard implements Act
kOnline.setEnabled(bankAccountProcessor != null);
setBankAccountProcessor(bankAccountProcessor);
MPaymentProcessor paymentProcessor = new MPaymentProcessor(Env.getCtx(), bankAccountProcessor.getC_PaymentProcessor_ID(), null);
kApprovalField.setReadWrite(paymentProcessor.isRequireVV());
if (bankAccountProcessor != null)
kApprovalField.setReadWrite(bankAccountProcessor.isRequireVV());
else
kApprovalField.setReadWrite(true);
}
else
{

View File

@ -35,7 +35,6 @@ import org.compiere.grid.PaymentFormCreditCard;
import org.compiere.model.GridTab;
import org.compiere.model.MBankAccountProcessor;
import org.compiere.model.MInvoice;
import org.compiere.model.MPaymentProcessor;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.ValueNamePair;
@ -80,6 +79,7 @@ public class WPaymentFormCreditCard extends PaymentFormCreditCard implements Eve
kNumberField.setCols(16);
kExpField.setCols(4);
kApprovalField.setCols(4);
kApprovalField.setType("password");
kTypeLabel.setText(Msg.translate(Env.getCtx(), "CreditCardType"));
kNumberLabel.setText(Msg.translate(Env.getCtx(), "CreditCardNumber"));
kExpLabel.setText(Msg.getMsg(Env.getCtx(), "Expires"));
@ -142,6 +142,7 @@ public class WPaymentFormCreditCard extends PaymentFormCreditCard implements Eve
if (m_C_Payment_ID != 0)
{
m_CCType = m_mPayment.getCreditCardType();
kNumberField.setText(m_mPayment.getCreditCardNumber());
kExpField.setText(m_mPayment.getCreditCardExp(null));
kApprovalField.setText(m_mPayment.getVoiceAuthCode());
@ -158,6 +159,7 @@ public class WPaymentFormCreditCard extends PaymentFormCreditCard implements Eve
}
else if (m_mPaymentTransaction != null)
{
m_CCType = m_mPaymentTransaction.getCreditCardType();
kNumberField.setText(m_mPaymentTransaction.getCreditCardNumber());
kExpField.setText(PaymentUtil.getCreditCardExp(m_mPaymentTransaction.getCreditCardExpMM(), m_mPaymentTransaction.getCreditCardExpYY(), null));
kApprovalField.setText(m_mPaymentTransaction.getVoiceAuthCode());
@ -209,6 +211,8 @@ public class WPaymentFormCreditCard extends PaymentFormCreditCard implements Eve
if (exist)
updateOnlineButton();
else
kApprovalField.setReadonly(false);
}
}
@ -232,14 +236,16 @@ public class WPaymentFormCreditCard extends PaymentFormCreditCard implements Eve
BigDecimal PayAmt = (BigDecimal) kAmountField.getValue();
if (CCType != null && PayAmt != null)
if (CCType != null && CCType.length() != 0 && PayAmt != null)
{
MBankAccountProcessor bankAccountProcessor = getBankAccountProcessor(CCType, PayAmt);
kOnline.setEnabled(bankAccountProcessor != null);
setBankAccountProcessor(bankAccountProcessor);
MPaymentProcessor paymentProcessor = new MPaymentProcessor(Env.getCtx(), bankAccountProcessor.getC_PaymentProcessor_ID(), null);
kApprovalField.setReadonly(!paymentProcessor.isRequireVV());
if (bankAccountProcessor != null)
kApprovalField.setReadonly(!bankAccountProcessor.isRequireVV());
else
kApprovalField.setReadonly(false);
}
else
{

View File

@ -16,6 +16,7 @@ package org.compiere.grid;
import java.math.BigDecimal;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.util.PaymentUtil;
import org.compiere.model.GridTab;
import org.compiere.model.MBankAccountProcessor;
import org.compiere.model.MDocType;
@ -105,6 +106,70 @@ public abstract class PaymentFormCreditCard extends PaymentForm {
}
}
}
if (m_mPayment == null || m_mPayment.getC_Payment_ID() == 0)
{
int C_Order_ID = Env.getContextAsInt(Env.getCtx(), getWindowNo(), "C_Order_ID");
int C_Invoice_ID = Env.getContextAsInt(Env.getCtx(), getWindowNo(), "C_Invoice_ID");
if (C_Invoice_ID == 0 && m_DocStatus.equals(MInvoice.DOCSTATUS_Completed))
C_Invoice_ID = getInvoiceID (C_Order_ID);
BigDecimal grandTotal = (BigDecimal) getGridTab().getValue("GrandTotal");
boolean isCreditMemo = false;
int doctype = Env.getContextAsInt(Env.getCtx(), getWindowNo(), "C_DocTypeTarget_ID");
if(doctype > 0)
{
MDocType mDocType = MDocType.get(Env.getCtx(), doctype);
if (MDocType.DOCBASETYPE_ARCreditMemo.equals(mDocType.getDocBaseType()))
isCreditMemo = true;
}
boolean found = false;
if (C_Order_ID > 0 || C_Invoice_ID > 0)
{
int[] ids = MPayment.getCompletedPaymentIDs(C_Order_ID, C_Invoice_ID, null);
if (ids.length > 0)
{
if (C_Invoice_ID > 0)
{
for (int id : ids)
{
MPayment p = new MPayment(Env.getCtx(), id, null);
BigDecimal payAmt = p.getPayAmt();
if (isCreditMemo)
payAmt = payAmt.negate();
if (p.getC_Invoice_ID() == C_Invoice_ID && payAmt.compareTo(grandTotal) >= 0)
{
m_C_Payment_ID = id;
m_mPayment = p;
m_mPaymentOriginal = new MPayment(Env.getCtx(), id, null);
found = true;
break;
}
}
}
if (!found)
{
for (int id : ids)
{
MPayment p = new MPayment(Env.getCtx(), id, null);
BigDecimal payAmt = p.getPayAmt();
if (isCreditMemo)
payAmt = payAmt.negate();
if (p.getC_Order_ID() == C_Order_ID && payAmt.compareTo(grandTotal) >= 0)
{
m_C_Payment_ID = id;
m_mPayment = p;
m_mPaymentOriginal = new MPayment(Env.getCtx(), id, null);
break;
}
}
}
}
}
}
if (m_mPayment == null)
{
@ -231,24 +296,9 @@ public abstract class PaymentFormCreditCard extends PaymentForm {
}
// Amount sign negative, if ARC (Credit Memo) or API (AP Invoice)
boolean negateAmt = false;
MInvoice invoice = null;
if (C_Invoice_ID != 0)
{
invoice = new MInvoice (Env.getCtx(), C_Invoice_ID, null);
negateAmt = invoice.isCreditMemo();
}
MOrder order = null;
if (invoice == null && C_Order_ID != 0)
order = new MOrder (Env.getCtx(), C_Order_ID, null);
BigDecimal payAmount = m_Amount;
if (negateAmt)
if (isCreditMemo)
payAmount = m_Amount.negate();
// Info
log.config("C_Order_ID=" + C_Order_ID + ", C_Invoice_ID=" + C_Invoice_ID + ", NegateAmt=" + negateAmt);
/***********************
* Payments
@ -268,6 +318,7 @@ public abstract class PaymentFormCreditCard extends PaymentForm {
}
else if (C_Invoice_ID != 0)
{
MInvoice invoice = new MInvoice (Env.getCtx(), C_Invoice_ID, null);
if (invoice.isComplete())
m_mPayment.setTrxType(MPayment.TRXTYPE_Sales);
}
@ -280,6 +331,13 @@ public abstract class PaymentFormCreditCard extends PaymentForm {
m_mPayment.setC_BPartner_ID(m_C_BPartner_ID);
m_mPayment.setC_Invoice_ID(C_Invoice_ID);
MInvoice invoice = null;
if (C_Invoice_ID != 0)
invoice = new MInvoice (Env.getCtx(), C_Invoice_ID, null);
MOrder order = null;
if (invoice == null && C_Order_ID != 0)
order = new MOrder (Env.getCtx(), C_Order_ID, null);
if (order != null)
{
m_mPayment.setC_Order_ID(C_Order_ID);
@ -311,7 +369,12 @@ public abstract class PaymentFormCreditCard extends PaymentForm {
}
}
else
{
log.fine("NotDraft " + m_mPayment);
m_mPayment.setCreditCardNumber(PaymentUtil.encrpytCreditCard(m_mPayment.getCreditCardNumber()));
m_mPayment.setCreditCardVV(PaymentUtil.encrpytCvv(m_mPayment.getCreditCardVV()));
m_mPayment.saveEx();
}
/**********************
* Save Values to mTab
@ -356,10 +419,14 @@ public abstract class PaymentFormCreditCard extends PaymentForm {
boolean approved = false;
BigDecimal payAmount = m_Amount;
if (isCreditMemo)
payAmount = m_Amount.negate();
MPaymentTransaction mpt = new MPaymentTransaction(Env.getCtx(), 0, null);
mpt.setAD_Org_ID(m_AD_Org_ID);
mpt.setCreditCard(MPayment.TRXTYPE_Sales, CCType, CCNumber, "", CCExp);
mpt.setAmount(m_C_Currency_ID, m_Amount);
mpt.setAmount(m_C_Currency_ID, payAmount);
mpt.setPaymentProcessor();
if (isPOSOrder || isInvoice)
@ -377,7 +444,7 @@ public abstract class PaymentFormCreditCard extends PaymentForm {
}
else
{
MPaymentProcessor paymentProcessor = new MPaymentProcessor(mpt.getCtx(), mpt.getC_PaymentProcessor_ID(), mpt.get_TrxName());
MPaymentProcessor paymentProcessor = new MPaymentProcessor(mpt.getCtx(), mpt.getC_PaymentProcessor_ID(), null);
if (paymentProcessor.getTrxType() != null)
mpt.setTrxType(paymentProcessor.getTrxType());
}
@ -400,7 +467,7 @@ public abstract class PaymentFormCreditCard extends PaymentForm {
m_needSave = true;
if (mpt.getC_Payment_ID() > 0)
{
m_mPayment = new MPayment(mpt.getCtx(), mpt.getC_Payment_ID(), mpt.get_TrxName());
m_mPayment = new MPayment(mpt.getCtx(), mpt.getC_Payment_ID(), null);
String info = m_mPayment.getR_RespMsg() + " (" + m_mPayment.getR_AuthCode() + ") ID=" + m_mPayment.getR_PnRef();
processMsg = info + "\n" + m_mPayment.getDocumentNo();
saveChanges();