/**
  * Sends a request type json 
  * 
  * @param Object $request this object is encode to json is used to request data
  * @param PayUHttpRequestInfo $payUHttpRequestInfo object with info to send an api request
  * @param bool $removeNullValues if remove null values in request and response object 
  * @return string response
  * @throws RuntimeException
  */
 public static function sendRequest($request, PayUHttpRequestInfo $payUHttpRequestInfo, $removeNullValues = NULL)
 {
     if (!isset($removeNullValues)) {
         $removeNullValues = PayUConfig::REMOVE_NULL_OVER_REQUEST;
     }
     if ($removeNullValues && $request != null) {
         $request = PayURequestObjectUtil::removeNullValues($request);
     }
     if ($request != NULL) {
         $request = PayURequestObjectUtil::encodeStringUtf8($request);
     }
     if (isset($request->transaction->order->signature)) {
         $request->transaction->order->signature = SignatureUtil::buildSignature($request->transaction->order, PayU::$merchantId, PayU::$apiKey, SignatureUtil::MD5_ALGORITHM);
     }
     $requestJson = json_encode($request);
     $responseJson = HttpClientUtil::sendRequest($requestJson, $payUHttpRequestInfo);
     if ($responseJson == 200 || $responseJson == 204) {
         return true;
     } else {
         $response = json_decode($responseJson);
         if (!isset($response)) {
             throw new PayUException(PayUErrorCodes::JSON_DESERIALIZATION_ERROR, sprintf(' Error decoding json. Please verify the json structure received. the json isn\'t added in this message ' . ' for security reasons please verify the variable $responseJson on class PayUApiServiceUtil'));
         }
         if ($removeNullValues) {
             $response = PayURequestObjectUtil::removeNullValues($response);
         }
         $response = PayURequestObjectUtil::formatDates($response);
         if ($payUHttpRequestInfo->environment === Environment::PAYMENTS_API || $payUHttpRequestInfo->environment === Environment::REPORTS_API) {
             if (PayUResponseCode::SUCCESS == $response->code) {
                 return $response;
             } else {
                 throw new PayUException(PayUErrorCodes::API_ERROR, $response->error);
             }
         } else {
             if ($payUHttpRequestInfo->environment === Environment::SUBSCRIPTIONS_API) {
                 if (!isset($response->type) || $response->type != 'BAD_REQUEST' && $response->type != 'NOT_FOUND' && $response->type != 'MALFORMED_REQUEST') {
                     return $response;
                 } else {
                     throw new PayUException(PayUErrorCodes::API_ERROR, $response->description);
                 }
             }
         }
     }
 }
 /**
  * Build a transaction object to be added to payment request
  * @param array $parameters the parameters to build a transaction
  * @param strng $lang to be used
  * @return the transaction built
  * @throws InvalidArgumentException if any paramter is invalid
  * 
  */
 private static function buildTransactionRequest($parameters, $lang)
 {
     $transaction = new stdClass();
     $order = null;
     $transaction->paymentCountry = CommonRequestUtil::getParameter($parameters, PayUParameters::COUNTRY);
     if (CommonRequestUtil::getParameter($parameters, PayUParameters::ORDER_ID) == null) {
         $signature = null;
         if (CommonRequestUtil::getParameter($parameters, PayUParameters::SIGNATURE) != null) {
             $signature = CommonRequestUtil::getParameter($parameters, PayUParameters::SIGNATURE);
         }
         $merchantId = PayU::$merchantId;
         $order = RequestPaymentsUtil::buildOrderRequest($parameters, $lang);
         if ($signature == null && $merchantId != null) {
             $signature = SignatureUtil::buildSignature($order, $merchantId, PayU::$apiKey, SignatureUtil::MD5_ALGORITHM);
         }
         $order->signature = $signature;
         $transaction->order = $order;
     } else {
         $orderId = CommonRequestUtil::getParameter($parameters, PayUParameters::ORDER_ID);
         $order = new stdClass();
         $order->orderId($orderId);
         $transaction . setOrder($order);
     }
     $transaction->order->buyer = RequestPaymentsUtil::buildBuyer($parameters);
     if (CommonRequestUtil::getParameter($parameters, PayUParameters::PAYER_IP_ADDRESS) != null) {
         $transaction->ipAddress = CommonRequestUtil::getParameter($parameters, PayUParameters::PAYER_IP_ADDRESS);
     } else {
         $transaction->ipAddress = RequestPaymentsUtil::getIpAddress();
     }
     if (CommonRequestUtil::getParameter($parameters, PayUParameters::PAYER_COOKIE) != null) {
         $transaction->cookie = CommonRequestUtil::getParameter($parameters, PayUParameters::PAYER_COOKIE);
     } else {
         $transaction->cookie = 'cookie_' . microtime();
     }
     $transaction->userAgent = sprintf("%s %s", PayU::API_NAME, PayU::API_VERSION);
     $transaction->source = PayU::API_CODE_NAME;
     if (CommonRequestUtil::getParameter($parameters, PayUParameters::CREDIT_CARD_NUMBER) != null) {
         $transaction->creditCard = RequestPaymentsUtil::buildCreditCardTransaction($transaction, $parameters);
     } else {
         if (CommonRequestUtil::getParameter($parameters, PayUParameters::TOKEN_ID) != null) {
             $transaction->creditCard = RequestPaymentsUtil::buildCreditCardForToken($parameters);
         }
     }
     if (CommonRequestUtil::getParameter($parameters, PayUParameters::INSTALLMENTS_NUMBER) != null) {
         $transaction = RequestPaymentsUtil::addExtraParameter($transaction, PayUKeyMapName::TRANSACTION_INSTALLMENTS_NUMBER, CommonRequestUtil::getParameter($parameters, PayUParameters::INSTALLMENTS_NUMBER));
     }
     $expirationDate = CommonRequestUtil::getParameter($parameters, PayUParameters::EXPIRATION_DATE);
     if (isset($expirationDate) && CommonRequestUtil::isValidDate($expirationDate, PayUConfig::PAYU_DATE_FORMAT, PayUParameters::EXPIRATION_DATE)) {
         $transaction->expirationDate = $expirationDate;
     }
     $transaction->creditCardTokenId = CommonRequestUtil::getParameter($parameters, PayUParameters::TOKEN_ID);
     $paymentMethod = CommonRequestUtil::getParameter($parameters, PayUParameters::PAYMENT_METHOD);
     if (!PaymentMethods::isValidPaymentMethod($paymentMethod)) {
         throw new InvalidArgumentException(sprintf("The payment method value %s sent in parameter %s is invalid", $paymentMethod, PayUParameters::PAYMENT_METHOD));
     }
     $transaction->paymentMethod = $paymentMethod;
     $transaction->payer = RequestPaymentsUtil::buildPayer($parameters);
     $transaction->order = $order;
     return $transaction;
 }