/**
  * @param $httpStatusCode
  * @param DataObject $errorObject
  * @param CallContext $callContext
  * @return DeclinedPaymentException
  *       | DeclinedPayoutException
  *       | DeclinedRefundException
  *       | ValidationException
  *       | AuthorizationException
  *       | ReferenceException
  *       | GlobalCollectException
  *       | ApiException
  */
 public function createException($httpStatusCode, DataObject $errorObject, CallContext $callContext = null)
 {
     if ($errorObject instanceof PaymentErrorResponse && !is_null($errorObject->paymentResult)) {
         return new DeclinedPaymentException($httpStatusCode, $errorObject);
     }
     if ($errorObject instanceof PayoutErrorResponse && !is_null($errorObject->payoutResult)) {
         return new DeclinedPayoutException($httpStatusCode, $errorObject);
     }
     if ($errorObject instanceof RefundErrorResponse && !is_null($errorObject->refundResult)) {
         return new DeclinedRefundException($httpStatusCode, $errorObject);
     }
     if ($httpStatusCode == 400) {
         return new ValidationException($httpStatusCode, $errorObject);
     }
     if ($httpStatusCode == 403) {
         return new AuthorizationException($httpStatusCode, $errorObject);
     }
     if ($httpStatusCode == 409 && $callContext && strlen($callContext->getIdempotenceKey()) > 0 && $this->isIdempotenceError($errorObject)) {
         return new IdempotenceException($httpStatusCode, $errorObject, null, $callContext->getIdempotenceKey(), $callContext->getIdempotenceRequestTimestamp());
     }
     $httpClassCode = floor($httpStatusCode / 100);
     // If a different HTTP status code was sent, then either the user made an error, or the server is in trouble.
     // If the user made an error, the server will give class 4 response. If the server made an error and realises
     // this, it will send an appropriate error message with a class 5 response. It should not be sending other
     // status codes; if it does, we raise an UnexpectedResponseException to signal this.
     switch ($httpClassCode) {
         case 4:
             return new ReferenceException($httpStatusCode, $errorObject);
         case 5:
             return new GlobalCollectException($httpStatusCode, $errorObject);
         default:
             return new ApiException($httpStatusCode, $errorObject);
     }
 }
 /**
  * @return string[]
  */
 public function generateRequestHeaders()
 {
     $contentType = static::MIME_APPLICATION_JSON;
     $rfc2616Date = $this->getRfc161Date();
     $requestHeaders = array();
     $requestHeaders['Content-Type'] = $contentType;
     $requestHeaders['Date'] = $rfc2616Date;
     if ($this->clientMetaInfo) {
         $requestHeaders['X-GCS-ClientMetaInfo'] = $this->clientMetaInfo;
     }
     $requestHeaders['X-GCS-ServerMetaInfo'] = $this->getServerMetaInfoValue();
     if ($this->callContext && strlen($this->callContext->getIdempotenceKey()) > 0) {
         $requestHeaders['X-GCS-Idempotence-Key'] = $this->callContext->getIdempotenceKey();
     }
     $requestHeaders['Authorization'] = $this->getAuthorizationHeaderValue($requestHeaders);
     return $requestHeaders;
 }
 public function testCreatePaymentWithIdempotenceKeyFailure()
 {
     $client = $this->getClient();
     $merchantId = self::MERCHANT_ID_FOR_CHALLENGED_PAYMENT_TEST;
     $callContext = new CallContext();
     $dateTimeWitMicroseconds = DateTime::createFromFormat('U.u', microtime(true));
     $callContext->setIdempotenceKey(__FUNCTION__ . '::' . $dateTimeWitMicroseconds->format('Ymd-His-u'));
     $this->assertEmpty($callContext->getIdempotenceRequestTimestamp());
     try {
         $client->merchant($merchantId)->payments()->create($this->getMinimalCreatePaymentRequest(false), $callContext);
         $this->fail('excepted exception');
     } catch (ValidationException $e) {
         $this->assertEmpty($callContext->getIdempotenceRequestTimestamp());
     }
     try {
         $client->merchant($merchantId)->payments()->create($this->getMinimalCreatePaymentRequest(false), $callContext);
         $this->fail('excepted exception');
     } catch (ValidationException $e) {
         $idempotenceRequestTimestamp = $callContext->getIdempotenceRequestTimestamp();
         $this->assertNotEmpty($idempotenceRequestTimestamp);
     }
     try {
         $client->merchant($merchantId)->payments()->create($this->getMinimalCreatePaymentRequest(false), $callContext);
         $this->fail('excepted exception');
     } catch (ValidationException $e) {
         $this->assertEquals($idempotenceRequestTimestamp, $callContext->getIdempotenceRequestTimestamp());
     }
 }
 /**
  * @param ConnectionResponse $response
  * @param CallContext $callContext
  */
 protected function updateCallContext(ConnectionResponse $response, CallContext $callContext)
 {
     $callContext->setIdempotenceRequestTimestamp($response->getHeaderValue('X-GCS-Idempotence-Request-Timestamp'));
 }