private static String getLastProductStoreId(Delegator delegator, String finAccountId) { GenericValue trans = null; try { trans = EntityQuery.use(delegator) .from("FinAccountTrans") .where( EntityCondition.makeCondition( "finAccountTransTypeId", EntityOperator.EQUALS, "DEPOSIT"), EntityCondition.makeCondition( "finAccountId", EntityOperator.EQUALS, finAccountId), EntityCondition.makeCondition("orderId", EntityOperator.NOT_EQUAL, null)) .orderBy("-transactionDate") .queryFirst(); } catch (GenericEntityException e) { Debug.logError(e, module); } if (trans != null) { String orderId = trans.getString("orderId"); OrderReadHelper orh = new OrderReadHelper(delegator, orderId); return orh.getProductStoreId(); } // none found; pick one from our set stores try { GenericValue store = EntityQuery.use(delegator).from("ProductStore").orderBy("productStoreId").queryFirst(); if (store != null) return store.getString("productStoreId"); } catch (GenericEntityException e) { Debug.logError(e, module); } return null; }
public static Map<String, Object> doAuthorization( DispatchContext dctx, Map<String, Object> context) { Delegator delegator = dctx.getDelegator(); String orderId = (String) context.get("orderId"); BigDecimal processAmount = (BigDecimal) context.get("processAmount"); GenericValue payPalPaymentMethod = (GenericValue) context.get("payPalPaymentMethod"); OrderReadHelper orh = new OrderReadHelper(delegator, orderId); GenericValue payPalConfig = getPaymentMethodGatewayPayPal(dctx, context, PaymentGatewayServices.AUTH_SERVICE_TYPE); Locale locale = (Locale) context.get("locale"); NVPEncoder encoder = new NVPEncoder(); encoder.add("METHOD", "DoAuthorization"); encoder.add("TRANSACTIONID", payPalPaymentMethod.getString("transactionId")); encoder.add("AMT", processAmount.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()); encoder.add("TRANSACTIONENTITY", "Order"); String currency = (String) context.get("currency"); if (currency == null) { currency = orh.getCurrency(); } encoder.add("CURRENCYCODE", currency); NVPDecoder decoder = null; try { decoder = sendNVPRequest(payPalConfig, encoder); } catch (PayPalException e) { Debug.logError(e, module); return ServiceUtil.returnError(e.getMessage()); } if (decoder == null) { return ServiceUtil.returnError( UtilProperties.getMessage(resource, "AccountingPayPalUnknownError", locale)); } Map<String, Object> result = ServiceUtil.returnSuccess(); Map<String, String> errors = getErrorMessageMap(decoder); if (UtilValidate.isNotEmpty(errors)) { result.put("authResult", false); result.put("authRefNum", "N/A"); result.put("processAmount", BigDecimal.ZERO); if (errors.size() == 1) { Map.Entry<String, String> error = errors.entrySet().iterator().next(); result.put("authCode", error.getKey()); result.put("authMessage", error.getValue()); } else { result.put( "authMessage", "Multiple errors occurred, please refer to the gateway response messages"); result.put("internalRespMsgs", errors); } } else { result.put("authResult", true); result.put("processAmount", new BigDecimal(decoder.get("AMT"))); result.put("authRefNum", decoder.get("TRANSACTIONID")); } // TODO: Look into possible PAYMENTSTATUS and PENDINGREASON return codes, it is unclear what // should be checked for this type of transaction return result; }
private static GenericValue getPaymentMethodGatewayPayPal( DispatchContext dctx, Map<String, ? extends Object> context, String paymentServiceTypeEnumId) { Delegator delegator = dctx.getDelegator(); String paymentGatewayConfigId = (String) context.get("paymentGatewayConfigId"); GenericValue payPalGatewayConfig = null; if (paymentGatewayConfigId == null) { String productStoreId = null; GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference"); if (orderPaymentPreference != null) { OrderReadHelper orh = new OrderReadHelper(delegator, orderPaymentPreference.getString("orderId")); productStoreId = orh.getProductStoreId(); } else { ShoppingCart cart = (ShoppingCart) context.get("cart"); if (cart != null) { productStoreId = cart.getProductStoreId(); } } if (productStoreId != null) { GenericValue payPalPaymentSetting = ProductStoreWorker.getProductStorePaymentSetting( delegator, productStoreId, "EXT_PAYPAL", paymentServiceTypeEnumId, true); if (payPalPaymentSetting != null) { paymentGatewayConfigId = payPalPaymentSetting.getString("paymentGatewayConfigId"); } } } if (paymentGatewayConfigId != null) { try { payPalGatewayConfig = EntityQuery.use(delegator) .from("PaymentGatewayPayPal") .where("paymentGatewayConfigId", paymentGatewayConfigId) .cache() .queryOne(); } catch (GenericEntityException e) { Debug.logError(e, module); } } return payPalGatewayConfig; }
public static Map<String, Object> assembleCrmsfaOrderFormMergeContext( Delegator delegator, String orderId) { Map<String, Object> templateContext = new HashMap<String, Object>(); if (UtilValidate.isNotEmpty(orderId)) { try { OrderReadHelper orh = new OrderReadHelper(delegator, orderId); templateContext.put("orderId", orderId); templateContext.put("externalOrderId", orh.getOrderHeader().get("externalId")); templateContext.put("orderDate", orh.getOrderHeader().getTimestamp("orderDate")); GenericValue billingParty = orh.getBillToParty(); if (UtilValidate.isNotEmpty(billingParty)) { if ("Person".equalsIgnoreCase(billingParty.getEntityName())) { templateContext.put("orderBillingFirstName", billingParty.get("firstName")); templateContext.put("orderBillingLastName", billingParty.get("lastName")); } templateContext.put("orderPartyId", billingParty.get("partyId")); templateContext.put( "orderBillingFullName", org.ofbiz.party.party.PartyHelper.getPartyName(billingParty, false)); } templateContext.put("orderSubtotal", orh.getOrderItemsSubTotal()); templateContext.put("orderTaxTotal", orh.getTaxTotal()); templateContext.put("orderShippingTotal", orh.getShippingTotal()); templateContext.put("orderGrandTotal", orh.getOrderGrandTotal()); templateContext.put( "orderPaymentTotal", orh.getOrderGrandTotal().subtract(UtilOrder.getOrderOpenAmount(orh))); GenericValue shippingParty = orh.getShipToParty(); if (UtilValidate.isNotEmpty(shippingParty)) { if ("Person".equalsIgnoreCase(shippingParty.getEntityName())) { templateContext.put("orderShippingFirstName", shippingParty.get("firstName")); templateContext.put("orderShippingLastName", shippingParty.get("lastName")); } else { templateContext.put("orderShippingCompanyName", shippingParty.get("groupName")); } templateContext.put( "orderShippingFullName", org.ofbiz.party.party.PartyHelper.getPartyName(shippingParty, false)); } List<GenericValue> orderItemVals = orh.getOrderItems(); List<Map<String, Object>> orderItems = new ArrayList<Map<String, Object>>(); for (GenericValue orderItemVal : orderItemVals) { Map<String, Object> orderItem = orderItemVal.getAllFields(); GenericValue product = orderItemVal.getRelatedOne("Product"); if (UtilValidate.isEmpty(product)) { continue; } for (String fieldName : (Set<String>) product.keySet()) { orderItem.put(fieldName, product.get(fieldName)); } orderItems.add(orderItem); } templateContext.put("orderItems", orderItems); } catch (GenericEntityException e) { Debug.logError(e, MODULE); } } return templateContext; }
public static Map<String, Object> assembleCrmsfaShipmentFormMergeContext( Delegator delegator, String orderId, String shipGroupSeqId, String shipmentId, Locale locale) { Map<String, Object> templateContext = new HashMap<String, Object>(); try { // Prefer shipment data if shipmentId is provided if (UtilValidate.isNotEmpty(shipmentId)) { GenericValue shipment = delegator.findByPrimaryKey("Shipment", UtilMisc.toMap("shipmentId", shipmentId)); if (UtilValidate.isNotEmpty(shipment)) { GenericValue shipLoc = shipment.getRelatedOne("DestinationPostalAddress"); if (UtilValidate.isNotEmpty(shipLoc)) { templateContext.put("orderShippingAddress1", shipLoc.get("address1")); templateContext.put("orderShippingAddress2", shipLoc.get("address2")); templateContext.put("orderShippingCity", shipLoc.get("city")); templateContext.put("orderShippingPostalCode", shipLoc.get("postalCode")); GenericValue stateProvGeo = shipLoc.getRelatedOne("StateProvinceGeo"); if (UtilValidate.isNotEmpty(stateProvGeo)) { templateContext.put("orderShippingStateProvince", stateProvGeo.get("geoName")); } GenericValue countryGeo = shipLoc.getRelatedOne("CountryGeo"); if (UtilValidate.isNotEmpty(countryGeo)) { templateContext.put("orderShippingCountry", countryGeo.get("geoName")); } } GenericValue phoneNumber = shipment.getRelatedOne("DestinationTelecomNumber"); if (UtilValidate.isNotEmpty(phoneNumber)) { String phoneNumberString = UtilValidate.isEmpty(phoneNumber.getString("countryCode")) ? "" : phoneNumber.getString("countryCode") + " "; if (UtilValidate.isNotEmpty(phoneNumber.getString("areaCode"))) { phoneNumberString += phoneNumber.getString("areaCode") + " "; } if (UtilValidate.isNotEmpty(phoneNumber.getString("contactNumber"))) { phoneNumberString += phoneNumber.getString("contactNumber"); } templateContext.put("orderShippingPhone", phoneNumberString); } GenericValue statusItem = shipment.getRelatedOne("StatusItem"); if (UtilValidate.isNotEmpty(statusItem)) { templateContext.put("shipmentStatus", statusItem.get("description", locale)); } } } else if (UtilValidate.isNotEmpty(orderId)) { OrderReadHelper orh = new OrderReadHelper(delegator, orderId); GenericValue shipGroup = orh.getOrderItemShipGroup(shipGroupSeqId); if (UtilValidate.isEmpty(shipGroup)) { // Default to the first ship group if no shipGroupSeqId is provided List shipGroups = orh.getOrderItemShipGroups(); if (UtilValidate.isNotEmpty(shipGroups)) { shipGroup = (GenericValue) shipGroups.get(0); } } if (UtilValidate.isNotEmpty(shipGroup)) { GenericValue shipLoc = shipGroup.getRelatedOne("PostalAddress"); if (UtilValidate.isNotEmpty(shipLoc)) { templateContext.put("orderShippingAddress1", shipLoc.get("address1")); templateContext.put("orderShippingAddress2", shipLoc.get("address2")); templateContext.put("orderShippingCity", shipLoc.get("city")); templateContext.put("orderShippingPostalCode", shipLoc.get("postalCode")); GenericValue stateProvGeo = shipLoc.getRelatedOne("StateProvinceGeo"); if (UtilValidate.isNotEmpty(stateProvGeo)) { templateContext.put("orderShippingStateProvince", stateProvGeo.get("geoName")); } GenericValue countryGeo = shipLoc.getRelatedOne("CountryGeo"); if (UtilValidate.isNotEmpty(countryGeo)) { templateContext.put("orderShippingCountry", countryGeo.get("geoName")); } } GenericValue phoneNumber = shipGroup.getRelatedOne("TelecomTelecomNumber"); if (UtilValidate.isNotEmpty(phoneNumber)) { String phoneNumberString = UtilValidate.isEmpty(phoneNumber.getString("countryCode")) ? "" : phoneNumber.getString("countryCode") + " "; if (UtilValidate.isNotEmpty(phoneNumber.getString("areaCode"))) { phoneNumberString += phoneNumber.getString("areaCode") + " "; } if (UtilValidate.isNotEmpty(phoneNumber.getString("contactNumber"))) { phoneNumberString += phoneNumber.getString("contactNumber"); } templateContext.put("orderShippingPhone", phoneNumberString); } // Find any shipments relating to this ship group List<GenericValue> shipments = delegator.findByAnd( "Shipment", UtilMisc.toMap( "primaryOrderId", orderId, "primaryShipGroupSeqId", shipGroup.getString("shipGroupSeqId")), UtilMisc.toList("createdStamp DESC")); GenericValue shipment = EntityUtil.getFirst(shipments); if (UtilValidate.isNotEmpty(shipment)) { GenericValue statusItem = shipment.getRelatedOne("StatusItem"); if (UtilValidate.isNotEmpty(statusItem)) { templateContext.put("shipmentStatus", statusItem.get("description", locale)); } } } } } catch (GenericEntityException e) { Debug.logError(e, MODULE); } return templateContext; }
// Note we're not doing a lot of error checking here as this method is really only used // to confirm the order with PayPal, the subsequent authorizations will handle any errors // that may occur. public static Map<String, Object> doExpressCheckout( DispatchContext dctx, Map<String, Object> context) { LocalDispatcher dispatcher = dctx.getDispatcher(); Delegator delegator = dctx.getDelegator(); GenericValue userLogin = (GenericValue) context.get("userLogin"); GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference"); OrderReadHelper orh = new OrderReadHelper(delegator, paymentPref.getString("orderId")); Locale locale = (Locale) context.get("locale"); GenericValue payPalPaymentSetting = getPaymentMethodGatewayPayPal(dctx, context, null); GenericValue payPalPaymentMethod = null; try { payPalPaymentMethod = paymentPref.getRelatedOne("PaymentMethod", false); payPalPaymentMethod = payPalPaymentMethod.getRelatedOne("PayPalPaymentMethod", false); } catch (GenericEntityException e) { Debug.logError(e, module); return ServiceUtil.returnError(e.getMessage()); } BigDecimal processAmount = paymentPref.getBigDecimal("maxAmount"); NVPEncoder encoder = new NVPEncoder(); encoder.add("METHOD", "DoExpressCheckoutPayment"); encoder.add("TOKEN", payPalPaymentMethod.getString("expressCheckoutToken")); encoder.add("PAYMENTACTION", "Order"); encoder.add("PAYERID", payPalPaymentMethod.getString("payerId")); // set the amount encoder.add("AMT", processAmount.setScale(2).toPlainString()); encoder.add("CURRENCYCODE", orh.getCurrency()); BigDecimal grandTotal = orh.getOrderGrandTotal(); BigDecimal shippingTotal = orh.getShippingTotal().setScale(2, BigDecimal.ROUND_HALF_UP); BigDecimal taxTotal = orh.getTaxTotal().setScale(2, BigDecimal.ROUND_HALF_UP); BigDecimal subTotal = grandTotal.subtract(shippingTotal).subtract(taxTotal).setScale(2, BigDecimal.ROUND_HALF_UP); encoder.add("ITEMAMT", subTotal.toPlainString()); encoder.add("SHIPPINGAMT", shippingTotal.toPlainString()); encoder.add("TAXAMT", taxTotal.toPlainString()); NVPDecoder decoder = null; try { decoder = sendNVPRequest(payPalPaymentSetting, encoder); } catch (PayPalException e) { Debug.logError(e, module); return ServiceUtil.returnError(e.getMessage()); } if (decoder == null) { return ServiceUtil.returnError( UtilProperties.getMessage(resource, "AccountingPayPalUnknownError", locale)); } Map<String, String> errorMessages = getErrorMessageMap(decoder); if (UtilValidate.isNotEmpty(errorMessages)) { if (errorMessages.containsKey("10417")) { // "The transaction cannot complete successfully, Instruct the customer to use an // alternative payment method" // I've only encountered this once and there's no indication of the cause so the temporary // solution is to try again boolean retry = context.get("_RETRY_") == null || (Boolean) context.get("_RETRY_"); if (retry) { context.put("_RETRY_", false); return PayPalServices.doExpressCheckout(dctx, context); } } return ServiceUtil.returnError(UtilMisc.toList(errorMessages.values())); } Map<String, Object> inMap = FastMap.newInstance(); inMap.put("userLogin", userLogin); inMap.put("paymentMethodId", payPalPaymentMethod.get("paymentMethodId")); inMap.put("transactionId", decoder.get("TRANSACTIONID")); Map<String, Object> outMap = null; try { outMap = dispatcher.runSync("updatePayPalPaymentMethod", inMap); } catch (GenericServiceException e) { Debug.logError(e, module); return ServiceUtil.returnError(e.getMessage()); } if (ServiceUtil.isError(outMap)) { Debug.logError(ServiceUtil.getErrorMessage(outMap), module); return outMap; } return ServiceUtil.returnSuccess(); }
// base payment integration services public static Map<String, Object> finAccountPreAuth( DispatchContext dctx, Map<String, Object> context) { LocalDispatcher dispatcher = dctx.getDispatcher(); Delegator delegator = dctx.getDelegator(); GenericValue userLogin = (GenericValue) context.get("userLogin"); Locale locale = (Locale) context.get("locale"); GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference"); String finAccountCode = (String) context.get("finAccountCode"); String finAccountPin = (String) context.get("finAccountPin"); String finAccountId = (String) context.get("finAccountId"); String orderId = (String) context.get("orderId"); BigDecimal amount = (BigDecimal) context.get("processAmount"); // check for an existing auth trans and cancel it GenericValue authTrans = PaymentGatewayServices.getAuthTransaction(paymentPref); if (authTrans != null) { Map<String, Object> input = UtilMisc.toMap("userLogin", userLogin, "finAccountAuthId", authTrans.get("referenceNum")); try { dispatcher.runSync("expireFinAccountAuth", input); } catch (GenericServiceException e) { Debug.logError(e, module); return ServiceUtil.returnError(e.getMessage()); } } if (finAccountId == null && paymentPref != null) { finAccountId = paymentPref.getString("finAccountId"); } // obtain the order information OrderReadHelper orh = new OrderReadHelper(delegator, orderId); // NOTE DEJ20070808: this means that we want store related settings for where the item is being // purchased, // NOT where the account was setup; should this be changed to use settings from the store where // the account was setup? String productStoreId = orh.getProductStoreId(); // TODO, NOTE DEJ20070808: why is this setup this way anyway? for the allowAuthToNegative // wouldn't that be better setup // on the FinAccount and not on the ProductStoreFinActSetting? maybe an override on the // FinAccount would be good... // get the financial account GenericValue finAccount; if (finAccountId != null) { try { finAccount = EntityQuery.use(delegator) .from("FinAccount") .where("finAccountId", finAccountId) .queryOne(); } catch (GenericEntityException e) { Debug.logError(e, module); return ServiceUtil.returnError(e.getMessage()); } } else { if (finAccountCode != null) { try { finAccount = FinAccountHelper.getFinAccountFromCode(finAccountCode, delegator); } catch (GenericEntityException e) { Debug.logError(e, module); return ServiceUtil.returnError( UtilProperties.getMessage( resourceError, "AccountingFinAccountCannotLocateItFromAccountCode", locale)); } } else { return ServiceUtil.returnError( UtilProperties.getMessage( resourceError, "AccountingFinAccountIdAndFinAccountCodeAreNull", locale)); } } if (finAccount == null) { return ServiceUtil.returnError( UtilProperties.getMessage(resourceError, "AccountingFinAccountIdInvalid", locale)); } String finAccountTypeId = finAccount.getString("finAccountTypeId"); finAccountId = finAccount.getString("finAccountId"); String statusId = finAccount.getString("statusId"); try { // fin the store requires a pin number; validate the PIN with the code Map<String, Object> findProductStoreFinActSettingMap = UtilMisc.<String, Object>toMap( "productStoreId", productStoreId, "finAccountTypeId", finAccountTypeId); GenericValue finAccountSettings = EntityQuery.use(delegator) .from("ProductStoreFinActSetting") .where(findProductStoreFinActSettingMap) .cache() .queryOne(); if (finAccountSettings == null) { Debug.logWarning( "In finAccountPreAuth could not find ProductStoreFinActSetting record, values searched by: " + findProductStoreFinActSettingMap, module); } if (Debug.verboseOn()) Debug.logVerbose("In finAccountPreAuth finAccountSettings=" + finAccountSettings, module); BigDecimal minBalance = FinAccountHelper.ZERO; String allowAuthToNegative = "N"; if (finAccountSettings != null) { allowAuthToNegative = finAccountSettings.getString("allowAuthToNegative"); minBalance = finAccountSettings.getBigDecimal("minBalance"); if (minBalance == null) { minBalance = FinAccountHelper.ZERO; } // validate the PIN if the store requires it if ("Y".equals(finAccountSettings.getString("requirePinCode"))) { if (!FinAccountHelper.validatePin(delegator, finAccountCode, finAccountPin)) { Map<String, Object> result = ServiceUtil.returnSuccess(); result.put( "authMessage", UtilProperties.getMessage( resourceError, "AccountingFinAccountPinCodeCombinatorNotFound", locale)); result.put("authResult", Boolean.FALSE); result.put("processAmount", amount); result.put("authFlag", "0"); result.put("authCode", "A"); result.put("authRefNum", "0"); Debug.logWarning("Unable to auth FinAccount: " + result, module); return result; } } } // check for expiration date if ((finAccount.getTimestamp("thruDate") != null) && (finAccount.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) { Map<String, Object> result = ServiceUtil.returnSuccess(); result.put( "authMessage", UtilProperties.getMessage( resourceError, "AccountingFinAccountExpired", UtilMisc.toMap("thruDate", finAccount.getTimestamp("thruDate")), locale)); result.put("authResult", Boolean.FALSE); result.put("processAmount", amount); result.put("authFlag", "0"); result.put("authCode", "A"); result.put("authRefNum", "0"); Debug.logWarning("Unable to auth FinAccount: " + result, module); return result; } // check for account being in bad standing somehow if ("FNACT_NEGPENDREPL".equals(statusId) || "FNACT_MANFROZEN".equals(statusId) || "FNACT_CANCELLED".equals(statusId)) { // refresh the finaccount finAccount.refresh(); statusId = finAccount.getString("statusId"); if ("FNACT_NEGPENDREPL".equals(statusId) || "FNACT_MANFROZEN".equals(statusId) || "FNACT_CANCELLED".equals(statusId)) { Map<String, Object> result = ServiceUtil.returnSuccess(); if ("FNACT_NEGPENDREPL".equals(statusId)) { result.put( "authMessage", UtilProperties.getMessage(resourceError, "AccountingFinAccountNegative", locale)); } else if ("FNACT_MANFROZEN".equals(statusId)) { result.put( "authMessage", UtilProperties.getMessage(resourceError, "AccountingFinAccountFrozen", locale)); } else if ("FNACT_CANCELLED".equals(statusId)) { result.put( "authMessage", UtilProperties.getMessage(resourceError, "AccountingFinAccountCancelled", locale)); } result.put("authResult", Boolean.FALSE); result.put("processAmount", amount); result.put("authFlag", "0"); result.put("authCode", "A"); result.put("authRefNum", "0"); Debug.logWarning("Unable to auth FinAccount: " + result, module); return result; } } // check the amount to authorize against the available balance of fin account, which includes // active authorizations as well as transactions BigDecimal availableBalance = finAccount.getBigDecimal("availableBalance"); if (availableBalance == null) { availableBalance = FinAccountHelper.ZERO; } else { BigDecimal availableBalanceOriginal = availableBalance; availableBalance = availableBalance.setScale(FinAccountHelper.decimals, FinAccountHelper.rounding); if (availableBalance.compareTo(availableBalanceOriginal) != 0) { Debug.logWarning( "In finAccountPreAuth for finAccountId [" + finAccountId + "] availableBalance [" + availableBalanceOriginal + "] was different after rounding [" + availableBalance + "]; it should never have made it into the database this way, so check whatever put it there.", module); } } Map<String, Object> result = ServiceUtil.returnSuccess(); String authMessage = null; Boolean processResult; String refNum; // make sure to round and scale it to the same as availableBalance amount = amount.setScale(FinAccountHelper.decimals, FinAccountHelper.rounding); Debug.logInfo( "Allow auth to negative: " + allowAuthToNegative + " :: available: " + availableBalance + " comp: " + minBalance + " = " + availableBalance.compareTo(minBalance) + " :: req: " + amount, module); // check the available balance to see if we can auth this tx if (("Y".equals(allowAuthToNegative) && availableBalance.compareTo(minBalance) > -1) || (availableBalance.compareTo(amount) > -1)) { Timestamp thruDate; if (finAccountSettings != null && finAccountSettings.getLong("authValidDays") != null) { thruDate = UtilDateTime.getDayEnd( UtilDateTime.nowTimestamp(), finAccountSettings.getLong("authValidDays")); } else { thruDate = UtilDateTime.getDayEnd( UtilDateTime.nowTimestamp(), Long.valueOf(30)); // default 30 days for an auth } Map<String, Object> tmpResult = dispatcher.runSync( "createFinAccountAuth", UtilMisc.<String, Object>toMap( "finAccountId", finAccountId, "amount", amount, "thruDate", thruDate, "userLogin", userLogin)); if (ServiceUtil.isError(tmpResult)) { return tmpResult; } refNum = (String) tmpResult.get("finAccountAuthId"); processResult = Boolean.TRUE; // refresh the account finAccount.refresh(); } else { Debug.logWarning( "Attempted to authorize [" + amount + "] against a balance of only [" + availableBalance + "] for finAccountId [" + finAccountId + "]", module); refNum = "0"; // a refNum is always required from authorization authMessage = "Insufficient funds"; processResult = Boolean.FALSE; } result.put("processAmount", amount); result.put("authMessage", authMessage); result.put("authResult", processResult); result.put("processAmount", amount); result.put("authFlag", "1"); result.put("authCode", "A"); result.put("authRefNum", refNum); Debug.logInfo("FinAccont Auth: " + result, module); return result; } catch (GenericEntityException ex) { Debug.logError(ex, "Cannot authorize financial account", module); return ServiceUtil.returnError( UtilProperties.getMessage( resourceError, "AccountingFinAccountCannotBeAuthorized", UtilMisc.toMap("errorString", ex.getMessage()), locale)); } catch (GenericServiceException ex) { Debug.logError(ex, "Cannot authorize financial account", module); return ServiceUtil.returnError( UtilProperties.getMessage( resourceError, "AccountingFinAccountCannotBeAuthorized", UtilMisc.toMap("errorString", ex.getMessage()), locale)); } }
public static Map<String, Object> finAccountRefund( DispatchContext dctx, Map<String, Object> context) { LocalDispatcher dispatcher = dctx.getDispatcher(); Delegator delegator = dctx.getDelegator(); Locale locale = (Locale) context.get("locale"); GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference"); GenericValue userLogin = (GenericValue) context.get("userLogin"); BigDecimal amount = (BigDecimal) context.get("refundAmount"); String currency = (String) context.get("currency"); String finAccountId = (String) context.get("finAccountId"); String productStoreId = null; String partyId = null; String orderId = null; if (orderPaymentPreference != null) { orderId = orderPaymentPreference.getString("orderId"); if (orderId != null) { OrderReadHelper orh = new OrderReadHelper(delegator, orderId); productStoreId = orh.getProductStoreId(); GenericValue billToParty = orh.getBillToParty(); if (billToParty != null) { partyId = billToParty.getString("partyId"); } } if (finAccountId == null) { finAccountId = orderPaymentPreference.getString("finAccountId"); } } if (finAccountId == null) { return ServiceUtil.returnError( UtilProperties.getMessage( resourceError, "AccountingFinAccountNotFound", UtilMisc.toMap("finAccountId", ""), locale)); } // call the deposit service Map<String, Object> depositCtx = new HashMap<String, Object>(); depositCtx.put("finAccountId", finAccountId); depositCtx.put("productStoreId", productStoreId); depositCtx.put("isRefund", Boolean.TRUE); depositCtx.put("currency", currency); depositCtx.put("partyId", partyId); depositCtx.put("orderId", orderId); depositCtx.put("amount", amount); depositCtx.put("reasonEnumId", "FATR_REFUND"); depositCtx.put("userLogin", userLogin); Map<String, Object> depositResp; try { depositResp = dispatcher.runSync("finAccountDeposit", depositCtx); } catch (GenericServiceException e) { Debug.logError(e, module); return ServiceUtil.returnError(e.getMessage()); } if (ServiceUtil.isError(depositResp)) { return depositResp; } // create the refund response Map<String, Object> result = ServiceUtil.returnSuccess(); Boolean processResult = (Boolean) depositResp.get("processResult"); BigDecimal depositAmount = (BigDecimal) depositResp.get("amount"); String referenceNum = (String) depositResp.get("referenceNum"); result.put("refundResult", processResult); result.put("refundRefNum", referenceNum); result.put("refundCode", "R"); result.put("refundFlag", "1"); result.put("refundAmount", depositAmount); return result; }
public static Map<String, Object> finAccountCapture( DispatchContext dctx, Map<String, Object> context) { LocalDispatcher dispatcher = dctx.getDispatcher(); Delegator delegator = dctx.getDelegator(); Locale locale = (Locale) context.get("locale"); GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference"); GenericValue userLogin = (GenericValue) context.get("userLogin"); GenericValue authTrans = (GenericValue) context.get("authTrans"); BigDecimal amount = (BigDecimal) context.get("captureAmount"); String currency = (String) context.get("currency"); // get the authorization transaction if (authTrans == null) { authTrans = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference); } if (authTrans == null) { return ServiceUtil.returnError( UtilProperties.getMessage(resourceError, "AccountingFinAccountCannotCapture", locale)); } // get the auth record String finAccountAuthId = authTrans.getString("referenceNum"); GenericValue finAccountAuth; try { finAccountAuth = EntityQuery.use(delegator) .from("FinAccountAuth") .where("finAccountAuthId", finAccountAuthId) .queryOne(); } catch (GenericEntityException e) { Debug.logError(e, module); return ServiceUtil.returnError(e.getMessage()); } Debug.logInfo( "Financial account capture [" + finAccountAuth.get("finAccountId") + "] for the amount of $" + amount + " Tx #" + finAccountAuth.get("finAccountAuthId"), module); // get the financial account GenericValue finAccount; try { finAccount = finAccountAuth.getRelatedOne("FinAccount", false); } catch (GenericEntityException e) { Debug.logError(e, module); return ServiceUtil.returnError(e.getMessage()); } // make sure authorization has not expired Timestamp authExpiration = finAccountAuth.getTimestamp("thruDate"); if ((authExpiration != null) && (authExpiration.before(UtilDateTime.nowTimestamp()))) { return ServiceUtil.returnError( UtilProperties.getMessage( resourceError, "AccountingFinAccountAuthorizationExpired", UtilMisc.toMap( "paymentGatewayResponseId", authTrans.getString("paymentGatewayResponseId"), "authExpiration", authExpiration), locale)); } // make sure the fin account itself has not expired if ((finAccount.getTimestamp("thruDate") != null) && (finAccount.getTimestamp("thruDate").before(UtilDateTime.nowTimestamp()))) { return ServiceUtil.returnError( UtilProperties.getMessage( resourceError, "AccountingFinAccountExpired", UtilMisc.toMap("thruDate", finAccount.getTimestamp("thruDate")), locale)); } String finAccountId = finAccount.getString("finAccountId"); // need the product store ID & party ID String orderId = orderPaymentPreference.getString("orderId"); String productStoreId = null; String partyId = null; if (orderId != null) { OrderReadHelper orh = new OrderReadHelper(delegator, orderId); productStoreId = orh.getProductStoreId(); GenericValue billToParty = orh.getBillToParty(); if (billToParty != null) { partyId = billToParty.getString("partyId"); } } // BIG NOTE: make sure the expireFinAccountAuth and finAccountWithdraw services are done in the // SAME TRANSACTION // (i.e. no require-new-transaction in either of them AND no running async) // cancel the authorization before doing the withdraw to avoid problems with way negative // available amount on account; should happen in same transaction to avoid conflict problems Map<String, Object> releaseResult; try { releaseResult = dispatcher.runSync( "expireFinAccountAuth", UtilMisc.<String, Object>toMap( "userLogin", userLogin, "finAccountAuthId", finAccountAuthId)); } catch (GenericServiceException e) { Debug.logError(e, module); return ServiceUtil.returnError(e.getMessage()); } if (ServiceUtil.isError(releaseResult)) { return releaseResult; } // build the withdraw context Map<String, Object> withdrawCtx = new HashMap<String, Object>(); withdrawCtx.put("finAccountId", finAccountId); withdrawCtx.put("productStoreId", productStoreId); withdrawCtx.put("currency", currency); withdrawCtx.put("partyId", partyId); withdrawCtx.put("orderId", orderId); withdrawCtx.put("amount", amount); withdrawCtx.put("reasonEnumId", "FATR_PURCHASE"); withdrawCtx.put("requireBalance", Boolean.FALSE); // for captures; if auth passed, allow withdrawCtx.put("userLogin", userLogin); // call the withdraw service Map<String, Object> withdrawResp; try { withdrawResp = dispatcher.runSync("finAccountWithdraw", withdrawCtx); } catch (GenericServiceException e) { Debug.logError(e, module); return ServiceUtil.returnError(e.getMessage()); } if (ServiceUtil.isError(withdrawResp)) { return withdrawResp; } // create the capture response Map<String, Object> result = ServiceUtil.returnSuccess(); Boolean processResult = (Boolean) withdrawResp.get("processResult"); BigDecimal withdrawAmount = (BigDecimal) withdrawResp.get("amount"); String referenceNum = (String) withdrawResp.get("referenceNum"); result.put("captureResult", processResult); result.put("captureRefNum", referenceNum); result.put("captureCode", "C"); result.put("captureFlag", "1"); result.put("captureAmount", withdrawAmount); return result; }