You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ofbiz.apache.org by Jacopo Cappellato <ti...@sastau.it> on 2007/05/21 09:25:25 UTC

Re: svn commit: r540041 - in /ofbiz/branches/release4.0/applications/accounting: servicedef/services_paymentmethod.xml src/org/ofbiz/accounting/payment/PaymentGatewayServices.java

Scott,

after the big work done in rev. 534944 by Andrew, I've committed a few 
minor fixes in the same area that are necessary to complete the work.
If we have decided to include this work we have to include them too.
Let me know if you can't find them, and I'll send you the list.

Jacopo

lektran@apache.org wrote:
> Author: lektran
> Date: Sun May 20 23:52:15 2007
> New Revision: 540041
> 
> URL: http://svn.apache.org/viewvc?view=rev&rev=540041
> Log:
> Applied fix from trunk for revision: 534944
> 
> Modified:
>     ofbiz/branches/release4.0/applications/accounting/servicedef/services_paymentmethod.xml
>     ofbiz/branches/release4.0/applications/accounting/src/org/ofbiz/accounting/payment/PaymentGatewayServices.java
> 
> Modified: ofbiz/branches/release4.0/applications/accounting/servicedef/services_paymentmethod.xml
> URL: http://svn.apache.org/viewvc/ofbiz/branches/release4.0/applications/accounting/servicedef/services_paymentmethod.xml?view=diff&rev=540041&r1=540040&r2=540041
> ==============================================================================
> --- ofbiz/branches/release4.0/applications/accounting/servicedef/services_paymentmethod.xml (original)
> +++ ofbiz/branches/release4.0/applications/accounting/servicedef/services_paymentmethod.xml Sun May 20 23:52:15 2007
> @@ -285,7 +285,13 @@
>          <attribute name="paymentId" type="String" mode="OUT" optional="false"/>
>          <attribute name="paymentGatewayResponseId" type="String" mode="OUT" optional="true"/>
>      </service>
> -        
> +
> +    <service name="processCaptureSplitPayment" engine="java" require-new-transaction="true"
> +            location="org.ofbiz.accounting.payment.PaymentGatewayServices" invoke="captureBillingAccountPayment" auth="true">
> +        <description>Handles the creation of new OrderPaymentPreference record (and Auth) for partial captures</description>
> +        <attribute name="orderPaymentPreference" type="GenericValue" mode="IN" optional="false"/>
> +        <attribute name="splitAmount" type="BigDecimal" mode="IN" optional="false"/> 
> +    </service>
>  
>      <service name="refundPayment" engine="java"
>              location="org.ofbiz.accounting.payment.PaymentGatewayServices" invoke="refundPayment" auth="true">
> @@ -332,13 +338,53 @@
>          <attribute name="internalRespMsgs" type="List" mode="IN" optional="true"/>
>      </service>
>  
> -    <service name="processPaymentServiceError" engine="java" require-new-transaction="true"
> +   <service name="processReleaseResult" engine="java"
> +            location="org.ofbiz.accounting.payment.PaymentGatewayServices" invoke="processReleaseResult" auth="true">
> +        <description>Process the payment release result(s)</description>
> +        <attribute name="orderPaymentPreference" type="GenericValue" mode="IN" optional="false"/>
> +        <attribute name="releaseAmount" type="Double" mode="IN" optional="false"/>
> +        <attribute name="currencyUomId" type="String" mode="IN" optional="true"/>
> +        <attribute name="releaseResult" type="Boolean" mode="IN" optional="false"/>
> +        <attribute name="releaseAltRefNum" type="String" mode="IN" optional="true"/>
> +        <attribute name="releaseRefNum" type="String" mode="IN" optional="false"/>
> +        <attribute name="releaseCode" type="String" mode="IN" optional="true"/>
> +        <attribute name="releaseFlag" type="String" mode="IN" optional="true"/>
> +        <attribute name="releaseMessage" type="String" mode="IN" optional="true"/>
> +        <attribute name="internalRespMsgs" type="List" mode="IN" optional="true"/>
> +    </service>
> +
> +    <service name="processRefundResult" engine="java"
> +            location="org.ofbiz.accounting.payment.PaymentGatewayServices" invoke="processRefundResult" auth="true">
> +        <description>Process the payment refund result(s)</description>
> +        <attribute name="orderPaymentPreference" type="GenericValue" mode="IN" optional="false"/>
> +        <attribute name="serviceTypeEnum" type="String" mode="IN" optional="true"/>
> +        <attribute name="payFromPartyId" type="String" mode="IN" optional="true"/>
> +        <attribute name="payToPartyId" type="String" mode="IN" optional="true"/>
> +        <attribute name="invoiceId" type="String" mode="IN" optional="true"/>
> +        <attribute name="refundAmount" type="Double" mode="IN" optional="false"/>
> +        <attribute name="currencyUomId" type="String" mode="IN" optional="true"/>
> +        <attribute name="refundResult" type="Boolean" mode="IN" optional="false"/>
> +        <attribute name="refundAltRefNum" type="String" mode="IN" optional="true"/>
> +        <attribute name="refundRefNum" type="String" mode="IN" optional="false"/>
> +        <attribute name="refundCode" type="String" mode="IN" optional="true"/>
> +        <attribute name="refundFlag" type="String" mode="IN" optional="true"/>
> +        <attribute name="refundMessage" type="String" mode="IN" optional="true"/>
> +        <attribute name="internalRespMsgs" type="List" mode="IN" optional="true"/>
> +    </service>
> +
> +    <service name="processPaymentServiceError" engine="java" require-new-transaction="true" max-retry="5"
>              location="org.ofbiz.accounting.payment.PaymentGatewayServices" invoke="storePaymentErrorMessage" auth="true">
>          <description>Process (store) error messages from payment service failures</description>
>          <attribute name="paymentServiceTypeEnumId" type="String" mode="IN" optional="false"/>
>          <attribute name="orderPaymentPreference" type="GenericValue" mode="IN" optional="false"/>
>          <attribute name="transCodeEnumId" type="String" mode="IN" optional="false"/>
>          <attribute name="serviceResultMap" type="Map" mode="IN" optional="false"/>
> +    </service>
> +
> +    <service name="savePaymentGatewayResponse" engine="java"
> +            location="org.ofbiz.accounting.payment.PaymentGatewayServices" invoke="storePaymentErrorMessage" auth="false">
> +        <description>Method to make sure PaymentGatewayResponse records get stored (uses XA wrapper on rollback)</description>
> +        <attribute name="paymentGatewayResponse" type="GenericValue" mode="IN" optional="false"/>
>      </service>
>  
>      <!-- Payment Gateway Interfaces -->
> 
> Modified: ofbiz/branches/release4.0/applications/accounting/src/org/ofbiz/accounting/payment/PaymentGatewayServices.java
> URL: http://svn.apache.org/viewvc/ofbiz/branches/release4.0/applications/accounting/src/org/ofbiz/accounting/payment/PaymentGatewayServices.java?view=diff&rev=540041&r1=540040&r2=540041
> ==============================================================================
> --- ofbiz/branches/release4.0/applications/accounting/src/org/ofbiz/accounting/payment/PaymentGatewayServices.java (original)
> +++ ofbiz/branches/release4.0/applications/accounting/src/org/ofbiz/accounting/payment/PaymentGatewayServices.java Sun May 20 23:52:15 2007
> @@ -49,11 +49,7 @@
>  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 org.ofbiz.service.*;
>  
>  /**
>   * PaymentGatewayServices
> @@ -127,6 +123,7 @@
>          orderPaymentPreference.set("processAttempt", new Long(procAttempt.longValue() + 1));
>          try {
>              orderPaymentPreference.store();
> +            orderPaymentPreference.refresh();
>          } catch (GenericEntityException e) {
>              Debug.logError(e, module);
>              return ServiceUtil.returnError("Unable to update OrderPaymentPreference record!");
> @@ -162,11 +159,6 @@
>  
>              // handle the response
>              if (authPaymentResult != null) {
> -                // get the customer messages
> -                if (authPaymentResult.get("customerRespMsgs") != null) {
> -                    // NOTE DEJ20060911: hmmm... was something supposed to be done here?
> -                }
> -
>                  // not null result means either an approval or decline; null would mean error
>                  Double thisAmount = (Double) authPaymentResult.get("processAmount");
>  
> @@ -526,6 +518,7 @@
>                  
>                  // at this point if we have a successful result, let's save the new creditCard expireDate
>                  if (!ServiceUtil.isError(processorResult) && Boolean.TRUE.equals((Boolean) 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();
>                  }
>              }
> @@ -811,93 +804,105 @@
>  
>          // get the release result code
>          if (releaseResult != null && !ServiceUtil.isError(releaseResult)) {
> -            Boolean releaseResponse = (Boolean) releaseResult.get("releaseResult");
> +            Map releaseResRes;
> +            try {
> +                ModelService model = dctx.getModelService("processReleaseResult");
> +                Map resCtx = model.makeValid(result, ModelService.IN_PARAM);
> +                releaseResRes = dispatcher.runSync(model.name,  resCtx);
> +            } catch (GenericServiceException e) {
> +                Debug.logError(e, module);
> +                return ServiceUtil.returnError("Trouble processing the release results: " + 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));
> +        }
>  
> -            // create the PaymentGatewayResponse
> -            String responseId = delegator.getNextSeqId("PaymentGatewayResponse");
> -            GenericValue pgResponse = delegator.makeValue("PaymentGatewayResponse", null);
> -            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("referenceNum", releaseResult.get("releaseRefNum"));
> -            pgResponse.set("altReference", releaseResult.get("releaseAltRefNum"));
> -            pgResponse.set("gatewayCode", releaseResult.get("releaseCode"));
> -            pgResponse.set("gatewayFlag", releaseResult.get("releaseFlag"));
> -            pgResponse.set("gatewayMessage", releaseResult.get("releaseMessage"));
> -            pgResponse.set("transactionDate", UtilDateTime.nowTimestamp());
> +        return result;
> +    }
> +
> +    public static Map processReleaseResult(DispatchContext dctx, Map context) {
> +        GenericDelegator delegator = dctx.getDelegator();
> +
> +        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
> +        Boolean releaseResponse = (Boolean) context.get("releaseResult");
> +
> +        // create the PaymentGatewayResponse
> +        String responseId = delegator.getNextSeqId("PaymentGatewayResponse");
> +        GenericValue pgResponse = delegator.makeValue("PaymentGatewayResponse", null);
> +        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("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());
> +
> +        // store the gateway response
> +        savePgr(dctx, pgResponse);
> +
> +        // create the internal messages
> +        List messages = (List) context.get("internalRespMsgs");
> +        if (messages != null && messages.size() > 0) {
> +            Iterator i = messages.iterator();
> +            while (i.hasNext()) {
> +                GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg", null);
> +                String respMsgId = delegator.getNextSeqId("PaymentGatewayRespMsg");
> +                String message = (String) i.next();
> +                respMsg.set("paymentGatewayRespMsgId", respMsgId);
> +                respMsg.set("paymentGatewayResponseId", responseId);
> +                respMsg.set("pgrMessage", message);
> +
> +                // store the messages
> +                savePgr(dctx, respMsg);
> +            }
> +        }
>  
> -            // store the gateway response
> +        if (releaseResponse != null && releaseResponse.booleanValue()) {
> +            paymentPref.set("statusId", "PAYMENT_CANCELLED");
>              try {
> -                pgResponse.create();
> +                paymentPref.store();
>              } catch (GenericEntityException e) {
> -                Debug.logError(e, "Problem storing PaymentGatewayResponse entity; authorization was released! : " + pgResponse, module);
> +                Debug.logError(e, "Problem storing updated payment preference; authorization was released!", module);
>              }
>  
> -            // create the internal messages
> -            List messages = (List) releaseResult.get("internalRespMsgs");
> -            if (messages != null && messages.size() > 0) {
> -                Iterator i = messages.iterator();
> -                while (i.hasNext()) {
> -                    GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg", null);
> -                    String respMsgId = delegator.getNextSeqId("PaymentGatewayRespMsg");
> -                    String message = (String) i.next();
> -                    respMsg.set("paymentGatewayRespMsgId", respMsgId);
> -                    respMsg.set("paymentGatewayResponseId", responseId);
> -                    respMsg.set("pgrMessage", message);
> -                    try {
> -                        delegator.create(respMsg);
> -                    } catch (GenericEntityException e) {
> -                        String errMsg = "Unable to create PaymentGatewayRespMsg record"; 
> -                        Debug.logError(e, errMsg, module);
> -                        return ServiceUtil.returnError(errMsg);
> -                    }
> -                }
> +            // cancel any payment records
> +            List paymentList = null;
> +            try {
> +                paymentList = paymentPref.getRelated("Payment");
> +            } catch (GenericEntityException e) {
> +                Debug.logError(e, "Unable to get Payment records from OrderPaymentPreference : " + paymentPref, module);
>              }
>  
> -            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 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 pi = paymentList.iterator();
> -                    while (pi.hasNext()) {
> -                        GenericValue pay = (GenericValue) pi.next();
> -                        pay.set("statusId", "PMNT_CANCELLED");
> -                        try {
> -                            pay.store();
> -                        } catch (GenericEntityException e) {
> -                            Debug.logError(e, "Unable to store Payment : " + pay, module);
> -                        }
> +            if (paymentList != null) {
> +                Iterator pi = paymentList.iterator();
> +                while (pi.hasNext()) {
> +                    GenericValue pay = (GenericValue) pi.next();
> +                    pay.set("statusId", "PMNT_CANCELLED");
> +                    try {
> +                        pay.store();
> +                    } catch (GenericEntityException e) {
> +                        Debug.logError(e, "Unable to store Payment : " + pay, module);
>                      }
>                  }
> -            } else {
> -                String errMsg = "Release failed for pref : " + paymentPref; 
> -                Debug.logError(errMsg, module);
> -                result = ServiceUtil.returnFailure(errMsg);
>              }
> -        } else if (ServiceUtil.isError(releaseResult)) {
> -            saveError(dispatcher, userLogin, paymentPref, releaseResult, RELEASE_SERVICE_TYPE, "PGT_RELEASE");
> -            result = ServiceUtil.returnError(ServiceUtil.getErrorMessage(releaseResult));
> +        } else {
> +            String errMsg = "Release failed for pref : " + paymentPref;
> +            Debug.logError(errMsg, module);
> +            return ServiceUtil.returnFailure(errMsg);
>          }
>  
> -        return result;
> +        return ServiceUtil.returnSuccess();
>      }
>  
>      /**
> @@ -1079,19 +1084,19 @@
>  
>          BigDecimal totalPayments = PaymentWorker.getPaymentsTotal(orh.getOrderPayments());
>          totalPayments = totalPayments.setScale(2, BigDecimal.ROUND_HALF_UP);
> +
>          BigDecimal remainingTotalBd = orderGrandTotal.subtract(totalPayments);
>          if (Debug.infoOn()) Debug.logInfo("Capture Remaining Total: " + remainingTotalBd, module);
>  
> -        double amountToCapture = 0.0;
> +        BigDecimal amountToCapture = ZERO;
>          if (captureAmountBd == null) {
> -            amountToCapture = remainingTotalBd.doubleValue();
> +            amountToCapture = remainingTotalBd;
>          } else {
> -            amountToCapture = captureAmountBd.doubleValue();
> +            amountToCapture = captureAmountBd;
>          }
>          if (Debug.infoOn()) Debug.logInfo("Actual Expected Capture Amount : " + amountToCapture, module);
>  
>          // iterate over the prefs and capture each one until we meet our total
> -        List finished = new ArrayList();
>          Iterator 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...
> @@ -1101,64 +1106,78 @@
>                  continue;
>              }
>  
> -            Double authAmount = authTrans.getDouble("amount");
> -            if (authAmount == null) authAmount = new Double(0.00);
> -            if (authAmount.doubleValue() == 0.00) {
> +            // 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 = new BigDecimal(0.00);
> +            authAmount = authAmount.setScale(2, BigDecimal.ROUND_HALF_UP);
> +
> +            if (authAmount.compareTo(ZERO) == 0) {
>                  // nothing to capture
>                  Debug.logInfo("Nothing to capture; authAmount = 0", module);
>                  continue;
>              }
> -            //Debug.log("Actual Auth amount : " + authAmount, module);
>   
>              // if the authAmount is more then the remaining total; just use remaining total
> -            if (authAmount.doubleValue() > remainingTotalBd.doubleValue()) {
> -                authAmount = new Double(remainingTotalBd.doubleValue());
> +            if (authAmount.compareTo(remainingTotalBd) == 1) {
> +                authAmount = new BigDecimal(remainingTotalBd.doubleValue());
>              }
>  
>              // if we have a billing account; total up auth + account available
> -            double amountToBillAccount = 0.00;
> +            BigDecimal amountToBillAccount = ZERO;
>              if (billingAccountAvail != null) {
> -                amountToBillAccount = authAmount.doubleValue() + billingAccountAvail.doubleValue();
> +                amountToBillAccount = authAmount.add(billingAccountAvail).setScale(2, BigDecimal.ROUND_HALF_UP);
>              }
>  
>              // the amount for *this* capture
> -            double amountThisCapture = 0.00;
> +            BigDecimal amountThisCapture;
>  
>              // determine how much for *this* capture
> -            if (authAmount.doubleValue() >= amountToCapture) {
> +            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.doubleValue();
> -            } else if (billingAccountAvail != null && amountToBillAccount >= amountToCapture) {
> +                amountThisCapture = authAmount;
> +            } else if (billingAccountAvail != null && amountToBillAccount.compareTo(amountToCapture) >= 0) {
>                  // the provided billing account will cover the remaining; just capture what was autorized
> -                amountThisCapture = authAmount.doubleValue();
> +                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.doubleValue();
> +                amountThisCapture = authAmount;
>              }
>             
>              Debug.logInfo("Payment preference = [" + paymentPref + "] amount to capture = [" + amountToCapture +"] amount of this capture = [" + amountThisCapture +"] actual auth amount =[" + authAmount + "] amountToBillAccount = [" + amountToBillAccount + "]", module); 
> -            Map captureResult = capturePayment(dctx, userLogin, orh, paymentPref, amountThisCapture);
> +            Map captureResult = capturePayment(dctx, userLogin, orh, paymentPref, amountThisCapture.doubleValue());
>              if (captureResult != null) {
>                  // credit card processors return captureAmount, but gift certificate processors return processAmount
>                  Double amountCaptured = (Double) captureResult.get("captureAmount");
>                  if (amountCaptured == null) {
>                      amountCaptured = (Double) captureResult.get("processAmount");
>                  }
> +
> +                // big decimal reference to the capture amount
> +                BigDecimal amountCapturedBd = new BigDecimal(amountCaptured.doubleValue());
> +                amountCapturedBd = amountCapturedBd.setScale(2, BigDecimal.ROUND_HALF_UP);
> +
>                  // decrease amount of next payment preference to capture
> -                if (amountCaptured != null) amountToCapture -= amountCaptured.doubleValue();
> -                finished.add(captureResult);
> +                if (amountCaptured != null) {
> +                    amountToCapture = amountToCapture.subtract(amountCapturedBd);                
> +                }
>  
>                  // add the invoiceId to the result for processing
>                  captureResult.put("invoiceId", invoiceId);
>  
> -               // process the capture's results
> +                // process the capture's results
>                  try {
>                      processResult(dctx, captureResult, userLogin, paymentPref);
>                  } catch (GeneralException e) {
> @@ -1167,58 +1186,27 @@
>                  }
>  
>                  // create any splits which are needed
> -                BigDecimal totalAmountCaptured = new BigDecimal(amountThisCapture);
> -                if (authAmount.doubleValue() > totalAmountCaptured.doubleValue()) {
> -                    // create a new payment preference and authorize it
> -                    double newAmount = authAmount.doubleValue() - totalAmountCaptured.doubleValue(); // TODO: use BigDecimal arithmetic here (and everywhere else for that matter)
> -                    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", paymentPref.get("maxAmount"));
> -                    newPref.set("statusId", "PAYMENT_NOT_AUTH");
> -                    newPref.set("createdDate", UtilDateTime.nowTimestamp());
> -                    if (userLogin != null) {
> -                        newPref.set("createdByUserLogin", userLogin.getString("userLoginId"));
> -                    }
> -                    Debug.logInfo("New preference : " + newPref, module);
> -                    Map processorResult = null;
> +                if (authAmount.compareTo(amountThisCapture) == 1) {
> +                    BigDecimal splitAmount = authAmount.subtract(amountThisCapture);
> +                    Map splitResp = null;
>                      try {
> -                        // create the new payment preference
> -                        delegator.create(newPref);
> -
> -                        // authorize the new preference
> -                        processorResult = authPayment(dispatcher, userLogin, orh, newPref, newAmount, false, null);
> -                        if (processorResult != null) {
> -                            // process the auth results
> -                            boolean authResult = processResult(dctx, processorResult, userLogin, newPref);
> -                            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);
> -                        }
> +                        Map splitCtx = UtilMisc.toMap("userLogin", userLogin, "orderPaymentPreference", paymentPref, "splitAmount", splitAmount);
> +                        dispatcher.addCommitService("processCaptureSplitPayment", splitCtx, true);
> +                    } catch (GenericServiceException e) {
> +                        Debug.logWarning(e, "Problem processing the capture split payment", module);
> +                    }
> +                    if (ServiceUtil.isError(splitResp)) {
> +                        Debug.logWarning("Problem processing the capture split payment: " + ServiceUtil.getErrorMessage(splitResp), module);
>                      }
>                  }
>              } else {
>                  Debug.logError("Payment not captured", module);
> -                continue;
>              }
>          }
>  
> -        if (amountToCapture > 0.00) {
> +        if (amountToCapture.compareTo(ZERO) == 1) {
>              GenericValue productStore = orh.getProductStore();
> -            if (! UtilValidate.isEmpty(productStore)) {
> +            if (!UtilValidate.isEmpty(productStore)) {
>                  boolean shipIfCaptureFails = UtilValidate.isEmpty(productStore.get("shipIfCaptureFails")) || "Y".equalsIgnoreCase(productStore.getString("shipIfCaptureFails"));
>                  if(! shipIfCaptureFails) {
>                      return ServiceUtil.returnError("Cannot ship order because credit card captures were unsuccessful");
> @@ -1234,6 +1222,61 @@
>          }
>      }
>  
> +    public static Map processCaptureSplitPayment(DispatchContext dctx, Map context) {
> +        LocalDispatcher dispatcher = dctx.getDispatcher();
> +        GenericDelegator delegator = dctx.getDelegator();
> +
> +        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);
> +
> +        // create a new payment preference and authorize it
> +        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", paymentPref.get("maxAmount"));
> +        newPref.set("statusId", "PAYMENT_NOT_AUTH");
> +        newPref.set("createdDate", UtilDateTime.nowTimestamp());
> +        if (userLogin != null) {
> +            newPref.set("createdByUserLogin", userLogin.getString("userLoginId"));
> +        }
> +        if (Debug.verboseOn()) Debug.logVerbose("New preference : " + newPref, module);
> +
> +        Map processorResult = null;
> +        try {
> +            // create the new payment preference
> +            delegator.create(newPref);
> +
> +            // authorize the new preference
> +            processorResult = authPayment(dispatcher, userLogin, orh, newPref, splitAmount.doubleValue(), false, null);
> +            if (processorResult != null) {
> +                // process the auth results
> +                boolean authResult = processResult(dctx, processorResult, userLogin, newPref);
> +                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();
> +    }
> +
>      public static Map captureBillingAccountPayment(DispatchContext dctx, Map context) {
>          GenericDelegator delegator = dctx.getDelegator();
>          LocalDispatcher dispatcher = dctx.getDispatcher();
> @@ -1296,7 +1339,9 @@
>                          // referenceNum holds the relation to the order.
>                          // todo: Extend PaymentGatewayResponse with a billingAccountId field?
>                          pgResponse.set("referenceNum", billingAccountId);
> -                        pgResponse.create();
> +
> +                        // save the response
> +                        savePgr(dctx, pgResponse);
>  
>                          // Update the orderPaymentPreference
>                          orderPaymentPreference.set("statusId", "PAYMENT_SETTLED");
> @@ -1505,17 +1550,21 @@
>          result.put("orderPaymentPreference", paymentPreference);
>          ModelService model = dctx.getModelService("processAuthResult");
>          Map context = model.makeValid(result, ModelService.IN_PARAM);
> -        Map svcResp = null;
> +
> +        // in case we rollback make sure this service gets called
> +        dispatcher.addRollbackService(model.name, context, true);
> +
> +        // invoke the service 
> +        Map resResp;
>          try {
> -            svcResp = dispatcher.runSync("processAuthResult", context);
> +            resResp = dispatcher.runSync(model.name, context);
>          } catch (GenericServiceException e) {
>              Debug.logError(e, module);
>              throw e;
>          }
> -        if (svcResp != null && ServiceUtil.isError(svcResp)) {
> -           Debug.logError(ServiceUtil.getErrorMessage(svcResp), module);
> -           throw new GeneralException(ServiceUtil.getErrorMessage(svcResp));
> -        }
> +        if (ServiceUtil.isError(resResp)) {
> +            throw new GeneralException(ServiceUtil.getErrorMessage(resResp));
> +        }        
>      }
>  
>      public static Map processAuthResult(DispatchContext dctx, Map context) {
> @@ -1526,6 +1575,14 @@
>          String currencyUomId = (String) context.get("currencyUomId");
>          Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
>  
> +        // 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;
> @@ -1567,8 +1624,9 @@
>              if (Boolean.TRUE.equals((Boolean) context.get("resultNsf"))) response.set("resultNsf", "Y");
>              if (Boolean.TRUE.equals((Boolean) context.get("resultBadExpire"))) response.set("resultBadExpire", "Y");
>              if (Boolean.TRUE.equals((Boolean) context.get("resultBadCardNumber"))) response.set("resultBadCardNumber", "Y");
> -            
> -            response.create();
> +
> +            // save the response
> +            savePgr(dctx, response);
>      
>              // create the internal messages
>              List messages = (List) context.get("internalRespMsgs");
> @@ -1581,7 +1639,7 @@
>                      respMsg.set("paymentGatewayRespMsgId", respMsgId);
>                      respMsg.set("paymentGatewayResponseId", responseId);
>                      respMsg.set("pgrMessage", message);
> -                    delegator.create(respMsg);
> +                    savePgr(dctx, respMsg);
>                  }
>              }
>      
> @@ -1607,8 +1665,8 @@
>              }
>  
>              orderPaymentPreference.store();
> -            
> -            // if the payment was declined and this is a CreditCard, save that information on the CreditCard entity  
> +
> +            // 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");
> @@ -1628,7 +1686,6 @@
>                          }
>                          creditCard.set("lastFailedNsfDate", nowTimestamp);
>                      }
> -                    
>                      creditCard.store();
>                  }
>              }
> @@ -1640,7 +1697,6 @@
>                      creditCard.set("lastFailedAuthDate", null);
>                      creditCard.set("consecutiveFailedNsf", new Long(0));
>                      creditCard.set("lastFailedNsfDate", null);
> -                    
>                      creditCard.store();
>                  }
>              }
> @@ -1692,6 +1748,10 @@
>      }
>  
>      private static void processCaptureResult(DispatchContext dctx, Map result, GenericValue userLogin, GenericValue paymentPreference, String authServiceType) 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");
>          Double amount = null;
> @@ -1706,14 +1766,19 @@
>              throw new GeneralException("Unable to process null capture amount");
>          }
>  
> -        if (result != null && captureResult.booleanValue()) {
> +        // setup the amount big decimal
> +        BigDecimal amtBd = new BigDecimal(amount.doubleValue());
> +        amtBd = amtBd.setScale(2, BigDecimal.ROUND_HALF_UP);
> +
> +        if (captureResult.booleanValue()) {
> +            // capture returned true (passed)
>              result.put("orderPaymentPreference", paymentPreference);
>              result.put("userLogin", userLogin);
>              result.put("serviceTypeEnum", authServiceType);
>  
>              ModelService model = dctx.getModelService("processCaptureResult");
>              Map context = model.makeValid(result, ModelService.IN_PARAM);
> -            Map capRes = null;
> +            Map capRes;
>              try {
>                  capRes = dispatcher.runSync("processCaptureResult", context);
>              } catch (GenericServiceException e) {
> @@ -1723,66 +1788,77 @@
>              if (capRes != null && ServiceUtil.isError(capRes)) {
>                  throw new GeneralException(ServiceUtil.getErrorMessage(capRes));
>              }
> -        } else if (result != null && !captureResult.booleanValue()) {
> -            // problem with the capture lets get some needed info
> -            OrderReadHelper orh = null;
> +        } else {
> +            // capture returned false (error)
>              try {
> -                GenericValue orderHeader = paymentPreference.getRelatedOne("OrderHeader");
> -                if (orderHeader != null)
> -                    orh = new OrderReadHelper(orderHeader);
> -            } catch (GenericEntityException e) {
> -                Debug.logError(e, "Problems getting OrderHeader; cannot re-auth the payment", module);
> +                processReAuthFromCaptureFailure(dctx, result, amtBd, userLogin, paymentPreference);
> +            } catch (GeneralException e) {
> +                // just log this for now (same as previous implementation)
> +                Debug.logError(e, module);
>              }
> +        }
> +    }
>  
> -            if (amount != null && amount.doubleValue() == new Double(0.00).doubleValue()) {
> -                amount = paymentPreference.getDouble("maxAmount");
> -                Debug.log("resetting payment amount from 0.00 to correctMax amount", module);
> -            }
> -            Debug.log("reauth with amount: " + amount, module);
> -            if (orh != null) {
> -                // first lets re-auth the card
> -                Map authPayRes = authPayment(dispatcher, userLogin, orh, paymentPreference, amount.doubleValue(), true, null);
> -                Debug.log("authPayRes: " + authPayRes, module);
> -                if (authPayRes != null) {
> -                    Boolean authResp = (Boolean) authPayRes.get("authResult");
> -                    Boolean capResp = (Boolean) authPayRes.get("captureResult");
> -                    if (authResp != null) {
> -                        GenericValue authTrans = processAuthRetryResult(dctx, authPayRes, userLogin, paymentPreference);
> -
> -                        if (authResp.booleanValue()) {
> -                            // first make sure we didn't already capture - probably not
> -                            if (capResp != null && capResp.booleanValue()) {
> -                                processCaptureResult(dctx, result, userLogin, paymentPreference);
> -                            } else {
> -                                // lets try to capture the funds now
> -                                Map capPayRes = capturePayment(dctx, userLogin, orh, paymentPreference, amount.doubleValue(), authTrans);
> -                                if (capPayRes != null) {
> -                                    Boolean capPayResp = (Boolean) capPayRes.get("captureResult");
> -                                    if (capPayResp != null && capPayResp.booleanValue()) {
> -                                        // it was successful
> -                                        processCaptureResult(dctx, capPayRes, userLogin, paymentPreference);
> -                                    } else {
> -                                        // not successful; log it
> -                                        Debug.logError("Capture of authorized payment failed: " + paymentPreference, module);
> -                                    }
> -                                } else {
> -                                    Debug.logError("Problems trying to capture payment (null result): " + paymentPreference, module);
> -                                }
> -                            }
> -                        } else {
> -                            Debug.logError("Payment authorization failed:  " + paymentPreference, module);
> -                        }
> -                    } else {
> -                        Debug.logError("Payment authorization failed (null result):  " + paymentPreference, module);
> -                    }
> +    private static void processReAuthFromCaptureFailure(DispatchContext dctx, Map result, BigDecimal amount, GenericValue userLogin, GenericValue paymentPreference) 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 authPayRes = authPayment(dispatcher, userLogin, orh, paymentPreference, amount.doubleValue(), 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);
> +            } else {
> +                // no auto-capture; do manual capture now
> +                Map capPayRes = capturePayment(dctx, userLogin, orh, paymentPreference, amount.doubleValue(), authTrans);
> +                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);
>                  } else {
> -                    Debug.logError("Problems trying to re-authorize the payment (null result): " + paymentPreference, module);
> +                    throw new GeneralException("Capture of authorized payment failed");
>                  }
> -            } else {
> -                Debug.logError("Null OrderReadHelper cannot process", module);
>              }
>          } else {
> -            Debug.logError("Result pass is null, no capture available", module);
> +            throw new GeneralException("Payment re-authorization failed");
>          }
>      }
>  
> @@ -1802,6 +1878,23 @@
>              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
> +        paymentPreference.set("statusId", "PAYMENT_SETTLED");
> +        try {
> +            paymentPreference.store();
> +        } catch (GenericEntityException e) {
> +            Debug.logError(e, module);
> +            return ServiceUtil.returnError(e.getMessage());
> +        }
> +
>          // create the PaymentGatewayResponse record
>          String responseId = delegator.getNextSeqId("PaymentGatewayResponse");
>          GenericValue response = delegator.makeValue("PaymentGatewayResponse", null);
> @@ -1826,12 +1919,9 @@
>          response.set("gatewayFlag", context.get("captureFlag"));
>          response.set("gatewayMessage", context.get("captureMessage"));
>          response.set("transactionDate", UtilDateTime.nowTimestamp());
> -        try {
> -            delegator.create(response);
> -        } catch (GenericEntityException e) {
> -            Debug.logError(e, module);
> -            return ServiceUtil.returnError("Error creating response information");
> -        }
> +
> +        // save the response
> +        savePgr(dctx, response);
>  
>          // create the internal messages
>          List messages = (List) context.get("internalRespMsgs");
> @@ -1844,12 +1934,9 @@
>                  respMsg.set("paymentGatewayRespMsgId", respMsgId);
>                  respMsg.set("paymentGatewayResponseId", responseId);
>                  respMsg.set("pgrMessage", message);
> -                try {
> -                    delegator.create(respMsg);
> -                } catch (GenericEntityException e) {
> -                    Debug.logError(e, module);
> -                    return ServiceUtil.returnError("Error creating response message information");
> -                }
> +
> +                // save the message
> +                savePgr(dctx, respMsg);
>              }
>          }
>  
> @@ -1879,7 +1966,7 @@
>              } catch (GenericEntityException e) {
>                  Debug.logError(e, module);
>              }
> -            if (orl.size() > 0) {
> +            if (orl != null && orl.size() > 0) {
>                  GenericValue orderRole = EntityUtil.getFirst(orl);
>                  partyIdFrom = orderRole.getString("partyId");
>              }
> @@ -1914,24 +2001,18 @@
>          paymentCtx.put("userLogin", userLogin);
>          paymentCtx.put("paymentRefNum", context.get("captureRefNum"));
>  
> -        Map payRes = null;
> +        Map payRes;
>          try {
>              payRes = dispatcher.runSync("createPayment", paymentCtx);
>          } catch (GenericServiceException e) {
>              Debug.logError(e, module);
>              return ServiceUtil.returnError("Error creating payment record");
>          }
> -        if (payRes != null && ServiceUtil.isError(payRes)) {
> +        if (ServiceUtil.isError(payRes)) {
>              return ServiceUtil.returnError(ServiceUtil.getErrorMessage(payRes));
>          }
>  
>          String paymentId = (String) payRes.get("paymentId");
> -        paymentPreference.set("statusId", "PAYMENT_SETTLED");
> -        try {
> -            paymentPreference.store();
> -        } catch (GenericEntityException e) {
> -            Debug.logError(e, module);
> -        }
>  
>          // create the PaymentApplication if invoiceId is available
>          if (invoiceId != null) {
> @@ -1939,7 +2020,7 @@
>              Map paCtx = UtilMisc.toMap("paymentId", paymentId, "invoiceId", invoiceId);
>              paCtx.put("amountApplied", context.get("captureAmount"));
>              paCtx.put("userLogin", userLogin);
> -            Map paRes = null;
> +            Map paRes;
>              try {
>                  paRes = dispatcher.runSync("createPaymentApplication", paCtx);
>              } catch (GenericServiceException e) {
> @@ -1955,7 +2036,6 @@
>      }
>  
>      public static Map refundPayment(DispatchContext dctx, Map context) {
> -        GenericDelegator delegator = dctx.getDelegator();
>          LocalDispatcher dispatcher = dctx.getDispatcher();
>          GenericValue userLogin = (GenericValue) context.get("userLogin");
>  
> @@ -2022,110 +2102,125 @@
>                      return ServiceUtil.returnError(ServiceUtil.getErrorMessage(refundResponse));
>                  }
>  
> -                //Debug.log("Called Electronic Refund Service : " + refundResponse, module);
> -
> -                // get the pay-from party
> -                if (paymentConfig == null || paymentConfig.length() == 0) {
> -                    paymentConfig = "payment.properties";
> -                }
> +                // get the pay to party ID for the order (will be the payFrom)
>                  String payFromPartyId = getPayToPartyId(orderHeader);
>  
> -                // create the PaymentGatewayResponse record
> -                String responseId = delegator.getNextSeqId("PaymentGatewayResponse");
> -                GenericValue response = delegator.makeValue("PaymentGatewayResponse", null);
> -                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", refundResponse.get("refundAmount"));
> -                response.set("referenceNum", refundResponse.get("refundRefNum"));
> -                response.set("altReference", refundResponse.get("refundAltRefNum"));
> -                response.set("gatewayCode", refundResponse.get("refundCode"));
> -                response.set("gatewayFlag", refundResponse.get("refundFlag"));
> -                response.set("gatewayMessage", refundResponse.get("refundMessage"));
> -                response.set("transactionDate", UtilDateTime.nowTimestamp());
> +                // process the refund result
> +                Map refundResRes;
>                  try {
> -                    delegator.create(response);
> -                } catch (GenericEntityException e) {
> +                    ModelService model = dctx.getModelService("processRefundResult");
> +                    Map refundResCtx = model.makeValid(context, ModelService.IN_PARAM);
> +                    refundResCtx.put("currencyUomId", orh.getCurrency());
> +                    refundResCtx.put("payToPartyId", payToPartyId);
> +                    refundResCtx.put("payFromPartyId", payFromPartyId);
> +                    refundResRes = dispatcher.runSync(model.name, refundResCtx);
> +                } catch (GenericServiceException e) {
>                      Debug.logError(e, module);
> -                    return ServiceUtil.returnError("Unable to create PaymentGatewayResponse record");
> +                    return ServiceUtil.returnError("Problem processing refund result: " + e.getMessage());
>                  }
>  
> -                // create the internal messages
> -                List messages = (List) refundResponse.get("internalRespMsgs");
> -                if (messages != null && messages.size() > 0) {
> -                    Iterator i = messages.iterator();
> -                    while (i.hasNext()) {
> -                        GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg", null);
> -                        String respMsgId = delegator.getNextSeqId("PaymentGatewayRespMsg");
> -                        String message = (String) i.next();
> -                        respMsg.set("paymentGatewayRespMsgId", respMsgId);
> -                        respMsg.set("paymentGatewayResponseId", responseId);
> -                        respMsg.set("pgrMessage", message);
> -                        try {
> -                            delegator.create(respMsg);
> -                        } catch (GenericEntityException e) {
> -                            Debug.logError(e, module);
> -                            return ServiceUtil.returnError("Unable to create PaymentGatewayRespMsg record");
> -                        }
> -                    }
> -                }
> +                return refundResRes;
> +            } else {
> +                return ServiceUtil.returnError("No refund service defined");
> +            }
> +        } else {
> +            return ServiceUtil.returnError("No payment settings found");
> +        }
> +    }
>  
> -                // handle the (reverse) payment
> -                Boolean refundResult = (Boolean) refundResponse.get("refundResult");
> -                if (refundResult != null && refundResult.booleanValue()) {
> -                    // create a payment record
> -                    Map paymentCtx = UtilMisc.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", orh.getCurrency());   
> -                    paymentCtx.put("amount", refundResponse.get("refundAmount"));
> -                    paymentCtx.put("userLogin", userLogin);
> -                    paymentCtx.put("paymentRefNum", refundResponse.get("refundRefNum"));
> -                    paymentCtx.put("comments", "Refund");
> +    public static Map processRefundResult(DispatchContext dctx, Map context) {
> +        LocalDispatcher dispatcher = dctx.getDispatcher();
> +        GenericDelegator delegator = dctx.getDelegator();
>  
> -                    String paymentId = null;
> -                    try {
> -                        Map 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("Problem creating Payment");
> -                    }
> -                    //Debug.log("Payment created : " + paymentId, module);
> +        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");
>  
> -                    if (paymentId == null) {
> -                        return ServiceUtil.returnError("Create payment failed");
> -                    }
> +        // create the PaymentGatewayResponse record
> +        String responseId = delegator.getNextSeqId("PaymentGatewayResponse");
> +        GenericValue response = delegator.makeValue("PaymentGatewayResponse", null);
> +        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("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 messages = (List) context.get("internalRespMsgs");
> +        if (messages != null && messages.size() > 0) {
> +            Iterator i = messages.iterator();
> +            while (i.hasNext()) {
> +                GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg", null);
> +                String respMsgId = delegator.getNextSeqId("PaymentGatewayRespMsg");
> +                String message = (String) i.next();
> +                respMsg.set("paymentGatewayRespMsgId", respMsgId);
> +                respMsg.set("paymentGatewayResponseId", responseId);
> +                respMsg.set("pgrMessage", message);
>  
> -                    Map result = ServiceUtil.returnSuccess();
> -                    result.put("paymentId", paymentId);
> -                    return result;
> +                // save the message
> +                savePgr(dctx, respMsg);
> +            }
> +        }
> +
> +        // handle the (reverse) payment
> +        Boolean refundResult = (Boolean) context.get("refundResult");
> +        if (refundResult != null && refundResult.booleanValue()) {
> +            // create a payment record
> +            Map paymentCtx = UtilMisc.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 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 {
> -                    return ServiceUtil.returnFailure("The refund failed");
> +                    paymentId = (String) payRes.get("paymentId");
>                  }
> -            } else {
> -                return ServiceUtil.returnError("No refund service defined");
> +            } catch (GenericServiceException e) {
> +                Debug.logError(e, "Problem creating Payment", module);
> +                return ServiceUtil.returnError("Problem creating Payment");
>              }
> +            //Debug.log("Payment created : " + paymentId, module);
> +
> +            if (paymentId == null) {
> +                return ServiceUtil.returnError("Create payment failed");
> +            }
> +
> +            Map result = ServiceUtil.returnSuccess();
> +            result.put("paymentId", paymentId);
> +            return result;
>          } else {
> -            return ServiceUtil.returnError("No payment settings found");
> +            return ServiceUtil.returnFailure("The refund failed");
>          }
>      }
>  
> -
>      public static Map retryFailedOrderAuth(DispatchContext dctx, Map context) {
>          GenericDelegator delegator = dctx.getDelegator();
>          LocalDispatcher dispatcher = dctx.getDispatcher();
> @@ -2393,6 +2488,33 @@
>          }
>  
>          return true;
> +    }
> +
> +    // safe payment gateway store
> +    private static void savePgr(DispatchContext dctx, GenericValue pgr) {        
> +        Map context = UtilMisc.toMap("paymentGatewayResponse", pgr);
> +        LocalDispatcher dispatcher = dctx.getDispatcher();
> +        GenericDelegator delegator = dctx.getDelegator();
> +
> +        try {
> +            dispatcher.addRollbackService("savePaymentGatewayResponse", context, true);
> +            delegator.create(pgr);
> +        } catch (Exception e) {
> +            Debug.logError(e, module);
> +        }
> +    }
> +
> +    public static Map savePaymentGatewayResponse(DispatchContext dctx, Map context) {
> +        GenericDelegator delegator = dctx.getDelegator();
> +        GenericValue pgr = (GenericValue) context.get("paymentGatewayResponse");
> +
> +        try {
> +            delegator.create(pgr);
> +        } catch (GenericEntityException e) {
> +            Debug.logError(e, module);
> +        }
> +
> +        return ServiceUtil.returnSuccess();
>      }
>  
>      // manual processing service
> 



Re: svn commit: r540041 - in /ofbiz/branches/release4.0/applications/accounting: servicedef/services_paymentmethod.xml src/org/ofbiz/accounting/payment/PaymentGatewayServices.java

Posted by Jacopo Cappellato <ti...@sastau.it>.
Scott,

in general, here is the list on my fixes to the trunk that I think 
should go in the release:

http://docs.ofbiz.org/x/7wg

Unfortunately I had no time to apply/test/commit them in the release branch.
Any help would be much appreciated.

Jacopo


Jacopo Cappellato wrote:
> Here is the list:
> 
> 536137
> 536143
> 536217
> 536545
> 
> Jacopo
> 
> Scott Gray wrote:
>> Hi Jacopo
>>
>> Thanks for letting me know, if you have a list on hand to send over that
>> would be great.
>>
>> Thanks
>> Scott
>>
>> On 21/05/07, Jacopo Cappellato <ti...@sastau.it> wrote:
>>>
>>> Scott,
>>>
>>> after the big work done in rev. 534944 by Andrew, I've committed a few
>>> minor fixes in the same area that are necessary to complete the work.
>>> If we have decided to include this work we have to include them too.
>>> Let me know if you can't find them, and I'll send you the list.
>>>
>>> Jacopo
>>>
> 



Re: svn commit: r540041 - in /ofbiz/branches/release4.0/applications/accounting: servicedef/services_paymentmethod.xml src/org/ofbiz/accounting/payment/PaymentGatewayServices.java

Posted by Jacopo Cappellato <ti...@sastau.it>.
Here is the list:

536137
536143
536217
536545

Jacopo

Scott Gray wrote:
> Hi Jacopo
> 
> Thanks for letting me know, if you have a list on hand to send over that
> would be great.
> 
> Thanks
> Scott
> 
> On 21/05/07, Jacopo Cappellato <ti...@sastau.it> wrote:
>>
>> Scott,
>>
>> after the big work done in rev. 534944 by Andrew, I've committed a few
>> minor fixes in the same area that are necessary to complete the work.
>> If we have decided to include this work we have to include them too.
>> Let me know if you can't find them, and I'll send you the list.
>>
>> Jacopo
>>



Re: svn commit: r540041 - in /ofbiz/branches/release4.0/applications/accounting: servicedef/services_paymentmethod.xml src/org/ofbiz/accounting/payment/PaymentGatewayServices.java

Posted by Scott Gray <le...@gmail.com>.
Hi Jacopo

Thanks for letting me know, if you have a list on hand to send over that
would be great.

Thanks
Scott

On 21/05/07, Jacopo Cappellato <ti...@sastau.it> wrote:
>
> Scott,
>
> after the big work done in rev. 534944 by Andrew, I've committed a few
> minor fixes in the same area that are necessary to complete the work.
> If we have decided to include this work we have to include them too.
> Let me know if you can't find them, and I'll send you the list.
>
> Jacopo
>
> lektran@apache.org wrote:
> > Author: lektran
> > Date: Sun May 20 23:52:15 2007
> > New Revision: 540041
> >
> > URL: http://svn.apache.org/viewvc?view=rev&rev=540041
> > Log:
> > Applied fix from trunk for revision: 534944
> >
> > Modified:
> >
> ofbiz/branches/release4.0/applications/accounting/servicedef/services_paymentmethod.xml
> >
> ofbiz/branches/release4.0/applications/accounting/src/org/ofbiz/accounting/payment/PaymentGatewayServices.java
> >
> > Modified:
> ofbiz/branches/release4.0/applications/accounting/servicedef/services_paymentmethod.xml
> > URL:
> http://svn.apache.org/viewvc/ofbiz/branches/release4.0/applications/accounting/servicedef/services_paymentmethod.xml?view=diff&rev=540041&r1=540040&r2=540041
> >
> ==============================================================================
> > ---
> ofbiz/branches/release4.0/applications/accounting/servicedef/services_paymentmethod.xml
> (original)
> > +++
> ofbiz/branches/release4.0/applications/accounting/servicedef/services_paymentmethod.xml
> Sun May 20 23:52:15 2007
> > @@ -285,7 +285,13 @@
> >          <attribute name="paymentId" type="String" mode="OUT"
> optional="false"/>
> >          <attribute name="paymentGatewayResponseId" type="String"
> mode="OUT" optional="true"/>
> >      </service>
> > -
> > +
> > +    <service name="processCaptureSplitPayment" engine="java"
> require-new-transaction="true"
> > +            location="
> org.ofbiz.accounting.payment.PaymentGatewayServices"
> invoke="captureBillingAccountPayment" auth="true">
> > +        <description>Handles the creation of new OrderPaymentPreference
> record (and Auth) for partial captures</description>
> > +        <attribute name="orderPaymentPreference" type="GenericValue"
> mode="IN" optional="false"/>
> > +        <attribute name="splitAmount" type="BigDecimal" mode="IN"
> optional="false"/>
> > +    </service>
> >
> >      <service name="refundPayment" engine="java"
> >              location="
> org.ofbiz.accounting.payment.PaymentGatewayServices"
> invoke="refundPayment" auth="true">
> > @@ -332,13 +338,53 @@
> >          <attribute name="internalRespMsgs" type="List" mode="IN"
> optional="true"/>
> >      </service>
> >
> > -    <service name="processPaymentServiceError" engine="java"
> require-new-transaction="true"
> > +   <service name="processReleaseResult" engine="java"
> > +            location="
> org.ofbiz.accounting.payment.PaymentGatewayServices"
> invoke="processReleaseResult" auth="true">
> > +        <description>Process the payment release
> result(s)</description>
> > +        <attribute name="orderPaymentPreference" type="GenericValue"
> mode="IN" optional="false"/>
> > +        <attribute name="releaseAmount" type="Double" mode="IN"
> optional="false"/>
> > +        <attribute name="currencyUomId" type="String" mode="IN"
> optional="true"/>
> > +        <attribute name="releaseResult" type="Boolean" mode="IN"
> optional="false"/>
> > +        <attribute name="releaseAltRefNum" type="String" mode="IN"
> optional="true"/>
> > +        <attribute name="releaseRefNum" type="String" mode="IN"
> optional="false"/>
> > +        <attribute name="releaseCode" type="String" mode="IN"
> optional="true"/>
> > +        <attribute name="releaseFlag" type="String" mode="IN"
> optional="true"/>
> > +        <attribute name="releaseMessage" type="String" mode="IN"
> optional="true"/>
> > +        <attribute name="internalRespMsgs" type="List" mode="IN"
> optional="true"/>
> > +    </service>
> > +
> > +    <service name="processRefundResult" engine="java"
> > +            location="
> org.ofbiz.accounting.payment.PaymentGatewayServices"
> invoke="processRefundResult" auth="true">
> > +        <description>Process the payment refund result(s)</description>
> > +        <attribute name="orderPaymentPreference" type="GenericValue"
> mode="IN" optional="false"/>
> > +        <attribute name="serviceTypeEnum" type="String" mode="IN"
> optional="true"/>
> > +        <attribute name="payFromPartyId" type="String" mode="IN"
> optional="true"/>
> > +        <attribute name="payToPartyId" type="String" mode="IN"
> optional="true"/>
> > +        <attribute name="invoiceId" type="String" mode="IN"
> optional="true"/>
> > +        <attribute name="refundAmount" type="Double" mode="IN"
> optional="false"/>
> > +        <attribute name="currencyUomId" type="String" mode="IN"
> optional="true"/>
> > +        <attribute name="refundResult" type="Boolean" mode="IN"
> optional="false"/>
> > +        <attribute name="refundAltRefNum" type="String" mode="IN"
> optional="true"/>
> > +        <attribute name="refundRefNum" type="String" mode="IN"
> optional="false"/>
> > +        <attribute name="refundCode" type="String" mode="IN"
> optional="true"/>
> > +        <attribute name="refundFlag" type="String" mode="IN"
> optional="true"/>
> > +        <attribute name="refundMessage" type="String" mode="IN"
> optional="true"/>
> > +        <attribute name="internalRespMsgs" type="List" mode="IN"
> optional="true"/>
> > +    </service>
> > +
> > +    <service name="processPaymentServiceError" engine="java"
> require-new-transaction="true" max-retry="5"
> >              location="
> org.ofbiz.accounting.payment.PaymentGatewayServices"
> invoke="storePaymentErrorMessage" auth="true">
> >          <description>Process (store) error messages from payment
> service failures</description>
> >          <attribute name="paymentServiceTypeEnumId" type="String"
> mode="IN" optional="false"/>
> >          <attribute name="orderPaymentPreference" type="GenericValue"
> mode="IN" optional="false"/>
> >          <attribute name="transCodeEnumId" type="String" mode="IN"
> optional="false"/>
> >          <attribute name="serviceResultMap" type="Map" mode="IN"
> optional="false"/>
> > +    </service>
> > +
> > +    <service name="savePaymentGatewayResponse" engine="java"
> > +            location="
> org.ofbiz.accounting.payment.PaymentGatewayServices"
> invoke="storePaymentErrorMessage" auth="false">
> > +        <description>Method to make sure PaymentGatewayResponse records
> get stored (uses XA wrapper on rollback)</description>
> > +        <attribute name="paymentGatewayResponse" type="GenericValue"
> mode="IN" optional="false"/>
> >      </service>
> >
> >      <!-- Payment Gateway Interfaces -->
> >
> > Modified:
> ofbiz/branches/release4.0/applications/accounting/src/org/ofbiz/accounting/payment/PaymentGatewayServices.java
> > URL:
> http://svn.apache.org/viewvc/ofbiz/branches/release4.0/applications/accounting/src/org/ofbiz/accounting/payment/PaymentGatewayServices.java?view=diff&rev=540041&r1=540040&r2=540041
> >
> ==============================================================================
> > ---
> ofbiz/branches/release4.0/applications/accounting/src/org/ofbiz/accounting/payment/PaymentGatewayServices.java
> (original)
> > +++
> ofbiz/branches/release4.0/applications/accounting/src/org/ofbiz/accounting/payment/PaymentGatewayServices.java
> Sun May 20 23:52:15 2007
> > @@ -49,11 +49,7 @@
> >  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 org.ofbiz.service.*;
> >
> >  /**
> >   * PaymentGatewayServices
> > @@ -127,6 +123,7 @@
> >          orderPaymentPreference.set("processAttempt", new Long(
> procAttempt.longValue() + 1));
> >          try {
> >              orderPaymentPreference.store();
> > +            orderPaymentPreference.refresh();
> >          } catch (GenericEntityException e) {
> >              Debug.logError(e, module);
> >              return ServiceUtil.returnError("Unable to update
> OrderPaymentPreference record!");
> > @@ -162,11 +159,6 @@
> >
> >              // handle the response
> >              if (authPaymentResult != null) {
> > -                // get the customer messages
> > -                if (authPaymentResult.get("customerRespMsgs") != null)
> {
> > -                    // NOTE DEJ20060911: hmmm... was something supposed
> to be done here?
> > -                }
> > -
> >                  // not null result means either an approval or decline;
> null would mean error
> >                  Double thisAmount = (Double) authPaymentResult.get
> ("processAmount");
> >
> > @@ -526,6 +518,7 @@
> >
> >                  // at this point if we have a successful result, let's
> save the new creditCard expireDate
> >                  if (!ServiceUtil.isError(processorResult) &&
> Boolean.TRUE.equals((Boolean) 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();
> >                  }
> >              }
> > @@ -811,93 +804,105 @@
> >
> >          // get the release result code
> >          if (releaseResult != null &&
> !ServiceUtil.isError(releaseResult)) {
> > -            Boolean releaseResponse = (Boolean) releaseResult.get
> ("releaseResult");
> > +            Map releaseResRes;
> > +            try {
> > +                ModelService model = dctx.getModelService
> ("processReleaseResult");
> > +                Map resCtx = model.makeValid(result,
> ModelService.IN_PARAM);
> > +                releaseResRes = dispatcher.runSync(model.name
> ,  resCtx);
> > +            } catch (GenericServiceException e) {
> > +                Debug.logError(e, module);
> > +                return ServiceUtil.returnError("Trouble processing the
> release results: " + 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));
> > +        }
> >
> > -            // create the PaymentGatewayResponse
> > -            String responseId = delegator.getNextSeqId
> ("PaymentGatewayResponse");
> > -            GenericValue pgResponse = delegator.makeValue("PaymentGatewayResponse",
> null);
> > -            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("referenceNum", releaseResult.get
> ("releaseRefNum"));
> > -            pgResponse.set("altReference", releaseResult.get
> ("releaseAltRefNum"));
> > -            pgResponse.set("gatewayCode", releaseResult.get
> ("releaseCode"));
> > -            pgResponse.set("gatewayFlag", releaseResult.get
> ("releaseFlag"));
> > -            pgResponse.set("gatewayMessage", releaseResult.get
> ("releaseMessage"));
> > -            pgResponse.set("transactionDate", UtilDateTime.nowTimestamp
> ());
> > +        return result;
> > +    }
> > +
> > +    public static Map processReleaseResult(DispatchContext dctx, Map
> context) {
> > +        GenericDelegator delegator = dctx.getDelegator();
> > +
> > +        GenericValue paymentPref = (GenericValue) context.get
> ("orderPaymentPreference");
> > +        Boolean releaseResponse = (Boolean) context.get
> ("releaseResult");
> > +
> > +        // create the PaymentGatewayResponse
> > +        String responseId = delegator.getNextSeqId
> ("PaymentGatewayResponse");
> > +        GenericValue pgResponse = delegator.makeValue("PaymentGatewayResponse",
> null);
> > +        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("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());
> > +
> > +        // store the gateway response
> > +        savePgr(dctx, pgResponse);
> > +
> > +        // create the internal messages
> > +        List messages = (List) context.get("internalRespMsgs");
> > +        if (messages != null && messages.size() > 0) {
> > +            Iterator i = messages.iterator();
> > +            while (i.hasNext()) {
> > +                GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg",
> null);
> > +                String respMsgId = delegator.getNextSeqId
> ("PaymentGatewayRespMsg");
> > +                String message = (String) i.next();
> > +                respMsg.set("paymentGatewayRespMsgId", respMsgId);
> > +                respMsg.set("paymentGatewayResponseId", responseId);
> > +                respMsg.set("pgrMessage", message);
> > +
> > +                // store the messages
> > +                savePgr(dctx, respMsg);
> > +            }
> > +        }
> >
> > -            // store the gateway response
> > +        if (releaseResponse != null && releaseResponse.booleanValue())
> {
> > +            paymentPref.set("statusId", "PAYMENT_CANCELLED");
> >              try {
> > -                pgResponse.create();
> > +                paymentPref.store();
> >              } catch (GenericEntityException e) {
> > -                Debug.logError(e, "Problem storing
> PaymentGatewayResponse entity; authorization was released! : " + pgResponse,
> module);
> > +                Debug.logError(e, "Problem storing updated payment
> preference; authorization was released!", module);
> >              }
> >
> > -            // create the internal messages
> > -            List messages = (List) releaseResult.get
> ("internalRespMsgs");
> > -            if (messages != null && messages.size() > 0) {
> > -                Iterator i = messages.iterator();
> > -                while (i.hasNext()) {
> > -                    GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg",
> null);
> > -                    String respMsgId = delegator.getNextSeqId
> ("PaymentGatewayRespMsg");
> > -                    String message = (String) i.next();
> > -                    respMsg.set("paymentGatewayRespMsgId", respMsgId);
> > -                    respMsg.set("paymentGatewayResponseId",
> responseId);
> > -                    respMsg.set("pgrMessage", message);
> > -                    try {
> > -                        delegator.create(respMsg);
> > -                    } catch (GenericEntityException e) {
> > -                        String errMsg = "Unable to create
> PaymentGatewayRespMsg record";
> > -                        Debug.logError(e, errMsg, module);
> > -                        return ServiceUtil.returnError(errMsg);
> > -                    }
> > -                }
> > +            // cancel any payment records
> > +            List paymentList = null;
> > +            try {
> > +                paymentList = paymentPref.getRelated("Payment");
> > +            } catch (GenericEntityException e) {
> > +                Debug.logError(e, "Unable to get Payment records from
> OrderPaymentPreference : " + paymentPref, module);
> >              }
> >
> > -            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 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 pi = paymentList.iterator();
> > -                    while (pi.hasNext()) {
> > -                        GenericValue pay = (GenericValue) pi.next();
> > -                        pay.set("statusId", "PMNT_CANCELLED");
> > -                        try {
> > -                            pay.store();
> > -                        } catch (GenericEntityException e) {
> > -                            Debug.logError(e, "Unable to store Payment
> : " + pay, module);
> > -                        }
> > +            if (paymentList != null) {
> > +                Iterator pi = paymentList.iterator();
> > +                while (pi.hasNext()) {
> > +                    GenericValue pay = (GenericValue) pi.next();
> > +                    pay.set("statusId", "PMNT_CANCELLED");
> > +                    try {
> > +                        pay.store();
> > +                    } catch (GenericEntityException e) {
> > +                        Debug.logError(e, "Unable to store Payment : "
> + pay, module);
> >                      }
> >                  }
> > -            } else {
> > -                String errMsg = "Release failed for pref : " +
> paymentPref;
> > -                Debug.logError(errMsg, module);
> > -                result = ServiceUtil.returnFailure(errMsg);
> >              }
> > -        } else if (ServiceUtil.isError(releaseResult)) {
> > -            saveError(dispatcher, userLogin, paymentPref,
> releaseResult, RELEASE_SERVICE_TYPE, "PGT_RELEASE");
> > -            result = ServiceUtil.returnError(
> ServiceUtil.getErrorMessage(releaseResult));
> > +        } else {
> > +            String errMsg = "Release failed for pref : " + paymentPref;
> > +            Debug.logError(errMsg, module);
> > +            return ServiceUtil.returnFailure(errMsg);
> >          }
> >
> > -        return result;
> > +        return ServiceUtil.returnSuccess();
> >      }
> >
> >      /**
> > @@ -1079,19 +1084,19 @@
> >
> >          BigDecimal totalPayments = PaymentWorker.getPaymentsTotal(
> orh.getOrderPayments());
> >          totalPayments = totalPayments.setScale(2,
> BigDecimal.ROUND_HALF_UP);
> > +
> >          BigDecimal remainingTotalBd = orderGrandTotal.subtract
> (totalPayments);
> >          if (Debug.infoOn()) Debug.logInfo("Capture Remaining Total: " +
> remainingTotalBd, module);
> >
> > -        double amountToCapture = 0.0;
> > +        BigDecimal amountToCapture = ZERO;
> >          if (captureAmountBd == null) {
> > -            amountToCapture = remainingTotalBd.doubleValue();
> > +            amountToCapture = remainingTotalBd;
> >          } else {
> > -            amountToCapture = captureAmountBd.doubleValue();
> > +            amountToCapture = captureAmountBd;
> >          }
> >          if (Debug.infoOn()) Debug.logInfo("Actual Expected Capture
> Amount : " + amountToCapture, module);
> >
> >          // iterate over the prefs and capture each one until we meet
> our total
> > -        List finished = new ArrayList();
> >          Iterator 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...
> > @@ -1101,64 +1106,78 @@
> >                  continue;
> >              }
> >
> > -            Double authAmount = authTrans.getDouble("amount");
> > -            if (authAmount == null) authAmount = new Double(0.00);
> > -            if (authAmount.doubleValue() == 0.00) {
> > +            // 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 = new BigDecimal(0.00);
> > +            authAmount = authAmount.setScale(2,
> BigDecimal.ROUND_HALF_UP);
> > +
> > +            if (authAmount.compareTo(ZERO) == 0) {
> >                  // nothing to capture
> >                  Debug.logInfo("Nothing to capture; authAmount = 0",
> module);
> >                  continue;
> >              }
> > -            //Debug.log("Actual Auth amount : " + authAmount, module);
> >
> >              // if the authAmount is more then the remaining total; just
> use remaining total
> > -            if (authAmount.doubleValue() > remainingTotalBd.doubleValue())
> {
> > -                authAmount = new Double(remainingTotalBd.doubleValue
> ());
> > +            if (authAmount.compareTo(remainingTotalBd) == 1) {
> > +                authAmount = new BigDecimal(
> remainingTotalBd.doubleValue());
> >              }
> >
> >              // if we have a billing account; total up auth + account
> available
> > -            double amountToBillAccount = 0.00;
> > +            BigDecimal amountToBillAccount = ZERO;
> >              if (billingAccountAvail != null) {
> > -                amountToBillAccount = authAmount.doubleValue() +
> billingAccountAvail.doubleValue();
> > +                amountToBillAccount = authAmount.add(billingAccountAvail).setScale(2,
> BigDecimal.ROUND_HALF_UP);
> >              }
> >
> >              // the amount for *this* capture
> > -            double amountThisCapture = 0.00;
> > +            BigDecimal amountThisCapture;
> >
> >              // determine how much for *this* capture
> > -            if (authAmount.doubleValue() >= amountToCapture) {
> > +            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.doubleValue();
> > -            } else if (billingAccountAvail != null &&
> amountToBillAccount >= amountToCapture) {
> > +                amountThisCapture = authAmount;
> > +            } else if (billingAccountAvail != null &&
> amountToBillAccount.compareTo(amountToCapture) >= 0) {
> >                  // the provided billing account will cover the
> remaining; just capture what was autorized
> > -                amountThisCapture = authAmount.doubleValue();
> > +                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.doubleValue();
> > +                amountThisCapture = authAmount;
> >              }
> >
> >              Debug.logInfo("Payment preference = [" + paymentPref + "]
> amount to capture = [" + amountToCapture +"] amount of this capture = [" +
> amountThisCapture +"] actual auth amount =[" + authAmount + "]
> amountToBillAccount = [" + amountToBillAccount + "]", module);
> > -            Map captureResult = capturePayment(dctx, userLogin, orh,
> paymentPref, amountThisCapture);
> > +            Map captureResult = capturePayment(dctx, userLogin, orh,
> paymentPref, amountThisCapture.doubleValue());
> >              if (captureResult != null) {
> >                  // credit card processors return captureAmount, but
> gift certificate processors return processAmount
> >                  Double amountCaptured = (Double) captureResult.get
> ("captureAmount");
> >                  if (amountCaptured == null) {
> >                      amountCaptured = (Double) captureResult.get
> ("processAmount");
> >                  }
> > +
> > +                // big decimal reference to the capture amount
> > +                BigDecimal amountCapturedBd = new BigDecimal(
> amountCaptured.doubleValue());
> > +                amountCapturedBd = amountCapturedBd.setScale(2,
> BigDecimal.ROUND_HALF_UP);
> > +
> >                  // decrease amount of next payment preference to
> capture
> > -                if (amountCaptured != null) amountToCapture -=
> amountCaptured.doubleValue();
> > -                finished.add(captureResult);
> > +                if (amountCaptured != null) {
> > +                    amountToCapture = amountToCapture.subtract
> (amountCapturedBd);
> > +                }
> >
> >                  // add the invoiceId to the result for processing
> >                  captureResult.put("invoiceId", invoiceId);
> >
> > -               // process the capture's results
> > +                // process the capture's results
> >                  try {
> >                      processResult(dctx, captureResult, userLogin,
> paymentPref);
> >                  } catch (GeneralException e) {
> > @@ -1167,58 +1186,27 @@
> >                  }
> >
> >                  // create any splits which are needed
> > -                BigDecimal totalAmountCaptured = new
> BigDecimal(amountThisCapture);
> > -                if (authAmount.doubleValue() >
> totalAmountCaptured.doubleValue()) {
> > -                    // create a new payment preference and authorize it
> > -                    double newAmount = authAmount.doubleValue() -
> totalAmountCaptured.doubleValue(); // TODO: use BigDecimal arithmetic here
> (and everywhere else for that matter)
> > -                    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", paymentPref.get
> ("maxAmount"));
> > -                    newPref.set("statusId", "PAYMENT_NOT_AUTH");
> > -                    newPref.set("createdDate",
> UtilDateTime.nowTimestamp());
> > -                    if (userLogin != null) {
> > -                        newPref.set("createdByUserLogin",
> userLogin.getString("userLoginId"));
> > -                    }
> > -                    Debug.logInfo("New preference : " + newPref,
> module);
> > -                    Map processorResult = null;
> > +                if (authAmount.compareTo(amountThisCapture) == 1) {
> > +                    BigDecimal splitAmount = authAmount.subtract
> (amountThisCapture);
> > +                    Map splitResp = null;
> >                      try {
> > -                        // create the new payment preference
> > -                        delegator.create(newPref);
> > -
> > -                        // authorize the new preference
> > -                        processorResult = authPayment(dispatcher,
> userLogin, orh, newPref, newAmount, false, null);
> > -                        if (processorResult != null) {
> > -                            // process the auth results
> > -                            boolean authResult = processResult(dctx,
> processorResult, userLogin, newPref);
> > -                            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);
> > -                        }
> > +                        Map splitCtx = UtilMisc.toMap("userLogin",
> userLogin, "orderPaymentPreference", paymentPref, "splitAmount",
> splitAmount);
> > +                        dispatcher.addCommitService("processCaptureSplitPayment",
> splitCtx, true);
> > +                    } catch (GenericServiceException e) {
> > +                        Debug.logWarning(e, "Problem processing the
> capture split payment", module);
> > +                    }
> > +                    if (ServiceUtil.isError(splitResp)) {
> > +                        Debug.logWarning("Problem processing the
> capture split payment: " + ServiceUtil.getErrorMessage(splitResp),
> module);
> >                      }
> >                  }
> >              } else {
> >                  Debug.logError("Payment not captured", module);
> > -                continue;
> >              }
> >          }
> >
> > -        if (amountToCapture > 0.00) {
> > +        if (amountToCapture.compareTo(ZERO) == 1) {
> >              GenericValue productStore = orh.getProductStore();
> > -            if (! UtilValidate.isEmpty(productStore)) {
> > +            if (!UtilValidate.isEmpty(productStore)) {
> >                  boolean shipIfCaptureFails = UtilValidate.isEmpty(
> productStore.get("shipIfCaptureFails")) || "Y".equalsIgnoreCase(
> productStore.getString("shipIfCaptureFails"));
> >                  if(! shipIfCaptureFails) {
> >                      return ServiceUtil.returnError("Cannot ship order
> because credit card captures were unsuccessful");
> > @@ -1234,6 +1222,61 @@
> >          }
> >      }
> >
> > +    public static Map processCaptureSplitPayment(DispatchContext dctx,
> Map context) {
> > +        LocalDispatcher dispatcher = dctx.getDispatcher();
> > +        GenericDelegator delegator = dctx.getDelegator();
> > +
> > +        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);
> > +
> > +        // create a new payment preference and authorize it
> > +        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", paymentPref.get("maxAmount"));
> > +        newPref.set("statusId", "PAYMENT_NOT_AUTH");
> > +        newPref.set("createdDate", UtilDateTime.nowTimestamp());
> > +        if (userLogin != null) {
> > +            newPref.set("createdByUserLogin", userLogin.getString
> ("userLoginId"));
> > +        }
> > +        if (Debug.verboseOn()) Debug.logVerbose("New preference : " +
> newPref, module);
> > +
> > +        Map processorResult = null;
> > +        try {
> > +            // create the new payment preference
> > +            delegator.create(newPref);
> > +
> > +            // authorize the new preference
> > +            processorResult = authPayment(dispatcher, userLogin, orh,
> newPref, splitAmount.doubleValue(), false, null);
> > +            if (processorResult != null) {
> > +                // process the auth results
> > +                boolean authResult = processResult(dctx,
> processorResult, userLogin, newPref);
> > +                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();
> > +    }
> > +
> >      public static Map captureBillingAccountPayment(DispatchContext
> dctx, Map context) {
> >          GenericDelegator delegator = dctx.getDelegator();
> >          LocalDispatcher dispatcher = dctx.getDispatcher();
> > @@ -1296,7 +1339,9 @@
> >                          // referenceNum holds the relation to the
> order.
> >                          // todo: Extend PaymentGatewayResponse with a
> billingAccountId field?
> >                          pgResponse.set("referenceNum",
> billingAccountId);
> > -                        pgResponse.create();
> > +
> > +                        // save the response
> > +                        savePgr(dctx, pgResponse);
> >
> >                          // Update the orderPaymentPreference
> >                          orderPaymentPreference.set("statusId",
> "PAYMENT_SETTLED");
> > @@ -1505,17 +1550,21 @@
> >          result.put("orderPaymentPreference", paymentPreference);
> >          ModelService model = dctx.getModelService("processAuthResult");
> >          Map context = model.makeValid(result, ModelService.IN_PARAM);
> > -        Map svcResp = null;
> > +
> > +        // in case we rollback make sure this service gets called
> > +        dispatcher.addRollbackService(model.name, context, true);
> > +
> > +        // invoke the service
> > +        Map resResp;
> >          try {
> > -            svcResp = dispatcher.runSync("processAuthResult", context);
> > +            resResp = dispatcher.runSync(model.name, context);
> >          } catch (GenericServiceException e) {
> >              Debug.logError(e, module);
> >              throw e;
> >          }
> > -        if (svcResp != null && ServiceUtil.isError(svcResp)) {
> > -           Debug.logError(ServiceUtil.getErrorMessage(svcResp),
> module);
> > -           throw new GeneralException(ServiceUtil.getErrorMessage
> (svcResp));
> > -        }
> > +        if (ServiceUtil.isError(resResp)) {
> > +            throw new GeneralException(ServiceUtil.getErrorMessage
> (resResp));
> > +        }
> >      }
> >
> >      public static Map processAuthResult(DispatchContext dctx, Map
> context) {
> > @@ -1526,6 +1575,14 @@
> >          String currencyUomId = (String) context.get("currencyUomId");
> >          Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
> >
> > +        // 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;
> > @@ -1567,8 +1624,9 @@
> >              if (Boolean.TRUE.equals((Boolean) context.get("resultNsf")))
> response.set("resultNsf", "Y");
> >              if (Boolean.TRUE.equals((Boolean) context.get("resultBadExpire")))
> response.set("resultBadExpire", "Y");
> >              if (Boolean.TRUE.equals((Boolean) context.get("resultBadCardNumber")))
> response.set("resultBadCardNumber", "Y");
> > -
> > -            response.create();
> > +
> > +            // save the response
> > +            savePgr(dctx, response);
> >
> >              // create the internal messages
> >              List messages = (List) context.get("internalRespMsgs");
> > @@ -1581,7 +1639,7 @@
> >                      respMsg.set("paymentGatewayRespMsgId", respMsgId);
> >                      respMsg.set("paymentGatewayResponseId",
> responseId);
> >                      respMsg.set("pgrMessage", message);
> > -                    delegator.create(respMsg);
> > +                    savePgr(dctx, respMsg);
> >                  }
> >              }
> >
> > @@ -1607,8 +1665,8 @@
> >              }
> >
> >              orderPaymentPreference.store();
> > -
> > -            // if the payment was declined and this is a CreditCard,
> save that information on the CreditCard entity
> > +
> > +            // 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");
> > @@ -1628,7 +1686,6 @@
> >                          }
> >                          creditCard.set("lastFailedNsfDate",
> nowTimestamp);
> >                      }
> > -
> >                      creditCard.store();
> >                  }
> >              }
> > @@ -1640,7 +1697,6 @@
> >                      creditCard.set("lastFailedAuthDate", null);
> >                      creditCard.set("consecutiveFailedNsf", new
> Long(0));
> >                      creditCard.set("lastFailedNsfDate", null);
> > -
> >                      creditCard.store();
> >                  }
> >              }
> > @@ -1692,6 +1748,10 @@
> >      }
> >
> >      private static void processCaptureResult(DispatchContext dctx, Map
> result, GenericValue userLogin, GenericValue paymentPreference, String
> authServiceType) 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");
> >          Double amount = null;
> > @@ -1706,14 +1766,19 @@
> >              throw new GeneralException("Unable to process null capture
> amount");
> >          }
> >
> > -        if (result != null && captureResult.booleanValue()) {
> > +        // setup the amount big decimal
> > +        BigDecimal amtBd = new BigDecimal(amount.doubleValue());
> > +        amtBd = amtBd.setScale(2, BigDecimal.ROUND_HALF_UP);
> > +
> > +        if (captureResult.booleanValue()) {
> > +            // capture returned true (passed)
> >              result.put("orderPaymentPreference", paymentPreference);
> >              result.put("userLogin", userLogin);
> >              result.put("serviceTypeEnum", authServiceType);
> >
> >              ModelService model = dctx.getModelService
> ("processCaptureResult");
> >              Map context = model.makeValid(result, ModelService.IN_PARAM
> );
> > -            Map capRes = null;
> > +            Map capRes;
> >              try {
> >                  capRes = dispatcher.runSync("processCaptureResult",
> context);
> >              } catch (GenericServiceException e) {
> > @@ -1723,66 +1788,77 @@
> >              if (capRes != null && ServiceUtil.isError(capRes)) {
> >                  throw new GeneralException(ServiceUtil.getErrorMessage
> (capRes));
> >              }
> > -        } else if (result != null && !captureResult.booleanValue()) {
> > -            // problem with the capture lets get some needed info
> > -            OrderReadHelper orh = null;
> > +        } else {
> > +            // capture returned false (error)
> >              try {
> > -                GenericValue orderHeader =
> paymentPreference.getRelatedOne("OrderHeader");
> > -                if (orderHeader != null)
> > -                    orh = new OrderReadHelper(orderHeader);
> > -            } catch (GenericEntityException e) {
> > -                Debug.logError(e, "Problems getting OrderHeader; cannot
> re-auth the payment", module);
> > +                processReAuthFromCaptureFailure(dctx, result, amtBd,
> userLogin, paymentPreference);
> > +            } catch (GeneralException e) {
> > +                // just log this for now (same as previous
> implementation)
> > +                Debug.logError(e, module);
> >              }
> > +        }
> > +    }
> >
> > -            if (amount != null && amount.doubleValue() == new Double(
> 0.00).doubleValue()) {
> > -                amount = paymentPreference.getDouble("maxAmount");
> > -                Debug.log("resetting payment amount from 0.00 to
> correctMax amount", module);
> > -            }
> > -            Debug.log("reauth with amount: " + amount, module);
> > -            if (orh != null) {
> > -                // first lets re-auth the card
> > -                Map authPayRes = authPayment(dispatcher, userLogin,
> orh, paymentPreference, amount.doubleValue(), true, null);
> > -                Debug.log("authPayRes: " + authPayRes, module);
> > -                if (authPayRes != null) {
> > -                    Boolean authResp = (Boolean) authPayRes.get
> ("authResult");
> > -                    Boolean capResp = (Boolean) authPayRes.get
> ("captureResult");
> > -                    if (authResp != null) {
> > -                        GenericValue authTrans =
> processAuthRetryResult(dctx, authPayRes, userLogin, paymentPreference);
> > -
> > -                        if (authResp.booleanValue()) {
> > -                            // first make sure we didn't already
> capture - probably not
> > -                            if (capResp != null && capResp.booleanValue())
> {
> > -                                processCaptureResult(dctx, result,
> userLogin, paymentPreference);
> > -                            } else {
> > -                                // lets try to capture the funds now
> > -                                Map capPayRes = capturePayment(dctx,
> userLogin, orh, paymentPreference, amount.doubleValue(), authTrans);
> > -                                if (capPayRes != null) {
> > -                                    Boolean capPayResp = (Boolean)
> capPayRes.get("captureResult");
> > -                                    if (capPayResp != null &&
> capPayResp.booleanValue()) {
> > -                                        // it was successful
> > -                                        processCaptureResult(dctx,
> capPayRes, userLogin, paymentPreference);
> > -                                    } else {
> > -                                        // not successful; log it
> > -                                        Debug.logError("Capture of
> authorized payment failed: " + paymentPreference, module);
> > -                                    }
> > -                                } else {
> > -                                    Debug.logError("Problems trying to
> capture payment (null result): " + paymentPreference, module);
> > -                                }
> > -                            }
> > -                        } else {
> > -                            Debug.logError("Payment authorization
> failed:  " + paymentPreference, module);
> > -                        }
> > -                    } else {
> > -                        Debug.logError("Payment authorization failed
> (null result):  " + paymentPreference, module);
> > -                    }
> > +    private static void processReAuthFromCaptureFailure(DispatchContext
> dctx, Map result, BigDecimal amount, GenericValue userLogin, GenericValue
> paymentPreference) 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 authPayRes = authPayment(dispatcher, userLogin, orh,
> paymentPreference, amount.doubleValue(), 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);
> > +            } else {
> > +                // no auto-capture; do manual capture now
> > +                Map capPayRes = capturePayment(dctx, userLogin, orh,
> paymentPreference, amount.doubleValue(), authTrans);
> > +                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);
> >                  } else {
> > -                    Debug.logError("Problems trying to re-authorize the
> payment (null result): " + paymentPreference, module);
> > +                    throw new GeneralException("Capture of authorized
> payment failed");
> >                  }
> > -            } else {
> > -                Debug.logError("Null OrderReadHelper cannot process",
> module);
> >              }
> >          } else {
> > -            Debug.logError("Result pass is null, no capture available",
> module);
> > +            throw new GeneralException("Payment re-authorization
> failed");
> >          }
> >      }
> >
> > @@ -1802,6 +1878,23 @@
> >              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
> > +        paymentPreference.set("statusId", "PAYMENT_SETTLED");
> > +        try {
> > +            paymentPreference.store();
> > +        } catch (GenericEntityException e) {
> > +            Debug.logError(e, module);
> > +            return ServiceUtil.returnError(e.getMessage());
> > +        }
> > +
> >          // create the PaymentGatewayResponse record
> >          String responseId = delegator.getNextSeqId
> ("PaymentGatewayResponse");
> >          GenericValue response = delegator.makeValue("PaymentGatewayResponse",
> null);
> > @@ -1826,12 +1919,9 @@
> >          response.set("gatewayFlag", context.get("captureFlag"));
> >          response.set("gatewayMessage", context.get("captureMessage"));
> >          response.set("transactionDate", UtilDateTime.nowTimestamp());
> > -        try {
> > -            delegator.create(response);
> > -        } catch (GenericEntityException e) {
> > -            Debug.logError(e, module);
> > -            return ServiceUtil.returnError("Error creating response
> information");
> > -        }
> > +
> > +        // save the response
> > +        savePgr(dctx, response);
> >
> >          // create the internal messages
> >          List messages = (List) context.get("internalRespMsgs");
> > @@ -1844,12 +1934,9 @@
> >                  respMsg.set("paymentGatewayRespMsgId", respMsgId);
> >                  respMsg.set("paymentGatewayResponseId", responseId);
> >                  respMsg.set("pgrMessage", message);
> > -                try {
> > -                    delegator.create(respMsg);
> > -                } catch (GenericEntityException e) {
> > -                    Debug.logError(e, module);
> > -                    return ServiceUtil.returnError("Error creating
> response message information");
> > -                }
> > +
> > +                // save the message
> > +                savePgr(dctx, respMsg);
> >              }
> >          }
> >
> > @@ -1879,7 +1966,7 @@
> >              } catch (GenericEntityException e) {
> >                  Debug.logError(e, module);
> >              }
> > -            if (orl.size() > 0) {
> > +            if (orl != null && orl.size() > 0) {
> >                  GenericValue orderRole = EntityUtil.getFirst(orl);
> >                  partyIdFrom = orderRole.getString("partyId");
> >              }
> > @@ -1914,24 +2001,18 @@
> >          paymentCtx.put("userLogin", userLogin);
> >          paymentCtx.put("paymentRefNum", context.get("captureRefNum"));
> >
> > -        Map payRes = null;
> > +        Map payRes;
> >          try {
> >              payRes = dispatcher.runSync("createPayment", paymentCtx);
> >          } catch (GenericServiceException e) {
> >              Debug.logError(e, module);
> >              return ServiceUtil.returnError("Error creating payment
> record");
> >          }
> > -        if (payRes != null && ServiceUtil.isError(payRes)) {
> > +        if (ServiceUtil.isError(payRes)) {
> >              return ServiceUtil.returnError(ServiceUtil.getErrorMessage
> (payRes));
> >          }
> >
> >          String paymentId = (String) payRes.get("paymentId");
> > -        paymentPreference.set("statusId", "PAYMENT_SETTLED");
> > -        try {
> > -            paymentPreference.store();
> > -        } catch (GenericEntityException e) {
> > -            Debug.logError(e, module);
> > -        }
> >
> >          // create the PaymentApplication if invoiceId is available
> >          if (invoiceId != null) {
> > @@ -1939,7 +2020,7 @@
> >              Map paCtx = UtilMisc.toMap("paymentId", paymentId,
> "invoiceId", invoiceId);
> >              paCtx.put("amountApplied", context.get("captureAmount"));
> >              paCtx.put("userLogin", userLogin);
> > -            Map paRes = null;
> > +            Map paRes;
> >              try {
> >                  paRes = dispatcher.runSync("createPaymentApplication",
> paCtx);
> >              } catch (GenericServiceException e) {
> > @@ -1955,7 +2036,6 @@
> >      }
> >
> >      public static Map refundPayment(DispatchContext dctx, Map context)
> {
> > -        GenericDelegator delegator = dctx.getDelegator();
> >          LocalDispatcher dispatcher = dctx.getDispatcher();
> >          GenericValue userLogin = (GenericValue) context.get
> ("userLogin");
> >
> > @@ -2022,110 +2102,125 @@
> >                      return ServiceUtil.returnError(
> ServiceUtil.getErrorMessage(refundResponse));
> >                  }
> >
> > -                //Debug.log("Called Electronic Refund Service : " +
> refundResponse, module);
> > -
> > -                // get the pay-from party
> > -                if (paymentConfig == null || paymentConfig.length() ==
> 0) {
> > -                    paymentConfig = "payment.properties";
> > -                }
> > +                // get the pay to party ID for the order (will be the
> payFrom)
> >                  String payFromPartyId = getPayToPartyId(orderHeader);
> >
> > -                // create the PaymentGatewayResponse record
> > -                String responseId = delegator.getNextSeqId
> ("PaymentGatewayResponse");
> > -                GenericValue response = delegator.makeValue("PaymentGatewayResponse",
> null);
> > -                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", refundResponse.get
> ("refundAmount"));
> > -                response.set("referenceNum", refundResponse.get
> ("refundRefNum"));
> > -                response.set("altReference", refundResponse.get
> ("refundAltRefNum"));
> > -                response.set("gatewayCode", refundResponse.get
> ("refundCode"));
> > -                response.set("gatewayFlag", refundResponse.get
> ("refundFlag"));
> > -                response.set("gatewayMessage", refundResponse.get
> ("refundMessage"));
> > -                response.set("transactionDate",
> UtilDateTime.nowTimestamp());
> > +                // process the refund result
> > +                Map refundResRes;
> >                  try {
> > -                    delegator.create(response);
> > -                } catch (GenericEntityException e) {
> > +                    ModelService model = dctx.getModelService
> ("processRefundResult");
> > +                    Map refundResCtx = model.makeValid(context,
> ModelService.IN_PARAM);
> > +                    refundResCtx.put("currencyUomId", orh.getCurrency
> ());
> > +                    refundResCtx.put("payToPartyId", payToPartyId);
> > +                    refundResCtx.put("payFromPartyId", payFromPartyId);
> > +                    refundResRes = dispatcher.runSync(model.name,
> refundResCtx);
> > +                } catch (GenericServiceException e) {
> >                      Debug.logError(e, module);
> > -                    return ServiceUtil.returnError("Unable to create
> PaymentGatewayResponse record");
> > +                    return ServiceUtil.returnError("Problem processing
> refund result: " + e.getMessage());
> >                  }
> >
> > -                // create the internal messages
> > -                List messages = (List) refundResponse.get
> ("internalRespMsgs");
> > -                if (messages != null && messages.size() > 0) {
> > -                    Iterator i = messages.iterator();
> > -                    while (i.hasNext()) {
> > -                        GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg",
> null);
> > -                        String respMsgId = delegator.getNextSeqId
> ("PaymentGatewayRespMsg");
> > -                        String message = (String) i.next();
> > -                        respMsg.set("paymentGatewayRespMsgId",
> respMsgId);
> > -                        respMsg.set("paymentGatewayResponseId",
> responseId);
> > -                        respMsg.set("pgrMessage", message);
> > -                        try {
> > -                            delegator.create(respMsg);
> > -                        } catch (GenericEntityException e) {
> > -                            Debug.logError(e, module);
> > -                            return ServiceUtil.returnError("Unable to
> create PaymentGatewayRespMsg record");
> > -                        }
> > -                    }
> > -                }
> > +                return refundResRes;
> > +            } else {
> > +                return ServiceUtil.returnError("No refund service
> defined");
> > +            }
> > +        } else {
> > +            return ServiceUtil.returnError("No payment settings
> found");
> > +        }
> > +    }
> >
> > -                // handle the (reverse) payment
> > -                Boolean refundResult = (Boolean) refundResponse.get
> ("refundResult");
> > -                if (refundResult != null && refundResult.booleanValue())
> {
> > -                    // create a payment record
> > -                    Map paymentCtx = UtilMisc.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", orh.getCurrency());
> > -                    paymentCtx.put("amount", refundResponse.get
> ("refundAmount"));
> > -                    paymentCtx.put("userLogin", userLogin);
> > -                    paymentCtx.put("paymentRefNum", refundResponse.get
> ("refundRefNum"));
> > -                    paymentCtx.put("comments", "Refund");
> > +    public static Map processRefundResult(DispatchContext dctx, Map
> context) {
> > +        LocalDispatcher dispatcher = dctx.getDispatcher();
> > +        GenericDelegator delegator = dctx.getDelegator();
> >
> > -                    String paymentId = null;
> > -                    try {
> > -                        Map 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("Problem
> creating Payment");
> > -                    }
> > -                    //Debug.log("Payment created : " + paymentId,
> module);
> > +        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");
> >
> > -                    if (paymentId == null) {
> > -                        return ServiceUtil.returnError("Create payment
> failed");
> > -                    }
> > +        // create the PaymentGatewayResponse record
> > +        String responseId = delegator.getNextSeqId
> ("PaymentGatewayResponse");
> > +        GenericValue response = delegator.makeValue("PaymentGatewayResponse",
> null);
> > +        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("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 messages = (List) context.get("internalRespMsgs");
> > +        if (messages != null && messages.size() > 0) {
> > +            Iterator i = messages.iterator();
> > +            while (i.hasNext()) {
> > +                GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg",
> null);
> > +                String respMsgId = delegator.getNextSeqId
> ("PaymentGatewayRespMsg");
> > +                String message = (String) i.next();
> > +                respMsg.set("paymentGatewayRespMsgId", respMsgId);
> > +                respMsg.set("paymentGatewayResponseId", responseId);
> > +                respMsg.set("pgrMessage", message);
> >
> > -                    Map result = ServiceUtil.returnSuccess();
> > -                    result.put("paymentId", paymentId);
> > -                    return result;
> > +                // save the message
> > +                savePgr(dctx, respMsg);
> > +            }
> > +        }
> > +
> > +        // handle the (reverse) payment
> > +        Boolean refundResult = (Boolean) context.get("refundResult");
> > +        if (refundResult != null && refundResult.booleanValue()) {
> > +            // create a payment record
> > +            Map paymentCtx = UtilMisc.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 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 {
> > -                    return ServiceUtil.returnFailure("The refund
> failed");
> > +                    paymentId = (String) payRes.get("paymentId");
> >                  }
> > -            } else {
> > -                return ServiceUtil.returnError("No refund service
> defined");
> > +            } catch (GenericServiceException e) {
> > +                Debug.logError(e, "Problem creating Payment", module);
> > +                return ServiceUtil.returnError("Problem creating
> Payment");
> >              }
> > +            //Debug.log("Payment created : " + paymentId, module);
> > +
> > +            if (paymentId == null) {
> > +                return ServiceUtil.returnError("Create payment
> failed");
> > +            }
> > +
> > +            Map result = ServiceUtil.returnSuccess();
> > +            result.put("paymentId", paymentId);
> > +            return result;
> >          } else {
> > -            return ServiceUtil.returnError("No payment settings
> found");
> > +            return ServiceUtil.returnFailure("The refund failed");
> >          }
> >      }
> >
> > -
> >      public static Map retryFailedOrderAuth(DispatchContext dctx, Map
> context) {
> >          GenericDelegator delegator = dctx.getDelegator();
> >          LocalDispatcher dispatcher = dctx.getDispatcher();
> > @@ -2393,6 +2488,33 @@
> >          }
> >
> >          return true;
> > +    }
> > +
> > +    // safe payment gateway store
> > +    private static void savePgr(DispatchContext dctx, GenericValue pgr)
> {
> > +        Map context = UtilMisc.toMap("paymentGatewayResponse", pgr);
> > +        LocalDispatcher dispatcher = dctx.getDispatcher();
> > +        GenericDelegator delegator = dctx.getDelegator();
> > +
> > +        try {
> > +            dispatcher.addRollbackService("savePaymentGatewayResponse",
> context, true);
> > +            delegator.create(pgr);
> > +        } catch (Exception e) {
> > +            Debug.logError(e, module);
> > +        }
> > +    }
> > +
> > +    public static Map savePaymentGatewayResponse(DispatchContext dctx,
> Map context) {
> > +        GenericDelegator delegator = dctx.getDelegator();
> > +        GenericValue pgr = (GenericValue) context.get
> ("paymentGatewayResponse");
> > +
> > +        try {
> > +            delegator.create(pgr);
> > +        } catch (GenericEntityException e) {
> > +            Debug.logError(e, module);
> > +        }
> > +
> > +        return ServiceUtil.returnSuccess();
> >      }
> >
> >      // manual processing service
> >
>
>
>