blob: c8f81aa1e9c27c50c20ce1c1bf344269d58ce2ef [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.apache.ofbiz.accounting.thirdparty.worldpay;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.UtilDateTime;
import org.apache.ofbiz.base.util.UtilFormatOut;
import org.apache.ofbiz.base.util.UtilHttp;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilProperties;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.transaction.GenericTransactionException;
import org.apache.ofbiz.entity.transaction.TransactionUtil;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.entity.util.EntityUtilProperties;
import org.apache.ofbiz.order.order.OrderChangeHelper;
import org.apache.ofbiz.product.store.ProductStoreWorker;
import org.apache.ofbiz.service.GenericServiceException;
import org.apache.ofbiz.service.LocalDispatcher;
import org.apache.ofbiz.service.ModelService;
/**
* WorldPay Select Junior Integration Events/Services
*/
public class WorldPayEvents {
public static final String resource = "AccountingUiLabels";
public static final String resourceErr = "AccountingErrorUiLabels";
public static final String commonResource = "CommonUiLabels";
public static final String module = WorldPayEvents.class.getName();
public static String worldPayRequest(HttpServletRequest request, HttpServletResponse response) {
Locale locale = UtilHttp.getLocale(request);
Delegator delegator = (Delegator) request.getAttribute("delegator");
// get the orderId from the request, stored by previous event(s)
String orderId = (String) request.getAttribute("orderId");
// get the order header
GenericValue orderHeader = null;
try {
orderHeader = EntityQuery.use(delegator).from("OrderHeader").where("orderId", orderId).queryOne();
} catch (GenericEntityException e) {
Debug.logError(e, "Cannot get the order header for order: " + orderId, module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "worldPayEvents.problemsGettingOrderHeader", locale));
return "error";
}
// get the order total
String orderTotal = orderHeader.getBigDecimal("grandTotal").toPlainString();
// 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, "worldPayEvents.problemsGettingMerchantConfiguration", locale));
return "error";
}
// get the payment properties file
GenericValue paymentConfig = ProductStoreWorker.getProductStorePaymentSetting(delegator, productStore.getString("productStoreId"), "EXT_WORLDPAY", 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 redirectURL = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "redirectUrl", configString, "payment.worldpay.redirectUrl", "");
String instId = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "instId", configString, "payment.worldpay.instId", "NONE");
String authMode = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "authMode", configString, "payment.worldpay.authMode", "A");
String fixContact = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "fixContact", configString, "payment.worldpay.fixContact", "N");
String hideContact = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "hideContact", configString, "payment.worldpay.hideContact", "N");
String hideCurrency = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "hideCurrency", configString, "payment.worldpay.hideCurrency", "N");
String langId = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "langId", configString, "payment.worldpay.langId", "");
String noLanguageMenu = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "noLanguageMenu", configString, "payment.worldpay.noLanguageMenu", "N");
String withDelivery = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "withDelivery", configString, "payment.worldpay.withDelivery", "N");
String testMode = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "testMode", configString, "payment.worldpay.testMode", "100");
// get the contact address to pass over
GenericValue contactAddress = null;
GenericValue contactAddressShip = null;
GenericValue addressOcm = null;
GenericValue shippingAddress = null;
try {
addressOcm = EntityQuery.use(delegator).from("OrderContactMech").where("orderId", orderId, "contactMechPurposeTypeId", "BILLING_LOCATION").queryFirst();
shippingAddress = EntityQuery.use(delegator).from("OrderContactMech").where("orderId", orderId, "contactMechPurposeTypeId", "SHIPPING_LOCATION").queryFirst();
if (addressOcm == null) {
addressOcm = shippingAddress;
}
contactAddress = EntityQuery.use(delegator).from("PostalAddress").where("contactMechId", addressOcm.getString("contactMechId")).queryOne();
} catch (GenericEntityException e) {
Debug.logWarning(e, "Problems getting order contact information", module);
}
// get the country geoID
GenericValue countryGeo = null;
String country = "";
if (contactAddress != null) {
try {
countryGeo = contactAddress.getRelatedOne("CountryGeo", false);
if (countryGeo != null) {
country = countryGeo.getString("geoCode");
}
} catch (GenericEntityException e) {
Debug.logWarning(e, "Problems getting country geo entity", module);
}
}
// string of customer's name
String name = "";
if (contactAddress != null) {
if (UtilValidate.isNotEmpty(contactAddress.getString("attnName")))
name = contactAddress.getString("attnName");
else if (UtilValidate.isNotEmpty(contactAddress.getString("toName")))
name = contactAddress.getString("toName");
}
// build an address string
StringBuilder address = new StringBuilder();
String postalCode = "";
if (contactAddress != null) {
if (contactAddress.get("address1") != null) {
address.append(contactAddress.getString("address1").trim());
}
if (contactAddress.get("address2") != null) {
if (address.length() > 0) {
address.append("
");
}
address.append(contactAddress.getString("address2").trim());
}
if (contactAddress.get("city") != null) {
if (address.length() > 0) {
address.append("
");
}
address.append(contactAddress.getString("city").trim());
}
if (contactAddress.get("stateProvinceGeoId") != null) {
if (contactAddress.get("city") != null) {
address.append(", ");
}
address.append(contactAddress.getString("stateProvinceGeoId").trim());
}
if (contactAddress.get("postalCode") != null) {
postalCode = contactAddress.getString("postalCode");
}
}
// get the email address to pass over
String emailAddress = null;
GenericValue emailContact = null;
try {
GenericValue emailOcm = EntityQuery.use(delegator).from("OrderContactMech").where("orderId", orderId, "contactMechPurposeTypeId", "ORDER_EMAIL").queryFirst();
emailContact = emailOcm.getRelatedOne("ContactMech", false);
emailAddress = emailContact.getString("infoString");
} catch (GenericEntityException e) {
Debug.logWarning(e, "Problems getting order email address", module);
}
// build an shipping address string
StringBuilder shipAddress = new StringBuilder();
String shipPostalCode = "";
String shipName = "";
if (shippingAddress != null) {
try {
contactAddressShip = EntityQuery.use(delegator).from("PostalAddress").where("contactMechId", shippingAddress.get("contactMechId")).queryOne();
if (UtilValidate.isNotEmpty(contactAddressShip)) {
if (UtilValidate.isNotEmpty(contactAddressShip.getString("attnName"))) {
shipName = contactAddressShip.getString("attnName");
} else if (UtilValidate.isNotEmpty(contactAddressShip.getString("toName"))) {
shipName = contactAddressShip.getString("toName");
}
if (contactAddressShip.get("address1") != null) {
shipAddress.append(contactAddressShip.getString("address1").trim());
}
if (contactAddressShip.get("address2") != null) {
if (shipAddress.length() > 0) {
shipAddress.append("
");
}
shipAddress.append(contactAddressShip.getString("address2").trim());
}
if (contactAddressShip.get("city") != null) {
if (shipAddress.length() > 0) {
shipAddress.append("
");
}
shipAddress.append(contactAddressShip.getString("city").trim());
}
if (contactAddressShip.get("stateProvinceGeoId") != null) {
if (contactAddressShip.get("city") != null) {
shipAddress.append(", ");
}
shipAddress.append(contactAddressShip.getString("stateProvinceGeoId").trim());
}
if (contactAddressShip.get("postalCode") != null) {
shipPostalCode = contactAddressShip.getString("postalCode");
}
}
} catch (GenericEntityException e) {
Debug.logWarning(e, "Problems getting shipping address", module);
}
}
// get the company name
String company = UtilFormatOut.checkEmpty(productStore.getString("companyName"), "");
// get the currency
String defCur = UtilFormatOut.checkEmpty(productStore.getString("defaultCurrencyUomId"), "USD");
// order description
String description = UtilProperties.getMessage(resource, "AccountingOrderNr", locale) + orderId + " " +
(company != null ? UtilProperties.getMessage(commonResource, "CommonFrom", locale) + " "+ company : "");
// check the instId - very important
if (instId == null || instId.equals("NONE")) {
Debug.logError("Worldpay InstId not found, cannot continue", module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "worldPayEvents.problemsGettingInstId", locale));
return "error";
}
try {
Integer.parseInt(instId);
} catch (NumberFormatException nfe) {
Debug.logError(nfe, "Problem converting instId string to integer", module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "worldPayEvents.problemsGettingInstIdToInteger", locale));
return "error";
}
// check the testMode
if (testMode != null) {
try {
Integer.parseInt(testMode);
} catch (NumberFormatException nfe) {
Debug.logWarning(nfe, "Problems getting the testMode value, setting to 0", module);
}
}
// create the redirect string
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("instId", instId);
parameters.put("cartId", orderId);
parameters.put("currency", defCur);
parameters.put("amount", orderTotal);
parameters.put("desc", description);
parameters.put("testMode", testMode);
parameters.put("authMode", authMode);
parameters.put("name", name);
parameters.put("address", address.toString());
parameters.put("country", country);
parameters.put("postcode", postalCode);
parameters.put("email", emailAddress);
if (UtilValidate.isNotEmpty(shipName)) {
parameters.put("M_shipping_name", shipName);
if (UtilValidate.isNotEmpty(shipAddress.toString())) {
parameters.put("M_shipping_address", shipAddress.toString());
}
if (UtilValidate.isNotEmpty(shipPostalCode)) {
parameters.put("M_shipping_postcode", shipPostalCode);
}
}
if ("Y".equals(fixContact)) {
parameters.put("fixContact", "");
}
if ("Y".equals(hideContact)) {
parameters.put("hideContact", "");
}
if ("Y".equals(hideCurrency)) {
parameters.put("hideCurrency", "");
}
if ("Y".equals(noLanguageMenu)) {
parameters.put("noLanguageMenu", "");
}
if ("Y".equals(withDelivery)) {
parameters.put("withDelivery", "");
}
if (UtilValidate.isNotEmpty(langId)) {
parameters.put("langId", langId);
}
// create the redirect URL
String encodedParameters = UtilHttp.urlEncodeArgs(parameters, false);
String redirectString = redirectURL + "?" + encodedParameters;
// redirect to WorldPay
try {
response.sendRedirect(redirectString);
} catch (IOException e) {
Debug.logError(e, "Problems redirecting to WorldPay", module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "worldPayEvents.problemsConnectingWithWorldPay", locale));
return "error";
}
return "success";
}
/** WorldPay notification */
public static String worldPayNotify(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 orderId = request.getParameter("cartId");
for (String name : parametersMap.keySet()) {
String value = request.getParameter(name);
Debug.logError("### Param: " + name + " => " + value, module);
}
// get the user
if (userLogin == null) {
String userLoginId = "system";
try {
userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", userLoginId).queryOne();
} catch (GenericEntityException e) {
Debug.logError(e, "Cannot get UserLogin for: " + userLoginId + "; cannot continue", module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "worldPayEvents.problemsGettingAuthenticationUser", locale));
return "error";
}
}
// get the order header
GenericValue orderHeader = null;
if (UtilValidate.isNotEmpty(orderId)) {
try {
orderHeader = EntityQuery.use(delegator).from("OrderHeader").where("orderId", orderId).queryOne();
} catch (GenericEntityException e) {
Debug.logError(e, "Cannot get the order header for order: " + orderId, module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "worldPayEvents.problemsGettingOrderHeader", locale));
return "error";
}
} else {
Debug.logError("WorldPay did not callback with a valid orderId!", module);
request.setAttribute("_ERROR_MESSAGE_", UtilProperties.getMessage(resourceErr, "worldPayEvents.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, "worldPayEvents.problemsGettingOrderHeader", locale));
return "error";
}
// get the transaction status
String paymentStatus = request.getParameter("transStatus");
// attempt to start a transaction
boolean okay = true;
boolean beganTransaction = false;
try {
beganTransaction = TransactionUtil.begin();
// authorized
if ("Y".equals(paymentStatus)) {
okay = OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId);
// cancelled
} else if ("C".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 WorldPay 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 WorldPay 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) {
// attempt to release the offline hold on the order (workflow)
OrderChangeHelper.releaseInitialOrderHold(dispatcher, orderId);
// call the email confirm service
Map<String, Object> 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 preferences..", module);
List<GenericValue> paymentPrefs = null;
try {
paymentPrefs = EntityQuery.use(delegator).from("OrderPaymentPreference")
.where("orderId", orderId, "statusId", "PAYMENT_NOT_RECEIVED").queryList();
} 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 paymentStatus = request.getParameter("transStatus");
String paymentAmount = request.getParameter("authAmount");
Long paymentDate = new Long(request.getParameter("transTime"));
String transactionId = request.getParameter("transId");
String gatewayFlag = request.getParameter("rawAuthCode");
String avs = request.getParameter("AVS");
List<GenericValue> toStore = new LinkedList<GenericValue>();
java.sql.Timestamp authDate = null;
try {
authDate = new java.sql.Timestamp(paymentDate.longValue());
} catch (Exception e) {
Debug.logError(e, "Cannot create date from long: " + paymentDate, module);
authDate = UtilDateTime.nowTimestamp();
}
paymentPreference.set("maxAmount", new BigDecimal(paymentAmount));
if ("Y".equals(paymentStatus)) {
paymentPreference.set("statusId", "PAYMENT_RECEIVED");
} else if ("C".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("referenceNum", transactionId);
response.set("gatewayCode", paymentStatus);
response.set("gatewayFlag", gatewayFlag);
response.set("transactionDate", authDate);
response.set("gatewayAvsResult", avs);
response.set("gatewayCvResult", avs.substring(0, 1));
toStore.add(response);
try {
delegator.storeAll(toStore);
} catch (GenericEntityException e) {
Debug.logError(e, "Cannot set payment preference/payment info", module);
return false;
}
// create a payment record too
Map<String, Object> results = null;
try {
String comment = UtilProperties.getMessage(resource, "AccountingPaymentReceiveViaWorldPay", locale);
results = dispatcher.runSync("createPaymentFromPreference", UtilMisc.toMap("userLogin", userLogin,
"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, "worldPayEvents.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_", (String) 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 worldPay = EntityQuery.use(delegator).from("PaymentGatewayWorldPay").where("paymentGatewayConfigId", paymentGatewayConfigId).queryOne();
if (UtilValidate.isNotEmpty(worldPay)) {
Object worldPayField = worldPay.get(paymentGatewayConfigParameterName);
if (worldPayField != null) {
returnValue = worldPayField.toString().trim();
}
}
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
} else {
String value = EntityUtilProperties.getPropertyValue(resource, parameterName, delegator);
if (value != null) {
returnValue = value.trim();
}
}
return returnValue;
}
private static String getPaymentGatewayConfigValue(Delegator delegator, String paymentGatewayConfigId, String paymentGatewayConfigParameterName,
String resource, String parameterName, String defaultValue) {
String returnValue = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, paymentGatewayConfigParameterName, resource, parameterName);
if (UtilValidate.isEmpty(returnValue)) {
returnValue = defaultValue;
}
return returnValue;
}
}