Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"issues": "https://github.com/bluem-development/bluem-php"
},
"require": {
"php": ">=8.0",
"php": "^8.0|^8.1|^8.2|^8.3",
"ext-dom": "*",
"ext-libxml": "*",
"ext-simplexml": "*",
Expand Down
4 changes: 0 additions & 4 deletions src/Contexts/IdentityContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ public function addPaymentMethodDetails(array $details = []): void

private function validateDetails(array $details = []): array
{
if ($this->isIDIN()) {
// no validation yet
}

return [];
}

Expand Down
7 changes: 1 addition & 6 deletions src/Extensions/IPAPI.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@
*/
class IPAPI
{
/**
* @var bool
*/
private bool $debug = false;

/**
* @var string
*/
Expand Down Expand Up @@ -69,7 +64,7 @@ public function QueryIP(string $ip = ""): mixed
$ip = $this->GetCurrentIP();
}

$call_url = "{$this->baseURL}{$ip}?access_key=$this->accessKey";
$call_url = sprintf("%s%s?access_key=%s", $this->baseURL, $ip, $this->accessKey);

// Initialize CURL:
$ch = curl_init(
Expand Down
2 changes: 1 addition & 1 deletion src/Helpers/BIC.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace Bluem\BluemPHP\Helpers;

class BIC
final class BIC
{
public function __construct(
public string $issuerID,
Expand Down
9 changes: 1 addition & 8 deletions src/Helpers/BluemConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,7 @@ class BluemConfiguration
* this is given by the bank and never changed (default 0)
*/
public string $merchantSubID;
private string $PaymentsBrandID;
// @todo: consider deprecating this?
private string $EmandateBrandID;
// @todo: consider deprecating this?

// additional helper flags
/**
* Allows for testing webhook on local environments with no HTTPS check and verbose output.
*/
Expand Down Expand Up @@ -80,9 +75,7 @@ public function __construct(object|array $raw)
$this->test_accessToken = $validated->test_accessToken ?? null;

$this->IDINBrandID = $this->_assumeBrandID("Identity", $this->brandID);
$this->PaymentsBrandID = $this->_assumeBrandID("Payment", $this->brandID);
$this->EmandateBrandID = $this->_assumeBrandID("Mandate", $this->brandID);


$this->sequenceType = $validated->sequenceType ?? null;

$this->merchantID = $validated->merchantID ?? null;
Expand Down
1 change: 0 additions & 1 deletion src/Helpers/BluemCurrency.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

class BluemCurrency implements Stringable
{

private const EURO_CURRENCY = 'EUR';
private const US_DOLLAR_CURRENCY = 'USD';

Expand Down
1 change: 0 additions & 1 deletion src/Helpers/BluemIdentityCategoryList.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

class BluemIdentityCategoryList
{

/**
* @var string[] $categories
*/
Expand Down
6 changes: 1 addition & 5 deletions src/Helpers/BluemMaxAmount.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,15 @@

class BluemMaxAmount implements \Stringable
{

public BluemCurrency $currency;
public float $amount;

public function __construct(
float $amount,
private float $amount,
string $currencyCode
) {
// @todo: validate the amount to be non-negative and have a maximum, see xsd
$this->amount = $amount;

try {

$this->currency = new BluemCurrency($currencyCode);
} catch (\Exception $e) {
$this->currency = new BluemCurrency();
Expand Down
31 changes: 14 additions & 17 deletions src/Helpers/Now.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ public function __construct($timezoneString = self::DEFAULT_TIMEZONE)
{
try {
$timezone = new DateTimeZone($timezoneString);
} catch (\Exception $e) {
} catch (Exception) {
$timezone = new DateTimeZone(self::DEFAULT_TIMEZONE);
}

try {
$this->dateTime = new DateTimeImmutable(datetime: "now", timezone: $timezone);
} catch (Exception $e) {
} catch (Exception) {
$this->dateTime = new DateTimeImmutable("now", self::DEFAULT_TIMEZONE);
}
}
Expand Down Expand Up @@ -55,28 +55,25 @@ public function addDay(int $days): static
return $this;
}

/**
* @throws Exception
*/
public function fromDate(string $dateTimeString): static
{
try {
$this->dateTime = new DateTimeImmutable(
datetime: $dateTimeString,
timezone: new DateTimeZone(self::DEFAULT_TIMEZONE)
);
} catch (Exception $e) {
throw $e;
}
$this->dateTime = new DateTimeImmutable(
datetime: $dateTimeString,
timezone: new DateTimeZone(self::DEFAULT_TIMEZONE)
);

return $this;
}

public function fromTimestamp(string $timestamp): static
{
try {
$this->dateTime = (new DateTimeImmutable())
->setTimestamp($timestamp)
->setTimezone(new DateTimeZone(self::DEFAULT_TIMEZONE));
} catch (Exception $e) {
throw $e;
}
$this->dateTime = (new DateTimeImmutable())
->setTimestamp($timestamp)
->setTimezone(new DateTimeZone(self::DEFAULT_TIMEZONE));

return $this;
}
}
26 changes: 10 additions & 16 deletions src/Webhook.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,46 +44,39 @@ private function parse($xmlData = ''): void
{
if (!$this->isHttpsRequest()) {
$this->exitWithError('Not HTTPS');
return;
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
$this->exitWithError('Not POST');
return;
}

// Check: content type: XML with utf-8 encoding
if ($_SERVER["CONTENT_TYPE"] !== self::XML_UTF8_CONTENT_TYPE) {
$this->exitWithError('Wrong Content-Type given: should be XML with UTF-8 encoding');
return;
}

// Check: An empty POST to the URL (normal HTTP request) always has to respond with HTTP 200 OK.
$xmlData = file_get_contents('php://input');

if (empty($xmlData)) {
$this->exitWithError('No data body given');
return;
}
}

$xmlObject = $this->parseRawXML($xmlData);

if (! $xmlObject instanceof \SimpleXMLElement) {
if (! $xmlObject instanceof SimpleXMLElement) {
$this->exitWithError('Could not parse XML');
return;
}

$xmlValidation = (new WebhookXmlValidation($this->senderID))->validate($xmlObject);
if (! $xmlValidation::$isValid) {
$this->exitWithError($xmlValidation->errorMessage());
return;
}

$signatureValidation = (new WebhookSignatureValidation($this->environment))->validate($xmlData);
if (! $signatureValidation::$isValid) {
$this->exitWithError($signatureValidation->errorMessage());
return;
}

$this->xmlObject = $xmlObject;
Expand All @@ -98,10 +91,11 @@ private function isHttpsRequest(): bool
|| $_SERVER['SERVER_PORT'] === 443
);
}

private function exitWithError(string $string): void
private function exitWithError(string $errorMessage): void
{
http_response_code(self::STATUSCODE_BAD_REQUEST);
exit($errorMessage);
}

private function parseRawXML($postData): string|SimpleXMLElement
Expand Down Expand Up @@ -144,7 +138,7 @@ private function getPayloadValue(string $key): SimpleXMLElement|string|null
if ((is_countable($payload->children()) ? count($payload->children()) : 0) > 0) {
return $payload;
}
return $payload->$key ?? '';
return $payload->$key ? ($payload->$key . '') : '';
}

private function getPayload(): SimpleXMLElement
Expand Down Expand Up @@ -261,31 +255,31 @@ public function getIDealDetails(): ?SimpleXMLElement
{
$paymentDetails = $this->getPaymentMethodDetails();

if (!$paymentDetails instanceof \SimpleXMLElement) {
if (!$paymentDetails instanceof SimpleXMLElement) {
return null;
}
return $paymentDetails->IDealDetails;
}
public function getDebtorAccountName(): ?string
{
$details = $this->getIDealDetails();
if (!$details instanceof \SimpleXMLElement) {
if (!$details instanceof SimpleXMLElement) {
return "";
}
return $details->DebtorAccountName."" ?? "";
}
public function getDebtorIBAN(): ?string
{
$details = $this->getIDealDetails();
if (!$details instanceof \SimpleXMLElement) {
if (!$details instanceof SimpleXMLElement) {
return "";
}
return $details->DebtorIBAN."" ?? "";
}
public function getDebtorBankID(): ?string
{
$details = $this->getIDealDetails();
if (!$details instanceof \SimpleXMLElement) {
if (!$details instanceof SimpleXMLElement) {
return "";
}
return $details->DebtorBankID."" ?? "";
Expand Down Expand Up @@ -358,7 +352,7 @@ public function getIdentityReportArray(): array
{
$report = $this->getPayload()->IdentityReport ?? null;

if (!$report instanceof \SimpleXMLElement) {
if (!$report instanceof SimpleXMLElement) {
return [];
}

Expand Down
71 changes: 56 additions & 15 deletions tests/Unit/BluemTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,82 @@
namespace Unit;

use Bluem\BluemPHP\Bluem;
use Bluem\BluemPHP\Contexts\IdentityContext;
use Bluem\BluemPHP\Exceptions\InvalidBluemConfigurationException;
use Exception;
use Bluem\BluemPHP\Interfaces\BluemResponseInterface;
use Bluem\BluemPHP\Requests\BluemRequest;
use Bluem\BluemPHP\Responses\ErrorBluemResponse;
use PHPUnit\Framework\TestCase;
use RuntimeException;
use stdClass;

class BluemTest extends TestCase
{
private Bluem $bluem;

/**
* @throws InvalidBluemConfigurationException
*/
protected function setUp(): void
{
parent::setUp();
// Mock the configuration as needed
$mockedConfig = $this->getConfig();
$this->bluem = new Bluem($mockedConfig);
}


$bluem_config = $this->getConfig();

try {
$this->bluem = new Bluem(
$bluem_config
);
} catch (Exception $e) {
$this->fail($e->getMessage());
}
public function testConstructorWithValidConfig(): void
{
$this->assertInstanceOf(Bluem::class, $this->bluem);
}

public function testConstructorWithInvalidConfig(): void
{
$this->expectException(InvalidBluemConfigurationException::class);
new Bluem(null);
}

protected function tearDown(): void

public function testMandateWithValidParameters(): void
{
//$this->bluem = Bluem;
// Mock the expected response
$mockedResponse = $this->createMock(BluemResponseInterface::class);

// Test the Mandate method with valid parameters
$response = $this->bluem->Mandate('customer_id', 'order_id', 'mandate_id');

// Assertions
$this->assertInstanceOf(BluemResponseInterface::class, $response);
}

public function testMandateRequest()
public function testMandateWithException(): void
{
$this->expectException(RuntimeException::class);
$this->bluem->Mandate('', '', '');
}
public function testCreateMandateID(): void
{
$mandateID = $this->bluem->CreateMandateID('order_id', 'customer_id');
$this->assertIsString($mandateID);
}
public function testPerformRequestWithInvalidXml(): void
{
$result = true;
$this->assertEquals(true, $result);
// Mock a request that would generate invalid XML
$mockBluemRequest = $this->createMock(BluemRequest::class);

$mockBluemRequest->method('XmlString')
->willReturn('<xmla>Some invalid aaXML String</xmla>');

$mockBluemRequest->method('HttpRequestURL')
->willReturn('https://example.com/api/request');
$mockBluemRequest->method('RequestContext')->willReturn(new IdentityContext());

$result = $this->bluem->PerformRequest($mockBluemRequest);
$this->assertInstanceOf(ErrorBluemResponse::class, $result);
}

// helper classes
private function getConfig(): stdClass
{
$bluem_config = new stdClass;
Expand Down