<commit_before>/*
 * Copyright 2014-2015 Groupon, Inc
 *
 * Groupon 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.killbill.billing.plugin.adyen.client.payment.service;

import java.io.Closeable;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.killbill.adyen.common.BrowserInfo;
import org.killbill.adyen.payment.AnyType2AnyTypeMap;
import org.killbill.adyen.payment.ModificationRequest;
import org.killbill.adyen.payment.ModificationResult;
import org.killbill.adyen.payment.PaymentRequest;
import org.killbill.adyen.payment.PaymentRequest3D;
import org.killbill.adyen.payment.PaymentResult;
import org.killbill.billing.plugin.adyen.api.AdyenPaymentPluginApi;
import org.killbill.billing.plugin.adyen.client.model.OrderData;
import org.killbill.billing.plugin.adyen.client.model.PaymentData;
import org.killbill.billing.plugin.adyen.client.model.PaymentInfo;
import org.killbill.billing.plugin.adyen.client.model.PaymentModificationResponse;
import org.killbill.billing.plugin.adyen.client.model.PaymentProvider;
import org.killbill.billing.plugin.adyen.client.model.PaymentServiceProviderResult;
import org.killbill.billing.plugin.adyen.client.model.PurchaseResult;
import org.killbill.billing.plugin.adyen.client.model.SplitSettlementData;
import org.killbill.billing.plugin.adyen.client.model.UserData;
import org.killbill.billing.plugin.adyen.client.model.paymentinfo.Card;
import org.killbill.billing.plugin.adyen.client.payment.builder.AdyenRequestFactory;
import org.killbill.billing.plugin.adyen.client.payment.converter.PaymentInfoConverterManagement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;

public class AdyenPaymentServiceProviderPort implements Closeable {

    private static final Logger logger = LoggerFactory.getLogger("adyen.port");

    private final PaymentInfoConverterManagement paymentInfoConverterManagement;
    private final AdyenRequestFactory adyenRequestFactory;
    private final AdyenPaymentRequestSender adyenPaymentRequestSender;

    public AdyenPaymentServiceProviderPort(final PaymentInfoConverterManagement paymentInfoConverterManagement,
                                           final AdyenRequestFactory adyenRequestFactory,
                                           final AdyenPaymentRequestSender adyenPaymentRequestSender) {
        this.paymentInfoConverterManagement = paymentInfoConverterManagement;
        this.adyenRequestFactory = adyenRequestFactory;
        this.adyenPaymentRequestSender = adyenPaymentRequestSender;
    }

    @Override
    public void close() throws IOException {
        adyenPaymentRequestSender.close();
    }

    public PurchaseResult authorise(final Long amount,
                                    final PaymentData paymentData,
                                    final OrderData orderData,
                                    final UserData userData,
                                    final String termUrl,
                                    final SplitSettlementData splitSettlementData) {
        logger.info("authorise Start");

        Preconditions.checkNotNull(paymentData.getPaymentTxnInternalRef(), "paymentTxnInternalRef");

        final PaymentInfo paymentInfo = paymentData.getPaymentInfo();
        Preconditions.checkNotNull(paymentInfo, "paymentInfo");
        Preconditions.checkNotNull(paymentInfo.getPaymentProvider(), "paymentProvider");
        Preconditions.checkNotNull(paymentInfo.getPaymentProvider().getCurrency(), "currency");
        Preconditions.checkNotNull(paymentInfo.getPaymentProvider().getCountryIsoCode(), "countryIsoCode");

        final PaymentRequest request = adyenRequestFactory.createPaymentRequest(amount, orderData, paymentData, userData, termUrl, splitSettlementData);
        return authorise(request, paymentInfo.getPaymentProvider().getCountryIsoCode(), paymentData, !paymentInfo.getPaymentProvider().send3DSTermUrl() ? termUrl : null);
    }

    @VisibleForTesting
    PurchaseResult authorise(final PaymentRequest request, final String countryIsoCode, final PaymentData paymentData, final String termUrl) {
        final AdyenCallResult<PaymentResult> adyenCallResult = adyenPaymentRequestSender.authorise(countryIsoCode, request);

        if (!adyenCallResult.receivedWellFormedResponse()) {
            return handleTechnicalFailureAtPurchase("authorize", paymentData, adyenCallResult);
        }

        logger.info("received adyen authorize response: {}", adyenCallResult);
        final PaymentResult result = adyenCallResult.getResult().get();
        final PurchaseResult purchaseResult;
        final PaymentServiceProviderResult paymentServiceProviderResult = PaymentServiceProviderResult.getPaymentResultForId(result.getResultCode());
        if (paymentServiceProviderResult != PaymentServiceProviderResult.REDIRECT_SHOPPER) {
            purchaseResult = new PurchaseResult(paymentServiceProviderResult,
                                                result.getAuthCode(),
                                                result.getPspReference(),
                                                result.getRefusalReason(),
                                                result.getResultCode(),
                                                paymentData.getPaymentInternalRef());
        } else {
            logger.info("proceed with 3dSecure flow");
            final Map<String, String> formParams = new HashMap<String, String>();
            formParams.put(AdyenPaymentPluginApi.PROPERTY_PA_REQ, result.getPaRequest());
            formParams.put(AdyenPaymentPluginApi.PROPERTY_MD, result.getMd());
            formParams.put(AdyenPaymentPluginApi.PROPERTY_DCC_AMOUNT_VALUE, result.getDccAmount() == null ? null : String.valueOf(result.getDccAmount().getValue()));
            formParams.put(AdyenPaymentPluginApi.PROPERTY_DCC_AMOUNT_CURRENCY, result.getDccAmount() == null ? null : result.getDccAmount().getCurrency());
            formParams.put(AdyenPaymentPluginApi.PROPERTY_DCC_SIGNATURE, result.getDccSignature());
            formParams.put(AdyenPaymentPluginApi.PROPERTY_ISSUER_URL, result.getIssuerUrl());
            formParams.putAll(extractMpiAdditionalData(result));
            if (termUrl != null) {
                formParams.put(AdyenPaymentPluginApi.PROPERTY_TERM_URL, termUrl);
            }

                purchaseResult = new PurchaseResult(paymentServiceProviderResult,
                                                    result.getAuthCode(),
                                                    result.getPspReference(),
                                                    result.getRefusalReason(),
                                                    result.getResultCode(),
                                                    paymentData.getPaymentInternalRef(),
                                                    result.getIssuerUrl(),
                                                    formParams);
            }

        logger.info("authorise Done", purchaseResult);
        return purchaseResult;
    }

    private PurchaseResult handleTechnicalFailureAtPurchase(final String callKey, final PaymentData paymentData, final AdyenCallResult<PaymentResult> adyenCallResult) {
        logger.info("payment {} call failed for internalReference: {} because of: {}", callKey, paymentData.getPaymentInternalRef(), adyenCallResult);
        return new PurchaseResult(paymentData.getPaymentInternalRef(), adyenCallResult.getResponseStatus().get());
    }

    public PurchaseResult authorize3DSecure(final Long billedAmount,
                                            final PaymentData<Card> paymentData,
                                            final UserData userData,
                                            final Map<String, String[]> requestParameterMap,
                                            final SplitSettlementData splitSettlementData) {
        logger.info("authorize3DSecure Start {} [}", billedAmount, userData);

        final Card paymentInfo = paymentData.getPaymentInfo();
        final BrowserInfo info = (BrowserInfo) paymentInfoConverterManagement.getBrowserInfoFor3DSecureAuth(billedAmount, paymentData.getPaymentInfo());
        final PaymentRequest3D request = adyenRequestFactory.paymentRequest3d(paymentData.getPaymentInternalRef(),
                                                                              paymentInfo,
                                                                              info,
                                                                              requestParameterMap,
                                                                              splitSettlementData,
                                                                              userData.getIP(),
                                                                              userData.getEmail(),
                                                                              userData.getCustomerId());
        final AdyenCallResult<PaymentResult> adyenCallResult = adyenPaymentRequestSender.authorise3D(paymentInfo.getPaymentProvider().getCountryIsoCode(), request);

        if (!adyenCallResult.receivedWellFormedResponse()) {
            handleTechnicalFailureAtPurchase("3dSecureAuthorise", paymentData, adyenCallResult);
        }

        logger.info("received adyen 3dSecure authorize response: {}", adyenCallResult);
        if (adyenCallResult.getResult().isPresent()) {
            final PaymentResult result = adyenCallResult.getResult().get();
            final PurchaseResult purchaseResult;
            final PaymentServiceProviderResult paymentServiceProviderResult = PaymentServiceProviderResult.getPaymentResultForId(result.getResultCode());
            if (paymentServiceProviderResult != PaymentServiceProviderResult.REDIRECT_SHOPPER) {
                purchaseResult = new PurchaseResult(PaymentServiceProviderResult.getPaymentResultForId(result.getResultCode()),
                                                    result.getAuthCode(),
                                                    result.getPspReference(),
                                                    result.getRefusalReason(),
                                                    result.getResultCode(),
                                                    paymentData.getPaymentInternalRef());
            } else {
                final Map<String, String> formParams = new HashMap<String, String>();
                formParams.put("PaReq", result.getPaRequest());
                formParams.put("MD", result.getMd());

                purchaseResult = new PurchaseResult(paymentServiceProviderResult,
                                                    result.getAuthCode(),
                                                    result.getPspReference(),
                                                    result.getRefusalReason(),
                                                    result.getResultCode(),
                                                    paymentData.getPaymentInternalRef(),
                                                    result.getIssuerUrl(),
                                                    formParams);
            }

            logger.info("authorize3DSecure Done {}", purchaseResult);
            return purchaseResult;
        } else {
            logger.error("authorize3DSecure Error {}", adyenCallResult);
            return new PurchaseResult(paymentData.getPaymentInternalRef(), adyenCallResult.getResponseStatus().get());
        }
    }

    public PaymentModificationResponse refund(final Long externalAmount,
                                              final PaymentProvider paymentProvider,
                                              final String pspReference,
                                              final SplitSettlementData splitSettlementData) {
        logger.info("refund Start for pspReference {}", pspReference);

        final ModificationRequest modificationRequest = adyenRequestFactory.paymentExecutionToAdyenModificationRequest(paymentProvider, externalAmount, pspReference, splitSettlementData);
        final AdyenCallResult<ModificationResult> adyenCallResult = adyenPaymentRequestSender.refund(paymentProvider.getCountryIsoCode(), modificationRequest);

        if (!adyenCallResult.receivedWellFormedResponse()) {
            return handleTechnicalErrorAtModificationRequest("refund", pspReference, adyenCallResult);
        }
<commit_msg>#26 Handle cases when authorize result is not present<commit_after>/*
 * Copyright 2014-2015 Groupon, Inc
 *
 * Groupon 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.killbill.billing.plugin.adyen.client.payment.service;

import java.io.Closeable;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.killbill.adyen.common.BrowserInfo;
import org.killbill.adyen.payment.AnyType2AnyTypeMap;
import org.killbill.adyen.payment.ModificationRequest;
import org.killbill.adyen.payment.ModificationResult;
import org.killbill.adyen.payment.PaymentRequest;
import org.killbill.adyen.payment.PaymentRequest3D;
import org.killbill.adyen.payment.PaymentResult;
import org.killbill.billing.plugin.adyen.api.AdyenPaymentPluginApi;
import org.killbill.billing.plugin.adyen.client.model.OrderData;
import org.killbill.billing.plugin.adyen.client.model.PaymentData;
import org.killbill.billing.plugin.adyen.client.model.PaymentInfo;
import org.killbill.billing.plugin.adyen.client.model.PaymentModificationResponse;
import org.killbill.billing.plugin.adyen.client.model.PaymentProvider;
import org.killbill.billing.plugin.adyen.client.model.PaymentServiceProviderResult;
import org.killbill.billing.plugin.adyen.client.model.PurchaseResult;
import org.killbill.billing.plugin.adyen.client.model.SplitSettlementData;
import org.killbill.billing.plugin.adyen.client.model.UserData;
import org.killbill.billing.plugin.adyen.client.model.paymentinfo.Card;
import org.killbill.billing.plugin.adyen.client.payment.builder.AdyenRequestFactory;
import org.killbill.billing.plugin.adyen.client.payment.converter.PaymentInfoConverterManagement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;

public class AdyenPaymentServiceProviderPort implements Closeable {

    private static final Logger logger = LoggerFactory.getLogger("adyen.port");

    private final PaymentInfoConverterManagement paymentInfoConverterManagement;
    private final AdyenRequestFactory adyenRequestFactory;
    private final AdyenPaymentRequestSender adyenPaymentRequestSender;

    public AdyenPaymentServiceProviderPort(final PaymentInfoConverterManagement paymentInfoConverterManagement,
                                           final AdyenRequestFactory adyenRequestFactory,
                                           final AdyenPaymentRequestSender adyenPaymentRequestSender) {
        this.paymentInfoConverterManagement = paymentInfoConverterManagement;
        this.adyenRequestFactory = adyenRequestFactory;
        this.adyenPaymentRequestSender = adyenPaymentRequestSender;
    }

    @Override
    public void close() throws IOException {
        adyenPaymentRequestSender.close();
    }

    public PurchaseResult authorise(final Long amount,
                                    final PaymentData paymentData,
                                    final OrderData orderData,
                                    final UserData userData,
                                    final String termUrl,
                                    final SplitSettlementData splitSettlementData) {
        logger.info("authorise Start");

        Preconditions.checkNotNull(paymentData.getPaymentTxnInternalRef(), "paymentTxnInternalRef");

        final PaymentInfo paymentInfo = paymentData.getPaymentInfo();
        Preconditions.checkNotNull(paymentInfo, "paymentInfo");
        Preconditions.checkNotNull(paymentInfo.getPaymentProvider(), "paymentProvider");
        Preconditions.checkNotNull(paymentInfo.getPaymentProvider().getCurrency(), "currency");
        Preconditions.checkNotNull(paymentInfo.getPaymentProvider().getCountryIsoCode(), "countryIsoCode");

        final PaymentRequest request = adyenRequestFactory.createPaymentRequest(amount, orderData, paymentData, userData, termUrl, splitSettlementData);
        return authorise(request, paymentInfo.getPaymentProvider().getCountryIsoCode(), paymentData, !paymentInfo.getPaymentProvider().send3DSTermUrl() ? termUrl : null);
    }

    @VisibleForTesting
    PurchaseResult authorise(final PaymentRequest request, final String countryIsoCode, final PaymentData paymentData, final String termUrl) {
        final AdyenCallResult<PaymentResult> adyenCallResult = adyenPaymentRequestSender.authorise(countryIsoCode, request);

        if (!adyenCallResult.receivedWellFormedResponse()) {
            return handleTechnicalFailureAtPurchase("authorize", paymentData, adyenCallResult);
        }

        logger.info("received adyen authorize response: {}", adyenCallResult);
        final PurchaseResult purchaseResult;
        if (adyenCallResult.getResult().isPresent()) {
            final PaymentResult result = adyenCallResult.getResult().get();
            final PaymentServiceProviderResult paymentServiceProviderResult = PaymentServiceProviderResult.getPaymentResultForId(result.getResultCode());
            if (paymentServiceProviderResult != PaymentServiceProviderResult.REDIRECT_SHOPPER) {
                purchaseResult = new PurchaseResult(paymentServiceProviderResult,
                                                    result.getAuthCode(),
                                                    result.getPspReference(),
                                                    result.getRefusalReason(),
                                                    result.getResultCode(),
                                                    paymentData.getPaymentInternalRef());
            } else {
                logger.info("proceed with 3dSecure flow");
                final Map<String, String> formParams = new HashMap<String, String>();
                formParams.put(AdyenPaymentPluginApi.PROPERTY_PA_REQ, result.getPaRequest());
                formParams.put(AdyenPaymentPluginApi.PROPERTY_MD, result.getMd());
                formParams.put(AdyenPaymentPluginApi.PROPERTY_DCC_AMOUNT_VALUE, result.getDccAmount() == null ? null : String.valueOf(result.getDccAmount().getValue()));
                formParams.put(AdyenPaymentPluginApi.PROPERTY_DCC_AMOUNT_CURRENCY, result.getDccAmount() == null ? null : result.getDccAmount().getCurrency());
                formParams.put(AdyenPaymentPluginApi.PROPERTY_DCC_SIGNATURE, result.getDccSignature());
                formParams.put(AdyenPaymentPluginApi.PROPERTY_ISSUER_URL, result.getIssuerUrl());
                formParams.putAll(extractMpiAdditionalData(result));
                if (termUrl != null) {
                    formParams.put(AdyenPaymentPluginApi.PROPERTY_TERM_URL, termUrl);
                }

                    purchaseResult = new PurchaseResult(paymentServiceProviderResult,
                                                        result.getAuthCode(),
                                                        result.getPspReference(),
                                                        result.getRefusalReason(),
                                                        result.getResultCode(),
                                                        paymentData.getPaymentInternalRef(),
                                                        result.getIssuerUrl(),
                                                        formParams);
            }
        } else {
            purchaseResult =  new PurchaseResult(paymentData.getPaymentInternalRef(),
                                                 adyenCallResult.getResponseStatus().get());
        }

        logger.info("authorise Done {}", purchaseResult);
        return purchaseResult;
    }

    private PurchaseResult handleTechnicalFailureAtPurchase(final String callKey, final PaymentData paymentData, final AdyenCallResult<PaymentResult> adyenCallResult) {
        logger.info("payment {} call failed for internalReference: {} because of: {}", callKey, paymentData.getPaymentInternalRef(), adyenCallResult);
        return new PurchaseResult(paymentData.getPaymentInternalRef(), adyenCallResult.getResponseStatus().get());
    }

    public PurchaseResult authorize3DSecure(final Long billedAmount,
                                            final PaymentData<Card> paymentData,
                                            final UserData userData,
                                            final Map<String, String[]> requestParameterMap,
                                            final SplitSettlementData splitSettlementData) {
        logger.info("authorize3DSecure Start {} [}", billedAmount, userData);

        final Card paymentInfo = paymentData.getPaymentInfo();
        final BrowserInfo info = (BrowserInfo) paymentInfoConverterManagement.getBrowserInfoFor3DSecureAuth(billedAmount, paymentData.getPaymentInfo());
        final PaymentRequest3D request = adyenRequestFactory.paymentRequest3d(paymentData.getPaymentInternalRef(),
                                                                              paymentInfo,
                                                                              info,
                                                                              requestParameterMap,
                                                                              splitSettlementData,
                                                                              userData.getIP(),
                                                                              userData.getEmail(),
                                                                              userData.getCustomerId());
        final AdyenCallResult<PaymentResult> adyenCallResult = adyenPaymentRequestSender.authorise3D(paymentInfo.getPaymentProvider().getCountryIsoCode(), request);

        if (!adyenCallResult.receivedWellFormedResponse()) {
            handleTechnicalFailureAtPurchase("3dSecureAuthorise", paymentData, adyenCallResult);
        }

        logger.info("received adyen 3dSecure authorize response: {}", adyenCallResult);
        final PurchaseResult purchaseResult;
        if (adyenCallResult.getResult().isPresent()) {
            final PaymentResult result = adyenCallResult.getResult().get();
            final PaymentServiceProviderResult paymentServiceProviderResult = PaymentServiceProviderResult.getPaymentResultForId(result.getResultCode());
            if (paymentServiceProviderResult != PaymentServiceProviderResult.REDIRECT_SHOPPER) {
                purchaseResult = new PurchaseResult(PaymentServiceProviderResult.getPaymentResultForId(result.getResultCode()),
                                                    result.getAuthCode(),
                                                    result.getPspReference(),
                                                    result.getRefusalReason(),
                                                    result.getResultCode(),
                                                    paymentData.getPaymentInternalRef());
            } else {
                final Map<String, String> formParams = new HashMap<String, String>();
                formParams.put("PaReq", result.getPaRequest());
                formParams.put("MD", result.getMd());

                purchaseResult = new PurchaseResult(paymentServiceProviderResult,
                                                    result.getAuthCode(),
                                                    result.getPspReference(),
                                                    result.getRefusalReason(),
                                                    result.getResultCode(),
                                                    paymentData.getPaymentInternalRef(),
                                                    result.getIssuerUrl(),
                                                    formParams);
            }
        } else {
            purchaseResult =  new PurchaseResult(paymentData.getPaymentInternalRef(),
                                                 adyenCallResult.getResponseStatus().get());
        }

        logger.info("authorize3DSecure Done {}", purchaseResult);
        return purchaseResult;
    }

    public PaymentModificationResponse refund(final Long externalAmount,
                                              final PaymentProvider paymentProvider,
                                              final String pspReference,
                                              final SplitSettlementData splitSettlementData) {
        logger.info("refund Start for pspReference {}", pspReference);

        final ModificationRequest modificationRequest = adyenRequestFactory.paymentExecutionToAdyenModificationRequest(paymentProvider, externalAmount, pspReference, splitSettlementData);
        final AdyenCallResult<ModificationResult> adyenCallResult = adyenPaymentRequestSender.refund(paymentProvider.getCountryIsoCode(), modificationRequest);

        if (!adyenCallResult.receivedWellFormedResponse()) {
            return handleTechnicalErrorAtModificationRequest("refund", pspReference, adyenCallResult);
        }

{'fraction_non_alphanumeric': 0.07276881015692296, 'fraction_numerical': 0.0021347515074341783, 'mean_word_length': 2.1234062463446017, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 188, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4447336', 'n_tokens_mistral': 5892, 'n_tokens_neox': 5710, 'n_words': 1070}