org.broadleafcommerce.payment.service.module.PayPalPaymentModule.java Source code

Java tutorial

Introduction

Here is the source code for org.broadleafcommerce.payment.service.module.PayPalPaymentModule.java

Source

/*
 * Copyright 2008-2012 the original author or authors.
 *
 * Licensed 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.broadleafcommerce.payment.service.module;

import org.broadleafcommerce.common.money.Money;
import org.broadleafcommerce.common.time.SystemTime;
import org.broadleafcommerce.core.order.domain.FulfillmentGroup;
import org.broadleafcommerce.core.payment.domain.AmountItem;
import org.broadleafcommerce.core.payment.domain.PaymentInfo;
import org.broadleafcommerce.core.payment.domain.PaymentResponseItem;
import org.broadleafcommerce.core.payment.domain.PaymentResponseItemImpl;
import org.broadleafcommerce.core.payment.service.PaymentContext;
import org.broadleafcommerce.core.payment.service.exception.PaymentException;
import org.broadleafcommerce.core.payment.service.module.PaymentModule;
import org.broadleafcommerce.core.payment.service.type.PaymentInfoType;
import org.broadleafcommerce.vendor.paypal.service.payment.MessageConstants;
import org.broadleafcommerce.vendor.paypal.service.payment.PayPalPaymentService;
import org.broadleafcommerce.vendor.paypal.service.payment.message.PayPalErrorResponse;
import org.broadleafcommerce.vendor.paypal.service.payment.message.details.PayPalDetailsRequest;
import org.broadleafcommerce.vendor.paypal.service.payment.message.details.PayPalDetailsResponse;
import org.broadleafcommerce.vendor.paypal.service.payment.message.payment.*;
import org.broadleafcommerce.vendor.paypal.service.payment.type.PayPalMethodType;
import org.broadleafcommerce.vendor.paypal.service.payment.type.PayPalRefundType;
import org.broadleafcommerce.vendor.paypal.service.payment.type.PayPalTransactionType;
import org.springframework.util.Assert;

/**
 * 
 * @author jfischer
 *
 */
public class PayPalPaymentModule implements PaymentModule {

    protected PayPalPaymentService payPalPaymentService;

    @Override
    public PaymentResponseItem authorize(PaymentContext paymentContext) throws PaymentException {
        //authorize from SetExpressCheckout "Authorization"
        return commonAuthorizeOrSale(paymentContext, PayPalTransactionType.AUTHORIZE);
    }

    @Override
    public PaymentResponseItem reverseAuthorize(PaymentContext paymentContext) throws PaymentException {
        //void authorization from DoVoid
        PayPalPaymentRequest request = buildBasicRequest(paymentContext, PayPalTransactionType.REVERSEAUTHORIZE);
        request.setMethodType(PayPalMethodType.VOID);
        request.setCurrency(paymentContext.getPaymentInfo().getAmount().getCurrency().getCurrencyCode());

        Assert.isTrue(
                paymentContext.getPaymentInfo().getAdditionalFields().get(MessageConstants.TRANSACTIONID) != null,
                "The TRANSACTIONID value must be defined as an additional field in the PaymentInfo instance passed in.");
        request.setTransactionID(
                paymentContext.getPaymentInfo().getAdditionalFields().get(MessageConstants.TRANSACTIONID));

        PayPalPaymentResponse response;
        try {
            response = (PayPalPaymentResponse) payPalPaymentService.process(request);
        } catch (org.broadleafcommerce.common.vendor.service.exception.PaymentException e) {
            throw new PaymentException(e);
        }

        PaymentResponseItem responseItem = buildBasicResponse(response);
        setDecisionInformation(response, responseItem);
        responseItem.setAmountPaid(paymentContext.getPaymentInfo().getAmount());

        return responseItem;
    }

    @Override
    public PaymentResponseItem debit(PaymentContext paymentContext) throws PaymentException {
        //PayPal Capture
        PayPalPaymentRequest request = buildBasicRequest(paymentContext, PayPalTransactionType.CAPTURE);
        request.setMethodType(PayPalMethodType.CAPTURE);
        request.setCurrency(paymentContext.getPaymentInfo().getAmount().getCurrency().getCurrencyCode());

        Assert.isTrue(
                paymentContext.getPaymentInfo().getAdditionalFields().get(MessageConstants.TRANSACTIONID) != null,
                "The TRANSACTIONID value must be defined as an additional field in the PaymentInfo instance passed in.");
        request.setTransactionID(
                paymentContext.getPaymentInfo().getAdditionalFields().get(MessageConstants.TRANSACTIONID));

        PayPalPaymentResponse response;
        try {
            response = (PayPalPaymentResponse) payPalPaymentService.process(request);
        } catch (org.broadleafcommerce.common.vendor.service.exception.PaymentException e) {
            throw new PaymentException(e);
        }

        PaymentResponseItem responseItem = buildBasicResponse(response);
        setDecisionInformation(response, responseItem);
        responseItem.setAmountPaid(paymentContext.getPaymentInfo().getAmount());

        return responseItem;
    }

    @Override
    public PaymentResponseItem authorizeAndDebit(PaymentContext paymentContext) throws PaymentException {
        return commonAuthorizeOrSale(paymentContext, PayPalTransactionType.AUTHORIZEANDCAPTURE);
    }

    @Override
    public PaymentResponseItem credit(PaymentContext paymentContext) throws PaymentException {
        //PayPal Refund
        PayPalPaymentRequest request = buildBasicRequest(paymentContext, PayPalTransactionType.CREDIT);
        request.setMethodType(PayPalMethodType.REFUND);
        request.setCurrency(paymentContext.getPaymentInfo().getAmount().getCurrency().getCurrencyCode());

        Assert.isTrue(
                paymentContext.getPaymentInfo().getAdditionalFields().get(MessageConstants.REFUNDTYPE) != null,
                "The REFUNDTYPE value must be defined as an additional field in the PaymentInfo instance passed in.");
        request.setRefundType(PayPalRefundType.getInstance(
                paymentContext.getPaymentInfo().getAdditionalFields().get(MessageConstants.REFUNDTYPE)));
        Assert.isTrue(
                paymentContext.getPaymentInfo().getAdditionalFields().get(MessageConstants.TRANSACTIONID) != null,
                "The TRANSACTIONID value must be defined as an additional field in the PaymentInfo instance passed in.");
        request.setTransactionID(
                paymentContext.getPaymentInfo().getAdditionalFields().get(MessageConstants.TRANSACTIONID));

        PayPalPaymentResponse response;
        try {
            response = (PayPalPaymentResponse) payPalPaymentService.process(request);
        } catch (org.broadleafcommerce.common.vendor.service.exception.PaymentException e) {
            throw new PaymentException(e);
        }

        PaymentResponseItem responseItem = buildBasicResponse(response);
        setDecisionInformation(response, responseItem);
        setRefundInformation(response, responseItem);
        responseItem.setAmountPaid(paymentContext.getPaymentInfo().getAmount());

        return responseItem;
    }

    @Override
    public PaymentResponseItem voidPayment(PaymentContext paymentContext) throws PaymentException {
        throw new PaymentException("The void method is not supported by this module");
    }

    @Override
    public PaymentResponseItem balance(PaymentContext paymentContext) throws PaymentException {
        throw new PaymentException("The balance method is not supported by this module");
    }

    public PayPalDetailsResponse getExpressCheckoutDetails(PayPalDetailsRequest request) throws PaymentException {
        PayPalDetailsResponse response;
        try {
            response = (PayPalDetailsResponse) payPalPaymentService.process(request);
        } catch (org.broadleafcommerce.common.vendor.service.exception.PaymentException e) {
            throw new PaymentException(e);
        }

        return response;
    }

    @Override
    public Boolean isValidCandidate(PaymentInfoType paymentType) {
        return PaymentInfoType.PAYPAL.equals(paymentType);
    }

    protected PaymentResponseItem commonAuthorizeOrSale(PaymentContext paymentContext,
            PayPalTransactionType transactionType) throws PaymentException {
        PayPalPaymentRequest request = buildBasicRequest(paymentContext, transactionType);

        Assert.isTrue(paymentContext.getPaymentInfo().getAdditionalFields().containsKey(MessageConstants.SUBTOTAL),
                "Must specify a SUBTOTAL value on the additionalFields of the PaymentInfo instance.");
        Assert.isTrue(
                paymentContext.getPaymentInfo().getAdditionalFields().containsKey(MessageConstants.TOTALSHIPPING),
                "Must specify a TOTALSHIPPING value on the additionalFields of the PaymentInfo instance.");
        Assert.isTrue(paymentContext.getPaymentInfo().getAdditionalFields().containsKey(MessageConstants.TOTALTAX),
                "Must specify a TOTALTAX value on the additionalFields of the PaymentInfo instance.");
        PaymentInfo paymentInfo = paymentContext.getPaymentInfo();
        PayPalSummaryRequest summaryRequest = request.getSummaryRequest();
        summaryRequest.setSubTotal(new Money(paymentInfo.getAdditionalFields().get(MessageConstants.SUBTOTAL),
                paymentInfo.getAmount().getCurrency().getCurrencyCode()));
        summaryRequest
                .setTotalShipping(new Money(paymentInfo.getAdditionalFields().get(MessageConstants.TOTALSHIPPING),
                        paymentInfo.getAmount().getCurrency().getCurrencyCode()));
        summaryRequest.setTotalTax(new Money(paymentInfo.getAdditionalFields().get(MessageConstants.TOTALTAX),
                paymentInfo.getAmount().getCurrency().getCurrencyCode()));

        String token = paymentContext.getPaymentInfo().getAdditionalFields().get(MessageConstants.TOKEN);
        if (token == null) {
            if (PayPalTransactionType.AUTHORIZE.equals(transactionType)) {
                request.setMethodType(PayPalMethodType.AUTHORIZATION);
            } else {
                request.setMethodType(PayPalMethodType.CHECKOUT);
            }
        } else {
            request.setMethodType(PayPalMethodType.PROCESS);
            if (PayPalTransactionType.AUTHORIZE.equals(transactionType)) {
                request.setSecondaryMethodType(PayPalMethodType.AUTHORIZATION);
            } else {
                request.setSecondaryMethodType(PayPalMethodType.CHECKOUT);
            }
            request.setPayerID(paymentContext.getPaymentInfo().getAdditionalFields().get(MessageConstants.PAYERID));
            request.setToken(token);
        }
        request.setCurrency(paymentContext.getPaymentInfo().getAmount().getCurrency().getCurrencyCode());
        for (AmountItem amountItem : paymentContext.getPaymentInfo().getAmountItems()) {
            PayPalItemRequest itemRequest = new PayPalItemRequest();
            itemRequest.setDescription(amountItem.getDescription());
            itemRequest.setShortDescription(amountItem.getShortDescription());
            itemRequest.setQuantity(amountItem.getQuantity());
            itemRequest.setUnitPrice(new Money(amountItem.getUnitPrice()));
            itemRequest.setSystemId(amountItem.getSystemId());
            request.getItemRequests().add(itemRequest);
        }

        for (FulfillmentGroup fulfillmentGroup : paymentContext.getPaymentInfo().getOrder()
                .getFulfillmentGroups()) {
            if (fulfillmentGroup.getAddress() != null) {
                PayPalShippingRequest shippingRequest = new PayPalShippingRequest();
                shippingRequest.setShipToName(fulfillmentGroup.getAddress().getFirstName() + " "
                        + fulfillmentGroup.getAddress().getLastName());
                shippingRequest.setShipToStreet(fulfillmentGroup.getAddress().getAddressLine1());
                shippingRequest.setShipToStreet2(fulfillmentGroup.getAddress().getAddressLine2());
                shippingRequest.setShipToCity(fulfillmentGroup.getAddress().getCity());
                if (fulfillmentGroup.getAddress().getState() != null) {
                    shippingRequest.setShipToState(fulfillmentGroup.getAddress().getState().getAbbreviation());
                }
                shippingRequest.setShipToZip(fulfillmentGroup.getAddress().getPostalCode());
                if (fulfillmentGroup.getAddress().getCountry() != null) {
                    shippingRequest
                            .setShipToCountryCode(fulfillmentGroup.getAddress().getCountry().getAbbreviation());
                }
                shippingRequest.setShipToPhoneNum(fulfillmentGroup.getAddress().getPrimaryPhone());
                request.getShippingRequests().add(shippingRequest);
            }
        }

        PayPalPaymentResponse response;
        try {
            response = (PayPalPaymentResponse) payPalPaymentService.process(request);
        } catch (org.broadleafcommerce.common.vendor.service.exception.PaymentException e) {
            throw new PaymentException(e);
        }

        PaymentResponseItem responseItem = buildBasicResponse(response);
        if (PayPalMethodType.PROCESS.equals(request.getMethodType())) {
            setDecisionInformation(response, responseItem);
        } else if (PayPalMethodType.CHECKOUT.equals(request.getMethodType())
                || PayPalMethodType.AUTHORIZATION.equals(request.getMethodType())) {
            responseItem.getAdditionalFields().put(MessageConstants.REDIRECTURL, response.getUserRedirectUrl());
        }
        responseItem.setAmountPaid(paymentContext.getPaymentInfo().getAmount());

        return responseItem;
    }

    protected void setDecisionInformation(PayPalPaymentResponse response, PaymentResponseItem responseItem) {
        responseItem.setTransactionId(response.getPaymentInfo().getTransactionId());
        if (response.getPaymentInfo().getParentTransactionId() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.PARENTTRANSACTIONID,
                    response.getPaymentInfo().getParentTransactionId());
        }
        if (response.getPaymentInfo().getReceiptId() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.RECEIPTID,
                    response.getPaymentInfo().getReceiptId());
        }
        if (response.getPaymentInfo().getExchangeRate() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.EXCHANGERATE,
                    response.getPaymentInfo().getExchangeRate().toString());
        }
        if (response.getPaymentInfo().getPaymentStatusType() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.PAYMENTSTATUS,
                    response.getPaymentInfo().getPaymentStatusType().getType());
        }
        if (response.getPaymentInfo().getPendingReasonType() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.PENDINGREASON,
                    response.getPaymentInfo().getPendingReasonType().getType());
        }
        if (response.getPaymentInfo().getReasonCodeType() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.REASONCODE,
                    response.getPaymentInfo().getReasonCodeType().getType());
        }
        if (response.getPaymentInfo().getHoldDecisionType() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.HOLDDECISION,
                    response.getPaymentInfo().getHoldDecisionType().getType());
        }
        if (response.getPaymentInfo().getFeeAmount() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.FEEAMOUNT,
                    response.getPaymentInfo().getFeeAmount().toString());
        }
        if (response.getPaymentInfo().getSettleAmount() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.SETTLEAMOUNT,
                    response.getPaymentInfo().getSettleAmount().toString());
        }
        if (response.getPaymentInfo().getTaxAmount() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.TAXAMOUNT,
                    response.getPaymentInfo().getTaxAmount().toString());
        }
    }

    protected void setRefundInformation(PayPalPaymentResponse response, PaymentResponseItem responseItem) {
        if (response.getRefundInfo().getRefundTransactionId() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.REFUNDTRANSACTIONID,
                    response.getRefundInfo().getRefundTransactionId());
        }
        if (response.getRefundInfo().getFeeRefundAmount() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.FEEREFUNDAMT,
                    response.getRefundInfo().getFeeRefundAmount().toString());
        }
        if (response.getRefundInfo().getGrossRefundAmount() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.GROSSREFUNDAMT,
                    response.getRefundInfo().getGrossRefundAmount().toString());
        }
        if (response.getRefundInfo().getNetRefundAmount() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.NETREFUNDAMT,
                    response.getRefundInfo().getNetRefundAmount().toString());
        }
        if (response.getRefundInfo().getTotalRefundAmount() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.TOTALREFUNDEDAMT,
                    response.getRefundInfo().getTotalRefundAmount().toString());
        }
        if (response.getRefundInfo().getRefundInfo() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.REFUNDINFO,
                    response.getRefundInfo().getRefundInfo());
        }
        if (response.getRefundInfo().getRefundStatusType() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.REFUNDSTATUS,
                    response.getRefundInfo().getRefundStatusType().getType());
        }
        if (response.getRefundInfo().getPendingReasonType() != null) {
            responseItem.getAdditionalFields().put(MessageConstants.PENDINGREASON,
                    response.getRefundInfo().getPendingReasonType().getType());
        }
    }

    protected PayPalPaymentRequest buildBasicRequest(PaymentContext paymentContext,
            PayPalTransactionType transactionType) {
        PayPalPaymentRequest request = new PayPalPaymentRequest();
        request.setTransactionType(transactionType);
        Assert.isTrue(paymentContext.getPaymentInfo().getReferenceNumber().length() <= 127,
                "The reference number for the paypal request cannot be greater than 127 characters");
        request.setReferenceNumber(paymentContext.getPaymentInfo().getReferenceNumber());

        PaymentInfo paymentInfo = paymentContext.getPaymentInfo();
        PayPalSummaryRequest summaryRequest = new PayPalSummaryRequest();
        summaryRequest.setGrandTotal(paymentInfo.getAmount());
        request.setSummaryRequest(summaryRequest);

        return request;
    }

    protected PaymentResponseItem buildBasicResponse(PayPalPaymentResponse response) {
        PaymentResponseItem responseItem = new PaymentResponseItemImpl();
        responseItem.setTransactionTimestamp(SystemTime.asDate());
        responseItem.setReferenceNumber(response.getResponseToken());
        responseItem.setTransactionSuccess(response.isSuccessful());
        responseItem.setAuthorizationCode(response.getAck());
        responseItem.setMiddlewareResponseCode(response.getAck());
        responseItem.setMiddlewareResponseText(response.getAck());
        int counter = 0;
        for (PayPalErrorResponse errorResponse : response.getErrorResponses()) {
            String errorCode = errorResponse.getErrorCode();
            if (counter == 0) {
                responseItem.setMiddlewareResponseCode(errorCode);
                responseItem.setMiddlewareResponseText(errorResponse.getLongMessage());
            }
            counter++;
            responseItem.getAdditionalFields().put(MessageConstants.MODULEERRORCODE, errorCode);
            responseItem.getAdditionalFields().put(MessageConstants.MODULEERRORSEVERITYCODE + "_" + errorCode,
                    errorResponse.getSeverityCode());
            responseItem.getAdditionalFields().put(MessageConstants.MODULEERRORLONGMESSAGE + "_" + errorCode,
                    errorResponse.getLongMessage());
            responseItem.getAdditionalFields().put(MessageConstants.MODULEERRORSHORTMESSAGE + "_" + errorCode,
                    errorResponse.getShortMessage());
        }
        responseItem.getAdditionalFields().putAll(response.getPassThroughErrors());

        return responseItem;
    }

    public PayPalPaymentService getPayPalPaymentService() {
        return payPalPaymentService;
    }

    public void setPayPalPaymentService(PayPalPaymentService payPalPaymentService) {
        this.payPalPaymentService = payPalPaymentService;
    }
}