/*******************************************************************************
 * 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.payment;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import javolution.util.FastList;
import javolution.util.FastMap;

import org.ofbiz.accounting.invoice.InvoiceWorker;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilGenerics;
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.condition.EntityCondition;
import org.ofbiz.entity.condition.EntityExpr;
import org.ofbiz.entity.condition.EntityJoinOperator;
import org.ofbiz.entity.condition.EntityOperator;
import org.ofbiz.entity.model.ModelEntity;
import org.ofbiz.entity.util.EntityListIterator;
import org.ofbiz.entity.util.EntityQuery;
import org.ofbiz.entity.util.EntityUtil;
import org.ofbiz.entity.util.EntityUtilProperties;
import org.ofbiz.order.order.OrderChangeHelper;
import org.ofbiz.order.order.OrderReadHelper;
import org.ofbiz.party.contact.ContactHelper;
import org.ofbiz.product.store.ProductStoreWorker;
import org.ofbiz.security.Security;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ModelService;
import org.ofbiz.service.ServiceUtil;

import com.ibm.icu.util.Calendar;

/**
 * PaymentGatewayServices
 */
public class PaymentGatewayServices {

    public static final String module = PaymentGatewayServices.class.getName();
    public static final String AUTH_SERVICE_TYPE = "PRDS_PAY_AUTH";
    public static final String REAUTH_SERVICE_TYPE = "PRDS_PAY_REAUTH";
    public static final String RELEASE_SERVICE_TYPE = "PRDS_PAY_RELEASE";
    public static final String CAPTURE_SERVICE_TYPE = "PRDS_PAY_CAPTURE";
    public static final String REFUND_SERVICE_TYPE = "PRDS_PAY_REFUND";
    public static final String CREDIT_SERVICE_TYPE = "PRDS_PAY_CREDIT";
    private static final int TX_TIME = 300;
    private static BigDecimal ZERO = BigDecimal.ZERO;
    private static int decimals;
    private static int rounding;
    public final static String resource = "AccountingUiLabels";
    public static final String resourceError = "AccountingErrorUiLabels";
    public static final String resourceOrder = "OrderUiLabels";
    
    static {
        decimals = UtilNumber.getBigDecimalScale("order.decimals");
        rounding = UtilNumber.getBigDecimalRoundingMode("order.rounding");

        // set zero to the proper scale
        if (decimals != -1) ZERO = ZERO.setScale(decimals);
    }

    /**
     * Authorizes a single order preference with an option to specify an amount. The result map has the Booleans
     * "errors" and "finished" which notify the user if there were any errors and if the authorization was finished.
     * There is also a List "messages" for the authorization response messages and a BigDecimal, "processAmount" as the
     * amount processed.
     *
     * TODO: it might be nice to return the paymentGatewayResponseId
     */
    public static Map<String, Object> authOrderPaymentPreference(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Locale locale = (Locale) context.get("locale");
        String orderPaymentPreferenceId = (String) context.get("orderPaymentPreferenceId");
        BigDecimal overrideAmount = (BigDecimal) context.get("overrideAmount");

        // validate overrideAmount if its available
        if (overrideAmount != null) {
            if (overrideAmount.compareTo(BigDecimal.ZERO) < 0) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "AccountingPaymentAmountIsNegative",
                        UtilMisc.toMap("overrideAmount", overrideAmount), locale));
            }
            if (overrideAmount.compareTo(BigDecimal.ZERO) == 0) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "AccountingPaymentAmountIsZero",
                        UtilMisc.toMap("overrideAmount", overrideAmount), locale));
            }
        }

        GenericValue orderHeader = null;
        GenericValue orderPaymentPreference = null;
        try {
            orderPaymentPreference = EntityQuery.use(delegator).from("OrderPaymentPreference").where("orderPaymentPreferenceId", orderPaymentPreferenceId).queryOne();
            orderHeader = orderPaymentPreference.getRelatedOne("OrderHeader", false);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingProblemGettingOrderPaymentPreferences", locale) + " " + 
                    orderPaymentPreferenceId);
        }
        OrderReadHelper orh = new OrderReadHelper(orderHeader);

        // get the total remaining
        BigDecimal totalRemaining = orh.getOrderGrandTotal();

        // get the process attempts so far
        Long procAttempt = orderPaymentPreference.getLong("processAttempt");
        if (procAttempt == null) {
            procAttempt = Long.valueOf(0);
        }

        // update the process attempt count
        orderPaymentPreference.set("processAttempt", Long.valueOf(procAttempt.longValue() + 1));
        try {
            orderPaymentPreference.store();
            orderPaymentPreference.refresh();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingProblemGettingOrderPaymentPreferences", locale));
        }

        // if we are already authorized, then this is a re-auth request
        boolean reAuth = false;
        if (orderPaymentPreference.get("statusId") != null && "PAYMENT_AUTHORIZED".equals(orderPaymentPreference.getString("statusId"))) {
            reAuth = true;
        }

        // use overrideAmount or maxAmount
        BigDecimal transAmount = null;
        if (overrideAmount != null) {
            transAmount = overrideAmount;
        } else {
            transAmount = orderPaymentPreference.getBigDecimal("maxAmount");
        }

        // round this before moving on just in case a funny number made it this far
        transAmount = transAmount.setScale(decimals, rounding);

        // if our transaction amount exists and is zero, there's nothing to process, so return
        if ((transAmount != null) && (transAmount.compareTo(BigDecimal.ZERO) <= 0)) {
            Map<String, Object> results = ServiceUtil.returnSuccess();
            results.put("finished", Boolean.TRUE); // finished is true since there is nothing to do
            results.put("errors", Boolean.FALSE); // errors is false since no error occurred
            return results;
        }

        try {
            // call the authPayment method
            Map<String, Object> authPaymentResult = authPayment(dispatcher, userLogin, orh, orderPaymentPreference, totalRemaining, reAuth, transAmount);

            // handle the response
            if (authPaymentResult != null) {
                // not null result means either an approval or decline; null would mean error
                BigDecimal thisAmount = (BigDecimal) authPaymentResult.get("processAmount");

                // process the auth results
                try {
                    boolean processResult = processResult(dctx, authPaymentResult, userLogin, orderPaymentPreference, locale);
                    if (processResult) {
                        Map<String, Object> results = ServiceUtil.returnSuccess();
                        results.put("messages", authPaymentResult.get("customerRespMsgs"));
                        results.put("processAmount", thisAmount);
                        results.put("finished", Boolean.TRUE);
                        results.put("errors", Boolean.FALSE);
                        results.put("authCode", authPaymentResult.get("authCode"));
                        return results;
                    } else {
                        boolean needsNsfRetry = needsNsfRetry(orderPaymentPreference, authPaymentResult, delegator);

                        // if we are doing an NSF retry then also...
                        if (needsNsfRetry) {
                            // TODO: what do we do with this? we need to fail the auth but still allow the order through so it can be fixed later
                            // NOTE: this is called through a different path for auto re-orders, so it should be good to go... will leave this comment here just in case...
                        }

                        // if we have a failure at this point and no NSF retry is needed, then try other credit cards on file, if the user has any
                        if (!needsNsfRetry) {
                            // is this an auto-order?
                            if (UtilValidate.isNotEmpty(orderHeader.getString("autoOrderShoppingListId"))) {
                                GenericValue productStore = orderHeader.getRelatedOne("ProductStore", false);
                                // according to the store should we try other cards?
                                if ("Y".equals(productStore.getString("autoOrderCcTryOtherCards"))) {
                                    // get other credit cards for the bill to party
                                    List<GenericValue> otherPaymentMethodAndCreditCardList = null;
                                    String billToPartyId = null;
                                    GenericValue billToParty = orh.getBillToParty();
                                    if (billToParty != null) {
                                        billToPartyId = billToParty.getString("partyId");
                                    } else {
                                        // TODO optional: any other ways to find the bill to party? perhaps look at info from OrderPaymentPreference, ie search back from other PaymentMethod...
                                    }

                                    if (UtilValidate.isNotEmpty(billToPartyId)) {
                                        otherPaymentMethodAndCreditCardList = EntityQuery.use(delegator).from("PaymentMethodAndCreditCard")
                                                .where("partyId", billToPartyId, "paymentMethodTypeId", "CREDIT_CARD").filterByDate().queryList();
                                    }

                                    if (UtilValidate.isNotEmpty(otherPaymentMethodAndCreditCardList)) {
                                        for (GenericValue otherPaymentMethodAndCreditCard : otherPaymentMethodAndCreditCardList) {
                                            // change OrderPaymentPreference in memory only and call auth service
                                            orderPaymentPreference.set("paymentMethodId", otherPaymentMethodAndCreditCard.getString("paymentMethodId"));
                                            Map<String, Object> authRetryResult = authPayment(dispatcher, userLogin, orh, orderPaymentPreference, totalRemaining, reAuth, transAmount);
                                            try {
                                                boolean processRetryResult = processResult(dctx, authPaymentResult, userLogin, 
                                                        orderPaymentPreference, locale);

                                                if (processRetryResult) {
                                                    // wow, we got here that means the other card was successful...
                                                    // on success save the OrderPaymentPreference, and then return finished (which will break from loop)
                                                    orderPaymentPreference.store();

                                                    Map<String, Object> results = ServiceUtil.returnSuccess();
                                                    results.put("messages", authRetryResult.get("customerRespMsgs"));
                                                    results.put("processAmount", thisAmount);
                                                    results.put("finished", Boolean.TRUE);
                                                    results.put("errors", Boolean.FALSE);
                                                    return results;
                                                }
                                            } catch (GeneralException e) {
                                                String errMsg = "Error saving and processing payment authorization results: " + e.toString();
                                                Debug.logError(e, errMsg + "; authRetryResult: " + authRetryResult, module);
                                                Map<String, Object> results = ServiceUtil.returnSuccess();
                                                results.put(ModelService.ERROR_MESSAGE, errMsg);
                                                results.put("finished", Boolean.FALSE);
                                                results.put("errors", Boolean.TRUE);
                                                return results;
                                            }

                                            // if no sucess, fall through to return not finished
                                        }
                                    }
                                }
                            }
                        }

                        Map<String, Object> results = ServiceUtil.returnSuccess();
                        results.put("messages", authPaymentResult.get("customerRespMsgs"));
                        results.put("finished", Boolean.FALSE);
                        results.put("errors", Boolean.FALSE);
                        return results;
                    }
                } catch (GeneralException e) {
                    String errMsg = "Error saving and processing payment authorization results: " + e.toString();
                    Debug.logError(e, errMsg + "; authPaymentResult: " + authPaymentResult, module);
                    Map<String, Object> results = ServiceUtil.returnSuccess();
                    results.put(ModelService.ERROR_MESSAGE, errMsg);
                    results.put("finished", Boolean.FALSE);
                    results.put("errors", Boolean.TRUE);
                    return results;
                }
            } else {
                // error with payment processor; will try later
                String errMsg = "Invalid Order Payment Preference: maxAmount is 0";
                Debug.logInfo(errMsg, module);
                Map<String, Object> results = ServiceUtil.returnSuccess();
                results.put("finished", Boolean.FALSE);
                results.put("errors", Boolean.TRUE);
                results.put(ModelService.ERROR_MESSAGE, errMsg);
                orderPaymentPreference.set("statusId", "PAYMENT_CANCELLED");
                try {
                    orderPaymentPreference.store();
                } catch (GenericEntityException e) {
                    Debug.logError(e, "ERROR: Problem setting OrderPaymentPreference status to CANCELLED", module);
                }
                return results;
            }
        } catch (GeneralException e) {
            Debug.logError(e, "Error processing payment authorization", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingPaymentCannotBeAuthorized", 
                    UtilMisc.toMap("errroString", e.toString()), locale));
        }
    }

    /**
     * Processes payments through service calls to the defined processing service for the ProductStore/PaymentMethodType
     * @return APPROVED|FAILED|ERROR for complete processing of ALL payment methods.
     */
    public static Map<String, Object> authOrderPayments(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        String orderId = (String) context.get("orderId");
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = FastMap.newInstance();
        boolean reAuth = false;
        if (context.get("reAuth") != null) {
            reAuth = ((Boolean)context.get("reAuth")).booleanValue();
        }
        // get the order header and payment preferences
        GenericValue orderHeader = null;
        List<GenericValue> paymentPrefs = null;

        try {
            // get the OrderHeader
            orderHeader = EntityQuery.use(delegator).from("OrderHeader").where("orderId", orderId).queryOne();

            // get the payments to auth
            Map<String, String> lookupMap = UtilMisc.toMap("orderId", orderId, "statusId", "PAYMENT_NOT_AUTH");
            List<String> orderList = UtilMisc.toList("maxAmount");
            paymentPrefs = EntityQuery.use(delegator).from("OrderPaymentPreference").where(lookupMap).orderBy(orderList).queryList();
            if (reAuth) {
                lookupMap.put("orderId", orderId);
                lookupMap.put("statusId", "PAYMENT_AUTHORIZED");
                paymentPrefs.addAll(EntityQuery.use(delegator).from("OrderPaymentPreference").where(lookupMap).orderBy(orderList).queryList());
            }
        } catch (GenericEntityException gee) {
            Debug.logError(gee, "Problems getting the order information", module);
            result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_ERROR);
            result.put(ModelService.ERROR_MESSAGE, "ERROR: Could not get order information (" + gee.toString() + ").");
            return result;
        }

        // make sure we have a OrderHeader
        if (orderHeader == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, 
                    "OrderOrderNotFound", UtilMisc.toMap("orderId", orderId), locale));
        }

        // get the order amounts
        OrderReadHelper orh = new OrderReadHelper(orderHeader);
        BigDecimal totalRemaining = orh.getOrderGrandTotal();

        // loop through and auth each order payment preference
        int finished = 0;
        int hadError = 0;
        List<String> messages = FastList.newInstance();
        for (GenericValue paymentPref : paymentPrefs) {
            if (reAuth && "PAYMENT_AUTHORIZED".equals(paymentPref.getString("statusId"))) {
                String paymentConfig = null;
                // get the payment settings i.e. serviceName and config properties file name
                GenericValue paymentSettings = getPaymentSettings(orh.getOrderHeader(), paymentPref, AUTH_SERVICE_TYPE, false);
                if (paymentSettings != null) {
                    paymentConfig = paymentSettings.getString("paymentPropertiesPath");
                    if (UtilValidate.isEmpty(paymentConfig)) {
                        paymentConfig = "payment.properties";
                    }
                }
                // check the validity of the authorization; re-auth if necessary
                if (PaymentGatewayServices.checkAuthValidity(paymentPref, paymentConfig)) {
                    finished += 1;
                    continue;
                }
            }
            Map<String, Object> authContext = FastMap.newInstance();
            authContext.put("orderPaymentPreferenceId", paymentPref.getString("orderPaymentPreferenceId"));
            authContext.put("userLogin", context.get("userLogin"));

            Map<String, Object> results = null;
            try {
                results = dispatcher.runSync("authOrderPaymentPreference", authContext);
            } catch (GenericServiceException se) {
                Debug.logError(se, "Error in calling authOrderPaymentPreference from authOrderPayments", module);
                hadError += 1;
                messages.add("Could not authorize OrderPaymentPreference [" + paymentPref.getString("orderPaymentPreferenceId") + "] for order [" + orderId + "]: " + se.toString());
                continue;
            }

            // add authorization code to the result
            result.put("authCode", results.get("authCode"));

            if (ServiceUtil.isError(results)) {
                hadError += 1;
                messages.add("Could not authorize OrderPaymentPreference [" + paymentPref.getString("orderPaymentPreferenceId") + "] for order [" + orderId + "]: " + results.get(ModelService.ERROR_MESSAGE));
                continue;
            }
            if (((Boolean) results.get("finished")).booleanValue()) {
                finished += 1;
            }
            if (((Boolean) results.get("errors")).booleanValue()) {
                hadError += 1;
            }
            if (results.get("messages") != null) {
                List<String> message = UtilGenerics.checkList(results.get("messages"));
                messages.addAll(message);
            }
            if (results.get("processAmount") != null) {
                totalRemaining = totalRemaining.subtract(((BigDecimal) results.get("processAmount")));
            }
        }

        Debug.logInfo("Finished with auth(s) checking results", module);

        // add messages to the result
        result.put("authResultMsgs", messages);

        if (hadError > 0) {
            Debug.logError("Error(s) (" + hadError + ") during auth; returning ERROR", module);
            result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
            result.put("processResult", "ERROR");
            return result;
        } else if (finished == paymentPrefs.size()) {
            Debug.logInfo("All auth(s) passed total remaining : " + totalRemaining, module);
            result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
            result.put("processResult", "APPROVED");
            return result;
        } else {
            Debug.logInfo("Only [" + finished + "/" + paymentPrefs.size() + "] OrderPaymentPreference authorizations passed; returning processResult=FAILED with no message so that message from ProductStore will be used", module);
            result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
            result.put("processResult", "FAILED");
            return result;
        }
    }


    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 = FastMap.newInstance();

        // get the visit record to obtain the client's IP address
        GenericValue orderHeader = orh.getOrderHeader();
        //if (orderHeader == null) {}

        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());
        processContext.put("shippingAddress", EntityUtil.getFirst(orh.getShippingLocations())); // TODO refactor the payment API to handle support all addresses
        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);
            }

            // 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);

                // 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.isError(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) && 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);
                }

                // at this point if we have a successful result, let's save the new creditCard expireDate
                if (!ServiceUtil.isError(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;
    }

    private static GenericValue getPaymentSettings(GenericValue orderHeader, GenericValue paymentPreference, String paymentServiceType, boolean anyServiceType) {
        Delegator delegator = orderHeader.getDelegator();
        GenericValue paymentSettings = null;
        String paymentMethodTypeId = paymentPreference.getString("paymentMethodTypeId");

        if (paymentMethodTypeId != null) {
            String productStoreId = orderHeader.getString("productStoreId");
            if (productStoreId != null) {
                paymentSettings = ProductStoreWorker.getProductStorePaymentSetting(delegator, productStoreId, paymentMethodTypeId, paymentServiceType, anyServiceType);
            }
        }
        return paymentSettings;
    }

    private static String getPayToPartyId(GenericValue orderHeader) {
        String payToPartyId = "Company"; // default value
        GenericValue productStore = null;
        try {
            productStore = orderHeader.getRelatedOne("ProductStore", false);
        } catch (GenericEntityException e) {
            Debug.logError(e, "Unable to get ProductStore from OrderHeader", module);
            return null;
        }
        if (productStore != null && productStore.get("payToPartyId") != null) {
            payToPartyId = productStore.getString("payToPartyId");
        } else {
            Debug.logWarning("Using default value of [Company] for payToPartyId on order [" + orderHeader.getString("orderId") + "]", module);
        }
        return payToPartyId;
    }

    private static String getBillingInformation(OrderReadHelper orh, GenericValue paymentPreference, Map<String, Object> toContext) throws GenericEntityException {
        // gather the payment related objects.
        String paymentMethodTypeId = paymentPreference.getString("paymentMethodTypeId");
        GenericValue paymentMethod = paymentPreference.getRelatedOne("PaymentMethod", false);
        if (paymentMethod != null && "CREDIT_CARD".equals(paymentMethodTypeId)) {
            // type credit card
            GenericValue creditCard = paymentMethod.getRelatedOne("CreditCard", false);
            GenericValue billingAddress = creditCard.getRelatedOne("PostalAddress", false);
            toContext.put("creditCard", creditCard);
            toContext.put("billingAddress", billingAddress);
        } else if (paymentMethod != null && "EFT_ACCOUNT".equals(paymentMethodTypeId)) {
            // type eft
            GenericValue eftAccount = paymentMethod.getRelatedOne("EftAccount", false);
            GenericValue billingAddress = eftAccount.getRelatedOne("PostalAddress", false);
            toContext.put("eftAccount", eftAccount);
            toContext.put("billingAddress", billingAddress);
        } else if (paymentMethod != null && "GIFT_CARD".equals(paymentMethodTypeId)) {
            // type gift card
            GenericValue giftCard = paymentMethod.getRelatedOne("GiftCard", false);
            toContext.put("giftCard", giftCard);
            GenericValue orderHeader = paymentPreference.getRelatedOne("OrderHeader", false);
            List<GenericValue> orderItems = orderHeader.getRelated("OrderItem", null, null, false);
            toContext.put("orderId", orderHeader.getString("orderId"));
            toContext.put("orderItems", orderItems);
        } else if ("FIN_ACCOUNT".equals(paymentMethodTypeId)) {
            toContext.put("finAccountId", paymentPreference.getString("finAccountId"));
        } else if ("EXT_PAYPAL".equals(paymentMethodTypeId)) {
            GenericValue payPalPaymentMethod = paymentMethod.getRelatedOne("PayPalPaymentMethod", false);
            toContext.put("payPalPaymentMethod", payPalPaymentMethod);
        } else {
            // add other payment types here; i.e. gift cards, etc.
            // unknown payment type; ignoring.
            Debug.logError("ERROR: Unsupported PaymentMethodType passed for authorization", module);
            return null;
        }

        // get some contact info.
        GenericValue billToPersonOrGroup = orh.getBillToParty();
        GenericValue billToEmail = null;

        Collection<GenericValue> emails = ContactHelper.getContactMech(billToPersonOrGroup.getRelatedOne("Party", false), "PRIMARY_EMAIL", "EMAIL_ADDRESS", false);

        if (UtilValidate.isNotEmpty(emails)) {
            billToEmail = emails.iterator().next();
        }

        toContext.put("billToParty", billToPersonOrGroup);
        toContext.put("billToEmail", billToEmail);

        return billToPersonOrGroup.getString("partyId");
    }

    /**
     *
     * Releases authorizations through service calls to the defined processing service for the ProductStore/PaymentMethodType
     * @return COMPLETE|FAILED|ERROR for complete processing of ALL payments.
     */
    public static Map<String, Object> releaseOrderPayments(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String orderPaymentPreferenceId = (String) context.get("orderPaymentPreferenceId");
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = ServiceUtil.returnSuccess();
        String orderId = "";
        // Get the OrderPaymentPreference
        GenericValue paymentPref = null;
        try {
            if (orderPaymentPreferenceId != null) {
                paymentPref = EntityQuery.use(delegator).from("OrderPaymentPreference").where("orderPaymentPreferenceId", orderPaymentPreferenceId).queryOne();
                orderId = paymentPref.getString("orderId");
            }
            else {
                orderId =  (String) context.get("orderId");
            }
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "AccountingProblemGettingOrderPaymentPreferences", locale) + " " + 
                    orderPaymentPreferenceId);
        }

        // get the payment preferences
        List<GenericValue> paymentPrefs = null;
        try {
            // get the valid payment prefs
            List<EntityExpr> othExpr = UtilMisc.toList(EntityCondition.makeCondition("paymentMethodTypeId", EntityOperator.EQUALS, "EFT_ACCOUNT"));
            othExpr.add(EntityCondition.makeCondition("paymentMethodTypeId", EntityOperator.EQUALS, "GIFT_CARD"));
            othExpr.add(EntityCondition.makeCondition("paymentMethodTypeId", EntityOperator.EQUALS, "FIN_ACCOUNT"));
            EntityCondition con1 = EntityCondition.makeCondition(othExpr, EntityJoinOperator.OR);
            EntityCondition statExpr = EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, "PAYMENT_SETTLED");
            EntityCondition con2 = EntityCondition.makeCondition(UtilMisc.toList(con1, statExpr), EntityOperator.AND);
            EntityCondition authExpr = EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, "PAYMENT_AUTHORIZED");
            EntityCondition con3 = EntityCondition.makeCondition(UtilMisc.toList(con2, authExpr), EntityOperator.OR);
            EntityExpr orderExpr = EntityCondition.makeCondition("orderId", EntityOperator.EQUALS, orderId);
            EntityCondition con4 = EntityCondition.makeCondition(UtilMisc.toList(con3, orderExpr), EntityOperator.AND);
            paymentPrefs = EntityQuery.use(delegator).from("OrderPaymentPreference").where(con4).queryList();
        } catch (GenericEntityException gee) {
            Debug.logError(gee, "Problems getting entity record(s), see stack trace", module);
            result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_ERROR);
            result.put(ModelService.ERROR_MESSAGE, "ERROR: Could not get order information (" + gee.toString() + ").");
            return result;
        }

        // return complete if no payment prefs were found
        if (paymentPrefs.size() == 0) {
            Debug.logWarning("No OrderPaymentPreference records available for release", module);
            result.put("processResult", "COMPLETE");
            result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
            return result;
        }

        // iterate over the prefs and release each one
        List<GenericValue> finished = FastList.newInstance();
        for (GenericValue pPref : paymentPrefs) {
            Map<String, Object> releaseContext = UtilMisc.toMap("userLogin", userLogin, "orderPaymentPreferenceId", pPref.getString("orderPaymentPreferenceId"));
            Map<String, Object> releaseResult = null;
            try {
                releaseResult = dispatcher.runSync("releaseOrderPaymentPreference", releaseContext);
            } catch (GenericServiceException e) {
                Debug.logError(e, "Problem calling releaseOrderPaymentPreference service for orderPaymentPreferenceId" + 
                        paymentPref.getString("orderPaymentPreferenceId"), module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                        "AccountingTroubleCallingReleaseOrderPaymentPreferenceService", locale) + " " +
                        paymentPref.getString("orderPaymentPreferenceId"));
            }
            if (ServiceUtil.isError(releaseResult)) {
                Debug.logError(ServiceUtil.getErrorMessage(releaseResult), module);
                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(releaseResult));
            } else if (! ServiceUtil.isFailure(releaseResult)) {
                finished.add(paymentPref);
            }
        }
        result = ServiceUtil.returnSuccess();
        if (finished.size() == paymentPrefs.size()) {
            result.put("processResult", "COMPLETE");
        } else {
            result.put("processResult", "FAILED");
        }

        return result;
    }

    public static Map<String, Object> processCreditResult(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String currencyUomId = (String) context.get("currencyUomId");
        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
        Boolean creditResponse = (Boolean) context.get("creditResult");
        Locale locale = (Locale) context.get("locale");
        // create the PaymentGatewayResponse
        String responseId = delegator.getNextSeqId("PaymentGatewayResponse");
        GenericValue pgCredit = delegator.makeValue("PaymentGatewayResponse");
        pgCredit.set("paymentGatewayResponseId", responseId);
        pgCredit.set("paymentServiceTypeEnumId", CREDIT_SERVICE_TYPE);
        pgCredit.set("orderPaymentPreferenceId", paymentPref.get("orderPaymentPreferenceId"));
        pgCredit.set("paymentMethodTypeId", paymentPref.get("paymentMethodTypeId"));
        pgCredit.set("paymentMethodId", paymentPref.get("paymentMethodId"));
        pgCredit.set("transCodeEnumId", "PGT_CREDIT");
        // set the credit info
        pgCredit.set("amount", context.get("creditAmount"));
        pgCredit.set("referenceNum", context.get("creditRefNum"));
        pgCredit.set("altReference", context.get("creditAltRefNum"));
        pgCredit.set("gatewayCode", context.get("creditCode"));
        pgCredit.set("gatewayFlag", context.get("creditFlag"));
        pgCredit.set("gatewayMessage", context.get("creditMessage"));
        pgCredit.set("transactionDate", UtilDateTime.nowTimestamp());
        pgCredit.set("currencyUomId", currencyUomId);
        // create the internal messages
        List<GenericValue> messageEntities = FastList.newInstance();
        List<String> messages = UtilGenerics.cast(context.get("internalRespMsgs"));
        if (UtilValidate.isNotEmpty(messages)) {
            for (String message : messages) {
                GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg");
                String respMsgId = delegator.getNextSeqId("PaymentGatewayRespMsg");
                respMsg.set("paymentGatewayRespMsgId", respMsgId);
                respMsg.set("paymentGatewayResponseId", responseId);
                respMsg.set("pgrMessage", message);
                // store the messages
                messageEntities.add(respMsg);
            }
        }
        // save the response and respective messages
        savePgrAndMsgs(dctx, pgCredit, messageEntities);

        if (creditResponse != null && creditResponse.booleanValue()) {
            paymentPref.set("statusId", "PAYMENT_CANCELLED");
            try {
                paymentPref.store();
            } catch (GenericEntityException e) {
                Debug.logError(e, "Problem storing updated payment preference; authorization was credit!", module);
            }
            // cancel any payment records
            List<GenericValue> paymentList = null;
            try {
                paymentList = paymentPref.getRelated("Payment", null, null, false);
            } catch (GenericEntityException e) {
                Debug.logError(e, "Unable to get Payment records from OrderPaymentPreference : " + paymentPref, module);
            }
            if (paymentList != null) {
                Iterator<GenericValue> pi = paymentList.iterator();
                while (pi.hasNext()) {
                    GenericValue pay = pi.next();
                    try {
                        Map<String, Object> cancelResults = dispatcher.runSync("setPaymentStatus", UtilMisc.toMap("userLogin", userLogin, "paymentId", pay.get("paymentId"), "statusId", "PMNT_CANCELLED"));
                        if (ServiceUtil.isError(cancelResults)) {
                            throw new GenericServiceException(ServiceUtil.getErrorMessage(cancelResults));
                        }
                    } catch (GenericServiceException e) {
                        Debug.logError(e, "Unable to cancel Payment : " + pay, module);
                    }
                }
            }
        } else {
            Debug.logError("Credit failed for pref : " + paymentPref, module);
            return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, 
                    "AccountingTroubleCallingCreditOrderPaymentPreferenceService", 
                    UtilMisc.toMap("paymentPref", paymentPref), locale));
        }
        return ServiceUtil.returnSuccess();
    }

    /**
     *
     * Releases authorization for a single OrderPaymentPreference through service calls to the defined processing service for the ProductStore/PaymentMethodType
     * @return SUCCESS|FAILED|ERROR for complete processing of payment.
     */
    public static Map<String, Object> releaseOrderPaymentPreference(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String orderPaymentPreferenceId = (String) context.get("orderPaymentPreferenceId");
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = ServiceUtil.returnSuccess();
        // Get the OrderPaymentPreference
        GenericValue paymentPref = null;
        try {
            paymentPref = EntityQuery.use(delegator).from("OrderPaymentPreference").where("orderPaymentPreferenceId", orderPaymentPreferenceId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logWarning(e, "Problem getting OrderPaymentPreference for orderPaymentPreferenceId " + 
                    orderPaymentPreferenceId, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingProblemGettingOrderPaymentPreferences", locale) + " " + 
                    orderPaymentPreferenceId);
        }
        // Error if no OrderPaymentPreference was found
        if (paymentPref == null) {
            Debug.logWarning("Could not find OrderPaymentPreference with orderPaymentPreferenceId: " + 
                    orderPaymentPreferenceId, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingProblemGettingOrderPaymentPreferences", locale) + " " + 
                    orderPaymentPreferenceId);
        }
        // Get the OrderHeader
        GenericValue orderHeader = null;
        String orderId = paymentPref.getString("orderId");
        try {
            orderHeader = EntityQuery.use(delegator).from("OrderHeader").where("orderId", orderId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logWarning(e, "Problem getting OrderHeader for orderId " + orderId, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, 
                    "OrderOrderNotFound", UtilMisc.toMap("orderId", orderId), locale));
        }
        // Error if no OrderHeader was found
        if (orderHeader == null) {
            Debug.logWarning("Could not find OrderHeader with orderId: " + 
                    orderId + "; not processing payments.", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, 
                    "OrderOrderNotFound", UtilMisc.toMap("orderId", orderId), locale));
        }
        OrderReadHelper orh = new OrderReadHelper(orderHeader);
        String currency = orh.getCurrency();
        // look up the payment configuration settings
        String serviceName = null;
        String paymentConfig = null;
        String paymentGatewayConfigId = null;
        // get the payment settings i.e. serviceName and config properties file name
        GenericValue paymentSettings = getPaymentSettings(orderHeader, paymentPref, RELEASE_SERVICE_TYPE, 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");
            if (serviceName == null) {
                Debug.logWarning("No payment release service for - " + paymentPref.getString("paymentMethodTypeId"), module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, 
                        "AccountingTroubleCallingReleaseOrderPaymentPreferenceService", locale) + " " + 
                        paymentPref.getString("paymentMethodTypeId"));
            }
        } else {
            Debug.logWarning("No payment release settings found for - " + paymentPref.getString("paymentMethodTypeId"), module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, 
                    "AccountingTroubleCallingReleaseOrderPaymentPreferenceService", locale) + " " + 
                    paymentPref.getString("paymentMethodTypeId"));            
        }
        if (UtilValidate.isEmpty(paymentConfig)) {
            paymentConfig = "payment.properties";
        }
        GenericValue authTransaction = PaymentGatewayServices.getAuthTransaction(paymentPref);
        Map<String, Object> releaseContext = FastMap.newInstance();
        releaseContext.put("orderPaymentPreference", paymentPref);
        releaseContext.put("releaseAmount", authTransaction.getBigDecimal("amount"));
        releaseContext.put("currency", currency);
        releaseContext.put("paymentConfig", paymentConfig);
        releaseContext.put("paymentGatewayConfigId", paymentGatewayConfigId);
        releaseContext.put("userLogin", userLogin);
        // run the defined service
        Map<String, Object> releaseResult = null;
        try {
            releaseResult = dispatcher.runSync(serviceName, releaseContext, TX_TIME, true);
        } catch (GenericServiceException e) {
            Debug.logError(e,"Problem releasing payment", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, 
                    "AccountingTroubleCallingReleaseOrderPaymentPreferenceService", locale));    
            
        }
        // get the release result code
        if (releaseResult != null && !ServiceUtil.isError(releaseResult)) {
            Map<String, Object> releaseResRes;
            try {
                ModelService model = dctx.getModelService("processReleaseResult");
                releaseResult.put("orderPaymentPreference", paymentPref);
                releaseResult.put("userLogin", userLogin);
                Map<String, Object> resCtx = model.makeValid(releaseResult, ModelService.IN_PARAM);
                releaseResRes = dispatcher.runSync(model.name,  resCtx);
            } catch (GenericServiceException e) {
                Debug.logError(e, "Trouble processing the release results", module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, 
                        "AccountingTroubleCallingReleaseOrderPaymentPreferenceService", locale) + " " +
                        e.getMessage());
            }
            if (releaseResRes != null && ServiceUtil.isError(releaseResRes)) {
                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(releaseResRes));
            }
        } else if (ServiceUtil.isError(releaseResult)) {
            saveError(dispatcher, userLogin, paymentPref, releaseResult, RELEASE_SERVICE_TYPE, "PGT_RELEASE");
            result = ServiceUtil.returnError(ServiceUtil.getErrorMessage(releaseResult));
        }
        return result;
    }

    public static Map<String, Object> processReleaseResult(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String currencyUomId = (String) context.get("currencyUomId");
        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
        Boolean releaseResponse = (Boolean) context.get("releaseResult");
        Locale locale = (Locale) context.get("locale");
        // create the PaymentGatewayResponse
        String responseId = delegator.getNextSeqId("PaymentGatewayResponse");
        GenericValue pgResponse = delegator.makeValue("PaymentGatewayResponse");
        pgResponse.set("paymentGatewayResponseId", responseId);
        pgResponse.set("paymentServiceTypeEnumId", RELEASE_SERVICE_TYPE);
        pgResponse.set("orderPaymentPreferenceId", paymentPref.get("orderPaymentPreferenceId"));
        pgResponse.set("paymentMethodTypeId", paymentPref.get("paymentMethodTypeId"));
        pgResponse.set("paymentMethodId", paymentPref.get("paymentMethodId"));
        pgResponse.set("transCodeEnumId", "PGT_RELEASE");
        // set the release info
        pgResponse.set("amount", context.get("releaseAmount"));
        pgResponse.set("referenceNum", context.get("releaseRefNum"));
        pgResponse.set("altReference", context.get("releaseAltRefNum"));
        pgResponse.set("gatewayCode", context.get("releaseCode"));
        pgResponse.set("gatewayFlag", context.get("releaseFlag"));
        pgResponse.set("gatewayMessage", context.get("releaseMessage"));
        pgResponse.set("transactionDate", UtilDateTime.nowTimestamp());
        pgResponse.set("currencyUomId", currencyUomId);
        // store the gateway response
        savePgr(dctx, pgResponse);
        // create the internal messages
        List<String> messages = UtilGenerics.cast(context.get("internalRespMsgs"));
        if (UtilValidate.isNotEmpty(messages)) {
            Iterator<String> i = messages.iterator();
            while (i.hasNext()) {
                GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg");
                String respMsgId = delegator.getNextSeqId("PaymentGatewayRespMsg");
                String message = i.next();
                respMsg.set("paymentGatewayRespMsgId", respMsgId);
                respMsg.set("paymentGatewayResponseId", responseId);
                respMsg.set("pgrMessage", message);
                // store the messages
                savePgr(dctx, respMsg);
            }
        }

        if (releaseResponse != null && releaseResponse.booleanValue()) {
            paymentPref.set("statusId", "PAYMENT_CANCELLED");
            try {
                paymentPref.store();
            } catch (GenericEntityException e) {
                Debug.logError(e, "Problem storing updated payment preference; authorization was released!", module);
            }
            // cancel any payment records
            List<GenericValue> paymentList = null;
            try {
                paymentList = paymentPref.getRelated("Payment", null, null, false);
            } catch (GenericEntityException e) {
                Debug.logError(e, "Unable to get Payment records from OrderPaymentPreference : " + paymentPref, module);
            }
            if (paymentList != null) {
                Iterator<GenericValue> pi = paymentList.iterator();
                while (pi.hasNext()) {
                    GenericValue pay = pi.next();
                    try {
                        Map<String, Object> cancelResults = dispatcher.runSync("setPaymentStatus", UtilMisc.toMap("userLogin", userLogin, "paymentId", pay.get("paymentId"), "statusId", "PMNT_CANCELLED"));
                        if (ServiceUtil.isError(cancelResults)) {
                            throw new GenericServiceException(ServiceUtil.getErrorMessage(cancelResults));
                        }
                    } catch (GenericServiceException e) {
                        Debug.logError(e, "Unable to cancel Payment : " + pay, module);
                    }
                }
            }
        } else {
            Debug.logError("Release failed for pref : " + paymentPref, module);
            return ServiceUtil.returnFailure(UtilProperties.getMessage(resourceOrder, 
                    "AccountingTroubleCallingReleaseOrderPaymentPreferenceService", locale) + " " +
                    paymentPref);
        }
        return ServiceUtil.returnSuccess();
    }

    /**
     * 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> capturePaymentsByInvoice(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String invoiceId = (String) context.get("invoiceId");
        Locale locale = (Locale) context.get("locale");

        // lookup the invoice
        GenericValue invoice = null;
        try {
            invoice = EntityQuery.use(delegator).from("Invoice").where("invoiceId", invoiceId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, "Trouble looking up Invoice #" + invoiceId, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingInvoiceNotFound", UtilMisc.toMap("invoiceId", invoiceId), locale));
        }

        if (invoice == null) {
            Debug.logError("Could not locate invoice #" + invoiceId, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingInvoiceNotFound", UtilMisc.toMap("invoiceId", invoiceId), locale));
        }

        // get the OrderItemBilling records for this invoice
        List<GenericValue> orderItemBillings = null;
        try {
            orderItemBillings = invoice.getRelated("OrderItemBilling", null, null, false);
        } catch (GenericEntityException e) {
            Debug.logError("Trouble getting OrderItemBilling(s) from Invoice #" + invoiceId, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingProblemLookingUpOrderItemBilling", 
                    UtilMisc.toMap("billFields", invoiceId), locale));
        }

        // check for an associated billing account
        String billingAccountId = invoice.getString("billingAccountId");

        // make sure they are all for the same order
        String testOrderId = null;
        boolean allSameOrder = true;
        if (orderItemBillings != null) {
            Iterator<GenericValue> oii = orderItemBillings.iterator();
            while (oii.hasNext()) {
                GenericValue oib = oii.next();
                String orderId = oib.getString("orderId");
                if (testOrderId == null) {
                    testOrderId = orderId;
                } else {
                    if (!orderId.equals(testOrderId)) {
                        allSameOrder = false;
                        break;
                    }
                }
            }
        }

        if (testOrderId == null || !allSameOrder) {
            Debug.logWarning("Attempt to settle Invoice #" + invoiceId + " which contained none/multiple orders", module);
            return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, 
                    "AccountingInvoiceCannotBeSettle", 
                    UtilMisc.toMap("invoiceId", invoiceId), locale));
        }

        // get the invoice amount (amount to bill)
        BigDecimal invoiceTotal = InvoiceWorker.getInvoiceNotApplied(invoice);
        if (Debug.infoOn()) Debug.logInfo("(Capture) Invoice [#" + invoiceId + "] total: " + invoiceTotal, module);

        // now capture the order
        Map<String, Object> serviceContext = UtilMisc.toMap("userLogin", userLogin, "orderId", testOrderId, "invoiceId", invoiceId, "captureAmount", invoiceTotal);
        if (UtilValidate.isNotEmpty(billingAccountId)) {
            serviceContext.put("billingAccountId", billingAccountId);
        }
        try {
            return dispatcher.runSync("captureOrderPayments", serviceContext);
        } catch (GenericServiceException e) {
            Debug.logError(e, "Trouble running captureOrderPayments service", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentCannotBeCaptured", locale));
        }
    }

    /**
     * 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);

                // If we have an invoice, we find unapplied payments associated
                // 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 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) {
                            captureResult.put("captureRefNum", ""); // FIXME: this is an hack to avoid a service validation error for processCaptureResult (captureRefNum is mandatory, but it is not used for billing accounts)
                        }                                                

                        // 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.isError(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.isEmpty(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;
        }
    }

    public static Map<String, Object> processCaptureSplitPayment(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");
        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
        BigDecimal splitAmount = (BigDecimal) context.get("splitAmount");

        String orderId = paymentPref.getString("orderId");
        OrderReadHelper orh = new OrderReadHelper(delegator, orderId);

        String statusId = "PAYMENT_NOT_AUTH";
        if ("EXT_BILLACT".equals(paymentPref.getString("paymentMethodTypeId"))) {
            statusId = "PAYMENT_NOT_RECEIVED";
        } else if ("EXT_PAYPAL".equals(paymentPref.get("paymentMethodTypeId"))) {
            statusId = "PAYMENT_AUTHORIZED";
        }
        // create a new payment preference
        Debug.logInfo("Creating payment preference split", module);
        String newPrefId = delegator.getNextSeqId("OrderPaymentPreference");
        GenericValue newPref = delegator.makeValue("OrderPaymentPreference", UtilMisc.toMap("orderPaymentPreferenceId", newPrefId));
        newPref.set("orderId", paymentPref.get("orderId"));
        newPref.set("paymentMethodTypeId", paymentPref.get("paymentMethodTypeId"));
        newPref.set("paymentMethodId", paymentPref.get("paymentMethodId"));
        newPref.set("maxAmount", splitAmount);
        newPref.set("statusId", statusId);
        newPref.set("createdDate", UtilDateTime.nowTimestamp());
        if (userLogin != null) {
            newPref.set("createdByUserLogin", userLogin.getString("userLoginId"));
        }
        if (Debug.verboseOn()) Debug.logVerbose("New preference : " + newPref, module);

        Map<String, Object> processorResult = null;
        try {
            // create the new payment preference
            delegator.create(newPref);

            // PayPal requires us to reuse the existing authorization, so we'll
            // fake it and copy the existing auth with the remaining amount
            if ("EXT_PAYPAL".equals(paymentPref.get("paymentMethodTypeId"))) {
                String newAuthId = delegator.getNextSeqId("PaymentGatewayResponse");
                GenericValue authTrans = getAuthTransaction(paymentPref);
                GenericValue newAuthTrans = delegator.makeValue("PaymentGatewayResponse", authTrans);
                newAuthTrans.set("paymentGatewayResponseId", newAuthId);
                newAuthTrans.set("orderPaymentPreferenceId", newPref.get("orderPaymentPreferenceId"));
                newAuthTrans.set("amount", splitAmount);
                savePgr(dctx, newAuthTrans);
            } else if ("PAYMENT_NOT_AUTH".equals(statusId)) {
                // authorize the new preference
                processorResult = authPayment(dispatcher, userLogin, orh, newPref, splitAmount, false, null);
                if (processorResult != null) {
                    // process the auth results
                    boolean authResult = processResult(dctx, processorResult, userLogin, newPref, locale);
                    if (!authResult) {
                        Debug.logError("Authorization failed : " + newPref + " : " + processorResult, module);
                    }
                } else {
                    Debug.logError("Payment not authorized : " + newPref + " : " + processorResult, module);
                }
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, "ERROR: cannot create new payment preference : " + newPref, module);
        } catch (GeneralException e) {
            if (processorResult != null) {
                Debug.logError(e, "Trouble processing the auth result: " + newPref + " : " + processorResult, module);
            } else {
                Debug.logError(e, "Trouble authorizing the payment: " + newPref, module);
            }
        }
        return ServiceUtil.returnSuccess();
    }

    // Deprecated: use captureBillingAccountPayments instead of this.
    public static Map<String, Object> captureBillingAccountPayment(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String invoiceId = (String) context.get("invoiceId");
        String billingAccountId = (String) context.get("billingAccountId");
        BigDecimal captureAmount = (BigDecimal) context.get("captureAmount");
        String orderId = (String) context.get("orderId");
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> results = ServiceUtil.returnSuccess();

        try {
            // Note that the partyIdFrom of the Payment should be the partyIdTo of the invoice, since you're receiving a payment from the party you billed
            GenericValue invoice = EntityQuery.use(delegator).from("Invoice").where("invoiceId", invoiceId).queryOne();
            Map<String, Object> paymentParams = UtilMisc.<String, Object>toMap("paymentTypeId", "CUSTOMER_PAYMENT", "paymentMethodTypeId", "EXT_BILLACT",
                    "partyIdFrom", invoice.getString("partyId"), "partyIdTo", invoice.getString("partyIdFrom"),
                    "statusId", "PMNT_RECEIVED", "effectiveDate", UtilDateTime.nowTimestamp());
            paymentParams.put("amount", captureAmount);
            paymentParams.put("currencyUomId", invoice.getString("currencyUomId"));
            paymentParams.put("userLogin", userLogin);
            Map<String, Object> tmpResult = dispatcher.runSync("createPayment", paymentParams);
            if (ServiceUtil.isError(tmpResult)) {
                return tmpResult;
            }

            String paymentId = (String) tmpResult.get("paymentId");
            tmpResult = dispatcher.runSync("createPaymentApplication", UtilMisc.<String, Object>toMap("paymentId", paymentId, "invoiceId", invoiceId, "billingAccountId", billingAccountId,
                    "amountApplied", captureAmount, "userLogin", userLogin));
            if (ServiceUtil.isError(tmpResult)) {
                return tmpResult;
            }
            if (paymentId == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                        "AccountingNoPaymentCreatedForInvoice", 
                        UtilMisc.toMap("invoiceId", invoiceId, "billingAccountId", billingAccountId), locale));
            }
            results.put("paymentId", paymentId);

            if (orderId != null && captureAmount.compareTo(BigDecimal.ZERO) > 0) {
                // Create a paymentGatewayResponse, if necessary
                GenericValue order = EntityQuery.use(delegator).from("OrderHeader").where("orderId", orderId).queryOne();
                if (order == null) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                            "AccountingNoPaymentGatewayResponseCreatedForInvoice", 
                            UtilMisc.toMap("invoiceId", invoiceId, "billingAccountId", billingAccountId,
                                    "orderId", orderId), locale));
                }
                // See if there's an orderPaymentPreference - there should be only one OPP for EXT_BILLACT per order
                GenericValue orderPaymentPreference = EntityQuery.use(delegator).from("OrderPaymentPreference").where("orderId", orderId, "paymentMethodTypeId", "EXT_BILLACT").queryFirst();
                if (orderPaymentPreference != null) {

                    // Check the productStore setting to see if we need to do this explicitly
                    GenericValue productStore = order.getRelatedOne("ProductStore", false);
                    if (productStore.getString("manualAuthIsCapture") == null || (! productStore.getString("manualAuthIsCapture").equalsIgnoreCase("Y"))) {
                        String responseId = delegator.getNextSeqId("PaymentGatewayResponse");
                        GenericValue pgResponse = delegator.makeValue("PaymentGatewayResponse");
                        pgResponse.set("paymentGatewayResponseId", responseId);
                        pgResponse.set("paymentServiceTypeEnumId", CAPTURE_SERVICE_TYPE);
                        pgResponse.set("orderPaymentPreferenceId", orderPaymentPreference.getString("orderPaymentPreferenceId"));
                        pgResponse.set("paymentMethodTypeId", "EXT_BILLACT");
                        pgResponse.set("transCodeEnumId", "PGT_CAPTURE");
                        pgResponse.set("amount", captureAmount);
                        pgResponse.set("currencyUomId", invoice.getString("currencyUomId"));
                        pgResponse.set("transactionDate", UtilDateTime.nowTimestamp());
                        // referenceNum holds the relation to the order.
                        // todo: Extend PaymentGatewayResponse with a billingAccountId field?
                        pgResponse.set("referenceNum", billingAccountId);

                        // save the response
                        savePgr(dctx, pgResponse);

                        // Update the orderPaymentPreference
                        orderPaymentPreference.set("statusId", "PAYMENT_SETTLED");
                        orderPaymentPreference.store();

                        results.put("paymentGatewayResponseId", responseId);
                    }
                }
            }
        } catch (GenericEntityException ex) {
            return ServiceUtil.returnError(ex.getMessage());
        } catch (GenericServiceException ex) {
            return ServiceUtil.returnError(ex.getMessage());
        }

        return results;
    }

    public static Map<String, Object> captureBillingAccountPayments(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        String invoiceId = (String) context.get("invoiceId");
        String billingAccountId = (String) context.get("billingAccountId");
        BigDecimal captureAmount = (BigDecimal) context.get("captureAmount");
        captureAmount = captureAmount.setScale(decimals, rounding);
        BigDecimal capturedAmount = BigDecimal.ZERO;

        try {
            // Select all the unapplied payment applications associated to the billing account
            List<GenericValue> paymentApplications = EntityQuery.use(delegator).from("PaymentApplication")
                    .where("billingAccountId", billingAccountId, "invoiceId", null)
                    .orderBy("-amountApplied").queryList();
            if (UtilValidate.isNotEmpty(paymentApplications)) {
                Iterator<GenericValue> paymentApplicationsIt = paymentApplications.iterator();
                while (paymentApplicationsIt.hasNext()) {
                    if (capturedAmount.compareTo(captureAmount) >= 0) {
                        // we have captured all the amount required
                        break;
                    }
                    GenericValue paymentApplication = paymentApplicationsIt.next();
                    GenericValue payment = paymentApplication.getRelatedOne("Payment", false);
                    if (payment.getString("paymentPreferenceId") != null) {
                        // if the payment is reserved for a specific OrderPaymentPreference,
                        // we don't use it.
                        continue;
                    }
                    // TODO: check the statusId of the payment
                    BigDecimal paymentApplicationAmount = paymentApplication.getBigDecimal("amountApplied");
                    BigDecimal amountToCapture = paymentApplicationAmount.min(captureAmount.subtract(capturedAmount));
                    amountToCapture = amountToCapture.setScale(decimals, rounding);
                    if (amountToCapture.compareTo(paymentApplicationAmount) == 0) {
                        // apply the whole payment application to the invoice
                        paymentApplication.set("invoiceId", invoiceId);
                        paymentApplication.store();
                    } else {
                        // the amount to capture is lower than the amount available in this payment application:
                        // split the payment application into two records and apply one to the invoice
                        GenericValue newPaymentApplication = delegator.makeValue("PaymentApplication", paymentApplication);
                        String paymentApplicationId = delegator.getNextSeqId("PaymentApplication");
                        paymentApplication.set("invoiceId", invoiceId);
                        paymentApplication.set("amountApplied", amountToCapture);
                        paymentApplication.store();
                        newPaymentApplication.set("paymentApplicationId", paymentApplicationId);
                        newPaymentApplication.set("amountApplied", paymentApplicationAmount.subtract(amountToCapture));
                        newPaymentApplication.create();
                    }
                    capturedAmount = capturedAmount.add(amountToCapture);
                }
            }
        } catch (GenericEntityException ex) {
            return ServiceUtil.returnError(ex.getMessage());
        }
        capturedAmount = capturedAmount.setScale(decimals, rounding);
        Map<String, Object> results = ServiceUtil.returnSuccess();
        results.put("captureAmount", capturedAmount);
        return results;
    }

    private static Map<String, Object> capturePayment(DispatchContext dctx, GenericValue userLogin, OrderReadHelper orh, 
            GenericValue paymentPref, BigDecimal amount, Locale locale) {
        return capturePayment(dctx, userLogin, orh, paymentPref, amount, null, locale);
    }

    private static Map<String, Object> capturePayment(DispatchContext dctx, GenericValue userLogin, OrderReadHelper orh, 
            GenericValue paymentPref, BigDecimal amount, GenericValue authTrans, Locale locale) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        // look up the payment configuration settings
        String serviceName = null;
        String paymentConfig = null;
        String paymentGatewayConfigId = null;

        // get the payment settings i.e. serviceName and config properties file name
        GenericValue paymentSettings = getPaymentSettings(orh.getOrderHeader(), paymentPref, CAPTURE_SERVICE_TYPE, 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");

            if (serviceName == null) {
                Debug.logError("Service name is null for payment setting; cannot process", module);
                return null;
            }
        } else {
            Debug.logError("Invalid payment settings entity, no payment settings found", module);
            return null;
        }

        if (UtilValidate.isEmpty(paymentConfig)) {
            paymentConfig = "payment.properties";
        }

        // check the validity of the authorization; re-auth if necessary
        if (!PaymentGatewayServices.checkAuthValidity(paymentPref, paymentConfig)) {
            try {
                // re-auth required before capture
                Map<String, Object> processorResult = PaymentGatewayServices.authPayment(dispatcher, userLogin, orh, paymentPref, amount, true, null);

                boolean authResult = false;
                if (processorResult != null) {
                    // process the auth results
                    try {
                        authResult = processResult(dctx, processorResult, userLogin, paymentPref, locale);
                        if (!authResult) {
                            Debug.logError("Re-Authorization failed : " + paymentPref + " : " + processorResult, module);
                        }
                    } catch (GeneralException e) {
                        Debug.logError(e, "Trouble processing the re-auth result : " + paymentPref + " : " + processorResult, module);
                    }
                } else {
                    Debug.logError("Payment not re-authorized : " + paymentPref + " : " + processorResult, module);
                }

                if (!authResult) {
                    // returning null to cancel the capture process.
                    return null;
                }

                // get the new auth transaction
                authTrans = getAuthTransaction(paymentPref);
            } catch (GeneralException e) {
                Debug.logError(e, "Error re-authorizing payment", module);
                return ServiceUtil.returnError(UtilProperties.getMessage("AccountingUiLabels", "AccountingPaymentReauthorizingError", locale));
            }
        }

        // prepare the context for the capture service (must follow the ccCaptureInterface
        Map<String, Object> captureContext = FastMap.newInstance();
        captureContext.put("userLogin", userLogin);
        captureContext.put("orderPaymentPreference", paymentPref);
        captureContext.put("paymentConfig", paymentConfig);
        captureContext.put("paymentGatewayConfigId", paymentGatewayConfigId);
        captureContext.put("currency", orh.getCurrency());

        // this is necessary because the ccCaptureInterface uses "captureAmount" but the paymentProcessInterface uses "processAmount"
        try {
            ModelService captureService = dctx.getModelService(serviceName);
            Set<String> inParams = captureService.getInParamNames();
            if (inParams.contains("captureAmount")) {
                captureContext.put("captureAmount", amount);
            } else if (inParams.contains("processAmount")) {
                captureContext.put("processAmount", amount);
            } else {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                        "AccountingPaymentServiceMissingAmount", 
                        UtilMisc.toMap("serviceName", serviceName, "inParams", inParams), locale));
            }
        } catch (GenericServiceException ex) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentServiceCannotGetModel", 
                    UtilMisc.toMap("serviceName", serviceName), locale));
        }


        if (authTrans != null) {
            captureContext.put("authTrans", authTrans);
        }

        if (Debug.infoOn()) Debug.logInfo("Capture [" + serviceName + "] : " + captureContext, module);
        try {
            String paymentMethodTypeId = paymentPref.getString("paymentMethodTypeId");
            if (paymentMethodTypeId != null && "GIFT_CARD".equals(paymentMethodTypeId)) {
                getBillingInformation(orh, paymentPref, captureContext);
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
        // now invoke the capture service
        Map<String, Object> captureResult = null;
        try {
            // NOTE DEJ20070819 calling this with a new transaction synchronously caused a deadlock because in this
            //transaction OrderHeader was updated and with this transaction paused and waiting for the new transaction
            //and the new transaction was waiting trying to read the same OrderHeader record; note that this only happens
            //for FinAccounts because they are processed internally whereas others are not
            // NOTE HOW TO FIX: don't call in separate transaction from here; individual services can have require-new-transaction
            //set to true if they want to behave that way (had: [, TX_TIME, true])
            captureResult = dispatcher.runSync(serviceName, captureContext);
        } catch (GenericServiceException e) {
            Debug.logError(e, "Could not capture payment ... serviceName: " + serviceName + " ... context: " + captureContext, module);
            return null;
        }

        // pass the payTo partyId to the result processor; we just add it to the result context.
        String payToPartyId = getPayToPartyId(orh.getOrderHeader());
        captureResult.put("payToPartyId", payToPartyId);

        // add paymentSettings to result; for use by later processors
        captureResult.put("paymentSettings", paymentSettings);

        // pass the currencyUomId as well
        captureResult.put("currencyUomId", orh.getCurrency());

        // log the error message as a gateway response when it fails
        if (ServiceUtil.isError(captureResult)) {
            saveError(dispatcher, userLogin, paymentPref, captureResult, CAPTURE_SERVICE_TYPE, "PGT_CAPTURE");
        }

        return captureResult;
    }

    private static void saveError(LocalDispatcher dispatcher, GenericValue userLogin, GenericValue paymentPref, Map<String, Object> result, String serviceType, String transactionCode) {
        Map<String, Object> serviceContext = FastMap.newInstance();
        serviceContext.put("paymentServiceTypeEnumId", serviceType);
        serviceContext.put("orderPaymentPreference", paymentPref);
        serviceContext.put("transCodeEnumId", transactionCode);
        serviceContext.put("serviceResultMap", result);
        serviceContext.put("userLogin", userLogin);

        try {
            dispatcher.runAsync("processPaymentServiceError", serviceContext);
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
        }
    }

    public static Map<String, Object> storePaymentErrorMessage(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
        String serviceType = (String) context.get("paymentServiceTypeEnumId");
        String transactionCode = (String) context.get("transCodeEnumId");
        Map<String, Object> result = UtilGenerics.cast(context.get("serviceResultMap"));
        Locale locale = (Locale) context.get("locale");
        String responseId = delegator.getNextSeqId("PaymentGatewayResponse");
        GenericValue response = delegator.makeValue("PaymentGatewayResponse");
        String message = ServiceUtil.getErrorMessage(result);
        if (message.length() > 255) {
            message = message.substring(0, 255);
        }
        response.set("paymentGatewayResponseId", responseId);
        response.set("paymentServiceTypeEnumId", serviceType);
        response.set("orderPaymentPreferenceId", paymentPref.get("orderPaymentPreferenceId"));
        response.set("paymentMethodTypeId", paymentPref.get("paymentMethodTypeId"));
        response.set("paymentMethodId", paymentPref.get("paymentMethodId"));
        response.set("transCodeEnumId", transactionCode);
        response.set("referenceNum", "ERROR");
        response.set("gatewayMessage", message);
        response.set("transactionDate", UtilDateTime.nowTimestamp());

        try {
            delegator.create(response);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingNoPaymentGatewayResponseCreatedForFailedService", locale));
        }

        Debug.logInfo("Created PaymentGatewayResponse record for returned error", module);
        return ServiceUtil.returnSuccess();
    }

    private static boolean processResult(DispatchContext dctx, Map<String, Object> result, GenericValue userLogin, 
            GenericValue paymentPreference, Locale locale) throws GeneralException {
        Boolean authResult = (Boolean) result.get("authResult");
        Boolean captureResult = (Boolean) result.get("captureResult");
        boolean resultPassed = false;
        String initialStatus = paymentPreference.getString("statusId");
        String authServiceType = null;

        if (authResult != null) {
            processAuthResult(dctx, result, userLogin, paymentPreference);
            resultPassed = authResult.booleanValue();
            authServiceType = ("PAYMENT_NOT_AUTH".equals(initialStatus)) ? AUTH_SERVICE_TYPE : REAUTH_SERVICE_TYPE;
        }
        if (captureResult != null) {
            processCaptureResult(dctx, result, userLogin, paymentPreference, authServiceType, locale);
            if (!resultPassed)
                resultPassed = captureResult.booleanValue();
        }
        return resultPassed;
    }

    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));
        }
    }

    public static Map<String, Object> processAuthResult(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        Boolean authResult = (Boolean) context.get("authResult");
        String authType = (String) context.get("serviceTypeEnum");
        String currencyUomId = (String) context.get("currencyUomId");
        Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
        Locale locale = (Locale) context.get("locale");

        // refresh the payment preference
        try {
            orderPaymentPreference.refresh();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        // type of auth this was can be determined by the previous status
        if (UtilValidate.isEmpty(authType)) {
            authType = ("PAYMENT_NOT_AUTH".equals(orderPaymentPreference.getString("statusId"))) ? AUTH_SERVICE_TYPE : REAUTH_SERVICE_TYPE;
        }

        try {
            String paymentMethodId = orderPaymentPreference.getString("paymentMethodId");
            GenericValue paymentMethod = EntityQuery.use(delegator).from("PaymentMethod").where("paymentMethodId", paymentMethodId).queryOne();
            GenericValue creditCard = null;
            if (paymentMethod != null && "CREDIT_CARD".equals(paymentMethod.getString("paymentMethodTypeId"))) {
                creditCard = paymentMethod.getRelatedOne("CreditCard", false);
            }

            // create the PaymentGatewayResponse
            String responseId = delegator.getNextSeqId("PaymentGatewayResponse");
            GenericValue response = delegator.makeValue("PaymentGatewayResponse");
            response.set("paymentGatewayResponseId", responseId);
            response.set("paymentServiceTypeEnumId", authType);
            response.set("orderPaymentPreferenceId", orderPaymentPreference.get("orderPaymentPreferenceId"));
            response.set("paymentMethodTypeId", orderPaymentPreference.get("paymentMethodTypeId"));
            response.set("paymentMethodId", orderPaymentPreference.get("paymentMethodId"));
            response.set("transCodeEnumId", "PGT_AUTHORIZE");
            response.set("currencyUomId", currencyUomId);

            // set the avs/fraud result
            response.set("gatewayAvsResult", context.get("avsCode"));
            response.set("gatewayCvResult", context.get("cvCode"));
            response.set("gatewayScoreResult", context.get("scoreCode"));

            // set the auth info
            BigDecimal processAmount = (BigDecimal) context.get("processAmount");
            response.set("amount", processAmount);
            response.set("referenceNum", context.get("authRefNum"));
            response.set("altReference", context.get("authAltRefNum"));
            response.set("gatewayCode", context.get("authCode"));
            response.set("gatewayFlag", context.get("authFlag"));
            response.set("gatewayMessage", context.get("authMessage"));
            response.set("transactionDate", UtilDateTime.nowTimestamp());

            if (Boolean.TRUE.equals(context.get("resultDeclined"))) response.set("resultDeclined", "Y");
            if (Boolean.TRUE.equals(context.get("resultNsf"))) response.set("resultNsf", "Y");
            if (Boolean.TRUE.equals(context.get("resultBadExpire"))) response.set("resultBadExpire", "Y");
            if (Boolean.TRUE.equals(context.get("resultBadCardNumber"))) response.set("resultBadCardNumber", "Y");

            // create the internal messages
            List<GenericValue> messageEntities = FastList.newInstance();
            List<String> messages = UtilGenerics.cast(context.get("internalRespMsgs"));
            if (UtilValidate.isNotEmpty(messages)) {
                Iterator<String> i = messages.iterator();
                while (i.hasNext()) {
                    GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg");
                    String respMsgId = delegator.getNextSeqId("PaymentGatewayRespMsg");
                    String message = i.next();
                    respMsg.set("paymentGatewayRespMsgId", respMsgId);
                    respMsg.set("paymentGatewayResponseId", responseId);
                    respMsg.set("pgrMessage", message);
                    messageEntities.add(respMsg);
                }
            }

            // save the response and respective messages
            savePgrAndMsgs(dctx, response, messageEntities);

            if (response.getBigDecimal("amount").compareTo((BigDecimal)context.get("processAmount")) != 0) {
                Debug.logWarning("The authorized amount does not match the max amount : Response - " + response + " : result - " + context, module);
            }

            // set the status of the OrderPaymentPreference
            if (authResult.booleanValue()) {
                orderPaymentPreference.set("statusId", "PAYMENT_AUTHORIZED");
            } else if (!authResult.booleanValue()) {
                orderPaymentPreference.set("statusId", "PAYMENT_DECLINED");
            } else {
                orderPaymentPreference.set("statusId", "PAYMENT_ERROR");
            }

            // remove sensitive credit card data regardless of outcome
            orderPaymentPreference.set("securityCode", null);
            orderPaymentPreference.set("track2", null);

            boolean needsNsfRetry = needsNsfRetry(orderPaymentPreference, context, delegator);
            if (needsNsfRetry) {
                orderPaymentPreference.set("needsNsfRetry", "Y");
            } else {
                orderPaymentPreference.set("needsNsfRetry", "N");
            }

            orderPaymentPreference.store();

            // if the payment was declined and this is a CreditCard, save that information on the CreditCard entity
            if (!authResult.booleanValue()) {
                if (creditCard != null) {
                    Long consecutiveFailedAuths = creditCard.getLong("consecutiveFailedAuths");
                    if (consecutiveFailedAuths == null) {
                        creditCard.set("consecutiveFailedAuths", Long.valueOf(1));
                    } else {
                        creditCard.set("consecutiveFailedAuths", Long.valueOf(consecutiveFailedAuths.longValue() + 1));
                    }
                    creditCard.set("lastFailedAuthDate", nowTimestamp);

                    if (Boolean.TRUE.equals(context.get("resultNsf"))) {
                        Long consecutiveFailedNsf = creditCard.getLong("consecutiveFailedNsf");
                        if (consecutiveFailedNsf == null) {
                            creditCard.set("consecutiveFailedNsf", Long.valueOf(1));
                        } else {
                            creditCard.set("consecutiveFailedNsf", Long.valueOf(consecutiveFailedNsf.longValue() + 1));
                        }
                        creditCard.set("lastFailedNsfDate", nowTimestamp);
                    }
                    creditCard.store();
                }
            }

            // auth was successful, to clear out any failed auth or nsf info
            if (authResult.booleanValue()) {
                if ((creditCard != null) && (creditCard.get("lastFailedAuthDate") != null)) {
                    creditCard.set("consecutiveFailedAuths", Long.valueOf(0));
                    creditCard.set("lastFailedAuthDate", null);
                    creditCard.set("consecutiveFailedNsf", Long.valueOf(0));
                    creditCard.set("lastFailedNsfDate", null);
                    creditCard.store();
                }
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, "Error updating payment status information", module);
            return ServiceUtil.returnError(UtilProperties.getMessage("AccountingUiLabels", "AccountingPaymentStatusUpdatingError", UtilMisc.toMap("errorString", e.toString()), locale));
        }

        return ServiceUtil.returnSuccess();
    }

    private static boolean needsNsfRetry(GenericValue orderPaymentPreference, Map<String, ? extends Object> processContext, Delegator delegator) throws GenericEntityException {
        boolean needsNsfRetry = false;
        if (Boolean.TRUE.equals(processContext.get("resultNsf"))) {
            // only track this for auto-orders, since we will only not fail and re-try on those
            GenericValue orderHeader = orderPaymentPreference.getRelatedOne("OrderHeader", false);
            if (UtilValidate.isNotEmpty(orderHeader.getString("autoOrderShoppingListId"))) {
                GenericValue productStore = orderHeader.getRelatedOne("ProductStore", false);
                if ("Y".equals(productStore.getString("autoOrderCcTryLaterNsf"))) {
                    // one last condition: make sure there have been less than ProductStore.autoOrderCcTryLaterMax
                    //   PaymentGatewayResponse records with the same orderPaymentPreferenceId and paymentMethodId (just in case it has changed)
                    //   and that have resultNsf = Y, ie only consider other NSF responses
                    Long autoOrderCcTryLaterMax = productStore.getLong("autoOrderCcTryLaterMax");
                    if (autoOrderCcTryLaterMax != null) {
                        long failedTries = EntityQuery.use(delegator).from("PaymentGatewayResponse")
                            .where("orderPaymentPreferenceId", orderPaymentPreference.get("orderPaymentPreferenceId"),
                                    "paymentMethodId", orderPaymentPreference.get("paymentMethodId"),
                                    "resultNsf", "Y")
                            .queryCount();
                        if (failedTries < autoOrderCcTryLaterMax.longValue()) {
                            needsNsfRetry = true;
                        }
                    } else {
                        needsNsfRetry = true;
                    }
                }
            }
        }
        return needsNsfRetry;
    }

    private static GenericValue processAuthRetryResult(DispatchContext dctx, Map<String, Object> result, GenericValue userLogin, GenericValue paymentPreference) throws GeneralException {
        processAuthResult(dctx, result, userLogin, paymentPreference);
        return getAuthTransaction(paymentPreference);
    }

    private static void processCaptureResult(DispatchContext dctx, Map<String, Object> result, GenericValue userLogin, 
            GenericValue paymentPreference, Locale locale) throws GeneralException {
        processCaptureResult(dctx, result, userLogin, paymentPreference, null, locale);
    }

    private static void processCaptureResult(DispatchContext dctx, Map<String, Object> result, GenericValue userLogin, 
            GenericValue paymentPreference, String authServiceType, Locale locale) throws GeneralException {
        if (result == null) {
            throw new GeneralException("Null capture result sent to processCaptureResult; fatal error");
        }

        LocalDispatcher dispatcher = dctx.getDispatcher();
        Boolean captureResult = (Boolean) result.get("captureResult");
        BigDecimal amount = null;
        if (result.get("captureAmount") != null) {
            amount = (BigDecimal) result.get("captureAmount");
        } else if (result.get("processAmount") != null) {
            amount = (BigDecimal) result.get("processAmount");
            result.put("captureAmount", amount);
        }

        if (amount == null) {
            throw new GeneralException("Unable to process null capture amount");
        }

        // setup the amount big decimal
        amount = amount.setScale(decimals, rounding);

        result.put("orderPaymentPreference", paymentPreference);
        result.put("userLogin", userLogin);
        result.put("serviceTypeEnum", authServiceType);

        ModelService model = dctx.getModelService("processCaptureResult");
        Map<String, Object> context = model.makeValid(result, ModelService.IN_PARAM);
        Map<String, Object> capRes;
        try {
            capRes = dispatcher.runSync("processCaptureResult", context);
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            throw e;
        }
        if (capRes != null && ServiceUtil.isError(capRes)) {
            throw new GeneralException(ServiceUtil.getErrorMessage(capRes));
        }
        if (!captureResult.booleanValue()) {
            // capture returned false (error)
            try {
                processReAuthFromCaptureFailure(dctx, result, amount, userLogin, paymentPreference, locale);
            } catch (GeneralException e) {
                // just log this for now (same as previous implementation)
                Debug.logError(e, module);
            }
        }
    }

    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");
        }
    }

    public static Map<String, Object> processCaptureResult(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Locale locale = (Locale) context.get("locale");
        GenericValue paymentPreference = (GenericValue) context.get("orderPaymentPreference");
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String invoiceId = (String) context.get("invoiceId");
        String payTo = (String) context.get("payToPartyId");
        BigDecimal amount = (BigDecimal) context.get("captureAmount");
        String serviceType = (String) context.get("serviceTypeEnum");
        String currencyUomId = (String) context.get("currencyUomId");
        boolean captureSuccessful = ((Boolean) context.get("captureResult")).booleanValue();

        String paymentMethodTypeId = paymentPreference.getString("paymentMethodTypeId");

        if (UtilValidate.isEmpty(serviceType)) {
            serviceType = CAPTURE_SERVICE_TYPE;
        }

        // refresh the payment preference
        try {
            paymentPreference.refresh();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        // update the status and maxAmount
        String prefStatusId;
        if (captureSuccessful) {
            prefStatusId = "EXT_BILLACT".equals(paymentMethodTypeId) ? "PAYMENT_RECEIVED": "PAYMENT_SETTLED";
        } else {
            prefStatusId = "PAYMENT_DECLINED";
        }
        paymentPreference.set("statusId", prefStatusId);
        paymentPreference.set("maxAmount", amount);
        try {
            paymentPreference.store();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        if (!"EXT_BILLACT".equals(paymentMethodTypeId)) {
            // create the PaymentGatewayResponse record
            String responseId = delegator.getNextSeqId("PaymentGatewayResponse");
            GenericValue response = delegator.makeValue("PaymentGatewayResponse");
            response.set("paymentGatewayResponseId", responseId);
            response.set("paymentServiceTypeEnumId", serviceType);
            response.set("orderPaymentPreferenceId", paymentPreference.get("orderPaymentPreferenceId"));
            response.set("paymentMethodTypeId", paymentMethodTypeId);
            response.set("paymentMethodId", paymentPreference.get("paymentMethodId"));
            response.set("transCodeEnumId", "PGT_CAPTURE");
            response.set("currencyUomId", currencyUomId);
            if (context.get("authRefNum") != null) {
                response.set("subReference", context.get("authRefNum"));
                response.set("altReference", context.get("authAltRefNum"));
            } else {
                response.set("altReference", context.get("captureAltRefNum"));
            }

            // set the capture info
            response.set("amount", amount);
            response.set("referenceNum", context.get("captureRefNum"));
            response.set("gatewayCode", context.get("captureCode"));
            response.set("gatewayFlag", context.get("captureFlag"));
            response.set("gatewayMessage", context.get("captureMessage"));
            response.set("transactionDate", UtilDateTime.nowTimestamp());

            // save the response
            savePgr(dctx, response);

            // create the internal messages
            List<String> messages = UtilGenerics.cast(context.get("internalRespMsgs"));
            if (UtilValidate.isNotEmpty(messages)) {
                Iterator<String> i = messages.iterator();
                while (i.hasNext()) {
                    GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg");
                    String respMsgId = delegator.getNextSeqId("PaymentGatewayRespMsg");
                    String message = i.next();
                    respMsg.set("paymentGatewayRespMsgId", respMsgId);
                    respMsg.set("paymentGatewayResponseId", responseId);
                    respMsg.set("pgrMessage", message);

                    // save the message
                    savePgr(dctx, respMsg);
                }
            }

            // get the invoice
            GenericValue invoice = null;
            if (invoiceId != null) {
                try {
                    invoice = EntityQuery.use(delegator).from("Invoice").where("invoiceId", invoiceId).queryOne();
                } catch (GenericEntityException e) {
                    String message = "Failed to process capture result:  Could not find invoice ["+invoiceId+"] due to entity error: " + e.getMessage();
                    Debug.logError(e, message, module);
                    return ServiceUtil.returnError(message);
                }
            }

            // determine the partyIdFrom for the payment, which is who made the payment
            String partyIdFrom = null;
            if (invoice != null) {
                // get the party from the invoice, which is the bill-to party (partyId)
                partyIdFrom = invoice.getString("partyId");
            } else {
                // otherwise get the party from the order's OrderRole
                String orderId = paymentPreference.getString("orderId");
                GenericValue orderRole = null;
                try {
                    orderRole = EntityQuery.use(delegator).from("OrderRole").where("orderId", orderId, "roleTypeId", "BILL_TO_CUSTOMER").queryFirst();
                } catch (GenericEntityException e) {
                    Debug.logError(e, module);
                }
                if (orderRole != null) {
                    partyIdFrom = orderRole.getString("partyId");
                }
            }

            // get the partyIdTo for the payment, which is who is receiving it
            String partyIdTo = null;
            if (!UtilValidate.isEmpty(payTo)) {
                // use input pay to party
                partyIdTo = payTo;
            } else if (invoice != null) {
                // ues the invoice partyIdFrom as the pay to party (which is who supplied the invoice)
                partyIdTo = invoice.getString("partyIdFrom");
            } else {
                // otherwise default to Company and print a big warning about this
                partyIdTo = "Company";
                Debug.logWarning("Using default value of [" + partyIdTo + "] for payTo on invoice [" + invoiceId + "] and orderPaymentPreference [" +
                        paymentPreference.getString("orderPaymentPreferenceId") + "]", module);
            }


            Map<String, Object> paymentCtx = UtilMisc.<String, Object>toMap("paymentTypeId", "CUSTOMER_PAYMENT");
            paymentCtx.put("paymentMethodTypeId", paymentPreference.get("paymentMethodTypeId"));
            paymentCtx.put("paymentMethodId", paymentPreference.get("paymentMethodId"));
            paymentCtx.put("paymentGatewayResponseId", responseId);
            paymentCtx.put("partyIdTo", partyIdTo);
            paymentCtx.put("partyIdFrom", partyIdFrom);
            paymentCtx.put("statusId", "PMNT_RECEIVED");
            paymentCtx.put("paymentPreferenceId", paymentPreference.get("orderPaymentPreferenceId"));
            paymentCtx.put("amount", amount);
            paymentCtx.put("currencyUomId", currencyUomId);
            paymentCtx.put("userLogin", userLogin);
            paymentCtx.put("paymentRefNum", context.get("captureRefNum"));

            Map<String, Object> payRes;
            try {
                payRes = dispatcher.runSync("createPayment", paymentCtx);
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                        "AccountingPaymentCreationError", locale));
            }
            if (ServiceUtil.isError(payRes)) {
                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(payRes));
            }

            String paymentId = (String) payRes.get("paymentId");

            // create the PaymentApplication if invoiceId is available
            if (invoiceId != null) {
                Debug.logInfo("Processing Invoice #" + invoiceId, module);
                Map<String, Object> paCtx = UtilMisc.<String, Object>toMap("paymentId", paymentId, "invoiceId", invoiceId);
                paCtx.put("amountApplied", context.get("captureAmount"));
                paCtx.put("userLogin", userLogin);
                Map<String, Object> paRes;
                try {
                    paRes = dispatcher.runSync("createPaymentApplication", paCtx);
                } catch (GenericServiceException e) {
                    Debug.logError(e, module);
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                            "AccountingInvoiceApplicationCreationError", locale));
                }
                if (paRes != null && ServiceUtil.isError(paRes)) {
                    return ServiceUtil.returnError(ServiceUtil.getErrorMessage(paRes));
                }
            }
        }
        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object> refundOrderPaymentPreference(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String orderPaymentPreferenceId = (String) context.get("orderPaymentPreferenceId");
        BigDecimal amount = (BigDecimal) context.get("amount");
        Locale locale = (Locale) context.get("locale");
        GenericValue orderPaymentPreference = null;
        try {
            orderPaymentPreference = EntityQuery.use(delegator).from("OrderPaymentPreference").where("orderPaymentPreferenceId", orderPaymentPreferenceId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingProblemGettingOrderPaymentPreferences", locale) + " " + 
                    orderPaymentPreferenceId);
        }
        // call the service refundPayment
        Map<String, Object> refundResponse = null;
        try {
            Map<String, Object> serviceContext = FastMap.newInstance();
            serviceContext.put("orderPaymentPreference", orderPaymentPreference);
            serviceContext.put("refundAmount", amount);
            serviceContext.put("userLogin", userLogin);
            refundResponse = dispatcher.runSync("refundPayment", serviceContext, TX_TIME, true);
        } catch (GenericServiceException e) {
            Debug.logError(e, "Problem refunding payment through processor", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentRefundError", locale));
        }
        refundResponse.putAll(ServiceUtil.returnSuccess("Payment #" + refundResponse.get("paymentId") +" is refunded successfully with amount " + refundResponse.get("refundAmount") +" for manual transaction."));
        return refundResponse;
    }

    public static Map<String, Object> refundPayment(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
        BigDecimal refundAmount = (BigDecimal) context.get("refundAmount");
        Locale locale = (Locale) context.get("locale");

        GenericValue orderHeader = null;
        try {
            orderHeader = paymentPref.getRelatedOne("OrderHeader", false);
        } catch (GenericEntityException e) {
            Debug.logError(e, "Cannot get OrderHeader from OrderPaymentPreference", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingProblemGettingOrderPaymentPreferences", locale) + " " + 
                    e.toString());
        }

        OrderReadHelper orh = new OrderReadHelper(orderHeader);

        GenericValue paymentSettings = null;
        if (orderHeader != null) {
            paymentSettings = getPaymentSettings(orderHeader, paymentPref, REFUND_SERVICE_TYPE, false);
        }

        String serviceName = null;
        String paymentGatewayConfigId = null;

        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");
            }
            String paymentConfig = paymentSettings.getString("paymentPropertiesPath");
            paymentGatewayConfigId = paymentSettings.getString("paymentGatewayConfigId");

            if (serviceName != null) {
                Map<String, Object> serviceContext = FastMap.newInstance();
                serviceContext.put("orderPaymentPreference", paymentPref);
                serviceContext.put("paymentConfig", paymentConfig);
                serviceContext.put("paymentGatewayConfigId", paymentGatewayConfigId);
                serviceContext.put("currency", orh.getCurrency());

                // get the creditCard/address/email
                String payToPartyId = null;
                try {
                    payToPartyId = getBillingInformation(orh, paymentPref, FastMap.<String, Object>newInstance());
                } catch (GenericEntityException e) {
                    Debug.logError(e, "Problems getting billing information", module);
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                            "AccountingBillingAccountNotFound", UtilMisc.toMap("billingAccountId", ""), locale));
                }

                BigDecimal processAmount = refundAmount.setScale(decimals, rounding);
                serviceContext.put("refundAmount", processAmount);
                serviceContext.put("userLogin", userLogin);

                // call the service
                Map<String, Object> refundResponse = null;
                try {
                    refundResponse = dispatcher.runSync(serviceName, serviceContext, TX_TIME, true);
                } catch (GenericServiceException e) {
                    Debug.logError(e, "Problem refunding payment through processor", module);
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                            "AccountingPaymentRefundError", locale));
                }
                if (ServiceUtil.isError(refundResponse)) {
                    saveError(dispatcher, userLogin, paymentPref, refundResponse, REFUND_SERVICE_TYPE, "PGT_REFUND");
                    return ServiceUtil.returnError(ServiceUtil.getErrorMessage(refundResponse));
                }

                // get the pay to party ID for the order (will be the payFrom)
                String payFromPartyId = getPayToPartyId(orderHeader);

                // process the refund result
                Map<String, Object> refundResRes;
                try {
                    ModelService model = dctx.getModelService("processRefundResult");
                    Map<String, Object> refundResCtx = model.makeValid(context, ModelService.IN_PARAM);
                    refundResCtx.put("currencyUomId", orh.getCurrency());
                    refundResCtx.put("payToPartyId", payToPartyId);
                    refundResCtx.put("payFromPartyId", payFromPartyId);
                    refundResCtx.put("refundRefNum", refundResponse.get("refundRefNum"));
                    refundResCtx.put("refundAltRefNum", refundResponse.get("refundAltRefNum"));
                    refundResCtx.put("refundMessage", refundResponse.get("refundMessage"));
                    refundResCtx.put("refundResult", refundResponse.get("refundResult"));

                    // The refund amount could be different from what we tell the payment gateway due to issues
                    // such as having to void the entire original auth amount and re-authorize the new order total.
                    BigDecimal actualRefundAmount = (BigDecimal) refundResponse.get("refundAmount");
                    if (actualRefundAmount != null && actualRefundAmount.compareTo(processAmount) != 0) {
                        refundResCtx.put("refundAmount", refundResponse.get("refundAmount"));
                    }
                    refundResRes = dispatcher.runSync(model.name, refundResCtx);
                } catch (GenericServiceException e) {
                    Debug.logError(e, module);
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                            "AccountingPaymentRefundError", locale) + " " + e.getMessage());
                }

                return refundResRes;
            } else {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                        "AccountingPaymentRefundServiceNotDefined", locale));
            }
        } else {
            return ServiceUtil.returnFailure(UtilProperties.getMessage(resource, 
                    "AccountingPaymentSettingNotFound",
                    UtilMisc.toMap("productStoreId", orderHeader.getString("productStoreId"),
                            "transactionType", REFUND_SERVICE_TYPE), locale));
        }
    }

    public static Map<String, Object> processRefundResult(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");
        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
        String currencyUomId = (String) context.get("currencyUomId");
        String payToPartyId = (String) context.get("payToPartyId");
        String payFromPartyId = (String) context.get("payFromPartyId");

        // create the PaymentGatewayResponse record
        String responseId = delegator.getNextSeqId("PaymentGatewayResponse");
        GenericValue response = delegator.makeValue("PaymentGatewayResponse");
        response.set("paymentGatewayResponseId", responseId);
        response.set("paymentServiceTypeEnumId", REFUND_SERVICE_TYPE);
        response.set("orderPaymentPreferenceId", paymentPref.get("orderPaymentPreferenceId"));
        response.set("paymentMethodTypeId", paymentPref.get("paymentMethodTypeId"));
        response.set("paymentMethodId", paymentPref.get("paymentMethodId"));
        response.set("transCodeEnumId", "PGT_REFUND");

        // set the capture info
        response.set("amount", context.get("refundAmount"));
        response.set("currencyUomId", currencyUomId);
        response.set("referenceNum", context.get("refundRefNum"));
        response.set("altReference", context.get("refundAltRefNum"));
        response.set("gatewayCode", context.get("refundCode"));
        response.set("gatewayFlag", context.get("refundFlag"));
        response.set("gatewayMessage", context.get("refundMessage"));
        response.set("transactionDate", UtilDateTime.nowTimestamp());

        // save the response
        savePgr(dctx, response);

        // create the internal messages
        List<String> messages = UtilGenerics.cast(context.get("internalRespMsgs"));
        if (UtilValidate.isNotEmpty(messages)) {
            Iterator<String> i = messages.iterator();
            while (i.hasNext()) {
                GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg");
                String respMsgId = delegator.getNextSeqId("PaymentGatewayRespMsg");
                String message = i.next();
                respMsg.set("paymentGatewayRespMsgId", respMsgId);
                respMsg.set("paymentGatewayResponseId", responseId);
                respMsg.set("pgrMessage", message);

                // save the message
                savePgr(dctx, respMsg);
            }
        }

        Boolean refundResult = (Boolean) context.get("refundResult");
        if (refundResult != null && refundResult.booleanValue()) {

            // mark the preference as refunded
            paymentPref.set("statusId", "PAYMENT_REFUNDED");
            try {
                paymentPref.store();
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }

            // handle the (reverse) payment
            Map<String, Object> paymentCtx = UtilMisc.<String, Object>toMap("paymentTypeId", "CUSTOMER_REFUND");
            paymentCtx.put("paymentMethodTypeId", paymentPref.get("paymentMethodTypeId"));
            paymentCtx.put("paymentMethodId", paymentPref.get("paymentMethodId"));
            paymentCtx.put("paymentGatewayResponseId", responseId);
            paymentCtx.put("partyIdTo", payToPartyId);
            paymentCtx.put("partyIdFrom", payFromPartyId);
            paymentCtx.put("statusId", "PMNT_SENT");
            paymentCtx.put("paymentPreferenceId", paymentPref.get("orderPaymentPreferenceId"));
            paymentCtx.put("currencyUomId", currencyUomId);
            paymentCtx.put("amount", context.get("refundAmount"));
            paymentCtx.put("userLogin", userLogin);
            paymentCtx.put("paymentRefNum", context.get("refundRefNum"));
            paymentCtx.put("comments", "Refund");

            String paymentId = null;
            try {
                Map<String, Object> payRes = dispatcher.runSync("createPayment", paymentCtx);
                if (ModelService.RESPOND_ERROR.equals(payRes.get(ModelService.RESPONSE_MESSAGE))) {
                    return ServiceUtil.returnError((String) payRes.get(ModelService.ERROR_MESSAGE));
                } else {
                    paymentId = (String) payRes.get("paymentId");
                }
            } catch (GenericServiceException e) {
                Debug.logError(e, "Problem creating Payment", module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                        "AccountingPaymentCreationError", locale));
            }
            //Debug.logInfo("Payment created : " + paymentId, module);

            if (paymentId == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                        "AccountingPaymentCreationError", locale));
            }

            Map<String, Object> result = ServiceUtil.returnSuccess();
            result.put("paymentId", paymentId);
            result.put("refundAmount", context.get("refundAmount"));
            return result;
        } else {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentRefundError", locale));            
        }
    }

    public static Map<String, Object>retryFailedOrderAuth(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        String orderId = (String) context.get("orderId");
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Locale locale = (Locale) context.get("locale");

        // get the order header
        GenericValue orderHeader = null;
        try {
            orderHeader = EntityQuery.use(delegator).from("OrderHeader").where("orderId", orderId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.toString());
        }

        // make sure we have a valid order record
        if (orderHeader == null || orderHeader.get("statusId") == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, 
                    "OrderOrderNotFound", UtilMisc.toMap("orderId", orderId), locale));
        }

        // check the current order status
        if (!"ORDER_CREATED".equals(orderHeader.getString("statusId"))) {
            // if we are out of the created status; then we were either cancelled, rejected or approved
            Debug.logWarning("Was re-trying a failed auth for orderId [" + orderId + "] but it is not in the ORDER_CREATED status, so skipping.", module);
            return ServiceUtil.returnSuccess();
        }

        // run the auth service and check for failure(s)
        Map<String, Object> serviceResult = null;
        try {
            serviceResult = dispatcher.runSync("authOrderPayments", UtilMisc.<String, Object>toMap("orderId", orderId, "userLogin", userLogin));
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.toString());
        }
        if (ServiceUtil.isError(serviceResult)) {
            return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
        }

        // check to see if there was a processor failure
        String authResp = (String) serviceResult.get("processResult");
        if (authResp == null) {
            authResp = "ERROR";
        }

        if ("ERROR".equals(authResp)) {
            Debug.logWarning("The payment processor had a failure in processing, will not modify any status", module);
        } else {
            if ("FAILED".equals(authResp)) {
                // declined; update the order status
                OrderChangeHelper.rejectOrder(dispatcher, userLogin, orderId);
            } else if ("APPROVED".equals(authResp)) {
                // approved; update the order status
                OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId);
            }
        }

        Map<String, Object> result = ServiceUtil.returnSuccess();
        result.put("processResult", authResp);

        return result;
    }


    public static Map<String, Object>retryFailedAuths(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        GenericValue userLogin = (GenericValue) context.get("userLogin");

        // get a list of all payment prefs still pending
        List<EntityExpr> exprs = UtilMisc.toList(EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, "PAYMENT_NOT_AUTH"),
                EntityCondition.makeCondition("processAttempt", EntityOperator.GREATER_THAN, Long.valueOf(0)));

        EntityListIterator eli = null;
        try {
            eli = EntityQuery.use(delegator).from("OrderPaymentPreference")
                    .where(EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, "PAYMENT_NOT_AUTH"),
                            EntityCondition.makeCondition("processAttempt", EntityOperator.GREATER_THAN, Long.valueOf(0)))
                    .orderBy("orderId").queryIterator();
            List<String> processList = FastList.newInstance();
            if (eli != null) {
                Debug.logInfo("Processing failed order re-auth(s)", module);
                GenericValue value = null;
                while (((value = eli.next()) != null)) {
                    String orderId = value.getString("orderId");
                    if (!processList.contains(orderId)) { // just try each order once
                        try {
                            // each re-try is independent of each other; if one fails it should not effect the others
                            dispatcher.runAsync("retryFailedOrderAuth", UtilMisc.<String, Object>toMap("orderId", orderId, "userLogin", userLogin));
                            processList.add(orderId);
                        } catch (GenericServiceException e) {
                            Debug.logError(e, module);
                        }
                    }
                }
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        } finally {
            if (eli != null) {
                try {
                    eli.close();
                } catch (GenericEntityException e) {
                    Debug.logError(e, module);
                }
            }
        }

        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object>retryFailedAuthNsfs(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        GenericValue userLogin = (GenericValue) context.get("userLogin");

        // get the date/time for one week before now since we'll only retry once a week for NSFs
        Calendar calcCal = Calendar.getInstance();
        calcCal.setTimeInMillis(System.currentTimeMillis());
        calcCal.add(Calendar.WEEK_OF_YEAR, -1);
        Timestamp oneWeekAgo = new Timestamp(calcCal.getTimeInMillis());

        EntityListIterator eli = null;
        try {
            eli = EntityQuery.use(delegator).from("OrderPaymentPreference")
                    .where(EntityCondition.makeCondition("needsNsfRetry", EntityOperator.EQUALS, "Y"), 
                            EntityCondition.makeCondition(ModelEntity.STAMP_FIELD, EntityOperator.LESS_THAN_EQUAL_TO, oneWeekAgo))
                    .orderBy("orderId").queryIterator();

            List<String> processList = FastList.newInstance();
            if (eli != null) {
                Debug.logInfo("Processing failed order re-auth(s)", module);
                GenericValue value = null;
                while (((value = eli.next()) != null)) {
                    String orderId = value.getString("orderId");
                    if (!processList.contains(orderId)) { // just try each order once
                        try {
                            // each re-try is independent of each other; if one fails it should not effect the others
                            dispatcher.runAsync("retryFailedOrderAuth", UtilMisc.<String, Object>toMap("orderId", orderId, "userLogin", userLogin));
                            processList.add(orderId);
                        } catch (GenericServiceException e) {
                            Debug.logError(e, module);
                        }
                    }
                }
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        } finally {
            if (eli != null) {
                try {
                    eli.close();
                } catch (GenericEntityException e) {
                    Debug.logError(e, module);
                }
            }
        }
        return ServiceUtil.returnSuccess();
    }

    public static GenericValue getCaptureTransaction(GenericValue orderPaymentPreference) {
        GenericValue capTrans = null;
        try {
            List<String> order = UtilMisc.toList("-transactionDate");
            List<GenericValue> transactions = orderPaymentPreference.getRelated("PaymentGatewayResponse", null, order, false);
            List<EntityExpr> exprs = UtilMisc.toList(EntityCondition.makeCondition("paymentServiceTypeEnumId", EntityOperator.EQUALS, CAPTURE_SERVICE_TYPE));
            List<GenericValue> capTransactions = EntityUtil.filterByAnd(transactions, exprs);
            capTrans = EntityUtil.getFirst(capTransactions);
        } catch (GenericEntityException e) {
            Debug.logError(e, "ERROR: Problem getting capture information from PaymentGatewayResponse", module);
        }
        return capTrans;
    }

    /**
     * Gets the chronologically latest PaymentGatewayResponse from an OrderPaymentPreference which is either a PRDS_PAY_AUTH
     * or PRDS_PAY_REAUTH.  Used for capturing.
     * @param orderPaymentPreference GenericValue object of the order payment preference
     * @return return the first authorization of the order payment preference
     */
    public static GenericValue getAuthTransaction(GenericValue orderPaymentPreference) {
        return EntityUtil.getFirst(getAuthTransactions(orderPaymentPreference));
    }

    /**
     * Gets a chronologically ordered list of PaymentGatewayResponses from an OrderPaymentPreference which is either a PRDS_PAY_AUTH
     * or PRDS_PAY_REAUTH.
     * @param orderPaymentPreference GenericValue object of the order payment preference
     * @return return the authorizations of the order payment preference
     */
    public static List<GenericValue> getAuthTransactions(GenericValue orderPaymentPreference) {
        List<GenericValue> authTransactions = null;
        try {
            List<String> order = UtilMisc.toList("-transactionDate");
            List<GenericValue> transactions = orderPaymentPreference.getRelated("PaymentGatewayResponse", null, order, false);
            List<EntityExpr> exprs = UtilMisc.toList(EntityCondition.makeCondition("paymentServiceTypeEnumId", EntityOperator.EQUALS, AUTH_SERVICE_TYPE),
                    EntityCondition.makeCondition("paymentServiceTypeEnumId", EntityOperator.EQUALS, REAUTH_SERVICE_TYPE));
            authTransactions = EntityUtil.filterByOr(transactions, exprs);
        } catch (GenericEntityException e) {
            Debug.logError(e, "ERROR: Problem getting authorization information from PaymentGatewayResponse", module);
        }
        return authTransactions;
    }

    public static Timestamp getAuthTime(GenericValue orderPaymentPreference) {
        GenericValue authTrans = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
        Timestamp authTime = null;

        if (authTrans != null) {
            authTime = authTrans.getTimestamp("transactionDate");
        }

        return authTime;
    }

    public static boolean checkAuthValidity(GenericValue orderPaymentPreference, String paymentConfig) {
    	Delegator delegator = orderPaymentPreference.getDelegator();
        Timestamp authTime = PaymentGatewayServices.getAuthTime(orderPaymentPreference);
        if (authTime == null) {
            return false;
        }

        String reauthDays = null;

        GenericValue paymentMethod = null;
        try {
            paymentMethod = orderPaymentPreference.getRelatedOne("PaymentMethod", false);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }

        if (paymentMethod != null && paymentMethod.getString("paymentMethodTypeId").equals("CREDIT_CARD")) {
            GenericValue creditCard = null;
            try {
                creditCard = paymentMethod.getRelatedOne("CreditCard", false);
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }
            if (creditCard != null) {
                String cardType = creditCard.getString("cardType");
                // add more types as necessary -- maybe we should create seed data for credit card types??
                if ("CCT_DISCOVER".equals(cardType)) {
                    reauthDays = EntityUtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.disc.days", "90", delegator);
                } else if ("CCT_AMERICANEXPRESS".equals(cardType)) {
                    reauthDays = EntityUtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.amex.days", "30", delegator);
                } else if ("CCT_MASTERCARD".equals(cardType)) {
                    reauthDays = EntityUtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.mc.days", "30", delegator);
                } else if ("CCT_VISA".equals(cardType)) {
                    reauthDays = EntityUtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.visa.days", "7", delegator);
                } else {
                    reauthDays = EntityUtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.other.days", "7", delegator);
                }

            }
        } else if (paymentMethod != null && "EXT_PAYPAL".equals(paymentMethod.get("paymentMethodTypeId"))) {
            reauthDays = EntityUtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.paypal.days", "3", delegator);
        }

        if (reauthDays != null) {
            int days = 0;
            try {
                days = Integer.parseInt(reauthDays);
            } catch (Exception e) {
                Debug.logError(e, module);
            }

            if (days > 0) {
                Calendar cal = Calendar.getInstance();
                cal.setTimeInMillis(authTime.getTime());
                cal.add(Calendar.DAY_OF_YEAR, days);
                Timestamp validTime = new Timestamp(cal.getTimeInMillis());
                Timestamp nowTime = UtilDateTime.nowTimestamp();
                if (nowTime.after(validTime)) {
                    return false;
                }
            }
        }

        return true;
    }

    // safe payment gateway response store

    /**
     * Saves either a PaymentGatewayResponse or PaymentGatewayRespMsg value and ensures that the value
     * is persisted even in the event of a rollback.
     * @param dctx
     * @param pgr Either a PaymentGatewayResponse or PaymentGatewayRespMsg GenericValue
     */
    private static void savePgr(DispatchContext dctx, GenericValue pgr) {
        Map<String, GenericValue> context = UtilMisc.<String, GenericValue>toMap("paymentGatewayResponse", pgr);
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();

        try {
            dispatcher.addRollbackService("savePaymentGatewayResponse", context, true);
            delegator.create(pgr);
        } catch (Exception e) {
            Debug.logError(e, module);
        }
    }

    private static void savePgrAndMsgs(DispatchContext dctx, GenericValue pgr, List<GenericValue> messages) {
        Map<String, GenericValue> context = UtilMisc.<String, GenericValue>toMap("paymentGatewayResponse", pgr, "messages", messages);
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();

        try {
            dispatcher.addRollbackService("savePaymentGatewayResponseAndMessages", context, true);
            delegator.create(pgr);
            for (GenericValue message : messages) {
                delegator.create(message);
            }
        } catch (Exception e) {
            Debug.logError(e, module);
        }
    }

    public static Map<String, Object> savePaymentGatewayResponse(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        GenericValue pgr = (GenericValue) context.get("paymentGatewayResponse");
        if ("PaymentGatewayResponse".equals(pgr.getEntityName())) {
            String message = pgr.getString("gatewayMessage");
            if (UtilValidate.isNotEmpty(message) && message.length() > 255) {
                pgr.set("gatewayMessage", message.substring(0, 255));
            }
        }

        try {
            delegator.create(pgr);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }

        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object> savePaymentGatewayResponseAndMessages(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        GenericValue pgr = (GenericValue) context.get("paymentGatewayResponse");
        String gatewayMessage = pgr.getString("gatewayMessage");
        if (UtilValidate.isNotEmpty(gatewayMessage) && gatewayMessage.length() > 255) {
            pgr.set("gatewayMessage", gatewayMessage.substring(0, 255));
        }
        @SuppressWarnings("unchecked")
        List<GenericValue> messages = (List<GenericValue>) context.get("messages");

        try {
            delegator.create(pgr);
            for (GenericValue message : messages) {
                delegator.create(message);
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }

        return ServiceUtil.returnSuccess();
    }

    // manual auth service
    public static Map<String, Object> processManualCcAuth(DispatchContext dctx, Map<String, ? extends Object> context) {
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Locale locale = (Locale) context.get("locale");
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Security security = dctx.getSecurity();

        // security check
        if (!security.hasEntityPermission("MANUAL", "_PAYMENT", userLogin) && !security.hasEntityPermission("ACCOUNTING", "_CREATE", userLogin)) {
            Debug.logWarning("**** Security [" + (new Date()).toString() + "]: " + userLogin.get("userLoginId") + " attempt to run manual payment transaction!", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentTransactionNotAuthorized", locale));
        }

        String paymentMethodId = (String) context.get("paymentMethodId");
        String productStoreId = (String) context.get("productStoreId");
        String securityCode = (String) context.get("securityCode");
        BigDecimal amount = (BigDecimal) context.get("amount");

        // check the payment method; verify type
        GenericValue paymentMethod;
        try {
            paymentMethod = EntityQuery.use(delegator).from("PaymentMethod").where("paymentMethodId", paymentMethodId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        if (paymentMethod == null || !"CREDIT_CARD".equals(paymentMethod.getString("paymentMethodTypeId"))) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentManualAuthOnlyForCreditCard", locale));
        }

        // get the billToParty object
        GenericValue billToParty;
        try {
            billToParty = paymentMethod.getRelatedOne("Party", false);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        // get the credit card object
        GenericValue creditCard;
        try {
            creditCard = EntityQuery.use(delegator).from("CreditCard").where("paymentMethodId", paymentMethodId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }
        if (UtilValidate.isEmpty(creditCard)) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentCreditCardNotFound",
                    UtilMisc.toMap("paymentMethodId", paymentMethodId), locale));
        }

        // get the transaction settings
        String paymentService = null;
        String paymentConfig = null;
        String paymentGatewayConfigId = null;

        GenericValue paymentSettings = ProductStoreWorker.getProductStorePaymentSetting(delegator, productStoreId, "CREDIT_CARD", "PRDS_PAY_AUTH", false);
        if (paymentSettings == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentSettingNotFound",
                    UtilMisc.toMap("productStoreId", productStoreId, "transactionType", ""), locale));
        } else {
            String customMethodId = paymentSettings.getString("paymentCustomMethodId");
            if (UtilValidate.isNotEmpty(customMethodId)) {
                paymentService = getPaymentCustomMethod(delegator, customMethodId);
            }
            if (UtilValidate.isEmpty(paymentService)) {
                paymentService = paymentSettings.getString("paymentService");
            }
            paymentConfig = paymentSettings.getString("paymentPropertiesPath");
            paymentGatewayConfigId = paymentSettings.getString("paymentGatewayConfigId");
            if (UtilValidate.isEmpty(paymentConfig)) {
                paymentConfig = "payment.properties";
            }
        }

        // prepare the order payment preference (facade)
        GenericValue orderPaymentPref = delegator.makeValue("OrderPaymentPreference", FastMap.newInstance());
        orderPaymentPref.set("orderPaymentPreferenceId", "_NA_");
        orderPaymentPref.set("orderId", "_NA_");
        orderPaymentPref.set("presentFlag", "N");
        orderPaymentPref.set("overflowFlag", "Y");
        orderPaymentPref.set("paymentMethodTypeId", "CREDIT_CARD");
        orderPaymentPref.set("paymentMethodId", paymentMethodId);
        if (UtilValidate.isNotEmpty(securityCode)) {
            orderPaymentPref.set("securityCode", securityCode);
        }
        // this record is not to be stored, just passed to the service for use

        // get the default currency
        String currency = EntityUtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD", delegator);

        // prepare the auth context
        Map<String, Object> authContext = FastMap.newInstance();
        authContext.put("orderId", "_NA_");
        authContext.put("orderItems", FastList.newInstance());
        authContext.put("orderPaymentPreference", orderPaymentPref);
        authContext.put("creditCard", creditCard);
        authContext.put("billToParty", billToParty);
        authContext.put("currency", currency);
        authContext.put("paymentConfig", paymentConfig);
        authContext.put("paymentGatewayConfigId", paymentGatewayConfigId);
        authContext.put("processAmount", amount);
        authContext.put("userLogin", userLogin);

        // call the auth service
        Map<String, Object> response;
        try {
            Debug.logInfo("Running authorization service: " + paymentService, module);
            response = dispatcher.runSync(paymentService, authContext, TX_TIME, true);
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentServiceError",
                    UtilMisc.toMap("paymentService", paymentService, "authContext", authContext),
                    locale));
        }
        if (ServiceUtil.isError(response)) {
            return ServiceUtil.returnError(ServiceUtil.getErrorMessage(response));
        }

        Boolean authResult = (Boolean) response.get("authResult");
        Debug.logInfo("Authorization service returned: " + authResult, module);
        if (authResult != null && authResult) {
            return ServiceUtil.returnSuccess();
        } else {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                    "AccountingPaymentAuthorizationFailed",    locale));
        }
    }

    // manual processing service
    public static Map<String, Object> processManualCcTx(DispatchContext dctx, Map<String, ? extends Object> context) {
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Locale locale = (Locale) context.get("locale");
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Security security = dctx.getSecurity();
        // security check
        if (!security.hasEntityPermission("MANUAL", "_PAYMENT", userLogin) && !security.hasEntityPermission("ACCOUNTING", "_CREATE", userLogin)) {
            Debug.logWarning("**** Security [" + (new Date()).toString() + "]: " + userLogin.get("userLoginId") + " attempt to run manual payment transaction!", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentTransactionNotAuthorized", locale));
        }
        String orderPaymentPreferenceId = (String) context.get("orderPaymentPreferenceId");
        String paymentMethodTypeId = (String) context.get("paymentMethodTypeId");
        String productStoreId = (String) context.get("productStoreId");
        String transactionType = (String) context.get("transactionType");
        String referenceCode = (String) context.get("referenceCode");
        if (referenceCode == null) {
            referenceCode = Long.valueOf(System.currentTimeMillis()).toString();
        }
        // Get the OrderPaymentPreference
        GenericValue paymentPref = null;
        try {
            paymentPref = EntityQuery.use(delegator).from("OrderPaymentPreference").where("orderPaymentPreferenceId", orderPaymentPreferenceId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logWarning(e, "Problem getting OrderPaymentPreference for orderPaymentPreferenceId " + 
                    orderPaymentPreferenceId, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingProblemGettingOrderPaymentPreferences", locale) + " " + 
                    orderPaymentPreferenceId);
        }
        // Error if no OrderPaymentPreference was found
        if (paymentPref == null) {
            Debug.logWarning("Could not find OrderPaymentPreference with orderPaymentPreferenceId: " + 
                    orderPaymentPreferenceId, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingProblemGettingOrderPaymentPreferences", locale) + " " + 
                    orderPaymentPreferenceId);            
        }
        // Get the OrderHeader
        GenericValue orderHeader = null;
        String orderId = paymentPref.getString("orderId");
        try {
            orderHeader = EntityQuery.use(delegator).from("OrderHeader").where("orderId", orderId).queryOne();
        } catch (GenericEntityException e) {
            Debug.logWarning(e, "Problem getting OrderHeader for orderId " + orderId, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, 
                    "OrderOrderNotFound", UtilMisc.toMap("orderId", orderId), locale));
        }
        // Error if no OrderHeader was found
        if (orderHeader == null) {
            Debug.logWarning("Could not find OrderHeader with orderId: " + orderId + "; not processing payments.", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceOrder, 
                    "OrderOrderNotFound", UtilMisc.toMap("orderId", orderId), locale));
        }
        OrderReadHelper orh = new OrderReadHelper(orderHeader);
        // check valid implemented types
        if (!transactionType.equals(CREDIT_SERVICE_TYPE)) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                    "AccountingPaymentTransactionNotYetSupported",    locale));
        }
        // transaction request context
        Map<String, Object> requestContext = FastMap.newInstance();
        String paymentService = null;
        String paymentConfig = null;
        String paymentGatewayConfigId = null;
        // get the transaction settings
        GenericValue paymentSettings = ProductStoreWorker.getProductStorePaymentSetting(delegator, productStoreId, paymentMethodTypeId, transactionType, false);
        if (paymentSettings == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentSettingNotFound",
                    UtilMisc.toMap("productStoreId", productStoreId, "transactionType", transactionType), locale));
        } else {
            paymentGatewayConfigId = paymentSettings.getString("paymentGatewayConfigId");
            String customMethodId = paymentSettings.getString("paymentCustomMethodId");
            if (UtilValidate.isNotEmpty(customMethodId)) {
                paymentService = getPaymentCustomMethod(delegator, customMethodId);
            }
            if (UtilValidate.isEmpty(paymentService)) {
                paymentService = paymentSettings.getString("paymentService");
            }
            paymentConfig = paymentSettings.getString("paymentPropertiesPath");
            if (paymentConfig == null) {
                paymentConfig = "payment.properties";
            }
            requestContext.put("paymentConfig", paymentConfig);
            requestContext.put("paymentGatewayConfigId", paymentGatewayConfigId);
        }
        // check the service name
        if (paymentService == null || paymentGatewayConfigId == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentSettingNotValid", locale));
        }

        if (paymentMethodTypeId.equals("CREDIT_CARD")) {
            GenericValue creditCard = delegator.makeValue("CreditCard");
            creditCard.setAllFields(context, true, null, null);
            if (creditCard.get("firstNameOnCard") == null || creditCard.get("lastNameOnCard") == null || creditCard.get("cardType") == null || creditCard.get("cardNumber") == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                        "AccountingPaymentCreditCardMissingMandatoryFields", locale));
            }
            String expMonth = (String) context.get("expMonth");
            String expYear = (String) context.get("expYear");
            String expDate = expMonth + "/" + expYear;
            creditCard.set("expireDate", expDate);
            requestContext.put("creditCard", creditCard);
            requestContext.put("cardSecurityCode", context.get("cardSecurityCode"));
            GenericValue billingAddress = delegator.makeValue("PostalAddress");
            billingAddress.setAllFields(context, true, null, null);
            if (billingAddress.get("address1") == null || billingAddress.get("city") == null || billingAddress.get("postalCode") == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                        "AccountingPaymentCreditCardBillingAddressMssingMandatoryFields", locale));
            }
            requestContext.put("billingAddress", billingAddress);
            GenericValue billToEmail = delegator.makeValue("ContactMech");
            billToEmail.set("infoString", context.get("infoString"));
            if (billToEmail.get("infoString") == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                        "AccountingPaymentCreditCardEmailAddressCannotBeEmpty", locale));
            }
            requestContext.put("billToParty", orh.getBillToParty());
            requestContext.put("billToEmail", billToEmail);
            requestContext.put("referenceCode", referenceCode);
            String currency = EntityUtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD", delegator);
            requestContext.put("currency", currency);
            requestContext.put("creditAmount", context.get("amount"));
        } else {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentTransactionNotYetSupported", locale) + " " + paymentMethodTypeId);
        }
        // process the transaction
        Map<String, Object> response = null;
        try {
            response = dispatcher.runSync(paymentService, requestContext, TX_TIME, true);
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentServiceError",
                    UtilMisc.toMap("paymentService", paymentService, "authContext", requestContext),
                    locale));
        }
        // get the response result code
        if (response != null && !ServiceUtil.isError(response)) {
            Map<String, Object> responseRes;
            try {
                ModelService model = dctx.getModelService("processCreditResult");
                response.put("orderPaymentPreference", paymentPref);
                response.put("userLogin", userLogin);
                Map<String, Object> resCtx = model.makeValid(response, ModelService.IN_PARAM);
                responseRes = dispatcher.runSync(model.name,  resCtx);
            } catch (GenericServiceException e) {
                Debug.logError(e, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                        "AccountingPaymentCreditError",
                        UtilMisc.toMap("errorString", e.getMessage()), locale));
            }
            if (responseRes != null && ServiceUtil.isError(responseRes)) {
                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(responseRes));
            }
        } else if (ServiceUtil.isError(response)) {
            saveError(dispatcher, userLogin, paymentPref, response, CREDIT_SERVICE_TYPE, "PGT_CREDIT");
            return ServiceUtil.returnError(ServiceUtil.getErrorMessage(response));
        }
        // check for errors
        if (ServiceUtil.isError(response)) {
            return ServiceUtil.returnError(ServiceUtil.makeErrorMessage(response, null, null, null, null));
        }
        // get the reference number
        String refNum = (String) response.get("creditRefNum");
        String code = (String) response.get("creditCode");
        String msg = (String) response.get("creditMessage");
        Map<String, Object> returnResults = ServiceUtil.returnSuccess(UtilProperties.getMessage(resource, 
                "AccountingPaymentTransactionManualResult",
                UtilMisc.toMap("msg", msg, "code", code, "refNum", refNum), locale));
        returnResults.put("referenceNum", refNum);
        return returnResults;
    }

    // Verify Credit Card (Manually) Service
    public static Map<String, Object>verifyCreditCard(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        String productStoreId = (String) context.get("productStoreId");
        String mode = (String) context.get("mode");
        String paymentMethodId = (String) context.get("paymentMethodId");
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Locale locale = (Locale) context.get("locale");
        if (Debug.infoOn()) Debug.logInfo("Running verifyCreditCard [ " + paymentMethodId + "] for store: " + productStoreId, module);

        GenericValue productStore = null;
        productStore = ProductStoreWorker.getProductStore(productStoreId, delegator);

        String productStorePaymentProperties = "payment.properties";
        if (productStore != null) {
            productStorePaymentProperties = ProductStoreWorker.getProductStorePaymentProperties(delegator, productStoreId, "CREDIT_CARD", "PRDS_PAY_AUTH", false);
        }

        String amount = null;
        if (mode.equalsIgnoreCase("CREATE")) {
            amount = EntityUtilProperties.getPropertyValue(productStorePaymentProperties, "payment.general.cc_create.auth", delegator);
        } else if (mode.equalsIgnoreCase("UPDATE")) {
            amount = EntityUtilProperties.getPropertyValue(productStorePaymentProperties, "payment.general.cc_update.auth", delegator);
        }
        if (Debug.infoOn()) Debug.logInfo("Running credit card verification [" + paymentMethodId + "] (" + amount + ") : " + productStorePaymentProperties + " : " + mode, module);

        if (UtilValidate.isNotEmpty(amount)) {
            BigDecimal authAmount = new BigDecimal(amount);
            if (authAmount.compareTo(BigDecimal.ZERO) > 0) {
                Map<String, Object> ccAuthContext = FastMap.newInstance();
                ccAuthContext.put("paymentMethodId", paymentMethodId);
                ccAuthContext.put("productStoreId", productStoreId);
                ccAuthContext.put("amount", authAmount);
                ccAuthContext.put("userLogin", userLogin);

                Map<String, Object> results;
                try {
                    results = dispatcher.runSync("manualForcedCcAuthTransaction", ccAuthContext);
                } catch (GenericServiceException e) {
                    Debug.logError(e, module);
                    return ServiceUtil.returnError(e.getMessage());
                }

                if (ServiceUtil.isError(results)) {
                    return ServiceUtil.returnError(UtilProperties.getMessage("AccountingUiLabels", "AccountingCreditCardManualAuthFailedError", locale));
                }
            }
        }

        return ServiceUtil.returnSuccess();
    }

    // ****************************************************
    // Test Services
    // ****************************************************


    /**
     * Simple test processor; declines all orders < 100.00; approves all orders >= 100.00
     */
    public static Map<String, Object> testProcessor(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = FastMap.newInstance();
        BigDecimal processAmount = (BigDecimal) context.get("processAmount");

        if (processAmount != null && processAmount.compareTo(new BigDecimal("100.00")) >= 0)
            result.put("authResult", Boolean.TRUE);
        if (processAmount != null && processAmount.compareTo(new BigDecimal("100.00")) < 0)
            result.put("authResult", Boolean.FALSE);
            result.put("customerRespMsgs", UtilMisc.toList(UtilProperties.getMessage(resource, 
                    "AccountingPaymentTestProcessorMinimumPurchase", locale)));
        if (processAmount == null)
            result.put("authResult", null);

        String refNum = UtilDateTime.nowAsString();

        result.put("processAmount", context.get("processAmount"));
        result.put("authRefNum", refNum);
        result.put("authAltRefNum", refNum);
        result.put("authFlag", "X");
        result.put("authMessage", UtilProperties.getMessage(resource, "AccountingPaymentTestProcessor", locale));
        result.put("internalRespMsgs", UtilMisc.toList(UtilProperties.getMessage(resource, 
                "AccountingPaymentTestProcessor", locale)));
        return result;
    }


    /**
     * Simple test processor; declines all orders < 100.00; approves all orders > 100.00
     */
    public static Map<String, Object> testProcessorWithCapture(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = FastMap.newInstance();
        BigDecimal processAmount = (BigDecimal) context.get("processAmount");

        if (processAmount != null && processAmount.compareTo(new BigDecimal("100.00")) >= 0)
            result.put("authResult", Boolean.TRUE);
            result.put("captureResult", Boolean.TRUE);
        if (processAmount != null && processAmount.compareTo(new BigDecimal("100.00")) < 0)
            result.put("authResult", Boolean.FALSE);
            result.put("captureResult", Boolean.FALSE);
            result.put("customerRespMsgs", UtilMisc.toList(UtilProperties.getMessage(resource, 
                    "AccountingPaymentTestProcessorMinimumPurchase", locale)));
        if (processAmount == null)
            result.put("authResult", null);

        String refNum = UtilDateTime.nowAsString();

        result.put("processAmount", context.get("processAmount"));
        result.put("authRefNum", refNum);
        result.put("authAltRefNum", refNum);
        result.put("captureRefNum", refNum);
        result.put("captureAltRefNum", refNum);
        result.put("authCode", "100");
        result.put("captureCode", "200");
        result.put("authFlag", "X");
        result.put("authMessage", UtilMisc.toList(UtilProperties.getMessage(resource, 
                "AccountingPaymentTestCapture", locale)));
        result.put("internalRespMsgs", UtilMisc.toList(UtilProperties.getMessage(resource, 
                "AccountingPaymentTestCapture", locale)));
        return result;
    }

    /**
     *  Test authorize - does random declines
     */
    public static Map<String, Object> testRandomAuthorize(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = ServiceUtil.returnSuccess();
        String refNum = UtilDateTime.nowAsString();
        Random r = new Random();
        int i = r.nextInt(9);
        if (i < 5 || i % 2 == 0) {
            result.put("authResult", Boolean.TRUE);
            result.put("authFlag", "A");
        } else {
            result.put("authResult", Boolean.FALSE);
            result.put("authFlag", "D");
        }

        result.put("processAmount", context.get("processAmount"));
        result.put("authRefNum", refNum);
        result.put("authAltRefNum", refNum);
        result.put("authCode", "100");
        result.put("authMessage", UtilProperties.getMessage(resource, 
                "AccountingPaymentTestCapture", locale));

        return result;
    }

    /**
     * Always approve processor.
     */
    public static Map<String, Object> alwaysApproveProcessor(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = FastMap.newInstance();
        Debug.logInfo("Test Processor Approving Credit Card", module);

        String refNum = UtilDateTime.nowAsString();

        result.put("authResult", Boolean.TRUE);
        result.put("processAmount", context.get("processAmount"));
        result.put("authRefNum", refNum);
        result.put("authAltRefNum", refNum);
        result.put("authCode", "100");
        result.put("authFlag", "A");
        result.put("authMessage", UtilProperties.getMessage(resource, 
                "AccountingPaymentTestProcessor", locale));
        return result;
    }

    public static Map<String, Object> alwaysApproveWithCapture(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = FastMap.newInstance();
        String refNum = UtilDateTime.nowAsString();
        Debug.logInfo("Test Processor Approving Credit Card with Capture", module);

        result.put("authResult", Boolean.TRUE);
        result.put("captureResult", Boolean.TRUE);
        result.put("processAmount", context.get("processAmount"));
        result.put("authRefNum", refNum);
        result.put("authAltRefNum", refNum);
        result.put("captureRefNum", refNum);
        result.put("captureAltRefNum", refNum);
        result.put("authCode", "100");
        result.put("captureCode", "200");
        result.put("authFlag", "A");
        result.put("authMessage", UtilProperties.getMessage(resource, 
                "AccountingPaymentTestCapture", locale));
        return result;
    }


    /**
     * Always decline processor
     */
    public static Map<String, Object> alwaysDeclineProcessor(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = ServiceUtil.returnSuccess();
        BigDecimal processAmount = (BigDecimal) context.get("processAmount");
        Debug.logInfo("Test Processor Declining Credit Card", module);

        String refNum = UtilDateTime.nowAsString();

        result.put("authResult", Boolean.FALSE);
        result.put("processAmount", processAmount);
        result.put("authRefNum", refNum);
        result.put("authAltRefNum", refNum);
        result.put("authFlag", "D");
        result.put("authMessage", UtilProperties.getMessage(resource, 
                "AccountingPaymentTestProcessorDeclined", locale));
        return result;
    }

    /**
     * Always NSF (not sufficient funds) processor
     */
    public static Map<String, Object> alwaysNsfProcessor(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = ServiceUtil.returnSuccess();
        BigDecimal processAmount = (BigDecimal) context.get("processAmount");
        Debug.logInfo("Test Processor NSF Credit Card", module);

        String refNum = UtilDateTime.nowAsString();

        result.put("authResult", Boolean.FALSE);
        result.put("resultNsf", Boolean.TRUE);
        result.put("processAmount", processAmount);
        result.put("authRefNum", refNum);
        result.put("authAltRefNum", refNum);
        result.put("authFlag", "N");
        result.put("authMessage", UtilProperties.getMessage(resource, 
                "AccountingPaymentTestProcessor", locale));
        return result;
    }

    /**
     * Always fail/bad expire date processor
     */
    public static Map<String, Object> alwaysBadExpireProcessor(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = ServiceUtil.returnSuccess();
        BigDecimal processAmount = (BigDecimal) context.get("processAmount");
        Debug.logInfo("Test Processor Bad Expire Date Credit Card", module);

        String refNum = UtilDateTime.nowAsString();

        result.put("authResult", Boolean.FALSE);
        result.put("resultBadExpire", Boolean.TRUE);
        result.put("processAmount", processAmount);
        result.put("authRefNum", refNum);
        result.put("authAltRefNum", refNum);
        result.put("authFlag", "E");
        result.put("authMessage", UtilProperties.getMessage(resource, 
                "AccountingPaymentTestProcessor", locale));
        return result;
    }

    /**
     * Fail/bad expire date when year is even processor
     */
    public static Map<String, Object>badExpireEvenProcessor(DispatchContext dctx, Map<String, ? extends Object> context) {
        GenericValue creditCard = (GenericValue) context.get("creditCard");
        String expireDate = creditCard.getString("expireDate");
        String lastNumberStr = expireDate.substring(expireDate.length() - 1);
        int lastNumber = Integer.parseInt(lastNumberStr);

        if (lastNumber % 2.0 == 0.0) {
            return alwaysBadExpireProcessor(dctx, context);
        } else {
            return alwaysApproveProcessor(dctx, context);
        }
    }

    /**
     * Always bad card number processor
     */
    public static Map<String, Object> alwaysBadCardNumberProcessor(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = ServiceUtil.returnSuccess();
        BigDecimal processAmount = (BigDecimal) context.get("processAmount");
        Debug.logInfo("Test Processor Bad Card Number Credit Card", module);

        String refNum = UtilDateTime.nowAsString();

        result.put("authResult", Boolean.FALSE);
        result.put("resultBadCardNumber", Boolean.TRUE);
        result.put("processAmount", processAmount);
        result.put("authRefNum", refNum);
        result.put("authAltRefNum", refNum);
        result.put("authFlag", "N");
        result.put("authMessage", UtilProperties.getMessage(resource, "AccountingPaymentTestBadCardNumber", locale));
        return result;
    }

    /**
     * Always fail (error) processor
     */
    public static Map<String, Object> alwaysFailProcessor(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                "AccountingPaymentTestAuthorizationAlwaysFailed", locale));
    }

    public static Map<String, Object> testRelease(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = ServiceUtil.returnSuccess();

        String refNum = UtilDateTime.nowAsString();

        result.put("releaseResult", Boolean.TRUE);
        result.put("releaseAmount", context.get("releaseAmount"));
        result.put("releaseRefNum", refNum);
        result.put("releaseAltRefNum", refNum);
        result.put("releaseFlag", "U");
        result.put("releaseMessage", UtilProperties.getMessage(resource, "AccountingPaymentTestRelease", locale));
        return result;
    }

    /**
     * Test capture service (returns true)
     */
    public static Map<String, Object> testCapture(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = ServiceUtil.returnSuccess();
        Debug.logInfo("Test Capture Process", module);

        String refNum = UtilDateTime.nowAsString();

        result.put("captureResult", Boolean.TRUE);
        result.put("captureAmount", context.get("captureAmount"));
        result.put("captureRefNum", refNum);
        result.put("captureAltRefNum", refNum);
        result.put("captureFlag", "C");
        result.put("captureMessage", UtilProperties.getMessage(resource, "AccountingPaymentTestCapture", locale));
        return result;
    }

    /**
     * Always decline processor
     */
    public static Map<String, Object> testCCProcessorCaptureAlwaysDecline(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = ServiceUtil.returnSuccess();
        BigDecimal processAmount = (BigDecimal) context.get("captureAmount");
        Debug.logInfo("Test Processor Declining Credit Card capture", module);

        String refNum = UtilDateTime.nowAsString();

        result.put("captureResult", Boolean.FALSE);
        result.put("captureAmount", processAmount);
        result.put("captureRefNum", refNum);
        result.put("captureAltRefNum", refNum);
        result.put("captureFlag", "D");
        result.put("captureMessage", UtilProperties.getMessage(resource, "AccountingPaymentTestCaptureDeclined", locale));
        return result;
    }

    public static Map<String, Object> testCaptureWithReAuth(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
        GenericValue authTransaction = (GenericValue) context.get("authTrans");
        Debug.logInfo("Test Capture with 2 minute delay failure/re-auth process", module);

        if (authTransaction == null) {
            authTransaction = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
        }

        if (authTransaction == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, 
                    "AccountingPaymentCannotBeCaptured", locale));
        }
        Timestamp txStamp = authTransaction.getTimestamp("transactionDate");
        Timestamp nowStamp = UtilDateTime.nowTimestamp();

        Map<String, Object> result = ServiceUtil.returnSuccess();
        result.put("captureAmount", context.get("captureAmount"));
        result.put("captureRefNum", UtilDateTime.nowAsString());

        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(txStamp.getTime());
        cal.add(Calendar.MINUTE, 2);
        Timestamp twoMinAfter = new Timestamp(cal.getTimeInMillis());
        if (Debug.infoOn()) Debug.logInfo("Re-Auth Capture Test : Tx Date - " + txStamp + " : 2 Min - " + twoMinAfter + " : Now - " + nowStamp, module);

        if (nowStamp.after(twoMinAfter)) {
            result.put("captureResult", Boolean.FALSE);
        } else {
            result.put("captureResult", Boolean.TRUE);
            result.put("captureFlag", "C");
            result.put("captureMessage", UtilProperties.getMessage(resource, "AccountingPaymentTestCaptureWithReauth", locale));
        }

        return result;
    }

    /**
     * Test refund service (returns true)
     */
    public static Map<String, Object> testRefund(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = ServiceUtil.returnSuccess();
        Debug.logInfo("Test Refund Process", module);

        result.put("refundResult", Boolean.TRUE);
        result.put("refundAmount", context.get("refundAmount"));
        result.put("refundRefNum", UtilDateTime.nowAsString());
        result.put("refundFlag", "R");
        result.put("refundMessage", UtilProperties.getMessage(resource, "AccountingPaymentTestRefund", locale));
        
        return result;
    }

    public static Map<String, Object> testRefundFailure(DispatchContext dctx, Map<String, ? extends Object> context) {
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = ServiceUtil.returnSuccess();
        Debug.logInfo("Test Refund Process", module);

        result.put("refundResult", Boolean.FALSE);
        result.put("refundAmount", context.get("refundAmount"));
        result.put("refundRefNum", UtilDateTime.nowAsString());
        result.put("refundFlag", "R");
        result.put("refundMessage", UtilProperties.getMessage(resource, "AccountingPaymentTestRefundFailure", locale));
        
        return result;
    }

    public static String getPaymentCustomMethod(Delegator delegator, String customMethodId) {
        String serviceName = null;
        GenericValue customMethod = null;
        try {
            customMethod = EntityQuery.use(delegator).from("CustomMethod").where("customMethodId", customMethodId).queryOne();
            if (UtilValidate.isNotEmpty(customMethod)) {
                serviceName = customMethod.getString("customMethodName");
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
        return serviceName;
    }

    public static boolean isReplacementOrder(GenericValue orderHeader) {
        boolean replacementOrderFlag = false;

        List<GenericValue> returnItemResponses = FastList.newInstance();
        try {
            returnItemResponses = orderHeader.getRelated("ReplacementReturnItemResponse", null, null, false);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return replacementOrderFlag;
        }
        if (UtilValidate.isNotEmpty(returnItemResponses)) {
            replacementOrderFlag = true;
        }

        return replacementOrderFlag;
    }
}
