Skip to content
Merged
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
115 changes: 17 additions & 98 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,25 @@ Utilized by other applications as well:
- [Magento2 module](https://github.com/bluem-development/bluem-magento/), available for Bluem customers.
- Several third-party customer applications by Bluem customers.

## Documentation

> Read our improved documentation [**here**](https://bluem-development.github.io/bluem-docs/bluemphp.html)

We have several guides available there. They include:

- [Getting started guide](https://bluem-development.github.io/bluem-docs/tutorial-configuration.html)
- [Tutorial on payments](https://bluem-development.github.io/bluem-docs/tutorial-payments.html)
- [Tutorial on webhooks](https://bluem-development.github.io/bluem-docs/tutorial-webhooks.html)
- More are coming soon!

## Remaining documentation

Most of this will be migrated into the documentation mentioned above. Note: You might find duplicate information below.

## Table of Contents

* [Requirements](#requirements)
- [Requirements](#requirements)

- [Getting started:](#getting-started)
- [Changelog](#changelog)
- [Testing](#testing)
Expand Down Expand Up @@ -183,103 +199,6 @@ The Webhook is only needed for ePayments and eMandates: online stores/portals th
Please note that the flow for the IBAN-Name check is shorter: a TransactionRequest is performed. The results return as a TransactionResponse.
This is because the end-user is not needed; the call is straight to the Bank Database, that provides in the TransactionResponse the IBAN-Name check results.

## Preselecting a bank for Payment requests using debtorWallet

**Note:** This is relevant for bank-based transactions and services:

It is possible to preselect a Bank within your own application for Payments, based on an IssuerID (BIC/Swift code) when creating a Mandate, Payment or Identity request. This can be used if you want to user to select the given bank in your own interface and skip the bank selection within the Bluem portal interface.
This reduces the amount of steps required by performing the selection of the bank within your own application and interface by utilizing the preselection feature from the PHP library on the request object as so:

```php
$BIC = "INGBNL2A";
$request->selectDebtorWallet($BIC);
```

Parameter has to be a valid BIC code of a supported bank. An invalid BIC code will trigger an exception. **Please note that supported BICs differ per service as not every bank offers the same services!** The supported BIC codes per service can also be requested from a Bluem object, given the service context. **As appendix to this Documentation file, you can find a full list of all BICs per context.**

Illustrated here is that a list of BICs per context can also be retrieved programmatically:

```php
$MandatesBICs = $bluem->retrieveBICsForContext("Mandates"); // also specific to localInstrumentCode, see notes.
$PaymentsBICs = $bluem->retrieveBICsForContext("Payments");
$IdentityBICs = $bluem->retrieveBICsForContext("Identity");
```

Input of a different context will trigger an exception. If valid, the result is an array of `Bluem\BluemPHP\BIC` objects with attributes `IssuerID` and `IssuerName`: the BIC and Bank name respectively. You can use this to populate your user interface.

Please note that the BIC list will vary when a different `localInstrumentCode` is configured. The localInstrumentCode `CORE` and `B2B` are supported by different banks. Based on your configuration, the right BIC list is loaded from context automatically and used to verify the debtorWallet.

This method can be used when creating iDIN and when creating iDEAL requests; you could store the selected bank (“Issuer”) on user level and use it when creating a request for your user.

- You can inform the user WHY this is necessary and refer to the new laws and rules, in your own website/application or refer to the news/public announcements.
- You can inform the user about the amount of trouble required: display a piece of text saying that it only takes a minute or two, and that it is stored for your convenience: that it ensures integrity, and a valid webshop experience.

## Using different Payment transaction methods

**Important note: ensure you have the right BrandID set up for specific payment methods. Refer to your account manager to retrieve a list of the specific BrandIDs per payment method**

You can allow the PayPal and Creditcard payment methods by selecting these within the request object before sending it.

To use iDeal, (default option). A BIC **can** be provided. If left empty, bank selection will occur in the Bluem portal.

```php
$BIC = 'INGBNL2A';
$request = $request->setPaymentMethodToIDEAL($BIC);
```

To use PayPal, give in a PayPal account email address. The email is also not required.

```php
$payPalAccount = 'john.doe@gmail.com';
$request = $request->setPaymentMethodToPayPal($payPalAccount);
```

To use Creditcards, you can set the credit card details as follows (not required)

```php
$request = $request->setPaymentMethodToCreditCard();
```

or

```php
$cardNumber = '1234000012340000';
$name = 'John Doe';
$securityCode = 123;
$expirationDateMonth = 11;
$expirationDateYear = 2025;

$request = $request->setPaymentMethodToCreditCard(
$cardNumber,
$name,
$securityCode,
$expirationDateMonth,
$expirationDateYear
);
```

To use Sofort, use the following method:

```php
$request = $request->setPaymentMethodToSofort();
```

To use Carte Bancaire, use the following method:

```php
$request = $request->setPaymentMethodToCarteBancaire();
```

To use Bancontact, use the following method

```php
$request = $request->setPaymentMethodToBancontact();
```

These methods will throw an exception if required information is missing.

Once the request executes, the link to the transaction will send you to the Bluem Portal with the corresponding interface and flow.

## Webhooks

Webhooks exist for Payments, eMandates and Identity. They trigger during requests to the Bluem flow and send data to your application.
Expand Down
11 changes: 7 additions & 4 deletions src/Contexts/PaymentsContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,21 @@ class PaymentsContext extends BluemContext
public const PAYMENT_METHOD_CREDITCARD = 'CreditCard';

public const PAYMENT_METHOD_SOFORT = 'Sofort';
public const PAYMENT_METHOD_SOFORT_DIGITAL_SERVICES = 'SofortDigitalServices';

public const PAYMENT_METHOD_CARTE_BANCAIRE = 'CarteBancaire';

public const PAYMENT_METHOD_BANCONTACT = 'Bancontact';
public const PAYMENT_METHOD_GIROPAY = 'Giropay';

public const PAYMENT_METHODS = [
self::PAYMENT_METHOD_BANCONTACT,
self::PAYMENT_METHOD_CARTE_BANCAIRE,
self::PAYMENT_METHOD_CREDITCARD,
self::PAYMENT_METHOD_GIROPAY,
self::PAYMENT_METHOD_IDEAL,
self::PAYMENT_METHOD_PAYPAL,
self::PAYMENT_METHOD_CREDITCARD,
self::PAYMENT_METHOD_SOFORT_DIGITAL_SERVICES,
self::PAYMENT_METHOD_SOFORT,
self::PAYMENT_METHOD_CARTE_BANCAIRE,
self::PAYMENT_METHOD_BANCONTACT,
];

public string $debtorWalletElementName = self::PAYMENT_METHOD_IDEAL;
Expand Down
14 changes: 14 additions & 0 deletions src/Requests/BluemRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -445,4 +445,18 @@ public function setBrandId(string $brandID): void
{
$this->brandID = $brandID;
}

/**
* Use the right separator based on the presence of a query string
*/
protected function appendToUrl(string $urlBase, string $key, $value): string
{
$hasQueryString = preg_match('/\?.+=.+/', $urlBase);

if ($hasQueryString) {
return "{$urlBase}&{$key}={$value}";
}

return "{$urlBase}?{$key}={$value}";
}
}
3 changes: 2 additions & 1 deletion src/Requests/EmandateBluemRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ public function __construct(BluemConfiguration $config, private $debtorReference
$this->mandateID = $mandateID;

// https - unique return URL for customer
$this->merchantReturnURL = sprintf('%s?mandateID=%s', $this->merchantReturnURLBase, $this->mandateID);
$this->merchantReturnURL = $this->appendToUrl($this->merchantReturnURLBase, 'mandateID', $this->mandateID);

$this->sequenceType = $config->sequenceType ?? "RCUR";
// reason for the mandate; configurable per client
$this->eMandateReason = $config->eMandateReason ?? "Incasso machtiging";
Expand Down
5 changes: 2 additions & 3 deletions src/Requests/IdentityBluemRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,9 @@ public function __construct(
$this->requestCategory = $this->getRequestCategoryElement($requestCategory);
$this->description = $this->_sanitizeDescription($description);
if (empty($debtorReturnURL)) {
throw new InvalidBluemRequestException("Debtor return URL is required");
$debtorReturnURL = $config->merchantReturnURLBase;
}

$this->debtorReturnURL = $debtorReturnURL . ('?debtorReference=' . $this->debtorReference);
$this->debtorReturnURL = $this->appendToUrl($debtorReturnURL, "debtorReference", $this->debtorReference);

// @todo: make this a configurable setting
$this->minAge = $config->minAge ?? BLUEM_DEFAULT_MIN_AGE;
Expand Down
18 changes: 14 additions & 4 deletions src/Requests/PaymentBluemRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,8 @@ public function __construct(
$this->debtorReturnURL = $config->merchantReturnURLBase;
}

$this->debtorReturnURL .= sprintf('?entranceCode=%s&transactionID=%s', $this->entranceCode, $this->transactionID);

$this->debtorReturnURL = str_replace('&', '&', $this->debtorReturnURL);
$this->debtorReturnURL = $this->appendToUrl($this->debtorReturnURL, 'entranceCode', $this->entranceCode);
$this->debtorReturnURL = $this->appendToUrl($this->debtorReturnURL, 'transactionID', $this->transactionID);

// Note: different variable name in config
// added entranceCode as well, useful. Defined in generic bluem request class.
Expand Down Expand Up @@ -276,19 +275,30 @@ public function setPaymentMethodToSofort(): self
return $this;
}

public function setPaymentMethodToSofortDigitalServices(): self
{
$this->setPaymentMethod($this->context::PAYMENT_METHOD_SOFORT_DIGITAL_SERVICES);
return $this;
}

public function setPaymentMethodToCarteBancaire(): self
{
$this->setPaymentMethod($this->context::PAYMENT_METHOD_CARTE_BANCAIRE);
return $this;
}

public function setPaymentMethodToGiropay(): self
{
$this->setPaymentMethod($this->context::PAYMENT_METHOD_GIROPAY);
return $this;
}

public function setPaymentMethodToBancontact(): self
{
$this->setPaymentMethod($this->context::PAYMENT_METHOD_BANCONTACT);
return $this;
}


/**
* @throws InvalidBluemRequestException
*/
Expand Down
2 changes: 1 addition & 1 deletion tests/Acceptance/PaymentsAcceptanceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function testPaymentRequestXmlUsesSandboxSampleData(): void
'<Currency>EUR</Currency>',
'<Amount>12.34</Amount>',
'<DueDateTime>2026-04-12T00:00:00.000Z</DueDateTime>',
'<DebtorReturnURL automaticRedirect="1">http://localhost:8000/?a=callback?entranceCode=PAYMENT-ENTRANCE-123&amp;transactionID=TRANS123</DebtorReturnURL>',
'<DebtorReturnURL automaticRedirect="1">http://localhost:8000/?a=callback&amp;entranceCode=PAYMENT-ENTRANCE-123&amp;transactionID=TRANS123</DebtorReturnURL>',
'<DebtorWallet>',
'<Bancontact>',
);
Expand Down
17 changes: 17 additions & 0 deletions validation/EPayment.xsd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1.7.0">
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1.7.0">
<!--=====================================================================-->
<!-- Schema Management -->
Expand All @@ -9,6 +10,8 @@
<xsd:documentation xml:lang="en"/>
<xsd:documentation>
<name>EPayment Interface</name>
<revision version="1.6.0">
<date>2023-JANUARY-10</date>
<revision version="1.6.0">
<date>2023-JANUARY-10</date>
</revision>
Expand Down Expand Up @@ -177,6 +180,7 @@
</xsd:restriction>
</xsd:simpleType>

<xsd:simpleType name="CurrencySimpleType">
<xsd:simpleType name="CurrencySimpleType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="EUR"/>
Expand Down Expand Up @@ -279,6 +283,7 @@
<xsd:enumeration value="SuccessManual"/>
<xsd:enumeration value="BankSelected"/>
<xsd:enumeration value="Refunded"/>
<xsd:enumeration value="Refunded"/>
</xsd:restriction>
</xsd:simpleType>

Expand Down Expand Up @@ -322,6 +327,7 @@
<xsd:enumeration value="VISA_MASTER"/>
<xsd:enumeration value="SOFORT"/>
<xsd:enumeration value="SOFORT_DIGITALSERVICES"/>
<xsd:enumeration value="SOFORT_DIGITALSERVICES"/>
<xsd:enumeration value="CARTE_BANCAIRE"/>
<xsd:enumeration value="BANCONTACT"/>
<xsd:enumeration value="GIROPAY"/>
Expand Down Expand Up @@ -464,8 +470,10 @@



<!-- BEGIN - DebtorWallet additions -->
<!-- BEGIN - DebtorWallet additions -->
<xsd:complexType name="DebtorCreditCardComplexType">
</xsd:complexType>
</xsd:complexType>

<xsd:complexType name="IDealComplexType">
Expand Down Expand Up @@ -553,6 +561,14 @@
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="SofortDigitalServicesDetailsComplexType">
<xsd:sequence>
<xsd:element name="DebtorAccountName" type="TokenLength70SimpleType" minOccurs="0"/>
<xsd:element name="DebtorAccount" type="TokenLength70SimpleType" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>


<xsd:complexType name="SofortDigitalServicesDetailsComplexType">
<xsd:sequence>
<xsd:element name="DebtorAccountName" type="TokenLength70SimpleType" minOccurs="0"/>
Expand Down Expand Up @@ -708,6 +724,7 @@
<xsd:attribute name="language" type="LanguageCodeSimpleType" default="nl"/>
</xsd:attributeGroup>


<xsd:element name="EPaymentInterface" type="EPaymentInterfaceType"/>

</xsd:schema>
Loading