Search in sources :

Example 36 with GeneralException

use of org.apache.ofbiz.base.util.GeneralException in project ofbiz-framework by apache.

the class GiftCertificateServices method createGiftCertificate.

// Base Gift Certificate Services
public static Map<String, Object> createGiftCertificate(DispatchContext dctx, Map<String, ? extends Object> context) {
    LocalDispatcher dispatcher = dctx.getDispatcher();
    Delegator delegator = dctx.getDelegator();
    Locale locale = (Locale) context.get("locale");
    GenericValue userLogin = (GenericValue) context.get("userLogin");
    String productStoreId = (String) context.get("productStoreId");
    BigDecimal initialAmount = (BigDecimal) context.get("initialAmount");
    String currency = (String) context.get("currency");
    String partyId = (String) context.get("partyId");
    if (UtilValidate.isEmpty(partyId)) {
        partyId = "_NA_";
    }
    String currencyUom = (String) context.get("currency");
    if (UtilValidate.isEmpty(currencyUom)) {
        currencyUom = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
    }
    String cardNumber = null;
    String pinNumber = null;
    String refNum = null;
    String finAccountId = null;
    try {
        final String accountName = "Gift Certificate Account";
        final String deposit = "DEPOSIT";
        GenericValue giftCertSettings = EntityQuery.use(delegator).from("ProductStoreFinActSetting").where("productStoreId", productStoreId, "finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId).cache().queryOne();
        Map<String, Object> acctResult = null;
        if ("Y".equals(giftCertSettings.getString("requirePinCode"))) {
            // TODO: move this code to createFinAccountForStore as well
            int cardNumberLength = CARD_NUMBER_LENGTH;
            int pinNumberLength = PIN_NUMBER_LENGTH;
            if (giftCertSettings.getLong("accountCodeLength") != null) {
                cardNumberLength = giftCertSettings.getLong("accountCodeLength").intValue();
            }
            if (giftCertSettings.getLong("pinCodeLength") != null) {
                pinNumberLength = giftCertSettings.getLong("pinCodeLength").intValue();
            }
            cardNumber = generateNumber(delegator, cardNumberLength, true);
            pinNumber = generateNumber(delegator, pinNumberLength, false);
            // in this case, the card number is the finAccountId
            finAccountId = cardNumber;
            // create the FinAccount
            Map<String, Object> acctCtx = UtilMisc.<String, Object>toMap("finAccountId", finAccountId);
            acctCtx.put("finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId);
            acctCtx.put("finAccountName", accountName);
            acctCtx.put("finAccountCode", pinNumber);
            acctCtx.put("userLogin", userLogin);
            acctResult = dispatcher.runSync("createFinAccount", acctCtx);
            if (ServiceUtil.isError(acctResult)) {
                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(acctResult));
            }
        } else {
            Map<String, Object> createAccountCtx = new HashMap<>();
            createAccountCtx.put("ownerPartyId", partyId);
            createAccountCtx.put("finAccountTypeId", FinAccountHelper.giftCertFinAccountTypeId);
            createAccountCtx.put("productStoreId", productStoreId);
            createAccountCtx.put("currencyUomId", currency);
            createAccountCtx.put("finAccountName", accountName + "for party [" + partyId + "]");
            createAccountCtx.put("userLogin", userLogin);
            acctResult = dispatcher.runSync("createFinAccountForStore", createAccountCtx);
            if (ServiceUtil.isError(acctResult)) {
                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(acctResult));
            }
            if (acctResult.get("finAccountId") != null) {
                finAccountId = cardNumber = (String) acctResult.get("finAccountId");
            }
            if (acctResult.get("finAccountCode") != null) {
                cardNumber = (String) acctResult.get("finAccountCode");
            }
        }
        // create the initial (deposit) transaction
        // do something tricky here: run as the "system" user
        // that can actually create a financial account transaction
        GenericValue permUserLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").cache().queryOne();
        refNum = createTransaction(delegator, dispatcher, permUserLogin, initialAmount, productStoreId, partyId, currencyUom, deposit, finAccountId, locale);
    } catch (GenericEntityException | GenericServiceException e) {
        Debug.logError(e, module);
        return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, "AccountingGiftCerticateNumberCreationError", locale));
    } catch (GeneralException e) {
        Debug.logError(e, module);
        return ServiceUtil.returnError(e.getMessage());
    }
    Map<String, Object> result = ServiceUtil.returnSuccess();
    result.put("cardNumber", cardNumber);
    result.put("pinNumber", pinNumber);
    result.put("initialAmount", initialAmount);
    result.put("processResult", Boolean.TRUE);
    result.put("responseCode", "1");
    result.put("referenceNum", refNum);
    Debug.logInfo("Create GC Result - " + result, module);
    return result;
}
Also used : Locale(java.util.Locale) GenericValue(org.apache.ofbiz.entity.GenericValue) LocalDispatcher(org.apache.ofbiz.service.LocalDispatcher) GeneralException(org.apache.ofbiz.base.util.GeneralException) HashMap(java.util.HashMap) BigDecimal(java.math.BigDecimal) Delegator(org.apache.ofbiz.entity.Delegator) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) GenericServiceException(org.apache.ofbiz.service.GenericServiceException)

Example 37 with GeneralException

use of org.apache.ofbiz.base.util.GeneralException in project ofbiz-framework by apache.

the class PaymentGatewayServices method captureOrderPayments.

/**
 * Captures payments through service calls to the defined processing service for the ProductStore/PaymentMethodType
 * @return COMPLETE|FAILED|ERROR for complete processing of ALL payment methods.
 */
public static Map<String, Object> captureOrderPayments(DispatchContext dctx, Map<String, ? extends Object> context) {
    Delegator delegator = dctx.getDelegator();
    LocalDispatcher dispatcher = dctx.getDispatcher();
    GenericValue userLogin = (GenericValue) context.get("userLogin");
    String orderId = (String) context.get("orderId");
    String invoiceId = (String) context.get("invoiceId");
    String billingAccountId = (String) context.get("billingAccountId");
    BigDecimal amountToCapture = (BigDecimal) context.get("captureAmount");
    Locale locale = (Locale) context.get("locale");
    amountToCapture = amountToCapture.setScale(decimals, rounding);
    // get the order header and payment preferences
    GenericValue orderHeader = null;
    List<GenericValue> paymentPrefs = null;
    List<GenericValue> paymentPrefsBa = null;
    try {
        orderHeader = EntityQuery.use(delegator).from("OrderHeader").where("orderId", orderId).queryOne();
        // get the payment prefs
        paymentPrefs = EntityQuery.use(delegator).from("OrderPaymentPreference").where("orderId", orderId, "statusId", "PAYMENT_AUTHORIZED").orderBy("-maxAmount").queryList();
        if (UtilValidate.isNotEmpty(billingAccountId)) {
            paymentPrefsBa = EntityQuery.use(delegator).from("OrderPaymentPreference").where("orderId", orderId, "paymentMethodTypeId", "EXT_BILLACT", "statusId", "PAYMENT_NOT_RECEIVED").orderBy("-maxAmount").queryList();
        }
    } catch (GenericEntityException gee) {
        Debug.logError(gee, "Problems getting entity record(s), see stack trace", module);
        return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, "OrderOrderNotFound", UtilMisc.toMap("orderId", orderId), locale) + " " + gee.toString());
    }
    // error if no order was found
    if (orderHeader == null) {
        return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, "OrderOrderNotFound", UtilMisc.toMap("orderId", orderId), locale));
    }
    // Check if the outstanding amount for the order is greater than the
    // amount that we are going to capture.
    OrderReadHelper orh = new OrderReadHelper(orderHeader);
    BigDecimal orderGrandTotal = orh.getOrderGrandTotal();
    orderGrandTotal = orderGrandTotal.setScale(decimals, rounding);
    BigDecimal totalPayments = PaymentWorker.getPaymentsTotal(orh.getOrderPayments());
    totalPayments = totalPayments.setScale(decimals, rounding);
    BigDecimal remainingTotal = orderGrandTotal.subtract(totalPayments);
    if (Debug.infoOn()) {
        Debug.logInfo("The Remaining Total for order: " + orderId + " is: " + remainingTotal, module);
    }
    // The amount to capture cannot be greater than the remaining total
    amountToCapture = amountToCapture.min(remainingTotal);
    if (Debug.infoOn()) {
        Debug.logInfo("Actual Expected Capture Amount : " + amountToCapture, module);
    }
    // Process billing accounts payments
    if (UtilValidate.isNotEmpty(paymentPrefsBa)) {
        Iterator<GenericValue> paymentsBa = paymentPrefsBa.iterator();
        while (paymentsBa.hasNext()) {
            GenericValue paymentPref = paymentsBa.next();
            BigDecimal authAmount = paymentPref.getBigDecimal("maxAmount");
            if (authAmount == null) {
                authAmount = ZERO;
            }
            authAmount = authAmount.setScale(decimals, rounding);
            if (authAmount.compareTo(ZERO) == 0) {
                // nothing to capture
                Debug.logInfo("Nothing to capture; authAmount = 0", module);
                continue;
            }
            // the amount for *this* capture
            BigDecimal amountThisCapture = amountToCapture.min(authAmount);
            // decrease amount of next payment preference to capture
            amountToCapture = amountToCapture.subtract(amountThisCapture);
            // to the billing account and we apply them to the invoice
            if (UtilValidate.isNotEmpty(invoiceId)) {
                Map<String, Object> captureResult = null;
                try {
                    captureResult = dispatcher.runSync("captureBillingAccountPayments", UtilMisc.<String, Object>toMap("invoiceId", invoiceId, "billingAccountId", billingAccountId, "captureAmount", amountThisCapture, "orderId", orderId, "userLogin", userLogin));
                    if (ServiceUtil.isError(captureResult)) {
                        return ServiceUtil.returnError(ServiceUtil.getErrorMessage(captureResult));
                    }
                } catch (GenericServiceException ex) {
                    return ServiceUtil.returnError(ex.getMessage());
                }
                if (captureResult != null) {
                    BigDecimal amountCaptured = (BigDecimal) captureResult.get("captureAmount");
                    if (Debug.infoOn()) {
                        Debug.logInfo("Amount captured for order [" + orderId + "] from unapplied payments associated to billing account [" + billingAccountId + "] is: " + amountCaptured, module);
                    }
                    amountCaptured = amountCaptured.setScale(decimals, rounding);
                    if (amountCaptured.compareTo(BigDecimal.ZERO) == 0) {
                        continue;
                    }
                    // add the invoiceId to the result for processing
                    captureResult.put("invoiceId", invoiceId);
                    captureResult.put("captureResult", Boolean.TRUE);
                    captureResult.put("orderPaymentPreference", paymentPref);
                    if (context.get("captureRefNum") == null) {
                        // FIXME: this is an hack to avoid a service validation error for processCaptureResult (captureRefNum is mandatory, but it is not used for billing accounts)
                        captureResult.put("captureRefNum", "");
                    }
                    // process the capture's results
                    try {
                        // the following method will set on the OrderPaymentPreference:
                        // maxAmount = amountCaptured and
                        // statusId = PAYMENT_RECEIVED
                        processResult(dctx, captureResult, userLogin, paymentPref, locale);
                    } catch (GeneralException e) {
                        Debug.logError(e, "Trouble processing the result; captureResult: " + captureResult, module);
                        return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, "AccountingPaymentCannotBeCaptured", locale) + " " + captureResult);
                    }
                    // create any splits which are needed
                    if (authAmount.compareTo(amountCaptured) > 0) {
                        BigDecimal splitAmount = authAmount.subtract(amountCaptured);
                        try {
                            Map<String, Object> splitCtx = UtilMisc.<String, Object>toMap("userLogin", userLogin, "orderPaymentPreference", paymentPref, "splitAmount", splitAmount);
                            dispatcher.addCommitService("processCaptureSplitPayment", splitCtx, true);
                        } catch (GenericServiceException e) {
                            Debug.logWarning(e, "Problem processing the capture split payment", module);
                        }
                        if (Debug.infoOn()) {
                            Debug.logInfo("Captured: " + amountThisCapture + " Remaining (re-auth): " + splitAmount, module);
                        }
                    }
                } else {
                    Debug.logError("Payment not captured for order [" + orderId + "] from billing account [" + billingAccountId + "]", module);
                }
            }
        }
    }
    // iterate over the prefs and capture each one until we meet our total
    if (UtilValidate.isNotEmpty(paymentPrefs)) {
        Iterator<GenericValue> payments = paymentPrefs.iterator();
        while (payments.hasNext()) {
            // DEJ20060708: Do we really want to just log and ignore the errors like this? I've improved a few of these in a review today, but it is being done all over...
            GenericValue paymentPref = payments.next();
            GenericValue authTrans = getAuthTransaction(paymentPref);
            if (authTrans == null) {
                Debug.logWarning("Authorized OrderPaymentPreference has no corresponding PaymentGatewayResponse, cannot capture payment: " + paymentPref, module);
                continue;
            }
            // check for an existing capture
            GenericValue captureTrans = getCaptureTransaction(paymentPref);
            if (captureTrans != null) {
                Debug.logWarning("Attempt to capture and already captured preference: " + captureTrans, module);
                continue;
            }
            BigDecimal authAmount = authTrans.getBigDecimal("amount");
            if (authAmount == null) {
                authAmount = ZERO;
            }
            authAmount = authAmount.setScale(decimals, rounding);
            if (authAmount.compareTo(ZERO) == 0) {
                // nothing to capture
                Debug.logInfo("Nothing to capture; authAmount = 0", module);
                continue;
            }
            // the amount for *this* capture
            BigDecimal amountThisCapture;
            // determine how much for *this* capture
            if (isReplacementOrder(orderHeader)) {
                // if it is a replacement order then just capture the auth amount
                amountThisCapture = authAmount;
            } else if (authAmount.compareTo(amountToCapture) >= 0) {
                // if the auth amount is more then expected capture just capture what is expected
                amountThisCapture = amountToCapture;
            } else if (payments.hasNext()) {
                // if we have more payments to capture; just capture what was authorized
                amountThisCapture = authAmount;
            } else {
                // we need to capture more then what was authorized; re-auth for the new amount
                // TODO: add what the billing account cannot support to the re-auth amount
                // TODO: add support for re-auth for additional funds
                // just in case; we will capture the authorized amount here; until this is implemented
                Debug.logError("The amount to capture was more then what was authorized; we only captured the authorized amount : " + paymentPref, module);
                amountThisCapture = authAmount;
            }
            Map<String, Object> captureResult = capturePayment(dctx, userLogin, orh, paymentPref, amountThisCapture, locale);
            if (captureResult != null && ServiceUtil.isSuccess(captureResult)) {
                // credit card processors return captureAmount, but gift certificate processors return processAmount
                BigDecimal amountCaptured = (BigDecimal) captureResult.get("captureAmount");
                if (amountCaptured == null) {
                    amountCaptured = (BigDecimal) captureResult.get("processAmount");
                }
                amountCaptured = amountCaptured.setScale(decimals, rounding);
                // decrease amount of next payment preference to capture
                amountToCapture = amountToCapture.subtract(amountCaptured);
                // add the invoiceId to the result for processing, not for a replacement order
                if (!isReplacementOrder(orderHeader)) {
                    captureResult.put("invoiceId", invoiceId);
                }
                // process the capture's results
                try {
                    processResult(dctx, captureResult, userLogin, paymentPref, locale);
                } catch (GeneralException e) {
                    Debug.logError(e, "Trouble processing the result; captureResult: " + captureResult, module);
                    return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, "AccountingPaymentCannotBeCaptured", locale) + " " + captureResult);
                }
                // create any splits which are needed
                if (authAmount.compareTo(amountCaptured) > 0) {
                    BigDecimal splitAmount = authAmount.subtract(amountCaptured);
                    try {
                        Map<String, Object> splitCtx = UtilMisc.<String, Object>toMap("userLogin", userLogin, "orderPaymentPreference", paymentPref, "splitAmount", splitAmount);
                        dispatcher.addCommitService("processCaptureSplitPayment", splitCtx, true);
                    } catch (GenericServiceException e) {
                        Debug.logWarning(e, "Problem processing the capture split payment", module);
                    }
                    if (Debug.infoOn()) {
                        Debug.logInfo("Captured: " + amountThisCapture + " Remaining (re-auth): " + splitAmount, module);
                    }
                }
            } else {
                Debug.logError("Payment not captured", module);
            }
        }
    }
    if (amountToCapture.compareTo(ZERO) > 0) {
        GenericValue productStore = orh.getProductStore();
        if (UtilValidate.isNotEmpty(productStore)) {
            boolean shipIfCaptureFails = UtilValidate.isEmpty(productStore.get("shipIfCaptureFails")) || "Y".equalsIgnoreCase(productStore.getString("shipIfCaptureFails"));
            if (!shipIfCaptureFails) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, "AccountingPaymentCannotBeCaptured", locale));
            } else {
                Debug.logWarning("Payment capture failed, shipping order anyway as per ProductStore setting (shipIfCaptureFails)", module);
            }
        }
        Map<String, Object> result = ServiceUtil.returnSuccess();
        result.put("processResult", "FAILED");
        return result;
    } else {
        Map<String, Object> result = ServiceUtil.returnSuccess();
        result.put("processResult", "COMPLETE");
        return result;
    }
}
Also used : Locale(java.util.Locale) GenericValue(org.apache.ofbiz.entity.GenericValue) LocalDispatcher(org.apache.ofbiz.service.LocalDispatcher) GeneralException(org.apache.ofbiz.base.util.GeneralException) BigDecimal(java.math.BigDecimal) OrderReadHelper(org.apache.ofbiz.order.order.OrderReadHelper) Delegator(org.apache.ofbiz.entity.Delegator) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) GenericServiceException(org.apache.ofbiz.service.GenericServiceException)

Example 38 with GeneralException

use of org.apache.ofbiz.base.util.GeneralException in project ofbiz-framework by apache.

the class PaymentGatewayServices method processAuthResult.

private static void processAuthResult(DispatchContext dctx, Map<String, Object> result, GenericValue userLogin, GenericValue paymentPreference) throws GeneralException {
    LocalDispatcher dispatcher = dctx.getDispatcher();
    result.put("userLogin", userLogin);
    result.put("orderPaymentPreference", paymentPreference);
    ModelService model = dctx.getModelService("processAuthResult");
    Map<String, Object> context = model.makeValid(result, ModelService.IN_PARAM);
    // in case we rollback make sure this service gets called
    dispatcher.addRollbackService(model.name, context, true);
    // invoke the service
    Map<String, Object> resResp;
    try {
        resResp = dispatcher.runSync(model.name, context);
    } catch (GenericServiceException e) {
        Debug.logError(e, module);
        throw e;
    }
    if (ServiceUtil.isError(resResp)) {
        throw new GeneralException(ServiceUtil.getErrorMessage(resResp));
    }
}
Also used : LocalDispatcher(org.apache.ofbiz.service.LocalDispatcher) GeneralException(org.apache.ofbiz.base.util.GeneralException) GenericServiceException(org.apache.ofbiz.service.GenericServiceException) ModelService(org.apache.ofbiz.service.ModelService)

Example 39 with GeneralException

use of org.apache.ofbiz.base.util.GeneralException in project ofbiz-framework by apache.

the class PaymentGatewayServices method processReAuthFromCaptureFailure.

private static void processReAuthFromCaptureFailure(DispatchContext dctx, Map<String, Object> result, BigDecimal amount, GenericValue userLogin, GenericValue paymentPreference, Locale locale) throws GeneralException {
    LocalDispatcher dispatcher = dctx.getDispatcher();
    // lookup the order header
    OrderReadHelper orh = null;
    try {
        GenericValue orderHeader = paymentPreference.getRelatedOne("OrderHeader", false);
        if (orderHeader != null) {
            orh = new OrderReadHelper(orderHeader);
        }
    } catch (GenericEntityException e) {
        throw new GeneralException("Problems getting OrderHeader; cannot re-auth the payment", e);
    }
    // make sure the order exists
    if (orh == null) {
        throw new GeneralException("No order found for payment preference #" + paymentPreference.get("orderPaymentPreferenceId"));
    }
    // set the re-auth amount
    if (amount == null) {
        amount = ZERO;
    }
    if (amount.compareTo(ZERO) == 0) {
        amount = paymentPreference.getBigDecimal("maxAmount");
        Debug.logInfo("resetting payment amount from 0.00 to correctMax amount", module);
    }
    Debug.logInfo("reauth with amount: " + amount, module);
    // first re-auth the card
    Map<String, Object> authPayRes = authPayment(dispatcher, userLogin, orh, paymentPreference, amount, true, null);
    if (authPayRes == null) {
        throw new GeneralException("Null result returned from payment re-authorization");
    }
    // check the auth-response
    Boolean authResp = (Boolean) authPayRes.get("authResult");
    Boolean capResp = (Boolean) authPayRes.get("captureResult");
    if (authResp != null && Boolean.TRUE.equals(authResp)) {
        GenericValue authTrans = processAuthRetryResult(dctx, authPayRes, userLogin, paymentPreference);
        // check if auto-capture was enabled; process if so
        if (capResp != null && capResp.booleanValue()) {
            processCaptureResult(dctx, result, userLogin, paymentPreference, locale);
        } else {
            // no auto-capture; do manual capture now
            Map<String, Object> capPayRes = capturePayment(dctx, userLogin, orh, paymentPreference, amount, authTrans, locale);
            if (capPayRes == null) {
                throw new GeneralException("Problems trying to capture payment (null result)");
            }
            // process the capture result
            Boolean capPayResp = (Boolean) capPayRes.get("captureResult");
            if (capPayResp != null && capPayResp.booleanValue()) {
                // process the capture result
                processCaptureResult(dctx, capPayRes, userLogin, paymentPreference, locale);
            } else {
                throw new GeneralException("Capture of authorized payment failed");
            }
        }
    } else {
        throw new GeneralException("Payment re-authorization failed");
    }
}
Also used : GenericValue(org.apache.ofbiz.entity.GenericValue) LocalDispatcher(org.apache.ofbiz.service.LocalDispatcher) GeneralException(org.apache.ofbiz.base.util.GeneralException) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) OrderReadHelper(org.apache.ofbiz.order.order.OrderReadHelper)

Example 40 with GeneralException

use of org.apache.ofbiz.base.util.GeneralException in project ofbiz-framework by apache.

the class PaymentGatewayServices method authPayment.

private static Map<String, Object> authPayment(LocalDispatcher dispatcher, GenericValue userLogin, OrderReadHelper orh, GenericValue paymentPreference, BigDecimal totalRemaining, boolean reauth, BigDecimal overrideAmount) throws GeneralException {
    String paymentConfig = null;
    String serviceName = null;
    String paymentGatewayConfigId = null;
    // get the payment settings i.e. serviceName and config properties file name
    String serviceType = AUTH_SERVICE_TYPE;
    if (reauth) {
        serviceType = REAUTH_SERVICE_TYPE;
    }
    GenericValue paymentSettings = getPaymentSettings(orh.getOrderHeader(), paymentPreference, serviceType, false);
    if (paymentSettings != null) {
        String customMethodId = paymentSettings.getString("paymentCustomMethodId");
        if (UtilValidate.isNotEmpty(customMethodId)) {
            serviceName = getPaymentCustomMethod(orh.getOrderHeader().getDelegator(), customMethodId);
        }
        if (UtilValidate.isEmpty(serviceName)) {
            serviceName = paymentSettings.getString("paymentService");
        }
        paymentConfig = paymentSettings.getString("paymentPropertiesPath");
        paymentGatewayConfigId = paymentSettings.getString("paymentGatewayConfigId");
    } else {
        throw new GeneralException("Could not find any valid payment settings for order with ID [" + orh.getOrderId() + "], and payment operation (serviceType) [" + serviceType + "]");
    }
    // make sure the service name is not null
    if (serviceName == null) {
        throw new GeneralException("Invalid payment processor, serviceName is null: " + paymentSettings);
    }
    // make the process context
    Map<String, Object> processContext = new HashMap<>();
    // get the visit record to obtain the client's IP address
    GenericValue orderHeader = orh.getOrderHeader();
    String visitId = orderHeader.getString("visitId");
    GenericValue visit = null;
    if (visitId != null) {
        try {
            visit = orderHeader.getDelegator().findOne("Visit", UtilMisc.toMap("visitId", visitId), false);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
    }
    if (visit != null && visit.get("clientIpAddress") != null) {
        processContext.put("customerIpAddress", visit.getString("clientIpAddress"));
    }
    GenericValue productStore = orderHeader.getRelatedOne("ProductStore", false);
    processContext.put("userLogin", userLogin);
    processContext.put("orderId", orh.getOrderId());
    processContext.put("orderItems", orh.getOrderItems());
    // TODO refactor the payment API to handle support all addresses
    processContext.put("shippingAddress", EntityUtil.getFirst(orh.getShippingLocations()));
    processContext.put("paymentConfig", paymentConfig);
    processContext.put("paymentGatewayConfigId", paymentGatewayConfigId);
    processContext.put("currency", orh.getCurrency());
    processContext.put("orderPaymentPreference", paymentPreference);
    if (paymentPreference.get("securityCode") != null) {
        processContext.put("cardSecurityCode", paymentPreference.get("securityCode"));
    }
    // get the billing information
    getBillingInformation(orh, paymentPreference, processContext);
    // default charge is totalRemaining
    BigDecimal processAmount = totalRemaining;
    // use override or max amount available
    if (overrideAmount != null) {
        processAmount = overrideAmount;
    } else if (paymentPreference.get("maxAmount") != null) {
        processAmount = paymentPreference.getBigDecimal("maxAmount");
    }
    // Check if the order is a replacement order
    boolean replacementOrderFlag = isReplacementOrder(orderHeader);
    // don't authorized more then what is required
    if (!replacementOrderFlag && processAmount.compareTo(totalRemaining) > 0) {
        processAmount = totalRemaining;
    }
    // format the decimal
    processAmount = processAmount.setScale(decimals, rounding);
    if (Debug.verboseOn()) {
        Debug.logVerbose("Charging amount: " + processAmount, module);
    }
    processContext.put("processAmount", processAmount);
    // invoke the processor
    Map<String, Object> processorResult = null;
    try {
        // invoke the payment processor; allow 5 minute transaction timeout and require a new tx; we'll capture the error and pass back nicely
        GenericValue creditCard = (GenericValue) processContext.get("creditCard");
        // only try other exp dates if orderHeader.autoOrderShoppingListId is not empty, productStore.autoOrderCcTryExp=Y and this payment is a creditCard
        boolean tryOtherExpDates = "Y".equals(productStore.getString("autoOrderCcTryExp")) && creditCard != null && UtilValidate.isNotEmpty(orderHeader.getString("autoOrderShoppingListId"));
        // if we are not trying other expire dates OR if we are and the date is after today, then run the service
        if (!tryOtherExpDates || UtilValidate.isDateAfterToday(creditCard.getString("expireDate"))) {
            processorResult = dispatcher.runSync(serviceName, processContext, TX_TIME, true);
            if (ServiceUtil.isError(processorResult)) {
                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(processorResult));
            }
        }
        // try other expire dates if the expireDate is not after today, or if we called the auth service and resultBadExpire = true
        if (tryOtherExpDates && (!UtilValidate.isDateAfterToday(creditCard.getString("expireDate")) || (processorResult != null && Boolean.TRUE.equals(processorResult.get("resultBadExpire"))))) {
            // try adding 2, 3, 4 years later with the same month
            String expireDate = creditCard.getString("expireDate");
            int dateSlash1 = expireDate.indexOf("/");
            String month = expireDate.substring(0, dateSlash1);
            String year = expireDate.substring(dateSlash1 + 1);
            // start adding 2 years, if comes back with resultBadExpire try again up to twice incrementing one year
            year = StringUtil.addToNumberString(year, 2);
            // note that this is set in memory only for now, not saved to the database unless successful
            creditCard.set("expireDate", month + "/" + year);
            // don't need to set back in the processContext, it's already there: processContext.put("creditCard", creditCard);
            processorResult = dispatcher.runSync(serviceName, processContext, TX_TIME, true);
            if (ServiceUtil.isError(processorResult)) {
                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(processorResult));
            }
            // note that these additional tries will only be done if the service return is not an error, in that case we let it pass through to the normal error handling
            if (ServiceUtil.isSuccess(processorResult) && Boolean.TRUE.equals(processorResult.get("resultBadExpire"))) {
                // okay, try one more year...
                year = StringUtil.addToNumberString(year, 1);
                creditCard.set("expireDate", month + "/" + year);
                processorResult = dispatcher.runSync(serviceName, processContext, TX_TIME, true);
                if (ServiceUtil.isError(processorResult)) {
                    return ServiceUtil.returnError(ServiceUtil.getErrorMessage(processorResult));
                }
            }
            if (ServiceUtil.isSuccess(processorResult) && Boolean.TRUE.equals(processorResult.get("resultBadExpire"))) {
                // okay, try one more year... and this is the last try
                year = StringUtil.addToNumberString(year, 1);
                creditCard.set("expireDate", month + "/" + year);
                processorResult = dispatcher.runSync(serviceName, processContext, TX_TIME, true);
                if (ServiceUtil.isError(processorResult)) {
                    return ServiceUtil.returnError(ServiceUtil.getErrorMessage(processorResult));
                }
            }
            // at this point if we have a successful result, let's save the new creditCard expireDate
            if (ServiceUtil.isSuccess(processorResult) && Boolean.TRUE.equals(processorResult.get("authResult"))) {
                // TODO: this is bad; we should be expiring the old card and creating a new one instead of editing it
                creditCard.store();
            }
        }
    } catch (GenericServiceException e) {
        Debug.logError(e, "Error occurred on: " + serviceName + ", Order ID is: [" + orh.getOrderId() + "]", module);
        throw new GeneralException("Problems invoking payment processor! Will retry later. Order ID is: [" + orh.getOrderId() + "]", e);
    }
    if (processorResult != null) {
        // check for errors from the processor implementation
        if (ServiceUtil.isError(processorResult)) {
            Debug.logError("Processor failed; will retry later: " + processorResult.get(ModelService.ERROR_MESSAGE), module);
            // log the error message as a gateway response when it fails
            saveError(dispatcher, userLogin, paymentPreference, processorResult, AUTH_SERVICE_TYPE, "PGT_AUTHORIZE");
            // this is the one place where we want to return null because the calling method will look for this
            return null;
        }
        // pass the payTo partyId to the result processor; we just add it to the result context.
        String payToPartyId = getPayToPartyId(orh.getOrderHeader());
        processorResult.put("payToPartyId", payToPartyId);
        // add paymentSettings to result; for use by later processors
        processorResult.put("paymentSettings", paymentSettings);
        // and pass on the currencyUomId
        processorResult.put("currencyUomId", orh.getCurrency());
    }
    return processorResult;
}
Also used : GenericValue(org.apache.ofbiz.entity.GenericValue) GeneralException(org.apache.ofbiz.base.util.GeneralException) HashMap(java.util.HashMap) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) GenericServiceException(org.apache.ofbiz.service.GenericServiceException) BigDecimal(java.math.BigDecimal)

Aggregations

GeneralException (org.apache.ofbiz.base.util.GeneralException)216 GenericValue (org.apache.ofbiz.entity.GenericValue)133 Delegator (org.apache.ofbiz.entity.Delegator)101 Locale (java.util.Locale)81 HashMap (java.util.HashMap)71 GenericEntityException (org.apache.ofbiz.entity.GenericEntityException)68 LocalDispatcher (org.apache.ofbiz.service.LocalDispatcher)68 IOException (java.io.IOException)65 BigDecimal (java.math.BigDecimal)55 GenericServiceException (org.apache.ofbiz.service.GenericServiceException)54 Writer (java.io.Writer)29 LinkedList (java.util.LinkedList)29 Map (java.util.Map)29 Timestamp (java.sql.Timestamp)26 StringWriter (java.io.StringWriter)19 Environment (freemarker.core.Environment)15 HttpServletRequest (javax.servlet.http.HttpServletRequest)14 ShoppingCart (org.apache.ofbiz.order.shoppingcart.ShoppingCart)14 HttpSession (javax.servlet.http.HttpSession)13 ParserConfigurationException (javax.xml.parsers.ParserConfigurationException)13