| /******************************************************************************* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| *******************************************************************************/ |
| package org.ofbiz.accounting.thirdparty.verisign; |
| |
| import java.math.BigDecimal; |
| import java.util.Date; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import javolution.util.FastMap; |
| |
| import org.apache.commons.lang.StringUtils; |
| import org.ofbiz.accounting.payment.PaymentGatewayServices; |
| import org.ofbiz.base.util.Debug; |
| import org.ofbiz.base.util.StringUtil; |
| import org.ofbiz.base.util.UtilDateTime; |
| import org.ofbiz.base.util.UtilMisc; |
| import org.ofbiz.base.util.UtilProperties; |
| import org.ofbiz.base.util.UtilValidate; |
| import org.ofbiz.base.util.string.FlexibleStringExpander; |
| import org.ofbiz.entity.Delegator; |
| import org.ofbiz.entity.GenericEntityException; |
| import org.ofbiz.entity.GenericValue; |
| import org.ofbiz.entity.util.EntityUtilProperties; |
| import org.ofbiz.order.order.OrderReadHelper; |
| import org.ofbiz.order.shoppingcart.ShoppingCart; |
| import org.ofbiz.order.shoppingcart.ShoppingCartItem; |
| import org.ofbiz.product.store.ProductStoreWorker; |
| import org.ofbiz.service.DispatchContext; |
| import org.ofbiz.service.GenericServiceException; |
| import org.ofbiz.service.LocalDispatcher; |
| import org.ofbiz.service.ServiceUtil; |
| |
| import paypal.payflow.PayflowAPI; |
| import paypal.payflow.SDKProperties; |
| /** |
| * PayflowPro - Verisign PayFlow Pro <=> OFBiz Service Module |
| */ |
| public class PayflowPro { |
| |
| public static final String module = PayflowPro.class.getName(); |
| public final static String resource = "AccountingUiLabels"; |
| |
| /** |
| * Authorize credit card payment service. Service wrapper around PayFlow Pro API. |
| * @param dctx Service Engine DispatchContext. |
| * @param context Map context of parameters. |
| * @return Response map, including RESPMSG, and RESULT keys. |
| */ |
| public static Map<String, Object> ccProcessor(DispatchContext dctx, Map<String, ? extends Object> context) { |
| Delegator delegator = dctx.getDelegator(); |
| GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference"); |
| GenericValue authTrans = (GenericValue) context.get("authTrans"); |
| String orderId = (String) context.get("orderId"); |
| String cvv2 = (String) context.get("cardSecurityCode"); |
| BigDecimal processAmount = (BigDecimal) context.get("processAmount"); |
| GenericValue party = (GenericValue) context.get("billToParty"); |
| GenericValue cc = (GenericValue) context.get("creditCard"); |
| GenericValue payPalPaymentMethod = (GenericValue) context.get("payPalPaymentMethod"); |
| GenericValue ps = (GenericValue) context.get("billingAddress"); |
| String paymentGatewayConfigId = (String) context.get("paymentGatewayConfigId"); |
| String configString = (String) context.get("paymentConfig"); |
| |
| if (configString == null) { |
| configString = "payment.properties"; |
| } |
| |
| boolean isPayPal = false; |
| // Are we doing a cc or a paypal payment? |
| if ("EXT_PAYPAL".equals(paymentPref.getString("paymentMethodTypeId"))) { |
| isPayPal = true; |
| } |
| |
| Map<String, String> data = FastMap.newInstance(); |
| |
| boolean isReAuth = false; |
| if (isPayPal) { |
| data.put("TRXTYPE", "A"); |
| data.put("TENDER", "P"); |
| data.put("ORIGID", payPalPaymentMethod.getString("transactionId")); |
| } else { |
| if (authTrans == null) { |
| authTrans = PaymentGatewayServices.getAuthTransaction(paymentPref); |
| } |
| |
| // set the orderId as comment1 so we can query in PF Manager |
| data.put("COMMENT1", orderId); |
| data.put("PONUM", orderId); |
| data.put("CUSTCODE", party.getString("partyId")); |
| |
| // transaction type |
| if (comparePaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "preAuth", configString, "payment.verisign.preAuth", "Y")) { |
| data.put("TRXTYPE", "A"); |
| // only support re-auth for auth types; sale types don't do it |
| if (authTrans != null) { |
| String refNum = authTrans.getString("referenceNum"); |
| data.put("ORIGID", refNum); |
| isReAuth = true; |
| } |
| } else { |
| data.put("TRXTYPE", "S"); |
| } |
| |
| // credit card tender |
| data.put("TENDER", "C"); |
| |
| // card security code |
| if (UtilValidate.isNotEmpty(cvv2)) { |
| data.put("CVV2", cvv2); |
| } |
| |
| // get the payment information |
| data.put("ACCT", cc.getString("cardNumber")); |
| |
| // name on card |
| String name = cc.getString("firstNameOnCard") + " " + cc.getString("lastNameOnCard"); |
| data.put("FIRSTNAME", cc.getString("firstNameOnCard")); |
| data.put("LASTNAME", cc.getString("lastNameOnCard")); |
| data.put("COMMENT2", name); |
| if (cc.get("expireDate") != null) { |
| String exp = cc.getString("expireDate"); |
| String expDate = exp.substring(0, 2); |
| |
| expDate = expDate + exp.substring(exp.length() - 2); |
| data.put("EXPDATE", expDate); |
| } |
| |
| // gather the address info |
| if (ps != null) { |
| String street = ps.getString("address1") + ((UtilValidate.isNotEmpty(ps.getString("address2"))) ? " " + ps.getString("address2") : ""); |
| data.put("STREET"+"["+street.length()+"]", street); |
| data.put("ZIP", ps.getString("postalCode")); |
| } |
| } |
| |
| // set the amount |
| data.put("AMT", processAmount.toString()); |
| |
| PayflowAPI pfp = init(delegator, paymentGatewayConfigId, configString, context); |
| |
| // get the base params |
| StringBuilder params = makeBaseParams(delegator, paymentGatewayConfigId, configString); |
| |
| // parse the context parameters |
| params.append("&").append(parseContext(data)); |
| |
| // transmit the request |
| //if (Debug.verboseOn()) Debug.logVerbose("Sending to Verisign: " + params.toString(), module); |
| String resp; |
| if (!comparePaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "enableTransmit", configString, "payment.verisign.enable_transmit", "false")) { |
| resp = pfp.submitTransaction(params.toString(), pfp.generateRequestId()); |
| } else { |
| resp = "RESULT=0&AUTHCODE=T&PNREF=" + (new Date()).getTime() + "&RESPMSG=Testing"; |
| } |
| |
| if (Debug.verboseOn()) { |
| Debug.logVerbose("Response from Verisign: " + resp, module); |
| } |
| if (isPayPal) { |
| // Attach the avs info returned in doExpressCheckout and stored in PayPalPaymentMethod |
| resp += "&AVSADDR=" + payPalPaymentMethod.getString("avsAddr") + "&AVSZIP=" + payPalPaymentMethod.getString("avsZip"); |
| } |
| |
| // check the response |
| Map<String, Object> result = ServiceUtil.returnSuccess(); |
| parseAuthResponse(delegator, paymentGatewayConfigId, resp, result, configString, isReAuth, isPayPal); |
| result.put("processAmount", processAmount); |
| return result; |
| } |
| |
| public static Map<String, Object> ccCapture(DispatchContext dctx, Map<String, ? extends Object> context) { |
| Delegator delegator = dctx.getDelegator(); |
| GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference"); |
| GenericValue authTrans = (GenericValue) context.get("authTrans"); |
| BigDecimal amount = (BigDecimal) context.get("captureAmount"); |
| String paymentGatewayConfigId = (String) context.get("paymentGatewayConfigId"); |
| String configString = (String) context.get("paymentConfig"); |
| Locale locale = (Locale) context.get("locale"); |
| if (configString == null) { |
| configString = "payment.properties"; |
| } |
| |
| boolean isPayPal = false; |
| // Are we doing a cc or a paypal payment? |
| if ("EXT_PAYPAL".equals(paymentPref.getString("paymentMethodTypeId"))) { |
| isPayPal = true; |
| } |
| |
| if (authTrans == null) { |
| authTrans = PaymentGatewayServices.getAuthTransaction(paymentPref); |
| } |
| |
| if (authTrans == null) { |
| return ServiceUtil.returnError(UtilProperties.getMessage(resource, |
| "AccountingPaymentTransactionAuthorizationNotFoundCannotCapture", locale)); |
| } |
| |
| // auth ref number |
| String refNum = authTrans.getString("referenceNum"); |
| Map<String, String> data = UtilMisc.toMap("ORIGID", refNum); |
| |
| // tx type (Delayed Capture) |
| data.put("TRXTYPE", "D"); |
| |
| if (isPayPal) { |
| // paypal tender |
| data.put("TENDER", "P"); |
| data.put("CAPTURECOMPLETE", "N"); |
| } else { |
| // credit card tender |
| data.put("TENDER", "C"); |
| |
| // get the orderID |
| String orderId = paymentPref.getString("orderId"); |
| data.put("COMMENT1", orderId); |
| } |
| |
| |
| // amount to capture |
| data.put("AMT", amount.toString()); |
| |
| PayflowAPI pfp = init(delegator, paymentGatewayConfigId, configString, context); |
| |
| // get the base params |
| StringBuilder params = makeBaseParams(delegator, paymentGatewayConfigId, configString); |
| |
| // parse the context parameters |
| params.append("&").append(parseContext(data)); |
| |
| // transmit the request |
| if (Debug.verboseOn()) Debug.logVerbose("Sending to Verisign: " + params.toString(), module); |
| String resp; |
| if (!comparePaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "enableTransmit", configString, "payment.verisign.enable_transmit", "false")) { |
| resp = pfp.submitTransaction(params.toString(), pfp.generateRequestId()); |
| } else { |
| resp = "RESULT=0&AUTHCODE=T&PNREF=" + (new Date()).getTime() + "&RESPMSG=Testing"; |
| } |
| |
| if (Debug.verboseOn()) Debug.logVerbose("Response from Verisign: " + resp, module); |
| |
| // check the response |
| Map<String, Object> result = ServiceUtil.returnSuccess(); |
| parseCaptureResponse(resp, result); |
| result.put("captureAmount", amount); |
| return result; |
| } |
| |
| public static Map<String, Object> ccVoid(DispatchContext dctx, Map<String, ? extends Object> context) { |
| Delegator delegator = dctx.getDelegator(); |
| GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference"); |
| GenericValue authTrans = (GenericValue) context.get("authTrans"); |
| BigDecimal amount = (BigDecimal) context.get("releaseAmount"); |
| String paymentGatewayConfigId = (String) context.get("paymentGatewayConfigId"); |
| String configString = (String) context.get("paymentConfig"); |
| Locale locale = (Locale) context.get("locale"); |
| if (configString == null) { |
| configString = "payment.properties"; |
| } |
| |
| if (authTrans == null) { |
| authTrans = PaymentGatewayServices.getAuthTransaction(paymentPref); |
| } |
| |
| if (authTrans == null) { |
| return ServiceUtil.returnError(UtilProperties.getMessage(resource, |
| "AccountingPaymentTransactionAuthorizationNotFoundCannotRelease", locale)); |
| } |
| |
| boolean isPayPal = false; |
| // Are we doing a cc or a paypal payment? |
| if ("EXT_PAYPAL".equals(paymentPref.getString("paymentMethodTypeId"))) { |
| isPayPal = true; |
| } |
| |
| // auth ref number |
| String refNum = authTrans.getString("referenceNum"); |
| Map<String, String> data = UtilMisc.toMap("ORIGID", refNum); |
| |
| // tx type (Void) |
| data.put("TRXTYPE", "V"); |
| |
| // get the orderID |
| String orderId = paymentPref.getString("orderId"); |
| |
| if (isPayPal) { |
| data.put("TENDER", "P"); |
| |
| data.put("NOTE", orderId); |
| } else { |
| // credit card tender |
| data.put("TENDER", "C"); |
| |
| data.put("COMMENT1", orderId); |
| |
| // amount to void |
| data.put("AMT", amount.toString()); |
| } |
| |
| |
| PayflowAPI pfp = init(delegator, paymentGatewayConfigId, configString, context); |
| |
| // get the base params |
| StringBuilder params = makeBaseParams(delegator, paymentGatewayConfigId, configString); |
| |
| // parse the context parameters |
| params.append("&").append(parseContext(data)); |
| |
| // transmit the request |
| if (Debug.verboseOn()) Debug.logVerbose("Sending to Verisign: " + params.toString(), module); |
| String resp; |
| if (!comparePaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "enableTransmit", configString, "payment.verisign.enable_transmit", "false")) { |
| resp = pfp.submitTransaction(params.toString(), pfp.generateRequestId()); |
| } else { |
| resp = "RESULT=0&AUTHCODE=T&PNREF=" + (new Date()).getTime() + "&RESPMSG=Testing"; |
| } |
| |
| if (Debug.verboseOn()) Debug.logVerbose("Response from Verisign: " + resp, module); |
| |
| // check the response |
| Map<String, Object> result = ServiceUtil.returnSuccess(); |
| parseVoidResponse(resp, result); |
| result.put("releaseAmount", amount); |
| return result; |
| } |
| |
| public static Map<String, Object> ccRefund(DispatchContext dctx, Map<String, ? extends Object> context) { |
| Delegator delegator = dctx.getDelegator(); |
| GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference"); |
| BigDecimal amount = (BigDecimal) context.get("refundAmount"); |
| String paymentGatewayConfigId = (String) context.get("paymentGatewayConfigId"); |
| String configString = (String) context.get("paymentConfig"); |
| Locale locale = (Locale) context.get("locale"); |
| if (configString == null) { |
| configString = "payment.properties"; |
| } |
| |
| GenericValue captureTrans = PaymentGatewayServices.getCaptureTransaction(paymentPref); |
| |
| if (captureTrans == null) { |
| return ServiceUtil.returnError(UtilProperties.getMessage(resource, |
| "AccountingPaymentTransactionAuthorizationNotFoundCannotRefund", locale)); |
| } |
| |
| boolean isPayPal = false; |
| // Are we doing a cc or a paypal payment? |
| if ("EXT_PAYPAL".equals(paymentPref.getString("paymentMethodTypeId"))) { |
| isPayPal = true; |
| } |
| |
| // auth ref number |
| String refNum = captureTrans.getString("referenceNum"); |
| Map<String, String> data = UtilMisc.toMap("ORIGID", refNum); |
| |
| // tx type (Credit) |
| data.put("TRXTYPE", "C"); |
| |
| // get the orderID |
| String orderId = paymentPref.getString("orderId"); |
| |
| if (isPayPal) { |
| data.put("TENDER", "P"); |
| |
| data.put("MEMO", orderId); |
| // PayPal won't allow us to refund more than the capture amount |
| BigDecimal captureAmount = captureTrans.getBigDecimal("amount"); |
| amount = amount.min(captureAmount); |
| } else { |
| // credit card tender |
| data.put("TENDER", "C"); |
| |
| data.put("COMMENT1", orderId); |
| } |
| |
| // amount to capture |
| data.put("AMT", amount.toString()); |
| |
| PayflowAPI pfp = init(delegator, paymentGatewayConfigId, configString, context); |
| |
| // get the base params |
| StringBuilder params = makeBaseParams(delegator, paymentGatewayConfigId, configString); |
| |
| // parse the context parameters |
| params.append("&").append(parseContext(data)); |
| |
| // transmit the request |
| if (Debug.verboseOn()) Debug.logVerbose("Sending to Verisign: " + params.toString(), module); |
| String resp; |
| if (!comparePaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "enableTransmit", configString, "payment.verisign.enable_transmit", "false")) { |
| resp = pfp.submitTransaction(params.toString(), pfp.generateRequestId()); |
| } else { |
| resp = "RESULT=0&AUTHCODE=T&PNREF=" + (new Date()).getTime() + "&RESPMSG=Testing"; |
| } |
| |
| if (Debug.verboseOn()) Debug.logVerbose("Response from Verisign: " + resp, module); |
| |
| // check the response |
| Map<String, Object> result = ServiceUtil.returnSuccess(); |
| parseRefundResponse(resp, result); |
| result.put("refundAmount", amount); |
| return result; |
| } |
| |
| |
| public static Map<String, Object> setExpressCheckout(DispatchContext dctx, Map<String, ? extends Object> context) { |
| Delegator delegator = dctx.getDelegator(); |
| ShoppingCart cart = (ShoppingCart) context.get("cart"); |
| Locale locale = cart.getLocale(); |
| GenericValue payPalPaymentSetting = ProductStoreWorker.getProductStorePaymentSetting(delegator, cart.getProductStoreId(), "EXT_PAYPAL", null, true); |
| String paymentGatewayConfigId = payPalPaymentSetting.getString("paymentGatewayConfigId"); |
| String configString = "payment.properties"; |
| |
| if (cart == null || cart.items().size() <= 0) { |
| return ServiceUtil.returnError(UtilProperties.getMessage("AccountingErrorUiLabels", |
| "AccountingPayPalShoppingCartIsEmpty", locale)); |
| } |
| |
| Map<String, String> data = FastMap.newInstance(); |
| |
| data.put("TRXTYPE", "O"); |
| data.put("TENDER", "P"); |
| data.put("ACTION", "S"); |
| String token = (String) cart.getAttribute("payPalCheckoutToken"); |
| if (UtilValidate.isNotEmpty(token)) { |
| data.put("TOKEN", token); |
| } |
| data.put("RETURNURL", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "returnUrl", configString, "payment.verisign.returnUrl")); |
| data.put("CANCELURL", getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "cancelReturnUrl", configString, "payment.verisign.cancelReturnUrl")); |
| |
| try { |
| addCartDetails(data, cart); |
| } catch (GenericEntityException e) { |
| Debug.logError(e, module); |
| return ServiceUtil.returnError(UtilProperties.getMessage(resource, |
| "AccountingPayflowErrorRetreivingCartDetails", locale)); |
| } |
| |
| PayflowAPI pfp = init(delegator, paymentGatewayConfigId, null, context); |
| |
| // get the base params |
| StringBuilder params = makeBaseParams(delegator, paymentGatewayConfigId, null); |
| |
| // parse the context parameters |
| params.append("&").append(parseContext(data)); |
| |
| // transmit the request |
| if (Debug.verboseOn()) Debug.logVerbose("Sending to Verisign: " + params.toString(), module); |
| String resp; |
| if (!comparePaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "enableTransmit", configString, "payment.verisign.enable_transmit", "false")) { |
| resp = pfp.submitTransaction(params.toString(), pfp.generateRequestId()); |
| } else { |
| resp = "RESULT=0&TOKEN=" + (new Date()).getTime() + "&RESPMSG=Testing"; |
| } |
| |
| if (Debug.verboseOn()) Debug.logVerbose("Response from Verisign: " + resp, module); |
| |
| Map<String, String> responseMap = parseResponse(resp); |
| String result = responseMap.get("RESULT"); |
| if (!"0".equals(result)) { |
| String respMsg = responseMap.get("RESPMSG"); |
| Debug.logError("A problem occurred while requesting an express checkout token from paypal: Result = " + result + ", Message = " + respMsg, module); |
| return ServiceUtil.returnError(UtilProperties.getMessage("AccountingErrorUiLabels", |
| "AccountingPayPalCommunicationError", locale)); |
| } |
| token = responseMap.get("TOKEN"); |
| cart.setAttribute("payPalCheckoutToken", token); |
| return ServiceUtil.returnSuccess(); |
| } |
| |
| private static void addCartDetails(Map<String, String> parameterMap, ShoppingCart cart) throws GenericEntityException { |
| parameterMap.put("CURRENCY", cart.getCurrency()); |
| int line = 0; |
| for (ShoppingCartItem item : cart.items()) { |
| //paramMap.put("L_NUMBER" + line, item.getProductId()); |
| parameterMap.put("L_NAME" + line, item.getName()); |
| parameterMap.put("L_DESC" + line, item.getDescription()); |
| parameterMap.put("L_AMT" + line, item.getBasePrice().setScale(2).toPlainString()); |
| parameterMap.put("L_QTY" + line, item.getQuantity().toBigInteger().toString()); |
| line++; |
| BigDecimal otherAdjustments = item.getOtherAdjustments(); |
| if (otherAdjustments.compareTo(BigDecimal.ZERO) != 0) { |
| parameterMap.put("L_NAME" + line, item.getName() + " Adjustments"); |
| parameterMap.put("L_DESC" + line, "Adjustments for item: " + item.getName()); |
| parameterMap.put("L_AMT" + line, otherAdjustments.setScale(2).toPlainString()); |
| parameterMap.put("L_QTY" + line, "1"); |
| line++; |
| } |
| } |
| BigDecimal otherAdjustments = cart.getOrderOtherAdjustmentTotal(); |
| if (otherAdjustments.compareTo(BigDecimal.ZERO) != 0) { |
| parameterMap.put("L_NAME" + line, "Order Adjustments"); |
| parameterMap.put("L_AMT" + line, otherAdjustments.setScale(2).toPlainString()); |
| parameterMap.put("L_QTY" + line, "1"); |
| line++; |
| } |
| parameterMap.put("ITEMAMT", cart.getSubTotal().add(otherAdjustments).setScale(2).toPlainString()); |
| parameterMap.put("TAXAMT", cart.getTotalSalesTax().setScale(2).toPlainString()); |
| parameterMap.put("FREIGHTAMT", cart.getTotalShipping().setScale(2).toPlainString()); |
| parameterMap.put("AMT", cart.getGrandTotal().setScale(2).toPlainString()); |
| |
| if (!cart.shippingApplies()) { |
| parameterMap.put("NOSHIPPING", "1"); |
| } else { |
| GenericValue shippingAddress = cart.getShippingAddress(); |
| parameterMap.put("ADDROVERRIDE", "1"); |
| parameterMap.put("SHIPTOSTREET", StringUtils.left(shippingAddress.getString("address1"), 30)); |
| parameterMap.put("SHIPTOSTREET2", StringUtils.left(shippingAddress.getString("address2"), 30)); |
| parameterMap.put("SHIPTOCITY", StringUtils.left(shippingAddress.getString("city"), 40)); |
| if (shippingAddress.getString("stateProvinceGeoId") != null && !"_NA_".equals(shippingAddress.getString("stateProvinceGeoId"))) { |
| GenericValue stateProvinceGeo = shippingAddress.getRelatedOne("StateProvinceGeo", false); |
| parameterMap.put("SHIPTOSTATE", StringUtils.left(stateProvinceGeo.getString("geoCode"), 40)); |
| } |
| parameterMap.put("SHIPTOZIP", StringUtils.left(shippingAddress.getString("postalCode"), 16)); |
| GenericValue countryGeo = shippingAddress.getRelatedOne("CountryGeo", false); |
| parameterMap.put("SHIPTOCOUNTRY", StringUtils.left(countryGeo.getString("geoCode"), 2)); |
| } |
| } |
| |
| public static Map<String, Object> getExpressCheckout(DispatchContext dctx, Map<String, Object> context) { |
| LocalDispatcher dispatcher = dctx.getDispatcher(); |
| Delegator delegator = dctx.getDelegator(); |
| ShoppingCart cart = (ShoppingCart) context.get("cart"); |
| Locale locale = cart.getLocale(); |
| GenericValue payPalPaymentSetting = ProductStoreWorker.getProductStorePaymentSetting(delegator, cart.getProductStoreId(), "EXT_PAYPAL", null, true); |
| String paymentGatewayConfigId = payPalPaymentSetting.getString("paymentGatewayConfigId"); |
| String configString = "payment.properties"; |
| |
| Map<String, String> data = FastMap.newInstance(); |
| data.put("TRXTYPE", "O"); |
| data.put("TENDER", "P"); |
| data.put("ACTION", "G"); |
| String token = (String) cart.getAttribute("payPalCheckoutToken"); |
| if (UtilValidate.isNotEmpty(token)) { |
| data.put("TOKEN", token); |
| } |
| |
| PayflowAPI pfp = init(delegator, paymentGatewayConfigId, null, context); |
| |
| // get the base params |
| StringBuilder params = makeBaseParams(delegator, paymentGatewayConfigId, null); |
| |
| // parse the context parameters |
| params.append("&").append(parseContext(data)); |
| |
| // transmit the request |
| if (Debug.verboseOn()) Debug.logVerbose("Sending to Verisign: " + params.toString(), module); |
| String resp; |
| if (!comparePaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "enableTransmit", configString, "payment.verisign.enable_transmit", "false")) { |
| resp = pfp.submitTransaction(params.toString(), pfp.generateRequestId()); |
| } else { |
| resp = "RESULT=0&PAYERID=" + (new Date()).getTime() + "&RESPMSG=Testing"; |
| } |
| |
| Map<String, String> responseMap = parseResponse(resp); |
| if (!"0".equals(responseMap.get("RESULT"))) { |
| Debug.logError("A problem occurred while requesting the checkout details from paypal: Result = " + responseMap.get("RESULT") + ", Message = " + responseMap.get("RESPMSG"), module); |
| return ServiceUtil.returnError(UtilProperties.getMessage("AccountingErrorUiLabels", |
| "AccountingPayPalCommunicationError", locale)); |
| } |
| |
| Map<String, Object> inMap = FastMap.newInstance(); |
| inMap.put("userLogin", cart.getUserLogin()); |
| inMap.put("partyId", cart.getOrderPartyId()); |
| inMap.put("contactMechId", cart.getShippingContactMechId()); |
| inMap.put("fromDate", UtilDateTime.nowTimestamp()); |
| inMap.put("payerId", responseMap.get("PAYERID")); |
| inMap.put("expressCheckoutToken", token); |
| inMap.put("payerStatus", responseMap.get("PAYERSTATUS")); |
| inMap.put("avsAddr", responseMap.get("AVSADDR")); |
| inMap.put("avsZip", responseMap.get("AVSZIP")); |
| inMap.put("correlationId", responseMap.get("CORRELATIONID")); |
| Map<String, Object> outMap = null; |
| try { |
| outMap = dispatcher.runSync("createPayPalPaymentMethod", inMap); |
| } catch (GenericServiceException e) { |
| Debug.logError(e, module); |
| return ServiceUtil.returnError(e.getMessage()); |
| } |
| String paymentMethodId = (String) outMap.get("paymentMethodId"); |
| |
| cart.clearPayments(); |
| cart.addPaymentAmount(paymentMethodId, cart.getGrandTotal(), true); |
| |
| return ServiceUtil.returnSuccess(); |
| |
| } |
| |
| 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")); |
| GenericValue payPalPaymentSetting = ProductStoreWorker.getProductStorePaymentSetting(delegator, orh.getProductStoreId(), "EXT_PAYPAL", null, true); |
| String paymentGatewayConfigId = payPalPaymentSetting.getString("paymentGatewayConfigId"); |
| String configString = "payment.properties"; |
| 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"); |
| |
| Map<String, String> data = FastMap.newInstance(); |
| data.put("TRXTYPE", "O"); |
| data.put("TENDER", "P"); |
| data.put("PAYERID", payPalPaymentMethod.getString("payerId")); |
| data.put("TOKEN", payPalPaymentMethod.getString("expressCheckoutToken")); |
| data.put("ACTION", "D"); |
| // set the amount |
| data.put("AMT", processAmount.setScale(2).toPlainString()); |
| |
| PayflowAPI pfp = init(delegator, paymentGatewayConfigId, null, context); |
| |
| // get the base params |
| StringBuilder params = makeBaseParams(delegator, paymentGatewayConfigId, null); |
| |
| // parse the context parameters |
| params.append("&").append(parseContext(data)); |
| |
| // transmit the request |
| if (Debug.verboseOn()) Debug.logVerbose("Sending to Verisign: " + params.toString(), module); |
| String resp; |
| if (!comparePaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "enableTransmit", configString, "payment.verisign.enable_transmit", "false")) { |
| resp = pfp.submitTransaction(params.toString(), pfp.generateRequestId()); |
| } else { |
| resp = "RESULT=0&PAYERID=" + (new Date()).getTime() + "&RESPMSG=Testing"; |
| } |
| |
| Map<String, String> responseMap = parseResponse(resp); |
| |
| Map<String, Object> inMap = FastMap.newInstance(); |
| inMap.put("userLogin", userLogin); |
| inMap.put("paymentMethodId", payPalPaymentMethod.get("paymentMethodId")); |
| inMap.put("transactionId", responseMap.get("PNREF")); |
| 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(); |
| } |
| |
| private static Map<String, String> parseResponse(String resp) { |
| Debug.logInfo("Verisign response string: " + resp, module); |
| Map<String, String> parameters = FastMap.newInstance(); |
| List<String> params = StringUtil.split(resp, "&"); |
| for (String str : params) { |
| if (str.length() > 0) { |
| List<String> kv = StringUtil.split(str, "="); |
| String k = kv.get(0); |
| String v = kv.get(1); |
| |
| if (k != null && v != null) |
| parameters.put(k, v); |
| } |
| } |
| return parameters; |
| } |
| private static void parseAuthResponse(Delegator delegator, String paymentGatewayConfigId, String resp, Map<String, Object> result, String resource, boolean isReAuth, boolean isPayPal) { |
| Map<String, String> parameters = parseResponse(resp); |
| |
| // txType |
| boolean isSale = !comparePaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "preAuth", resource, "payment.verisign.preAuth", "Y"); |
| |
| // avs checking - ignore on re-auth |
| boolean avsCheckOkay = true; |
| String avsCode = null; |
| if (!isReAuth) { |
| boolean checkAvs = comparePaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "checkAvs", resource, "payment.verisign.checkAvs", "Y"); |
| if (checkAvs && !isSale) { |
| String addAvs = (String) parameters.get("AVSADDR"); |
| String zipAvs = (String) parameters.get("AVSZIP"); |
| avsCode = addAvs + zipAvs; |
| if (addAvs == null || "N".equals(addAvs) || zipAvs == null || "N".equals(zipAvs)) { |
| avsCheckOkay = false; |
| } |
| } |
| } |
| |
| // cvv2 checking - ignore on re-auth or paypal |
| boolean cvv2CheckOkay = true; |
| String cvvCode = null; |
| if (!isReAuth && !isPayPal) { |
| boolean checkCvv2 = comparePaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "checkCvv2", resource, "payment.verisign.checkCvv2", "Y"); |
| if (checkCvv2 && !isSale) { |
| cvvCode = (String) parameters.get("CVV2MATCH"); |
| if (cvvCode == null || "N".equals(cvvCode)) { |
| cvv2CheckOkay = false; |
| } |
| } |
| } |
| |
| String respCode = (String) parameters.get("RESULT"); |
| int codeInt = -999; // custom response code -- not from payflow docs |
| try { |
| codeInt = Integer.parseInt(respCode); |
| } catch (NumberFormatException e) { |
| Debug.logError(e, "Unable to parse response code; not a number!", module); |
| } |
| |
| |
| result.put("authRefNum", parameters.get("PNREF")); |
| |
| if (codeInt == 0 && avsCheckOkay && cvv2CheckOkay) { |
| result.put("authResult", Boolean.TRUE); |
| result.put("authCode", parameters.get("AUTHCODE")); |
| } else if (codeInt < 0) { |
| // communications error |
| Debug.logWarning("In PayflowPro failing authorization; respCode/RESULT=" + respCode + ", avsCheckOkay=" + avsCheckOkay + ", cvv2CheckOkay=" + cvv2CheckOkay + "; AUTHCODE=" + parameters.get("AUTHCODE"), module); |
| result.put("authResult", Boolean.FALSE); |
| result.put("authRefNum", respCode); |
| } else if (codeInt == 0) { |
| Debug.logWarning("In PayflowPro approved, but invalid flags; respCode/RESULT=" + respCode + ", avsCheckOkay=" + avsCheckOkay + ", cvv2CheckOkay=" + cvv2CheckOkay + "; AUTHCODE=" + parameters.get("AUTHCODE"), module); |
| result.put("authResult", Boolean.TRUE); |
| result.put("authCode", parameters.get("AUTHCODE")); |
| } else { |
| // other error |
| Debug.logWarning("In PayflowPro failing authorization; respCode/RESULT=" + respCode + ", avsCheckOkay=" + avsCheckOkay + ", cvv2CheckOkay=" + cvv2CheckOkay + "; AUTHCODE=" + parameters.get("AUTHCODE"), module); |
| result.put("authResult", Boolean.FALSE); |
| |
| // now check certain special conditions and report back through the generic params |
| if ("12".equals(respCode)) { |
| result.put("resultDeclined", Boolean.TRUE); |
| } else if ("50".equals(respCode)) { |
| result.put("resultNsf", Boolean.TRUE); |
| } else if ("23".equals(respCode)) { |
| result.put("resultBadCardNumber", Boolean.TRUE); |
| } else if ("24".equals(respCode)) { |
| result.put("resultBadExpire", Boolean.TRUE); |
| } |
| } |
| result.put("cvCode", cvvCode); |
| result.put("avsCode", avsCode); |
| result.put("authFlag", parameters.get("RESULT")); |
| result.put("authMessage", parameters.get("RESPMSG")); |
| } |
| |
| private static void parseCaptureResponse(String resp, Map<String, Object> result) { |
| Map<String, String> parameters = parseResponse(resp); |
| |
| String respCode = (String) parameters.get("RESULT"); |
| int codeInt = -999; // custom response code -- not from payflow docs |
| try { |
| codeInt = Integer.parseInt(respCode); |
| } catch (NumberFormatException e) { |
| Debug.logError(e, "Unable to parse response code; not a number!", module); |
| } |
| |
| if (codeInt == 0) { |
| result.put("captureResult", Boolean.TRUE); |
| result.put("captureCode", parameters.get("AUTHCODE")); |
| } else if (codeInt < 0) { |
| // communications error |
| Debug.logWarning("In PayflowPro failing capture; respCode/RESULT=" + respCode + "; PNREF=" + parameters.get("PNREF") + "; AUTHCODE=" + parameters.get("AUTHCODE"), module); |
| result.put("captureResult", Boolean.FALSE); |
| result.put("captureRefNum", respCode); |
| } else { |
| Debug.logWarning("In PayflowPro failing capture; respCode/RESULT=" + respCode + "; PNREF=" + parameters.get("PNREF") + "; AUTHCODE=" + parameters.get("AUTHCODE"), module); |
| result.put("captureResult", Boolean.FALSE); |
| } |
| result.put("captureRefNum", parameters.get("PNREF")); |
| result.put("captureFlag", parameters.get("RESULT")); |
| result.put("captureMessage", parameters.get("RESPMSG")); |
| } |
| |
| private static void parseVoidResponse(String resp, Map<String, Object> result) { |
| Map<String, String> parameters = parseResponse(resp); |
| |
| String respCode = (String) parameters.get("RESULT"); |
| int codeInt = -999; // custom response code -- not from payflow docs |
| try { |
| codeInt = Integer.parseInt(respCode); |
| } catch (NumberFormatException e) { |
| Debug.logError(e, "Unable to parse response code; not a number!", module); |
| } |
| |
| if (codeInt == 0) { |
| result.put("releaseResult", Boolean.TRUE); |
| result.put("releaseCode", parameters.get("AUTHCODE")); |
| } else if (codeInt < 0) { |
| // communications error |
| Debug.logWarning("In PayflowPro failing void; respCode/RESULT=" + respCode + "; PNREF=" + parameters.get("PNREF") + "; AUTHCODE=" + parameters.get("AUTHCODE"), module); |
| result.put("releaseResult", Boolean.FALSE); |
| result.put("releaseRefNum", respCode); |
| } else { |
| Debug.logWarning("In PayflowPro failing void; respCode/RESULT=" + respCode + "; PNREF=" + parameters.get("PNREF") + "; AUTHCODE=" + parameters.get("AUTHCODE"), module); |
| result.put("releaseResult", Boolean.FALSE); |
| } |
| result.put("releaseRefNum", parameters.get("PNREF")); |
| result.put("releaseFlag", parameters.get("RESULT")); |
| result.put("releaseMessage", parameters.get("RESPMSG")); |
| } |
| |
| private static void parseRefundResponse(String resp, Map<String, Object> result) { |
| Map<String, String> parameters = parseResponse(resp); |
| |
| String respCode = (String) parameters.get("RESULT"); |
| int codeInt = -999; // custom response code -- not from payflow docs |
| try { |
| codeInt = Integer.parseInt(respCode); |
| } catch (NumberFormatException e) { |
| Debug.logError(e, "Unable to parse response code; not a number!", module); |
| } |
| |
| if (codeInt == 0) { |
| result.put("refundResult", Boolean.TRUE); |
| result.put("refundCode", parameters.get("AUTHCODE")); |
| } else if (codeInt < 0) { |
| // communications error |
| Debug.logWarning("In PayflowPro failing refund; respCode/RESULT=" + respCode + "; PNREF=" + parameters.get("PNREF") + "; AUTHCODE=" + parameters.get("AUTHCODE"), module); |
| result.put("refundResult", Boolean.FALSE); |
| result.put("refundRefNum", respCode); |
| } else { |
| Debug.logWarning("In PayflowPro failing refund; respCode/RESULT=" + respCode + "; PNREF=" + parameters.get("PNREF") + "; AUTHCODE=" + parameters.get("AUTHCODE"), module); |
| result.put("refundResult", Boolean.FALSE); |
| } |
| result.put("refundRefNum", parameters.get("PNREF")); |
| result.put("refundFlag", parameters.get("RESULT")); |
| result.put("refundMessage", parameters.get("RESPMSG")); |
| } |
| |
| private static String parseContext(Map<String, ? extends Object> context) { |
| StringBuilder buf = new StringBuilder(); |
| Set<String> keySet = context.keySet(); |
| Iterator<String> i = keySet.iterator(); |
| |
| while (i.hasNext()) { |
| String name = (String) i.next(); |
| Object valueObj = context.get(name); |
| |
| if (valueObj == null || (valueObj instanceof String) && ((String) valueObj).length() == 0) { |
| // not valid; do nothing |
| } else { |
| String value = valueObj.toString(); |
| |
| // Payflow expects an unencoded name/value pair string |
| buf.append(name).append("="); |
| buf.append(value); |
| if (i.hasNext()) |
| buf.append("&"); |
| } |
| } |
| return buf.toString(); |
| } |
| |
| private static StringBuilder makeBaseParams(Delegator delegator, String paymentGatewayConfigId, String resource) { |
| StringBuilder buf = new StringBuilder(); |
| |
| try { |
| buf.append("PARTNER="); |
| buf.append(getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "partner", resource, "payment.verisign.partner", "VeriSign")); |
| buf.append("&"); |
| buf.append("VENDOR="); |
| buf.append(getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "vendor", resource, "payment.verisign.vendor", "nobody")); |
| buf.append("&"); |
| buf.append("USER="); |
| buf.append(getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "userId", resource, "payment.verisign.user", "nobody")); |
| buf.append("&"); |
| buf.append("PWD="); |
| buf.append(getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "pwd", resource, "payment.verisign.pwd", "password")); |
| } catch (Exception e) { |
| Debug.logError(e, module); |
| return null; |
| } |
| return buf; |
| } |
| |
| private static PayflowAPI init(Delegator delegator, String paymentGatewayConfigId, String resource, Map<String, ? extends Object> context) { |
| // No more used |
| // String certsPath = FlexibleStringExpander.expandString(getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "certsPath", resource, "payment.verisign.certsPath", "pfcerts"), context); |
| String hostAddress = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "hostAddress", resource, "payment.verisign.hostAddress", "pilot-payflowpro.paypal.com"); |
| Integer hostPort = Integer.decode(getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "hostPort", resource, "payment.verisign.hostPort", "443")); |
| Integer timeout = Integer.decode(getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "timeout", resource, "payment.verisign.timeout", "80")); |
| String proxyAddress = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "proxyAddress", resource, "payment.verisign.proxyAddress", ""); |
| Integer proxyPort = Integer.decode(getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "proxyPort", resource, "payment.verisign.proxyPort", "80")); |
| String proxyLogon = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "proxyLogon", resource, "payment.verisign.proxyLogon", ""); |
| String proxyPassword = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "proxyPassword", resource, "payment.verisign.proxyPassword", ""); |
| String logFileName = FlexibleStringExpander.expandString(getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "logFileName", resource, "payment.verisign.logFileName", ""), context); |
| Integer loggingLevel = Integer.decode(getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "loggingLevel", resource, "payment.verisign.loggingLevel", "6")); |
| Integer maxLogFileSize = Integer.decode(getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "maxLogFileSize", resource, "payment.verisign.maxLogFileSize", "1000000")); |
| boolean stackTraceOn = "Y".equalsIgnoreCase(getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, "stackTraceOn", resource, "payment.verisign.stackTraceOn", "N")); |
| |
| PayflowAPI pfp = new PayflowAPI(hostAddress, hostPort.intValue(), timeout.intValue(), proxyAddress, |
| proxyPort.intValue(), proxyLogon, proxyPassword); |
| SDKProperties.setLogFileName(logFileName); |
| SDKProperties.setLoggingLevel(loggingLevel); |
| SDKProperties.setMaxLogFileSize(maxLogFileSize); |
| SDKProperties.setStackTraceOn(stackTraceOn); |
| return pfp; |
| } |
| |
| private static String getPaymentGatewayConfigValue(Delegator delegator, String paymentGatewayConfigId, String paymentGatewayConfigParameterName, |
| String resource, String parameterName) { |
| String returnValue = ""; |
| if (UtilValidate.isNotEmpty(paymentGatewayConfigId)) { |
| try { |
| GenericValue payflowPro = EntityQuery.use(delegator).from("PaymentGatewayPayflowPro").where("paymentGatewayConfigId", paymentGatewayConfigId).queryOne(); |
| if (UtilValidate.isNotEmpty(payflowPro)) { |
| Object payflowProField = payflowPro.get(paymentGatewayConfigParameterName); |
| if (payflowProField != null) { |
| returnValue = payflowProField.toString().trim(); |
| } |
| } |
| } catch (GenericEntityException e) { |
| Debug.logError(e, module); |
| } |
| } else { |
| String value = EntityUtilProperties.getPropertyValue(resource, parameterName, delegator); |
| if (value != null) { |
| returnValue = value.trim(); |
| } |
| } |
| return returnValue; |
| } |
| |
| private static String getPaymentGatewayConfigValue(Delegator delegator, String paymentGatewayConfigId, String paymentGatewayConfigParameterName, |
| String resource, String parameterName, String defaultValue) { |
| String returnValue = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, paymentGatewayConfigParameterName, resource, parameterName); |
| if (UtilValidate.isEmpty(returnValue)) { |
| returnValue = defaultValue; |
| } |
| return returnValue; |
| } |
| |
| private static boolean comparePaymentGatewayConfigValue(Delegator delegator, String paymentGatewayConfigId, String paymentGatewayConfigParameterName, |
| String resource, String parameterName, String compareValue) { |
| boolean returnValue = false; |
| |
| String value = getPaymentGatewayConfigValue(delegator, paymentGatewayConfigId, paymentGatewayConfigParameterName, resource, parameterName, compareValue); |
| if (UtilValidate.isNotEmpty(value)) { |
| returnValue = value.trim().equalsIgnoreCase(compareValue); |
| } |
| return returnValue; |
| } |
| |
| /* |
| * RESULT values (and RESPMSG text) |
| * |
| 0 Approved |
| 1 User authentication failed. Error is caused by one or more of the following: |
| Login information is incorrect. Verify that USER, VENDOR, PARTNER, and |
| PASSWORD have been entered correctly. See Table 3.2 on page 26 for additional |
| information and field descriptions. |
| Invalid Processor information entered. Contact merchant bank to verify. |
| "Allowed IP Address" security feature implemented. The transaction is coming |
| from an unknown IP address. See VeriSign Manager online help for details on how |
| to use Manager to update the allowed IP addresses. |
| You are using a test (not active) account to submit a transaction to the live VeriSign |
| servers. Change the URL from pilot-payflowpro.paypal.com to payflowpro.paypal.com. |
| 2 Invalid tender type. Your merchant bank account does not support the following |
| credit card type that was submitted. |
| 3 Invalid transaction type. Transaction type is not appropriate for this transaction. For |
| example, you cannot credit an authorization-only transaction. |
| 4 Invalid amount format. Use the format: #####.## Do not include currency |
| symbols or commas. |
| 5 Invalid merchant information. Processor does not recognize your merchant account |
| information. Contact your bank account acquirer to resolve this problem. |
| 6 Invalid or unsupported currency code |
| 7 Field format error. Invalid information entered. See RESPMSG. |
| 8 Not a transaction server |
| 9 Too many parameters or invalid stream |
| 10 Too many line items |
| 11 Client time-out waiting for response |
| 12 Declined. Check the credit card number, expiration date, and transaction information to |
| make sure they were entered correctly. If this does not resolve the problem, have the |
| customer call their card issuing bank to resolve. |
| 13 Referral. Transaction cannot be approved electronically but can be approved with a |
| verbal authorization. Contact your merchant bank to obtain an authorization and submit |
| a manual Voice Authorization transaction. |
| 14 Invalid Client Certification ID. Check the HTTP header. If the tag, X-VPS-VIT- |
| CLIENT-CERTIFICATION-ID, is missing, RESULT code 14 is returned. |
| 19 Original transaction ID not found. The transaction ID you entered for this |
| transaction is not valid. See RESPMSG. |
| 20 Cannot find the customer reference number |
| 22 Invalid ABA number |
| |
| 23 Invalid account number. Check credit card number and re-submit. |
| 24 Invalid expiration date. Check and re-submit. |
| 25 Invalid Host Mapping. You are trying to process a tender type such as Discover Card, |
| but you are not set up with your merchant bank to accept this card type. |
| 26 Invalid vendor account |
| 27 Insufficient partner permissions |
| 28 Insufficient user permissions |
| 29 Invalid XML document. This could be caused by an unrecognized XML tag or a bad |
| XML format that cannot be parsed by the system. |
| 30 Duplicate transaction |
| 31 Error in adding the recurring profile |
| 32 Error in modifying the recurring profile |
| 33 Error in canceling the recurring profile |
| 34 Error in forcing the recurring profile |
| 35 Error in reactivating the recurring profile |
| 36 OLTP Transaction failed |
| 37 Invalid recurring profile ID |
| 50 Insufficient funds available in account |
| 99 General error. See RESPMSG. |
| 100 Transaction type not supported by host |
| 101 Time-out value too small |
| 102 Processor not available |
| 103 Error reading response from host |
| 104 Timeout waiting for processor response. Try your transaction again. |
| 105 Credit error. Make sure you have not already credited this transaction, or that this |
| transaction ID is for a creditable transaction. (For example, you cannot credit an |
| authorization.) |
| 106 Host not available |
| 107 Duplicate suppression time-out |
| |
| 108 Void error. See RESPMSG. Make sure the transaction ID entered has not already been |
| voided. If not, then look at the Transaction Detail screen for this transaction to see if it |
| has settled. (The Batch field is set to a number greater than zero if the transaction has |
| been settled). If the transaction has already settled, your only recourse is a reversal |
| (credit a payment or submit a payment for a credit). |
| 109 Time-out waiting for host response |
| 111 Capture error. Either an attempt to capture a transaction that is not an authorization |
| transaction type, or an attempt to capture an authorization transaction that has already |
| been captured. |
| 112 Failed AVS check. Address and ZIP code do not match. An authorization may still |
| exist on the cardholder account. |
| 113 Merchant sale total will exceed the sales cap with current transaction. ACH |
| transactions only. |
| 114 Card Security Code (CSC) Mismatch. An authorization may still exist on the |
| cardholder account. |
| 115 System busy, try again later |
| 116 VPS Internal error. Failed to lock terminal number |
| 117 Failed merchant rule check. One or more of the following three failures occurred: |
| An attempt was made to submit a transaction that failed to meet the security settings |
| specified on the Payflow Pro Java SDK Security Settings page. If the transaction |
| exceeded the Maximum Amount security setting, then no values are returned for AVS |
| or CSC. |
| AVS validation failed. The AVS return value should appear in the RESPMSG. |
| CSC validation failed. The CSC return value should appear in the RESPMSG. |
| 118 Invalid keywords found in string fields |
| 122 Merchant sale total will exceed the credit cap with current transaction. ACH |
| transactions only. |
| 125 Fraud Protection Services Filter _ Declined by filters |
| |
| 126 Fraud Protection Services Filter _ Flagged for review by filters |
| Important Note: Result code 126 indicates that a transaction triggered a fraud filter. |
| This is not an error, but a notice that the transaction is in a review status. The |
| transaction has been authorized but requires you to review and to manually accept the |
| transaction before it will be allowed to settle. |
| Result code 126 is intended to give you an idea of the kind of transaction that is |
| considered suspicious to enable you to evaluate whether you can benefit from using the |
| Fraud Protection Services. |
| To eliminate result 126, turn the filters off. |
| For more information, see the User Guide for Payflow Pro With Fraud Protection |
| Services or User Guide for Payflow Link Guide With Fraud Protection Services. |
| 127 Fraud Protection Services Filter _ Not processed by filters |
| 128 Fraud Protection Services Filter _ Declined by merchant after being flagged for |
| review by filters |
| 131 Version 1 Payflow Pro SDK client no longer supported. Upgrade to the most recent |
| version of the Payflow Pro client. |
| 150 Issuing bank timed out |
| 151 Issuing bank unavailable |
| 1000 Generic host error. This is a generic message returned by your credit card processor. |
| The RESPMSG will contain more information describing the error. |
| 1001 Buyer Authentication Service unavailable |
| 1002 Buyer Authentication Service _ Transaction timeout |
| 1003 Buyer Authentication Service _ Invalid client version |
| 1004 Buyer Authentication Service _ Invalid timeout value |
| 1011 Buyer Authentication Service unavailable |
| 1012 Buyer Authentication Service unavailable |
| 1013 Buyer Authentication Service unavailable |
| 1014 Buyer Authentication Service _ Merchant is not enrolled for Buyer |
| Authentication Service (3-D Secure). |
| 1016 Buyer Authentication Service _ 3-D Secure error response received. Instead of |
| receiving a PARes response to a Validate Authentication transaction, an error response |
| was received. |
| 1017 Buyer Authentication Service _ 3-D Secure error response is invalid. An error |
| response is received and the response is not well formed for a Validate Authentication |
| transaction. |
| |
| 1021 Buyer Authentication Service _ Invalid card type |
| 1022 Buyer Authentication Service _ Invalid or missing currency code |
| 1023 Buyer Authentication Service _ merchant status for 3D secure is invalid |
| 1041 Buyer Authentication Service _ Validate Authentication failed: missing or |
| invalid PARES |
| 1042 Buyer Authentication Service _ Validate Authentication failed: PARES format is |
| invalid |
| 1043 Buyer Authentication Service _ Validate Authentication failed: Cannot find |
| successful Verify Enrollment |
| 1044 Buyer Authentication Service _ Validate Authentication failed: Signature |
| validation failed for PARES |
| 1045 Buyer Authentication Service _ Validate Authentication failed: Mismatched or |
| invalid amount in PARES |
| 1046 Buyer Authentication Service _ Validate Authentication failed: Mismatched or |
| invalid acquirer in PARES |
| 1047 Buyer Authentication Service _ Validate Authentication failed: Mismatched or |
| invalid Merchant ID in PARES |
| 1048 Buyer Authentication Service _ Validate Authentication failed: Mismatched or |
| invalid card number in PARES |
| 1049 Buyer Authentication Service _ Validate Authentication failed: Mismatched or |
| invalid currency code in PARES |
| 1050 Buyer Authentication Service _ Validate Authentication failed: Mismatched or |
| invalid XID in PARES |
| 1051 Buyer Authentication Service _ Validate Authentication failed: Mismatched or |
| invalid order date in PARES |
| 1052 Buyer Authentication Service _ Validate Authentication failed: This PARES was |
| already validated for a previous Validate Authentication transaction |
| |
| */ |
| |
| /* RESULT for communication errors (less than 0) |
| * |
| -1 Failed to connect to host |
| -2 Failed to resolve hostname |
| -5 Failed to initialize SSL context |
| -6 Parameter list format error: & in name |
| -7 Parameter list format error: invalid [ ] name length clause |
| -8 SSL failed to connect to host |
| -9 SSL read failed |
| -10 SSL write failed |
| -11 Proxy authorization failed |
| -12 Timeout waiting for response |
| -13 Select failure |
| -14 Too many connections |
| -15 Failed to set socket options |
| -20 Proxy read failed |
| -21 Proxy write failed |
| -22 Failed to initialize SSL certificate |
| -23 Host address not specified |
| -24 Invalid transaction type |
| -25 Failed to create a socket |
| -26 Failed to initialize socket layer |
| -27 Parameter list format error: invalid [ ] name length clause |
| -28 Parameter list format error: name |
| -29 Failed to initialize SSL connection |
| -30 Invalid timeout value |
| |
| -31 The certificate chain did not validate, no local certificate found |
| -32 The certificate chain did not validate, common name did not match URL |
| - 40 Unexpected Request ID found in request. |
| - 41 Required Request ID not found in request |
| - 42 Required Response ID not found in request |
| - 43 Unexpected Response ID found in request |
| - 44 Response ID not found in the response received from the server |
| -99 Out of memory |
| -100 Parameter list cannot be empty |
| -103 Context initialization failed |
| -104 Unexpected transaction state |
| -105 Invalid name value pair request |
| -106 Invalid response format |
| -107 This XMLPay version is not supported |
| -108 The server certificate chain did not validate |
| -109 Unable to do logging |
| -111 The following error occurred while initializing from message file: <Details of |
| the error message> |
| -113 Unable to round and truncate the currency value simultaneously |
| */ |
| } |