com.payu.sdk.helper.HttpClientHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.payu.sdk.helper.HttpClientHelper.java

Source

/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 developers-payu-latam
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.payu.sdk.helper;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;

import com.payu.sdk.PayU;
import com.payu.sdk.constants.Constants;
import com.payu.sdk.constants.Resources.RequestMethod;
import com.payu.sdk.exceptions.AuthenticationException;
import com.payu.sdk.exceptions.ConnectionException;
import com.payu.sdk.exceptions.PayUException;
import com.payu.sdk.exceptions.SDKException;
import com.payu.sdk.exceptions.SDKException.ErrorCode;
import com.payu.sdk.model.Language;
import com.payu.sdk.model.MediaType;
import com.payu.sdk.model.Merchant;
import com.payu.sdk.model.error.ErrorResponse;
import com.payu.sdk.model.request.CommandRequest;
import com.payu.sdk.model.request.Request;
import com.payu.sdk.utils.JaxbUtil;
import com.payu.sdk.utils.LoggerUtil;
import com.payu.sdk.utils.xml.XmlFormatter;

/**
 * The PayU SDK Helper for Http Client
 *
 * @author PayU Latam
 * @since 1.0.0
 * @version 1.0.0, 21/08/2013
 * @see HttpClient
 */
public final class HttpClientHelper {

    /** The connection timeout in ms. */
    private static final int CONNECTION_TIMEOUT = 10000;

    /** The socket timeout in ms. */
    public static final int SOCKET_TIMEOUT = 85000;

    /**
     * Default private empty constructor
     */
    private HttpClientHelper() {
    }

    /**
     * Sends the post request to the server
     *
     * @param request
     *            The request to be sent to the server
     * @param requestMethod
     *            The request method to be sent to the server
     * @return The response in a xml format
     * @throws ConnectionException
     * @throws SDKException
     */
    public static String sendRequest(Request request, RequestMethod requestMethod)
            throws PayUException, ConnectionException {

        return sendRequest(request, requestMethod, SOCKET_TIMEOUT);
    }

    /**
     * Sends the post request to the server
     *
     * @param request
     *            The request to be sent to the server
     * @param requestMethod
     *            The request method to be sent to the server
     * @param the socket time out.
     * @return The response in a xml format
     * @throws ConnectionException
     * @throws SDKException
     */
    public static String sendRequest(Request request, RequestMethod requestMethod, Integer socketTimeOut)
            throws PayUException, ConnectionException {

        HttpClient httpClient = new DefaultHttpClient();
        setHttpClientParameters(httpClient.getParams(), socketTimeOut);

        httpClient = WebClientDevWrapper.wrapClient(httpClient);

        try {

            HttpRequestBase httpRequest = createHttpRequest(request, requestMethod);

            HttpResponse httpResponse = httpClient.execute(httpRequest);

            if (httpResponse == null) {
                throw new ConnectionException("No response from server");
            }

            Integer httpStatus = httpResponse.getStatusLine().getStatusCode();

            Integer[] successStatus = { HttpStatus.SC_OK, HttpStatus.SC_CREATED, HttpStatus.SC_ACCEPTED };

            if (Arrays.asList(successStatus).contains(httpStatus)) {

                return getXmlResponse(httpResponse);
            } else {
                return manageResponse(httpResponse);
            }

        } catch (PayUException e) {
            throw e;
        } catch (Exception e) {
            throw new ConnectionException(e.getMessage(), e);
        } finally {
            httpClient.getConnectionManager().shutdown();
        }
    }

    /**
     * Manage the response with specific exceptions
     *
     * @param httpResponse
     *            The response sent by the server
     * @return The reason of the error response
     * @throws IOException
     * @throws SDKException
     */
    private static String manageResponse(HttpResponse httpResponse) throws IOException, SDKException {
        int httpStatus = httpResponse.getStatusLine().getStatusCode();
        switch (httpStatus) {
        case HttpStatus.SC_UNAUTHORIZED: {
            throw new AuthenticationException("Invalid credentials");
        }
        case HttpStatus.SC_SERVICE_UNAVAILABLE: {
            throw new ConnectionException(httpResponse.getStatusLine().getReasonPhrase());
        }
        case HttpStatus.SC_NOT_FOUND: {
            String error;
            try {
                error = getErrorMessage(httpResponse);
            } catch (Exception exception) {
                throw new ConnectionException(httpResponse.getStatusLine().toString());
            }
            throw new PayUException(ErrorCode.NO_RESULTS_FOUND, error);
        }
        case HttpStatus.SC_UNPROCESSABLE_ENTITY: {
            String error = getErrorMessage(httpResponse);
            throw new PayUException(ErrorCode.INVALID_PARAMETERS, error);
        }
        default: {
            String error = getErrorMessage(httpResponse);
            throw new ConnectionException(error);
        }
        }
    }

    /**
     * Gets the response error message
     *
     * @param httpResponse
     *            The response sent by the server
     * @return The message associated to the error response
     * @throws PayUException
     * @throws IOException
     */
    private static String getErrorMessage(HttpResponse httpResponse) throws PayUException, IOException {

        String error = httpResponse.getStatusLine().getReasonPhrase();

        String xml = getXmlResponse(httpResponse);

        if (xml != null && !xml.isEmpty()) {

            ErrorResponse response;

            try {

                response = JaxbUtil.convertXmlToJava(ErrorResponse.class, xml);

            } catch (PayUException ex) {
                LoggerUtil.debug("Invalid XML entity");
                return error;
            }

            if (response.getDescription() != null) {
                return response.getDescription();
            }

            if (response.getErrorList() != null && response.getErrorList().length > 0) {
                return Arrays.toString(response.getErrorList());
            }

        }

        return error;
    }

    /**
     * Get xml response
     *
     * @param httpResponse
     *            The response sent by the server
     * @return The xml associated to the response
     * @throws PayUException
     * @throws IOException
     */
    private static String getXmlResponse(HttpResponse httpResponse) throws PayUException, IOException {

        HttpEntity entity = httpResponse.getEntity();
        InputStream inputStream = (InputStream) entity.getContent();
        String xml = inputStreamToString(inputStream);

        if (!xml.isEmpty()) {
            LoggerUtil.debug("Response:\n {0}", XmlFormatter.prettyFormat(xml));
        }

        return xml;
    }

    /**
     * Sets the parameters to the request
     *
     * @param params
     *            The parameters to be set
     * @param the socket time out.
     */
    private static void setHttpClientParameters(HttpParams params, Integer socketTimeOut) {

        HttpProtocolParams.setContentCharset(params, Constants.DEFAULT_ENCODING);
        HttpConnectionParams.setConnectionTimeout(params, CONNECTION_TIMEOUT);
        HttpConnectionParams.setSoTimeout(params, socketTimeOut);
    }

    /**
     * Creates a http request with the given request
     *
     * @param request
     *            The original request
     * @param requestMethod
     *            The request method to be sent to the server
     * @return The created http request
     * @throws URISyntaxException
     * @throws UnsupportedEncodingException
     * @throws PayUException
     * @throws ConnectionException
     */
    private static HttpRequestBase createHttpRequest(Request request, RequestMethod requestMethod)
            throws URISyntaxException, UnsupportedEncodingException, PayUException, ConnectionException {

        String url = request.getRequestUrl(requestMethod);

        URI postUrl = new URI(url);

        HttpRequestBase httpMethod;

        LoggerUtil.debug("sending request...");

        String xml = Constants.EMPTY_STRING;

        switch (requestMethod) {
        case POST:
            httpMethod = new HttpPost();
            break;
        case GET:
            httpMethod = new HttpGet();
            break;
        case DELETE:
            httpMethod = new HttpDelete();
            break;
        case PUT:
            httpMethod = new HttpPut();
            break;
        default:
            throw new ConnectionException("Invalid connection method");
        }

        httpMethod.addHeader("Content-Type", MediaType.XML.getCode() + "; charset=utf-8");

        Language lng = request.getLanguage() != null ? request.getLanguage() : PayU.language;
        httpMethod.setHeader("Accept-Language", lng.name());

        // Sets the method entity
        if (httpMethod instanceof HttpEntityEnclosingRequestBase) {
            xml = request.toXml();
            ((HttpEntityEnclosingRequestBase) httpMethod)
                    .setEntity(new StringEntity(xml, Constants.DEFAULT_ENCODING));
            LoggerUtil.debug("Message to send:\n {0}", xml);
        }

        httpMethod.setURI(postUrl);

        addRequestHeaders(request, httpMethod);

        LoggerUtil.debug("URL to send:\n {0}", url);

        return httpMethod;
    }

    /**
     * Updates the base request to add the header
     *
     * @param requestBase
     *            The request that needs its header
     */
    private static void addRequestHeaders(Request apiRequest, HttpRequestBase requestBase) {

        requestBase.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.XML.getCode() + "; charset=utf-8");
        requestBase.addHeader(HttpHeaders.ACCEPT, MediaType.XML.getCode());

        String username = getUserName(apiRequest);

        String password = getPassword(apiRequest);

        Credentials credentials = new UsernamePasswordCredentials(username, password);

        requestBase.addHeader(BasicScheme.authenticate(credentials, Constants.DEFAULT_ENCODING, false));
    }

    /**
     * Gets the user name.
     * 
     * @param apiRequest
     * @return
     */
    private static String getUserName(Request apiRequest) {

        Merchant merchant = null;

        if (apiRequest instanceof CommandRequest) {
            merchant = ((CommandRequest) apiRequest).getMerchant();
        }

        return apiRequest.getApiLogin() != null ? apiRequest.getApiLogin()
                : merchant != null && merchant.getApiLogin() != null ? merchant.getApiLogin() : PayU.apiLogin;
    }

    /**
     * Gets the password.
     * 
     * @param apiRequest
     * @return
     */
    private static String getPassword(Request apiRequest) {

        Merchant merchant = null;

        if (apiRequest instanceof CommandRequest) {
            merchant = ((CommandRequest) apiRequest).getMerchant();
        }

        return apiRequest.getApiKey() != null ? apiRequest.getApiKey()
                : merchant != null && merchant.getApiKey() != null ? merchant.getApiKey() : PayU.apiKey;
    }

    /**
     * Transforms an incoming InputStream into a String
     *
     * @param inputStream
     *            The stream to be transformed
     * @return The transformed stream
     * @throws IOException
     * @throws PayUException
     */
    private static String inputStreamToString(InputStream inputStream) throws IOException, PayUException {

        BufferedReader bufferedReader = new BufferedReader(
                new InputStreamReader(inputStream, Constants.DEFAULT_ENCODING));
        StringBuilder stringBuilder = new StringBuilder();

        String line = null;
        try {
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line).append(Constants.LINE_SEPARATOR);
            }
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new PayUException(PayUException.ErrorCode.XML_DESERIALIZATION_ERROR, e);
            }
        }

        return stringBuilder.toString();
    }
}