blob: 21618dd3432e195c0224d21d40cb7dfeb8012519 [file] [log] [blame]
/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*******************************************************************************/
package org.ofbiz.accounting.thirdparty.ideal;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javolution.util.FastList;
import javolution.util.FastMap;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilHttp;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilNumber;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.transaction.GenericTransactionException;
import org.ofbiz.entity.transaction.TransactionUtil;
import org.ofbiz.order.order.OrderChangeHelper;
import org.ofbiz.product.store.ProductStoreWorker;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ModelService;
import com.ing.ideal.connector.IdealConnector;
import com.ing.ideal.connector.IdealException;
import com.ing.ideal.connector.Issuer;
import com.ing.ideal.connector.Issuers;
import com.ing.ideal.connector.Transaction;
public class IdealEvents {
public static final String resource = "AccountingUiLabels";
public static final String resourceErr = "AccountingErrorUiLabels";
public static final String commonResource = "CommonUiLabels";
public static final String module = IdealEvents.class.getName();
private static int decimals = UtilNumber.getBigDecimalScale("invoice.decimals");
private static int rounding = UtilNumber.getBigDecimalRoundingMode("invoice.rounding");
/** Initiate iDEAL Request */
public static String callIdeal(HttpServletRequest request, HttpServletResponse response) {
Locale locale = UtilHttp.getLocale(request);
Delegator delegator = (Delegator) request.getAttribute("delegator");
// get the orderId
String orderId = (String) request.getAttribute("orderId");
String issuerId = (String) request.getAttribute("issuerId");
// get the order header
GenericValue orderHeader = null;
List<GenericValue> orderItemList = null;
try {
orderHeader = delegator.findOne("OrderHeader", UtilMisc.toMap("orderId", orderId), false);
orderItemList = delegator.findByAnd("OrderItem", UtilMisc.toMap("orderId", orderId));
} catch (GenericEntityException e) {
Debug.logError(e, "Cannot get the order header for order: " + orderId, module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.problemsGettingOrderHeader", locale));
return "error";
}
// get the order total
BigDecimal orderTotal = orderHeader.getBigDecimal("grandTotal");
// get the product store
GenericValue productStore = ProductStoreWorker.getProductStore(request);
if (productStore == null) {
Debug.logError("ProductStore is null", module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.problemsGettingMerchantConfiguration", locale));
return "error";
}
// get the payment properties file
GenericValue paymentConfig = ProductStoreWorker.getProductStorePaymentSetting(delegator, productStore.getString("productStoreId"), "EXT_IDEAL", null, true);
String configString = null;
String paymentGatewayConfigId = null;
if (paymentConfig != null) {
paymentGatewayConfigId = paymentConfig.getString("paymentGatewayConfigId");
configString = paymentConfig.getString("paymentPropertiesPath");
}
if (configString == null) {
configString = "payment.properties";
}
String merchantId = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "merchantId", configString, "merchantId");
String merchantSubId = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "merchantSubId", configString, "merchantSubId");
String merchantReturnURL = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "merchantReturnURL", configString, "merchantReturnURL");
String acquirerURL = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "acquirerURL", configString, "acquirerURL");
String acquirerTimeout = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "acquirerTimeout", configString, "acquirerTimeout");
String privateCert = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "privateCert", configString, "privateCert");
String acquirerKeyStoreFilename = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "acquirerKeyStoreFilename", configString, "acquirerKeyStoreFilename");
String acquirerKeyStorePassword = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "acquirerKeyStorePassword", configString, "acquirerKeyStorePassword");
String merchantKeyStoreFilename = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "merchantKeyStoreFilename", configString, "merchantKeyStoreFilename");
String merchantKeyStorePassword = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "merchantKeyStorePassword", configString, "merchantKeyStorePassword");
String expirationPeriod = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "expirationPeriod", configString, "expirationPeriod");
if (UtilValidate.isEmpty(merchantId)
|| UtilValidate.isEmpty(merchantReturnURL)
|| UtilValidate.isEmpty(privateCert)
|| UtilValidate.isEmpty(merchantKeyStoreFilename)
|| UtilValidate.isEmpty(merchantKeyStoreFilename)) {
Debug.logError("Payment properties is not configured properly, some notify URL from iDEAL is not correctly defined!", module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.problemsGettingMerchantConfiguration", locale));
return "error";
}
List<String> descriptionList = FastList.newInstance();
for (GenericValue orderItem : orderItemList) {
if (UtilValidate.isNotEmpty(orderItem.get("itemDescription"))){
descriptionList.add((String) orderItem.get("itemDescription"));
}
}
String orderDescription = StringUtil.join(descriptionList, ",");
String amount = orderTotal.setScale(decimals, rounding).movePointRight(2).toPlainString();
String redirectString = null;
try {
IdealConnector connector = new IdealConnector("payment");
Transaction transaction = new Transaction();
transaction.setIssuerID(issuerId);
transaction.setAmount(amount);
transaction.setPurchaseID(orderId);
transaction.setDescription(orderDescription);
String returnURL = merchantReturnURL + "?orderId=" + orderId;
Random random = new Random();
String EntranceCode = Long.toString(Math.abs(random.nextLong()), 36);
transaction.setEntranceCode(EntranceCode);
transaction.setMerchantReturnURL(returnURL);
Transaction trx = connector.requestTransaction(transaction);
redirectString = trx.getIssuerAuthenticationURL();
request.getSession().setAttribute("purchaseID", orderId);
request.getSession().setAttribute("payAmount", orderTotal.toPlainString());
} catch (IdealException ex) {
Debug.logError(ex.getMessage(), module);
request.setAttribute("_ERROR_MESSAGE_", ex.getConsumerMessage());
return "error";
}
// redirect to iDEAL
try {
response.sendRedirect(redirectString);
} catch (IOException e) {
Debug.logError(e, "Problems redirecting to iDEAL", module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.problemsConnectingWithIdeal", locale));
return "error";
}
return "success";
}
/** iDEAL notification */
public static String idealNotify(HttpServletRequest request, HttpServletResponse response) {
Locale locale = UtilHttp.getLocale(request);
Delegator delegator = (Delegator) request.getAttribute("delegator");
LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
GenericValue userLogin = (GenericValue) request.getSession().getAttribute("userLogin");
Map <String, Object> parametersMap = UtilHttp.getParameterMap(request);
String transactionId = request.getParameter("trxid");
for(String name : parametersMap.keySet()) {
String value = request.getParameter(name);
Debug.logError("### Param: " + name + " => " + value, module);
}
String orderId = null;
String paymentStatus = null;
try {
IdealConnector connector = new IdealConnector("payment");
Transaction transaction = connector.requestTransactionStatus(transactionId);
orderId = transaction.getPurchaseID();
if (orderId == null) {
orderId = (String) request.getSession().getAttribute("purchaseID");
}
String payAmount = transaction.getAmount();
if (payAmount == null) {
payAmount = (String) request.getSession().getAttribute("payAmount");
}
paymentStatus = transaction.getStatus();
request.setAttribute("transactionId", transactionId);
request.setAttribute("paymentStatus", paymentStatus);
request.setAttribute("paymentAmount", payAmount);
} catch (IdealException ex) {
Debug.logError(ex.getMessage(), module);
request.setAttribute("_ERROR_MESSAGE_", ex.getConsumerMessage());
return "error";
}
// get the user
if (userLogin == null) {
String userLoginId = "system";
try {
userLogin = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", userLoginId), false);
} catch (GenericEntityException e) {
Debug.logError(e, "Cannot get UserLogin for: " + userLoginId + "; cannot continue", module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.problemsGettingAuthenticationUser", locale));
return "error";
}
}
// get the order header
GenericValue orderHeader = null;
if (UtilValidate.isNotEmpty(orderId)) {
try {
orderHeader = delegator.findOne("OrderHeader", UtilMisc.toMap("orderId", orderId), false);
} catch (GenericEntityException e) {
Debug.logError(e, "Cannot get the order header for order: " + orderId, module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.problemsGettingOrderHeader", locale));
return "error";
}
} else {
Debug.logError("iDEAL did not callback with a valid orderId!", module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.noValidOrderIdReturned", locale));
return "error";
}
if (orderHeader == null) {
Debug.logError("Cannot get the order header for order: " + orderId, module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.problemsGettingOrderHeader", locale));
return "error";
}
// attempt to start a transaction
boolean okay = true;
boolean beganTransaction = false;
try {
beganTransaction = TransactionUtil.begin();
// authorized
if ("Success".equals(paymentStatus)) {
okay = OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId);
// cancelled
} else if ("Cancelled".equals(paymentStatus)) {
okay = OrderChangeHelper.cancelOrder(dispatcher, userLogin, orderId);
}
if (okay) {
// set the payment preference
okay = setPaymentPreferences(delegator, dispatcher, userLogin, orderId, request);
}
} catch (Exception e) {
String errMsg = "Error handling iDEAL notification";
Debug.logError(e, errMsg, module);
try {
TransactionUtil.rollback(beganTransaction, errMsg, e);
} catch (GenericTransactionException gte2) {
Debug.logError(gte2, "Unable to rollback transaction", module);
}
} finally {
if (!okay) {
try {
TransactionUtil.rollback(beganTransaction, "Failure in processing iDEAL callback", null);
} catch (GenericTransactionException gte) {
Debug.logError(gte, "Unable to rollback transaction", module);
}
} else {
try {
TransactionUtil.commit(beganTransaction);
} catch (GenericTransactionException gte) {
Debug.logError(gte, "Unable to commit transaction", module);
}
}
}
if (okay) {
request.setAttribute("_EVENT_MESSAGE_", UtilProperties.getMessage(resource, "IdealSuccessful", locale));
// attempt to release the offline hold on the order (workflow)
OrderChangeHelper.releaseInitialOrderHold(dispatcher, orderId);
// call the email confirm service
Map<String, String> emailContext = UtilMisc.toMap("orderId", orderId, "userLogin", userLogin);
try {
dispatcher.runSync("sendOrderConfirmation", emailContext);
} catch (GenericServiceException e) {
Debug.logError(e, "Problems sending email confirmation", module);
}
}
return "success";
}
private static boolean setPaymentPreferences(Delegator delegator, LocalDispatcher dispatcher, GenericValue userLogin, String orderId, HttpServletRequest request) {
Debug.logVerbose("Setting payment prefrences..", module);
List <GenericValue> paymentPrefs = null;
try {
Map <String, String> paymentFields = UtilMisc.toMap("orderId", orderId, "statusId", "PAYMENT_NOT_RECEIVED");
paymentPrefs = delegator.findByAnd("OrderPaymentPreference", paymentFields);
} catch (GenericEntityException e) {
Debug.logError(e, "Cannot get payment preferences for order #" + orderId, module);
return false;
}
if (paymentPrefs.size() > 0) {
for(GenericValue pref : paymentPrefs) {
boolean okay = setPaymentPreference(dispatcher, userLogin, pref, request);
if (!okay)
return false;
}
}
return true;
}
private static boolean setPaymentPreference(LocalDispatcher dispatcher, GenericValue userLogin, GenericValue paymentPreference, HttpServletRequest request) {
Locale locale = UtilHttp.getLocale(request);
String paymentAmount = (String) request.getAttribute("paymentAmount");
String paymentStatus = (String) request.getAttribute("paymentStatus");
String transactionId = (String) request.getAttribute("transactionId");
List <GenericValue> toStore = new LinkedList <GenericValue> ();
java.sql.Timestamp authDate = UtilDateTime.nowTimestamp();
paymentPreference.set("maxAmount", new BigDecimal(paymentAmount));
if ("Success".equals(paymentStatus)) {
paymentPreference.set("statusId", "PAYMENT_RECEIVED");
} else if ("Cancelled".equals(paymentStatus)) {
paymentPreference.set("statusId", "PAYMENT_CANCELLED");
} else {
paymentPreference.set("statusId", "PAYMENT_NOT_RECEIVED");
}
toStore.add(paymentPreference);
Delegator delegator = paymentPreference.getDelegator();
// create the PaymentGatewayResponse
String responseId = delegator.getNextSeqId("PaymentGatewayResponse");
GenericValue response = delegator.makeValue("PaymentGatewayResponse");
response.set("paymentGatewayResponseId", responseId);
response.set("paymentServiceTypeEnumId", "PRDS_PAY_EXTERNAL");
response.set("orderPaymentPreferenceId", paymentPreference.get("orderPaymentPreferenceId"));
response.set("paymentMethodTypeId", paymentPreference.get("paymentMethodTypeId"));
response.set("paymentMethodId", paymentPreference.get("paymentMethodId"));
// set the auth info
response.set("amount", new BigDecimal(paymentAmount));
response.set("currencyUomId", "EUR");
response.set("referenceNum", transactionId);
response.set("gatewayCode", paymentStatus);
response.set("gatewayFlag", paymentStatus.substring(0,1));
response.set("transactionDate", authDate);
toStore.add(response);
try {
delegator.storeAll(toStore);
} catch (GenericEntityException e) {
Debug.logError(e, "Cannot set payment preference/payment info", module);
return false;
}
GenericValue userLoginId = null;
try {
userLoginId = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", "system"), false);
} catch (GenericEntityException e) {
return false;
}
// create a payment record too
Map <String, Object> results = null;
try {
String comment = UtilProperties.getMessage(resource, "AccountingPaymentReceiveViaiDEAL", locale);
results = dispatcher.runSync("createPaymentFromPreference", UtilMisc.toMap("userLogin", userLoginId,
"orderPaymentPreferenceId", paymentPreference.get("orderPaymentPreferenceId"), "comments", comment));
} catch (GenericServiceException e) {
Debug.logError(e, "Failed to execute service createPaymentFromPreference", module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "idealEvents.failedToExecuteServiceCreatePaymentFromPreference", locale));
return false;
}
if ((results == null) || (results.get(ModelService.RESPONSE_MESSAGE).equals(ModelService.RESPOND_ERROR))) {
Debug.logError((String) results.get(ModelService.ERROR_MESSAGE), module);
request.setAttribute("_ERROR_MESSAGE_", results.get(ModelService.ERROR_MESSAGE));
return false;
}
return true;
}
private static String getPaymentGatewayConfigValue(Delegator delegator, String paymentGatewayConfigId, String paymentGatewayConfigParameterName,
String resource, String parameterName) {
String returnValue = "";
if (UtilValidate.isNotEmpty(paymentGatewayConfigId)) {
try {
GenericValue ideal = delegator.findOne("PaymentGatewayiDEAL", UtilMisc.toMap("paymentGatewayConfigId", paymentGatewayConfigId), false);
if (UtilValidate.isNotEmpty(ideal)) {
Object idealField = ideal.get(paymentGatewayConfigParameterName);
if (idealField != null) {
returnValue = idealField.toString().trim();
}
}
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
} else {
String value = UtilProperties.getPropertyValue(resource, parameterName);
if (value != null) {
returnValue = value.trim();
}
}
return returnValue;
}
public static List<Issuer> getIssuerList() {
List<Issuer> issuerList = FastList.newInstance();
try {
IdealConnector connector = new IdealConnector("payment");
Issuers issuers = connector.getIssuerList();
List<Issuer> shortList = issuers.getShortList();
List<Issuer> longList = issuers.getLongList();
for (Iterator<Issuer> iter = shortList.iterator(); iter.hasNext();) {
Issuer issuer = (Issuer) iter.next();
issuerList.add(issuer);
}
for (Iterator<Issuer> iter = longList.iterator(); iter.hasNext();) {
Issuer issuer = (Issuer) iter.next();
issuerList.add(issuer);
}
} catch (IdealException ex){
Debug.logError(ex.getMessage(), module);
}
return issuerList;
}
}