0001: /*
0002: * $Id: PaymentGatewayServices.java,v 1.26 2004/01/22 17:47:24 ajzeneski Exp $
0003: *
0004: * Copyright (c) 2002 The Open For Business Project - www.ofbiz.org
0005: *
0006: * Permission is hereby granted, free of charge, to any person obtaining a
0007: * copy of this software and associated documentation files (the "Software"),
0008: * to deal in the Software without restriction, including without limitation
0009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0010: * and/or sell copies of the Software, and to permit persons to whom the
0011: * Software is furnished to do so, subject to the following conditions:
0012: *
0013: * The above copyright notice and this permission notice shall be included
0014: * in all copies or substantial portions of the Software.
0015: *
0016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
0019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
0020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
0021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
0022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0023: */
0024: package org.ofbiz.accounting.payment;
0025:
0026: import java.text.DecimalFormat;
0027: import java.text.ParseException;
0028: import java.util.ArrayList;
0029: import java.util.Collection;
0030: import java.util.Date;
0031: import java.util.HashMap;
0032: import java.util.Iterator;
0033: import java.util.List;
0034: import java.util.Map;
0035:
0036: import org.ofbiz.accounting.invoice.InvoiceWorker;
0037: import org.ofbiz.base.util.Debug;
0038: import org.ofbiz.base.util.GeneralException;
0039: import org.ofbiz.base.util.UtilDateTime;
0040: import org.ofbiz.base.util.UtilMisc;
0041: import org.ofbiz.base.util.UtilProperties;
0042: import org.ofbiz.base.util.UtilValidate;
0043: import org.ofbiz.entity.GenericDelegator;
0044: import org.ofbiz.entity.GenericEntityException;
0045: import org.ofbiz.entity.GenericValue;
0046: import org.ofbiz.entity.condition.EntityCondition;
0047: import org.ofbiz.entity.condition.EntityConditionList;
0048: import org.ofbiz.entity.condition.EntityExpr;
0049: import org.ofbiz.entity.condition.EntityJoinOperator;
0050: import org.ofbiz.entity.condition.EntityOperator;
0051: import org.ofbiz.entity.util.EntityUtil;
0052: import org.ofbiz.order.order.OrderReadHelper;
0053: import org.ofbiz.party.contact.ContactHelper;
0054: import org.ofbiz.product.store.ProductStoreWorker;
0055: import org.ofbiz.service.DispatchContext;
0056: import org.ofbiz.service.GenericServiceException;
0057: import org.ofbiz.service.LocalDispatcher;
0058: import org.ofbiz.service.ModelService;
0059: import org.ofbiz.service.ServiceUtil;
0060: import org.ofbiz.security.Security;
0061:
0062: /**
0063: * PaymentGatewayServices
0064: *
0065: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
0066: * @version $Revision: 1.26 $
0067: * @since 2.0
0068: */
0069: public class PaymentGatewayServices {
0070:
0071: public static final String module = PaymentGatewayServices.class
0072: .getName();
0073: public static final String AUTH_SERVICE_TYPE = "PRDS_PAY_AUTH";
0074: public static final String REAUTH_SERVICE_TYPE = "PRDS_PAY_REAUTH";
0075: public static final String RELEASE_SERVICE_TYPE = "PRDS_PAY_RELEASE";
0076: public static final String CAPTURE_SERVICE_TYPE = "PRDS_PAY_CAPTURE";
0077: public static final String REFUND_SERVICE_TYPE = "PRDS_PAY_REFUND";
0078: public static final String CREDIT_SERVICE_TYPE = "PRDS_PAY_CREDIT";
0079:
0080: /**
0081: * Processes payments through service calls to the defined processing service for the ProductStore/PaymentMethodType
0082: * @return APPROVED|FAILED|ERROR for complete processing of ALL payment methods.
0083: */
0084: public static Map authOrderPayments(DispatchContext dctx,
0085: Map context) {
0086: GenericDelegator delegator = dctx.getDelegator();
0087: LocalDispatcher dispatcher = dctx.getDispatcher();
0088: GenericValue userLogin = (GenericValue) context
0089: .get("userLogin");
0090: String orderId = (String) context.get("orderId");
0091: Map result = new HashMap();
0092:
0093: // get the order header and payment preferences
0094: GenericValue orderHeader = null;
0095: List paymentPrefs = null;
0096:
0097: try {
0098: // get the OrderHeader
0099: orderHeader = delegator.findByPrimaryKey("OrderHeader",
0100: UtilMisc.toMap("orderId", orderId));
0101:
0102: // get the payments to auth
0103: Map lookupMap = UtilMisc.toMap("orderId", orderId,
0104: "statusId", "PAYMENT_NOT_AUTH");
0105: List orderList = UtilMisc.toList("maxAmount");
0106: paymentPrefs = delegator.findByAnd(
0107: "OrderPaymentPreference", lookupMap, orderList);
0108: } catch (GenericEntityException gee) {
0109: Debug.logError(gee,
0110: "Problems getting the order information", module);
0111: result.put(ModelService.RESPONSE_MESSAGE,
0112: ModelService.RESPOND_ERROR);
0113: result.put(ModelService.ERROR_MESSAGE,
0114: "ERROR: Could not get order information ("
0115: + gee.getMessage() + ").");
0116: return result;
0117: }
0118:
0119: // make sure we have a OrderHeader
0120: if (orderHeader == null) {
0121: return ServiceUtil
0122: .returnError("Could not find OrderHeader with orderId: "
0123: + orderId + "; not processing payments.");
0124: }
0125:
0126: // get the order amounts
0127: String currencyFormat = UtilProperties.getPropertyValue(
0128: "general.properties", "currency.decimal.format",
0129: "##0.00");
0130: OrderReadHelper orh = new OrderReadHelper(orderHeader);
0131: DecimalFormat formatter = new DecimalFormat(currencyFormat);
0132: String grandTotalString = formatter.format(orh
0133: .getOrderGrandTotal());
0134: Double grandTotal = null;
0135: try {
0136: grandTotal = new Double(formatter.parse(grandTotalString)
0137: .doubleValue());
0138: } catch (ParseException e) {
0139: Debug
0140: .logError(
0141: e,
0142: "Problem getting parsed grand total amount",
0143: module);
0144: return ServiceUtil
0145: .returnError("ERROR: Cannot parse grand total from formatted string; see logs");
0146: }
0147:
0148: double totalRemaining = grandTotal.doubleValue();
0149:
0150: // loop through and auth each payment
0151: List finished = new ArrayList();
0152: List hadError = new ArrayList();
0153: Iterator payments = paymentPrefs.iterator();
0154: while (payments.hasNext()) {
0155: GenericValue paymentPref = (GenericValue) payments.next();
0156: boolean reAuth = false;
0157:
0158: // if we are already authorized, then this is a re-auth request
0159: if (paymentPref.get("statusId") != null
0160: && "PAYMENT_AUTHORIZED".equals(paymentPref
0161: .getString("statusId"))) {
0162: reAuth = true;
0163: }
0164:
0165: // check the maxAmount for 0.00
0166: Double maxAmount = paymentPref.getDouble("maxAmount");
0167: if (maxAmount == null || maxAmount.doubleValue() > 0) {
0168: // call the authPayment method
0169: Map processorResult = authPayment(dispatcher,
0170: userLogin, orh, paymentPref, totalRemaining,
0171: reAuth);
0172:
0173: // handle the response
0174: if (processorResult != null) {
0175: // not null result means either an approval or decline; null would mean error
0176: GenericValue paymentSettings = (GenericValue) processorResult
0177: .get("paymentSettings");
0178: Double this Amount = (Double) processorResult
0179: .get("processAmount");
0180:
0181: // process the auth results
0182: boolean processResult = false;
0183: try {
0184: processResult = processResult(dctx,
0185: processorResult, userLogin,
0186: paymentPref, paymentSettings);
0187: if (processResult) {
0188: totalRemaining -= this Amount.doubleValue();
0189: finished.add(processorResult);
0190: }
0191: } catch (GeneralException e) {
0192: Debug.logError(e,
0193: "Trouble processing the result; processorResult: "
0194: + processorResult, module);
0195: hadError.add(paymentPref);
0196: ServiceUtil
0197: .returnError("Trouble processing the auth results");
0198: }
0199: } else {
0200: // error with payment processor; will try later
0201: hadError.add(paymentPref);
0202: continue;
0203: }
0204: } else {
0205: Debug
0206: .logInfo(
0207: "Invalid OrderPaymentPreference; maxAmount is 0",
0208: module);
0209: paymentPref.set("statusId", "PAYMENT_CANCELLED");
0210: try {
0211: paymentPref.store();
0212: } catch (GenericEntityException e) {
0213: Debug
0214: .logError(
0215: e,
0216: "ERROR: Problem setting OrderPaymentPreference status to CANCELLED",
0217: module);
0218: }
0219: finished.add(null);
0220: }
0221: }
0222:
0223: Debug.logInfo("Finished with auth(s) checking results", module);
0224:
0225: if (hadError.size() > 0) {
0226: Debug.logError("Error(s) (" + hadError.size()
0227: + ") during auth; returning ERROR", module);
0228: result.put(ModelService.RESPONSE_MESSAGE,
0229: ModelService.RESPOND_SUCCESS);
0230: result.put("processResult", "ERROR");
0231: return result;
0232:
0233: } else if (finished.size() == paymentPrefs.size()) {
0234: Debug.logInfo("All auth(s) passed total remaining : "
0235: + totalRemaining, module);
0236: result.put(ModelService.RESPONSE_MESSAGE,
0237: ModelService.RESPOND_SUCCESS);
0238: result.put("processResult", "APPROVED");
0239: return result;
0240: } else {
0241: Debug.logInfo("Only (" + finished.size()
0242: + ") passed auth; returning FAILED", module);
0243: result.put(ModelService.RESPONSE_MESSAGE,
0244: ModelService.RESPOND_SUCCESS);
0245: result.put("processResult", "FAILED");
0246: return result;
0247: }
0248: }
0249:
0250: private static Map authPayment(LocalDispatcher dispatcher,
0251: GenericValue userLogin, OrderReadHelper orh,
0252: GenericValue paymentPref, double totalRemaining,
0253: boolean reauth) {
0254: String paymentConfig = null;
0255: String serviceName = null;
0256:
0257: // get the payment settings i.e. serviceName and config properties file name
0258: String serviceType = AUTH_SERVICE_TYPE;
0259: if (reauth) {
0260: serviceType = REAUTH_SERVICE_TYPE;
0261: }
0262:
0263: GenericValue paymentSettings = getPaymentSettings(orh
0264: .getOrderHeader(), paymentPref, serviceType, false);
0265: if (paymentSettings != null) {
0266: serviceName = paymentSettings.getString("paymentService");
0267: paymentConfig = paymentSettings
0268: .getString("paymentPropertiesPath");
0269: } else {
0270: Debug
0271: .logError(
0272: "Invalid payment settings entity, no payment settings found",
0273: module);
0274: return null;
0275: }
0276:
0277: // make sure the service name is not null
0278: if (serviceName == null) {
0279: Debug.logError("Invalid payment processor: + "
0280: + paymentSettings, module);
0281: return null;
0282: }
0283:
0284: // get the process context
0285: Map processContext = null;
0286: try {
0287: processContext = makeAuthContext(orh, userLogin,
0288: paymentPref, paymentConfig, totalRemaining);
0289: } catch (GeneralException e) {
0290: Debug
0291: .logError(
0292: e,
0293: "Problems creating the context for the auth service",
0294: module);
0295: return null;
0296: }
0297:
0298: // the amount of this transaction
0299: Double this Amount = (Double) processContext
0300: .get("processAmount");
0301:
0302: // invoke the processor.
0303: Map processorResult = null;
0304: try {
0305: processorResult = dispatcher.runSync(serviceName,
0306: processContext);
0307: } catch (GenericServiceException gse) {
0308: Debug.logError("Error occurred on: " + serviceName + " => "
0309: + processContext, module);
0310: Debug.logError(gse,
0311: "Problems invoking payment processor! Will retry later."
0312: + "(" + orh.getOrderId() + ")", module);
0313: return null;
0314: }
0315:
0316: if (processorResult != null) {
0317: // check for errors from the processor implementation
0318: String resultResponseCode = (String) processorResult
0319: .get(ModelService.RESPONSE_MESSAGE);
0320: if (resultResponseCode != null
0321: && resultResponseCode
0322: .equals(ModelService.RESPOND_ERROR)) {
0323: Debug.logError("Processor failed; will retry later : "
0324: + processorResult
0325: .get(ModelService.ERROR_MESSAGE),
0326: module);
0327: return null;
0328: }
0329:
0330: // pass the payTo partyId to the result processor; we just add it to the result context.
0331: String payToPartyId = getPayToPartyId(orh.getOrderHeader());
0332: processorResult.put("payToPartyId", payToPartyId);
0333:
0334: // add paymentSettings to result; for use by later processors
0335: processorResult.put("paymentSettings", paymentSettings);
0336: }
0337:
0338: return processorResult;
0339: }
0340:
0341: private static GenericValue getPaymentSettings(
0342: GenericValue orderHeader, GenericValue paymentPreference,
0343: String paymentServiceType, boolean anyServiceType) {
0344: GenericDelegator delegator = orderHeader.getDelegator();
0345: GenericValue paymentSettings = null;
0346: GenericValue paymentMethod = null;
0347: try {
0348: paymentMethod = paymentPreference
0349: .getRelatedOne("PaymentMethod");
0350: } catch (GenericEntityException e) {
0351: Debug
0352: .logError(
0353: e,
0354: "Problem getting PaymentMethod from OrderPaymentPreference",
0355: module);
0356: }
0357: if (paymentMethod != null) {
0358: String productStoreId = orderHeader
0359: .getString("productStoreId");
0360: String paymentMethodTypeId = paymentMethod
0361: .getString("paymentMethodTypeId");
0362: if (productStoreId != null && paymentMethodTypeId != null) {
0363: paymentSettings = ProductStoreWorker
0364: .getProductStorePaymentSetting(delegator,
0365: productStoreId, paymentMethodTypeId,
0366: paymentServiceType, anyServiceType);
0367: }
0368: }
0369: return paymentSettings;
0370: }
0371:
0372: private static String getPayToPartyId(GenericValue orderHeader) {
0373: String payToPartyId = "Company"; // default value
0374: GenericValue productStore = null;
0375: try {
0376: productStore = orderHeader.getRelatedOne("ProductStore");
0377: } catch (GenericEntityException e) {
0378: Debug.logError(e,
0379: "Unable to get ProductStore from OrderHeader",
0380: module);
0381: return null;
0382: }
0383: if (productStore != null
0384: && productStore.get("payToPartyId") != null) {
0385: payToPartyId = productStore.getString("payToPartyId");
0386: }
0387: return payToPartyId;
0388: }
0389:
0390: private static Map makeAuthContext(OrderReadHelper orh,
0391: GenericValue userLogin, GenericValue paymentPreference,
0392: String paymentConfig, double totalRemaining)
0393: throws GeneralException {
0394: Map processContext = new HashMap();
0395:
0396: processContext.put("userLogin", userLogin);
0397: processContext.put("orderId", orh.getOrderId());
0398: processContext.put("orderItems", orh.getOrderItems());
0399: processContext.put("shippingAddress", orh.getShippingAddress());
0400: processContext.put("paymentConfig", paymentConfig);
0401: processContext.put("currency", orh.getCurrency());
0402: processContext.put("orderPaymentPreference", paymentPreference);
0403:
0404: // get the billing information
0405: getBillingInformation(orh, paymentPreference, processContext);
0406:
0407: // get the process amount
0408: double this Amount = totalRemaining;
0409: if (paymentPreference.get("maxAmount") != null) {
0410: this Amount = paymentPreference.getDouble("maxAmount")
0411: .doubleValue();
0412: }
0413:
0414: // don't authorized more then what is required
0415: if (this Amount > totalRemaining) {
0416: this Amount = totalRemaining;
0417: }
0418:
0419: // format the decimal
0420: String currencyFormat = UtilProperties.getPropertyValue(
0421: "general.properties", "currency.decimal.format",
0422: "##0.00");
0423: DecimalFormat formatter = new DecimalFormat(currencyFormat);
0424: String amountString = formatter.format(this Amount);
0425: Double processAmount = null;
0426: try {
0427: processAmount = new Double(formatter.parse(amountString)
0428: .doubleValue());
0429: } catch (ParseException e) {
0430: Debug
0431: .logError(
0432: e,
0433: "Problems parsing string formatted double to Double",
0434: module);
0435: throw new GeneralException(
0436: "ParseException in number format", e);
0437: }
0438:
0439: if (Debug.verboseOn())
0440: Debug.logVerbose("Charging amount: " + processAmount,
0441: module);
0442: processContext.put("processAmount", processAmount);
0443:
0444: return processContext;
0445: }
0446:
0447: private static String getBillingInformation(OrderReadHelper orh,
0448: GenericValue paymentPreference, Map toContext)
0449: throws GenericEntityException {
0450: // gather the payment related objects.
0451: GenericValue paymentMethod = paymentPreference
0452: .getRelatedOne("PaymentMethod");
0453: if (paymentMethod != null
0454: && paymentMethod.getString("paymentMethodTypeId")
0455: .equals("CREDIT_CARD")) {
0456: // type credit card
0457: GenericValue creditCard = paymentMethod
0458: .getRelatedOne("CreditCard");
0459: GenericValue billingAddress = creditCard
0460: .getRelatedOne("PostalAddress");
0461: toContext.put("creditCard", creditCard);
0462: toContext.put("billingAddress", billingAddress);
0463: } else if (paymentMethod != null
0464: && paymentMethod.getString("paymentMethodTypeId")
0465: .equals("EFT_ACCOUNT")) {
0466: // type eft
0467: GenericValue eftAccount = paymentMethod
0468: .getRelatedOne("EftAccount");
0469: GenericValue billingAddress = eftAccount
0470: .getRelatedOne("PostalAddress");
0471: toContext.put("eftAccount", eftAccount);
0472: toContext.put("billingAddress", billingAddress);
0473: } else if (paymentMethod != null
0474: && paymentMethod.getString("paymentMethodTypeId")
0475: .equals("GIFT_CARD")) {
0476: // type gift card
0477: GenericValue giftCard = paymentMethod
0478: .getRelatedOne("GiftCard");
0479: toContext.put("giftCard", giftCard);
0480: } else {
0481: // add other payment types here; i.e. gift cards, etc.
0482: // unknown payment type; ignoring.
0483: Debug
0484: .logError(
0485: "ERROR: Unsupported PaymentMethodType passed for authorization",
0486: module);
0487: return null;
0488: }
0489:
0490: // get some contact info.
0491: GenericValue contactPerson = orh.getBillToPerson();
0492: GenericValue contactEmail = null;
0493: Collection emails = null;
0494:
0495: try {
0496: emails = ContactHelper.getContactMech(contactPerson
0497: .getRelatedOne("Party"), "PRIMARY_EMAIL",
0498: "EMAIL_ADDRESS", false);
0499: } catch (GenericEntityException gee) {
0500: Debug.logError("Problems getting contact information: "
0501: + gee.getMessage(), module);
0502: }
0503: if (emails != null && emails.size() > 0)
0504: contactEmail = (GenericValue) emails.iterator().next();
0505:
0506: toContext.put("contactPerson", contactPerson);
0507: toContext.put("contactEmail", contactEmail);
0508:
0509: return contactPerson.getString("partyId");
0510: }
0511:
0512: /**
0513: *
0514: * Releases authorizations through service calls to the defined processing service for the ProductStore/PaymentMethodType
0515: * @return COMPLETE|FAILED|ERROR for complete processing of ALL payments.
0516: */
0517: public static Map releaseOrderPayments(DispatchContext dctx,
0518: Map context) {
0519: GenericDelegator delegator = dctx.getDelegator();
0520: LocalDispatcher dispatcher = dctx.getDispatcher();
0521: GenericValue userLogin = (GenericValue) context
0522: .get("userLogin");
0523: String orderId = (String) context.get("orderId");
0524:
0525: Map result = new HashMap();
0526:
0527: // get the order header and payment preferences
0528: GenericValue orderHeader = null;
0529: List paymentPrefs = null;
0530:
0531: try {
0532: // first get the order header
0533: orderHeader = delegator.findByPrimaryKey("OrderHeader",
0534: UtilMisc.toMap("orderId", orderId));
0535: // get the valid payment prefs
0536: List othExpr = UtilMisc.toList(new EntityExpr(
0537: "paymentMethodTypeId", EntityOperator.EQUALS,
0538: "EFT_ACCOUNT"));
0539: othExpr.add(new EntityExpr("paymentMethodTypeId",
0540: EntityOperator.EQUALS, "GIFT_CARD"));
0541: EntityCondition con1 = new EntityConditionList(othExpr,
0542: EntityJoinOperator.OR);
0543:
0544: EntityCondition statExpr = new EntityExpr("statusId",
0545: EntityOperator.EQUALS, "PAYMENT_SETTLED");
0546: EntityCondition con2 = new EntityConditionList(UtilMisc
0547: .toList(con1, statExpr), EntityOperator.AND);
0548:
0549: EntityCondition authExpr = new EntityExpr("statusId",
0550: EntityOperator.EQUALS, "PAYMENT_AUTHORIZED");
0551: EntityCondition con3 = new EntityConditionList(UtilMisc
0552: .toList(con2, authExpr), EntityOperator.OR);
0553:
0554: EntityExpr orderExpr = new EntityExpr("orderId",
0555: EntityOperator.EQUALS, orderId);
0556: EntityCondition con4 = new EntityConditionList(UtilMisc
0557: .toList(con3, orderExpr), EntityOperator.AND);
0558:
0559: paymentPrefs = delegator.findByCondition(
0560: "OrderPaymentPreference", con4, null, null);
0561: } catch (GenericEntityException gee) {
0562: Debug
0563: .logError(
0564: gee,
0565: "Problems getting entity record(s), see stack trace",
0566: module);
0567: result.put(ModelService.RESPONSE_MESSAGE,
0568: ModelService.RESPOND_ERROR);
0569: result.put(ModelService.ERROR_MESSAGE,
0570: "ERROR: Could not get order information ("
0571: + gee.getMessage() + ").");
0572: return result;
0573: }
0574:
0575: // error if no order was found
0576: if (orderHeader == null) {
0577: return ServiceUtil
0578: .returnError("Could not find OrderHeader with orderId: "
0579: + orderId + "; not processing payments.");
0580: }
0581:
0582: // return complete if no payment prefs were found
0583: if (paymentPrefs == null || paymentPrefs.size() == 0) {
0584: Debug
0585: .logWarning(
0586: "No OrderPaymentPreference records available for release",
0587: module);
0588: result.put("processResult", "COMPLETE");
0589: result.put(ModelService.RESPONSE_MESSAGE,
0590: ModelService.RESPOND_SUCCESS);
0591: return result;
0592: }
0593:
0594: OrderReadHelper orh = new OrderReadHelper(orderHeader);
0595: String currency = orh.getCurrency();
0596:
0597: // iterate over the prefs and release each one
0598: List finished = new ArrayList();
0599: Iterator payments = paymentPrefs.iterator();
0600: while (payments.hasNext()) {
0601: GenericValue paymentPref = (GenericValue) payments.next();
0602:
0603: // look up the payment configuration settings
0604: String serviceName = null;
0605: String paymentConfig = null;
0606:
0607: // get the payment settings i.e. serviceName and config properties file name
0608: GenericValue paymentSettings = getPaymentSettings(orh
0609: .getOrderHeader(), paymentPref,
0610: RELEASE_SERVICE_TYPE, false);
0611: if (paymentSettings != null) {
0612: paymentConfig = paymentSettings
0613: .getString("paymentPropertiesPath");
0614: serviceName = paymentSettings
0615: .getString("paymentService");
0616: if (serviceName == null) {
0617: Debug.logError(
0618: "Service name is null for payment setting; cannot process for : "
0619: + paymentPref, module);
0620: }
0621: } else {
0622: Debug.logError(
0623: "Invalid payment settings entity, no payment release settings found for : "
0624: + paymentPref, module);
0625: continue; // no release service available -- has been logged
0626: }
0627:
0628: if (paymentConfig == null || paymentConfig.length() == 0) {
0629: paymentConfig = "payment.properties";
0630: }
0631:
0632: GenericValue authTransaction = PaymentGatewayServices
0633: .getAuthTransaction(paymentPref);
0634: Map releaseContext = new HashMap();
0635: releaseContext.put("orderPaymentPreference", paymentPref);
0636: releaseContext.put("releaseAmount", authTransaction
0637: .getDouble("amount"));
0638: releaseContext.put("currency", currency);
0639: releaseContext.put("paymentConfig", paymentConfig);
0640: releaseContext.put("userLogin", userLogin);
0641:
0642: // run the defined service
0643: Map releaseResult = null;
0644: try {
0645: releaseResult = dispatcher.runSync(serviceName,
0646: releaseContext);
0647: } catch (GenericServiceException e) {
0648: Debug.logError(e, "Problem releasing payment", module);
0649: }
0650:
0651: // get the release result code
0652: Boolean releaseResponse = (Boolean) releaseResult
0653: .get("releaseResult");
0654:
0655: // create the PaymentGatewayResponse
0656: String responseId = delegator.getNextSeqId(
0657: "PaymentGatewayResponse").toString();
0658: GenericValue pgResponse = delegator.makeValue(
0659: "PaymentGatewayResponse", null);
0660: pgResponse.set("paymentGatewayResponseId", responseId);
0661: pgResponse.set("paymentServiceTypeEnumId",
0662: RELEASE_SERVICE_TYPE);
0663: pgResponse.set("orderPaymentPreferenceId", paymentPref
0664: .get("orderPaymentPreferenceId"));
0665: pgResponse.set("paymentMethodTypeId", paymentPref
0666: .get("paymentMethodTypeId"));
0667: pgResponse.set("paymentMethodId", paymentPref
0668: .get("paymentMethodId"));
0669:
0670: // set the auth info
0671: pgResponse.set("referenceNum", releaseResult
0672: .get("releaseRefNum"));
0673: pgResponse.set("gatewayCode", releaseResult
0674: .get("releaseCode"));
0675: pgResponse.set("gatewayFlag", releaseResult
0676: .get("releaseFlag"));
0677: pgResponse.set("gatewayMessage", releaseResult
0678: .get("releaseMessage"));
0679: pgResponse.set("transactionDate", UtilDateTime
0680: .nowTimestamp());
0681:
0682: // store the gateway response
0683: try {
0684: pgResponse.create();
0685: } catch (GenericEntityException e) {
0686: Debug.logError(e,
0687: "Problem storing PaymentGatewayResponse entity; authorization was released! : "
0688: + pgResponse, module);
0689: }
0690:
0691: if (releaseResponse != null
0692: && releaseResponse.booleanValue()) {
0693: paymentPref.set("statusId", "PAYMENT_CANCELLED");
0694: try {
0695: paymentPref.store();
0696: } catch (GenericEntityException e) {
0697: Debug
0698: .logError(
0699: e,
0700: "Problem storing updated payment preference; authorization was released!",
0701: module);
0702: }
0703: finished.add(paymentPref);
0704:
0705: // cancel any payment records
0706: List paymentList = null;
0707: try {
0708: paymentList = paymentPref.getRelated("Payment");
0709: } catch (GenericEntityException e) {
0710: Debug.logError(e,
0711: "Unable to get Payment records from OrderPaymentPreference : "
0712: + paymentPref, module);
0713: }
0714:
0715: if (paymentList != null) {
0716: Iterator pi = paymentList.iterator();
0717: while (pi.hasNext()) {
0718: GenericValue pay = (GenericValue) pi.next();
0719: pay.set("statusId", "PMNT_CANCELLED");
0720: try {
0721: pay.store();
0722: } catch (GenericEntityException e) {
0723: Debug.logError(e,
0724: "Unable to store Payment : " + pay,
0725: module);
0726: }
0727: }
0728: }
0729: } else {
0730: Debug.logError("Release failed for pref : "
0731: + paymentPref, module);
0732: }
0733: }
0734:
0735: result = ServiceUtil.returnSuccess();
0736: if (finished.size() == paymentPrefs.size()) {
0737: result.put("processResult", "COMPLETE");
0738: } else {
0739: result.put("processResult", "FAILED");
0740: }
0741:
0742: return result;
0743: }
0744:
0745: /**
0746: * Captures payments through service calls to the defined processing service for the ProductStore/PaymentMethodType
0747: * @return COMPLETE|FAILED|ERROR for complete processing of ALL payment methods.
0748: */
0749: public static Map capturePaymentsByInvoice(DispatchContext dctx,
0750: Map context) {
0751: GenericDelegator delegator = dctx.getDelegator();
0752: LocalDispatcher dispatcher = dctx.getDispatcher();
0753: GenericValue userLogin = (GenericValue) context
0754: .get("userLogin");
0755: String invoiceId = (String) context.get("invoiceId");
0756:
0757: // lookup the invoice
0758: GenericValue invoice = null;
0759: try {
0760: invoice = delegator.findByPrimaryKey("Invoice", UtilMisc
0761: .toMap("invoiceId", invoiceId));
0762: } catch (GenericEntityException e) {
0763: Debug.logError(e, "Trouble looking up Invoice #"
0764: + invoiceId, module);
0765: return ServiceUtil
0766: .returnError("Trouble looking up Invoice #"
0767: + invoiceId);
0768: }
0769:
0770: if (invoice == null) {
0771: Debug.logError("Could not locate invoice #" + invoiceId,
0772: module);
0773: return ServiceUtil.returnError("Could not locate invoice #"
0774: + invoiceId);
0775: }
0776:
0777: // get the OrderItemBilling records for this invoice
0778: List orderItemBillings = null;
0779: try {
0780: orderItemBillings = invoice.getRelated("OrderItemBilling");
0781: } catch (GenericEntityException e) {
0782: Debug.logError(
0783: "Trouble getting OrderItemBilling(s) from Invoice #"
0784: + invoiceId, module);
0785: return ServiceUtil
0786: .returnError("Trouble getting OrderItemBilling(s) from Invoice #"
0787: + invoiceId);
0788: }
0789:
0790: // check for an associated billing account
0791: String billingAccountId = invoice.getString("billingAccountId");
0792:
0793: // make sure they are all for the same order
0794: String testOrderId = null;
0795: boolean allSameOrder = true;
0796: if (orderItemBillings != null) {
0797: Iterator oii = orderItemBillings.iterator();
0798: while (oii.hasNext()) {
0799: GenericValue oib = (GenericValue) oii.next();
0800: String orderId = oib.getString("orderId");
0801: if (testOrderId == null) {
0802: testOrderId = orderId;
0803: } else {
0804: if (!orderId.equals(testOrderId)) {
0805: allSameOrder = false;
0806: break;
0807: }
0808: }
0809: }
0810: }
0811:
0812: if (testOrderId == null || !allSameOrder) {
0813: Debug.logWarning("Attempt to settle Invoice #" + invoiceId
0814: + " which contained none/multiple orders", module);
0815: return ServiceUtil.returnSuccess();
0816: }
0817:
0818: // get the invoice amount (amount to bill)
0819: double invoiceTotal = InvoiceWorker.getInvoiceTotal(invoice);
0820: //Debug.logInfo("Invoice total: " + invoiceTotal, module);
0821:
0822: // now capture the order
0823: Map serviceContext = UtilMisc.toMap("userLogin", userLogin,
0824: "orderId", testOrderId, "invoiceId", invoiceId,
0825: "captureAmount", new Double(invoiceTotal));
0826: if (UtilValidate.isNotEmpty(billingAccountId)) {
0827: serviceContext.put("billingAccountId", billingAccountId);
0828: }
0829: try {
0830: return dispatcher.runSync("captureOrderPayments",
0831: serviceContext);
0832: } catch (GenericServiceException e) {
0833: Debug.logError(e,
0834: "Trouble running captureOrderPayments service",
0835: module);
0836: return ServiceUtil
0837: .returnError("Trouble running captureOrderPayments service");
0838: }
0839: }
0840:
0841: /**
0842: * Captures payments through service calls to the defined processing service for the ProductStore/PaymentMethodType
0843: * @return COMPLETE|FAILED|ERROR for complete processing of ALL payment methods.
0844: */
0845: public static Map captureOrderPayments(DispatchContext dctx,
0846: Map context) {
0847: GenericDelegator delegator = dctx.getDelegator();
0848: LocalDispatcher dispatcher = dctx.getDispatcher();
0849: GenericValue userLogin = (GenericValue) context
0850: .get("userLogin");
0851: String orderId = (String) context.get("orderId");
0852: String invoiceId = (String) context.get("invoiceId");
0853: String billingAccountId = (String) context
0854: .get("billingAccountId");
0855: Double captureAmount = (Double) context.get("captureAmount");
0856:
0857: Map result = new HashMap();
0858:
0859: // get the order header and payment preferences
0860: GenericValue orderHeader = null;
0861: List paymentPrefs = null;
0862:
0863: try {
0864: orderHeader = delegator.findByPrimaryKey("OrderHeader",
0865: UtilMisc.toMap("orderId", orderId));
0866:
0867: // get the payment prefs
0868: Map lookupMap = UtilMisc.toMap("orderId", orderId,
0869: "statusId", "PAYMENT_AUTHORIZED");
0870: List orderList = UtilMisc.toList("-authAmount");
0871: paymentPrefs = delegator.findByAnd(
0872: "OrderPaymentPreference", lookupMap, orderList);
0873: } catch (GenericEntityException gee) {
0874: Debug
0875: .logError(
0876: gee,
0877: "Problems getting entity record(s), see stack trace",
0878: module);
0879: result.put(ModelService.RESPONSE_MESSAGE,
0880: ModelService.RESPOND_ERROR);
0881: result.put(ModelService.ERROR_MESSAGE,
0882: "ERROR: Could not get order information ("
0883: + gee.getMessage() + ").");
0884: return result;
0885: }
0886:
0887: // error if no order was found
0888: if (orderHeader == null) {
0889: return ServiceUtil
0890: .returnError("Could not find OrderHeader with orderId: "
0891: + orderId + "; not processing payments.");
0892: }
0893:
0894: // return complete if no payment prefs were found
0895: if (paymentPrefs == null || paymentPrefs.size() == 0) {
0896: Debug.logWarning(
0897: "No orderPaymentPreferences available to capture",
0898: module);
0899: result.put("processResult", "COMPLETE");
0900: result.put(ModelService.RESPONSE_MESSAGE,
0901: ModelService.RESPOND_SUCCESS);
0902: return result;
0903: }
0904:
0905: OrderReadHelper orh = new OrderReadHelper(orderHeader);
0906: double orderTotal = orh.getOrderGrandTotal();
0907: double totalPayments = PaymentWorker.getPaymentsTotal(orh
0908: .getOrderPayments());
0909: double remainingTotal = orderTotal - totalPayments;
0910: Debug.logInfo("Remaining Total: " + remainingTotal, module);
0911:
0912: // re-format the remaining total
0913: String currencyFormat = UtilProperties.getPropertyValue(
0914: "general.properties", "currency.decimal.format",
0915: "##0.00");
0916: DecimalFormat formatter = new DecimalFormat(currencyFormat);
0917: String remainingTotalString = formatter.format(remainingTotal);
0918: try {
0919: Number remaining = formatter.parse(remainingTotalString);
0920: if (remaining != null) {
0921: remainingTotal = remaining.doubleValue();
0922: }
0923: } catch (ParseException e) {
0924: Debug.logError(e, "Problem getting parsed remaining total",
0925: module);
0926: return ServiceUtil
0927: .returnError("ERROR: Cannot parse grand total from formatted string; see logs");
0928: }
0929:
0930: if (captureAmount == null) {
0931: captureAmount = new Double(remainingTotal);
0932: }
0933: //Debug.logInfo("Formatted Remaining total : " + remainingTotal, module);
0934:
0935: double amountToCapture = captureAmount.doubleValue();
0936: //Debug.logInfo("Expected Capture Amount : " + amountToCapture, module);
0937:
0938: // if we have a billing account get balance/limit and available
0939: GenericValue billingAccount = null;
0940: Double billingAccountBalance = null;
0941: Double billingAccountAvail = null;
0942: Map billingAccountInfo = null;
0943: if (UtilValidate.isNotEmpty(billingAccountId)) {
0944: try {
0945: billingAccountInfo = dispatcher.runSync(
0946: "calcBillingAccountBalance", UtilMisc.toMap(
0947: "billingAccountId", billingAccountId));
0948: } catch (GenericServiceException e) {
0949: Debug.logError(e,
0950: "Unable to get billing account information for #"
0951: + billingAccountId, module);
0952: }
0953: }
0954: if (billingAccountInfo != null) {
0955: billingAccount = (GenericValue) billingAccountInfo
0956: .get("billingAccount");
0957: billingAccountBalance = (Double) billingAccountInfo
0958: .get("accountBalance");
0959: }
0960: if (billingAccount != null && billingAccountBalance != null) {
0961: Double accountLimit = billingAccount
0962: .getDouble("accountLimit");
0963: if (accountLimit == null) {
0964: accountLimit = new Double(0.00);
0965: }
0966: billingAccountAvail = new Double(accountLimit.doubleValue()
0967: - billingAccountBalance.doubleValue());
0968: }
0969:
0970: // iterate over the prefs and capture each one until we meet our total
0971: List finished = new ArrayList();
0972: Iterator payments = paymentPrefs.iterator();
0973: while (payments.hasNext()) {
0974: GenericValue paymentPref = (GenericValue) payments.next();
0975: GenericValue authTrans = getAuthTransaction(paymentPref);
0976: if (authTrans == null) {
0977: continue;
0978: }
0979:
0980: Double authAmount = authTrans.getDouble("amount");
0981: if (authAmount == null)
0982: authAmount = new Double(0.00);
0983: if (authAmount.doubleValue() == 0.00) {
0984: // nothing to capture
0985: Debug.logInfo("Nothing to capture; authAmount = 0",
0986: module);
0987: continue;
0988: }
0989: //Debug.log("Actual Auth amount : " + authAmount, module);
0990:
0991: // if the authAmount is more then the remaining total; just use remaining total
0992: if (authAmount.doubleValue() > remainingTotal) {
0993: authAmount = new Double(remainingTotal);
0994: }
0995:
0996: // if we have a billing account; total up auth + account available
0997: double amountToBillAccount = 0.00;
0998: if (billingAccountAvail != null) {
0999: amountToBillAccount = authAmount.doubleValue()
1000: + billingAccountAvail.doubleValue();
1001: }
1002:
1003: // the amount for *this* capture
1004: double amountThisCapture = 0.00;
1005:
1006: // determine how much for *this* capture
1007: if (authAmount.doubleValue() >= amountToCapture) {
1008: // if the auth amount is more then expected capture just capture what is expected
1009: amountThisCapture = amountToCapture;
1010: } else if (payments.hasNext()) {
1011: // if we have more payments to capture; just capture what was authorized
1012: amountThisCapture = authAmount.doubleValue();
1013: } else if (billingAccountAvail != null
1014: && amountToBillAccount >= amountToCapture) {
1015: // the provided billing account will cover the remaining; just capture what was autorized
1016: amountThisCapture = authAmount.doubleValue();
1017: } else {
1018: // we need to capture more then what was authorized; re-auth for the new amount
1019: // TODO: add what the billing account cannot support to the re-auth amount
1020: // TODO: add support for re-auth for additional funds
1021: // just in case; we will capture the authorized amount here; until this is implemented
1022: Debug
1023: .logError(
1024: "The amount to capture was more then what was authorized; we only captured the authorized amount : "
1025: + paymentPref, module);
1026: amountThisCapture = authAmount.doubleValue();
1027: }
1028:
1029: Map captureResult = capturePayment(dispatcher, userLogin,
1030: orh, paymentPref, amountThisCapture);
1031: if (captureResult != null) {
1032: GenericValue paymentSettings = (GenericValue) captureResult
1033: .get("paymentSettings");
1034: Double amountCaptured = (Double) captureResult
1035: .get("captureAmount");
1036: if (amountCaptured != null)
1037: amountToCapture -= amountCaptured.doubleValue();
1038: finished.add(captureResult);
1039:
1040: // add the invoiceId to the result for processing
1041: captureResult.put("invoiceId", invoiceId);
1042:
1043: //Debug.log("Capture result : " + captureResult, module);
1044:
1045: // process the capture's results
1046: boolean processResult = false;
1047: try {
1048: processResult = processResult(dctx, captureResult,
1049: userLogin, paymentPref, paymentSettings);
1050: } catch (GeneralException e) {
1051: Debug.logError(e,
1052: "Trouble processing the result; captureResult: "
1053: + captureResult, module);
1054: ServiceUtil
1055: .returnError("Trouble processing the capture results");
1056: }
1057:
1058: // create any splits which are needed
1059: if (authAmount.doubleValue() > amountThisCapture) {
1060: // create a new payment preference and authorize it
1061: Debug.logInfo("Creating payment preference split",
1062: module);
1063: double newAmount = authAmount.doubleValue()
1064: - amountThisCapture;
1065: String newPrefId = delegator.getNextSeqId(
1066: "OrderPaymentPreference").toString();
1067: GenericValue newPref = delegator.makeValue(
1068: "OrderPaymentPreference", UtilMisc.toMap(
1069: "orderPaymentPreferenceId",
1070: newPrefId));
1071: newPref.set("orderId", paymentPref.get("orderId"));
1072: newPref.set("paymentMethodTypeId", paymentPref
1073: .get("paymentMethodTypeId"));
1074: newPref.set("paymentMethodId", paymentPref
1075: .get("paymentMethodId"));
1076: newPref.set("maxAmount", paymentPref
1077: .get("maxAmount"));
1078: newPref.set("statusId", "PAYMENT_NOT_AUTH");
1079: Debug
1080: .logInfo("New preference : " + newPref,
1081: module);
1082: try {
1083: // create the new payment preference
1084: delegator.create(newPref);
1085:
1086: // authorize the new preference
1087: Map processorResult = authPayment(dispatcher,
1088: userLogin, orh, newPref, newAmount,
1089: false);
1090: if (processorResult != null) {
1091: GenericValue pSetting = (GenericValue) processorResult
1092: .get("paymentSettings");
1093: Double this Amount = (Double) processorResult
1094: .get("processAmount");
1095:
1096: // process the auth results
1097: boolean authResult = false;
1098: try {
1099: authResult = processResult(dctx,
1100: processorResult, userLogin,
1101: newPref, pSetting);
1102: if (!authResult) {
1103: Debug.logError(
1104: "Authorization failed : "
1105: + newPref + " : "
1106: + processorResult,
1107: module);
1108: }
1109: } catch (GeneralException e) {
1110: Debug.logError(e,
1111: "Trouble processing the auth result : "
1112: + newPref + " : "
1113: + processorResult,
1114: module);
1115: }
1116: } else {
1117: Debug.logError(
1118: "Payment not authorized : "
1119: + newPref + " : "
1120: + processorResult, module);
1121: }
1122: } catch (GenericEntityException e) {
1123: Debug.logError(e,
1124: "ERROR: cannot create new payment preference : "
1125: + newPref, module);
1126: }
1127: }
1128: } else {
1129: Debug.logError("Payment not captured", module);
1130: continue;
1131: }
1132: }
1133:
1134: if (amountToCapture > 0.00) {
1135: result.put(ModelService.RESPONSE_MESSAGE,
1136: ModelService.RESPOND_SUCCESS);
1137: result.put("processResult", "FAILED");
1138: return result;
1139: } else {
1140: result.put(ModelService.RESPONSE_MESSAGE,
1141: ModelService.RESPOND_SUCCESS);
1142: result.put("processResult", "COMPLETE");
1143: return result;
1144: }
1145: }
1146:
1147: private static Map capturePayment(LocalDispatcher dispatcher,
1148: GenericValue userLogin, OrderReadHelper orh,
1149: GenericValue paymentPref, double amount) {
1150: // look up the payment configuration settings
1151: String serviceName = null;
1152: String paymentConfig = null;
1153:
1154: // get the payment settings i.e. serviceName and config properties file name
1155: GenericValue paymentSettings = getPaymentSettings(orh
1156: .getOrderHeader(), paymentPref, CAPTURE_SERVICE_TYPE,
1157: false);
1158: if (paymentSettings != null) {
1159: paymentConfig = paymentSettings
1160: .getString("paymentPropertiesPath");
1161: serviceName = paymentSettings.getString("paymentService");
1162: if (serviceName == null) {
1163: Debug
1164: .logError(
1165: "Service name is null for payment setting; cannot process",
1166: module);
1167: return null;
1168: }
1169: } else {
1170: Debug
1171: .logError(
1172: "Invalid payment settings entity, no payment settings found",
1173: module);
1174: return null;
1175: }
1176:
1177: if (paymentConfig == null || paymentConfig.length() == 0) {
1178: paymentConfig = "payment.properties";
1179: }
1180:
1181: // prepare the context for the capture service (must follow the ccCaptureInterface
1182: Map captureContext = new HashMap();
1183: captureContext.put("userLogin", userLogin);
1184: captureContext.put("orderPaymentPreference", paymentPref);
1185: captureContext.put("paymentConfig", paymentConfig);
1186: captureContext.put("captureAmount", new Double(amount));
1187: captureContext.put("currency", orh.getCurrency());
1188:
1189: Debug.logInfo("Capture [" + serviceName + "] : "
1190: + captureContext, module);
1191:
1192: // now invoke the capture service
1193: Map captureResult = null;
1194: try {
1195: captureResult = dispatcher.runSync(serviceName,
1196: captureContext);
1197: } catch (GenericServiceException e) {
1198: Debug.logError(e,
1199: "Could not capture payment ... serviceName: "
1200: + serviceName + " ... context: "
1201: + captureContext, module);
1202: return null;
1203: }
1204:
1205: // pass the payTo partyId to the result processor; we just add it to the result context.
1206: String payToPartyId = getPayToPartyId(orh.getOrderHeader());
1207: captureResult.put("payToPartyId", payToPartyId);
1208:
1209: // add paymentSettings to result; for use by later processors
1210: captureResult.put("paymentSettings", paymentSettings);
1211:
1212: return captureResult;
1213: }
1214:
1215: private static boolean processResult(DispatchContext dctx,
1216: Map result, GenericValue userLogin,
1217: GenericValue paymentPreference, GenericValue paymentSettings)
1218: throws GeneralException {
1219: Boolean authResult = (Boolean) result.get("authResult");
1220: Boolean captureResult = (Boolean) result.get("captureResult");
1221: boolean resultPassed = false;
1222: boolean fromAuth = false;
1223:
1224: if (authResult != null) {
1225: processAuthResult(dctx, result, userLogin,
1226: paymentPreference, paymentSettings);
1227: resultPassed = authResult.booleanValue();
1228: fromAuth = true;
1229: }
1230: if (captureResult != null) {
1231: processCaptureResult(dctx, result, userLogin,
1232: paymentPreference, paymentSettings, fromAuth);
1233: if (!resultPassed)
1234: resultPassed = captureResult.booleanValue();
1235: }
1236: return resultPassed;
1237: }
1238:
1239: private static void processAuthResult(DispatchContext dctx,
1240: Map result, GenericValue userLogin,
1241: GenericValue paymentPreference, GenericValue paymentSettings)
1242: throws GeneralException {
1243: Boolean authResult = (Boolean) result.get("authResult");
1244: GenericDelegator delegator = paymentPreference.getDelegator();
1245:
1246: // type of auth this was can be determined by the previous status
1247: String authType = paymentPreference.getString("statusId")
1248: .equals("PAYMENT_NOT_AUTH") ? AUTH_SERVICE_TYPE
1249: : REAUTH_SERVICE_TYPE;
1250:
1251: // create the PaymentGatewayResponse
1252: String responseId = delegator.getNextSeqId(
1253: "PaymentGatewayResponse").toString();
1254: GenericValue response = delegator.makeValue(
1255: "PaymentGatewayResponse", null);
1256: response.set("paymentGatewayResponseId", responseId);
1257: response.set("paymentServiceTypeEnumId", authType);
1258: response.set("orderPaymentPreferenceId", paymentPreference
1259: .get("orderPaymentPreferenceId"));
1260: response.set("paymentMethodTypeId", paymentPreference
1261: .get("paymentMethodTypeId"));
1262: response.set("paymentMethodId", paymentPreference
1263: .get("paymentMethodId"));
1264:
1265: // set the avs/fraud result
1266: response.set("gatewayAvsResult", result.get("avsCode"));
1267: response.set("gatewayScoreResult", result.get("scoreCode"));
1268:
1269: // set the auth info
1270: response.set("amount", result.get("processAmount"));
1271: response.set("referenceNum", result.get("authRefNum"));
1272: response.set("gatewayCode", result.get("authCode"));
1273: response.set("gatewayFlag", result.get("authFlag"));
1274: response.set("gatewayMessage", result.get("authMessage"));
1275: response.set("transactionDate", UtilDateTime.nowTimestamp());
1276: delegator.create(response);
1277:
1278: if (response.getDouble("amount").doubleValue() != ((Double) result
1279: .get("processAmount")).doubleValue()) {
1280: Debug.logWarning(
1281: "The authorized amount does not match the max amount : Response - "
1282: + response + " : result - " + result,
1283: module);
1284: }
1285:
1286: // set the status of the OrderPaymentPreference
1287: if (result != null && authResult.booleanValue()) {
1288: paymentPreference.set("statusId", "PAYMENT_AUTHORIZED");
1289: } else if (result != null && !authResult.booleanValue()) {
1290: paymentPreference.set("statusId", "PAYMENT_DECLINED");
1291: } else {
1292: paymentPreference.set("statusId", "PAYMENT_ERROR");
1293: }
1294: paymentPreference.store();
1295: }
1296:
1297: private static void processCaptureResult(DispatchContext dctx,
1298: Map result, GenericValue userLogin,
1299: GenericValue paymentPreference, GenericValue paymentSettings)
1300: throws GeneralException {
1301: processCaptureResult(dctx, result, userLogin,
1302: paymentPreference, paymentSettings, false);
1303: }
1304:
1305: private static void processCaptureResult(DispatchContext dctx,
1306: Map result, GenericValue userLogin,
1307: GenericValue paymentPreference,
1308: GenericValue paymentSettings, boolean fromAuth)
1309: throws GeneralException {
1310: Boolean captureResult = (Boolean) result.get("captureResult");
1311: String invoiceId = (String) result.get("invoiceId");
1312: String payTo = (String) result.get("payToPartyId");
1313: GenericDelegator delegator = dctx.getDelegator();
1314: LocalDispatcher dispatcher = dctx.getDispatcher();
1315: Double amount = null;
1316: if (result.get("captureAmount") != null) {
1317: amount = (Double) result.get("captureAmount");
1318: } else if (result.get("processAmount") != null) {
1319: amount = (Double) result.get("processAmount");
1320: }
1321:
1322: if (amount == null) {
1323: throw new GeneralException(
1324: "Unable to process null capture amount");
1325: }
1326:
1327: Debug.logInfo("Invoice ID: " + invoiceId, module);
1328:
1329: if (payTo == null)
1330: payTo = "Company";
1331:
1332: String serviceType = fromAuth ? "AUTH" : CAPTURE_SERVICE_TYPE;
1333: if (serviceType.equals("AUTH")) {
1334: serviceType = paymentPreference.getString("statusId")
1335: .equals("PAYMENT_NOT_AUTH") ? AUTH_SERVICE_TYPE
1336: : REAUTH_SERVICE_TYPE;
1337: }
1338:
1339: if (result != null && captureResult.booleanValue()) {
1340: // create the PaymentGatewayResponse record
1341: String responseId = delegator.getNextSeqId(
1342: "PaymentGatewayResponse").toString();
1343: GenericValue response = delegator.makeValue(
1344: "PaymentGatewayResponse", null);
1345: response.set("paymentGatewayResponseId", responseId);
1346: response.set("paymentServiceTypeEnumId", serviceType);
1347: response.set("orderPaymentPreferenceId", paymentPreference
1348: .get("orderPaymentPreferenceId"));
1349: response.set("paymentMethodTypeId", paymentPreference
1350: .get("paymentMethodTypeId"));
1351: response.set("paymentMethodId", paymentPreference
1352: .get("paymentMethodId"));
1353: if (result.get("authRefNum") != null) {
1354: response.set("subReference", result.get("authRefNum"));
1355: }
1356:
1357: // set the capture info
1358: response.set("amount", amount);
1359: response.set("referenceNum", result.get("captureRefNum"));
1360: response.set("gatewayCode", result.get("captureCode"));
1361: response.set("gatewayFlag", result.get("captureFlag"));
1362: response
1363: .set("gatewayMessage", result.get("captureMessage"));
1364: response
1365: .set("transactionDate", UtilDateTime.nowTimestamp());
1366: delegator.create(response);
1367:
1368: String orderId = paymentPreference.getString("orderId");
1369: GenericValue orderRole = EntityUtil
1370: .getFirst(delegator.findByAnd("OrderRole", UtilMisc
1371: .toMap("orderId", orderId, "roleTypeId",
1372: "BILL_TO_CUSTOMER")));
1373:
1374: Map paymentCtx = UtilMisc.toMap("paymentTypeId", "RECEIPT");
1375: paymentCtx.put("paymentMethodTypeId", paymentPreference
1376: .get("paymentMethodTypeId"));
1377: paymentCtx.put("paymentMethodId", paymentPreference
1378: .get("paymentMethodId"));
1379: paymentCtx.put("paymentGatewayResponseId", responseId);
1380: paymentCtx.put("partyIdTo", payTo);
1381: paymentCtx.put("partyIdFrom", orderRole.get("partyId"));
1382: paymentCtx.put("statusId", "PMNT_RECEIVED");
1383: paymentCtx.put("paymentPreferenceId", paymentPreference
1384: .get("orderPaymentPreferenceId"));
1385: paymentCtx.put("amount", amount);
1386: paymentCtx.put("userLogin", userLogin);
1387: paymentCtx
1388: .put("paymentRefNum", result.get("captureRefNum"));
1389:
1390: Map payRes = dispatcher
1391: .runSync("createPayment", paymentCtx);
1392: String paymentId = (String) payRes.get("paymentId");
1393:
1394: paymentPreference.set("statusId", "PAYMENT_SETTLED");
1395: paymentPreference.store();
1396:
1397: // create the PaymentApplication if invoiceId is available
1398: if (invoiceId != null) {
1399: Debug.logInfo("Processing Invoice #" + invoiceId,
1400: module);
1401: Map paCtx = UtilMisc.toMap("paymentId", paymentId,
1402: "invoiceId", invoiceId);
1403: paCtx.put("amountApplied", result.get("captureAmount"));
1404: paCtx.put("userLogin", userLogin);
1405: Map paRes = dispatcher.runSync(
1406: "createPaymentApplication", paCtx);
1407: }
1408: } else if (result != null && !captureResult.booleanValue()) {
1409: // problem with the capture lets get some needed info
1410: OrderReadHelper orh = null;
1411: try {
1412: GenericValue orderHeader = paymentPreference
1413: .getRelatedOne("OrderHeader");
1414: if (orderHeader != null)
1415: orh = new OrderReadHelper(orderHeader);
1416: } catch (GenericEntityException e) {
1417: Debug
1418: .logError(
1419: e,
1420: "Problems getting OrderHeader; cannot re-auth the payment",
1421: module);
1422: }
1423:
1424: if (orh != null) {
1425: // first lets re-auth the card
1426: Map authPayRes = authPayment(dispatcher, userLogin,
1427: orh, paymentPreference, amount.doubleValue(),
1428: true);
1429: if (authPayRes != null) {
1430: Boolean authResp = (Boolean) result
1431: .get("authResult");
1432: Boolean capResp = (Boolean) result
1433: .get("captureResult");
1434: if (authResp != null) {
1435: processAuthResult(dctx, authPayRes, userLogin,
1436: paymentPreference, paymentSettings);
1437: if (authResp.booleanValue()) {
1438: // first make sure we didn't already capture - probably not
1439: if (capResp != null
1440: && capResp.booleanValue()) {
1441: processCaptureResult(dctx, result,
1442: userLogin, paymentPreference,
1443: paymentSettings);
1444: } else {
1445: // lets try to capture the funds now
1446: Map capPayRes = capturePayment(
1447: dispatcher, userLogin, orh,
1448: paymentPreference, amount
1449: .doubleValue());
1450: if (capPayRes != null) {
1451: Boolean capPayResp = (Boolean) result
1452: .get("captureResult");
1453: if (capPayResp != null
1454: && capPayResp
1455: .booleanValue()) {
1456: // it was successful
1457: processCaptureResult(dctx,
1458: result, userLogin,
1459: paymentPreference,
1460: paymentSettings);
1461: } else {
1462: // not successful; log it
1463: Debug
1464: .logError(
1465: "Capture of authorized payment failed: "
1466: + paymentPreference,
1467: module);
1468: }
1469: } else {
1470: Debug
1471: .logError(
1472: "Problems trying to capture payment (null result): "
1473: + paymentPreference,
1474: module);
1475: }
1476: }
1477: } else {
1478: Debug
1479: .logError(
1480: "Payment authorization failed: "
1481: + paymentPreference,
1482: module);
1483: }
1484: } else {
1485: Debug.logError(
1486: "Payment authorization failed (null result): "
1487: + paymentPreference, module);
1488: }
1489: } else {
1490: Debug.logError(
1491: "Problems trying to re-authorize the payment (null result): "
1492: + paymentPreference, module);
1493: }
1494: } else {
1495: Debug.logError("Null OrderReadHelper cannot process",
1496: module);
1497: }
1498: } else {
1499: Debug.logError("Result pass is null, no capture available",
1500: module);
1501: }
1502: }
1503:
1504: public static Map refundPayment(DispatchContext dctx, Map context) {
1505: GenericDelegator delegator = dctx.getDelegator();
1506: LocalDispatcher dispatcher = dctx.getDispatcher();
1507: GenericValue userLogin = (GenericValue) context
1508: .get("userLogin");
1509:
1510: GenericValue paymentPref = (GenericValue) context
1511: .get("orderPaymentPreference");
1512: Double refundAmount = (Double) context.get("refundAmount");
1513:
1514: GenericValue orderHeader = null;
1515: try {
1516: orderHeader = paymentPref.getRelatedOne("OrderHeader");
1517: } catch (GenericEntityException e) {
1518: Debug
1519: .logError(
1520: e,
1521: "Cannot get OrderHeader from OrderPaymentPreference",
1522: module);
1523: return ServiceUtil
1524: .returnError("Problems getting OrderHeader from OrderPaymentPreference: "
1525: + e.getMessage());
1526: }
1527:
1528: OrderReadHelper orh = new OrderReadHelper(orderHeader);
1529:
1530: GenericValue paymentSettings = null;
1531: if (orderHeader != null) {
1532: paymentSettings = getPaymentSettings(orderHeader,
1533: paymentPref, REFUND_SERVICE_TYPE, false);
1534: }
1535:
1536: if (paymentSettings != null) {
1537: String paymentConfig = paymentSettings
1538: .getString("paymentPropertiesPath");
1539: String serviceName = paymentSettings
1540: .getString("paymentService");
1541: if (serviceName != null) {
1542: Map serviceContext = new HashMap();
1543: serviceContext.put("orderPaymentPreference",
1544: paymentPref);
1545: serviceContext.put("paymentConfig", paymentConfig);
1546: serviceContext.put("currency", orh.getCurrency());
1547:
1548: // get the creditCard/address/email
1549: String payToPartyId = null;
1550: try {
1551: payToPartyId = getBillingInformation(orh,
1552: paymentPref, new HashMap());
1553: } catch (GenericEntityException e) {
1554: Debug.logError(e,
1555: "Problems getting billing information",
1556: module);
1557: return ServiceUtil
1558: .returnError("Problems getting billing information");
1559: }
1560:
1561: // format the price
1562: String currencyFormat = UtilProperties
1563: .getPropertyValue("general.properties",
1564: "currency.decimal.format", "##0.00");
1565: DecimalFormat formatter = new DecimalFormat(
1566: currencyFormat);
1567: String amountString = formatter.format(refundAmount);
1568: Double processAmount = null;
1569: try {
1570: processAmount = new Double(formatter.parse(
1571: amountString).doubleValue());
1572: } catch (ParseException e) {
1573: Debug
1574: .logError(
1575: e,
1576: "Problem parsing amount using DecimalFormat",
1577: module);
1578: return ServiceUtil
1579: .returnError("Refund processor problems; see logs");
1580: }
1581: serviceContext.put("refundAmount", processAmount);
1582: serviceContext.put("userLogin", userLogin);
1583:
1584: // call the service
1585: Map refundResponse = null;
1586: try {
1587: refundResponse = dispatcher.runSync(serviceName,
1588: serviceContext);
1589: } catch (GenericServiceException e) {
1590: Debug
1591: .logError(
1592: e,
1593: "Problem refunding payment through processor",
1594: module);
1595: return ServiceUtil
1596: .returnError("Refund processor problems; see logs");
1597: }
1598:
1599: //Debug.log("Called Electronic Refund Service : " + refundResponse, module);
1600:
1601: // get the pay-from party
1602: if (paymentConfig == null
1603: || paymentConfig.length() == 0) {
1604: paymentConfig = "payment.properties";
1605: }
1606: String payFromPartyId = getPayToPartyId(orderHeader);
1607:
1608: // create the PaymentGatewayResponse record
1609: String responseId = delegator.getNextSeqId(
1610: "PaymentGatewayResponse").toString();
1611: GenericValue response = delegator.makeValue(
1612: "PaymentGatewayResponse", null);
1613: response.set("paymentGatewayResponseId", responseId);
1614: response.set("paymentServiceTypeEnumId",
1615: REFUND_SERVICE_TYPE);
1616: response.set("orderPaymentPreferenceId", paymentPref
1617: .get("orderPaymentPreferenceId"));
1618: response.set("paymentMethodTypeId", paymentPref
1619: .get("paymentMethodTypeId"));
1620: response.set("paymentMethodId", paymentPref
1621: .get("paymentMethodId"));
1622:
1623: // set the capture info
1624: response.set("amount", refundResponse
1625: .get("refundAmount"));
1626: response.set("referenceNum", refundResponse
1627: .get("refundRefNum"));
1628: response.set("gatewayCode", refundResponse
1629: .get("refundCode"));
1630: response.set("gatewayFlag", refundResponse
1631: .get("refundFlag"));
1632: response.set("gatewayMessage", refundResponse
1633: .get("refundMessage"));
1634: response.set("transactionDate", UtilDateTime
1635: .nowTimestamp());
1636: try {
1637: delegator.create(response);
1638: } catch (GenericEntityException e) {
1639: Debug.logError(e, module);
1640: return ServiceUtil
1641: .returnError("Unable to create PaymentGatewayResponse record");
1642: }
1643:
1644: // handle the (reverse) payment
1645: Boolean refundResult = (Boolean) refundResponse
1646: .get("refundResult");
1647: if (refundResult != null && refundResult.booleanValue()) {
1648: // create a payment record
1649: Map paymentCtx = UtilMisc.toMap("paymentTypeId",
1650: "DISBURSEMENT");
1651: paymentCtx.put("paymentMethodTypeId", paymentPref
1652: .get("paymentMethodTypeId"));
1653: paymentCtx.put("paymentMethodId", paymentPref
1654: .get("paymentMethodId"));
1655: paymentCtx.put("paymentGatewayResponseId",
1656: responseId);
1657: paymentCtx.put("partyIdTo", payToPartyId);
1658: paymentCtx.put("partyIdFrom", payFromPartyId);
1659: paymentCtx.put("statusId", "PMNT_SENT");
1660: paymentCtx.put("paymentPreferenceId", paymentPref
1661: .get("orderPaymentPreferenceId"));
1662: paymentCtx.put("amount", refundResponse
1663: .get("refundAmount"));
1664: paymentCtx.put("userLogin", userLogin);
1665: paymentCtx.put("paymentRefNum", refundResponse
1666: .get("refundRefNum"));
1667: paymentCtx.put("comments", "Refund");
1668:
1669: String paymentId = null;
1670: try {
1671: Map payRes = dispatcher.runSync(
1672: "createPayment", paymentCtx);
1673: if (ModelService.RESPOND_ERROR.equals(payRes
1674: .get(ModelService.RESPONSE_MESSAGE))) {
1675: return ServiceUtil
1676: .returnError((String) payRes
1677: .get(ModelService.ERROR_MESSAGE));
1678: } else {
1679: paymentId = (String) payRes
1680: .get("paymentId");
1681: }
1682: } catch (GenericServiceException e) {
1683: Debug.logError(e, "Problem creating Payment",
1684: module);
1685: return ServiceUtil
1686: .returnError("Problem creating Payment");
1687: }
1688: //Debug.log("Payment created : " + paymentId, module);
1689:
1690: if (paymentId == null) {
1691: return ServiceUtil
1692: .returnError("Create payment failed");
1693: }
1694:
1695: Map result = ServiceUtil.returnSuccess();
1696: result.put("paymentId", "10000");
1697: return result;
1698: } else {
1699: return ServiceUtil.returnError("The refund failed");
1700: }
1701: } else {
1702: return ServiceUtil
1703: .returnError("No refund service defined");
1704: }
1705: } else {
1706: return ServiceUtil.returnError("No payment settings found");
1707: }
1708: }
1709:
1710: public static Map retryFailedAuths(DispatchContext dctx, Map context) {
1711: return ServiceUtil.returnError("Service not yet implemented");
1712: }
1713:
1714: public static GenericValue getAuthTransaction(
1715: GenericValue orderPaymentPreference) {
1716: GenericValue authTrans = null;
1717: try {
1718: List order = UtilMisc.toList("transactionDate");
1719: List transactions = orderPaymentPreference.getRelated(
1720: "PaymentGatewayResponse", null, order);
1721:
1722: List exprs = UtilMisc.toList(new EntityExpr(
1723: "paymentServiceTypeEnumId", EntityOperator.EQUALS,
1724: "PRDS_PAY_AUTH"), new EntityExpr(
1725: "paymentServiceTypeEnumId", EntityOperator.EQUALS,
1726: "PRDS_PAY_REAUTH"));
1727:
1728: List authTransactions = EntityUtil.filterByOr(transactions,
1729: exprs);
1730: authTrans = EntityUtil.getFirst(authTransactions);
1731: } catch (GenericEntityException e) {
1732: Debug
1733: .logError(
1734: e,
1735: "ERROR: Problem getting authorization information from PaymentGatewayResponse",
1736: module);
1737: }
1738: return authTrans;
1739: }
1740:
1741: // manual processing service
1742: public static Map processManualCcTx(DispatchContext dctx,
1743: Map context) {
1744: GenericValue userLogin = (GenericValue) context
1745: .get("userLogin");
1746: LocalDispatcher dispatcher = dctx.getDispatcher();
1747: GenericDelegator delegator = dctx.getDelegator();
1748: Security security = dctx.getSecurity();
1749:
1750: // security check
1751: if (!security.hasEntityPermission("MANUAL", "_PAYMENT",
1752: userLogin)) {
1753: Debug.logWarning("**** Security ["
1754: + (new Date()).toString() + "]: "
1755: + userLogin.get("userLoginId")
1756: + " attempt to run manual payment transaction!",
1757: module);
1758: return ServiceUtil
1759: .returnError("You do not have permission for this transaction.");
1760: }
1761:
1762: String paymentMethodTypeId = (String) context
1763: .get("paymentMethodTypeId");
1764: String productStoreId = (String) context.get("productStoreId");
1765: String transactionType = (String) context
1766: .get("transactionType");
1767: String referenceCode = (String) context.get("referenceCode");
1768: if (referenceCode == null) {
1769: referenceCode = new Long(System.currentTimeMillis())
1770: .toString();
1771: }
1772:
1773: // check valid implemented types
1774: if (!transactionType.equals("PRDS_PAY_CREDIT")) {
1775: return ServiceUtil
1776: .returnError("This transaction type is not yet supported.");
1777: }
1778:
1779: // transaction request context
1780: Map requestContext = new HashMap();
1781: String paymentService = null;
1782: String paymentConfig = null;
1783:
1784: // get the transaction settings
1785: GenericValue paymentSettings = ProductStoreWorker
1786: .getProductStorePaymentSetting(delegator,
1787: productStoreId, paymentMethodTypeId,
1788: transactionType, false);
1789: if (paymentSettings == null) {
1790: return ServiceUtil
1791: .returnError("No valid payment settings found for : "
1792: + productStoreId + "/" + transactionType);
1793: } else {
1794: paymentConfig = paymentSettings
1795: .getString("paymentPropertiesPath");
1796: paymentService = paymentSettings
1797: .getString("paymentService");
1798: requestContext.put("paymentConfig", paymentConfig);
1799: }
1800:
1801: // check the service name
1802: if (paymentService == null || paymentConfig == null) {
1803: return ServiceUtil
1804: .returnError("Invalid product store payment settings");
1805: }
1806:
1807: if (paymentMethodTypeId.equals("CREDIT_CARD")) {
1808: GenericValue creditCard = delegator.makeValue("CreditCard",
1809: null);
1810: creditCard.setAllFields(context, true, null, null);
1811: if (creditCard.get("nameOnCard") == null
1812: || creditCard.get("cardType") == null
1813: || creditCard.get("cardNumber") == null) {
1814: return ServiceUtil
1815: .returnError("Credit card is missing required fields.");
1816: }
1817: String expMonth = (String) context.get("expMonth");
1818: String expYear = (String) context.get("expYear");
1819: String expDate = expMonth + "/" + expYear;
1820: creditCard.set("expireDate", expDate);
1821: requestContext.put("creditCard", creditCard);
1822:
1823: GenericValue billingAddress = delegator.makeValue(
1824: "PostalAddress", null);
1825: billingAddress.setAllFields(context, true, null, null);
1826: if (billingAddress.get("address1") == null
1827: || billingAddress.get("city") == null
1828: || billingAddress.get("postalCode") == null) {
1829: return ServiceUtil
1830: .returnError("Credit card billing address is missing required fields.");
1831: }
1832: requestContext.put("billingAddress", billingAddress);
1833:
1834: GenericValue contactPerson = delegator.makeValue("Person",
1835: null);
1836: contactPerson.setAllFields(context, true, null, null);
1837: if (contactPerson.get("firstName") == null
1838: || contactPerson.get("lastName") == null) {
1839: return ServiceUtil
1840: .returnError("Contact person is missing required fields.");
1841: }
1842: requestContext.put("contactPerson", contactPerson);
1843:
1844: GenericValue contactEmail = delegator.makeValue(
1845: "ContactMech", null);
1846: contactEmail.set("infoString", context.get("infoString"));
1847: if (contactEmail.get("infoString") == null) {
1848: return ServiceUtil
1849: .returnError("Email address field cannot be empty.");
1850: }
1851: requestContext.put("contactEmail", contactEmail);
1852: requestContext.put("referenceCode", referenceCode);
1853: requestContext.put("currency", "USD");
1854: requestContext.put("creditAmount", context.get("amount")); // TODO fix me to work w/ other services
1855: } else {
1856: return ServiceUtil
1857: .returnError("Payment method type : "
1858: + paymentMethodTypeId
1859: + " is not yet implemented for manual transactions");
1860: }
1861:
1862: // process the transaction
1863: Map response = null;
1864: try {
1865: response = dispatcher.runSync(paymentService,
1866: requestContext);
1867: } catch (GenericServiceException e) {
1868: Debug.logError(e, module);
1869: return ServiceUtil.returnError("Error calling service : "
1870: + paymentService + " / " + requestContext);
1871: }
1872:
1873: // check for errors
1874: if (ServiceUtil.isError(response)) {
1875: return ServiceUtil
1876: .returnError(ServiceUtil.makeErrorMessage(response,
1877: null, null, null, null));
1878: }
1879:
1880: // get the reference number // TODO add support for other tx types
1881: String refNum = (String) response.get("creditRefNum");
1882: String code = (String) response.get("creditCode");
1883: String msg = (String) response.get("creditMessage");
1884: Map returnResults = ServiceUtil
1885: .returnSuccess("Transaction result [" + msg + "/"
1886: + code + "] Ref#: " + refNum);
1887: returnResults.put("referenceNum", refNum);
1888: return returnResults;
1889: }
1890:
1891: // ****************************************************
1892: // Test Services
1893: // ****************************************************
1894:
1895: /**
1896: * Simple test processor; declines all orders < 100.00; approves all orders > 100.00
1897: */
1898: public static Map testProcessor(DispatchContext dctx, Map context) {
1899: Map result = new HashMap();
1900: Double processAmount = (Double) context.get("processAmount");
1901:
1902: if (processAmount != null
1903: && processAmount.doubleValue() >= 100.00)
1904: result.put("authResult", new Boolean(true));
1905: if (processAmount != null
1906: && processAmount.doubleValue() < 100.00)
1907: result.put("authResult", new Boolean(false));
1908: if (processAmount == null)
1909: result.put("authResult", null);
1910:
1911: long nowTime = new Date().getTime();
1912:
1913: result.put("processAmount", context.get("processAmount"));
1914: result.put("authRefNum", new Long(nowTime).toString());
1915: result.put("authFlag", "X");
1916: result
1917: .put("authMessage",
1918: "This is a test processor; no payments were captured or authorized.");
1919: return result;
1920: }
1921:
1922: /**
1923: * Always approve processor.
1924: */
1925: public static Map alwaysApproveProcessor(DispatchContext dctx,
1926: Map context) {
1927: Map result = new HashMap();
1928: Double processAmount = (Double) context.get("processAmount");
1929: long nowTime = new Date().getTime();
1930: Debug.logInfo("Test Processor Approving Credit Card", module);
1931:
1932: result.put("authResult", new Boolean(true));
1933: result.put("processAmount", context.get("processAmount"));
1934: result.put("authRefNum", new Long(nowTime).toString());
1935: result.put("authCode", "100");
1936: result.put("authFlag", "A");
1937: result
1938: .put("authMessage",
1939: "This is a test processor; no payments were captured or authorized.");
1940: return result;
1941: }
1942:
1943: public static Map alwaysApproveWithCapture(DispatchContext dctx,
1944: Map context) {
1945: Map result = new HashMap();
1946: long nowTime = new Date().getTime();
1947: String refNum = new Long(nowTime).toString();
1948: Debug.logInfo(
1949: "Test Processor Approving Credit Card with Capture",
1950: module);
1951:
1952: result.put("authResult", new Boolean(true));
1953: result.put("captureResult", new Boolean(true));
1954: result.put("processAmount", context.get("processAmount"));
1955: result.put("authRefNum", refNum);
1956: result.put("captureRefNum", refNum);
1957: result.put("authCode", "100");
1958: result.put("captureCode", "200");
1959: result.put("authFlag", "A");
1960: result
1961: .put("authMessage",
1962: "This is a test processor; no payments were captured or authorized.");
1963: return result;
1964: }
1965:
1966: /**
1967: * Always decline processor.
1968: */
1969: public static Map alwaysDeclineProcessor(DispatchContext dctx,
1970: Map context) {
1971: Map result = new HashMap();
1972: Double processAmount = (Double) context.get("processAmount");
1973: long nowTime = new Date().getTime();
1974: Debug.logInfo("Test Processor Declining Credit Card", module);
1975:
1976: result.put("authResult", new Boolean(false));
1977: result.put("processAmount", context.get("processAmount"));
1978: result.put("authRefNum", new Long(nowTime).toString());
1979: result.put("authFlag", "D");
1980: result
1981: .put("authMessage",
1982: "This is a test processor; no payments were captured or authorized");
1983: return result;
1984: }
1985:
1986: /**
1987: * Always fail (error) processor
1988: */
1989: public static Map alwaysFailProcessor(DispatchContext dctx,
1990: Map context) {
1991: return ServiceUtil
1992: .returnError("Unable to communicate with bla");
1993: }
1994:
1995: public static Map testRelease(DispatchContext dctx, Map context) {
1996: Map result = new HashMap();
1997: long nowTime = new Date().getTime();
1998:
1999: result.put("releaseResult", new Boolean(true));
2000: result.put("releaseAmount", context.get("releaseAmount"));
2001: result.put("releaseRefNum", new Long(nowTime).toString());
2002: result.put("releaseFlag", "U");
2003: result.put("releaseMessage",
2004: "This is a test release; no authorizations exist");
2005: return result;
2006: }
2007:
2008: /**
2009: * Test capture service (returns true)
2010: */
2011: public static Map testCapture(DispatchContext dctx, Map context) {
2012: Map result = new HashMap();
2013: long nowTime = new Date().getTime();
2014:
2015: result.put("captureResult", new Boolean(true));
2016: result.put("captureAmount", context.get("captureAmount"));
2017: result.put("captureRefNum", new Long(nowTime).toString());
2018: result.put("captureFlag", "C");
2019: result.put("captureMessage",
2020: "This is a test capture; no money was transferred");
2021: return result;
2022: }
2023:
2024: /**
2025: * Test refund service (returns true)
2026: */
2027: public static Map testRefund(DispatchContext dctx, Map context) {
2028: Map result = new HashMap();
2029: long nowTime = new Date().getTime();
2030:
2031: result.put("refundResult", new Boolean(true));
2032: result.put("refundAmount", context.get("refundAmount"));
2033: result.put("refundRefNum", new Long(nowTime).toString());
2034: result.put("refundFlag", "R");
2035: result.put("refundMessage",
2036: "This is a test refund; no money was transferred");
2037: return result;
2038: }
2039:
2040: }
|