/*
jBilling - The Enterprise Open Source Billing System
Copyright (C) 2003-2011 Enterprise jBilling Software Ltd. and Emiliano Conde
This file is part of jbilling.
jbilling is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
jbilling 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with jbilling. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sapienter.jbilling.server.user.db;
import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Transient;
import javax.persistence.Version;
import com.sapienter.jbilling.common.Constants;
import com.sapienter.jbilling.common.JBCrypto;
import com.sapienter.jbilling.common.Util;
import com.sapienter.jbilling.server.payment.db.PaymentDTO;
import org.apache.log4j.Logger;
@Entity
@TableGenerator(
name = "credit_card_GEN",
table = "jbilling_seqs",
pkColumnName = "name",
valueColumnName = "next_id",
pkColumnValue = "credit_card",
allocationSize = 100)
@Table(name = "credit_card")
public class CreditCardDTO implements Serializable {
private static final Logger LOG = Logger.getLogger(CreditCardDTO.class);
private static final String OBSCURED_NUMBER_FORMAT = "************"; // + last four digits
private int id;
private String ccNumber;
private Date ccExpiry;
private String name;
private Integer ccType;
private int deleted;
private String securityCode;
private String ccNumberPlain;
private String gatewayKey;
private Set<PaymentDTO> payments = new HashSet<PaymentDTO>(0);
private Set<UserDTO> baseUsers = new HashSet<UserDTO>(0);
private Integer versionNum;
public CreditCardDTO() {
}
public CreditCardDTO(int id, String ccNumber, Date ccExpiry, int ccType, int deleted) {
this.id = id;
this.ccNumber = ccNumber;
this.ccExpiry = ccExpiry;
this.ccType = ccType;
this.deleted = deleted;
}
public CreditCardDTO(int id, String ccNumber, Date ccExpiry, String name,
int ccType, int deleted, String securityCode,
String ccNumberPlain) {
this.id = id;
this.ccNumber = ccNumber;
this.ccExpiry = ccExpiry;
this.name = name;
this.ccType = ccType;
this.deleted = deleted;
this.securityCode = securityCode;
this.ccNumberPlain = ccNumberPlain;
}
public CreditCardDTO(com.sapienter.jbilling.server.entity.CreditCardDTO oldCC) {
this.id = oldCC.getId() == null ? 0 : oldCC.getId();
this.ccExpiry = oldCC.getExpiry();
this.securityCode = oldCC.getSecurityCode();
this.ccType = oldCC.getType();
this.deleted = oldCC.getDeleted() == null ? 0 : oldCC.getDeleted();
this.gatewayKey = oldCC.getGatewayKey();
setName(oldCC.getName());
setNumber(oldCC.getNumber());
}
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "credit_card_GEN")
@Column(name = "id", unique = true, nullable = false)
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
/**
* Returns the raw encrypted credit card number as persisted to the database.
* Do not use unless you know what you are doing, use {@link #getNumber()} instead.
*
* @return raw encrypted credit card number
*/
@Column(name = "cc_number", nullable = false, length = 100)
public String getRawNumber() {
return this.ccNumber;
}
protected void setRawNumber(String ccNumber) {
this.ccNumber = ccNumber;
}
@Column(name = "cc_expiry", nullable = false, length = 13)
public Date getCcExpiry() {
return this.ccExpiry;
}
public void setCcExpiry(Date ccExpiry) {
this.ccExpiry = ccExpiry;
}
@Transient
public Date getExpiry() {
return getCcExpiry();
}
public void setExpiry(Date ccExpiry) {
setCcExpiry(ccExpiry);
}
@Transient
public String getName() {
if (getRawName() == null) return null;
return JBCrypto.getCreditCardCrypto().decrypt(getRawName());
}
public void setName(String name) {
if (name == null) {
setRawName(null);
return;
}
setRawName(JBCrypto.getCreditCardCrypto().encrypt(name));
// validate that the saved name is retrivable and valid
try {
if (!getName().equals(name)) {
LOG.error("The credit card name " + name + " was wrongly encrypted to " + getName());
}
} catch (Exception e) {
LOG.error("The credit card name " + name + " was wrongly encrypted to " + getName());
}
}
@Column(name = "name", length = 150)
protected String getRawName() {
return this.name;
}
protected void setRawName(String name) {
this.name = name;
}
@Transient
public Integer getType() {
return getCcType();
}
@Column(name = "cc_type", nullable = false)
public Integer getCcType() {
return this.ccType;
}
/**
* Sets the credit card type. Note that the {@link #setNumber(String)} attempts to auto-detect
* this value whenever a credit card number is set, eliminating the need to explicity
* set the type.
*
* @see com.sapienter.jbilling.common.CommonConstants PAYMENT_METHOD*
* @param ccType credit card type
*/
public void setCcType(Integer ccType) {
this.ccType = ccType;
}
@Column(name = "deleted", nullable = false)
public int getDeleted() {
return this.deleted;
}
public void setDeleted(int deleted) {
this.deleted = deleted;
}
@Transient
public String getSecurityCode() {
return this.securityCode;
}
public void setSecurityCode(String securityCode) {
this.securityCode = securityCode;
}
@Column(name = "cc_number_plain", length = 20)
public String getCcNumberPlain() {
return this.ccNumberPlain;
}
public void setCcNumberPlain(String ccNumberPlain) {
this.ccNumberPlain = ccNumberPlain;
}
/**
* Returns a vendor specific gateway key that can be used to authenticate payments
* without sending the rest of the credit card details.
*
* @return unique gateway key
*/
@Column(name = "gateway_key")
public String getGatewayKey() {
return gatewayKey;
}
public void setGatewayKey(String gatewayKey) {
this.gatewayKey = gatewayKey;
}
/**
* Returns true if this credit card should be handled using the stored gateway key instead
* of the stored credit card number. This usually means that the credit card number has
* been obscured and cannot be used to make a payment.
*
* @return true if gateway key should be used for payment, false if not
*/
@Transient
public boolean useGatewayKey() {
return (Constants.PAYMENT_METHOD_GATEWAY_KEY.equals(getCcType()) || getGatewayKey() != null);
}
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "creditCard")
public Set<PaymentDTO> getPayments() {
return this.payments;
}
public void setPayments(Set<PaymentDTO> payments) {
this.payments = payments;
}
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "user_credit_card_map", joinColumns = {@JoinColumn(name = "credit_card_id", updatable = false)}, inverseJoinColumns = {@JoinColumn(name = "user_id", updatable = false)})
public Set<UserDTO> getBaseUsers() {
return this.baseUsers;
}
public void setBaseUsers(Set<UserDTO> baseUsers) {
this.baseUsers = baseUsers;
}
@Version
@Column(name = "OPTLOCK")
public Integer getVersionNum() {
return versionNum;
}
public void setVersionNum(Integer versionNum) {
this.versionNum = versionNum;
}
@Transient
public String getNumber() {
if (getRawNumber() == null) return null;
return JBCrypto.getCreditCardCrypto().decrypt(getRawNumber());
}
/**
* This method sets the current credit card number in an encrypted form,
* and attempts to auto-detect the credit card type from the given number.
*
* @see Util#getPaymentMethod(String)
* @param number credit card number
*/
@Transient
public void setNumber(String number) {
if (number == null || number.trim().equals("")) {
setRawNumber(null);
setCcNumberPlain(null);
} else {
String crip = JBCrypto.getCreditCardCrypto().encrypt(number);
setRawNumber(crip);
setCcNumberPlain(number.substring(number.length() - 4));
setCcType(Util.getPaymentMethod(number));
}
}
/**
* Obscures this credit cards stored number by replacing all but the last four digits
* with asterisks (*). This method will overwrite the current number rendering this
* credit card invalid for anything other than display purposes.
*/
public void obscureNumber() {
if (getRawNumber() != null && getCcNumberPlain() != null) {
setNumber(OBSCURED_NUMBER_FORMAT + getCcNumberPlain());
}
}
/**
* Returns true if this credit card has been obscured (part of the number
* has been masked with asterisks '*') false if not, or if the number is null.
* @return true if masked, false if not or number is null.
*/
@Transient
public boolean isNumberObsucred() {
return getRawNumber() != null && getNumber().contains("*");
}
@Transient
public com.sapienter.jbilling.server.entity.CreditCardDTO getOldDTO() {
com.sapienter.jbilling.server.entity.CreditCardDTO oldCC =
new com.sapienter.jbilling.server.entity.CreditCardDTO();
oldCC.setDeleted(this.getDeleted());
oldCC.setExpiry(this.getExpiry());
oldCC.setId(this.getId());
oldCC.setName(this.getName());
oldCC.setNumber(this.getNumber());
oldCC.setSecurityCode(this.getSecurityCode());
oldCC.setType(this.getCcType());
oldCC.setGatewayKey(this.getGatewayKey());
return oldCC;
}
}