Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The payment gateway process class should extend com.crm.process.paymentgateway.CRMProcessPaymentGatewayBean and implement its abstract methods for creating/updating/deleting a payment gateway account and card, creating a payment and payment cancellation, and checking whether a currency is supported by the payment gateway. Implement only the methods required by your business model.

Below you can find both Payeezy and Braintree process classes.

Code Block
languagejava
titlecom.crm.process.paymentgateway.CRMProcessPaymentGatewayBean.javaPAYEEZYCRMProcessPayeezyGatewayBean
linenumberstrue
collapsetrue
package payeezy.process.paymentgateway.payeezy;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import org.json.JSONException;
import org.apache.commons.codec.binary.Base64;
import com.crm.businessobject.accounts.CRMBOAccountReceivableBean;
import com.crm.businessobject.billing.CRMBOBillBean;
import com.crm.businessobject.financialtransactions.CRMBOPaymentBean;
import com.crm.businessobject.financialtransactions.CRMBOPaymentCancellationBean;
import com.crm.businessobject.financialtransactions.CRMBOPaymentIntentionBean;
import com.crm.businessobject.paymentgateway.CRMBOPaymentGatewayCardBean;
import com.crm.dataobject.financialtransactions.CRMDOPayment;
import com.crm.dataobject.paymentgateway.CRMDOPaymentGatewayCard;
import com.crm.dataobject.paymentgateway.CRMDOPaymentGatewaySetting;
import com.crm.dataobject.paymentgateway.PaymentGatewayRequestLifeCycleState;
import com.crm.dataobject.platform.CRMDOCurrency;
import com.crm.exception.MandatoryFieldException;
import com.crm.framework.json.JSONArray;
import com.crm.framework.json.JSONObject;
import com.crm.framework.json.JSONUtil;
import com.crm.framework.util.CallList;
import com.crm.framework.util.DateUtil;
import com.crm.framework.util.ExceptionUtil;
import com.crm.process.paymentgateway.CRMProcessPaymentGatewayBean;
import com.crm.process.paymentgateway.CreateAccountParameters;
import com.crm.process.paymentgateway.CreateCardParameters;
import com.crm.process.paymentgateway.CreatePaymentCancellationParameters;
import com.crm.process.paymentgateway.CreatePaymentGatewayAccountResult;
import com.crm.process.paymentgateway.CreatePaymentGatewayCardResult;
import com.crm.process.paymentgateway.CreatePaymentGatewayPaymentCancellationResult;
import com.crm.process.paymentgateway.CreatePaymentGatewayPaymentResult;
import com.crm.process.paymentgateway.CreatePaymentParameters;
import com.crm.process.paymentgateway.DeleteAccountParameters;
import com.crm.process.paymentgateway.DeleteCardParameters;
import com.crm.process.paymentgateway.DeletePaymentGatewayAccountResult;
import com.crm.process.paymentgateway.DeletePaymentGatewayCardResult;
import com.crm.process.paymentgateway.PaymentGatewayCardResult;
import com.crm.process.paymentgateway.PaymentGatewayParameters;
import com.crm.process.paymentgateway.PaymentGatewayResult;
import com.crm.process.paymentgateway.UpdateAccountParameters;
import com.crm.process.paymentgateway.UpdateCardParameters;
import com.crm.process.paymentgateway.UpdatePaymentGatewayAccountResult;
import com.crm.process.paymentgateway.UpdatePaymentGatewayCardResult;
import payeezy.businessobject.paymentgateway.payeezy.PAYEEZYCRMBOPayeezyPaymentGatewaySettingBean;
import payeezy.dataobject.paymentgateway.payeezy.PayeezyMode;
import payeezy.dataobject.paymentgateway.payeezy.PayeezyParameter;
import payeezy.exception.paymentgateway.PaymentGatewayPayeezyException;

@Stateless(mappedName = "ejb/PAYEEZYCRMProcessPayeezyGateway")
@LocalBean
public class PAYEEZYCRMProcessPayeezyGatewayBean extends CRMProcessPaymentGatewayBean {
	private static final long serialVersionUID = 1L;
	private static final String PAYEEZY_PAYMENT_GATEWAY_SUC_LOG_PATH		= "Providers/Payment Gateways/Payeezy_Gateway";
	private static final String PAYEEZY_PAYMENT_GATEWAY_ERROR_LOG_PATH		= "Providers/Payment Gateways/Errors/Payeezy_Gateway";
	private static final String HMAC_SHA256_ALGORITHM 						= "HmacSHA256";
	@EJB private CRMBOPaymentBean paymentBean;
	@EJB private CRMBOPaymentCancellationBean paymentCancellationBean;
	@EJB private CRMBOAccountReceivableBean accountReceivableBean;
	@EJB private CRMBOPaymentIntentionBean paymentIntentionBean;
	@EJB private CRMBOBillBean billBean;
	@EJB private CRMBOPaymentGatewayCardBean paymentGatewayCardBean;
	@EJB private PAYEEZYCRMBOPayeezyPaymentGatewaySettingBean payeezyPaymentGatewaySettingBean;	
	
	protected static Integer timeout = 300 * 1000;

	/**
	 * Default constructor.
	 */
	public PAYEEZYCRMProcessPayeezyGatewayBean() {
		super();
	}
	@Override
	public CreatePaymentGatewayAccountResult processCreateAccount(CreateAccountParameters parameters) throws Exception {
		CreatePaymentGatewayAccountResult result = new CreatePaymentGatewayAccountResult();
		result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.POSTED);
		result.setResponseID(parameters.getAccountNumber());
		return result;
	}
	@Override
	public UpdatePaymentGatewayAccountResult processUpdateAccount(UpdateAccountParameters parameters) throws Exception {
		return null;
	}
	@Override
	public DeletePaymentGatewayAccountResult processDeleteAccount(DeleteAccountParameters parameters) throws Exception {
		return null;
	}
	
	@Override
	public CreatePaymentGatewayCardResult processCreateCard(CreateCardParameters parameters) throws PaymentGatewayPayeezyException, Exception{
		CreatePaymentGatewayCardResult result = new CreatePaymentGatewayCardResult();

		result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.POSTED);
		result.setReferenceNumber(parameters.getToken());
		
		return result;
	}

	@Override
	public UpdatePaymentGatewayCardResult processUpdateCard(UpdateCardParameters parameters) throws Exception {
		return null;
	}
	@Override
	public DeletePaymentGatewayCardResult processDeleteCard(DeleteCardParameters parameters) throws Exception {
		return null;
	}
	
	@Override
	public CreatePaymentGatewayPaymentResult processCreatePayment(CreatePaymentParameters parameters) throws Exception {
		CreatePaymentGatewayPaymentResult result = new CreatePaymentGatewayPaymentResult();
	
		
		String requestStr = null;
		try
		{
			String cardReferenceNumber = parameters.getCardReferenceNumber();
			if(cardReferenceNumber==null)
			{
				throw new MandatoryFieldException(getCRMSession(), "key_card_reference_number");
			}
			CRMDOPaymentGatewayCard paymentGatewayCard = paymentGatewayCardBean.loadByReferenceNumber(cardReferenceNumber, new ArrayList<String>());
			
			String cardHolderName = null;
			String brand = null;
			Integer expirationMonth = null;
			Integer expirationYear = null;
			
			if(paymentGatewayCard!=null)
			{
				cardHolderName = paymentGatewayCard.getHolderName();
				brand = paymentGatewayCard.getBrand();
				expirationMonth = paymentGatewayCard.getExpMonth();
				expirationYear = paymentGatewayCard.getExpYear();
			}
			
			PayeezyConnectionParameters connectionParameters = getConnectionParameters(parameters);
			
			JSONObject request = new JSONObject();
			
			Integer amountInt = parameters.getAmount().multiply(new BigDecimal(100)).intValue();
			String amountStr = amountInt.toString();
			
			ArrayList<String> billNumbers = parameters.getBillNumbers();
			ArrayList<String> invoiceNumbers = parameters.getInvoiceNumbers();
			
			String orderData = "Bills: "+getMetadataList(billNumbers)+" Invoices: "+getMetadataList(invoiceNumbers);
			request.put("method", "token");
			request.put("transaction_type", "purchase");
			request.put("amount", amountStr);
			request.put("order_data ", orderData);
			request.put("currency_code", "USD");			
			request.put("token", getTokenJSON(cardHolderName, cardReferenceNumber, brand, expirationMonth, expirationYear));
			String authorization = getAuthorization(connectionParameters, request.toString());
			String urlStr = connectionParameters.getUrl();
			URL url = new URL(urlStr);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setDoOutput(true);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Content-Type", connectionParameters.getContentType());
			conn.setRequestProperty("apiKey", connectionParameters.getApiKey());
			conn.setRequestProperty("token", connectionParameters.getMerchantToken());
			conn.setRequestProperty("Authorization", authorization);
			conn.setRequestProperty("nonce", connectionParameters.getNonce());
			conn.setRequestProperty("timestamp", connectionParameters.getTimestamp());
			
			conn.setDoOutput(true);
			requestStr = getRequest(urlStr,request);
			JSONObject responseJSON = getResponse(conn, request, "Create Payment Request: " +requestStr);
			result = (CreatePaymentGatewayPaymentResult) setTransactionInformation(result, responseJSON);
		}
		catch (Exception e)
		{
			CallList.LogTextFile(getCRMSession(), "Create Payment Request: " +requestStr+") Error: "+ExceptionUtil.getStackTrace(e), PAYEEZY_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
			result.setErrorDescription(e.getMessage());
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
		}
		
		return result;
	}
	@Override
	public CreatePaymentGatewayPaymentCancellationResult processCreatePaymentCancellation(CreatePaymentCancellationParameters parameters) throws Exception {
		CreatePaymentGatewayPaymentCancellationResult result = new CreatePaymentGatewayPaymentCancellationResult();
		
		String requestStr = null;
		try
		{
			
			ArrayList<String> associations =  new ArrayList<String>();
			associations.add("accountReceivable");
			associations.add("paymentGatewayCard");
			associations.add("accountReceivable.currency");
			
			CRMDOPayment payment 							= paymentBean.loadByReferenceNumber(parameters.getPaymentNumber(), associations);
			String paymentPayeezyRefNumber					= payment.getPaymentGatewayRefNumber();
			CRMDOPaymentGatewayCard paymentGatewayCard 		= payment.getPaymentGatewayCard();
			String transactionTag 							= parameters.getPaymentReferenceNumber();
			Integer amountInt 								= payment.getTotalAmount().multiply(new BigDecimal(100)).intValue();
			String amountStr 								= amountInt.toString();
			String currency 								= payment.getAccountReceivable().getCurrency().getCode();
			String cardReferenceNumber 						= paymentGatewayCard.getReferenceNumber();
			String cardHolderName 							= null;
			String brand 									= null;
			Integer expirationMonth							= null;
			Integer expirationYear 							= null;
			
			if(paymentGatewayCard!=null)
			{
				cardHolderName = paymentGatewayCard.getHolderName();
				brand = paymentGatewayCard.getBrand();
				expirationMonth = paymentGatewayCard.getExpMonth();
				expirationYear = paymentGatewayCard.getExpYear();
			}
			
			PayeezyConnectionParameters connectionParameters = getConnectionParameters(parameters);
			
			JSONObject request = new JSONObject();
			request.put("method", "token");
			request.put("transaction_type", "refund");
			request.put("amount", amountStr);
			request.put("transaction_tag ", transactionTag);
			request.put("currency_code", "USD");			
			request.put("token", getTokenJSON(cardHolderName, cardReferenceNumber, brand, expirationMonth, expirationYear));
			String urlStr = connectionParameters.getUrl()+"/"+paymentPayeezyRefNumber;
			URL url = new URL(urlStr);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setDoOutput(true);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Content-Type", connectionParameters.getContentType());
			conn.setRequestProperty("apiKey", connectionParameters.getApiKey());
			conn.setRequestProperty("token", connectionParameters.getMerchantToken());
			conn.setRequestProperty("Authorization", getAuthorization(connectionParameters,request.toString()));
			conn.setRequestProperty("nonce", connectionParameters.getNonce());
			conn.setRequestProperty("timestamp", connectionParameters.getTimestamp());
			conn.setDoOutput(true);

			requestStr = getRequest(urlStr,request);
			JSONObject responseJSON = getResponse(conn, request, "Create Payment Cancellation Request: " +requestStr);
			result = (CreatePaymentGatewayPaymentCancellationResult) setTransactionInformation(result, responseJSON);
		}
		catch (Exception e)
		{
			CallList.LogTextFile(getCRMSession(), "Create Payment Cancellation Request: " +requestStr+") Error: "+ExceptionUtil.getStackTrace(e), PAYEEZY_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
			result.setErrorDescription(e.getMessage());
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
		}
		
		return result;
	}	
	
	private PaymentGatewayCardResult setCardInformation(PaymentGatewayCardResult card, JSONObject responseJSON) throws Exception{
		
		if(responseJSON!=null)
		{
			JSONObject tokenJSON 	= JSONUtil.getJSONObjectParameter(responseJSON, "token", getCRMSession());
			String status 			= JSONUtil.getStringParameter(responseJSON, "status", getCRMSession());
			
			if(status!=null && status.equalsIgnoreCase("success"))
			{
				card.setLifeCycleState(PaymentGatewayRequestLifeCycleState.POSTED);
			}
			else
			{
				card = (PaymentGatewayCardResult) setErrorInformation(card, responseJSON);
				card.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
			}
			
			if(tokenJSON!=null)
			{
				String cardholderName 	= JSONUtil.getStringParameter(tokenJSON, "cardholder_name", getCRMSession());
				String expDate			= JSONUtil.getStringParameter(tokenJSON, "exp_date", getCRMSession());
				String type 			= JSONUtil.getStringParameter(tokenJSON, "type", getCRMSession());
				String token 			= JSONUtil.getStringParameter(tokenJSON, "value", getCRMSession());
				
				card.setHolderName(cardholderName);
				card.setResponseID(token);
				card.setBrand(payeezyPaymentGatewaySettingBean.getCardBrand(type));
				
				if(expDate!=null)
				{
					Integer expMonth = new Integer(expDate.substring(0,2));
					Integer expYear = new Integer(expDate.substring(2,4))+2000;
					
					card.setExpMonth(expMonth);
					card.setExpYear(expYear);
				}
				
			}
		}
		
		return card;
	}
	private PaymentGatewayResult setTransactionInformation(PaymentGatewayResult result, JSONObject responseJSON) throws Exception{
		if(responseJSON!=null)
		{
			
			String transactionStatus 			= JSONUtil.getStringParameter(responseJSON, "transaction_status", getCRMSession());
			String valisationStatus 			= JSONUtil.getStringParameter(responseJSON, "validation_status", getCRMSession());
			if(valisationStatus!=null && 
					valisationStatus.equalsIgnoreCase("success") && 
					transactionStatus!=null && 
					transactionStatus.equalsIgnoreCase("approved"))
			{
				String transactionTag = JSONUtil.getStringParameter(responseJSON, "transaction_tag", getCRMSession());
				result.setResponseID(transactionTag);
				result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.POSTED);
			}
			else
			{
				result = (CreatePaymentGatewayPaymentResult) setErrorInformation(result, responseJSON);
				result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
			}
		}
		return result;
	}
	private PaymentGatewayResult setErrorInformation(PaymentGatewayResult result, JSONObject responseJSON) throws Exception{
		String errorCode = "";
		String errorDescription = "";
		
		if(responseJSON!=null)
		{
			JSONObject errorJSON 	= JSONUtil.getJSONObjectParameter(responseJSON, "error", getCRMSession());
			
			if(errorJSON!=null)
			{
				JSONArray messagesJSON = JSONUtil.getJSONArrayParameter(errorJSON, "messages", getCRMSession());
				
				if(messagesJSON!=null)
				{
					for(int i=0;i<messagesJSON.size();i++)
					{
						JSONObject messageJSON = (JSONObject) messagesJSON.get(i);
						if(messageJSON!=null)
						{
							errorCode += JSONUtil.getStringParameter(messageJSON, "code", getCRMSession())+", ";
							errorDescription += JSONUtil.getStringParameter(messageJSON, "description", getCRMSession())+", ";
						}
					}
				}
			}
		}
		
		if(errorCode!=null && !errorCode.isEmpty())
		{
			errorCode = errorCode.substring(0, errorCode.length()-2);
			if(errorCode.length()>32)
			{
				errorCode = errorCode.substring(0, 31);
			}
			
			result.setErrorCode(errorCode);
		}
		
		if(errorDescription!=null && !errorDescription.isEmpty())
		{
			errorDescription = errorDescription.substring(0, errorDescription.length()-2);
			
			result.setErrorDescription(errorDescription);
		}
		return result;
	}
	
	private String getRequest(String url, JSONObject originalRequestJSON) throws Exception{
		
		JSONObject requestJSON = new JSONObject(originalRequestJSON, JSONObject.getNames(originalRequestJSON));
		String request="";
		
		if(url!=null)
		{
			request = "URL:" +url;
		}
		
		if(requestJSON!=null)
		{
			JSONObject creditCardJSON = JSONUtil.getJSONObjectParameter(requestJSON, "credit_card", getCRMSession());
			
			if(creditCardJSON!=null)
			{
				creditCardJSON.remove("cvv");
				String cardNumber 		= JSONUtil.getStringParameter(requestJSON, "card_number", getCRMSession());
				
				if(cardNumber!=null)
				{
					cardNumber = "************"+cardNumber.substring(cardNumber.length()-4,cardNumber.length());
					creditCardJSON.remove("card_number");
				}
				
				creditCardJSON.put("card_number", cardNumber);
			}
			
			request+= ", Request: "+requestJSON.toString();
		}
		
		
		
		return request;
	}
	
	private String getMetadataList(ArrayList<String> list){
		String s = "";
		if(list!=null)
		{
			for(String o:list)
			{
				s += ""+o+",";
			}
			if(s.length()>0)
			{
				s = s.substring(0, s.length()-1);
			}
		}
		return s;
	}
	@Override
	public Boolean isCurrencySupported(CRMDOCurrency currency, CRMDOPaymentGatewaySetting paymentGatewaySetting) throws Exception {
		return payeezyPaymentGatewaySettingBean.isCurrencySupported(currency,paymentGatewaySetting);
	}
	
	private PayeezyConnectionParameters getConnectionParameters(PaymentGatewayParameters parameters) throws NoSuchAlgorithmException{
		PayeezyConnectionParameters connectionParameters = new PayeezyConnectionParameters();
		
		String mode 			= (String) parameters.getGeneralparameter(PayeezyParameter.MODE.toString());
		String apiKey 			= null;
		String merchantToken 	= null;
		String apiSecret 		= null;
		String jsSecurityKey 	= null;
		String transarmorToken 	= null;
		String url				= null;
		String nonce = Long.toString(Math.abs(SecureRandom.getInstance("SHA1PRNG").nextLong()));
		String timestamp =  Long.toString(Instant.now().toEpochMilli());
		
		if(mode!=null && mode.equals(PayeezyMode.TEST.toString()))
		{
			apiKey 			= (String) parameters.getGeneralparameter(PayeezyParameter.TEST_API_KEY.toString());
			merchantToken 	= (String) parameters.getGeneralparameter(PayeezyParameter.TEST_MERCHANT_TOKEN.toString());
			apiSecret 		= (String) parameters.getGeneralparameter(PayeezyParameter.TEST_API_SECRET.toString());
			jsSecurityKey 	= (String) parameters.getGeneralparameter(PayeezyParameter.TEST_JS_SECURITY_KEY.toString());
			transarmorToken = (String) parameters.getGeneralparameter(PayeezyParameter.TEST_TA_TOKEN.toString());
			url				= (String) parameters.getGeneralparameter(PayeezyParameter.TEST_URL.toString());
		}
		else if(mode!=null && mode.equals(PayeezyMode.LIVE.toString()))
		{
			apiKey 			= (String) parameters.getGeneralparameter(PayeezyParameter.LIVE_API_KEY.toString());
			merchantToken 	= (String) parameters.getGeneralparameter(PayeezyParameter.LIVE_MERCHANT_TOKEN.toString());
			apiSecret 		= (String) parameters.getGeneralparameter(PayeezyParameter.LIVE_API_SECRET.toString());
			jsSecurityKey 	= (String) parameters.getGeneralparameter(PayeezyParameter.LIVE_JS_SECURITY_KEY.toString());
			transarmorToken = (String) parameters.getGeneralparameter(PayeezyParameter.LIVE_TA_TOKEN.toString());
			url				= (String) parameters.getGeneralparameter(PayeezyParameter.LIVE_URL.toString());
		}
		
		if(url!=null)
		{
			if(parameters instanceof CreateCardParameters)
			{
				url += "transactions/tokens";
			}
			else if(parameters instanceof CreatePaymentParameters)
			{
				url += "transactions";
			}
			else if(parameters instanceof CreatePaymentCancellationParameters)
			{
				url += "transactions";
			}
		}
		
		connectionParameters.setApiKey(apiKey);
		connectionParameters.setMerchantToken(merchantToken);
		connectionParameters.setUrl(url);
		connectionParameters.setApiSecret(apiSecret);
		connectionParameters.setJsSecurityKey(jsSecurityKey);
		connectionParameters.setContentType("application/json");
		connectionParameters.setTransarmorToken(transarmorToken);
		connectionParameters.setNonce(nonce);
		connectionParameters.setTimestamp(timestamp);
		
		return connectionParameters;
		
	}
	
	public JSONObject getCreditCardJSON(String cardHolderName, String cardNumber, String cardBrand, Integer expMonth, Integer expYear, String cvv) throws Exception {
		JSONObject creditCardJSON=new JSONObject();
		Integer expDate = null;
		
		if(expMonth!=null && expYear!=null)
		{
			expDate = expMonth*100+expYear % 1000;
		}
		
		creditCardJSON.put("type", payeezyPaymentGatewaySettingBean.getCardType(cardBrand));
		creditCardJSON.put("cardholder_name", cardHolderName);
		creditCardJSON.put("card_number", cardNumber);
		creditCardJSON.put("exp_date", expDate);
		creditCardJSON.put("cvv", cvv);
		
		return creditCardJSON;
	}
	public JSONObject getTokenJSON(String cardHolderName, String cardReferenceNumber, String cardBrand, Integer expMonth, Integer expYear) throws Exception {
		JSONObject tokenJSON=new JSONObject();
		tokenJSON.put("token_type", "FDToken");
		JSONObject tokenDataJSON=new JSONObject();
		Integer expDate = null;
		if(expMonth!=null && expYear!=null)
		{
			expDate = expMonth*100+expYear % 1000;
		}
		tokenDataJSON.put("type", payeezyPaymentGatewaySettingBean.getCardType(cardBrand));
		tokenDataJSON.put("cardholder_name", cardHolderName);
		tokenDataJSON.put("value", cardReferenceNumber);
		tokenDataJSON.put("exp_date", expDate);
		tokenJSON.put("token_data", tokenDataJSON);
		return tokenJSON;
	}
	private String getAuthorization(PayeezyConnectionParameters connectionParameters, String request) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException, Exception{		
		
		Mac mac=Mac.getInstance(HMAC_SHA256_ALGORITHM);
		String apiSecret=connectionParameters.getApiSecret();
		SecretKeySpec secret_key = new SecretKeySpec(apiSecret.getBytes(), HMAC_SHA256_ALGORITHM);
		mac.init(secret_key);
		String apikey = connectionParameters.getApiKey();
		String nonce = connectionParameters.getNonce();
		String timeStamp = connectionParameters.getTimestamp();
		String token = connectionParameters.getMerchantToken();
		String payload = request;
		StringBuilder buff=new StringBuilder();
		buff.append(apikey)
		.append(nonce)
		.append(timeStamp);
		if(token!=null){
			buff.append(token);
		}
		if(payload != null){
			buff.append(payload);
		}
		String bufferData = buff.toString();
		//MessageLogger.logMessage(String.format(bufferData));
		byte[] macHash=mac.doFinal(bufferData.getBytes("UTF-8"));
		//MessageLogger.logMessage(Integer.toString(macHash.length));
		//MessageLogger.logMessage(String.format("MacHAsh:{}" , macHash));
		String authorizeString = new String(Base64.encodeBase64(toHex(macHash)));
		//   MessageLogger.logMessage(String.format("Authorize:{}" , authorizeString));

		return authorizeString;
	}
	
	   /**
     * Converts the bytes to Hex bytes
     * @param arr
     * @return
     */
    private byte[] toHex(byte[] arr) {
        String hex= byteArrayToHex(arr);
        return hex.getBytes();
    }
    private String byteArrayToHex(byte[] a) {
        StringBuilder sb = new StringBuilder(a.length * 2);
        for(byte b: a)
            sb.append(String.format("%02x", b & 0xff));
        return sb.toString();
    }
	
	
	@SuppressWarnings("deprecation")
	private JSONObject getResponse(HttpURLConnection conn, JSONObject request, String requestInfo) throws Exception{
		JSONObject responseJSON = null;
		
		CallList.LogTextFile(getCRMSession(), requestInfo, PAYEEZY_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
		
		OutputStream os = conn.getOutputStream();
		os.write(request.toString().getBytes());
		os.flush();
		if (conn.getResponseCode() != HttpURLConnection.HTTP_OK && 
				conn.getResponseCode() != HttpURLConnection.HTTP_CREATED && 
				conn.getResponseCode() != HttpURLConnection.HTTP_ACCEPTED) 
		{
			String errorDescription = "";
			if(conn.getErrorStream()!=null)
			{
				BufferedReader br = new BufferedReader(new InputStreamReader((conn.getErrorStream())));
				if(br!=null)
				{
					errorDescription = br.readLine();
				}
			}
			CallList.LogTextFile(getCRMSession(),requestInfo+"\nError: HTTP error code : "+ conn.getResponseCode()+"\nError Description: "+errorDescription,PAYEEZY_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
			throw new RuntimeException("Failed : HTTP error code : "+ conn.getResponseCode()+" error description: "+errorDescription);
		}

		BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
		String output;
		Date date = DateUtil.getCurrentDate();
		long startTime = date.getTime();
		long duration = 0;
		while( true )
		{
			duration =DateUtil.getCurrentDate().getTime() - startTime;
			if(duration>timeout)
			{
				throw new Exception("Time out");
			}
			if ((output = br.readLine()) != null) 
			{
				try
				{
					CallList.LogTextFile(getCRMSession(),requestInfo+"\nResponse: "+output,PAYEEZY_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
					break;
				}
				catch (JSONException ex)
				{
				}
			}
			else{
				try {
					Thread.sleep(50);
				} catch (Exception e) {
				}
			}
		}
		conn.disconnect();
		responseJSON = new JSONObject(output);
		
		
		return responseJSON;
	}
}

6. Summary Page

You will need to create one summary page for payment gateway requests.

...

Code Block
languagexmljava
titlerequests.xmlCRMProcessBraintreePaypalGatewayBean
linenumberstrue
collapsetrue
<?xml version="1.0" encoding="UTF-8"?><summary xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../xsd/summary.xsd">
	<title>key_payment_gateway_requests</title>
	<sql>FROM PAYMENTGATEWAYREQUESTS 
		package com.crm.process.paymentgateway.braintree;
import java.math.BigDecimal;
import java.util.ArrayList;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import com.braintreegateway.BraintreeGateway;
import com.braintreegateway.CreditCard;
import com.braintreegateway.Customer;
import com.braintreegateway.CustomerRequest;
import com.braintreegateway.Environment;
import com.braintreegateway.PayPalAccount;
import com.braintreegateway.PaymentMethod;
import com.braintreegateway.PaymentMethodNonce;
import com.braintreegateway.PaymentMethodRequest;
import com.braintreegateway.Result;
import com.braintreegateway.Transaction;
import com.braintreegateway.TransactionRequest;
import com.braintreegateway.ValidationError;
import com.braintreegateway.exceptions.NotFoundException;
import com.crm.businessobject.accounts.CRMBOAccountReceivableBean;
import com.crm.businessobject.billing.CRMBOBillBean;
import com.crm.businessobject.financialtransactions.CRMBOPaymentBean;
import com.crm.businessobject.financialtransactions.CRMBOPaymentCancellationBean;
import com.crm.businessobject.financialtransactions.CRMBOPaymentIntentionBean;
import com.crm.businessobject.paymentgateway.CRMBOPaymentGatewayCardBean;
import com.crm.businessobject.paymentgateway.braintree.CRMBOBraintreePaymentGatewaySettingBean;
import com.crm.dataobject.accounts.PaymentPreferencePaymentMethod;
import com.crm.dataobject.paymentgateway.CRMDOPaymentGatewaySetting;
import com.crm.dataobject.paymentgateway.PaymentGatewayCardType;
import com.crm.dataobject.paymentgateway.PaymentGatewayRequestLifeCycleState;
import com.crm.dataobject.paymentgateway.braintree.BraintreeMode;
import com.crm.dataobject.paymentgateway.braintree.BraintreeParameter;
import com.crm.dataobject.platform.CRMDOCurrency;
import com.crm.exception.paymentgateway.PaymentGatewayBraintreeException;
import com.crm.framework.util.CallList;
import com.crm.framework.util.ExceptionUtil;
import com.crm.process.paymentgateway.CRMProcessPaymentGatewayBean;
import com.crm.process.paymentgateway.CreateAccountParameters;
import com.crm.process.paymentgateway.CreateCardParameters;
import com.crm.process.paymentgateway.CreatePaymentCancellationParameters;
import com.crm.process.paymentgateway.CreatePaymentGatewayAccountResult;
import com.crm.process.paymentgateway.CreatePaymentGatewayCardResult;
import com.crm.process.paymentgateway.CreatePaymentGatewayPaymentCancellationResult;
import com.crm.process.paymentgateway.CreatePaymentGatewayPaymentResult;
import com.crm.process.paymentgateway.CreatePaymentParameters;
import com.crm.process.paymentgateway.DeleteAccountParameters;
import com.crm.process.paymentgateway.DeleteCardParameters;
import com.crm.process.paymentgateway.DeletePaymentGatewayAccountResult;
import com.crm.process.paymentgateway.DeletePaymentGatewayCardResult;
import com.crm.process.paymentgateway.PaymentGatewayCardResult;
import com.crm.process.paymentgateway.PaymentGatewayParameters;
import com.crm.process.paymentgateway.PaymentGatewayResult;
import com.crm.process.paymentgateway.UpdateAccountParameters;
import com.crm.process.paymentgateway.UpdateCardParameters;
import com.crm.process.paymentgateway.UpdatePaymentGatewayAccountResult;
import com.crm.process.paymentgateway.UpdatePaymentGatewayCardResult;

@Stateless(mappedName = "ejb/CRMProcessBraintreePaypalGateway")
@LocalBean
public class CRMProcessBraintreePaypalGatewayBean extends CRMProcessPaymentGatewayBean {
	private static final long serialVersionUID = 1L;
	private static final String BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH		= "Providers/Payment Gateways/Braintree_Paypal_Gateway";
	private static final String BRAINTREE_PAYMENT_GATEWAY_ERROR_LOG_PATH	= "Providers/Payment Gateways/Errors/Braintree_Paypal_Gateway";
	@EJB private CRMBOPaymentBean paymentBean;
	@EJB private CRMBOPaymentCancellationBean paymentCancellationBean;
	@EJB private CRMBOAccountReceivableBean accountReceivableBean;
	@EJB private CRMBOPaymentIntentionBean paymentIntentionBean;
	@EJB private CRMBOBillBean billBean;
	@EJB private CRMBOPaymentGatewayCardBean paymentGatewayCardBean;
	@EJB private CRMBOBraintreePaymentGatewaySettingBean braintreePaymentGatewaySettingBean;

	/**
	 * Default constructor.
	 */
	public CRMProcessBraintreePaypalGatewayBean() {
		super();
	}
	@Override
	public CreatePaymentGatewayAccountResult processCreateAccount(CreateAccountParameters parameters) throws Exception {
		CreatePaymentGatewayAccountResult result = new CreatePaymentGatewayAccountResult();
		BraintreeGateway gateway = getBraintreeGateway(parameters);
		String accountNumber = parameters.getAccountNumber();
		
		if(accountNumber.length()>36)
		{
			accountNumber = accountNumber.substring(0, 35);
		}
		
		try
		{
			CallList.LogTextFile(getCRMSession(), "Create Customer Request: Account number (" +accountNumber+")", BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
//			Result<Customer> br = gateway.customer().delete(accountNumber);
			
			CustomerRequest request = new CustomerRequest();
			request.id(accountNumber);
			Result<Customer> braintreeResult = gateway.customer().create(request);
			if(braintreeResult.isSuccess())
			{
				result.setResponseID(braintreeResult.getTarget().getId());
				result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.POSTED);
				CallList.LogTextFile(getCRMSession(), "Create Customer Response: Account Number (" +accountNumber+") - OK - Payment Gateway Account Number: "+result.getResponseID(), BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
			}
			else
			{
				result = (CreatePaymentGatewayAccountResult) setErrorInformation(result, braintreeResult,"Create Customer Response: Account Number (" +accountNumber+")");
			}
		}
		catch (Exception e) 
		{ 
			result.setErrorDescription(e.getMessage());
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
			CallList.LogTextFile(getCRMSession(), "Create Customer Response: Account Number (" +accountNumber+") Error: "+ExceptionUtil.getStackTrace(e), BRAINTREE_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
		}
		
		return result;
	}
	@Override
	public UpdatePaymentGatewayAccountResult processUpdateAccount(UpdateAccountParameters parameters) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public DeletePaymentGatewayAccountResult processDeleteAccount(DeleteAccountParameters parameters) throws Exception {
		DeletePaymentGatewayAccountResult result = new DeletePaymentGatewayAccountResult();
		BraintreeGateway gateway = getBraintreeGateway(parameters);
		
		String accountReferenceNumber = parameters.getAccountReferenceNumber();
		try
		{
			CallList.LogTextFile(getCRMSession(), "Delete Customer Request: Payment Gateway Account Number (" +accountReferenceNumber+")", BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
			Result<Customer> braintreeResult = gateway.customer().delete(accountReferenceNumber);
			
			if(braintreeResult.isSuccess())
			{
				result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.POSTED);
				CallList.LogTextFile(getCRMSession(), "Delete Customer Response: Payment Gateway Account Number (" +accountReferenceNumber+") - OK", BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
			}
			else
			{
				result = (DeletePaymentGatewayAccountResult) setErrorInformation(result, braintreeResult,"Delete Customer Response: Payment Gateway Account Number (" +accountReferenceNumber+")");
			}
		}
		catch (NotFoundException e) 
		{ 
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.POSTED);
			CallList.LogTextFile(getCRMSession(), "Delete Customer Response:  Payment Gateway Account Number (" +accountReferenceNumber+") Not Found", BRAINTREE_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
		}
		catch (Exception e) 
		{ 
			result.setErrorDescription(e.getMessage());
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
			CallList.LogTextFile(getCRMSession(), "Delete Customer Response:  Payment Gateway Account Number (" +accountReferenceNumber+") Error: "+ExceptionUtil.getStackTrace(e), BRAINTREE_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
		}
		return result;
	}
	@Override
	public CreatePaymentGatewayCardResult processCreateCard(CreateCardParameters parameters) throws PaymentGatewayBraintreeException, Exception{
		CreatePaymentGatewayCardResult result = new CreatePaymentGatewayCardResult();
		
		boolean isAccountNew = parameters.isAccountNew();
		boolean isCardDefault = parameters.isCardDefault();
		boolean verifyCard = parameters.verifyCard();
		
		String accountReferenceNumber = parameters.getAccountReferenceNumber();
		String cardHolderName = parameters.getCardHolderName();
		String cardNumber = parameters.getCardNumber();
		String addressLine1 = parameters.getAddressLine1();
		String addressLine2 = parameters.getAddressLine2();
		String city = parameters.getCity();
		String zipCode = parameters.getZipCode();
		String state = parameters.getState();
		String country = parameters.getCountry();
		Integer expirationMonth = parameters.getExpirationMonth();
		Integer expirationYear = parameters.getExpirationYear();
		String cvc = parameters.getCvc();
		String paymentPreferencePaymentMethod = parameters.getPaymentMethod();
		
		BraintreeGateway gateway = getBraintreeGateway(parameters);
		String nonce = null;
		
		try
		{	
			nonce = parameters.getToken();
			PaymentMethodRequest request = new PaymentMethodRequest();
			if(paymentPreferencePaymentMethod!=null && paymentPreferencePaymentMethod.equals(PaymentPreferencePaymentMethod.CREDIT_CARD.toString()))
			{
				request.customerId(accountReferenceNumber).paymentMethodNonce(nonce).cardholderName(cardHolderName);
				request.billingAddress().streetAddress(addressLine1).extendedAddress(addressLine2).postalCode(zipCode).locality(city).region(state).countryName(country).done();
				request.options().makeDefault(isCardDefault).verifyCard(verifyCard);
			}
			else if(paymentPreferencePaymentMethod!=null && paymentPreferencePaymentMethod.equals(PaymentPreferencePaymentMethod.EMAIL_ADDRESS.toString()))
			{
				request.customerId(accountReferenceNumber).paymentMethodNonce(nonce);
			}
			
			CallList.LogTextFile(getCRMSession(), "Create Payment Method Request: Nonce (" +nonce+")", BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
			Result<? extends PaymentMethod> braintreeResult = gateway.paymentMethod().create(request);
			
			if(braintreeResult.isSuccess())
			{
				PaymentMethod paymentMethod = braintreeResult.getTarget();
				result = (CreatePaymentGatewayCardResult) setCardInfomration(result, braintreeResult);
				result.setResponseID(paymentMethod.getToken());
				result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.POSTED);
				 
			}
			else
			{
				result = (CreatePaymentGatewayCardResult) setErrorInformation(result, braintreeResult, "Create Payment Method Response: Nonce (" +nonce+")");
				if(isAccountNew)
				{
					gateway.customer().delete(parameters.getAccountReferenceNumber());
					result.setAccountDeleted(true);
				}
			}
		}
		catch (NotFoundException e) 
		{ 
			try
			{
				if(isAccountNew)
				{
					gateway.customer().delete(parameters.getAccountReferenceNumber());
					result.setAccountDeleted(true);
				}
			}
			catch  (Exception e2) {}
			CallList.LogTextFile(getCRMSession(), "Create Payment Method Response:  Nonce (" +nonce+") Error: "+e.getLocalizedMessage(), BRAINTREE_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
			result.setErrorDescription(e.getMessage());
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
		} 
		catch (Exception e) 
		{ 
			try
			{
				if(isAccountNew)
				{
					gateway.customer().delete(parameters.getAccountReferenceNumber());
					result.setAccountDeleted(true);
				}
			}
			catch  (Exception e2) {}
			CallList.LogTextFile(getCRMSession(), "Create Payment Method Response:   Nonce (" +nonce+") Error: "+ExceptionUtil.getStackTrace(e), BRAINTREE_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
			result.setErrorDescription(e.getMessage());
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
		}
		return result;
	}
	@Override
	public UpdatePaymentGatewayCardResult processUpdateCard(UpdateCardParameters parameters) throws Exception {
		UpdatePaymentGatewayCardResult result = new UpdatePaymentGatewayCardResult();
		
		BraintreeGateway gateway = getBraintreeGateway(parameters);
		String accountReferenceNumber = parameters.getAccountReferenceNumber();
		String cardReferenceNumber = parameters.getCardReferenceNumber();
		String cardHolderName = parameters.getCardHolderName();
		String addressLine1 = parameters.getAddressLine1();
		String addressLine2 = parameters.getAddressLine2();
		String city = parameters.getCity();
		String zipCode = parameters.getZipCode();
		String state = parameters.getState();
		String country = parameters.getCountry();
		Integer expirationMonth = parameters.getExpirationMonth();
		Integer expirationYear = parameters.getExpirationYear();
		String token = parameters.getToken();
		boolean isCardDefault = parameters.isCardDefault();
		boolean verifyCard = parameters.verifyCard();
		
		String paymentPreferencePaymentMethod = parameters.getPaymentMethod();
		
		if(addressLine1!=null && addressLine1.length()>255)
		{
			addressLine1 = addressLine1.substring(0,254);
		}
		
		if(addressLine2!=null && addressLine2.length()>255)
		{
			addressLine2 = addressLine2.substring(0,254);
		}
		
		try
		{			
			PaymentMethodRequest updateRequest = new PaymentMethodRequest();
			if(paymentPreferencePaymentMethod!=null && paymentPreferencePaymentMethod.equals(PaymentPreferencePaymentMethod.CREDIT_CARD.toString()))
			{
				updateRequest.cardholderName(cardHolderName).billingAddress().streetAddress(addressLine1).extendedAddress(addressLine2).postalCode(zipCode).locality(city).region(state).countryName(country).options().updateExisting(true).done();
				updateRequest.expirationMonth(expirationMonth.toString()).expirationYear(expirationYear.toString());
				updateRequest.options().makeDefault(isCardDefault).verifyCard(verifyCard);
			}
			else if(paymentPreferencePaymentMethod!=null && paymentPreferencePaymentMethod.equals(PaymentPreferencePaymentMethod.EMAIL_ADDRESS.toString()))
			{
				updateRequest.token(token);
			}
			
			CallList.LogTextFile(getCRMSession(), "Update Payment Method Request: Payment gateway card number (" +cardReferenceNumber+")", BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
			Result<? extends PaymentMethod> braintreeResult = gateway.paymentMethod().update(cardReferenceNumber, updateRequest);
			
			if(braintreeResult.isSuccess())
			{
				result = (UpdatePaymentGatewayCardResult) setCardInfomration(result, braintreeResult);
				result.setResponseID(braintreeResult.getTarget().getToken());
				result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.POSTED);
				CallList.LogTextFile(getCRMSession(), "Update Payment Method Response: Payment gateway card number (" +cardReferenceNumber+") - OK - Payment gateway card number:"+result.getResponseID(), BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
			}
			else
			{
				result = (UpdatePaymentGatewayCardResult) setErrorInformation(result, braintreeResult,"Update Payment Method Response: Payment gateway card number (" +cardReferenceNumber+")");
			}
		}
		catch (NotFoundException e) 
		{ 
			CallList.LogTextFile(getCRMSession(), "Update Payment Method Response:  Payment gateway card number (" +cardReferenceNumber+") Error: "+e.getLocalizedMessage(), BRAINTREE_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
			result.setErrorDescription(e.getMessage());
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
		}
		catch (Exception e) 
		{ 
			CallList.LogTextFile(getCRMSession(), "Update Payment Method Response:  Payment gateway card number (" +cardReferenceNumber+") Error: "+ExceptionUtil.getStackTrace(e), BRAINTREE_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
			result.setErrorDescription(e.getMessage());
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
		}
		
		return result;
	}
	@Override
	public DeletePaymentGatewayCardResult processDeleteCard(DeleteCardParameters parameters) throws Exception {
		DeletePaymentGatewayCardResult result = new DeletePaymentGatewayCardResult();
		BraintreeGateway gateway = getBraintreeGateway(parameters);
		String cardReferenceNumber = parameters.getCardReferenceNumber();
		try
		{
			CallList.LogTextFile(getCRMSession(), "Delete Payment Method Request: Payment gateway card number (" +cardReferenceNumber+")", BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
			Result<? extends PaymentMethod> braintreeResult = gateway.paymentMethod().delete(cardReferenceNumber);
			if(braintreeResult.isSuccess())
			{
				result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.POSTED);
				CallList.LogTextFile(getCRMSession(), "Delete Payment Method Response: Payment gateway card number (" +cardReferenceNumber+") - OK", BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
			}
			else
			{
				result = (DeletePaymentGatewayCardResult) setErrorInformation(result, braintreeResult,"Delete Payment Method Response: Payment gateway card number (" +cardReferenceNumber+")");
			}
		}
		catch (NotFoundException e) 
		{
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.POSTED);
			CallList.LogTextFile(getCRMSession(), "Delete Payment Method Response:  Payment gateway card number (" +cardReferenceNumber+") not found.", BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
		} 
		catch (Exception e) 
		{ 
			CallList.LogTextFile(getCRMSession(), "Delete Payment Method Response:  Payment gateway card number (" +cardReferenceNumber+") Error: "+ExceptionUtil.getStackTrace(e), BRAINTREE_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
			result.setErrorDescription(e.getMessage());
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
		}
		return result;
	}
	@Override
	public CreatePaymentGatewayPaymentResult processCreatePayment(CreatePaymentParameters parameters) throws Exception {
		CreatePaymentGatewayPaymentResult result = new CreatePaymentGatewayPaymentResult();
		BraintreeGateway gateway = getBraintreeGateway(parameters);
		
		BigDecimal totalAmount = parameters.getAmount();
		String notes = parameters.getNotes();
		String currencyCode = parameters.getCurrency();
		String paymentNumber = parameters.getPaymentNumber();
		String processName = parameters.getProcessName();
		String processNumber = parameters.getProcessNumber();
		String accountReferenceNumber = parameters.getAccountReferenceNumber();
		String cardReferenceNumber = parameters.getCardReferenceNumber();
		ArrayList<String> billNumbers = parameters.getBillNumbers();
		ArrayList<String> invoiceNumbers = parameters.getInvoiceNumbers();
		
		String description = "Bills: "+getMetadataList(billNumbers)+" Invoices: "+getMetadataList(invoiceNumbers);
		
		if(description.length()>127)
		{
			description = description.substring(0, 126);
		}

		try
		{
			CallList.LogTextFile(getCRMSession(), "Get Nonce Request: Payment gateway card number (" +cardReferenceNumber+") "+description, BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
			
			Result<PaymentMethodNonce> nonceResult = gateway.paymentMethodNonce().create(cardReferenceNumber);
			String nonce = nonceResult.getTarget().getNonce();
			
			CallList.LogTextFile(getCRMSession(), "Get Nonce Response: Payment gateway card number (" +cardReferenceNumber+") "+description+" - OK", BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
			
			TransactionRequest request = new TransactionRequest();
			request.amount(totalAmount).paymentMethodNonce(nonce).options().submitForSettlement(true).paypal().description(description).done();
			
			CallList.LogTextFile(getCRMSession(), "Create Sales Transaction Request: Payment gateway card number (" +cardReferenceNumber+") "+description, BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
			Result<Transaction> braintreeResult = gateway.transaction().sale(request);
			
			if(braintreeResult.isSuccess())
			{
				result.setResponseID(braintreeResult.getTarget().getId());
				result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.POSTED);
				CallList.LogTextFile(getCRMSession(), "Create Sales Transaction Response: Payment gateway card number (" +cardReferenceNumber+") "+description+" - OK - Sale id:"+result.getResponseID(), BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
			}
			else
			{
				result = (CreatePaymentGatewayPaymentResult) setErrorInformation(result, braintreeResult,"Create Sales Transaction Response: Payment gateway card number (" +cardReferenceNumber+") "+description);
			}
		} 
		catch (NotFoundException e) 
		{ 
			CallList.LogTextFile(getCRMSession(), "Create Sales Transaction Response:  Payment gateway card number (" +cardReferenceNumber+") "+description+" Error: "+e.getLocalizedMessage(), BRAINTREE_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
			result.setErrorDescription(e.getMessage());
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
		} 
		catch (Exception e) 
		{ 
			CallList.LogTextFile(getCRMSession(), "Create Sales Transaction Response:  Payment gateway card number (" +cardReferenceNumber+") "+description+" Error: "+ExceptionUtil.getStackTrace(e), BRAINTREE_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
			result.setErrorDescription(e.getMessage());
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
		}
		return result;
	}

	@Override
	public CreatePaymentGatewayPaymentCancellationResult processCreatePaymentCancellation(CreatePaymentCancellationParameters parameters) throws Exception {
		CreatePaymentGatewayPaymentCancellationResult result = new CreatePaymentGatewayPaymentCancellationResult();
		
		BraintreeGateway gateway = getBraintreeGateway(parameters);
		
		String paymentReferenceNumber = parameters.getPaymentReferenceNumber();
		String paymentCancellationNotes = parameters.getPaymentCancellationNotes();
		String paymentNumber = parameters.getPaymentNumber();
		String paymentCancellationNumber = parameters.getPaymentCancellationNumber();
		
		try
		{
			CallList.LogTextFile(getCRMSession(), "Create Refund Transaction Request: Payment reference number (" +paymentReferenceNumber+")", BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
			Result<Transaction> braintreeResult = gateway.transaction().refund(paymentReferenceNumber);
			
			if(braintreeResult.isSuccess())
			{
				result.setResponseID(braintreeResult.getTarget().getId());
				result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.POSTED);
				CallList.LogTextFile(getCRMSession(), "Create Refund Transaction Response: Payment reference number (" +paymentReferenceNumber+") - OK - Refund id:"+result.getResponseID(), BRAINTREE_PAYMENT_GATEWAY_SUC_LOG_PATH,"");
			}
			else
			{
				result = (CreatePaymentGatewayPaymentCancellationResult) setErrorInformation(result, braintreeResult,"Create Refund Transaction Response: Payment reference number (" +paymentReferenceNumber+")");
			}
		}
		catch (NotFoundException e) 
		{ 
			CallList.LogTextFile(getCRMSession(), "Create Refund Transaction Response:  Payment reference number (" +paymentReferenceNumber+") Error: "+e.getLocalizedMessage(), BRAINTREE_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
			result.setErrorDescription(e.getMessage());
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
		} 
		catch (Exception e) 
		{ 
			CallList.LogTextFile(getCRMSession(), "Create Refund Transaction Response:  Payment reference number (" +paymentReferenceNumber+") Error: "+ExceptionUtil.getStackTrace(e), BRAINTREE_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
			result.setErrorDescription(e.getMessage());
			result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
		}
		
		return result;
	}
	
	private PaymentGatewayCardResult setCardInfomration(PaymentGatewayCardResult result, Result<? extends PaymentMethod> braintreeResult){
		PaymentMethod paymentMethod = braintreeResult.getTarget();
		if(paymentMethod instanceof CreditCard)
		{
			CreditCard creditCard = (CreditCard)paymentMethod;
			result.setReferenceNumber(creditCard.getToken());
			result.setHolderName(creditCard.getCardholderName());
			if(creditCard.getBillingAddress()!=null)
			{
				result.setAddressLine1(creditCard.getBillingAddress().getStreetAddress());
				result.setAddressLine2(creditCard.getBillingAddress().getExtendedAddress());
				result.setAddressZip(creditCard.getBillingAddress().getPostalCode());
				result.setAddressCity(creditCard.getBillingAddress().getLocality());
				result.setAddressState(creditCard.getBillingAddress().getRegion());
				result.setAddressCountry(creditCard.getBillingAddress().getCountryName());
			}
			if(creditCard.getExpirationMonth()!=null)
			{
				result.setExpMonth(new Integer(creditCard.getExpirationMonth()));
			}
			if(creditCard.getExpirationMonth()!=null)
			{
				result.setExpYear(new Integer(creditCard.getExpirationYear()));
			}
			if(creditCard.getLast4()!=null)
			{
				result.setLastDigits(new Integer(creditCard.getLast4()));
			}
			if(creditCard.getCardType()!=null)
			{
				result.setBrand(braintreePaymentGatewaySettingBean.getCardBrand(creditCard.getCardType()));
			}
			if(creditCard.getDebit()!=null)
			{
				if(creditCard.getDebit().equals(CreditCard.Debit.YES))
				{
					result.setType(PaymentGatewayCardType.DEBIT.toString());
				}
				else if(creditCard.getDebit().equals(CreditCard.Debit.UNKNOWN))
				{
					result.setType(PaymentGatewayCardType.UNKNOWN.toString());
				}
			}
			
			if(creditCard.getPrepaid()!=null)
			{
				if(creditCard.getPrepaid().equals(CreditCard.Debit.YES))
				{
					result.setType(PaymentGatewayCardType.PREPAID.toString());
				}
				else if(creditCard.getPrepaid().equals(CreditCard.Debit.UNKNOWN))
				{
					result.setType(PaymentGatewayCardType.UNKNOWN.toString());
				}
			}
			
			if(result.getType()==null)
			{
				result.setType(PaymentGatewayCardType.CREDIT.toString());
			}
			if(creditCard.getVerification()!=null)
			{
				if(creditCard.getVerification().getAvsPostalCodeResponseCode()!=null)
				{
					result.setAddressZipCheckResult(creditCard.getVerification().getAvsPostalCodeResponseCode());
				}
				if(creditCard.getVerification().getAvsStreetAddressResponseCode()!=null)
				{
					result.setAddressLine1CheckResult(creditCard.getVerification().getAvsStreetAddressResponseCode());
				}
				if(creditCard.getVerification().getCvvResponseCode()!=null)
				{
					result.setSecurityCodeCheckResult(creditCard.getVerification().getCvvResponseCode());
				}
			}
		}
		if(paymentMethod instanceof PayPalAccount)
		{
			PayPalAccount paypalAccount = (PayPalAccount)paymentMethod;
			result.setReferenceNumber(paypalAccount.getToken());
		}
		
		
		return result;
	}
	
	private PaymentGatewayResult setErrorInformation(PaymentGatewayResult result, Result<?> braintreeResult, String logMessage) throws Exception{
		
		result.setLifeCycleState(PaymentGatewayRequestLifeCycleState.REJECTED);
		String errorDescription = "";
		String errorCode = "";
		for (ValidationError error : braintreeResult.getErrors().getAllDeepValidationErrors()) 
		{
			if(!errorDescription.isEmpty())
			{
				errorDescription +=", "+ error.getMessage();
			}
			else
			{
				errorDescription =  error.getMessage();
			}
			
			if(!errorCode.isEmpty())
			{
				errorCode += ", "+error.getCode().code;
			}
			else
			{
				errorCode =  error.getCode().code;
			}
		}
		
		result.setErrorDescription(errorDescription);
		if(errorCode.length()>32)
		{
			errorCode = errorCode.substring(0, 31);
		}
		result.setErrorCode(errorCode);
		
		CallList.LogTextFile(getCRMSession(), logMessage+" Error Code: "+errorCode+" Error Description: "+errorDescription, BRAINTREE_PAYMENT_GATEWAY_ERROR_LOG_PATH,"");
		
		return result;
	}
	
	private String getMetadataList(ArrayList<String> list){
		String s = "";
		if(list!=null)
		{
			for(String o:list)
			{
				s += ""+o+",";
			}
			if(s.length()>0)
			{
				s = s.substring(0, s.length()-1);
			}
		}
		return s;
	}
	
	private BraintreeGateway getBraintreeGateway(PaymentGatewayParameters parameters){
		String mode = (String) parameters.getGeneralparameter(BraintreeParameter.MODE.toString());
		String merchantID = (String) parameters.getGeneralparameter(BraintreeParameter.MERCHANT_ID.toString());
		String publicKey = null;
		String privateKey = null;
		Environment environment = Environment.SANDBOX;
		if(mode!=null && mode.equals(BraintreeMode.TEST.toString()))
		{
			environment = Environment.SANDBOX;
			publicKey = (String) parameters.getGeneralparameter(BraintreeParameter.TEST_PUBLIC_KEY.toString());
			privateKey = (String) parameters.getGeneralparameter(BraintreeParameter.TEST_PRIVATE_KEY.toString());
		}
		else if(mode!=null && mode.equals(BraintreeMode.LIVE.toString()))
		{
			environment = Environment.PRODUCTION;
			publicKey = (String) parameters.getGeneralparameter(BraintreeParameter.LIVE_PUBLIC_KEY.toString());
			privateKey = (String) parameters.getGeneralparameter(BraintreeParameter.LIVE_PRIVATE_KEY.toString());
		}
		BraintreeGateway gateway = new BraintreeGateway(environment,merchantID,publicKey,privateKey);
		
		return gateway;
	}
	@Override
	public Boolean isCurrencySupported(CRMDOCurrency currency, CRMDOPaymentGatewaySetting paymentGatewaySetting) throws Exception {
		return braintreePaymentGatewaySettingBean.isCurrencySupported(currency,paymentGatewaySetting);
	}
}

6. Summary Page

You will need to create one summary page for payment gateway requests.

For more information on creating custom summary pages go to Customize Summary Pages.

Code Block
languagexml
titlerequests.xml
linenumberstrue
collapsetrue
<?xml version="1.0" encoding="UTF-8"?><summary xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../xsd/summary.xsd">
	<title>key_payment_gateway_requests</title>
	<sql>FROM PAYMENTGATEWAYREQUESTS 
		LEFT JOIN USERS CREATEDBY ON CREATEDBY.USERID = PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQCREATEDBYUSERID
		LEFT JOIN USERS UPDATEDBY ON UPDATEDBY.USERID = PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQUPDATEDBYUSERID
		LEFT JOIN OUUNITS CREATEDBYUNIT ON CREATEDBYUNIT.OUUID = PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQCREATEDBYOUUID
		LEFT JOIN OUUNITS UPDATEDBYUNIT ON UPDATEDBYUNIT.OUUID = PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQUPDATEDBYOUUID
		LEFT JOIN PAYMENTGATEWAYSETTINGS ON PAYMENTGATEWAYSETTINGS.PAYGATEWAYSETID = PAYMENTGATEWAYREQUESTS.PAYGATEWAYSETID
		LEFT JOIN PAYMENTGATEWAYCUSTOMERACCOUNT ON PAYMENTGATEWAYCUSTOMERACCOUNT.PAYGATECUSACCID = PAYMENTGATEWAYREQUESTS.PAYGATECUSACCID
		LEFT JOIN ACCOUNTSRECEIVABLE ON PAYMENTGATEWAYCUSTOMERACCOUNT.ACCRECID = ACCOUNTSRECEIVABLE.ACCRECID
		LEFT JOIN PAYMENTGATEWAYCARDS ON PAYMENTGATEWAYCARDS.PAYGATEWAYCARDID = PAYMENTGATEWAYREQUESTS.PAYGATEWAYCARDID
		LEFT JOIN ACCPAYMENTPREFERENCES ON ACCPAYMENTPREFERENCES.ACCPAYPREFID = PAYMENTGATEWAYCARDS.ACCPAYPREFID
		LEFT JOIN PAYMENTPREFERENCES ON PAYMENTPREFERENCES.PAYPREFID = ACCPAYMENTPREFERENCES.PAYPREFID
		LEFT JOIN PAYMENTS ON PAYMENTS.PAYMENTID = PAYMENTGATEWAYREQUESTS.PAYMENTID
		LEFT JOIN PAYMENTCANCELLATIONS ON PAYMENTCANCELLATIONS.PAYMENTCANCELID = PAYMENTGATEWAYREQUESTS.PAYMENTCANCELID	
		LEFT JOIN BILLS ON BILLS.BILLID = PAYMENTGATEWAYREQUESTS.BILLID
		LEFT JOIN WALLETS ON WALLETS.WALLETID = PAYMENTGATEWAYREQUESTS.WALLETID
		LEFT JOIN SUBSCRIPTIONS ON SUBSCRIPTIONS.SUBID=PAYMENTGATEWAYREQUESTS.SUBID
		LEFT JOIN PROCESSRUNLOG ON PROCESSRUNLOG.PROCESSRUNLOGID = PAYMENTGATEWAYREQUESTS.PROCESSID
		WHERE PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQDELETED = 0 AND PAYMENTGATEWAYSETTINGS.PAYMENTGATEWAYPROTOCOL='PAYEEZY'
	</sql>
	<rowsperpage>20</rowsperpage>
	<primaryfield>PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQID</primaryfield>
	<mainlinkfield>PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQNUM</mainlinkfield>
	<orderbyfields>PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQCREATEDDATE DESC</orderbyfields>
	<multiselect>false</multiselect>
	<entityfilter></entityfilter>
	<module>CUSTOM_PAYEEZY</module>
	
	<fieldlist>
		<!-- external filters -->
		<field>
			<fieldname>PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQID</fieldname>
			<filtertextoption>equal</filtertextoption>
		</field>
		<field>
			<fieldname>PAYMENTGATEWAYREQUESTS.PAYMENTID</fieldname>
		</field>
		<field>
			<fieldname>PAYMENTGATEWAYREQUESTS.PAYMENTCANCELID</fieldname>
		</field>
		<field>
			<fieldname>PAYMENTGATEWAYREQUESTS.BILLID</fieldname>
		</field>
		<field>
			<fieldname>PAYMENTGATEWAYREQUESTS.WALLETID</fieldname>
		</field>
		<field>
			<fieldname>PAYMENTGATEWAYREQUESTS.SUBID</fieldname>
		</field>
		<field>
			<fieldname>ACCOUNTSRECEIVABLE.ACCRECID</fieldname>
		</field>
                <field>
			<fieldname>PAYMENTGATEWAYREQUESTS.PAYGATECUSACCID</fieldname>
			<filtertextoption>equal</filtertextoption>
		</field>
		<!-- fields -->
		<field>
			<fieldname>PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQNUM</fieldname>
			<caption>key_number</caption>
			<summary>true</summary>
			<available>true</available>
			<filter>true</filter>
			<filteravailable>true</filteravailable>
		</field>
		
		<field>
			<fieldname>PAYMENTGATEWAYSETTINGS.PAYGATEWAYSETNAME</fieldname>
			<caption>key_payment_gateway_provider</caption>
			<summary>true</summary>
		</field>		
		
		<field>
			<fieldname>TYPE</fieldname>
			<fieldfunction>
			CASE 
				WHEN PAYMENTGATEWAYREQUESTS.PAYMENTID IS NOT NULL THEN 'Payment'
				WHEN PAYMENTGATEWAYREQUESTS.PAYMENTCANCELID IS NOT NULL THEN 'Payment Cancellation' 
				WHEN PAYMENTGATEWAYREQUESTS.REFUNDID IS NOT NULL THEN 'Refund' 
				WHEN PAYMENTGATEWAYREQUESTS.PAYGATEWAYCARDID IS NOT NULL THEN 'Card'
				WHEN PAYMENTGATEWAYREQUESTS.PAYGATECUSACCID IS NOT NULL THEN 'Account'
			END
			</fieldfunction>
			<caption>key_type</caption>
			<filter>true</filter>
			<summary>true</summary>
			<fixedlookup>|key_all|Payment|key_payment|Payment Cancellation|key_payment_cancellation|Refund|key_refund|Account|key_account|Card|key_card</fixedlookup>	
		</field>
		
		<field>
			<fieldname>PROCESSRUNDEFINITION</fieldname>
			<fieldfunction>PROCESSRUNLOG.PROCESSRUNLOGNUM</fieldfunction>
			<caption>key_payment_gateway_run</caption>
			<summary>true</summary>
		</field>
		<field>
			<fieldname>PAYMENTNUMBER</fieldname>
			<fieldfunction> 
				case when PAYMENTGATEWAYREQUESTS.LIFECYCLESTATE = 'POSTED' then PAYMENTS.PAYMENTNUM else PAYMENTS.PAYMENTREFNUM end
			</fieldfunction>
			<caption>key_payment</caption>
			<summary>true</summary>
            <link>javascript:displayModalCreate('financialtransactions/payment','ejb/CRMUIPayment','loadForm','java.lang.String@((PAYMENTGATEWAYREQUESTS.PAYMENTID))','',null,'','')</link>
		</field>
		
		<field>
			<fieldname>PAYMENTCANCELNUMBER</fieldname>
			<fieldfunction> 
				CASE 
					WHEN PAYMENTCANCELLATIONS.LIFECYCLESTATE = 'POSTED' 
					then PAYMENTCANCELLATIONS.PAYMENTCANCELNUM
				
				ELSE PAYMENTCANCELLATIONS.PAYMENTCANCELREFNUM
				END
			</fieldfunction>
			<caption>key_payment_cancellation</caption>
			<summary>true</summary>
            <link>javascript:displayModalCreate('financialtransactions/paymentCancellation','ejb/CRMUIPaymentCancellation','loadForm','java.lang.String@((PAYMENTGATEWAYREQUESTS.PAYMENTCANCELID))','',null,'','')</link>
		</field>
		
		<field>
			<fieldname>PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQREFNUM</fieldname>
			<caption>key_payment_gateway_reference_number</caption>
			<summary>true</summary>
		</field>
		
		<field>
			<fieldname>PAYMENT_FILTER</fieldname>
			<fieldfunction>PAYMENTS.PAYMENTID</fieldfunction>
			<caption>key_payment</caption>
			<filter>true</filter>
			<filterlookupname>dataset;financialtransactions.loadpayments;paymentid;paymentrefnum</filterlookupname>
		</field>
		
		<field>
			<fieldname>PAYMENT_CANCELLATION_FILTER</fieldname>
			<fieldfunction>PAYMENTCANCELLATIONS.PAYMENTCANCELID</fieldfunction>
			<caption>key_payment_cancellation</caption>
			<filter>true</filter>
			<filterlookupname>dataset;financialtransactions.loadpaymentcancellations;paymentcancelid;paymentcancelrefnum</filterlookupname>
		</field>
		
		<field>
			<fieldname>CARD_FILTER</fieldname>
			<fieldfunction>PAYMENTGATEWAYCARDS.PAYGATEWAYCARDID</fieldfunction>
			<caption>key_payment_gateway_card</caption>
			<filter>true</filter>
			<filterlookupname>dataset;paymentgateway.loadcards;paygatewaycardid;PAYGATEWAYCARDHOLDERNAME</filterlookupname>
		</field>
		
		<field>
			<fieldname>ACCOUNTSRECEIVABLE.ACCRECID</fieldname>
			<caption>key_account_name</caption>
			<filter>true</filter>
			<filteravailable>true</filteravailable>
			<fieldtype>string</fieldtype>
			<filterlookupname>dataset;accounts.load;accrecid;accrecname</filterlookupname>
		</field> 
		
		<field>
			<fieldname>SUBSCRIPTION_FILTER</fieldname>
			<fieldfunction>SUBSCRIPTIONS.SUBID</fieldfunction>
			<caption>key_subscription</caption>
			<filter>true</filter>
			<filterlookupname>dataset;subscriptions.load;subid;subnum</filterlookupname>
		</field>
		<field>
			<fieldname>ACCOUNTSRECEIVABLE.ACCRECNUM</fieldname>
			<caption>key_account_number</caption>
            <mouseover>true</mouseover>  
			<summary>true</summary>
			<link>javascript:displayModalCreate('accounts/accountReceivable','ejb/CRMUIAccountReceivable','loadForm','java.lang.String@((ACCOUNTSRECEIVABLE.ACCRECID))','',null,'','')</link>
		</field>	
		
		<field>
			<fieldname>PAYMENTPREFERENCES.PAYPREFNAME</fieldname>
			<caption>key_accounts_receivable_payment_preference</caption>
            <mouseover>true</mouseover>  
			<summary>true</summary>
		</field>		
		
		<field>
			<fieldname>PAYMENTGATEWAYCARDS.PAYGATEWAYCARDHOLDERNAME</fieldname>
			<caption>key_payment_gateway_card</caption>
			<mouseover>true</mouseover>  
			<summary>true</summary>
		</field>
		
		<field>
			<fieldname>PAYMENTGATEWAYCUSTOMERACCOUNT.PAYGATECUSACCNUM</fieldname>
			<caption>key_payment_gateway_customer_account</caption>
			<mouseover>true</mouseover>  
			<summary>true</summary>
		</field>
		
		<field>
			<fieldname>BILLS.BILLNUM</fieldname>
			<caption>key_paid_bill</caption>
			<summary>true</summary>
		 	<available>true</available>
		    <link>javascript:displayModalCreate('billing/bill','ejb/CRMUIBill','loadForm','java.lang.String@((PAYMENTGATEWAYREQUESTS.BILLID))','',null,'','')</link>
		</field>
		
		<field>
			<fieldname>BILL_FILTER</fieldname>
			<fieldfunction>BILLS.BILLID</fieldfunction>
			<caption>key_paid_bill</caption>
			<filter>true</filter>
			<filterlookupname>dataset;billing.load;billid;billnum</filterlookupname>
		</field>
		
		<field>
			<fieldname>WALLETS.WALLETNUM</fieldname>
			<caption>key_topped_up_wallet</caption>
			<summary>true</summary>
		 	<available>true</available>
		    <link>javascript:displayModalCreate('wallets/wallet','ejb/CRMUIWallet','loadForm','java.lang.String@((PAYMENTGATEWAYREQUESTS.WALLETID))','',null,'','')</link>
		</field>
		
		<field>
			<fieldname>SUBSCRIPTIONS.SUBNUM</fieldname>
			<caption>key_subscription</caption>
			<summary>true</summary>
		 	<available>true</available>
		    <link>javascript:displayModalCreate('subscriptions/subscription','ejb/CRMUISubscription','loadForm','java.lang.String@((PAYMENTGATEWAYREQUESTS.SUBID))','',null,'','')</link>
		</field>
		
		<field>
			<fieldname>WALLETNUM_FILTER</fieldname>
			<fieldfunction>WALLETS.WALLETID</fieldfunction>
			<caption>key_wallet</caption>
			<filter>true</filter>
			<filterlookupname>dataset;wallets.load;walletid;walletnum</filterlookupname>
		</field>
		
		<field>
			<fieldname>PROCESSID_FILTER</fieldname>
			<fieldfunction>PAYMENTGATEWAYREQUESTS.PROCESSID</fieldfunction>
			<caption>key_process_run</caption>
			<filter>true</filter>
			<filtertextoption>equal</filtertextoption>			
			<filterlookupname>dataset;processrun.paymentgateway.loadpayeezy;PROCESSRUNLOGID;PROCESSRUNLOGNUM:PROCESSID:PROCESSRUNLOGSTARTDATE:PROCESSRUNLOGENDDATE</filterlookupname>
		</field>
		<field>
			<fieldname>PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQEXECUTIONDATE</fieldname>
			<caption>key_execution_date</caption>
			<summary>true</summary>
			<filter>true</filter>
			<fieldtype>date</fieldtype>
			<filtertextoption>range</filtertextoption>
		</field>
		
		<field>
			<fieldname>LIFECYCLESTATE_FILTER</fieldname>
			<fieldfunction>PAYMENTGATEWAYREQUESTS.LIFECYCLESTATE</fieldfunction>
			<caption>key_life_cycle_state</caption>
			<filter>true</filter>
			<fixedlookup>ejb/CRMUIPaymentGatewayRequest.getLifeCycleStateOptions:key_all</fixedlookup>
		</field>
		<field>
			<fieldname>LIFECYCLESTATE</fieldname>
			<fieldfunction>PAYMENTGATEWAYREQUESTS.LIFECYCLESTATE</fieldfunction>
			<caption>key_life_cycle_state</caption>
			<summary>true</summary>
			<fixedlookup>ejb/CRMUIPaymentGatewayRequest.getLifeCycleStateOptions:key_n/a</fixedlookup>
		</field>
		
		<field>
			<fieldname>PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQERRORCODE</fieldname>
			<caption>key_error_code</caption>
			<summary>true</summary>
		</field>
	
		<field>
			<fieldname>CREATEDBY_FILTER</fieldname>
			<fieldfunction>CREATEDBY.USERID</fieldfunction>
			<caption>key_created_by_user</caption>
			<filter>true</filter>
			<filteronexpand>true</filteronexpand>
			<filterlookupname>dataset;users.load;userid;username:name</filterlookupname>
		</field>
		<field>
			<fieldname>UPDATEDBY_FILTER</fieldname>
			<fieldfunction>UPDATEDBY.USERID</fieldfunction>
			<caption>key_updated_by_user</caption>
			<filter>true</filter>
			<filteronexpand>true</filteronexpand>
			<filterlookupname>dataset;users.load;userid;username:name</filterlookupname>
		</field>
		<field>
			<fieldname>CREATEDBYUNIT_FILTER</fieldname>
			<fieldfunction>CREATEDBYUNIT.OUUID</fieldfunction>
			<caption>key_created_by_unit</caption>
			<filter>true</filter>
			<filteronexpand>true</filteronexpand>
			<filterlookupname>dataset;networkmanagement.loadunits;ouuid;ouuname:ougname:oucname</filterlookupname>
		</field>
		<field>
			<fieldname>UPDATEDBYUNIT_FILTER</fieldname>
			<fieldfunction>UPDATEDBYUNIT.OUUID</fieldfunction>
			<caption>key_updated_by_unit</caption>
			<filter>true</filter>
			<filteronexpand>true</filteronexpand>
			<filterlookupname>dataset;networkmanagement.loadunits;ouuid;ouuname:ougname:oucname</filterlookupname>
		</field>
		<field>
			<fieldname>CREATEDBYUSERNAME</fieldname>
			<fieldfunction>CREATEDBY.USERNAME</fieldfunction>
			<caption>key_created_by_user</caption>
			<expand>true</expand>
		</field>
		<field>
			<fieldname>UPDATEDBYUSERNAME</fieldname>
			<fieldfunction>UPDATEDBY.USERNAME</fieldfunction>
			<caption>key_updated_by_user</caption>
			<expand>true</expand>
		</field>
		<field>
			<fieldname>CREATEDBYUNITOUUNAME</fieldname>
			<fieldfunction>CREATEDBYUNIT.OUUNAME</fieldfunction>
			<caption>key_created_by_unit</caption>
			<expand>true</expand>
		</field>
		<field>
			<fieldname>UPDATEDBYUNITOUUNAME</fieldname>
			<fieldfunction>UPDATEDBYUNIT.OUUNAME</fieldfunction>
			<caption>key_updated_by_unit</caption>
			<expand>true</expand>
		</field>
		<field>
			<fieldname>PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQCREATEDDATE</fieldname>
			<caption>key_date_created</caption>
			<expand>true</expand>
			<filter>true</filter>
			<fieldtype>date</fieldtype>
			<filtertextoption>range</filtertextoption>
			<filteronexpand>true</filteronexpand>
		</field>
		<field>
			<fieldname>PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQUPDATEDDATE</fieldname>
			<caption>key_date_updated</caption>
			<expand>true</expand>
			<filter>true</filter>
			<fieldtype>date</fieldtype>
			<filtertextoption>range</filtertextoption>
			<filteronexpand>true</filteronexpand>
		</field>
		<field>
			<fieldname>PAYGATEWAYREQERRORDESC</fieldname>
			<fieldfunction>PAYMENTGATEWAYREQUESTS.PAYGATEWAYREQERRORDESC</fieldfunction>
			<caption>key_error_description</caption>
			<expand>true</expand>
		</field>
	</fieldlist>
</summary>

...

You will need to create one data entry page for the payment gateway. For more information on creating custom data entry pages go to Customize Data Entry Pages. 

Code Block
languagexml
titlesetting.xml
linenumberstrue
collapsetrue
<?xml version="1.0" encoding="UTF-8"?><page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../xsd/dataEntry.xsd">
	<id>paymentgateway/payeezy/setting</id>
	<name/>
	<datapath>name</datapath>
	<entity></entity>	
	<module>CUSTOM_PAYEEZY</module>
	<functioncall>
		<functions>
			<function>
			</function>
		</functions>
	</functioncall>
	<datasources>
		<datasource>
			<key>form</key>
			<classname>com.crm.web.generator.datasource.DTODatasource</classname>
		</datasource>
	</datasources>
	<mainmenu>
		<components> 
			<component>
				<id>cmpHome</id>
				<name>key_home</name>
				<hideinmodal>true</hideinmodal>
				<visiblemodes>read</visiblemodes>
				<elements>
					<button>
						<id>btnHome</id>
						<name>key_home</name>
						<setmode>read</setmode>
						<refresh>page</refresh>
						<url>page.do?act=summary&amp;xml=paymentgateway/payeezy/settings</url>
					</button>
				</elements>
			</component>
			<component>
				<id>cmpNew</id>
				<name>key_new</name>
				<hideinmodal>true</hideinmodal>
				<visiblemodes>read</visiblemodes>
				<elements>
					<button>
						<id>btnNew</id>
						<name>key_new</name>
						<setmode>new</setmode>
						<refresh>page</refresh>
						<functioncall>
							<functions>
								<function>
									<type>ejb</type>
									<classname>ejb/PAYEEZYCRMUIPayeezyPaymentGatewaySetting</classname>
									<functionname>createButton</functionname>
									<resultaction>replace</resultaction>
									<datatype>root</datatype>
									<parameters>
										<parameter>
											<value>PAYEEZY</value>
											<datatype>java.lang.String</datatype>
										</parameter>
									</parameters>
								</function>
							</functions>
						</functioncall>
					</button>
				</elements>
			</component>
			<component>
				<id>cmpEdit</id>
				<name>key_edit</name>
				<visiblemodes>read</visiblemodes>
				<elements>
					<button>
						<id>btnEdit</id>
						<name>key_edit</name>
						<visibilityconditions>'[[getValue,java.lang.String,isEditable]]'!='0'</visibilityconditions>
						<setmode>edit</setmode>
						<refresh>page</refresh>
						<disableonclick>true</disableonclick>
						<functioncall>
							<functions>
								<function>
									<type>ejb</type>
									<classname>ejb/PAYEEZYCRMUIPayeezyPaymentGatewaySetting</classname>
									<functionname>editButton</functionname>
									<resultaction>replace</resultaction>
									<datatype>root</datatype>
									<parameters>
										<parameter>
											<value>[[getDTO]]</value>
											<datatype>java.lang.Object</datatype>
										</parameter>
									</parameters>
								</function>
							</functions>
						</functioncall>
					</button>
					<button>
						<id>btnEdit</id>
						<name>key_edit</name>
						<visibilityconditions>'[[getValue,java.lang.String,isEditable]]'=='0'</visibilityconditions>
						<style>TopToolbarItemsDisabled</style>
					</button>
				</elements>
			</component>
			<component>
				<id>cmpSave</id>
				<name>key_save</name>
				<visiblemodes>edit,new</visiblemodes>
				<elements>
					<button>
						<id>btnSave</id>
						<name>key_save</name>
						<setmode>read</setmode>
						<refresh>page</refresh>
						<functioncall>
							<functions>
								<function>
									<type>ejb</type>
									<classname>ejb/PAYEEZYCRMUIPayeezyPaymentGatewaySetting</classname>
									<functionname>saveButton</functionname>
									<resultaction>replace</resultaction>
									<datatype>root</datatype>
									<parameters>
										<parameter>
											<value>[[getDTO]]</value>
											<datatype>java.lang.Object</datatype>
										</parameter>
									</parameters>
								</function>
							</functions>
						</functioncall>
					</button>
				</elements>
			</component>
			<component>
				<id>cmpCancel</id>
				<name>key_cancel</name>
				<visiblemodes>edit,new</visiblemodes>
				<elements>
					<button>
						<id>btnCancel</id>
						<name>key_cancel</name>
						<setmode>read</setmode>
						<refresh>cancel,page.do?act=summary&amp;xml=paymentgateway/payeezy/settings</refresh>
					</button>
				</elements>
			</component>
		</components>
	</mainmenu>
	<main>
		<components>
		
			<component>
				<id>cmpEmpty</id>
				<elements>
					<emptyline></emptyline>
				</elements>
			</component>
			
			<component>
				<id>cmpParametersDrilldown</id>
				<name>key_parameter</name>
				<elements>
					<drilldown>
						<id>ddParameters</id>
						<tabid>tabParameters</tabid>
					</drilldown>
				</elements>
			</component>
			
			<component>
				<id>cmpParametersEmtpyDrilldown</id>
				<name/>
				<elements>
					<emptyline/>
				</elements>
			</component>
			<component>
				<id>cmpEmptyLine</id>
				<elements>
                    <emptyline/>
				</elements>
			</component> 
			<component>
				<id>cmpCurrenciesEmpty</id>
				<name/>
				<elements>
					<emptyline/>
				</elements>
			</component>
			
			<component>
				<id>cmpEmpty1</id>
				<visibilityconditions>'[[getAlias,java.lang.String,showPaymentType]]'!='1'</visibilityconditions>
				<elements>
					<emptyline></emptyline>
				</elements>
			</component>		
			
			<component>
				<id>cmpEmpty2</id>
				<visibilityconditions>'[[getAlias,java.lang.String,showRefundType]]'!='1'</visibilityconditions>
				<elements>
					<emptyline></emptyline>
				</elements>
			</component>
			
			<component>
				<id>cmpEmpty3</id>
				<elements>
					<emptyline></emptyline>
				</elements>
			</component>
			
			<component>
				<id>cmpEmpty4</id>
				<elements>
					<emptyline></emptyline>
				</elements>
			</component>
			
			<component>
				<id>cmpEmpty5</id>
				<elements>
					<emptyline></emptyline>
				</elements>
			</component>
		</components>
	</main>
	<details>
		<tabs>				
			<tab>
				<id>tabCurrencies</id>
				<name>key_currencies</name>
				<datasourcesetkey>paymentGatewayCurrencies</datasourcesetkey>
				<functioncall>
					<functions>
						<function>
							<type>ejb</type>
							<classname>ejb/PAYEEZYCRMUIPayeezyPaymentGatewaySetting</classname>
							<functionname>loadCurrenciesTab</functionname>
							<resultaction>setreplace</resultaction>
							<datapath>paymentGatewayCurrencies</datapath>
							<datasourcesetkey>paymentGatewayCurrencies</datasourcesetkey>
							<parameters>
								<parameter>
									<value>[[getDTO]]</value>
									<datatype>java.lang.Object</datatype>
								</parameter>
							</parameters>
						</function>
					</functions>
				</functioncall>
				<tabmenu>
					<components>
						<component>
							<id>cmpAdd</id>
							<name>key_add</name>
							<visiblemodes>edit,new</visiblemodes>
							<elements>
								<button>
									<id>btnAdd</id>
									<name>key_add</name>
									<refresh>tab,tabCurrencies</refresh>
									<functioncall>
										<functions>
											<function>
												<type>ejb</type>
												<classname>ejb/PAYEEZYCRMUIPayeezyPaymentGatewaySetting</classname>
												<functionname>addCurrencyButton</functionname>
												<datasourcesetkey>paymentGatewayCurrencies</datasourcesetkey>
												<resultaction>setappend</resultaction>
												<parameters>
									<parameter>
										<value>[[getDTO]]</value>
										<datatype>java.lang.Object</datatype>
									</parameter>
								</parameters>
											</function>
										</functions>
									</functioncall>
								</button>
							</elements>
						</component>
						<component>
							<id>cmpRemove</id>
							<name>key_remove</name>
							<visiblemodes>edit,new</visiblemodes>
							<elements>
								<button>
									<id>btnRemove</id>
									<name>key_remove</name>
									<refresh>tab,tabCurrencies</refresh>
									<functioncall>
										<functions>
											<function>
												<type>ejb</type>
												<classname>ejb/PAYEEZYCRMUIPayeezyPaymentGatewaySetting</classname>
												<functionname>removeCurrencyButton</functionname>
												<datasourcesetkey>paymentGatewayCurrencies</datasourcesetkey>
												<resultaction>setdelete</resultaction>
												<parameters>
													<parameter>
														<value>[[getSelectedDTOs,java.lang.String,paymentGatewayCurrencies]]</value>
														<datatype>java.lang.Object</datatype>
													</parameter>
												</parameters>
											</function>
										</functions>
									</functioncall>
								</button>
							</elements>
						</component>
					</components>
				</tabmenu>
				<components>
					<component>
						<id>cmpSelect</id>
						<name/>
						<elements>
							<rowselector>
								<id>rowID</id>
								<datapath>id</datapath>
							</rowselector>
						</elements>
					</component>
					<component>
						<id>cmpCurrency</id>
						<name>key_currency</name>
						<elements>
							<selectbox>
								<id>slbCurrency</id>
								<lookuptype>ejb</lookuptype>
								<datapath>currency</datapath>
								<datapathid>id</datapathid>
								<classname>com.crm.dataobject.platform.CRMDOCurrency</classname>
								<datatype>load</datatype>
								<reload>true</reload>
								<refresh>page</refresh>
								<onload>
									<type>ejb</type>
									<classname>ejb/CRMUIPaymentGatewaySetting</classname>
									<functionname>getCurrencyCodeOptions</functionname>
									<parameters>
										<parameter>
											<value>[[getDTO]]</value>
											<datatype>java.lang.Object</datatype>
										</parameter>
									</parameters>
								</onload>
							</selectbox>
						</elements>
					</component>
				</components>
			</tab>	
			
			<tab>
				<id>tabParameters</id>
				<rowvisibilityconditions>'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/isVisible]]'==1</rowvisibilityconditions>
				<name>key_parameters</name>
				<datasourcesetkey>gatewayParameters</datasourcesetkey>
				<functioncall>
					<functions>
						<function>
							<type>ejb</type>
							<classname>ejb/PAYEEZYCRMUIPayeezyPaymentGatewaySetting</classname>
							<functionname>loadParametersTab</functionname>
							<resultaction>setreplace</resultaction>
							<datapath>gatewayParameters</datapath>
							<datasourcesetkey>gatewayParameters</datasourcesetkey>
							<datasortby>order,asc</datasortby>
							<parameters>
								<parameter>
									<value>[[getDTO]]</value>
									<datatype>java.lang.Object</datatype>
								</parameter>
							</parameters>
						</function> 
						<function>
							<type>ejb</type>
							<classname>ejb/PAYEEZYCRMUIPayeezyPaymentGatewaySetting</classname>
							<functionname>echoDTOs</functionname>
							<resultaction>setoverwrite</resultaction>
							<datasourcesetkey>gatewayParameters</datasourcesetkey>
							<datasortby>order,asc</datasortby>
							<parameters>
								<parameter>
									<value>[[getAllDTOs,java.lang.String,gatewayParameters]]</value>
									<datatype>java.lang.Object</datatype>
								</parameter>
							</parameters>
						</function>
					</functions>
				</functioncall>
				<tabmenu>
					<components>
					</components>
				</tabmenu>
				<components>
					<component>
						<id>cmpSelect</id>
						<name/>
						<elements>
							<rowselector>
								<id>rowID</id>
								<datapath>id</datapath>
							</rowselector>
						</elements>
					</component>
					<component>
						<id>cmpParameter</id>
						<name>key_parameter</name>
						<elements>
							<textbox>
								<id>txtParameter</id>
								<datapath>parameter/name</datapath>
								<readonly>true</readonly>
								<datatype>alias</datatype>
							</textbox>
						</elements>
					</component>
					<component>
						<id>cmpValue</id>
						<name>key_value</name>
						<elements>
							<textbox>
								<visibilityconditions>
									'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/type]]'=='String' &amp;&amp;
									('[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/parameter/name]]'=='TEST_MERCHANT_TOKEN' ||
									'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/parameter/name]]'=='TEST_URL' || 
									'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/parameter/name]]'=='TEST_TA_TOKEN' ||
									'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/parameter/name]]'=='TEST_API_KEY' ||
									'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/parameter/name]]'=='LIVE_MERCHANT_TOKEN' ||
									'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/parameter/name]]'=='LIVE_URL' || 
									'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/parameter/name]]'=='LIVE_TA_TOKEN' ||
									'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/parameter/name]]'=='LIVE_API_KEY') 
								</visibilityconditions>
								<id>txtValue</id>
								<datapath>value/stringValue</datapath>
								<width>50%</width>
							</textbox>
							<selectbox>
								<id>slbMode</id>
								<visibilityconditions>
									'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/type]]'=='String' &amp;&amp;
									'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/parameter/name]]'=='MODE' 
								</visibilityconditions>
								<lookuptype>ejb</lookuptype>
								<datapath>value/stringValue</datapath>
								<datatype>enum</datatype> 
								<classname>com.crm.dataobject.paymentgateway.braintree.BraintreeMode</classname>
								<refresh>section,secAuthenticationSettings</refresh>
								<onload>
									<type>ejb</type>
									<classname>ejb/PAYEEZYCRMUIPayeezyPaymentGatewaySetting</classname>
									<functionname>getModeOptions</functionname>
								</onload>
								<onchange>
									<functions>
										<function>
											<type>ejb</type>
											<classname>ejb/PAYEEZYCRMUIPayeezyPaymentGatewaySetting</classname>
											<functionname>setParametersVisibility</functionname>
											<resultaction>replace</resultaction>
											<datatype>root</datatype>
											<parameters>
												<parameter>
													<value>[[getDTO]]</value>
													<datatype>java.lang.Object</datatype>
												</parameter>
											</parameters>
										</function>
								</functions>
							</onchange>
								<width>50%</width>
							</selectbox>
							<password>
								<visibilityconditions>
									'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/type]]'=='String' &amp;&amp;
									('[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/parameter/name]]'=='TEST_API_SECRET' ||
									'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/parameter/name]]'=='TEST_JS_SECURITY_KEY' ||
									'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/parameter/name]]'=='LIVE_API_SECRET' ||
									'[[getValue,java.lang.String,gatewayParameters[CURRENT_ROW]/parameter/name]]'=='LIVE_JS_SECURITY_KEY')
								</visibilityconditions>
								<id>pswPassword</id>
								<datapath>value/stringValue</datapath>
								<datatype>java.lang.String</datatype>
								<width>50%</width>
							</password>							
						</elements>
					</component>
				</components>
			</tab>
		</tabs>
	</details>
</page>

...