KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > accounting > payment > PaymentGatewayServices


1 /*
2  * $Id: PaymentGatewayServices.java 7233 2006-04-07 14:26:24Z sichen $
3  *
4  * Copyright (c) 2001-2005 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */

24 package org.ofbiz.accounting.payment;
25
26 import java.text.DecimalFormat JavaDoc;
27 import java.text.ParseException JavaDoc;
28 import java.util.ArrayList JavaDoc;
29 import java.util.Collection JavaDoc;
30 import java.util.Date JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.Calendar JavaDoc;
36 import java.util.Set JavaDoc;
37 import java.math.BigDecimal JavaDoc;
38 import java.sql.Timestamp JavaDoc;
39
40 import org.ofbiz.accounting.invoice.InvoiceWorker;
41 import org.ofbiz.base.util.Debug;
42 import org.ofbiz.base.util.GeneralException;
43 import org.ofbiz.base.util.UtilDateTime;
44 import org.ofbiz.base.util.UtilMisc;
45 import org.ofbiz.base.util.UtilNumber;
46 import org.ofbiz.base.util.UtilProperties;
47 import org.ofbiz.base.util.UtilValidate;
48 import org.ofbiz.entity.GenericDelegator;
49 import org.ofbiz.entity.GenericEntityException;
50 import org.ofbiz.entity.GenericValue;
51 import org.ofbiz.entity.condition.EntityCondition;
52 import org.ofbiz.entity.condition.EntityConditionList;
53 import org.ofbiz.entity.condition.EntityExpr;
54 import org.ofbiz.entity.condition.EntityJoinOperator;
55 import org.ofbiz.entity.condition.EntityOperator;
56 import org.ofbiz.entity.util.EntityListIterator;
57 import org.ofbiz.entity.util.EntityUtil;
58 import org.ofbiz.order.order.OrderChangeHelper;
59 import org.ofbiz.order.order.OrderReadHelper;
60 import org.ofbiz.party.contact.ContactHelper;
61 import org.ofbiz.product.store.ProductStoreWorker;
62 import org.ofbiz.security.Security;
63 import org.ofbiz.service.DispatchContext;
64 import org.ofbiz.service.GenericServiceException;
65 import org.ofbiz.service.LocalDispatcher;
66 import org.ofbiz.service.ModelService;
67 import org.ofbiz.service.ServiceUtil;
68
69 /**
70  * PaymentGatewayServices
71  *
72  * @author <a HREF="mailto:jaz@ofbiz.org">Andy Zeneski</a>
73  * @version $Rev: 7233 $
74  * @since 2.0
75  */

76 public class PaymentGatewayServices {
77
78     public static final String JavaDoc module = PaymentGatewayServices.class.getName();
79     public static final String JavaDoc AUTH_SERVICE_TYPE = "PRDS_PAY_AUTH";
80     public static final String JavaDoc REAUTH_SERVICE_TYPE = "PRDS_PAY_REAUTH";
81     public static final String JavaDoc RELEASE_SERVICE_TYPE = "PRDS_PAY_RELEASE";
82     public static final String JavaDoc CAPTURE_SERVICE_TYPE = "PRDS_PAY_CAPTURE";
83     public static final String JavaDoc REFUND_SERVICE_TYPE = "PRDS_PAY_REFUND";
84     public static final String JavaDoc CREDIT_SERVICE_TYPE = "PRDS_PAY_CREDIT";
85     private static final int TX_TIME = 300;
86     private static BigDecimal JavaDoc ZERO = new BigDecimal JavaDoc("0");
87     private static int decimals = -1;
88     private static int rounding = -1;
89     static {
90         decimals = UtilNumber.getBigDecimalScale("order.decimals");
91         rounding = UtilNumber.getBigDecimalRoundingMode("order.rounding");
92
93         // set zero to the proper scale
94
if (decimals != -1) ZERO.setScale(decimals);
95     }
96     
97     /**
98      * Helper method to parse total remaining balance in an order from order read helper.
99      */

100     private static double getTotalRemaining(OrderReadHelper orh) throws ParseException JavaDoc, NumberFormatException JavaDoc {
101         String JavaDoc currencyFormat = UtilProperties.getPropertyValue("general.properties", "currency.decimal.format", "##0.00");
102         DecimalFormat JavaDoc formatter = new DecimalFormat JavaDoc(currencyFormat);
103         String JavaDoc grandTotalString = formatter.format(orh.getOrderGrandTotal());
104         Double JavaDoc grandTotal = new Double JavaDoc(formatter.parse(grandTotalString).doubleValue());
105         return grandTotal.doubleValue();
106     }
107
108     /**
109      * Authorizes a single order preference with an option to specify an amount. The result map has the Booleans
110      * "errors" and "finished" which notify the user if there were any errors and if the authorizatoin was finished.
111      * There is also a List "messages" for the authorization response messages and a Double, "processAmount" as the
112      * amount processed. TODO: it might be nice to return the paymentGatewayResponseId
113      */

114     public static Map JavaDoc authOrderPaymentPreference(DispatchContext dctx, Map JavaDoc context) {
115         GenericDelegator delegator = dctx.getDelegator();
116         LocalDispatcher dispatcher = dctx.getDispatcher();
117         GenericValue userLogin = (GenericValue) context.get("userLogin");
118
119         String JavaDoc orderPaymentPreferenceId = (String JavaDoc) context.get("orderPaymentPreferenceId");
120         Double JavaDoc overrideAmount = (Double JavaDoc) context.get("overrideAmount");
121
122         // validate overrideAmount if its available
123
if (overrideAmount != null) {
124             if (overrideAmount.doubleValue() < 0) return ServiceUtil.returnError("Amount entered (" + overrideAmount + ") is negative.");
125             if (overrideAmount.doubleValue() == 0) return ServiceUtil.returnError("Amount entered (" + overrideAmount + ") is zero.");
126         }
127
128         GenericValue orderHeader = null;
129         GenericValue orderPaymentPreference = null;
130         try {
131             orderPaymentPreference = delegator.findByPrimaryKey("OrderPaymentPreference", UtilMisc.toMap("orderPaymentPreferenceId", orderPaymentPreferenceId));
132             orderHeader = orderPaymentPreference.getRelatedOne("OrderHeader");
133         } catch (GenericEntityException e) {
134             Debug.logError(e, module);
135             return ServiceUtil.returnError("Problems getting required information: orderPaymentPreference [" + orderPaymentPreferenceId + "]");
136         }
137         OrderReadHelper orh = new OrderReadHelper(orderHeader);
138
139         // get the total remaining
140
double totalRemaining = 0.0;
141         try {
142             totalRemaining = getTotalRemaining(orh);
143         } catch (Exception JavaDoc e) {
144             Debug.logError(e, "Problem getting parsed grand total amount", module);
145             return ServiceUtil.returnError("ERROR: Cannot parse grand total from formatted string; see logs");
146         }
147
148         // get the process attempts so far
149
Long JavaDoc procAttempt = orderPaymentPreference.getLong("processAttempt");
150         if (procAttempt == null) {
151             procAttempt = new Long JavaDoc(0);
152         }
153
154         // update the process attempt count
155
orderPaymentPreference.set("processAttempt", new Long JavaDoc(procAttempt.longValue() + 1));
156         try {
157             orderPaymentPreference.store();
158         } catch (GenericEntityException e) {
159             Debug.logError(e, module);
160             return ServiceUtil.returnError("Unable to update OrderPaymentPreference record!");
161         }
162
163         // if we are already authorized, then this is a re-auth request
164
boolean reAuth = false;
165         if (orderPaymentPreference.get("statusId") != null && "PAYMENT_AUTHORIZED".equals(orderPaymentPreference.getString("statusId"))) {
166             reAuth = true;
167         }
168
169         // use overrideAmount or maxAmount
170
Double JavaDoc transAmount = null;
171         if (overrideAmount != null) {
172             transAmount = overrideAmount;
173         } else {
174             transAmount = orderPaymentPreference.getDouble("maxAmount");
175         }
176
177         // prepare the return map (always return success, default finished=false, default errors=false
178
Map JavaDoc results = UtilMisc.toMap(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS, "finished", new Boolean JavaDoc(false), "errors", new Boolean JavaDoc(false));
179
180         // if our transaction amount exists and is zero, there's nothing to process, so return
181
if ((transAmount != null) && (transAmount.doubleValue() <= 0)) {
182             return results;
183         }
184
185         // call the authPayment method
186
Map JavaDoc processorResult = authPayment(dispatcher, userLogin, orh, orderPaymentPreference, totalRemaining, reAuth, overrideAmount);
187
188         // handle the response
189
if (processorResult != null) {
190
191             // get the customer messages
192
if (processorResult.get("customerRespMsgs") != null) {
193                 results.put("messages", processorResult.get("customerRespMsgs"));
194             }
195
196             // not null result means either an approval or decline; null would mean error
197
Double JavaDoc thisAmount = (Double JavaDoc) processorResult.get("processAmount");
198
199             // process the auth results
200
boolean processResult = false;
201             try {
202                 processResult = processResult(dctx, processorResult, userLogin, orderPaymentPreference);
203                 if (processResult) {
204                     results.put("processAmount", thisAmount);
205                     results.put("finished", new Boolean JavaDoc(true));
206                 }
207             } catch (GeneralException e) {
208                 Debug.logError(e, "Trouble processing the result; processorResult: " + processorResult, module);
209                 results.put("errors", new Boolean JavaDoc(true));
210             }
211         } else {
212             // error with payment processor; will try later
213
Debug.logInfo("Invalid OrderPaymentPreference; maxAmount is 0", module);
214             orderPaymentPreference.set("statusId", "PAYMENT_CANCELLED");
215             try {
216                 orderPaymentPreference.store();
217             } catch (GenericEntityException e) {
218                 Debug.logError(e, "ERROR: Problem setting OrderPaymentPreference status to CANCELLED", module);
219             }
220             results.put("errors", new Boolean JavaDoc(true));
221         }
222         return results;
223     }
224
225     /**
226      * Processes payments through service calls to the defined processing service for the ProductStore/PaymentMethodType
227      * @return APPROVED|FAILED|ERROR for complete processing of ALL payment methods.
228      */

229     public static Map JavaDoc authOrderPayments(DispatchContext dctx, Map JavaDoc context) {
230         GenericDelegator delegator = dctx.getDelegator();
231         LocalDispatcher dispatcher = dctx.getDispatcher();
232         String JavaDoc orderId = (String JavaDoc) context.get("orderId");
233         Map JavaDoc result = new HashMap JavaDoc();
234
235         // get the order header and payment preferences
236
GenericValue orderHeader = null;
237         List JavaDoc paymentPrefs = null;
238
239         try {
240             // get the OrderHeader
241
orderHeader = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap("orderId", orderId));
242
243             // get the payments to auth
244
Map JavaDoc lookupMap = UtilMisc.toMap("orderId", orderId, "statusId", "PAYMENT_NOT_AUTH");
245             List JavaDoc orderList = UtilMisc.toList("maxAmount");
246             paymentPrefs = delegator.findByAnd("OrderPaymentPreference", lookupMap, orderList);
247         } catch (GenericEntityException gee) {
248             Debug.logError(gee, "Problems getting the order information", module);
249             result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_ERROR);
250             result.put(ModelService.ERROR_MESSAGE, "ERROR: Could not get order information (" + gee.getMessage() + ").");
251             return result;
252         }
253
254         // make sure we have a OrderHeader
255
if (orderHeader == null) {
256             return ServiceUtil.returnError("Could not find OrderHeader with orderId: " + orderId + "; not processing payments.");
257         }
258
259         // get the order amounts
260
OrderReadHelper orh = new OrderReadHelper(orderHeader);
261         double totalRemaining = 0.0;
262         try {
263             totalRemaining = getTotalRemaining(orh);
264         } catch (Exception JavaDoc e) {
265             Debug.logError(e, "Problem getting parsed grand total amount", module);
266             return ServiceUtil.returnError("ERROR: Cannot parse grand total from formatted string; see logs");
267         }
268
269         // loop through and auth each order payment preference
270
int finished = 0;
271         int hadError = 0;
272         List JavaDoc messages = new ArrayList JavaDoc();
273         Iterator JavaDoc payments = paymentPrefs.iterator();
274         while (payments.hasNext()) {
275             GenericValue paymentPref = (GenericValue) payments.next();
276
277             Map JavaDoc authContext = new HashMap JavaDoc();
278             authContext.put("orderPaymentPreferenceId", paymentPref.getString("orderPaymentPreferenceId"));
279             authContext.put("userLogin", context.get("userLogin"));
280
281             Map JavaDoc results = null;
282             try {
283                 results = dispatcher.runSync("authOrderPaymentPreference", authContext);
284             } catch (GenericServiceException se) {
285                 Debug.logError(se, "Error in calling authOrderPaymentPreference from authOrderPayments: " + se.getMessage(), module);
286                 hadError += 1;
287                 messages.add("Could not authorize OrderPaymentPreference [" + paymentPref.getString("orderPaymentPreferenceId") + "] for order [" + orderId + "]: "
288                     + se.getMessage());
289                 continue;
290             }
291
292             if (ServiceUtil.isError(results)) {
293                 hadError += 1;
294                 messages.add("Could not authorize OrderPaymentPreference [" + paymentPref.getString("orderPaymentPreferenceId") + "] for order [" + orderId + "]: "
295                     + results.get(ModelService.ERROR_MESSAGE));
296                 continue;
297             }
298
299             if (((Boolean JavaDoc)results.get("finished")).booleanValue()) finished += 1;
300             if (((Boolean JavaDoc)results.get("errors")).booleanValue()) hadError += 1;
301             if (results.get("messages") != null) messages.addAll((List JavaDoc) results.get("messages"));
302             if (results.get("processAmount") != null) totalRemaining -= ((Double JavaDoc) results.get("processAmount")).doubleValue();
303         }
304
305         Debug.logInfo("Finished with auth(s) checking results", module);
306
307         // add messages to the result
308
result.put("authResultMsgs", messages);
309
310         if (hadError > 0) {
311             Debug.logError("Error(s) (" + hadError + ") during auth; returning ERROR", module);
312             result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
313             result.put("processResult", "ERROR");
314             return result;
315         } else if (finished == paymentPrefs.size()) {
316             Debug.logInfo("All auth(s) passed total remaining : " + totalRemaining, module);
317             result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
318             result.put("processResult", "APPROVED");
319             return result;
320         } else {
321             Debug.logInfo("Only (" + finished + ") passed auth; returning FAILED", module);
322             result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
323             result.put("processResult", "FAILED");
324             return result;
325         }
326     }
327
328
329     private static Map JavaDoc authPayment(LocalDispatcher dispatcher, GenericValue userLogin, OrderReadHelper orh, GenericValue paymentPref, double totalRemaining, boolean reauth) {
330         return authPayment(dispatcher, userLogin, orh, paymentPref, totalRemaining, reauth, null);
331     }
332
333     private static Map JavaDoc authPayment(LocalDispatcher dispatcher, GenericValue userLogin, OrderReadHelper orh, GenericValue paymentPref, double totalRemaining, boolean reauth, Double JavaDoc overrideAmount) {
334         String JavaDoc paymentConfig = null;
335         String JavaDoc serviceName = null;
336
337         // get the payment settings i.e. serviceName and config properties file name
338
String JavaDoc serviceType = AUTH_SERVICE_TYPE;
339         if (reauth) {
340             serviceType = REAUTH_SERVICE_TYPE;
341         }
342
343         GenericValue paymentSettings = getPaymentSettings(orh.getOrderHeader(), paymentPref, serviceType, false);
344         if (paymentSettings != null) {
345             serviceName = paymentSettings.getString("paymentService");
346             paymentConfig = paymentSettings.getString("paymentPropertiesPath");
347         } else {
348             Debug.logError("Invalid payment settings entity, no payment settings found", module);
349             return null;
350         }
351
352         // make sure the service name is not null
353
if (serviceName == null) {
354             Debug.logError("Invalid payment processor: + " + paymentSettings, module);
355             return null;
356         }
357
358         // get the process context
359
Map JavaDoc processContext = null;
360         try {
361             processContext = makeAuthContext(orh, userLogin, paymentPref, paymentConfig, totalRemaining, overrideAmount);
362         } catch (GeneralException e) {
363             Debug.logError(e, "Problems creating the context for the auth service", module);
364             return null;
365         }
366
367         // invoke the processor.
368
Map JavaDoc processorResult = null;
369         try {
370             // invoke the payment processor; allow 5 minute transaction timeout and require a new tx; we'll capture the error and pass back nicely.
371
processorResult = dispatcher.runSync(serviceName, processContext, TX_TIME, true);
372         } catch (GenericServiceException gse) {
373             Debug.logError("Error occurred on: " + serviceName + " => " + processContext, module);
374             Debug.logError(gse, "Problems invoking payment processor! Will retry later." + "(" + orh.getOrderId() + ")", module);
375             return null;
376         }
377
378         if (processorResult != null) {
379             // check for errors from the processor implementation
380
String JavaDoc resultResponseCode = (String JavaDoc) processorResult.get(ModelService.RESPONSE_MESSAGE);
381             if (resultResponseCode != null && resultResponseCode.equals(ModelService.RESPOND_ERROR)) {
382                 Debug.logError("Processor failed; will retry later : " + processorResult.get(ModelService.ERROR_MESSAGE), module);
383                 // log the error message as a gateway response when it fails
384
saveError(dispatcher, userLogin, paymentPref, processorResult, "PRDS_PAY_AUTH", "PGT_AUTHORIZE");
385                 return null;
386             }
387
388             // pass the payTo partyId to the result processor; we just add it to the result context.
389
String JavaDoc payToPartyId = getPayToPartyId(orh.getOrderHeader());
390             processorResult.put("payToPartyId", payToPartyId);
391
392             // add paymentSettings to result; for use by later processors
393
processorResult.put("paymentSettings", paymentSettings);
394
395             // and pass on the currencyUomId
396
processorResult.put("currencyUomId", orh.getCurrency());
397         }
398
399         return processorResult;
400     }
401
402     private static GenericValue getPaymentSettings(GenericValue orderHeader, GenericValue paymentPreference, String JavaDoc paymentServiceType, boolean anyServiceType) {
403         GenericDelegator delegator = orderHeader.getDelegator();
404         GenericValue paymentSettings = null;
405         GenericValue paymentMethod = null;
406         try {
407             paymentMethod = paymentPreference.getRelatedOne("PaymentMethod");
408         } catch (GenericEntityException e) {
409             Debug.logError(e, "Problem getting PaymentMethod from OrderPaymentPreference", module);
410         }
411         if (paymentMethod != null) {
412             String JavaDoc productStoreId = orderHeader.getString("productStoreId");
413             String JavaDoc paymentMethodTypeId = paymentMethod.getString("paymentMethodTypeId");
414             if (productStoreId != null && paymentMethodTypeId != null) {
415                 paymentSettings = ProductStoreWorker.getProductStorePaymentSetting(delegator, productStoreId, paymentMethodTypeId, paymentServiceType, anyServiceType);
416             }
417         }
418         return paymentSettings;
419     }
420
421     private static String JavaDoc getPayToPartyId(GenericValue orderHeader) {
422         String JavaDoc payToPartyId = "Company"; // default value
423
GenericValue productStore = null;
424         try {
425             productStore = orderHeader.getRelatedOne("ProductStore");
426         } catch (GenericEntityException e) {
427             Debug.logError(e, "Unable to get ProductStore from OrderHeader", module);
428             return null;
429         }
430         if (productStore != null && productStore.get("payToPartyId") != null) {
431             payToPartyId = productStore.getString("payToPartyId");
432         } else {
433             Debug.logWarning("Using default value of [Company] for payToPartyId on order [" + orderHeader.getString("orderId") + "]", module);
434         }
435         return payToPartyId;
436     }
437
438     private static Map JavaDoc makeAuthContext(OrderReadHelper orh, GenericValue userLogin, GenericValue paymentPreference, String JavaDoc paymentConfig, double totalRemaining, Double JavaDoc overrideAmount) throws GeneralException {
439         Map JavaDoc processContext = new HashMap JavaDoc();
440
441         // get the visit record to obtain the client's IP address
442
GenericValue orderHeader = orh.getOrderHeader();
443         if (orderHeader != null) {
444             String JavaDoc visitId = orderHeader.getString("visitId");
445             GenericValue visit = null;
446             if (visitId != null) {
447                 try {
448                     visit = orderHeader.getDelegator().findByPrimaryKey("Visit", UtilMisc.toMap("visitId", visitId));
449                 } catch (GenericEntityException e) {
450                     Debug.logError(e, module);
451                 }
452             }
453
454             if (visit != null && visit.get("clientIpAddress") != null) {
455                 processContext.put("customerIpAddress", visit.getString("clientIpAddress"));
456             }
457         }
458
459         processContext.put("userLogin", userLogin);
460         processContext.put("orderId", orh.getOrderId());
461         processContext.put("orderItems", orh.getOrderItems());
462         processContext.put("shippingAddress", EntityUtil.getFirst(orh.getShippingLocations())); // TODO refactor the payment API to handle support all addresses
463
processContext.put("paymentConfig", paymentConfig);
464         processContext.put("currency", orh.getCurrency());
465         processContext.put("orderPaymentPreference", paymentPreference);
466         if (paymentPreference.get("securityCode") != null) {
467             processContext.put("cardSecurityCode", paymentPreference.get("securityCode"));
468         }
469
470         // get the billing information
471
getBillingInformation(orh, paymentPreference, processContext);
472
473         // default charge is totalRemaining
474
double thisAmount = totalRemaining;
475
476         // use override or max amount available
477
if (overrideAmount != null) {
478             thisAmount = overrideAmount.doubleValue();
479         } else if (paymentPreference.get("maxAmount") != null) {
480             thisAmount = paymentPreference.getDouble("maxAmount").doubleValue();
481         }
482
483         // don't authorized more then what is required
484
if (thisAmount > totalRemaining) {
485             thisAmount = totalRemaining;
486         }
487
488         // format the decimal
489
String JavaDoc currencyFormat = UtilProperties.getPropertyValue("general.properties", "currency.decimal.format", "##0.00");
490         DecimalFormat JavaDoc formatter = new DecimalFormat JavaDoc(currencyFormat);
491         String JavaDoc amountString = formatter.format(thisAmount);
492         Double JavaDoc processAmount = null;
493         try {
494             processAmount = new Double JavaDoc(formatter.parse(amountString).doubleValue());
495         } catch (ParseException JavaDoc e) {
496             Debug.logError(e, "Problems parsing string formatted double to Double", module);
497             throw new GeneralException("ParseException in number format", e);
498         }
499
500         if (Debug.verboseOn())
501             Debug.logVerbose("Charging amount: " + processAmount, module);
502         processContext.put("processAmount", processAmount);
503
504         return processContext;
505     }
506
507     private static String JavaDoc getBillingInformation(OrderReadHelper orh, GenericValue paymentPreference, Map JavaDoc toContext) throws GenericEntityException {
508         // gather the payment related objects.
509
GenericValue paymentMethod = paymentPreference.getRelatedOne("PaymentMethod");
510         if (paymentMethod != null && paymentMethod.getString("paymentMethodTypeId").equals("CREDIT_CARD")) {
511             // type credit card
512
GenericValue creditCard = paymentMethod.getRelatedOne("CreditCard");
513             GenericValue billingAddress = creditCard.getRelatedOne("PostalAddress");
514             toContext.put("creditCard", creditCard);
515             toContext.put("billingAddress", billingAddress);
516         } else if (paymentMethod != null && paymentMethod.getString("paymentMethodTypeId").equals("EFT_ACCOUNT")) {
517             // type eft
518
GenericValue eftAccount = paymentMethod.getRelatedOne("EftAccount");
519             GenericValue billingAddress = eftAccount.getRelatedOne("PostalAddress");
520             toContext.put("eftAccount", eftAccount);
521             toContext.put("billingAddress", billingAddress);
522         } else if (paymentMethod != null && paymentMethod.getString("paymentMethodTypeId").equals("GIFT_CARD")) {
523             // type gift card
524
GenericValue giftCard = paymentMethod.getRelatedOne("GiftCard");
525             toContext.put("giftCard", giftCard);
526         } else {
527             // add other payment types here; i.e. gift cards, etc.
528
// unknown payment type; ignoring.
529
Debug.logError("ERROR: Unsupported PaymentMethodType passed for authorization", module);
530             return null;
531         }
532
533         // get some contact info.
534
GenericValue billToPersonOrGroup = orh.getBillToParty();
535         GenericValue billToEmail = null;
536
537         Collection JavaDoc emails = ContactHelper.getContactMech(billToPersonOrGroup.getRelatedOne("Party"), "PRIMARY_EMAIL", "EMAIL_ADDRESS", false);
538
539         if (UtilValidate.isNotEmpty(emails)) {
540             billToEmail = (GenericValue) emails.iterator().next();
541         }
542
543         toContext.put("billToParty", billToPersonOrGroup);
544         toContext.put("billToEmail", billToEmail);
545
546         return billToPersonOrGroup.getString("partyId");
547     }
548
549     /**
550      *
551      * Releases authorizations through service calls to the defined processing service for the ProductStore/PaymentMethodType
552      * @return COMPLETE|FAILED|ERROR for complete processing of ALL payments.
553      */

554     public static Map JavaDoc releaseOrderPayments(DispatchContext dctx, Map JavaDoc context) {
555         GenericDelegator delegator = dctx.getDelegator();
556         LocalDispatcher dispatcher = dctx.getDispatcher();
557         GenericValue userLogin = (GenericValue) context.get("userLogin");
558         String JavaDoc orderId = (String JavaDoc) context.get("orderId");
559
560         Map JavaDoc result = new HashMap JavaDoc();
561
562         // get the payment preferences
563
List JavaDoc paymentPrefs = null;
564
565         try {
566             // get the valid payment prefs
567
List JavaDoc othExpr = UtilMisc.toList(new EntityExpr("paymentMethodTypeId", EntityOperator.EQUALS, "EFT_ACCOUNT"));
568             othExpr.add(new EntityExpr("paymentMethodTypeId", EntityOperator.EQUALS, "CREDIT_CARD"));
569             othExpr.add(new EntityExpr("paymentMethodTypeId", EntityOperator.EQUALS, "GIFT_CARD"));
570             EntityCondition con1 = new EntityConditionList(othExpr, EntityJoinOperator.OR);
571
572             EntityCondition statExpr = new EntityExpr("statusId", EntityOperator.EQUALS, "PAYMENT_SETTLED");
573             EntityCondition con2 = new EntityConditionList(UtilMisc.toList(con1, statExpr), EntityOperator.AND);
574
575             EntityCondition authExpr = new EntityExpr("statusId", EntityOperator.EQUALS, "PAYMENT_AUTHORIZED");
576             EntityCondition con3 = new EntityConditionList(UtilMisc.toList(con2, authExpr), EntityOperator.OR);
577
578             EntityExpr orderExpr = new EntityExpr("orderId", EntityOperator.EQUALS, orderId);
579             EntityCondition con4 = new EntityConditionList(UtilMisc.toList(con3, orderExpr), EntityOperator.AND);
580
581             paymentPrefs = delegator.findByCondition("OrderPaymentPreference", con4, null, null);
582         } catch (GenericEntityException gee) {
583             Debug.logError(gee, "Problems getting entity record(s), see stack trace", module);
584             result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_ERROR);
585             result.put(ModelService.ERROR_MESSAGE, "ERROR: Could not get order information (" + gee.toString() + ").");
586             return result;
587         }
588
589         // return complete if no payment prefs were found
590
if (paymentPrefs == null || paymentPrefs.size() == 0) {
591             Debug.logWarning("No OrderPaymentPreference records available for release", module);
592             result.put("processResult", "COMPLETE");
593             result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
594             return result;
595         }
596
597         // iterate over the prefs and release each one
598
List JavaDoc finished = new ArrayList JavaDoc();
599         Iterator JavaDoc payments = paymentPrefs.iterator();
600         while (payments.hasNext()) {
601             GenericValue paymentPref = (GenericValue) payments.next();
602             Map JavaDoc releaseContext = UtilMisc.toMap("userLogin", userLogin, "orderPaymentPreferenceId", paymentPref.getString("orderPaymentPreferenceId"));
603             Map JavaDoc releaseResult = null;
604             try {
605                 releaseResult = dispatcher.runSync("releaseOrderPaymentPreference", releaseContext);
606             } catch( GenericServiceException e ) {
607                 String JavaDoc errMsg = "Problem calling releaseOrderPaymentPreference service for orderPaymentPreferenceId" + paymentPref.getString("orderPaymentPreferenceId");
608                 Debug.logError(e, errMsg, module);
609                 return ServiceUtil.returnError(errMsg);
610             }
611             if (ServiceUtil.isError(releaseResult)) {
612                 Debug.logError(ServiceUtil.getErrorMessage(releaseResult), module);
613                 return ServiceUtil.returnError(ServiceUtil.getErrorMessage(releaseResult));
614             } else if (! ServiceUtil.isFailure(releaseResult)) {
615                 finished.add(paymentPref);
616             }
617         }
618         result = ServiceUtil.returnSuccess();
619         if (finished.size() == paymentPrefs.size()) {
620             result.put("processResult", "COMPLETE");
621         } else {
622             result.put("processResult", "FAILED");
623         }
624
625         return result;
626     }
627
628     /**
629      *
630      * Releases authorization for a single OrderPaymentPreference through service calls to the defined processing service for the ProductStore/PaymentMethodType
631      * @return SUCCESS|FAILED|ERROR for complete processing of payment.
632      */

633     public static Map JavaDoc releaseOrderPaymentPreference(DispatchContext dctx, Map JavaDoc context) {
634         GenericDelegator delegator = dctx.getDelegator();
635         LocalDispatcher dispatcher = dctx.getDispatcher();
636         GenericValue userLogin = (GenericValue) context.get("userLogin");
637         String JavaDoc orderPaymentPreferenceId = (String JavaDoc) context.get("orderPaymentPreferenceId");
638
639         Map JavaDoc result = ServiceUtil.returnSuccess();
640
641         // Get the OrderPaymentPreference
642
GenericValue paymentPref = null;
643         try {
644             paymentPref = delegator.findByPrimaryKey("OrderPaymentPreference", UtilMisc.toMap("orderPaymentPreferenceId", orderPaymentPreferenceId));
645         } catch( GenericEntityException e ) {
646             String JavaDoc errMsg = "Problem getting OrderPaymentPreference for orderPaymentPreferenceId " + orderPaymentPreferenceId;
647             Debug.logWarning(e, errMsg, module);
648             return ServiceUtil.returnError(errMsg);
649         }
650
651         // Error if no OrderPaymentPreference was found
652
if (paymentPref == null) {
653             String JavaDoc errMsg = "Could not find OrderPaymentPreference with orderPaymentPreferenceId: " + orderPaymentPreferenceId;
654             Debug.logWarning(errMsg, module);
655             return ServiceUtil.returnError(errMsg);
656         }
657
658         // Get the OrderHeader
659
GenericValue orderHeader = null;
660         try {
661             orderHeader = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap("orderId", paymentPref.getString("orderId")));
662         } catch( GenericEntityException e ) {
663             String JavaDoc errMsg = "Problem getting OrderHeader for orderId " + paymentPref.getString("orderId");
664             Debug.logWarning(e, errMsg, module);
665             return ServiceUtil.returnError(errMsg);
666         }
667
668         // Error if no OrderHeader was found
669
if (orderHeader == null) {
670             String JavaDoc errMsg = "Could not find OrderHeader with orderId: " + paymentPref.getString("orderId") + "; not processing payments.";
671             Debug.logWarning(errMsg, module);
672             return ServiceUtil.returnError(errMsg);
673         }
674
675         OrderReadHelper orh = new OrderReadHelper(orderHeader);
676         String JavaDoc currency = orh.getCurrency();
677
678         // look up the payment configuration settings
679
String JavaDoc serviceName = null;
680         String JavaDoc paymentConfig = null;
681
682         // get the payment settings i.e. serviceName and config properties file name
683
GenericValue paymentSettings = getPaymentSettings(orderHeader, paymentPref, RELEASE_SERVICE_TYPE, false);
684         if (paymentSettings != null) {
685             paymentConfig = paymentSettings.getString("paymentPropertiesPath");
686             serviceName = paymentSettings.getString("paymentService");
687             if (serviceName == null) {
688                 String JavaDoc errMsg = "No payment release service for - " + paymentPref.getString("paymentMethodTypeId");
689                 Debug.logWarning(errMsg, module);
690                 return ServiceUtil.returnError(errMsg);
691             }
692         } else {
693             String JavaDoc errMsg = "No payment release settings found for - " + paymentPref.getString("paymentMethodTypeId");
694             Debug.logWarning(errMsg, module);
695             return ServiceUtil.returnError(errMsg);
696         }
697
698         if (paymentConfig == null || paymentConfig.length() == 0) {
699             paymentConfig = "payment.properties";
700         }
701
702         GenericValue authTransaction = PaymentGatewayServices.getAuthTransaction(paymentPref);
703         Map JavaDoc releaseContext = new HashMap JavaDoc();
704         releaseContext.put("orderPaymentPreference", paymentPref);
705         releaseContext.put("releaseAmount", authTransaction.getDouble("amount"));
706         releaseContext.put("currency", currency);
707         releaseContext.put("paymentConfig", paymentConfig);
708         releaseContext.put("userLogin", userLogin);
709
710         // run the defined service
711
Map JavaDoc releaseResult = null;
712         try {
713             releaseResult = dispatcher.runSync(serviceName, releaseContext, TX_TIME, true);
714         } catch (GenericServiceException e) {
715             String JavaDoc errMsg = "Problem releasing payment";
716             Debug.logError(e,errMsg, module);
717             return ServiceUtil.returnError(errMsg);
718         }
719
720         // get the release result code
721
if (releaseResult != null && !ServiceUtil.isError(releaseResult)) {
722             Boolean JavaDoc releaseResponse = (Boolean JavaDoc) releaseResult.get("releaseResult");
723
724             // create the PaymentGatewayResponse
725
String JavaDoc responseId = delegator.getNextSeqId("PaymentGatewayResponse");
726             GenericValue pgResponse = delegator.makeValue("PaymentGatewayResponse", null);
727             pgResponse.set("paymentGatewayResponseId", responseId);
728             pgResponse.set("paymentServiceTypeEnumId", RELEASE_SERVICE_TYPE);
729             pgResponse.set("orderPaymentPreferenceId", paymentPref.get("orderPaymentPreferenceId"));
730             pgResponse.set("paymentMethodTypeId", paymentPref.get("paymentMethodTypeId"));
731             pgResponse.set("paymentMethodId", paymentPref.get("paymentMethodId"));
732             pgResponse.set("transCodeEnumId", "PGT_RELEASE");
733
734             // set the release info
735
pgResponse.set("referenceNum", releaseResult.get("releaseRefNum"));
736             pgResponse.set("altReference", releaseResult.get("releaseAltRefNum"));
737             pgResponse.set("gatewayCode", releaseResult.get("releaseCode"));
738             pgResponse.set("gatewayFlag", releaseResult.get("releaseFlag"));
739             pgResponse.set("gatewayMessage", releaseResult.get("releaseMessage"));
740             pgResponse.set("transactionDate", UtilDateTime.nowTimestamp());
741
742             // store the gateway response
743
try {
744                 pgResponse.create();
745             } catch (GenericEntityException e) {
746                 Debug.logError(e, "Problem storing PaymentGatewayResponse entity; authorization was released! : " + pgResponse, module);
747             }
748
749             // create the internal messages
750
List JavaDoc messages = (List JavaDoc) releaseResult.get("internalRespMsgs");
751             if (messages != null && messages.size() > 0) {
752                 Iterator JavaDoc i = messages.iterator();
753                 while (i.hasNext()) {
754                     GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg", null);
755                     String JavaDoc respMsgId = delegator.getNextSeqId("PaymentGatewayRespMsg");
756                     String JavaDoc message = (String JavaDoc) i.next();
757                     respMsg.set("paymentGatewayRespMsgId", respMsgId);
758                     respMsg.set("paymentGatewayResponseId", responseId);
759                     respMsg.set("pgrMessage", message);
760                     try {
761                         delegator.create(respMsg);
762                     } catch (GenericEntityException e) {
763                         String JavaDoc errMsg = "Unable to create PaymentGatewayRespMsg record";
764                         Debug.logError(e, errMsg, module);
765                         return ServiceUtil.returnError(errMsg);
766                     }
767                 }
768             }
769
770             if (releaseResponse != null && releaseResponse.booleanValue()) {
771                 paymentPref.set("statusId", "PAYMENT_CANCELLED");
772                 try {
773                     paymentPref.store();
774                 } catch (GenericEntityException e) {
775                     Debug.logError(e, "Problem storing updated payment preference; authorization was released!", module);
776                 }
777
778                 // cancel any payment records
779
List JavaDoc paymentList = null;
780                 try {
781                     paymentList = paymentPref.getRelated("Payment");
782                 } catch (GenericEntityException e) {
783                     Debug.logError(e, "Unable to get Payment records from OrderPaymentPreference : " + paymentPref, module);
784                 }
785
786                 if (paymentList != null) {
787                     Iterator JavaDoc pi = paymentList.iterator();
788                     while (pi.hasNext()) {
789                         GenericValue pay = (GenericValue) pi.next();
790                         pay.set("statusId", "PMNT_CANCELLED");
791                         try {
792                             pay.store();
793                         } catch (GenericEntityException e) {
794                             Debug.logError(e, "Unable to store Payment : " + pay, module);
795                         }
796                     }
797                 }
798             } else {
799                 String JavaDoc errMsg = "Release failed for pref : " + paymentPref;
800                 Debug.logError(errMsg, module);
801                 result = ServiceUtil.returnFailure(errMsg);
802             }
803         } else if (ServiceUtil.isError(releaseResult)) {
804             saveError(dispatcher, userLogin, paymentPref, releaseResult, "PRDS_PAY_RELEASE", "PGT_RELEASE");
805             result = ServiceUtil.returnError(ServiceUtil.getErrorMessage(releaseResult));
806         }
807
808         return result;
809     }
810
811     /**
812      * Captures payments through service calls to the defined processing service for the ProductStore/PaymentMethodType
813      * @return COMPLETE|FAILED|ERROR for complete processing of ALL payment methods.
814      */

815     public static Map JavaDoc capturePaymentsByInvoice(DispatchContext dctx, Map JavaDoc context) {
816         GenericDelegator delegator = dctx.getDelegator();
817         LocalDispatcher dispatcher = dctx.getDispatcher();
818         GenericValue userLogin = (GenericValue) context.get("userLogin");
819         String JavaDoc invoiceId = (String JavaDoc) context.get("invoiceId");
820
821         // lookup the invoice
822
GenericValue invoice = null;
823         try {
824             invoice = delegator.findByPrimaryKey("Invoice", UtilMisc.toMap("invoiceId", invoiceId));
825         } catch (GenericEntityException e) {
826             Debug.logError(e, "Trouble looking up Invoice #" + invoiceId, module);
827             return ServiceUtil.returnError("Trouble looking up Invoice #" + invoiceId);
828         }
829
830         if (invoice == null) {
831             Debug.logError("Could not locate invoice #" + invoiceId, module);
832             return ServiceUtil.returnError("Could not locate invoice #" + invoiceId);
833         }
834
835         // get the OrderItemBilling records for this invoice
836
List JavaDoc orderItemBillings = null;
837         try {
838             orderItemBillings = invoice.getRelated("OrderItemBilling");
839         } catch (GenericEntityException e) {
840             Debug.logError("Trouble getting OrderItemBilling(s) from Invoice #" + invoiceId, module);
841             return ServiceUtil.returnError("Trouble getting OrderItemBilling(s) from Invoice #" + invoiceId);
842         }
843
844         // check for an associated billing account
845
String JavaDoc billingAccountId = invoice.getString("billingAccountId");
846
847         // make sure they are all for the same order
848
String JavaDoc testOrderId = null;
849         boolean allSameOrder = true;
850         if (orderItemBillings != null) {
851             Iterator JavaDoc oii = orderItemBillings.iterator();
852             while (oii.hasNext()) {
853                 GenericValue oib = (GenericValue) oii.next();
854                 String JavaDoc orderId = oib.getString("orderId");
855                 if (testOrderId == null) {
856                     testOrderId = orderId;
857                 } else {
858                     if (!orderId.equals(testOrderId)) {
859                         allSameOrder = false;
860                         break;
861                     }
862                 }
863             }
864         }
865
866         if (testOrderId == null || !allSameOrder) {
867             Debug.logWarning("Attempt to settle Invoice #" + invoiceId + " which contained none/multiple orders", module);
868             return ServiceUtil.returnSuccess();
869         }
870
871         // get the invoice amount (amount to bill)
872
double invoiceTotal = InvoiceWorker.getInvoiceTotal(invoice);
873         if (Debug.infoOn()) Debug.logInfo("(Capture) Invoice [#" + invoiceId + "] total: " + invoiceTotal, module);
874
875         // now capture the order
876
Map JavaDoc serviceContext = UtilMisc.toMap("userLogin", userLogin, "orderId", testOrderId, "invoiceId", invoiceId, "captureAmount", new Double JavaDoc(invoiceTotal));
877         if (UtilValidate.isNotEmpty(billingAccountId)) {
878             serviceContext.put("billingAccountId", billingAccountId);
879         }
880         try {
881             return dispatcher.runSync("captureOrderPayments", serviceContext);
882         } catch (GenericServiceException e) {
883             Debug.logError(e, "Trouble running captureOrderPayments service", module);
884             return ServiceUtil.returnError("Trouble running captureOrderPayments service");
885         }
886     }
887
888     /**
889      * Captures payments through service calls to the defined processing service for the ProductStore/PaymentMethodType
890      * @return COMPLETE|FAILED|ERROR for complete processing of ALL payment methods.
891      */

892     public static Map JavaDoc captureOrderPayments(DispatchContext dctx, Map JavaDoc context) {
893         GenericDelegator delegator = dctx.getDelegator();
894         LocalDispatcher dispatcher = dctx.getDispatcher();
895         GenericValue userLogin = (GenericValue) context.get("userLogin");
896         String JavaDoc orderId = (String JavaDoc) context.get("orderId");
897         String JavaDoc invoiceId = (String JavaDoc) context.get("invoiceId");
898         String JavaDoc billingAccountId = (String JavaDoc) context.get("billingAccountId");
899         Double JavaDoc captureAmount = (Double JavaDoc) context.get("captureAmount");
900         BigDecimal JavaDoc captureAmountBd = new BigDecimal JavaDoc(captureAmount.doubleValue());
901
902         Map JavaDoc result = new HashMap JavaDoc();
903
904         // get the order header and payment preferences
905
GenericValue orderHeader = null;
906         List JavaDoc paymentPrefs = null;
907
908         try {
909             orderHeader = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap("orderId", orderId));
910
911             // get the payment prefs
912
Map JavaDoc lookupMap = UtilMisc.toMap("orderId", orderId, "statusId", "PAYMENT_AUTHORIZED");
913             List JavaDoc orderList = UtilMisc.toList("-maxAmount");
914             paymentPrefs = delegator.findByAnd("OrderPaymentPreference", lookupMap, orderList);
915         } catch (GenericEntityException gee) {
916             Debug.logError(gee, "Problems getting entity record(s), see stack trace", module);
917             result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_ERROR);
918             result.put(ModelService.ERROR_MESSAGE, "ERROR: Could not get order information (" + gee.getMessage() + ").");
919             return result;
920         }
921
922         // error if no order was found
923
if (orderHeader == null) {
924             return ServiceUtil.returnError("Could not find OrderHeader with orderId: " + orderId + "; not processing payments.");
925         }
926
927         OrderReadHelper orh = new OrderReadHelper(orderHeader);
928         
929         // See if there is a billing account first. If so, just charge the captureAmount to the billing account via PaymentApplication
930
GenericValue billingAccount = null;
931         BigDecimal JavaDoc billingAccountAvail = null;
932         BigDecimal JavaDoc billingAccountCaptureAmount = ZERO;
933         Map JavaDoc billingAccountInfo = null;
934         if (UtilValidate.isNotEmpty(billingAccountId)) {
935             try {
936                 billingAccountInfo = dispatcher.runSync("calcBillingAccountBalance", UtilMisc.toMap("billingAccountId", billingAccountId));
937             } catch (GenericServiceException e) {
938                 Debug.logError(e, "Unable to get billing account information for #" + billingAccountId, module);
939             }
940         }
941         if (billingAccountInfo != null) {
942             billingAccount = (GenericValue) billingAccountInfo.get("billingAccount");
943             // use available to capture because we want to know how much we can charge to a billing account
944
Double JavaDoc availableToCapture = (Double JavaDoc) billingAccountInfo.get("availableToCapture");
945             billingAccountAvail = new BigDecimal JavaDoc(availableToCapture.doubleValue());
946         }
947         
948         // if a billing account is used to pay for an order, then charge as much as we can to it before proceeding to other payment methods.
949
if (billingAccount != null && billingAccountAvail != null) {
950             try {
951                 // the amount to be "charged" to the billing account, which is the minimum of the amount the order wants to charge to the billing account
952
// or the amount still available for capturing from the billing account or the total amount to be captured on the order
953
BigDecimal JavaDoc billingAccountMaxAmount = new BigDecimal JavaDoc(orh.getBillingAccountMaxAmount());
954                 billingAccountCaptureAmount = billingAccountMaxAmount.min(billingAccountAvail).min(captureAmountBd);
955                 Debug.logInfo("billing account avail = [" + billingAccountAvail + "] capture amount = [" + billingAccountCaptureAmount + "] maxAmount = ["+billingAccountMaxAmount+"]", module);
956                 // capturing to a billing account if amount is greater than zero
957
if (billingAccountCaptureAmount.compareTo(ZERO) == 1) {
958                     Map JavaDoc tmpResult = dispatcher.runSync("captureBillingAccountPayment", UtilMisc.toMap("invoiceId", invoiceId, "billingAccountId", billingAccountId,
959                             "captureAmount", new Double JavaDoc(billingAccountCaptureAmount.doubleValue()), "userLogin", userLogin));
960                     if (ServiceUtil.isError(tmpResult)) {
961                         return tmpResult;
962                     }
963
964                     // now, if the full amount had not been captured, then capture
965
// it from other methods, otherwise return
966
if (billingAccountCaptureAmount.compareTo(captureAmountBd) == -1) {
967                         BigDecimal JavaDoc outstandingAmount = captureAmountBd.subtract(billingAccountCaptureAmount).setScale(decimals, rounding);
968                         captureAmount = new Double JavaDoc(outstandingAmount.doubleValue());
969                     } else {
970                         Debug.logInfo("Amount to capture [" + captureAmount + "] was fully captured in Payment [" + tmpResult.get("paymentId") + "].", module);
971                         result = ServiceUtil.returnSuccess();
972                         result.put("processResult", "COMPLETE");
973                         return result;
974                     }
975                }
976             } catch (GenericServiceException ex) {
977                 return ServiceUtil.returnError(ex.getMessage());
978             }
979         }
980         
981         // return complete if no payment prefs were found
982
if (paymentPrefs == null || paymentPrefs.size() == 0) {
983             Debug.logWarning("No orderPaymentPreferences available to capture", module);
984             result.put("processResult", "COMPLETE");
985             result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
986             return result;
987         }
988
989         double orderTotal = orh.getOrderGrandTotal();
990         double totalPayments = PaymentWorker.getPaymentsTotal(orh.getOrderPayments());
991         double remainingTotal = orderTotal - totalPayments;
992         if (Debug.infoOn()) Debug.logInfo("Capture Remaining Total: " + remainingTotal, module);
993
994         // re-format the remaining total
995
String JavaDoc currencyFormat = UtilProperties.getPropertyValue("general.properties", "currency.decimal.format", "##0.00");
996         DecimalFormat JavaDoc formatter = new DecimalFormat JavaDoc(currencyFormat);
997         String JavaDoc remainingTotalString = formatter.format(remainingTotal);
998         try {
999             Number JavaDoc remaining = formatter.parse(remainingTotalString);
1000            if (remaining != null) {
1001                remainingTotal = remaining.doubleValue();
1002            }
1003        } catch (ParseException JavaDoc e) {
1004            Debug.logError(e, "Problem getting parsed remaining total", module);
1005            return ServiceUtil.returnError("ERROR: Cannot parse grand total from formatted string; see logs");
1006        }
1007        //Debug.logInfo("Formatted Remaining total : " + remainingTotal, module);
1008

1009        if (captureAmount == null) {
1010            captureAmount = new Double JavaDoc(remainingTotal);
1011        }
1012        double amountToCapture = captureAmount.doubleValue();
1013        if (Debug.infoOn()) Debug.logInfo("Actual Expected Capture Amount : " + amountToCapture, module);
1014
1015        // iterate over the prefs and capture each one until we meet our total
1016
List JavaDoc finished = new ArrayList JavaDoc();
1017        Iterator JavaDoc payments = paymentPrefs.iterator();
1018        while (payments.hasNext()) {
1019            GenericValue paymentPref = (GenericValue) payments.next();
1020            GenericValue authTrans = getAuthTransaction(paymentPref);
1021            if (authTrans == null) {
1022                continue;
1023            }
1024
1025            Double JavaDoc authAmount = authTrans.getDouble("amount");
1026            if (authAmount == null) authAmount = new Double JavaDoc(0.00);
1027            if (authAmount.doubleValue() == 0.00) {
1028                // nothing to capture
1029
Debug.logInfo("Nothing to capture; authAmount = 0", module);
1030                continue;
1031            }
1032            //Debug.log("Actual Auth amount : " + authAmount, module);
1033

1034            // if the authAmount is more then the remaining total; just use remaining total
1035
if (authAmount.doubleValue() > remainingTotal) {
1036                authAmount = new Double JavaDoc(remainingTotal);
1037            }
1038
1039            // if we have a billing account; total up auth + account available
1040
double amountToBillAccount = 0.00;
1041            if (billingAccountAvail != null) {
1042                amountToBillAccount = authAmount.doubleValue() + billingAccountAvail.doubleValue();
1043            }
1044
1045            // the amount for *this* capture
1046
double amountThisCapture = 0.00;
1047
1048            // determine how much for *this* capture
1049
if (authAmount.doubleValue() >= amountToCapture) {
1050                // if the auth amount is more then expected capture just capture what is expected
1051
amountThisCapture = amountToCapture;
1052            } else if (payments.hasNext()) {
1053                // if we have more payments to capture; just capture what was authorized
1054
amountThisCapture = authAmount.doubleValue();
1055            } else if (billingAccountAvail != null && amountToBillAccount >= amountToCapture) {
1056                // the provided billing account will cover the remaining; just capture what was autorized
1057
amountThisCapture = authAmount.doubleValue();
1058            } else {
1059                // we need to capture more then what was authorized; re-auth for the new amount
1060
// TODO: add what the billing account cannot support to the re-auth amount
1061
// TODO: add support for re-auth for additional funds
1062
// just in case; we will capture the authorized amount here; until this is implemented
1063
Debug.logError("The amount to capture was more then what was authorized; we only captured the authorized amount : " + paymentPref, module);
1064                amountThisCapture = authAmount.doubleValue();
1065            }
1066           
1067            Debug.logInfo("Payment preference = [" + paymentPref + "] amount to capture = [" + amountToCapture +"] amount of this capture = [" + amountThisCapture +"] actual auth amount =[" + authAmount + "] amountToBillAccount = [" + amountToBillAccount + "]", module);
1068            Map JavaDoc captureResult = capturePayment(dctx, userLogin, orh, paymentPref, amountThisCapture);
1069            if (captureResult != null) {
1070                // credit card processors return captureAmount, but gift certificate processors return processAmount
1071
Double JavaDoc amountCaptured = (Double JavaDoc) captureResult.get("captureAmount");
1072                if (amountCaptured == null) {
1073                    amountCaptured = (Double JavaDoc) captureResult.get("processAmount");
1074                }
1075                // decrease amount of next payment preference to capture
1076
if (amountCaptured != null) amountToCapture -= amountCaptured.doubleValue();
1077                finished.add(captureResult);
1078
1079                // add the invoiceId to the result for processing
1080
captureResult.put("invoiceId", invoiceId);
1081
1082               // process the capture's results
1083
try {
1084                    processResult(dctx, captureResult, userLogin, paymentPref);
1085                } catch (GeneralException e) {
1086                    Debug.logError(e, "Trouble processing the result; captureResult: " + captureResult, module);
1087                    return ServiceUtil.returnError("Trouble processing the capture results");
1088                }
1089
1090                // create any splits which are needed
1091
BigDecimal JavaDoc totalAmountCaptured = new BigDecimal JavaDoc(amountThisCapture);
1092                if (authAmount.doubleValue() > totalAmountCaptured.doubleValue()) {
1093                    // create a new payment preference and authorize it
1094
double newAmount = authAmount.doubleValue() - totalAmountCaptured.doubleValue(); // TODO: use BigDecimal arithmetic here (and everywhere else for that matter)
1095
Debug.logInfo("Creating payment preference split", module);
1096                    String JavaDoc newPrefId = delegator.getNextSeqId("OrderPaymentPreference");
1097                    GenericValue newPref = delegator.makeValue("OrderPaymentPreference", UtilMisc.toMap("orderPaymentPreferenceId", newPrefId));
1098                    newPref.set("orderId", paymentPref.get("orderId"));
1099                    newPref.set("paymentMethodTypeId", paymentPref.get("paymentMethodTypeId"));
1100                    newPref.set("paymentMethodId", paymentPref.get("paymentMethodId"));
1101                    newPref.set("maxAmount", paymentPref.get("maxAmount"));
1102                    newPref.set("statusId", "PAYMENT_NOT_AUTH");
1103                    newPref.set("createdDate", UtilDateTime.nowTimestamp());
1104                    if (userLogin != null) {
1105                        newPref.set("createdByUserLogin", userLogin.getString("userLoginId"));
1106                    }
1107                    Debug.logInfo("New preference : " + newPref, module);
1108                    try {
1109                        // create the new payment preference
1110
delegator.create(newPref);
1111
1112                        // authorize the new preference
1113
Map JavaDoc processorResult = authPayment(dispatcher, userLogin, orh, newPref, newAmount, false);
1114                        if (processorResult != null) {
1115                            // process the auth results
1116
boolean authResult = false;
1117                            try {
1118                                authResult = processResult(dctx, processorResult, userLogin, newPref);
1119                                if (!authResult) {
1120                                    Debug.logError("Authorization failed : " + newPref + " : " + processorResult, module);
1121                                }
1122                            } catch (GeneralException e) {
1123                                Debug.logError(e, "Trouble processing the auth result : " + newPref + " : " + processorResult, module);
1124                            }
1125                        } else {
1126                            Debug.logError("Payment not authorized : " + newPref + " : " + processorResult, module);
1127                        }
1128                    } catch (GenericEntityException e) {
1129                        Debug.logError(e, "ERROR: cannot create new payment preference : " + newPref, module);
1130                    }
1131                }
1132            } else {
1133                Debug.logError("Payment not captured", module);
1134                continue;
1135            }
1136        }
1137
1138        if (amountToCapture > 0.00) {
1139            result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
1140            result.put("processResult", "FAILED");
1141            return result;
1142        } else {
1143            result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
1144            result.put("processResult", "COMPLETE");
1145            return result;
1146        }
1147    }
1148
1149    public static Map JavaDoc captureBillingAccountPayment(DispatchContext dctx, Map JavaDoc context) {
1150        GenericDelegator delegator = dctx.getDelegator();
1151        LocalDispatcher dispatcher = dctx.getDispatcher();
1152        GenericValue userLogin = (GenericValue) context.get("userLogin");
1153        String JavaDoc invoiceId = (String JavaDoc) context.get("invoiceId");
1154        String JavaDoc billingAccountId = (String JavaDoc) context.get("billingAccountId");
1155        Double JavaDoc captureAmount = (Double JavaDoc) context.get("captureAmount");
1156        Map JavaDoc results = ServiceUtil.returnSuccess();
1157        
1158        try {
1159            // Note that the partyIdFrom of the Payment should be the partyIdTo of the invoice, since you're receiving a payment from the party you billed
1160
GenericValue invoice = delegator.findByPrimaryKey("Invoice", UtilMisc.toMap("invoiceId", invoiceId));
1161            Map JavaDoc paymentParams = UtilMisc.toMap("paymentTypeId", "CUSTOMER_PAYMENT", "paymentMethodTypeId", "EXT_BILLACT",
1162                    "partyIdFrom", invoice.getString("partyId"), "partyIdTo", invoice.getString("partyIdFrom"),
1163                    "statusId", "PMNT_RECEIVED", "effectiveDate", UtilDateTime.nowTimestamp());
1164            paymentParams.put("amount", captureAmount);
1165            paymentParams.put("currencyUomId", invoice.getString("currencyUomId"));
1166            paymentParams.put("userLogin", userLogin);
1167            Map JavaDoc tmpResult = dispatcher.runSync("createPayment", paymentParams);
1168            if (ServiceUtil.isError(tmpResult)) {
1169                return tmpResult;
1170            }
1171            
1172            String JavaDoc paymentId = (String JavaDoc) tmpResult.get("paymentId");
1173            tmpResult = dispatcher.runSync("createPaymentApplication", UtilMisc.toMap("paymentId", paymentId, "invoiceId", invoiceId, "billingAccountId", billingAccountId,
1174                    "amountApplied", captureAmount, "userLogin", userLogin));
1175            if (ServiceUtil.isError(tmpResult)) {
1176                return tmpResult;
1177            }
1178            if (paymentId == null) {
1179                return ServiceUtil.returnError("No payment created for invoice [" + invoiceId + "] and billing account [" + billingAccountId + "]");
1180            }
1181            results.put("paymentId", paymentId);
1182        } catch (GenericEntityException ex) {
1183            return ServiceUtil.returnError(ex.getMessage());
1184        } catch (GenericServiceException ex) {
1185            return ServiceUtil.returnError(ex.getMessage());
1186        }
1187
1188        return results;
1189    }
1190    
1191    private static Map JavaDoc capturePayment(DispatchContext dctx, GenericValue userLogin, OrderReadHelper orh, GenericValue paymentPref, double amount) {
1192        return capturePayment(dctx, userLogin, orh, paymentPref, amount, null);
1193    }
1194
1195    private static Map JavaDoc capturePayment(DispatchContext dctx, GenericValue userLogin, OrderReadHelper orh, GenericValue paymentPref, double amount, GenericValue authTrans) {
1196        LocalDispatcher dispatcher = dctx.getDispatcher();
1197        // look up the payment configuration settings
1198
String JavaDoc serviceName = null;
1199        String JavaDoc paymentConfig = null;
1200
1201        // get the payment settings i.e. serviceName and config properties file name
1202
GenericValue paymentSettings = getPaymentSettings(orh.getOrderHeader(), paymentPref, CAPTURE_SERVICE_TYPE, false);
1203        if (paymentSettings != null) {
1204            paymentConfig = paymentSettings.getString("paymentPropertiesPath");
1205            serviceName = paymentSettings.getString("paymentService");
1206            if (serviceName == null) {
1207                Debug.logError("Service name is null for payment setting; cannot process", module);
1208                return null;
1209            }
1210        } else {
1211            Debug.logError("Invalid payment settings entity, no payment settings found", module);
1212            return null;
1213        }
1214
1215        if (paymentConfig == null || paymentConfig.length() == 0) {
1216            paymentConfig = "payment.properties";
1217        }
1218
1219        // check the validity of the authorization; re-auth if necessary
1220
if (!PaymentGatewayServices.checkAuthValidity(paymentPref, paymentConfig)) {
1221            // re-auth required before capture
1222
Map JavaDoc processorResult = PaymentGatewayServices.authPayment(dispatcher, userLogin, orh, paymentPref, amount, true);
1223
1224            boolean authResult = false;
1225            if (processorResult != null) {
1226                // process the auth results
1227
try {
1228                    authResult = processResult(dctx, processorResult, userLogin, paymentPref);
1229                    if (!authResult) {
1230                        Debug.logError("Re-Authorization failed : " + paymentPref + " : " + processorResult, module);
1231                    }
1232                } catch (GeneralException e) {
1233                    Debug.logError(e, "Trouble processing the re-auth result : " + paymentPref + " : " + processorResult, module);
1234                }
1235            } else {
1236                Debug.logError("Payment not re-authorized : " + paymentPref + " : " + processorResult, module);
1237            }
1238
1239            if (!authResult) {
1240                // returning null to cancel the capture process.
1241
return null;
1242            }
1243
1244            // get the new auth transaction
1245
authTrans = getAuthTransaction(paymentPref);
1246        }
1247
1248        // prepare the context for the capture service (must follow the ccCaptureInterface
1249
Map JavaDoc captureContext = new HashMap JavaDoc();
1250        captureContext.put("userLogin", userLogin);
1251        captureContext.put("orderPaymentPreference", paymentPref);
1252        captureContext.put("paymentConfig", paymentConfig);
1253        captureContext.put("currency", orh.getCurrency());
1254
1255        // this is necessary because the ccCaptureInterface uses "captureAmount" but the paymentProcessInterface uses "processAmount"
1256
try {
1257            ModelService captureService = dctx.getModelService(serviceName);
1258            Set JavaDoc inParams = captureService.getInParamNames();
1259            if (inParams.contains("captureAmount")) {
1260                captureContext.put("captureAmount", new Double JavaDoc(amount));
1261            } else if (inParams.contains("processAmount")) {
1262                captureContext.put("processAmount", new Double JavaDoc(amount));
1263            } else {
1264                return ServiceUtil.returnError("Service [" + serviceName + "] does not have a captureAmount or processAmount. Its parameters are: " + inParams);
1265            }
1266        } catch (GenericServiceException ex) {
1267            return ServiceUtil.returnError("Cannot get model service for " + serviceName);
1268        }
1269        
1270        
1271        if (authTrans != null) {
1272            captureContext.put("authTrans", authTrans);
1273        }
1274
1275        Debug.logInfo("Capture [" + serviceName + "] : " + captureContext, module);
1276
1277        // now invoke the capture service
1278
Map JavaDoc captureResult = null;
1279        try {
1280            captureResult = dispatcher.runSync(serviceName, captureContext, TX_TIME, true);
1281        } catch (GenericServiceException e) {
1282            Debug.logError(e, "Could not capture payment ... serviceName: " + serviceName + " ... context: " + captureContext, module);
1283            return null;
1284        }
1285
1286        // pass the payTo partyId to the result processor; we just add it to the result context.
1287
String JavaDoc payToPartyId = getPayToPartyId(orh.getOrderHeader());
1288        captureResult.put("payToPartyId", payToPartyId);
1289
1290        // add paymentSettings to result; for use by later processors
1291
captureResult.put("paymentSettings", paymentSettings);
1292
1293        // pass the currencyUomId as well
1294
captureResult.put("currencyUomId", orh.getCurrency());
1295
1296        // log the error message as a gateway response when it fails
1297
if (ServiceUtil.isError(captureResult)) {
1298            saveError(dispatcher, userLogin, paymentPref, captureResult, "PRDS_PAY_CAPTURE", "PGT_CAPTURE");
1299        }
1300
1301        return captureResult;
1302    }
1303
1304    private static void saveError(LocalDispatcher dispatcher, GenericValue userLogin, GenericValue paymentPref, Map JavaDoc result, String JavaDoc serviceType, String JavaDoc transactionCode) {
1305        Map JavaDoc serviceContext = new HashMap JavaDoc();
1306        serviceContext.put("paymentServiceTypeEnumId", serviceType);
1307        serviceContext.put("orderPaymentPreference", paymentPref);
1308        serviceContext.put("transCodeEnumId", transactionCode);
1309        serviceContext.put("serviceResultMap", result);
1310        serviceContext.put("userLogin", userLogin);
1311
1312        try {
1313            dispatcher.runAsync("processPaymentServiceError", serviceContext);
1314        } catch (GenericServiceException e) {
1315            Debug.logError(e, module);
1316        }
1317    }
1318
1319    public static Map JavaDoc storePaymentErrorMessage(DispatchContext dctx, Map JavaDoc context) {
1320        GenericDelegator delegator = dctx.getDelegator();
1321        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
1322        String JavaDoc serviceType = (String JavaDoc) context.get("paymentServiceTypeEnumId");
1323        String JavaDoc transactionCode = (String JavaDoc) context.get("transCodeEnumId");
1324        Map JavaDoc result = (Map JavaDoc) context.get("serviceResultMap");
1325
1326        String JavaDoc responseId = delegator.getNextSeqId("PaymentGatewayResponse");
1327        GenericValue response = delegator.makeValue("PaymentGatewayResponse", null);
1328        response.set("paymentGatewayResponseId", responseId);
1329        response.set("paymentServiceTypeEnumId", serviceType);
1330        response.set("orderPaymentPreferenceId", paymentPref.get("orderPaymentPreferenceId"));
1331        response.set("paymentMethodTypeId", paymentPref.get("paymentMethodTypeId"));
1332        response.set("paymentMethodId", paymentPref.get("paymentMethodId"));
1333        response.set("transCodeEnumId", transactionCode);
1334        response.set("referenceNum", "ERROR");
1335        response.set("gatewayMessage", ServiceUtil.getErrorMessage(result));
1336        response.set("transactionDate", UtilDateTime.nowTimestamp());
1337
1338        try {
1339            delegator.create(response);
1340        } catch (GenericEntityException e) {
1341            Debug.logError(e, module);
1342            return ServiceUtil.returnError("Unable to create PaymentGatewayResponse for failed service call!");
1343        }
1344
1345        Debug.logInfo("Created PaymentGatewayResponse record for returned error", module);
1346        return ServiceUtil.returnSuccess();
1347    }
1348
1349    private static boolean processResult(DispatchContext dctx, Map JavaDoc result, GenericValue userLogin, GenericValue paymentPreference) throws GeneralException {
1350        Boolean JavaDoc authResult = (Boolean JavaDoc) result.get("authResult");
1351        Boolean JavaDoc captureResult = (Boolean JavaDoc) result.get("captureResult");
1352        boolean resultPassed = false;
1353        String JavaDoc initialStatus = paymentPreference.getString("statusId");
1354        String JavaDoc authServiceType = null;
1355
1356        if (authResult != null) {
1357            processAuthResult(dctx, result, userLogin, paymentPreference);
1358            resultPassed = authResult.booleanValue();
1359            authServiceType = ("PAYMENT_NOT_AUTH".equals(initialStatus)) ? AUTH_SERVICE_TYPE : REAUTH_SERVICE_TYPE;;
1360        }
1361        if (captureResult != null) {
1362            processCaptureResult(dctx, result, userLogin, paymentPreference, authServiceType);
1363            if (!resultPassed)
1364                resultPassed = captureResult.booleanValue();
1365        }
1366        return resultPassed;
1367    }
1368
1369    private static void processAuthResult(DispatchContext dctx, Map JavaDoc result, GenericValue userLogin, GenericValue paymentPreference) throws GeneralException {
1370        LocalDispatcher dispatcher = dctx.getDispatcher();
1371        result.put("userLogin", userLogin);
1372        result.put("orderPaymentPreference", paymentPreference);
1373        ModelService model = dctx.getModelService("processAuthResult");
1374        Map JavaDoc context = model.makeValid(result, ModelService.IN_PARAM);
1375        Map JavaDoc svcResp = null;
1376        try {
1377            svcResp = dispatcher.runSync("processAuthResult", context);
1378        } catch (GenericServiceException e) {
1379            Debug.logError(e, module);
1380            throw e;
1381        }
1382        if (svcResp != null && ServiceUtil.isError(svcResp)) {
1383           Debug.logError(ServiceUtil.getErrorMessage(svcResp), module);
1384           throw new GeneralException(ServiceUtil.getErrorMessage(svcResp));
1385        }
1386    }
1387
1388    public static Map JavaDoc processAuthResult(DispatchContext dctx, Map JavaDoc context) {
1389        GenericDelegator delegator = dctx.getDelegator();
1390        GenericValue paymentPreference = (GenericValue) context.get("orderPaymentPreference");
1391        Boolean JavaDoc authResult = (Boolean JavaDoc) context.get("authResult");
1392        String JavaDoc authType = (String JavaDoc) context.get("serviceTypeEnum");
1393        String JavaDoc currencyUomId = (String JavaDoc) context.get("currencyUomId");
1394
1395        // type of auth this was can be determined by the previous status
1396
if (UtilValidate.isEmpty(authType)) {
1397            authType = ("PAYMENT_NOT_AUTH".equals(paymentPreference.getString("statusId"))) ?
1398                    AUTH_SERVICE_TYPE : REAUTH_SERVICE_TYPE;
1399        }
1400
1401        // create the PaymentGatewayResponse
1402
String JavaDoc responseId = delegator.getNextSeqId("PaymentGatewayResponse");
1403        GenericValue response = delegator.makeValue("PaymentGatewayResponse", null);
1404        response.set("paymentGatewayResponseId", responseId);
1405        response.set("paymentServiceTypeEnumId", authType);
1406        response.set("orderPaymentPreferenceId", paymentPreference.get("orderPaymentPreferenceId"));
1407        response.set("paymentMethodTypeId", paymentPreference.get("paymentMethodTypeId"));
1408        response.set("paymentMethodId", paymentPreference.get("paymentMethodId"));
1409        response.set("transCodeEnumId", "PGT_AUTHORIZE");
1410        response.set("currencyUomId", currencyUomId);
1411
1412        // set the avs/fraud result
1413
response.set("gatewayAvsResult", context.get("avsCode"));
1414        response.set("gatewayScoreResult", context.get("scoreCode"));
1415
1416        // set the auth info
1417
response.set("amount", context.get("processAmount"));
1418        response.set("referenceNum", context.get("authRefNum"));
1419        response.set("altReference", context.get("authAltRefNum"));
1420        response.set("gatewayCode", context.get("authCode"));
1421        response.set("gatewayFlag", context.get("authFlag"));
1422        response.set("gatewayMessage", context.get("authMessage"));
1423        response.set("transactionDate", UtilDateTime.nowTimestamp());
1424        try {
1425            delegator.create(response);
1426        } catch (GenericEntityException e) {
1427            Debug.logError(e, module);
1428            return ServiceUtil.returnError("Error creating response information");
1429        }
1430
1431        // create the internal messages
1432
List JavaDoc messages = (List JavaDoc) context.get("internalRespMsgs");
1433        if (messages != null && messages.size() > 0) {
1434            Iterator JavaDoc i = messages.iterator();
1435            while (i.hasNext()) {
1436                GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg", null);
1437                String JavaDoc respMsgId = delegator.getNextSeqId("PaymentGatewayRespMsg");
1438                String JavaDoc message = (String JavaDoc) i.next();
1439                respMsg.set("paymentGatewayRespMsgId", respMsgId);
1440                respMsg.set("paymentGatewayResponseId", responseId);
1441                respMsg.set("pgrMessage", message);
1442                try {
1443                    delegator.create(respMsg);
1444                } catch (GenericEntityException e) {
1445                    Debug.logError(e, module);
1446                    return ServiceUtil.returnError("Error creating response message information");
1447                }
1448            }
1449        }
1450
1451        if (response.getDouble("amount").doubleValue() != ((Double JavaDoc) context.get("processAmount")).doubleValue()) {
1452            Debug.logWarning("The authorized amount does not match the max amount : Response - " + response + " : result - " + context, module);
1453        }
1454
1455        // set the status of the OrderPaymentPreference
1456
if (context != null && authResult.booleanValue()) {
1457            paymentPreference.set("statusId", "PAYMENT_AUTHORIZED");
1458            paymentPreference.set("securityCode", null);
1459        } else if (context != null && !authResult.booleanValue()) {
1460            paymentPreference.set("statusId", "PAYMENT_DECLINED");
1461        } else {
1462            paymentPreference.set("statusId", "PAYMENT_ERROR");
1463        }
1464        try {
1465            paymentPreference.store();
1466        } catch (GenericEntityException e) {
1467            Debug.logError(e, module);
1468            return ServiceUtil.returnError("Error updating order payment preference information");
1469        }
1470
1471        return ServiceUtil.returnSuccess();
1472    }
1473
1474    private static GenericValue processAuthRetryResult(DispatchContext dctx, Map JavaDoc result, GenericValue userLogin, GenericValue paymentPreference) throws GeneralException {
1475        processAuthResult(dctx, result, userLogin, paymentPreference);
1476        return getAuthTransaction(paymentPreference);
1477    }
1478
1479    private static void processCaptureResult(DispatchContext dctx, Map JavaDoc result, GenericValue userLogin, GenericValue paymentPreference) throws GeneralException {
1480        processCaptureResult(dctx, result, userLogin, paymentPreference, null);
1481    }
1482
1483    private static void processCaptureResult(DispatchContext dctx, Map JavaDoc result, GenericValue userLogin, GenericValue paymentPreference, String JavaDoc authServiceType) throws GeneralException {
1484        LocalDispatcher dispatcher = dctx.getDispatcher();
1485        Boolean JavaDoc captureResult = (Boolean JavaDoc) result.get("captureResult");
1486        Double JavaDoc amount = null;
1487        if (result.get("captureAmount") != null) {
1488            amount = (Double JavaDoc) result.get("captureAmount");
1489        } else if (result.get("processAmount") != null) {
1490            amount = (Double JavaDoc) result.get("processAmount");
1491            result.put("captureAmount", amount);
1492        }
1493
1494        if (amount == null) {
1495            throw new GeneralException("Unable to process null capture amount");
1496        }
1497
1498        if (result != null && captureResult.booleanValue()) {
1499            result.put("orderPaymentPreference", paymentPreference);
1500            result.put("userLogin", userLogin);
1501            result.put("serviceTypeEnum", authServiceType);
1502
1503            ModelService model = dctx.getModelService("processCaptureResult");
1504            Map JavaDoc context = model.makeValid(result, ModelService.IN_PARAM);
1505            Map JavaDoc capRes = null;
1506            try {
1507                capRes = dispatcher.runSync("processCaptureResult", context);
1508            } catch (GenericServiceException e) {
1509                Debug.logError(e, module);
1510                throw e;
1511            }
1512            if (capRes != null && ServiceUtil.isError(capRes)) {
1513                throw new GeneralException(ServiceUtil.getErrorMessage(capRes));
1514            }
1515        } else if (result != null && !captureResult.booleanValue()) {
1516            // problem with the capture lets get some needed info
1517
OrderReadHelper orh = null;
1518            try {
1519                GenericValue orderHeader = paymentPreference.getRelatedOne("OrderHeader");
1520                if (orderHeader != null)
1521                    orh = new OrderReadHelper(orderHeader);
1522            } catch (GenericEntityException e) {
1523                Debug.logError(e, "Problems getting OrderHeader; cannot re-auth the payment", module);
1524            }
1525
1526            if (amount != null && (double) amount.doubleValue() == new Double JavaDoc(0.00).doubleValue()) {
1527                amount = paymentPreference.getDouble("maxAmount");
1528                Debug.log("resetting payment amount from 0.00 to correctMax amount", module);
1529            }
1530            Debug.log("reauth with amount: " + amount, module);
1531            if (orh != null) {
1532                // first lets re-auth the card
1533
Map JavaDoc authPayRes = authPayment(dispatcher, userLogin, orh, paymentPreference, amount.doubleValue(), true);
1534                Debug.log("authPayRes: " + authPayRes, module);
1535                if (authPayRes != null) {
1536                    Boolean JavaDoc authResp = (Boolean JavaDoc) authPayRes.get("authResult");
1537                    Boolean JavaDoc capResp = (Boolean JavaDoc) authPayRes.get("captureResult");
1538                    if (authResp != null) {
1539                        GenericValue authTrans = processAuthRetryResult(dctx, authPayRes, userLogin, paymentPreference);
1540
1541                        if (authResp.booleanValue()) {
1542                            // first make sure we didn't already capture - probably not
1543
if (capResp != null && capResp.booleanValue()) {
1544                                processCaptureResult(dctx, result, userLogin, paymentPreference);
1545                            } else {
1546                                // lets try to capture the funds now
1547
Map JavaDoc capPayRes = capturePayment(dctx, userLogin, orh, paymentPreference, amount.doubleValue(), authTrans);
1548                                if (capPayRes != null) {
1549                                    Boolean JavaDoc capPayResp = (Boolean JavaDoc) capPayRes.get("captureResult");
1550                                    if (capPayResp != null && capPayResp.booleanValue()) {
1551                                        // it was successful
1552
processCaptureResult(dctx, capPayRes, userLogin, paymentPreference);
1553                                    } else {
1554                                        // not successful; log it
1555
Debug.logError("Capture of authorized payment failed: " + paymentPreference, module);
1556                                    }
1557                                } else {
1558                                    Debug.logError("Problems trying to capture payment (null result): " + paymentPreference, module);
1559                                }
1560                            }
1561                        } else {
1562                            Debug.logError("Payment authorization failed: " + paymentPreference, module);
1563                        }
1564                    } else {
1565                        Debug.logError("Payment authorization failed (null result): " + paymentPreference, module);
1566                    }
1567                } else {
1568                    Debug.logError("Problems trying to re-authorize the payment (null result): " + paymentPreference, module);
1569                }
1570            } else {
1571                Debug.logError("Null OrderReadHelper cannot process", module);
1572            }
1573        } else {
1574            Debug.logError("Result pass is null, no capture available", module);
1575        }
1576    }
1577
1578    public static Map JavaDoc processCaptureResult(DispatchContext dctx, Map JavaDoc context) {
1579        GenericDelegator delegator = dctx.getDelegator();
1580        LocalDispatcher dispatcher = dctx.getDispatcher();
1581
1582        GenericValue paymentPreference = (GenericValue) context.get("orderPaymentPreference");
1583        GenericValue userLogin = (GenericValue) context.get("userLogin");
1584        String JavaDoc invoiceId = (String JavaDoc) context.get("invoiceId");
1585        String JavaDoc payTo = (String JavaDoc) context.get("payToPartyId");
1586        Double JavaDoc amount = (Double JavaDoc) context.get("captureAmount");
1587        String JavaDoc serviceType = (String JavaDoc) context.get("serviceTypeEnum");
1588        String JavaDoc currencyUomId = (String JavaDoc) context.get("currencyUomId");
1589        
1590        if (UtilValidate.isEmpty(serviceType)) {
1591            serviceType = CAPTURE_SERVICE_TYPE;
1592        }
1593
1594        // create the PaymentGatewayResponse record
1595
String JavaDoc responseId = delegator.getNextSeqId("PaymentGatewayResponse");
1596        GenericValue response = delegator.makeValue("PaymentGatewayResponse", null);
1597        response.set("paymentGatewayResponseId", responseId);
1598        response.set("paymentServiceTypeEnumId", serviceType);
1599        response.set("orderPaymentPreferenceId", paymentPreference.get("orderPaymentPreferenceId"));
1600        response.set("paymentMethodTypeId", paymentPreference.get("paymentMethodTypeId"));
1601        response.set("paymentMethodId", paymentPreference.get("paymentMethodId"));
1602        response.set("transCodeEnumId", "PGT_CAPTURE");
1603        response.set("currencyUomId", currencyUomId);
1604        if (context.get("authRefNum") != null) {
1605            response.set("subReference", context.get("authRefNum"));
1606            response.set("altReference", context.get("authAltRefNum"));
1607        } else {
1608            response.set("altReference", context.get("captureAltRefNum"));
1609        }
1610
1611        // set the capture info
1612
response.set("amount", amount);
1613        response.set("referenceNum", context.get("captureRefNum"));
1614        response.set("gatewayCode", context.get("captureCode"));
1615        response.set("gatewayFlag", context.get("captureFlag"));
1616        response.set("gatewayMessage", context.get("captureMessage"));
1617        response.set("transactionDate", UtilDateTime.nowTimestamp());
1618        try {
1619            delegator.create(response);
1620        } catch (GenericEntityException e) {
1621            Debug.logError(e, module);
1622            return ServiceUtil.returnError("Error creating response information");
1623        }
1624
1625        // create the internal messages
1626
List JavaDoc messages = (List JavaDoc) context.get("internalRespMsgs");
1627        if (messages != null && messages.size() > 0) {
1628            Iterator JavaDoc i = messages.iterator();
1629            while (i.hasNext()) {
1630                GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg", null);
1631                String JavaDoc respMsgId = delegator.getNextSeqId("PaymentGatewayRespMsg");
1632                String JavaDoc message = (String JavaDoc) i.next();
1633                respMsg.set("paymentGatewayRespMsgId", respMsgId);
1634                respMsg.set("paymentGatewayResponseId", responseId);
1635                respMsg.set("pgrMessage", message);
1636                try {
1637                    delegator.create(respMsg);
1638                } catch (GenericEntityException e) {
1639                    Debug.logError(e, module);
1640                    return ServiceUtil.returnError("Error creating response message information");
1641                }
1642            }
1643        }
1644
1645        // get the invoice
1646
GenericValue invoice = null;
1647        if (invoiceId != null) {
1648            try {
1649                invoice = delegator.findByPrimaryKey("Invoice", UtilMisc.toMap("invoiceId", invoiceId));
1650            } catch (GenericEntityException e) {
1651                String JavaDoc message = "Failed to process capture result: Could not find invoice ["+invoiceId+"] due to entity error: " + e.getMessage();
1652                Debug.logError(e, message, module);
1653                return ServiceUtil.returnError(message );
1654            }
1655        }
1656
1657        // determine the partyIdFrom for the payment, which is who made the payment
1658
String JavaDoc partyIdFrom = null;
1659        if (invoice != null) {
1660            // get the party from the invoice, which is the bill-to party (partyId)
1661
partyIdFrom = invoice.getString("partyId");
1662        } else {
1663            // otherwise get the party from the order's OrderRole
1664
String JavaDoc orderId = paymentPreference.getString("orderId");
1665            List JavaDoc orl = null;
1666            try {
1667                orl = delegator.findByAnd("OrderRole", UtilMisc.toMap("orderId", orderId, "roleTypeId", "BILL_TO_CUSTOMER"));
1668            } catch (GenericEntityException e) {
1669                Debug.logError(e, module);
1670            }
1671            if (orl.size() > 0) {
1672                GenericValue orderRole = EntityUtil.getFirst(orl);
1673                partyIdFrom = orderRole.getString("partyId");
1674            }
1675        }
1676
1677        // get the partyIdTo for the payment, which is who is receiving it
1678
String JavaDoc partyIdTo = null;
1679        if (!UtilValidate.isEmpty(payTo)) {
1680            // use input pay to party
1681
partyIdTo = payTo;
1682        } else if (invoice != null) {
1683            // ues the invoice partyIdFrom as the pay to party (which is who supplied the invoice)
1684
partyIdTo = invoice.getString("partyIdFrom");
1685        } else {
1686            // otherwise default to Company and print a big warning about this
1687
payTo = "Company";
1688            Debug.logWarning("Using default value of [Company] for payTo on invoice [" + invoiceId + "] and orderPaymentPreference [" +
1689                    paymentPreference.getString("orderPaymentPreferenceId") + "]", module);
1690        }
1691
1692
1693        Map JavaDoc paymentCtx = UtilMisc.toMap("paymentTypeId", "CUSTOMER_PAYMENT");
1694        paymentCtx.put("paymentMethodTypeId", paymentPreference.get("paymentMethodTypeId"));
1695        paymentCtx.put("paymentMethodId", paymentPreference.get("paymentMethodId"));
1696        paymentCtx.put("paymentGatewayResponseId", responseId);
1697        paymentCtx.put("partyIdTo", partyIdTo);
1698        paymentCtx.put("partyIdFrom", partyIdFrom);
1699        paymentCtx.put("statusId", "PMNT_RECEIVED");
1700        paymentCtx.put("paymentPreferenceId", paymentPreference.get("orderPaymentPreferenceId"));
1701        paymentCtx.put("amount", amount);
1702        paymentCtx.put("currencyUomId", currencyUomId);
1703        paymentCtx.put("userLogin", userLogin);
1704        paymentCtx.put("paymentRefNum", context.get("captureRefNum"));
1705
1706        Map JavaDoc payRes = null;
1707        try {
1708            payRes = dispatcher.runSync("createPayment", paymentCtx);
1709        } catch (GenericServiceException e) {
1710            Debug.logError(e, module);
1711            return ServiceUtil.returnError("Error creating payment record");
1712        }
1713        if (payRes != null && ServiceUtil.isError(payRes)) {
1714            return ServiceUtil.returnError(ServiceUtil.getErrorMessage(payRes));
1715        }
1716
1717        String JavaDoc paymentId = (String JavaDoc) payRes.get("paymentId");
1718        paymentPreference.set("statusId", "PAYMENT_SETTLED");
1719        try {
1720            paymentPreference.store();
1721        } catch (GenericEntityException e) {
1722            Debug.logError(e, module);
1723        }
1724
1725        // create the PaymentApplication if invoiceId is available
1726
if (invoiceId != null) {
1727            Debug.logInfo("Processing Invoice #" + invoiceId, module);
1728            Map JavaDoc paCtx = UtilMisc.toMap("paymentId", paymentId, "invoiceId", invoiceId);
1729            paCtx.put("amountApplied", context.get("captureAmount"));
1730            paCtx.put("userLogin", userLogin);
1731            Map JavaDoc paRes = null;
1732            try {
1733                paRes = dispatcher.runSync("createPaymentApplication", paCtx);
1734            } catch (GenericServiceException e) {
1735                Debug.logError(e, module);
1736                return ServiceUtil.returnError("Error creating invoice application");
1737            }
1738            if (paRes != null && ServiceUtil.isError(paRes)) {
1739                return ServiceUtil.returnError(ServiceUtil.getErrorMessage(paRes));
1740            }
1741        }
1742
1743        return ServiceUtil.returnSuccess();
1744    }
1745
1746    public static Map JavaDoc refundPayment(DispatchContext dctx, Map JavaDoc context) {
1747        GenericDelegator delegator = dctx.getDelegator();
1748        LocalDispatcher dispatcher = dctx.getDispatcher();
1749        GenericValue userLogin = (GenericValue) context.get("userLogin");
1750
1751        GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
1752        Double JavaDoc refundAmount = (Double JavaDoc) context.get("refundAmount");
1753
1754        GenericValue orderHeader = null;
1755        try {
1756            orderHeader = paymentPref.getRelatedOne("OrderHeader");
1757        } catch (GenericEntityException e) {
1758            Debug.logError(e, "Cannot get OrderHeader from OrderPaymentPreference", module);
1759            return ServiceUtil.returnError("Problems getting OrderHeader from OrderPaymentPreference: " + e.getMessage());
1760        }
1761
1762        OrderReadHelper orh = new OrderReadHelper(orderHeader);
1763
1764        GenericValue paymentSettings = null;
1765        if (orderHeader != null) {
1766            paymentSettings = getPaymentSettings(orderHeader, paymentPref, REFUND_SERVICE_TYPE, false);
1767        }
1768
1769        if (paymentSettings != null) {
1770            String JavaDoc paymentConfig = paymentSettings.getString("paymentPropertiesPath");
1771            String JavaDoc serviceName = paymentSettings.getString("paymentService");
1772            if (serviceName != null) {
1773                Map JavaDoc serviceContext = new HashMap JavaDoc();
1774                serviceContext.put("orderPaymentPreference", paymentPref);
1775                serviceContext.put("paymentConfig", paymentConfig);
1776                serviceContext.put("currency", orh.getCurrency());
1777
1778                // get the creditCard/address/email
1779
String JavaDoc payToPartyId = null;
1780                try {
1781                    payToPartyId = getBillingInformation(orh, paymentPref, new HashMap JavaDoc());
1782                } catch (GenericEntityException e) {
1783                    Debug.logError(e, "Problems getting billing information", module);
1784                    return ServiceUtil.returnError("Problems getting billing information");
1785                }
1786
1787                // format the price
1788
String JavaDoc currencyFormat = UtilProperties.getPropertyValue("general.properties", "currency.decimal.format", "##0.00");
1789                DecimalFormat JavaDoc formatter = new DecimalFormat JavaDoc(currencyFormat);
1790                String JavaDoc amountString = formatter.format(refundAmount);
1791                Double JavaDoc processAmount = null;
1792                try {
1793                    processAmount = new Double JavaDoc(formatter.parse(amountString).doubleValue());
1794                } catch (ParseException JavaDoc e) {
1795                    Debug.logError(e, "Problem parsing amount using DecimalFormat", module);
1796                    return ServiceUtil.returnError("Refund processor problems; see logs");
1797                }
1798                serviceContext.put("refundAmount", processAmount);
1799                serviceContext.put("userLogin", userLogin);
1800
1801                // call the service
1802
Map JavaDoc refundResponse = null;
1803                try {
1804                    refundResponse = dispatcher.runSync(serviceName, serviceContext, TX_TIME, true);
1805                } catch (GenericServiceException e) {
1806                    Debug.logError(e, "Problem refunding payment through processor", module);
1807                    return ServiceUtil.returnError("Refund processor problems; see logs");
1808                }
1809                if (ServiceUtil.isError(refundResponse)) {
1810                    saveError(dispatcher, userLogin, paymentPref, refundResponse, "PRDS_PAY_REFUND", "PGT_REFUND");
1811                    return ServiceUtil.returnError(ServiceUtil.getErrorMessage(refundResponse));
1812                }
1813
1814                //Debug.log("Called Electronic Refund Service : " + refundResponse, module);
1815

1816                // get the pay-from party
1817
if (paymentConfig == null || paymentConfig.length() == 0) {
1818                    paymentConfig = "payment.properties";
1819                }
1820                String JavaDoc payFromPartyId = getPayToPartyId(orderHeader);
1821
1822                // create the PaymentGatewayResponse record
1823
String JavaDoc responseId = delegator.getNextSeqId("PaymentGatewayResponse");
1824                GenericValue response = delegator.makeValue("PaymentGatewayResponse", null);
1825                response.set("paymentGatewayResponseId", responseId);
1826                response.set("paymentServiceTypeEnumId", REFUND_SERVICE_TYPE);
1827                response.set("orderPaymentPreferenceId", paymentPref.get("orderPaymentPreferenceId"));
1828                response.set("paymentMethodTypeId", paymentPref.get("paymentMethodTypeId"));
1829                response.set("paymentMethodId", paymentPref.get("paymentMethodId"));
1830                response.set("transCodeEnumId", "PGT_REFUND");
1831
1832                // set the capture info
1833
response.set("amount", refundResponse.get("refundAmount"));
1834                response.set("referenceNum", refundResponse.get("refundRefNum"));
1835                response.set("altReference", refundResponse.get("refundAltRefNum"));
1836                response.set("gatewayCode", refundResponse.get("refundCode"));
1837                response.set("gatewayFlag", refundResponse.get("refundFlag"));
1838                response.set("gatewayMessage", refundResponse.get("refundMessage"));
1839                response.set("transactionDate", UtilDateTime.nowTimestamp());
1840                try {
1841                    delegator.create(response);
1842                } catch (GenericEntityException e) {
1843                    Debug.logError(e, module);
1844                    return ServiceUtil.returnError("Unable to create PaymentGatewayResponse record");
1845                }
1846
1847                // create the internal messages
1848
List JavaDoc messages = (List JavaDoc) refundResponse.get("internalRespMsgs");
1849                if (messages != null && messages.size() > 0) {
1850                    Iterator JavaDoc i = messages.iterator();
1851                    while (i.hasNext()) {
1852                        GenericValue respMsg = delegator.makeValue("PaymentGatewayRespMsg", null);
1853                        String JavaDoc respMsgId = delegator.getNextSeqId("PaymentGatewayRespMsg");
1854                        String JavaDoc message = (String JavaDoc) i.next();
1855                        respMsg.set("paymentGatewayRespMsgId", respMsgId);
1856                        respMsg.set("paymentGatewayResponseId", responseId);
1857                        respMsg.set("pgrMessage", message);
1858                        try {
1859                            delegator.create(respMsg);
1860                        } catch (GenericEntityException e) {
1861                            Debug.logError(e, module);
1862                            return ServiceUtil.returnError("Unable to create PaymentGatewayRespMsg record");
1863                        }
1864                    }
1865                }
1866
1867                // handle the (reverse) payment
1868
Boolean JavaDoc refundResult = (Boolean JavaDoc) refundResponse.get("refundResult");
1869                if (refundResult != null && refundResult.booleanValue()) {
1870                    // create a payment record
1871
Map JavaDoc paymentCtx = UtilMisc.toMap("paymentTypeId", "CUSTOMER_REFUND");
1872                    paymentCtx.put("paymentMethodTypeId", paymentPref.get("paymentMethodTypeId"));
1873                    paymentCtx.put("paymentMethodId", paymentPref.get("paymentMethodId"));
1874                    paymentCtx.put("paymentGatewayResponseId", responseId);
1875                    paymentCtx.put("partyIdTo", payToPartyId);
1876                    paymentCtx.put("partyIdFrom", payFromPartyId);
1877                    paymentCtx.put("statusId", "PMNT_SENT");
1878                    paymentCtx.put("paymentPreferenceId", paymentPref.get("orderPaymentPreferenceId"));
1879                    paymentCtx.put("currencyUomId", orh.getCurrency());
1880                    paymentCtx.put("amount", refundResponse.get("refundAmount"));
1881                    paymentCtx.put("userLogin", userLogin);
1882                    paymentCtx.put("paymentRefNum", refundResponse.get("refundRefNum"));
1883                    paymentCtx.put("comments", "Refund");
1884
1885                    String JavaDoc paymentId = null;
1886                    try {
1887                        Map JavaDoc payRes = dispatcher.runSync("createPayment", paymentCtx);
1888                        if (ModelService.RESPOND_ERROR.equals(payRes.get(ModelService.RESPONSE_MESSAGE))) {
1889                            return ServiceUtil.returnError((String JavaDoc) payRes.get(ModelService.ERROR_MESSAGE));
1890                        } else {
1891                            paymentId = (String JavaDoc) payRes.get("paymentId");
1892                        }
1893                    } catch (GenericServiceException e) {
1894                        Debug.logError(e, "Problem creating Payment", module);
1895                        return ServiceUtil.returnError("Problem creating Payment");
1896                    }
1897                    //Debug.log("Payment created : " + paymentId, module);
1898

1899                    if (paymentId == null) {
1900                        return ServiceUtil.returnError("Create payment failed");
1901                    }
1902
1903                    Map JavaDoc result = ServiceUtil.returnSuccess();
1904                    result.put("paymentId", paymentId);
1905                    return result;
1906                } else {
1907                    return ServiceUtil.returnError("The refund failed");
1908                }
1909            } else {
1910                return ServiceUtil.returnError("No refund service defined");
1911            }
1912        } else {
1913            return ServiceUtil.returnError("No payment settings found");
1914        }
1915    }
1916
1917    public static Map JavaDoc retryFailedOrderAuth(DispatchContext dctx, Map JavaDoc context) {
1918        GenericDelegator delegator = dctx.getDelegator();
1919        LocalDispatcher dispatcher = dctx.getDispatcher();
1920        String JavaDoc orderId = (String JavaDoc) context.get("orderId");
1921        GenericValue userLogin = (GenericValue) context.get("userLogin");
1922
1923        // get the order header
1924
GenericValue orderHeader = null;
1925        try {
1926            orderHeader = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap("orderId", orderId));
1927        } catch (GenericEntityException e) {
1928            Debug.logError(e, module);
1929            return ServiceUtil.returnError(e.getMessage());
1930        }
1931
1932        // make sure we have a valid order record
1933
if (orderHeader == null || orderHeader.get("statusId") == null) {
1934            return ServiceUtil.returnError("Invalid OrderHeader record for ID: " + orderId);
1935        }
1936
1937        // check the current order status
1938
if (!"ORDER_CREATED".equals(orderHeader.getString("statusId"))) {
1939            // if we are out of the created status; then we were either cancelled, rejected or approved
1940
return ServiceUtil.returnSuccess();
1941        }
1942
1943        // run the auth service and check for failure(s)
1944
Map JavaDoc serviceResult = null;
1945        try {
1946            serviceResult = dispatcher.runSync("authOrderPayments", UtilMisc.toMap("orderId", orderId, "userLogin", userLogin));
1947        } catch (GenericServiceException e) {
1948            Debug.logError(e, module);
1949            return ServiceUtil.returnError(e.getMessage());
1950        }
1951        if (ServiceUtil.isError(serviceResult)) {
1952            return ServiceUtil.returnError(ServiceUtil.getErrorMessage(serviceResult));
1953        }
1954
1955        // check to see if there was a processor failure
1956
String JavaDoc authResp = (String JavaDoc) serviceResult.get("processResult");
1957        if (authResp == null) {
1958            authResp = "ERROR";
1959        }
1960
1961        if ("ERROR".equals(authResp)) {
1962            Debug.logWarning("The payment processor had a failure in processing, will not modify any status", module);
1963        } else {
1964            if ("FAILED".equals(authResp)) {
1965                // declined; update the order status
1966
OrderChangeHelper.rejectOrder(dispatcher, userLogin, orderId);
1967
1968            } else if ("APPROVED".equals(authResp)) {
1969                // approved; update the order status
1970
OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId);
1971            }
1972        }
1973
1974        Map JavaDoc result = ServiceUtil.returnSuccess();
1975        result.put("processResult", authResp);
1976
1977        return result;
1978    }
1979
1980    public static Map JavaDoc retryFailedAuths(DispatchContext dctx, Map JavaDoc context) {
1981        GenericDelegator delegator = dctx.getDelegator();
1982        LocalDispatcher dispatcher = dctx.getDispatcher();
1983        GenericValue userLogin = (GenericValue) context.get("userLogin");
1984
1985        // get a list of all payment prefs still pending
1986
List JavaDoc exprs = UtilMisc.toList(new EntityExpr("statusId", EntityOperator.EQUALS, "PAYMENT_NOT_AUTH"),
1987                new EntityExpr("processAttempt", EntityOperator.GREATER_THAN, new Long JavaDoc(0)));
1988
1989        EntityListIterator eli = null;
1990        try {
1991            eli = delegator.findListIteratorByCondition("OrderPaymentPreference",
1992                    new EntityConditionList(exprs, EntityOperator.AND), null, UtilMisc.toList("orderId"));
1993        } catch (GenericEntityException e) {
1994            Debug.logError(e, module);
1995        }
1996
1997        List JavaDoc processList = new ArrayList JavaDoc();
1998        if (eli != null) {
1999            Debug.logInfo("Processing failed order re-auth(s)", module);
2000            GenericValue value;
2001            while (((value = (GenericValue) eli.next()) != null)) {
2002                String JavaDoc orderId = value.getString("orderId");
2003                if (!processList.contains(orderId)) { // just try each order once
2004
try {
2005                        // each re-try is independent of each other; if one fails it should not effect the others
2006
dispatcher.runAsync("retryFailedOrderAuth", UtilMisc.toMap("orderId", orderId, "userLogin", userLogin));
2007                        processList.add(orderId);
2008                    } catch (GenericServiceException e) {
2009                        Debug.logError(e, module);
2010                    }
2011                }
2012            }
2013
2014            try {
2015                eli.close();
2016            } catch (GenericEntityException e) {
2017                Debug.logError(e, module);
2018            }
2019        }
2020
2021        processList = null;
2022        return ServiceUtil.returnSuccess();
2023    }
2024
2025    public static GenericValue getCaptureTransaction(GenericValue orderPaymentPreference) {
2026        GenericValue capTrans = null;
2027        try {
2028            List JavaDoc order = UtilMisc.toList("-transactionDate");
2029            List JavaDoc transactions = orderPaymentPreference.getRelated("PaymentGatewayResponse", null, order);
2030
2031            List JavaDoc exprs = UtilMisc.toList(new EntityExpr("paymentServiceTypeEnumId", EntityOperator.EQUALS, "PRDS_PAY_CAPTURE"));
2032
2033            List JavaDoc capTransactions = EntityUtil.filterByAnd(transactions, exprs);
2034
2035            capTrans = EntityUtil.getFirst(capTransactions);
2036        } catch (GenericEntityException e) {
2037            Debug.logError(e, "ERROR: Problem getting capture information from PaymentGatewayResponse", module);
2038        }
2039        return capTrans;
2040    }
2041
2042    /**
2043     * Gets the chronologically latest PaymentGatewayResponse from an OrderPaymentPreference which is either a PRDS_PAY_AUTH
2044     * or PRDS_PAY_REAUTH. Used for capturing.
2045     * @param orderPaymentPreference
2046     * @return
2047     */

2048    public static GenericValue getAuthTransaction(GenericValue orderPaymentPreference) {
2049        GenericValue authTrans = null;
2050        try {
2051            List JavaDoc order = UtilMisc.toList("-transactionDate");
2052            List JavaDoc transactions = orderPaymentPreference.getRelated("PaymentGatewayResponse", null, order);
2053
2054            List JavaDoc exprs = UtilMisc.toList(new EntityExpr("paymentServiceTypeEnumId", EntityOperator.EQUALS, "PRDS_PAY_AUTH"),
2055                    new EntityExpr("paymentServiceTypeEnumId", EntityOperator.EQUALS, "PRDS_PAY_REAUTH"));
2056
2057            List JavaDoc authTransactions = EntityUtil.filterByOr(transactions, exprs);
2058
2059            authTrans = EntityUtil.getFirst(authTransactions);
2060        } catch (GenericEntityException e) {
2061            Debug.logError(e, "ERROR: Problem getting authorization information from PaymentGatewayResponse", module);
2062        }
2063        return authTrans;
2064    }
2065
2066    public static Timestamp JavaDoc getAuthTime(GenericValue orderPaymentPreference) {
2067        GenericValue authTrans = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
2068        Timestamp JavaDoc authTime = null;
2069
2070        if (authTrans != null) {
2071            authTime = authTrans.getTimestamp("transactionDate");
2072        }
2073
2074        return authTime;
2075    }
2076
2077    public static boolean checkAuthValidity(GenericValue orderPaymentPreference, String JavaDoc paymentConfig) {
2078        Timestamp JavaDoc authTime = PaymentGatewayServices.getAuthTime(orderPaymentPreference);
2079        if (authTime == null) {
2080            return false;
2081        }
2082
2083        GenericValue paymentMethod = null;
2084        try {
2085            paymentMethod = orderPaymentPreference.getRelatedOne("PaymentMethod");
2086        } catch (GenericEntityException e) {
2087            Debug.logError(e, module);
2088        }
2089
2090        if (paymentMethod != null && paymentMethod.getString("paymentMethodTypeId").equals("CREDIT_CARD")) {
2091            GenericValue creditCard = null;
2092            try {
2093                creditCard = paymentMethod.getRelatedOne("CreditCard");
2094            } catch (GenericEntityException e) {
2095                Debug.logError(e, module);
2096            }
2097            if (creditCard != null) {
2098                String JavaDoc cardType = creditCard.getString("cardType");
2099                String JavaDoc reauthDays = null;
2100                // add more types as necessary -- maybe we should create seed data for credit card types??
2101
if ("Discover".equals(cardType)) {
2102                    reauthDays = UtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.disc.days", "90");
2103                } else if ("AmericanExpress".equals(cardType)) {
2104                    reauthDays = UtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.amex.days", "30");
2105                } else if ("MasterCard".equals(cardType)) {
2106                    reauthDays = UtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.mc.days", "30");
2107                } else if ("Visa".equals(cardType)) {
2108                    reauthDays = UtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.visa.days", "7");
2109                } else {
2110                    reauthDays = UtilProperties.getPropertyValue(paymentConfig, "payment.general.reauth.other.days", "7");
2111                }
2112
2113                int days = 0;
2114                try {
2115                    days = Integer.parseInt(reauthDays);
2116                } catch (Exception JavaDoc e) {
2117                    Debug.logError(e, module);
2118                }
2119
2120                if (days > 0) {
2121                    Calendar JavaDoc cal = Calendar.getInstance();
2122                    cal.setTimeInMillis(authTime.getTime());
2123                    cal.add(Calendar.DAY_OF_YEAR, days);
2124                    Timestamp JavaDoc validTime = new Timestamp JavaDoc(cal.getTimeInMillis());
2125                    Timestamp JavaDoc nowTime = UtilDateTime.nowTimestamp();
2126                    if (nowTime.after(validTime)) {
2127                        return false;
2128                    }
2129                }
2130            }
2131        }
2132
2133        return true;
2134    }
2135
2136    // manual processing service
2137
public static Map JavaDoc processManualCcTx(DispatchContext dctx, Map JavaDoc context) {
2138        GenericValue userLogin = (GenericValue) context.get("userLogin");
2139        LocalDispatcher dispatcher = dctx.getDispatcher();
2140        GenericDelegator delegator = dctx.getDelegator();
2141        Security security = dctx.getSecurity();
2142
2143        // security check
2144
if (!security.hasEntityPermission("MANUAL", "_PAYMENT", userLogin)) {
2145            Debug.logWarning("**** Security [" + (new Date JavaDoc()).toString() + "]: " + userLogin.get("userLoginId") + " attempt to run manual payment transaction!", module);
2146            return ServiceUtil.returnError("You do not have permission for this transaction.");
2147        }
2148
2149        String JavaDoc paymentMethodTypeId = (String JavaDoc) context.get("paymentMethodTypeId");
2150        String JavaDoc productStoreId = (String JavaDoc) context.get("productStoreId");
2151        String JavaDoc transactionType = (String JavaDoc) context.get("transactionType");
2152        String JavaDoc referenceCode = (String JavaDoc) context.get("referenceCode");
2153        if (referenceCode == null) {
2154            referenceCode = new Long JavaDoc(System.currentTimeMillis()).toString();
2155        }
2156
2157        // check valid implemented types
2158
if (!transactionType.equals("PRDS_PAY_CREDIT")) {
2159            return ServiceUtil.returnError("This transaction type is not yet supported.");
2160        }
2161
2162        // transaction request context
2163
Map JavaDoc requestContext = new HashMap JavaDoc();
2164        String JavaDoc paymentService = null;
2165        String JavaDoc paymentConfig = null;
2166
2167        // get the transaction settings
2168
GenericValue paymentSettings = ProductStoreWorker.getProductStorePaymentSetting(delegator, productStoreId, paymentMethodTypeId, transactionType, false);
2169        if (paymentSettings == null) {
2170            return ServiceUtil.returnError("No valid payment settings found for : " + productStoreId + "/" + transactionType);
2171        } else {
2172            paymentConfig = paymentSettings.getString("paymentPropertiesPath");
2173            paymentService = paymentSettings.getString("paymentService");
2174            requestContext.put("paymentConfig", paymentConfig);
2175        }
2176
2177        // check the service name
2178
if (paymentService == null || paymentConfig == null) {
2179            return ServiceUtil.returnError("Invalid product store payment settings");
2180        }
2181
2182        if (paymentMethodTypeId.equals("CREDIT_CARD")) {
2183            GenericValue creditCard = delegator.makeValue("CreditCard", null);
2184            creditCard.setAllFields(context, true, null, null);
2185            if (creditCard.get("firstNameOnCard") == null || creditCard.get("lastNameOnCard") == null || creditCard.get("cardType") == null || creditCard.get("cardNumber") == null) {
2186                return ServiceUtil.returnError("Credit card is missing required fields.");
2187            }
2188            String JavaDoc expMonth = (String JavaDoc) context.get("expMonth");
2189            String JavaDoc expYear = (String JavaDoc) context.get("expYear");
2190            String JavaDoc expDate = expMonth + "/" + expYear;
2191            creditCard.set("expireDate", expDate);
2192            requestContext.put("creditCard", creditCard);
2193            requestContext.put("cardSecurityCode", context.get("cardSecurityCode"));
2194
2195            GenericValue billingAddress = delegator.makeValue("PostalAddress", null);
2196            billingAddress.setAllFields(context, true, null, null);
2197            if (billingAddress.get("address1") == null || billingAddress.get("city") == null || billingAddress.get("postalCode") == null) {
2198                return ServiceUtil.returnError("Credit card billing address is missing required fields.");
2199            }
2200            requestContext.put("billingAddress", billingAddress);
2201
2202            /* This is not needed any more, using names on CC as a kludge instead of these kludge names until we get a firstName/lastName on the shipping PostalAddress
2203            GenericValue contactPerson = delegator.makeValue("Person", null);
2204            contactPerson.setAllFields(context, true, null, null);
2205            if (contactPerson.get("firstName") == null || contactPerson.get("lastName") == null) {
2206                return ServiceUtil.returnError("Contact person is missing required fields.");
2207            }
2208            requestContext.put("contactPerson", contactPerson);
2209            */

2210
2211            GenericValue billToEmail = delegator.makeValue("ContactMech", null);
2212            billToEmail.set("infoString", context.get("infoString"));
2213            if (billToEmail.get("infoString") == null) {
2214                return ServiceUtil.returnError("Email address field cannot be empty.");
2215            }
2216            requestContext.put("billToEmail", billToEmail);
2217            requestContext.put("referenceCode", referenceCode);
2218            String JavaDoc currency = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD");
2219            requestContext.put("currency", currency);
2220            requestContext.put("creditAmount", context.get("amount")); // TODO fix me to work w/ other services
2221
} else {
2222            return ServiceUtil.returnError("Payment method type : " + paymentMethodTypeId + " is not yet implemented for manual transactions");
2223        }
2224
2225        // process the transaction
2226
Map JavaDoc response = null;
2227        try {
2228            response = dispatcher.runSync(paymentService, requestContext, TX_TIME, true);
2229        } catch (GenericServiceException e) {
2230            Debug.logError(e, module);
2231            return ServiceUtil.returnError("Error calling service : " + paymentService + " / " + requestContext);
2232        }
2233
2234        // check for errors
2235
if (ServiceUtil.isError(response)) {
2236            return ServiceUtil.returnError(ServiceUtil.makeErrorMessage(response, null, null, null, null));
2237        }
2238
2239        // get the reference number // TODO add support for other tx types
2240
String JavaDoc refNum = (String JavaDoc) response.get("creditRefNum");
2241        String JavaDoc code = (String JavaDoc) response.get("creditCode");
2242        String JavaDoc msg = (String JavaDoc) response.get("creditMessage");
2243        Map JavaDoc returnResults = ServiceUtil.returnSuccess("Transaction result [" + msg + "/" + code +"] Ref#: " + refNum);
2244        returnResults.put("referenceNum", refNum);
2245        return returnResults;
2246    }
2247
2248    // ****************************************************
2249
// Test Services
2250
// ****************************************************
2251

2252    /**
2253     * Simple test processor; declines all orders < 100.00; approves all orders > 100.00
2254     */

2255    public static Map JavaDoc testProcessor(DispatchContext dctx, Map JavaDoc context) {
2256        Map JavaDoc result = new HashMap JavaDoc();
2257        Double JavaDoc processAmount = (Double JavaDoc) context.get("processAmount");
2258
2259        if (processAmount != null && processAmount.doubleValue() >= 100.00)
2260            result.put("authResult", new Boolean JavaDoc(true));
2261        if (processAmount != null && processAmount.doubleValue() < 100.00)
2262            result.put("authResult", new Boolean JavaDoc(false));
2263            result.put("customerRespMsgs", UtilMisc.toList("Sorry this processor requires at least a $100.00 purchase."));
2264        if (processAmount == null)
2265            result.put("authResult", null);
2266
2267        long nowTime = new Date JavaDoc().getTime();
2268        String JavaDoc refNum = new Long JavaDoc(nowTime).toString();
2269
2270        result.put("processAmount", context.get("processAmount"));
2271        result.put("authRefNum", refNum);
2272        result.put("authAltRefNum", refNum);
2273        result.put("authFlag", "X");
2274        result.put("authMessage", "This is a test processor; no payments were captured or authorized.");
2275        result.put("internalRespMsgs", UtilMisc.toList("This is a test processor; no payments were captured or authorized."));
2276        return result;
2277    }
2278
2279    /**
2280     * Simple test processor; declines all orders < 100.00; approves all orders > 100.00
2281     */

2282    public static Map JavaDoc testProcessorWithCapture(DispatchContext dctx, Map JavaDoc context) {
2283        Map JavaDoc result = new HashMap JavaDoc();
2284        Double JavaDoc processAmount = (Double JavaDoc) context.get("processAmount");
2285
2286        if (processAmount != null && processAmount.doubleValue() >= 100.00)
2287            result.put("authResult", new Boolean JavaDoc(true));
2288            result.put("captureResult", new Boolean JavaDoc(true));
2289        if (processAmount != null && processAmount.doubleValue() < 100.00)
2290            result.put("authResult", new Boolean JavaDoc(false));
2291            result.put("captureResult", new Boolean JavaDoc(false));
2292            result.put("customerRespMsgs", UtilMisc.toList("Sorry this processor requires at least a $100.00 purchase."));
2293        if (processAmount == null)
2294            result.put("authResult", null);
2295
2296        long nowTime = new Date JavaDoc().getTime();
2297        String JavaDoc refNum = new Long JavaDoc(nowTime).toString();
2298
2299        result.put("processAmount", context.get("processAmount"));
2300        result.put("authRefNum", refNum);
2301        result.put("authAltRefNum", refNum);
2302        result.put("captureRefNum", refNum);
2303        result.put("captureAltRefNum", refNum);
2304        result.put("authCode", "100");
2305        result.put("captureCode", "200");
2306        result.put("authFlag", "X");
2307        result.put("authMessage", "This is a test processor; no payments were captured or authorized.");
2308        result.put("internalRespMsgs", UtilMisc.toList("This is a test processor; no payments were captured or authorized."));
2309        return result;
2310    }
2311
2312    /**
2313     * Always approve processor.
2314     */

2315    public static Map JavaDoc alwaysApproveProcessor(DispatchContext dctx, Map JavaDoc context) {
2316        Map JavaDoc result = new HashMap JavaDoc();
2317        long nowTime = new Date JavaDoc().getTime();
2318        Debug.logInfo("Test Processor Approving Credit Card", module);
2319
2320        result.put("authResult", new Boolean JavaDoc(true));
2321        result.put("processAmount", context.get("processAmount"));
2322        result.put("authRefNum", new Long JavaDoc(nowTime).toString());
2323        result.put("authAltRefNum", new Long JavaDoc(nowTime).toString());
2324        result.put("authCode", "100");
2325        result.put("authFlag", "A");
2326        result.put("authMessage", "This is a test processor; no payments were captured or authorized.");
2327        return result;
2328    }
2329
2330    public static Map JavaDoc alwaysApproveWithCapture(DispatchContext dctx, Map JavaDoc context) {
2331        Map JavaDoc result = new HashMap JavaDoc();
2332        long nowTime = new Date JavaDoc().getTime();
2333        String JavaDoc refNum = new Long JavaDoc(nowTime).toString();
2334        Debug.logInfo("Test Processor Approving Credit Card with Capture", module);
2335
2336        result.put("authResult", new Boolean JavaDoc(true));
2337        result.put("captureResult", new Boolean JavaDoc(true));
2338        result.put("processAmount", context.get("processAmount"));
2339        result.put("authRefNum", refNum);
2340        result.put("authAltRefNum", refNum);
2341        result.put("captureRefNum", refNum);
2342        result.put("captureAltRefNum", refNum);
2343        result.put("authCode", "100");
2344        result.put("captureCode", "200");
2345        result.put("authFlag", "A");
2346        result.put("authMessage", "This is a test processor; no payments were captured or authorized.");
2347        return result;
2348    }
2349
2350    /**
2351     * Always decline processor.
2352     */

2353    public static Map JavaDoc alwaysDeclineProcessor(DispatchContext dctx, Map JavaDoc context) {
2354        Map JavaDoc result = ServiceUtil.returnSuccess();
2355        Double JavaDoc processAmount = (Double JavaDoc) context.get("processAmount");
2356        long nowTime = new Date JavaDoc().getTime();
2357        Debug.logInfo("Test Processor Declining Credit Card", module);
2358
2359        result.put("authResult", new Boolean JavaDoc(false));
2360        result.put("processAmount", processAmount);
2361        result.put("authRefNum", new Long JavaDoc(nowTime).toString());
2362        result.put("authAltRefNum", new Long JavaDoc(nowTime).toString());
2363        result.put("authFlag", "D");
2364        result.put("authMessage", "This is a test processor; no payments were captured or authorized");
2365        return result;
2366    }
2367
2368    /**
2369     * Always fail (error) processor
2370     */

2371    public static Map JavaDoc alwaysFailProcessor(DispatchContext dctx, Map JavaDoc context) {
2372        return ServiceUtil.returnError("Unable to communicate with bla");
2373    }
2374
2375    public static Map JavaDoc testRelease(DispatchContext dctx, Map JavaDoc context) {
2376        Map JavaDoc result = ServiceUtil.returnSuccess();
2377        long nowTime = new Date JavaDoc().getTime();
2378
2379        result.put("releaseResult", new Boolean JavaDoc(true));
2380        result.put("releaseAmount", context.get("releaseAmount"));
2381        result.put("releaseRefNum", new Long JavaDoc(nowTime).toString());
2382        result.put("releaseAltRefNum", new Long JavaDoc(nowTime).toString());
2383        result.put("releaseFlag", "U");
2384        result.put("releaseMessage", "This is a test release; no authorizations exist");
2385        return result;
2386    }
2387
2388    /**
2389     * Test capture service (returns true)
2390     */

2391     public static Map JavaDoc testCapture(DispatchContext dctx, Map JavaDoc context) {
2392         Map JavaDoc result = ServiceUtil.returnSuccess();
2393         long nowTime = new Date JavaDoc().getTime();
2394            Debug.logInfo("Test Capture Process", module);
2395
2396         result.put("captureResult", new Boolean JavaDoc(true));
2397         result.put("captureAmount", context.get("captureAmount"));
2398         result.put("captureRefNum", new Long JavaDoc(nowTime).toString());
2399         result.put("captureAltRefNum", new Long JavaDoc(nowTime).toString());
2400         result.put("captureFlag", "C");
2401         result.put("captureMessage", "This is a test capture; no money was transferred");
2402         return result;
2403     }
2404
2405    public static Map JavaDoc testCaptureWithReAuth(DispatchContext dctx, Map JavaDoc context) {
2406        GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
2407        GenericValue authTransaction = (GenericValue) context.get("authTrans");
2408        Debug.logInfo("Test Capture with 2 minute delay failure/re-auth process", module);
2409
2410        if (authTransaction == null){
2411            authTransaction = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
2412        }
2413
2414        if (authTransaction == null) {
2415            return ServiceUtil.returnError("No authorization transaction found for the OrderPaymentPreference; cannot capture");
2416        }
2417        Timestamp JavaDoc txStamp = authTransaction.getTimestamp("transactionDate");
2418        Timestamp JavaDoc nowStamp = UtilDateTime.nowTimestamp();
2419
2420        Map JavaDoc result = ServiceUtil.returnSuccess();
2421        long nowTime = new Date JavaDoc().getTime();
2422        result.put("captureAmount", context.get("captureAmount"));
2423        result.put("captureRefNum", new Long JavaDoc(nowTime).toString());
2424
2425        Calendar JavaDoc cal = Calendar.getInstance();
2426        cal.setTimeInMillis(txStamp.getTime());
2427        cal.add(Calendar.MINUTE, 2);
2428        Timestamp JavaDoc twoMinAfter = new Timestamp JavaDoc(cal.getTimeInMillis());
2429        Debug.log("Re-Auth Capture Test : Tx Date - " + txStamp + " : 2 Min - " + twoMinAfter + " : Now - " + nowStamp, module);
2430
2431        if (nowStamp.after(twoMinAfter)) {
2432            result.put("captureResult", new Boolean JavaDoc(false));
2433        } else {
2434            result.put("captureResult", new Boolean JavaDoc(true));
2435            result.put("captureFlag", "C");
2436            result.put("captureMessage", "This is a test capture; no money was transferred");
2437        }
2438
2439        return result;
2440    }
2441
2442    /**
2443     * Test refund service (returns true)
2444     */

2445    public static Map JavaDoc testRefund(DispatchContext dctx, Map JavaDoc context) {
2446        Map JavaDoc result = ServiceUtil.returnSuccess();
2447        long nowTime = new Date JavaDoc().getTime();
2448        Debug.logInfo("Test Refund Process", module);
2449
2450        result.put("refundResult", new Boolean JavaDoc(true));
2451        result.put("refundAmount", context.get("refundAmount"));
2452        result.put("refundRefNum", new Long JavaDoc(nowTime).toString());
2453        result.put("refundFlag", "R");
2454        result.put("refundMessage", "This is a test refund; no money was transferred");
2455        return result;
2456    }
2457
2458    public static Map JavaDoc testRefundFailure(DispatchContext dctx, Map JavaDoc context) {
2459        Map JavaDoc result = ServiceUtil.returnSuccess();
2460        long nowTime = new Date JavaDoc().getTime();
2461        Debug.logInfo("Test Refund Process", module);
2462
2463        result.put("refundResult", new Boolean JavaDoc(false));
2464        result.put("refundAmount", context.get("refundAmount"));
2465        result.put("refundRefNum", new Long JavaDoc(nowTime).toString());
2466        result.put("refundFlag", "R");
2467        result.put("refundMessage", "This is a test refund failure; no money was transferred");
2468        return result;
2469    }
2470
2471}
2472
Popular Tags