<?php
/**
 * *© Copyright 2018 - 2020 Visa. All Rights Reserved.**
 *
 * NOTICE: The software and accompanying information and documentation (together, the “Software”) remain the property of and are proprietary to Visa and its suppliers and affiliates. The Software remains protected by intellectual property rights and may be covered by U.S. and foreign patents or patent applications. The Software is licensed and not sold.*
 *
 *  By accessing the Software you are agreeing to Visa's terms of use (developer.visa.com/terms) and privacy policy (developer.visa.com/privacy).In addition, all permissible uses of the Software must be in support of Visa products, programs and services provided through the Visa Developer Program (VDP) platform only (developer.visa.com). **THE SOFTWARE AND ANY ASSOCIATED INFORMATION OR DOCUMENTATION IS PROVIDED ON AN “AS IS,” “AS AVAILABLE,” “WITH ALL FAULTS” BASIS WITHOUT WARRANTY OR  CONDITION OF ANY KIND. YOUR USE IS AT YOUR OWN RISK.** All brand names are the property of their respective owners, used for identification purposes only, and do not imply product endorsement or affiliation with Visa. Any links to third party sites are for your information only and equally  do not constitute a Visa endorsement. Visa has no insight into and control over third party content and code and disclaims all liability for any such components, including continued availability and functionality. Benefits depend on implementation details and business factors and coding steps shown are exemplary only and do not reflect all necessary elements for the described capabilities. Capabilities and features are subject to Visa’s terms and conditions and may require development,implementation and resources by you based on your business and operational details. Please refer to the specific API documentation for details on the requirements, eligibility and geographic availability.*
 *
 * This Software includes programs, concepts and details under continuing development by Visa. Any Visa features,functionality, implementation, branding, and schedules may be amended, updated or canceled at Visa’s discretion.The timing of widespread availability of programs and functionality is also subject to a number of factors outside Visa’s control,including but not limited to deployment of necessary infrastructure by issuers, acquirers, merchants and mobile device manufacturers.*
 *
 */
/**
 * MLETest
 *
 * @category Class
 * @package  mle
 * @author   Swagger Codegen team
 * @link     https://github.com/swagger-api/swagger-codegen
 */

/**
 * NOTE: This class is auto generated by the swagger code generator program.
 * https://github.com/swagger-api/swagger-codegen
 * Please update the test case below to test the endpoint.
 */

namespace mle\test;

require_once(__DIR__ . '/../../vendor/autoload.php');
require_once(__DIR__ . '/../../autoload.php');

include_once __DIR__ . '/../../globalConfig.php';

use globalConfig\GlobalConfig;
use mle\ApiClient;
use mle\ApiException;
use mle\Configuration;
use mle\EncryptionUtils;

/**
 * QueryApiTest Class Doc Comment
 *
 * @category Class
 * @package  mle
 * @author   Swagger Codegen team
 * @link     https://github.com/swagger-api/swagger-codegen
 */
class MLETest extends \PHPUnit\Framework\TestCase
{

    protected $apiClient;

    protected $encryptionUtils;

    protected $config;

    /**
     * Setup before running each test case
     */
    public function setUp(): void
    {
        $gc = new GlobalConfig();
        $config = Configuration::getDefaultConfiguration();

        // Configure HTTP basic authorization
        $config->setUsername($gc->getUserName());
        $config->setPassword($gc->getPassword());
        $config->setCertificatePath($gc->getCertificatePath());
        $config->setPrivateKey($gc->getPrivateKeyPath());
        $config->setCaCertPath($gc->getCaCertPath());

        // Configure API key authorization:
        $config->setSharedSecret($gc->getSharedSecret());
        $config->setApiKey("apikey", $gc->getApiKey());

        // Configure proxy settings
        $config->setCurlProxyHost($gc->getProxyHost());
        $config->setCurlProxyPort($gc->getProxyPort());
        $config->setCurlProxyUser($gc->getProxyUser());
        $config->setCurlProxyPassword($gc->getProxyPassword());

        // Configure MLE Settings
        $config->setMleServerPublicCertificatePath($gc->getMleServerPublicCertificatePath());
        $config->setMleClientPrivateKeyPath($gc->getMleClientPrivateKeyPath());
        $config->setKeyId($gc->getKeyId());

        $this->config = $config;

        $this->apiClient = new ApiClient();
        $this->encryptionUtils = new EncryptionUtils();
    }

    /**
     * Clean up after running each test case
     */
    public function tearDown(): void
    {

    }

    /**
     * Test MLE
     *
     * @throws ApiException
     */

    public function testMLEOctWithQueryAPIT()
    {
        echo '.................Testing MLE With OCT + Query API...........................' . "\xA";
        $acquiringBin = '408999';
        $localTransactionDateTime = date_format(new \DateTime(), "Y-m-d\TH:i:s");

        echo '.................START Push Funds Transaction API Call.......................' . "\xA";
        $payload = '{
          "amount": "124.05",
          "senderAddress": "901 Metro Center Blvd",
          "localTransactionDateTime": "' . $localTransactionDateTime . '",
          "pointOfServiceData": {
            "panEntryMode": "90",
            "posConditionCode": "00",
            "motoECIIndicator": "0"
          },
          "recipientPrimaryAccountNumber": "4957030420210496",
          "colombiaNationalServiceData": {
            "addValueTaxReturn": "10.00",
            "taxAmountConsumption": "10.00",
            "nationalNetReimbursementFeeBaseAmount": "20.00",
            "addValueTaxAmount": "10.00",
            "nationalNetMiscAmount": "10.00",
            "countryCodeNationalService": "170",
            "nationalChargebackReason": "11",
            "emvTransactionIndicator": "1",
            "nationalNetMiscAmountType": "A",
            "costTransactionIndicator": "0",
            "nationalReimbursementFee": "20.00"
          },
          "cardAcceptor": {
            "address": {
              "country": "USA",
              "zipCode": "94404",
              "county": "San Mateo",
              "state": "CA"
            },
            "idCode": "CA-IDCode-77765",
            "name": "Visa Inc. USA-Foster City",
            "terminalId": "TID-9999"
          },
          "senderReference": "",
          "transactionIdentifier": "381228649430015",
          "acquirerCountryCode": "840",
          "acquiringBin": "' . $acquiringBin . '",
          "retrievalReferenceNumber": "412770451018",
          "senderCity": "Foster City",
          "senderStateCode": "CA",
          "systemsTraceAuditNumber": "451018",
          "senderName": "Mohammed Qasim",
          "businessApplicationId": "AA",
          "settlementServiceIndicator": "9",
          "merchantCategoryCode": "6012",
          "transactionCurrencyCode": "USD",
          "recipientName": "rohan",
          "senderCountryCode": "124",
          "sourceOfFundsCode": "05",
          "senderAccountNumber": "4653459515756154"
        }';

        $encryptedPayload = $this->encryptionUtils->encryptPayload($payload, $this->config->getKeyId(), $this->config->getMleServerPublicCertificatePath());
        $response = $this->postPushFundsTransaction($encryptedPayload);

        $statusCode = $response[1];
        if (!($statusCode >= 200 && $statusCode <= 299)) {
            throw new ApiException('Push Funds API Call failed wth status code: ' . $statusCode);
        }

        $encryptedResponse = $response[0];
        $responseData = $this->encryptionUtils->decryptJwe($encryptedResponse, $this->config->getMleClientPrivateKeyPath());
        echo '.................END Push Funds Transaction API Call.........................' . "\xA";

        echo '.................START Query API Call.........................' . "\xA";
        $jsonData = json_decode($responseData, 1);

        $transactionIdentifier = $jsonData['transactionIdentifier'];
        $response = $this->getTransactionQuery($acquiringBin, $transactionIdentifier);

        $encryptedResponse = $response[0];
        $responseData = $this->encryptionUtils->decryptJwe($encryptedResponse, $this->config->getMleClientPrivateKeyPath());

        $transactions = json_decode($responseData);
        $this->assertNotNull($transactions);
        echo '.................END Query API Call.........................' . "\xA";
    }

    /**
     * Get Transaction Query
     *
     * @param $acquiringBIN
     * @param $transactionIdentifier
     * @return array
     * @throws ApiException
     */
    private function getTransactionQuery($acquiringBIN, $transactionIdentifier)
    {
        echo "\nMaking a call to getTransactionQuery()\n";
        $queryParams = [];
        if ($acquiringBIN !== null) {
            $queryParams['acquiringBIN'] = $this->apiClient->getSerializer()->toQueryValue($acquiringBIN);
        }
        // query params
        if ($transactionIdentifier !== null) {
            $queryParams['transactionIdentifier'] = $this->apiClient->getSerializer()->toQueryValue($transactionIdentifier);
        }
        return $this->call('/visadirect/v1/transactionquery', 'transactionquery', null, 'GET', 'string', $queryParams);
    }

    /**
     * Post Pull Transaction
     *
     * @throws ApiException
     */
    private function postPushFundsTransaction($pushfundspostPayload)
    {
        echo "\nMaking a call to postPushFundsTransaction()\n";
        return $this->call('/visadirect/fundstransfer/v1/pushfundstransactions', 'pushfundstransactions', $pushfundspostPayload, 'POST', 'string');
    }

    private function call($path, $resourcePath, $payload, $method, $responseType, $queryParams = [])
    {
        // parse inputs
        $httpBody = '';
        $headerParams = [];
        $formParams = [];
        $_header_accept = $this->apiClient->selectHeaderAccept(['application/json']);
        if (!is_null($_header_accept)) {
            $headerParams['Accept'] = $_header_accept;
        }
        $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(['application/json']);
        $headerParams['keyId'] = $this->config->getKeyId();

        // default format to json
        $path = str_replace("{format}", "json", $path);
        $resourcePath = str_replace("{format}", "json", $resourcePath);

        // body params
        $_tempBody = null;
        if (isset($payload)) {
            $_tempBody = $payload;
        }

        if (isset($_tempBody)) {
            $httpBody = $_tempBody; // $_tempBody is the method argument, if present
        } elseif (count($formParams) > 0) {
            $httpBody = $formParams; // for HTTP post (form)
        }

        // this endpoint requires HTTP basic authentication
        if (strlen($this->apiClient->getConfig()->getUsername()) !== 0 or strlen($this->apiClient->getConfig()->getPassword()) !== 0) {
            $headerParams['Authorization'] = 'Basic ' . base64_encode($this->apiClient->getConfig()->getUsername() . ":" . $this->apiClient->getConfig()->getPassword());
        }

        if (sizeof($queryParams) !== 0) {
            ksort($queryParams);
        }

        // make the API Call
        try {
            list($response, $statusCode, $httpHeader) = $this->apiClient->callApi(
                $path,
                $resourcePath,
                $method,
                $queryParams,
                $httpBody,
                $headerParams,
                $responseType,
                $path
            );

            return [$response, $statusCode, $httpHeader];
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $e->setResponseObject($e->getResponseBody());
                    break;
            }

            throw $e;
        }
    }

}
