/*******************************************************************************
 * 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.GenericEntity;
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.EntityUtil;
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 = delegator.findByPrimaryKey("OrderPaymentPreference", 
                    UtilMisc.toMap("orderPaymentPreferenceId", orderPaymentPreferenceId));
            orderHeader = orderPaymentPreference.getRelatedOne("OrderHeader");
        } 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");
                                // 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 = delegator.findByAnd("PaymentMethodAndCreditCard",
                                                UtilMisc.toMap("partyId", billToPartyId, "paymentMethodTypeId", "CREDIT_CARD"));
                                        otherPaymentMethodAndCreditCardList = EntityUtil.filterByDate(otherPaymentMethodAndCreditCardList, true);
                                    }

                                    if (UtilValidate.isNotEmpty(otherPaymentMethodAndCreditCardList)) {
                                        Iterator<GenericValue> otherPaymentMethodAndCreditCardIter = otherPaymentMethodAndCreditCardList.iterator();
                                        while (otherPaymentMethodAndCreditCardIter.hasNext()) {
                                            GenericValue otherPaymentMethodAndCreditCard = otherPaymentMethodAndCreditCardIter.next();

                                            // 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: " + e.toString(), 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 = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap("orderId", orderId));

            // get the payments to auth
            Map<String, String> lookupMap = UtilMisc.toMap("orderId", orderId, "statusId", "PAYMENT_NOT_AUTH");
            List<String> orderList = UtilMisc.toList("maxAmount");
            paymentPrefs = delegator.findByAnd("OrderPaymentPreference", lookupMap, orderList);
            if (reAuth) {
                lookupMap.put("orderId", orderId);
                lookupMap.put("statusId", "PAYMENT_AUTHORIZED");
                paymentPrefs.addAll(delegator.findByAnd("OrderPaymentPreference", lookupMap, orderList));
            }
        } 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();
        Iterator<GenericValue> payments = paymentPrefs.iterator();
        while (payments.hasNext()) {
            GenericValue paymentPref = payments.next();
            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: " + se.toString(), 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().findByPrimaryKey("Visit", UtilMisc.toMap("visitId", visitId));
            } 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");

        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 + " => " + processContext, 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");
        } 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");
        if (paymentMethod != null && "CREDIT_CARD".equals(paymentMethodTypeId)) {
            // type credit card
            GenericValue creditCard = paymentMethod.getRelatedOne("CreditCard");
            GenericValue billingAddress = creditCard.getRelatedOne("PostalAddress");
            toContext.put("creditCard", creditCard);
            toContext.put("billingAddress", billingAddress);
        } else if (paymentMethod != null && "EFT_ACCOUNT".equals(paymentMethodTypeId)) {
            // type eft
            GenericValue eftAccount = paymentMethod.getRelatedOne("EftAccount");
            GenericValue billingAddress = eftAccount.getRelatedOne("PostalAddress");
            toContext.put("eftAccount", eftAccount);
            toContext.put("billingAddress", billingAddress);
        } else if (paymentMethod != null && "GIFT_CARD".equals(paymentMethodTypeId)) {
            // type gift card
            GenericValue giftCard = paymentMethod.getRelatedOne("GiftCard");
            toContext.put("giftCard", giftCard);
            GenericValue orderHeader = paymentPreference.getRelatedOne("OrderHeader");
            List<GenericValue> orderItems = orderHeader.getRelated("OrderItem");
            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");
            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"), "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 = delegator.findOne("OrderPaymentPreference", 
                        UtilMisc.toMap("orderPaymentPreferenceId", orderPaymentPreferenceId), false);
                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 = delegator.findList("OrderPaymentPreference", con4, null, null, null, false);
        } 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();
        Iterator<GenericValue> payments = paymentPrefs.iterator();
        while (payments.hasNext()) {
            paymentPref = payments.next();
            Map<String, Object> releaseContext = UtilMisc.toMap("userLogin", userLogin, "orderPaymentPreferenceId", paymentPref.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)) {
            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
                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");
            } 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 = delegator.findByPrimaryKey("OrderPaymentPreference", UtilMisc.toMap("orderPaymentPreferenceId", orderPaymentPreferenceId));
        } 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 = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap("orderId", orderId));
        } 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: " + e.getMessage(), 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");
            } 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 = delegator.findByPrimaryKey("Invoice", UtilMisc.toMap("invoiceId", invoiceId));
        } 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");
        } 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 = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap("orderId", orderId));

            // get the payment prefs
            Map<String, String> lookupMap = UtilMisc.toMap("orderId", orderId, "statusId", "PAYMENT_AUTHORIZED");
            List<String> orderList = UtilMisc.toList("-maxAmount");
            paymentPrefs = delegator.findByAnd("OrderPaymentPreference", lookupMap, orderList);

            if (UtilValidate.isNotEmpty(billingAccountId)) {
                lookupMap = UtilMisc.toMap("orderId", orderId, "paymentMethodTypeId", "EXT_BILLACT", "statusId", "PAYMENT_NOT_RECEIVED");
                paymentPrefsBa = delegator.findByAnd("OrderPaymentPreference", lookupMap, orderList);
            }
        } 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");
                        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);
                            }
                            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);
                        }
                        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 = delegator.findByPrimaryKey("Invoice", UtilMisc.toMap("invoiceId", invoiceId));
            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 = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap("orderId", orderId));
                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
                List<GenericValue> orderPaymentPreferences = delegator.findByAnd("OrderPaymentPreference", UtilMisc.toMap("orderId", orderId, "paymentMethodTypeId", "EXT_BILLACT"));
                if (orderPaymentPreferences.size() > 0) {
                    GenericValue orderPaymentPreference = EntityUtil.getFirst(orderPaymentPreferences);

                    // Check the productStore setting to see if we need to do this explicitly
                    GenericValue productStore = order.getRelatedOne("ProductStore");
                    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<EntityExpr> conditionList = UtilMisc.toList(EntityCondition.makeCondition("billingAccountId", EntityOperator.EQUALS, billingAccountId),
                                                  EntityCondition.makeCondition("invoiceId", EntityOperator.EQUALS, GenericEntity.NULL_FIELD));
            EntityCondition conditions = EntityCondition.makeCondition(conditionList, EntityOperator.AND);

            List<GenericValue> paymentApplications = delegator.findList("PaymentApplication", conditions, null, UtilMisc.toList("-amountApplied"), null, false);
            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");
                    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: " + e.toString(), 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);
        }

        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 = delegator.findByPrimaryKey("PaymentMethod", UtilMisc.toMap("paymentMethodId", paymentMethodId));
            GenericValue creditCard = null;
            if (paymentMethod != null && "CREDIT_CARD".equals(paymentMethod.getString("paymentMethodTypeId"))) {
                creditCard = paymentMethod.getRelatedOne("CreditCard");
            }

            // 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 (context != null && authResult.booleanValue()) {
                orderPaymentPreference.set("statusId", "PAYMENT_AUTHORIZED");
            } else if (context != null && !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: " + e.toString(), 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");
            if (UtilValidate.isNotEmpty(orderHeader.getString("autoOrderShoppingListId"))) {
                GenericValue productStore = orderHeader.getRelatedOne("ProductStore");
                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 = delegator.findCountByCondition("PaymentGatewayResponse",
                                EntityCondition.makeCondition(UtilMisc.toMap(
                                        "orderPaymentPreferenceId", orderPaymentPreference.get("orderPaymentPreferenceId"),
                                        "paymentMethodId", orderPaymentPreference.get("paymentMethodId"),
                                        "resultNsf", "Y"),
                                    EntityOperator.AND),
                                null, null);
                        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");
            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.log("resetting payment amount from 0.00 to correctMax amount", module);
        }
        Debug.log("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 = delegator.findByPrimaryKey("Invoice", UtilMisc.toMap("invoiceId", invoiceId));
                } 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");
                List<GenericValue> orl = null;
                try {
                    orl = delegator.findByAnd("OrderRole", UtilMisc.toMap("orderId", orderId, "roleTypeId", "BILL_TO_CUSTOMER"));
                } catch (GenericEntityException e) {
                    Debug.logError(e, module);
                }
                if (UtilValidate.isNotEmpty(orl)) {
                    GenericValue orderRole = EntityUtil.getFirst(orl);
                    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 = delegator.findOne("OrderPaymentPreference", UtilMisc.toMap("orderPaymentPreferenceId", orderPaymentPreferenceId), false);
        } 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");
        } 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.log("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 = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap("orderId", orderId));
        } 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 = delegator.find("OrderPaymentPreference",
                    EntityCondition.makeCondition(exprs, EntityOperator.AND), null, null, UtilMisc.toList("orderId"), null);
            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 = delegator.find("OrderPaymentPreference",
                    EntityCondition.makeCondition(EntityCondition.makeCondition("needsNsfRetry", EntityOperator.EQUALS, "Y"), EntityOperator.AND, EntityCondition.makeCondition(ModelEntity.STAMP_FIELD, EntityOperator.LESS_THAN_EQUAL_TO, oneWeekAgo)),
                    null, null, UtilMisc.toList("orderId"), null);

            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);
            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);
            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) {
        Timestamp authTime = PaymentGatewayServices.getAuthTime(orderPaymentPreference);
        if (authTime == null) {
            return false;
        }

        String reauthDays = null;

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

        if (paymentMethod != null && paymentMethod.getString("paymentMethodTypeId").equals("CREDIT_CARD")) {
            GenericValue creditCard = null;
            try {
                creditCard = paymentMethod.getRelatedOne("CreditCard");
            } 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 ("Discover".equals(cardType)) {
                    reauthDays = UtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.disc.days", "90");
                } else if ("AmericanExpress".equals(cardType)) {
                    reauthDays = UtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.amex.days", "30");
                } else if ("MasterCard".equals(cardType)) {
                    reauthDays = UtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.mc.days", "30");
                } else if ("Visa".equals(cardType)) {
                    reauthDays = UtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.visa.days", "7");
                } else {
                    reauthDays = UtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.other.days", "7");
                }

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

        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)) {
            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 = delegator.findByPrimaryKey("PaymentMethod", UtilMisc.toMap("paymentMethodId", paymentMethodId));
        } 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");
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.getMessage());
        }

        // get the credit card object
        GenericValue creditCard;
        try {
            creditCard = delegator.findByPrimaryKey("CreditCard", UtilMisc.toMap("paymentMethodId", paymentMethodId));
        } 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 = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");

        // 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)) {
            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 = delegator.findOne("OrderPaymentPreference", UtilMisc.toMap("orderPaymentPreferenceId", orderPaymentPreferenceId), false);
        } 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 = delegator.findOne("OrderHeader", UtilMisc.toMap("orderId", orderId), false);
        } 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 && paymentConfig == 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 = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");
            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");
        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 = UtilProperties.getPropertyValue(productStorePaymentProperties, "payment.general.cc_create.auth");
        } else if (mode.equalsIgnoreCase("UPDATE")) {
            amount = UtilProperties.getPropertyValue(productStorePaymentProperties, "payment.general.cc_update.auth");
        }
        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());
        Debug.log("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 = delegator.findOne("CustomMethod", UtilMisc.toMap("customMethodId", customMethodId), false);
            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");
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return replacementOrderFlag;
        }
        if (UtilValidate.isNotEmpty(returnItemResponses)) {
            replacementOrderFlag = true;
        }

        return replacementOrderFlag;
    }
}
