Skip to content

Commit

Permalink
feat: add handling for fatal errors by the gateway (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
rommelfreddy authored Mar 28, 2022
1 parent 52e0925 commit 29eae73
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 3 deletions.
11 changes: 10 additions & 1 deletion src/Service/CommunicationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,15 @@ public function send($xml, $connectionTimeout = 0, $executionTimeout = 0, $retri

$errno = curl_errno($ch);

$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

// close connection
curl_close($ch);

if ($response === false) {
// status codes 3xx and 5xx are not processable by the SDK (we assume that the body will be invalid too)
$invalidStatusCode = $statusCode < 200 || ($statusCode >= 300 && ($statusCode < 400 || $statusCode >= 500));

if ($invalidStatusCode || $response === false) {
if ($retries > 0) {
if ($retryDelay > 0) {
// halt time in milliseconds (entered microseconds * 1000)
Expand All @@ -108,6 +113,10 @@ public function send($xml, $connectionTimeout = 0, $executionTimeout = 0, $retri
if ($errno > 0) {
throw new CurlException(curl_strerror($errno));
}

if ($invalidStatusCode) {
throw new CurlException('There server answered with an invalid status code.');
}
}

return $response;
Expand Down
14 changes: 12 additions & 2 deletions src/Service/ValidateGatewayResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

namespace RatePAY\Service;

use RatePAY\Exception\RequestException;

/**
* Class ValidateGatewayResponse.
*/
Expand Down Expand Up @@ -44,9 +46,17 @@ public function __construct($requestType, \SimpleXMLElement $response)
$responsePath = 'RatePAY\\Model\\Response\\';
$responseInstance = $responsePath . $this->responseType;

$this->responseModel = new $responseInstance($response);
try {
$this->responseModel = new $responseInstance($response);

$this->responseModel->validateResponse();
$this->responseModel->validateResponse();
} catch (\Throwable $exception) {
// this catch works only on PHP < 7.0. On PHP versions lower than 7.0 the error will be propagated because
// it is not catchable.
// This will catch all errors which will throw by accessing non-existing fields or methods on objects
$message = $exception->getPrevious() ? $exception->getPrevious()->getMessage() : $exception->getMessage();
throw new RequestException(sprintf('An error occurred during the processing of the response from the gateway. Error message: %s', $message));
}
}

/**
Expand Down
26 changes: 26 additions & 0 deletions tests/Unit/Service/CommunicationServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,19 @@ function curl_strerror($errorCode)

return $messages[$errorCode];
}

function curl_getinfo($handle, $optionCode)
{
if (!should_call_mocked_global_functions()) {
return call_user_func_array('\curl_getinfo', func_get_args());
}

if ($optionCode === CURLINFO_HTTP_CODE) {
return CommunicationServiceTest::$forceHttpStatus;
}

return null;
}
}

namespace RatePAY\Tests\Unit\Service {
Expand All @@ -89,6 +102,7 @@ class CommunicationServiceTest extends TestCase
public static $curlDataMock = [];
public static $curlExecutions = 0;
public static $expectedCurlFailures = 0;
public static $forceHttpStatus = 200;

/**
* This method is called before the first test of this test class is run.
Expand Down Expand Up @@ -168,6 +182,18 @@ public function testSendAndRetryCurl()
$this->assertEquals('cURL Executed!', $response);
}

public function testCurlRequestWillFailWithHttpError500()
{
self::$forceHttpStatus = 500;
$xml = '<?xml version="1.0" encoding="UTF-8"?><note><to>Foo</to></note>';

$this->expectException(CurlException::class);
$this->expectExceptionMessage('There server answered with an invalid status code.');

$service = new CommunicationService();
$service->send($xml, 0, 0, 6, 1);
}

public static function incrementCurlExcecutions()
{
self::$curlExecutions++;
Expand Down
34 changes: 34 additions & 0 deletions tests/Unit/Service/ValidateGatewayResponseTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

/*
* Ratepay PHP-Library
*
* This document contains trade secret data which are the property of
* Ratepay GmbH, Berlin, Germany. Information contained herein must not be used,
* copied or disclosed in whole or part unless permitted in writing by Ratepay GmbH.
* All rights reserved by Ratepay GmbH.
*
* Copyright (c) 2022 Ratepay GmbH / Berlin / Germany
*/

namespace RatePAY\Service;

use PHPUnit\Framework\TestCase;
use RatePAY\Exception\RequestException;

class ValidateGatewayResponseTest extends TestCase
{

/**
* @requires PHPUnit 7.5
*/
public function testIfExceptionWillThrownIfUnexpectedXML()
{
$xml = '<?xml version="1.0" encoding="UTF-8"?><note><to>Foo</to></note>';

$this->expectException(RequestException::class);
$this->expectExceptionMessageMatches('/An error occurred during the processing of the response from the gateway. Error message: (.*)/');

new ValidateGatewayResponse('PaymentInit', new \SimpleXMLElement($xml));
}
}

0 comments on commit 29eae73

Please sign in to comment.