in applications/order/src/main/java/org/apache/ofbiz/order/shoppingcart/CheckOutHelper.java [1095:1350]
public static Map<String, Object> processPayment(String orderId, BigDecimal orderTotal, String currencyUomId, GenericValue productStore,
GenericValue userLogin, boolean faceToFace, boolean manualHold, LocalDispatcher dispatcher, Delegator delegator)
throws GeneralException {
// Get some payment related strings
String declineMessage = productStore.getString("authDeclinedMessage");
String errMessage = productStore.getString("authErrorMessage");
String retryOnError = productStore.getString("retryFailedAuths");
if (retryOnError == null) {
retryOnError = "Y";
}
List<GenericValue> allPaymentPreferences = null;
try {
allPaymentPreferences = EntityQuery.use(delegator).from("OrderPaymentPreference").where("orderId", orderId).queryList();
} catch (GenericEntityException e) {
throw new GeneralException("Problems getting payment preferences", e);
}
// filter out cancelled preferences
List<EntityExpr> canExpr = UtilMisc.toList(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "PAYMENT_CANCELLED"));
allPaymentPreferences = EntityUtil.filterByAnd(allPaymentPreferences, canExpr);
// check for online payment methods or in-hand payment types with verbal or external refs
List<EntityExpr> exprs = UtilMisc.toList(EntityCondition.makeCondition("manualRefNum", EntityOperator.NOT_EQUAL, null));
List<GenericValue> manualRefPaymentPrefs = EntityUtil.filterByAnd(allPaymentPreferences, exprs);
if (UtilValidate.isNotEmpty(manualRefPaymentPrefs)) {
for (GenericValue opp : manualRefPaymentPrefs) {
Map<String, Object> authCtx = new HashMap<>();
authCtx.put("orderPaymentPreference", opp);
if (opp.get("paymentMethodId") == null) {
authCtx.put("serviceTypeEnum", "PRDS_PAY_EXTERNAL");
}
authCtx.put("processAmount", opp.getBigDecimal("maxAmount"));
authCtx.put("authRefNum", opp.getString("manualRefNum"));
authCtx.put("authResult", Boolean.TRUE);
authCtx.put("userLogin", userLogin);
authCtx.put("currencyUomId", currencyUomId);
Map<String, Object> authResp = dispatcher.runSync("processAuthResult", authCtx);
if (ServiceUtil.isError(authResp)) {
String errorMessage = ServiceUtil.getErrorMessage(authResp);
Debug.logError(errorMessage, MODULE);
throw new GeneralException(errorMessage);
}
// approve the order
OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId, manualHold);
if ("Y".equalsIgnoreCase(productStore.getString("manualAuthIsCapture"))) {
Map<String, Object> captCtx = new HashMap<>();
captCtx.put("orderPaymentPreference", opp);
if (opp.get("paymentMethodId") == null) {
captCtx.put("serviceTypeEnum", "PRDS_PAY_EXTERNAL");
}
captCtx.put("payToPartyId", productStore.get("payToPartyId"));
captCtx.put("captureResult", Boolean.TRUE);
captCtx.put("captureAmount", opp.getBigDecimal("maxAmount"));
captCtx.put("captureRefNum", opp.getString("manualRefNum"));
captCtx.put("userLogin", userLogin);
captCtx.put("currencyUomId", currencyUomId);
Map<String, Object> capResp = dispatcher.runSync("processCaptureResult", captCtx);
if (ServiceUtil.isError(capResp)) {
String errorMessage = ServiceUtil.getErrorMessage(capResp);
Debug.logError(errorMessage, MODULE);
throw new GeneralException(errorMessage);
}
}
}
}
// check for a paypal express checkout needing completion
List<EntityExpr> payPalExprs = UtilMisc.toList(
EntityCondition.makeCondition("paymentMethodId", EntityOperator.NOT_EQUAL, null),
EntityCondition.makeCondition("paymentMethodTypeId", "EXT_PAYPAL"));
List<GenericValue> payPalPaymentPrefs = EntityUtil.filterByAnd(allPaymentPreferences, payPalExprs);
if (UtilValidate.isNotEmpty(payPalPaymentPrefs)) {
GenericValue payPalPaymentPref = EntityUtil.getFirst(payPalPaymentPrefs);
ExpressCheckoutEvents.doExpressCheckout(productStore.getString("productStoreId"), orderId, payPalPaymentPref, userLogin,
delegator, dispatcher);
}
// check for online payment methods needing authorization
Map<String, Object> paymentFields = UtilMisc.<String, Object>toMap("statusId", "PAYMENT_NOT_AUTH");
List<GenericValue> onlinePaymentPrefs = EntityUtil.filterByAnd(allPaymentPreferences, paymentFields);
// Check the payment preferences; if we have ANY w/ status PAYMENT_NOT_AUTH invoke payment service.
// Invoke payment processing.
if (UtilValidate.isNotEmpty(onlinePaymentPrefs)) {
boolean autoApproveOrder = UtilValidate.isEmpty(productStore.get("autoApproveOrder")) || "Y".equalsIgnoreCase(productStore
.getString("autoApproveOrder"));
if (orderTotal.compareTo(BigDecimal.ZERO) == 0 && autoApproveOrder) {
// if there is nothing to authorize; don't bother
boolean ok = OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId, manualHold);
if (!ok) {
throw new GeneralException("Problem with order change; see above error");
}
}
// now there should be something to authorize; go ahead
Map<String, Object> paymentResult = null;
try {
// invoke the payment gateway service.
paymentResult = dispatcher.runSync("authOrderPayments",
UtilMisc.<String, Object>toMap("orderId", orderId, "userLogin", userLogin), 180, false);
if (ServiceUtil.isError(paymentResult)) {
String errorMessage = ServiceUtil.getErrorMessage(paymentResult);
Debug.logError(errorMessage, MODULE);
throw new GeneralException(errorMessage);
}
} catch (GenericServiceException e) {
Debug.logWarning(e, MODULE);
throw new GeneralException("Error in authOrderPayments service: " + e.toString(), e.getNested());
}
if (Debug.verboseOn()) {
Debug.logVerbose("Finished w/ Payment Service", MODULE);
}
if (paymentResult != null && paymentResult.containsKey("processResult")) {
// grab the customer messages -- only passed back in the case of an error or failure
List<String> messages = UtilGenerics.cast(paymentResult.get("authResultMsgs"));
String authResp = (String) paymentResult.get("processResult");
if ("FAILED".equals(authResp)) {
// order was NOT approved
if (Debug.verboseOn()) {
Debug.logVerbose("Payment auth was NOT a success!", MODULE);
}
boolean ok = OrderChangeHelper.rejectOrder(dispatcher, userLogin, orderId);
if (!ok) {
throw new GeneralException("Problem with order change; see above error");
}
if (UtilValidate.isEmpty(messages)) {
return ServiceUtil.returnError(declineMessage);
}
return ServiceUtil.returnError(messages);
} else if ("APPROVED".equals(authResp)) {
// order WAS approved
if (Debug.verboseOn()) {
Debug.logVerbose("Payment auth was a success!", MODULE);
}
// set the order and item status to approved
if (autoApproveOrder) {
List<GenericValue> productStorePaymentSettingList = EntityQuery.use(delegator).from("ProductStorePaymentSetting")
.where("productStoreId", productStore.getString("productStoreId"), "paymentMethodTypeId", "CREDIT_CARD",
"paymentService", "cyberSourceCCAuth").queryList();
if (!productStorePaymentSettingList.isEmpty()) {
String decision = (String) paymentResult.get("authCode");
if (UtilValidate.isNotEmpty(decision)) {
if ("ACCEPT".equalsIgnoreCase(decision)) {
boolean ok = OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId, manualHold);
if (!ok) {
throw new GeneralException("Problem with order change; see above error");
}
}
} else {
boolean ok = OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId, manualHold);
if (!ok) {
throw new GeneralException("Problem with order change; see above error");
}
}
} else {
boolean ok = OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId, manualHold);
if (!ok) {
throw new GeneralException("Problem with order change; see above error");
}
}
}
} else if ("ERROR".equals(authResp)) {
// service failed
if (Debug.verboseOn()) {
Debug.logVerbose("Payment auth failed due to processor trouble.", MODULE);
}
if (!faceToFace && "Y".equalsIgnoreCase(retryOnError)) {
// never do this for a face to face purchase regardless of store setting
return ServiceUtil.returnSuccess(errMessage);
}
boolean ok = OrderChangeHelper.cancelOrder(dispatcher, userLogin, orderId);
if (!ok) {
throw new GeneralException("Problem with order change; see above error");
}
if (UtilValidate.isEmpty(messages)) {
return ServiceUtil.returnError(errMessage);
}
return ServiceUtil.returnError(messages);
} else {
// should never happen
return ServiceUtil.returnError(UtilProperties.getMessage(RES_ERROR, "OrderPleaseContactCustomerServicePaymentReturnCodeUnknown",
Locale.getDefault()));
}
} else {
// result returned null == service failed
if (Debug.verboseOn()) {
Debug.logVerbose("Payment auth failed due to processor trouble.", MODULE);
}
if (!faceToFace && "Y".equalsIgnoreCase(retryOnError)) {
// never do this for a face to face purchase regardless of store setting
return ServiceUtil.returnSuccess(errMessage);
}
boolean ok = OrderChangeHelper.cancelOrder(dispatcher, userLogin, orderId);
if (!ok) {
throw new GeneralException("Problem with order change; see above error");
}
return ServiceUtil.returnError(errMessage);
}
} else {
// Get the paymentMethodTypeIds - this will need to change when ecom supports multiple payments
List<EntityExpr> cashCodPcBaExpr = UtilMisc.toList(EntityCondition.makeCondition("paymentMethodTypeId", EntityOperator.EQUALS, "CASH"),
EntityCondition.makeCondition("paymentMethodTypeId", EntityOperator.EQUALS, "EXT_COD"),
EntityCondition.makeCondition("paymentMethodTypeId", EntityOperator.EQUALS, "PERSONAL_CHECK"),
EntityCondition.makeCondition("paymentMethodTypeId", EntityOperator.EQUALS, "EXT_BILLACT"));
List<GenericValue> cashCodPcBaPaymentPreferences = EntityUtil.filterByOr(allPaymentPreferences, cashCodPcBaExpr);
if (UtilValidate.isNotEmpty(cashCodPcBaPaymentPreferences)
&& UtilValidate.isNotEmpty(allPaymentPreferences)
&& cashCodPcBaPaymentPreferences.size() == allPaymentPreferences.size()) {
//if there are Check type, approve the order only if it is face to face
List<GenericValue> checkPreferences = EntityUtil.filterByAnd(cashCodPcBaPaymentPreferences,
UtilMisc.toMap("paymentMethodTypeId", "PERSONAL_CHECK"));
if (UtilValidate.isNotEmpty(checkPreferences)) {
if (faceToFace) {
boolean ok = OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId, manualHold);
if (!ok) {
throw new GeneralException("Problem with order change; see above error");
}
}
// approve this as long as there are only CASH, COD and Billing Account types
} else {
boolean ok = OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId, manualHold);
if (!ok) {
throw new GeneralException("Problem with order change; see above error");
}
}
}
}
// check to see if we should auto-invoice/bill
if (faceToFace) {
if (Debug.verboseOn()) {
Debug.logVerbose("Face-To-Face Sale - " + orderId, MODULE);
}
CheckOutHelper.adjustFaceToFacePayment(orderId, orderTotal, allPaymentPreferences, userLogin, delegator);
boolean ok = OrderChangeHelper.completeOrder(dispatcher, userLogin, orderId);
if (Debug.verboseOn()) {
Debug.logVerbose("Complete Order Result - " + ok, MODULE);
}
if (!ok) {
throw new GeneralException("Problem with order change; see error logs");
}
}
return ServiceUtil.returnSuccess();
}