예제 #1
0
  public static Map<String, Object> doVoid(DispatchContext dctx, Map<String, Object> context) {
    GenericValue payPalConfig = getPaymentMethodGatewayPayPal(dctx, context, null);
    Locale locale = (Locale) context.get("locale");
    if (payPalConfig == null) {
      return ServiceUtil.returnError(
          UtilProperties.getMessage(
              resource, "AccountingPayPalPaymentGatewayConfigCannotFind", locale));
    }
    GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
    GenericValue authTrans = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference);
    NVPEncoder encoder = new NVPEncoder();
    encoder.add("METHOD", "DoVoid");
    encoder.add("AUTHORIZATIONID", authTrans.getString("referenceNum"));
    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("releaseResult", false);
      result.put("releaseRefNum", authTrans.getString("referenceNum"));
      result.put("releaseAmount", BigDecimal.ZERO);
      if (errors.size() == 1) {
        Map.Entry<String, String> error = errors.entrySet().iterator().next();
        result.put("releaseCode", error.getKey());
        result.put("releaseMessage", error.getValue());
      } else {
        result.put(
            "releaseMessage",
            "Multiple errors occurred, please refer to the gateway response messages");
        result.put("internalRespMsgs", errors);
      }
    } else {
      result.put("releaseResult", true);
      // PayPal voids the entire order amount minus any captures, that's a little difficult to
      // figure out here
      // so until further testing proves we should do otherwise I'm just going to return requested
      // void amount
      result.put("releaseAmount", context.get("releaseAmount"));
      result.put("releaseRefNum", decoder.get("AUTHORIZATIONID"));
    }
    return result;
  }
예제 #2
0
  private static NVPDecoder sendNVPRequest(GenericValue payPalConfig, NVPEncoder encoder)
      throws PayPalException {
    NVPCallerServices caller = new NVPCallerServices();
    try {
      APIProfile profile = ProfileFactory.createSignatureAPIProfile();
      profile.setAPIUsername(payPalConfig.getString("apiUserName"));
      profile.setAPIPassword(payPalConfig.getString("apiPassword"));
      profile.setSignature(payPalConfig.getString("apiSignature"));
      profile.setEnvironment(payPalConfig.getString("apiEnvironment"));
      caller.setAPIProfile(profile);
    } catch (PayPalException e) {
      Debug.logError(e.getMessage(), module);
    }

    String requestMessage = encoder.encode();
    String responseMessage = caller.call(requestMessage);

    NVPDecoder decoder = new NVPDecoder();
    decoder.decode(responseMessage);
    if (!"Success".equals(decoder.get("ACK"))) {
      Debug.logError(
          "A response other than success was received from PayPal: " + responseMessage, module);
    }

    return decoder;
  }
예제 #3
0
  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;
  }
예제 #4
0
  public static Map<String, Object> doRefund(DispatchContext dctx, Map<String, Object> context) {
    Locale locale = (Locale) context.get("locale");
    GenericValue payPalConfig = getPaymentMethodGatewayPayPal(dctx, context, null);
    if (payPalConfig == null) {
      return ServiceUtil.returnError(
          UtilProperties.getMessage(
              resource, "AccountingPayPalPaymentGatewayConfigCannotFind", locale));
    }
    GenericValue orderPaymentPreference = (GenericValue) context.get("orderPaymentPreference");
    GenericValue captureTrans =
        PaymentGatewayServices.getCaptureTransaction(orderPaymentPreference);
    BigDecimal refundAmount = (BigDecimal) context.get("refundAmount");
    NVPEncoder encoder = new NVPEncoder();
    encoder.add("METHOD", "RefundTransaction");
    encoder.add("TRANSACTIONID", captureTrans.getString("referenceNum"));
    encoder.add("REFUNDTYPE", "Partial");
    encoder.add("CURRENCYCODE", captureTrans.getString("currencyUomId"));
    encoder.add("AMT", refundAmount.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
    encoder.add("NOTE", "Order #" + orderPaymentPreference.getString("orderId"));
    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("refundResult", false);
      result.put("refundRefNum", captureTrans.getString("referenceNum"));
      result.put("refundAmount", BigDecimal.ZERO);
      if (errors.size() == 1) {
        Map.Entry<String, String> error = errors.entrySet().iterator().next();
        result.put("refundCode", error.getKey());
        result.put("refundMessage", error.getValue());
      } else {
        result.put(
            "refundMessage",
            "Multiple errors occurred, please refer to the gateway response messages");
        result.put("internalRespMsgs", errors);
      }
    } else {
      result.put("refundResult", true);
      result.put("refundAmount", new BigDecimal(decoder.get("GROSSREFUNDAMT")));
      result.put("refundRefNum", decoder.get("REFUNDTRANSACTIONID"));
    }
    return result;
  }
예제 #5
0
  public static Map<String, Object> doCapture(DispatchContext dctx, Map<String, Object> context) {
    GenericValue paymentPref = (GenericValue) context.get("orderPaymentPreference");
    BigDecimal captureAmount = (BigDecimal) context.get("captureAmount");
    GenericValue payPalConfig =
        getPaymentMethodGatewayPayPal(dctx, context, PaymentGatewayServices.AUTH_SERVICE_TYPE);
    GenericValue authTrans = (GenericValue) context.get("authTrans");
    Locale locale = (Locale) context.get("locale");
    if (authTrans == null) {
      authTrans = PaymentGatewayServices.getAuthTransaction(paymentPref);
    }

    NVPEncoder encoder = new NVPEncoder();
    encoder.add("METHOD", "DoCapture");
    encoder.add("AUTHORIZATIONID", authTrans.getString("referenceNum"));
    encoder.add("AMT", captureAmount.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
    encoder.add("CURRENCYCODE", authTrans.getString("currencyUomId"));
    encoder.add("COMPLETETYPE", "NotComplete");

    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("captureResult", false);
      result.put("captureRefNum", "N/A");
      result.put("captureAmount", BigDecimal.ZERO);
      if (errors.size() == 1) {
        Map.Entry<String, String> error = errors.entrySet().iterator().next();
        result.put("captureCode", error.getKey());
        result.put("captureMessage", error.getValue());
      } else {
        result.put(
            "captureMessage",
            "Multiple errors occurred, please refer to the gateway response messages");
        result.put("internalRespMsgs", errors);
      }
    } else {
      result.put("captureResult", true);
      result.put("captureAmount", new BigDecimal(decoder.get("AMT")));
      result.put("captureRefNum", 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;
  }
예제 #6
0
  public String ReauthorizationCode(String authorizationId, String amount, String currencyCode) {

    NVPCallerServices caller = null;
    NVPEncoder encoder = new NVPEncoder();
    NVPDecoder decoder = new NVPDecoder();

    try {
      caller = new NVPCallerServices();
      APIProfile profile = ProfileFactory.createSignatureAPIProfile();
      /*
      WARNING: Do not embed plaintext credentials in your application code.
      Doing so is insecure and against best practices.
      Your API credentials must be handled securely. Please consider
      encrypting them for use in any production environment, and ensure
      that only authorized individuals may view or modify them.
      */

      // Set up your API credentials, PayPal end point, API operation and version.
      profile.setAPIUsername("sdk-three_api1.sdk.com");
      profile.setAPIPassword("QFZCWN5HZM8VBG7Q");
      profile.setSignature("AVGidzoSQiGWu.lGj3z15HLczXaaAcK6imHawrjefqgclVwBe8imgCHZ");
      profile.setEnvironment("sandbox");
      profile.setSubject("");
      caller.setAPIProfile(profile);
      encoder.add("VERSION", "51.0");
      encoder.add("METHOD", "DoReauthorization");

      // Add request-specific fields to the request string.
      encoder.add("AuthorizationID", authorizationId);
      encoder.add("AMT", amount);
      encoder.add("CURRENCYCODE", currencyCode);

      // Execute the API operation and obtain the response.
      String NVPRequest = encoder.encode();
      String NVPResponse = caller.call(NVPRequest);
      decoder.decode(NVPResponse);

    } catch (Exception ex) {
      ex.printStackTrace();
    }

    return decoder.get("ACK");
  }
예제 #7
0
  public static Map<String, Object> setExpressCheckout(
      DispatchContext dctx, Map<String, ? extends Object> context) {
    ShoppingCart cart = (ShoppingCart) context.get("cart");
    Locale locale = cart.getLocale();
    if (cart == null || cart.items().size() <= 0) {
      return ServiceUtil.returnError(
          UtilProperties.getMessage(resource, "AccountingPayPalShoppingCartIsEmpty", locale));
    }

    GenericValue payPalConfig = getPaymentMethodGatewayPayPal(dctx, context, null);
    if (payPalConfig == null) {
      return ServiceUtil.returnError(
          UtilProperties.getMessage(
              resource, "AccountingPayPalPaymentGatewayConfigCannotFind", locale));
    }

    NVPEncoder encoder = new NVPEncoder();

    // Set Express Checkout Request Parameters
    encoder.add("METHOD", "SetExpressCheckout");
    String token = (String) cart.getAttribute("payPalCheckoutToken");
    if (UtilValidate.isNotEmpty(token)) {
      encoder.add("TOKEN", token);
    }
    encoder.add("RETURNURL", payPalConfig.getString("returnUrl"));
    encoder.add("CANCELURL", payPalConfig.getString("cancelReturnUrl"));
    if (!cart.shippingApplies()) {
      encoder.add("NOSHIPPING", "1");
    } else {
      encoder.add("CALLBACK", payPalConfig.getString("shippingCallbackUrl"));
      encoder.add("CALLBACKTIMEOUT", "6");
      // Default to no
      String reqConfirmShipping =
          "Y".equals(payPalConfig.getString("requireConfirmedShipping")) ? "1" : "0";
      encoder.add("REQCONFIRMSHIPPING", reqConfirmShipping);
      // Default shipment method
      encoder.add("L_SHIPPINGOPTIONISDEFAULT0", "true");
      encoder.add("L_SHIPPINGOPTIONNAME0", "Calculated Offline");
      encoder.add("L_SHIPPINGOPTIONAMOUNT0", "0.00");
    }
    encoder.add("ALLOWNOTE", "1");
    encoder.add("INSURANCEOPTIONOFFERED", "false");
    if (UtilValidate.isNotEmpty(payPalConfig.getString("imageUrl"))) ;
    encoder.add("PAYMENTACTION", "Order");

    // Cart information
    try {
      addCartDetails(encoder, cart);
    } catch (GenericEntityException e) {
      Debug.logError(e, module);
      return ServiceUtil.returnError(
          UtilProperties.getMessage(
              resource, "AccountingPayPalErrorDuringRetrievingCartDetails", locale));
    }

    NVPDecoder decoder;
    try {
      decoder = sendNVPRequest(payPalConfig, encoder);
    } catch (PayPalException e) {
      Debug.logError(e, module);
      return ServiceUtil.returnError(e.getMessage());
    }

    Map<String, String> errorMessages = getErrorMessageMap(decoder);
    if (UtilValidate.isNotEmpty(errorMessages)) {
      if (errorMessages.containsKey("10411")) {
        // Token has expired, get a new one
        cart.setAttribute("payPalCheckoutToken", null);
        return PayPalServices.setExpressCheckout(dctx, context);
      }
      return ServiceUtil.returnError(UtilMisc.toList(errorMessages.values()));
    }

    token = decoder.get("TOKEN");
    cart.setAttribute("payPalCheckoutToken", token);
    TokenWrapper tokenWrapper = new TokenWrapper(token);
    cart.setAttribute("payPalCheckoutTokenObj", tokenWrapper);
    PayPalServices.tokenCartMap.put(tokenWrapper, new WeakReference<ShoppingCart>(cart));
    return ServiceUtil.returnSuccess();
  }
예제 #8
0
  // 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();
  }
예제 #9
0
  public static Map<String, Object> getExpressCheckout(
      DispatchContext dctx, Map<String, Object> context) {
    Locale locale = (Locale) context.get("locale");
    LocalDispatcher dispatcher = dctx.getDispatcher();
    Delegator delegator = dctx.getDelegator();

    ShoppingCart cart = (ShoppingCart) context.get("cart");
    GenericValue payPalConfig = getPaymentMethodGatewayPayPal(dctx, context, null);
    if (payPalConfig == null) {
      return ServiceUtil.returnError(
          UtilProperties.getMessage(
              resource, "AccountingPayPalPaymentGatewayConfigCannotFind", locale));
    }

    NVPEncoder encoder = new NVPEncoder();
    encoder.add("METHOD", "GetExpressCheckoutDetails");
    String token = (String) cart.getAttribute("payPalCheckoutToken");
    if (UtilValidate.isNotEmpty(token)) {
      encoder.add("TOKEN", token);
    } else {
      return ServiceUtil.returnError(
          UtilProperties.getMessage(resource, "AccountingPayPalTokenNotFound", locale));
    }

    NVPDecoder decoder;
    try {
      decoder = sendNVPRequest(payPalConfig, encoder);
    } catch (PayPalException e) {
      Debug.logError(e, module);
      return ServiceUtil.returnError(e.getMessage());
    }

    if (UtilValidate.isNotEmpty(decoder.get("NOTE"))) {
      cart.addOrderNote(decoder.get("NOTE"));
    }

    if (cart.getUserLogin() == null) {
      try {
        GenericValue userLogin =
            EntityQuery.use(delegator)
                .from("UserLogin")
                .where("userLoginId", "anonymous")
                .queryOne();
        try {
          cart.setUserLogin(userLogin, dispatcher);
        } catch (CartItemModifyException e) {
          Debug.logError(e, module);
          return ServiceUtil.returnError(e.getMessage());
        }
      } catch (GenericEntityException e) {
        Debug.logError(e, module);
        return ServiceUtil.returnError(e.getMessage());
      }
    }
    boolean anon = "anonymous".equals(cart.getUserLogin().getString("userLoginId"));
    // Even if anon, a party could already have been created
    String partyId = cart.getOrderPartyId();
    if (partyId == null && anon) {
      // Check nothing has been set on the anon userLogin either
      partyId = cart.getUserLogin() != null ? cart.getUserLogin().getString("partyId") : null;
      cart.setOrderPartyId(partyId);
    }
    if (partyId != null) {
      GenericValue party = null;
      try {
        party = EntityQuery.use(delegator).from("Party").where("partyId", partyId).queryOne();
      } catch (GenericEntityException e) {
        Debug.logError(e, module);
      }
      if (party == null) {
        partyId = null;
      }
    }

    Map<String, Object> inMap = FastMap.newInstance();
    Map<String, Object> outMap = null;
    // Create the person if necessary
    boolean newParty = false;
    if (partyId == null) {
      newParty = true;
      inMap.put("userLogin", cart.getUserLogin());
      inMap.put("personalTitle", decoder.get("SALUTATION"));
      inMap.put("firstName", decoder.get("FIRSTNAME"));
      inMap.put("middleName", decoder.get("MIDDLENAME"));
      inMap.put("lastName", decoder.get("LASTNAME"));
      inMap.put("suffix", decoder.get("SUFFIX"));
      try {
        outMap = dispatcher.runSync("createPerson", inMap);
        partyId = (String) outMap.get("partyId");
        cart.setOrderPartyId(partyId);
        cart.getUserLogin().setString("partyId", partyId);
        inMap.clear();
        inMap.put("userLogin", cart.getUserLogin());
        inMap.put("partyId", partyId);
        inMap.put("roleTypeId", "CUSTOMER");
        dispatcher.runSync("createPartyRole", inMap);
      } catch (GenericServiceException e) {
        Debug.logError(e, module);
        return ServiceUtil.returnError(e.getMessage());
      }
    }
    // Create a new email address if necessary
    String emailContactMechId = null;
    String emailContactPurposeTypeId = "PRIMARY_EMAIL";
    String emailAddress = decoder.get("EMAIL");
    if (!newParty) {
      EntityCondition cond =
          EntityCondition.makeCondition(
              UtilMisc.toList(
                  EntityCondition.makeCondition(
                      UtilMisc.toMap("partyId", partyId, "contactMechTypeId", "EMAIL_ADDRESS")),
                  EntityCondition.makeCondition(
                      EntityFunction.UPPER_FIELD("infoString"),
                      EntityComparisonOperator.EQUALS,
                      EntityFunction.UPPER(emailAddress))));

      try {
        GenericValue matchingEmail =
            EntityQuery.use(delegator)
                .from("PartyAndContactMech")
                .where(cond)
                .orderBy("fromDate")
                .filterByDate()
                .queryFirst();
        if (matchingEmail != null) {
          emailContactMechId = matchingEmail.getString("contactMechId");
        } else {
          // No email found so we'll need to create one but first check if it should be PRIMARY or
          // just BILLING
          long primaryEmails =
              EntityQuery.use(delegator)
                  .from("PartyContactWithPurpose")
                  .where(
                      "partyId",
                      partyId,
                      "contactMechTypeId",
                      "EMAIL_ADDRESS",
                      "contactMechPurposeTypeId",
                      "PRIMARY_EMAIL")
                  .filterByDate(
                      "contactFromDate", "contactThruDate", "purposeFromDate", "purposeThruDate")
                  .queryCount();
          if (primaryEmails > 0) emailContactPurposeTypeId = "BILLING_EMAIL";
        }
      } catch (GenericEntityException e) {
        Debug.logError(e, module);
      }
    }
    if (emailContactMechId == null) {
      inMap.clear();
      inMap.put("userLogin", cart.getUserLogin());
      inMap.put("contactMechPurposeTypeId", emailContactPurposeTypeId);
      inMap.put("emailAddress", emailAddress);
      inMap.put("partyId", partyId);
      inMap.put("roleTypeId", "CUSTOMER");
      inMap.put("verified", "Y"); // Going to assume PayPal has taken care of this for us
      inMap.put("fromDate", UtilDateTime.nowTimestamp());
      try {
        outMap = dispatcher.runSync("createPartyEmailAddress", inMap);
        emailContactMechId = (String) outMap.get("contactMechId");
      } catch (GenericServiceException e) {
        Debug.logError(e, module);
        return ServiceUtil.returnError(e.getMessage());
      }
    }
    cart.addContactMech("ORDER_EMAIL", emailContactMechId);

    // Phone number
    String phoneNumber = decoder.get("PHONENUM");
    String phoneContactId = null;
    if (phoneNumber != null) {
      inMap.clear();
      if (phoneNumber.startsWith("+")) {
        // International, format is +XXX XXXXXXXX which we'll split into countryCode + contactNumber
        String[] phoneNumbers = phoneNumber.split(" ");
        inMap.put("countryCode", StringUtil.removeNonNumeric(phoneNumbers[0]));
        inMap.put("contactNumber", phoneNumbers[1]);
      } else {
        // U.S., format is XXX-XXX-XXXX which we'll split into areaCode + contactNumber
        inMap.put("countryCode", "1");
        String[] phoneNumbers = phoneNumber.split("-");
        inMap.put("areaCode", phoneNumbers[0]);
        inMap.put("contactNumber", phoneNumbers[1] + phoneNumbers[2]);
      }
      inMap.put("userLogin", cart.getUserLogin());
      inMap.put("partyId", partyId);
      try {
        outMap = dispatcher.runSync("createUpdatePartyTelecomNumber", inMap);
        phoneContactId = (String) outMap.get("contactMechId");
        cart.addContactMech("PHONE_BILLING", phoneContactId);
      } catch (GenericServiceException e) {
        Debug.logError(e, module);
      }
    }
    // Create a new Postal Address if necessary
    String postalContactId = null;
    boolean needsShippingPurpose = true;
    // if the cart for some reason already has a billing address, we'll leave it be
    boolean needsBillingPurpose = (cart.getContactMech("BILLING_LOCATION") == null);
    Map<String, Object> postalMap = FastMap.newInstance();
    postalMap.put("toName", decoder.get("SHIPTONAME"));
    postalMap.put("address1", decoder.get("SHIPTOSTREET"));
    postalMap.put("address2", decoder.get("SHIPTOSTREET2"));
    postalMap.put("city", decoder.get("SHIPTOCITY"));
    String countryGeoId =
        PayPalServices.getCountryGeoIdFromGeoCode(decoder.get("SHIPTOCOUNTRYCODE"), delegator);
    postalMap.put("countryGeoId", countryGeoId);
    postalMap.put(
        "stateProvinceGeoId",
        parseStateProvinceGeoId(decoder.get("SHIPTOSTATE"), countryGeoId, delegator));
    postalMap.put("postalCode", decoder.get("SHIPTOZIP"));
    if (!newParty) {
      // We want an exact match only
      EntityCondition cond =
          EntityCondition.makeCondition(
              UtilMisc.toList(
                  EntityCondition.makeCondition(postalMap),
                  EntityCondition.makeCondition(
                      UtilMisc.toMap(
                          "attnName",
                          null,
                          "directions",
                          null,
                          "postalCodeExt",
                          null,
                          "postalCodeGeoId",
                          null)),
                  EntityCondition.makeCondition("partyId", partyId)));
      try {
        GenericValue postalMatch =
            EntityQuery.use(delegator)
                .from("PartyAndPostalAddress")
                .where(cond)
                .orderBy("fromDate")
                .filterByDate()
                .queryFirst();
        if (postalMatch != null) {
          postalContactId = postalMatch.getString("contactMechId");
          List<GenericValue> postalPurposes =
              EntityQuery.use(delegator)
                  .from("PartyContactMechPurpose")
                  .where("partyId", partyId, "contactMechId", postalContactId)
                  .filterByDate()
                  .queryList();
          List<Object> purposeStrings =
              EntityUtil.getFieldListFromEntityList(
                  postalPurposes, "contactMechPurposeTypeId", false);
          if (UtilValidate.isNotEmpty(purposeStrings)
              && purposeStrings.contains("SHIPPING_LOCATION")) {
            needsShippingPurpose = false;
          }
          if (needsBillingPurpose
              && UtilValidate.isNotEmpty(purposeStrings)
              && purposeStrings.contains("BILLING_LOCATION")) {
            needsBillingPurpose = false;
          }
        }
      } catch (GenericEntityException e) {
        Debug.logError(e, module);
      }
    }
    if (postalContactId == null) {
      postalMap.put("userLogin", cart.getUserLogin());
      postalMap.put("fromDate", UtilDateTime.nowTimestamp());
      try {
        outMap = dispatcher.runSync("createPartyPostalAddress", postalMap);
        postalContactId = (String) outMap.get("contactMechId");
      } catch (GenericServiceException e) {
        Debug.logError(e, module);
        return ServiceUtil.returnError(e.getMessage());
      }
    }
    if (needsShippingPurpose || needsBillingPurpose) {
      inMap.clear();
      inMap.put("userLogin", cart.getUserLogin());
      inMap.put("contactMechId", postalContactId);
      inMap.put("partyId", partyId);
      try {
        if (needsShippingPurpose) {
          inMap.put("contactMechPurposeTypeId", "SHIPPING_LOCATION");
          dispatcher.runSync("createPartyContactMechPurpose", inMap);
        }
        if (needsBillingPurpose) {
          inMap.put("contactMechPurposeTypeId", "BILLING_LOCATION");
          dispatcher.runSync("createPartyContactMechPurpose", inMap);
        }
      } catch (GenericServiceException e) {
        // Not the end of the world, we'll carry on
        Debug.logInfo(e.getMessage(), module);
      }
    }

    // Load the selected shipping method - thanks to PayPal's less than sane API all we've to work
    // with is the shipping option label
    // that was shown to the customer
    String shipMethod = decoder.get("SHIPPINGOPTIONNAME");
    if ("Calculated Offline".equals(shipMethod)) {
      cart.setAllCarrierPartyId("_NA_");
      cart.setAllShipmentMethodTypeId("NO_SHIPPING");
    } else {
      String[] shipMethodSplit = shipMethod.split(" - ");
      cart.setAllCarrierPartyId(shipMethodSplit[0]);
      String shippingMethodTypeDesc =
          StringUtils.join(shipMethodSplit, " - ", 1, shipMethodSplit.length);
      try {
        GenericValue shipmentMethod =
            EntityQuery.use(delegator)
                .from("ProductStoreShipmentMethView")
                .where(
                    "productStoreId",
                    cart.getProductStoreId(),
                    "partyId",
                    shipMethodSplit[0],
                    "roleTypeId",
                    "CARRIER",
                    "description",
                    shippingMethodTypeDesc)
                .queryFirst();
        cart.setAllShipmentMethodTypeId(shipmentMethod.getString("shipmentMethodTypeId"));
      } catch (GenericEntityException e1) {
        Debug.logError(e1, module);
      }
    }
    // Get rid of any excess ship groups
    List<CartShipInfo> shipGroups = cart.getShipGroups();
    for (int i = 1; i < shipGroups.size(); i++) {
      Map<ShoppingCartItem, BigDecimal> items = cart.getShipGroupItems(i);
      for (Map.Entry<ShoppingCartItem, BigDecimal> entry : items.entrySet()) {
        cart.positionItemToGroup(entry.getKey(), entry.getValue(), i, 0, false);
      }
    }
    cart.cleanUpShipGroups();
    cart.setAllShippingContactMechId(postalContactId);
    Map<String, Object> result =
        ShippingEvents.getShipGroupEstimate(dispatcher, delegator, cart, 0);
    if (result.get(ModelService.RESPONSE_MESSAGE).equals(ModelService.RESPOND_ERROR)) {
      return ServiceUtil.returnError((String) result.get(ModelService.ERROR_MESSAGE));
    }

    BigDecimal shippingTotal = (BigDecimal) result.get("shippingTotal");
    if (shippingTotal == null) {
      shippingTotal = BigDecimal.ZERO;
    }
    cart.setItemShipGroupEstimate(shippingTotal, 0);
    CheckOutHelper cho = new CheckOutHelper(dispatcher, delegator, cart);
    try {
      cho.calcAndAddTax();
    } catch (GeneralException e) {
      Debug.logError(e, module);
      return ServiceUtil.returnError(e.getMessage());
    }

    // Create the PayPal payment method
    inMap.clear();
    inMap.put("userLogin", cart.getUserLogin());
    inMap.put("partyId", partyId);
    inMap.put("contactMechId", postalContactId);
    inMap.put("fromDate", UtilDateTime.nowTimestamp());
    inMap.put("payerId", decoder.get("PAYERID"));
    inMap.put("expressCheckoutToken", token);
    inMap.put("payerStatus", decoder.get("PAYERSTATUS"));

    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();
    BigDecimal maxAmount = cart.getGrandTotal().setScale(2, BigDecimal.ROUND_HALF_UP);
    cart.addPaymentAmount(paymentMethodId, maxAmount, true);

    return ServiceUtil.returnSuccess();
  }
예제 #10
0
 private static void addCartDetails(NVPEncoder encoder, ShoppingCart cart)
     throws GenericEntityException {
   encoder.add("CURRENCYCODE", cart.getCurrency());
   int line = 0;
   for (ShoppingCartItem item : cart.items()) {
     encoder.add("L_NUMBER" + line, item.getProductId());
     encoder.add("L_NAME" + line, item.getName());
     encoder.add(
         "L_AMT" + line,
         item.getBasePrice().setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
     encoder.add("L_QTY" + line, item.getQuantity().toBigInteger().toString());
     line++;
     BigDecimal otherAdjustments = item.getOtherAdjustments();
     if (otherAdjustments.compareTo(BigDecimal.ZERO) != 0) {
       encoder.add("L_NUMBER" + line, item.getProductId());
       encoder.add("L_NAME" + line, item.getName() + " Adjustments");
       encoder.add(
           "L_AMT" + line, otherAdjustments.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
       encoder.add("L_QTY" + line, "1");
       line++;
     }
   }
   BigDecimal otherAdjustments = cart.getOrderOtherAdjustmentTotal();
   if (otherAdjustments.compareTo(BigDecimal.ZERO) != 0) {
     encoder.add("L_NUMBER" + line, "N/A");
     encoder.add("L_NAME" + line, "Order Adjustments");
     encoder.add(
         "L_AMT" + line, otherAdjustments.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
     encoder.add("L_QTY" + line, "1");
     line++;
   }
   encoder.add("ITEMAMT", cart.getSubTotal().add(otherAdjustments).setScale(2).toPlainString());
   encoder.add("SHIPPINGAMT", "0.00");
   encoder.add("TAXAMT", "0.00");
   encoder.add("AMT", cart.getSubTotal().add(otherAdjustments).setScale(2).toPlainString());
   // NOTE: The docs say this is optional but then won't work without it
   encoder.add("MAXAMT", cart.getSubTotal().add(otherAdjustments).setScale(2).toPlainString());
 }
예제 #11
0
  public static Map<String, Object> payPalCheckoutUpdate(
      DispatchContext dctx, Map<String, Object> context) {
    LocalDispatcher dispatcher = dctx.getDispatcher();
    Delegator delegator = dctx.getDelegator();
    HttpServletRequest request = (HttpServletRequest) context.get("request");
    HttpServletResponse response = (HttpServletResponse) context.get("response");

    Map<String, Object> paramMap = UtilHttp.getParameterMap(request);

    String token = (String) paramMap.get("TOKEN");
    WeakReference<ShoppingCart> weakCart = tokenCartMap.get(new TokenWrapper(token));
    ShoppingCart cart = null;
    if (weakCart != null) {
      cart = weakCart.get();
    }
    if (cart == null) {
      Debug.logError("Could locate the ShoppingCart for token " + token, module);
      return ServiceUtil.returnSuccess();
    }
    // Since most if not all of the shipping estimate codes requires a persisted contactMechId we'll
    // create one and
    // then delete once we're done, now is not the time to worry about updating everything
    String contactMechId = null;
    Map<String, Object> inMap = FastMap.newInstance();
    inMap.put("address1", paramMap.get("SHIPTOSTREET"));
    inMap.put("address2", paramMap.get("SHIPTOSTREET2"));
    inMap.put("city", paramMap.get("SHIPTOCITY"));
    String countryGeoCode = (String) paramMap.get("SHIPTOCOUNTRY");
    String countryGeoId = PayPalServices.getCountryGeoIdFromGeoCode(countryGeoCode, delegator);
    if (countryGeoId == null) {
      return ServiceUtil.returnSuccess();
    }
    inMap.put("countryGeoId", countryGeoId);
    inMap.put(
        "stateProvinceGeoId",
        parseStateProvinceGeoId((String) paramMap.get("SHIPTOSTATE"), countryGeoId, delegator));
    inMap.put("postalCode", paramMap.get("SHIPTOZIP"));

    try {
      GenericValue userLogin =
          EntityQuery.use(delegator)
              .from("UserLogin")
              .where("userLoginId", "system")
              .cache()
              .queryOne();
      inMap.put("userLogin", userLogin);
    } catch (GenericEntityException e) {
      Debug.logError(e, module);
    }
    boolean beganTransaction = false;
    Transaction parentTransaction = null;
    try {
      parentTransaction = TransactionUtil.suspend();
      beganTransaction = TransactionUtil.begin();
    } catch (GenericTransactionException e1) {
      Debug.logError(e1, module);
    }
    try {
      Map<String, Object> outMap = dispatcher.runSync("createPostalAddress", inMap);
      contactMechId = (String) outMap.get("contactMechId");
    } catch (GenericServiceException e) {
      Debug.logError(e.getMessage(), module);
      return ServiceUtil.returnSuccess();
    }
    try {
      TransactionUtil.commit(beganTransaction);
      if (parentTransaction != null) TransactionUtil.resume(parentTransaction);
    } catch (GenericTransactionException e) {
      Debug.logError(e, module);
    }
    // clone the cart so we can modify it temporarily
    CheckOutHelper coh = new CheckOutHelper(dispatcher, delegator, cart);
    String oldShipAddress = cart.getShippingContactMechId();
    coh.setCheckOutShippingAddress(contactMechId);
    ShippingEstimateWrapper estWrapper = new ShippingEstimateWrapper(dispatcher, cart, 0);
    int line = 0;
    NVPEncoder encoder = new NVPEncoder();
    encoder.add("METHOD", "CallbackResponse");

    for (GenericValue shipMethod : estWrapper.getShippingMethods()) {
      BigDecimal estimate = estWrapper.getShippingEstimate(shipMethod);
      // Check that we have a valid estimate (allowing zero value estimates for now)
      if (estimate == null || estimate.compareTo(BigDecimal.ZERO) < 0) {
        continue;
      }
      cart.setAllShipmentMethodTypeId(shipMethod.getString("shipmentMethodTypeId"));
      cart.setAllCarrierPartyId(shipMethod.getString("partyId"));
      try {
        coh.calcAndAddTax();
      } catch (GeneralException e) {
        Debug.logError(e, module);
        continue;
      }
      String estimateLabel =
          shipMethod.getString("partyId") + " - " + shipMethod.getString("description");
      encoder.add("L_SHIPINGPOPTIONLABEL" + line, estimateLabel);
      encoder.add(
          "L_SHIPPINGOPTIONAMOUNT" + line,
          estimate.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
      // Just make this first one default for now
      encoder.add("L_SHIPPINGOPTIONISDEFAULT" + line, line == 0 ? "true" : "false");
      encoder.add(
          "L_TAXAMT" + line,
          cart.getTotalSalesTax().setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
      line++;
    }
    String responseMsg = null;
    try {
      responseMsg = encoder.encode();
    } catch (PayPalException e) {
      Debug.logError(e, module);
    }
    if (responseMsg != null) {
      try {
        response.setContentLength(responseMsg.getBytes("UTF-8").length);
      } catch (UnsupportedEncodingException e) {
        Debug.logError(e, module);
      }

      try {
        Writer writer = response.getWriter();
        writer.write(responseMsg);
        writer.close();
      } catch (IOException e) {
        Debug.logError(e, module);
      }
    }

    // Remove the temporary ship address
    try {
      GenericValue postalAddress =
          EntityQuery.use(delegator)
              .from("PostalAddress")
              .where("contactMechId", contactMechId)
              .queryOne();
      postalAddress.remove();
      GenericValue contactMech =
          EntityQuery.use(delegator)
              .from("ContactMech")
              .where("contactMechId", contactMechId)
              .queryOne();
      contactMech.remove();
    } catch (GenericEntityException e) {
      Debug.logError(e, module);
    }
    coh.setCheckOutShippingAddress(oldShipAddress);
    return ServiceUtil.returnSuccess();
  }