GiroCheckout driver for the Omnipay PHP payment processing library
Omnipay is a framework agnostic, multi-gateway payment processing library for PHP 5.
This package implements Girocheckout support, and supports PHP 7.1+.
This package is currently built for the Omnipay v3.0-beta.1
on the master
branch.
The major version number of this driver is intended to track the major version number
of the omnipay-common package.
If you are using the Omnipay 2.x, please use the 2.x branch.
- Omnipay: GiroCheckout
- Table of Contents
- Installation
- Authentication
- Credit Card Payment Type
- Direct Debit Payment Type
- PayPal Payment Type
- Giropay Payment Type
- Paydirekt Payment Type
- Payment Page Payment Type
- Bluecode Payment Type
Using composer, the 3.0 branch can be installed like this:
composer require league/omnipay academe/omnipay-girocheckout:~3.0
A GiroCheckout merchant account is first set up. Within that account, one of more projects are set up. Each project is configured to run just one payment type (e.g. credit card, direct debit).
Each project contains a pre-shared secret. That secret is used to sign all messages, in both directions (requests to the gateway, responses to those requests, and server request notification messages from the gateway to your merchant site).
So for each payment type, you will have the following matched authentication details, required for all interaction:
- Merchant ID
- Project ID
- Pre-shared secret (passphrase)
- Payment type
A gateway could be set up like this:
use Omnipay\GiroCheckout\Gateway;
use Omnipay\Omnipay;
// The backward slashes are needed to make the driver base class absolute.
// An issue will be raised against Omnipay Common to fix this.
$gateway = Omnipay::create('\\' . Gateway::class);
// or
$gateway = Omnipay::create('GiroCheckout/Gateway';
// The IDs can be given as integers in strings.
$gateway->setMerchantID('3610000');
$gateway->setProjectID('37000');
$gateway->setProjectPassphrase('ZFXDMpXDMpVV9Z');
// Other payment types are supported.
$gateway->setPaymentType(Gateway::PAYMENT_TYPE_CREDIT_CARD);
// or
$gateway->initialize([
'merchantId' => 3610000,
'projectId' => 37000,
'projectPassphrase' => 'ZFXDMpXDMpVV9Z',
'paymentType' => Gateway::PAYMENT_TYPE_CREDIT_PAYPAL,
]);
This payment type supports authorize and purchase. A card can be tokenised during a transaction and used again for future payments with the user present, or for offline repeat payments.
The capture/refund/void methods are also available.
A simple authorize will look like this:
use Money\Money;
use Money\Currency;
$gateway->setPaymentType(Gateway::PAYMENT_TYPE_CREDIT_CARD);
$authRequest = $gateway->authorize([
'transactionId' => $yourMerchantTransactionId,
//
// Several ways to supply the amount:
'amount' => '4.56',
'amount' => new Money(456, new Currency('EUR')),
'amount' => Money::EUR(456),
//
'currency' => 'EUR',
'description' => 'Mandatory reason for the transaction',
'language' => 'en',
'returnUrl' => 'url to bring the user back to the merchant site',
'notifyUrl' => 'url for the gateway to send direct notifications',
'mobile' => false,
]);
The response will be a redirect to the gateway, where the user will enter their credit card details. The language setting will define the language used in the user interface and in error messages returned in the response.
On completion, the result of the transaction will sent to the merchant site in two ways (both will be used):
- Via the notification URL.
- Through query parameters given to the return URL.
The notifyUrl
and the returnUrl
can both take custom query parameters.
The gateway will merge in its own parameters when using the URLs.
When the user returns to the returnUrl
, the transaction result can be extracted
like this:
$completeRequest = $gateway->completeAuthorize();
$completeResponse = $completeRequest->send();
// Available standard Omnipay details:
$completeResponse->getCode();
$completeResponse->getMessage();
$completeResponse->isSuccessful();
$completeResponse->isCancelled();
$completeResponse->getTransactionStatus();
$completeResponse->getTransactionReference();
If the response fails its hash check against the shared secret, then an exception
will be raised on send()
. The raw response data can still be read for logging as
$completeRequest->getData()
, which returns an array.
The notification handler, on the notifyUrl
, is set up like this:
$notifyRequest = $gateway->acceptNotification();
$notifyResponse = $notifyRequest->send();
Once the authorisation is complete, the amount still needs to be captured.
Exactly the same rules apply as to the completeAuthorize
request - an exception
will be raised if the hash does not validate; the same standard Omnipay result
details are available.
When authorizing, the gateway can be asked to create a reusable card reference. This flag in the authorize request will trigger that:
$authRequest = $gateway->authorize([
...
'createCard' => true,
]);
After the authorize completes, the card reference is fetched using this request:
$getCardRequest = $gateway->getCard([
'transactionReference' => 'otiginal transaction reference',
]);
$getCardResponse = $getCardRequest->send();
// The reusable `cardReference` is available here:
$cardReference = $getCardResponse->getTransactionReference();
// Other details about the card that may be useful:
$getCardResponse->getNumberMasked();
$getCardResponse->getExpiryYear();
$getCardResponse->getExpiryMonth();
The $cardReference
is then used for authorizing:
$authRequest = $gateway->authorize([
...
'cardReference' => $cardReference,
]);
The user will be redirected to the payment gateway like the basic authorize,
but the credit card details will be already completed (and cannot be changed
by the user).
The user will need to enter their CVV
to authorise use of the card.
By setting the recurring
parameter flag, even the need for the CVV to be
entered can be avoided. This feature is only available on application.
Even through the user will be redirected to the gateway, they will be redirected
back again immediately with no need to enter any card or CVV details.
However, the redirect does give the gateway the option to insert some additional
validation if it needs to.
When a reusable cardReference
is used, the need to redirect the user to the
gateway can be avoided by resetting the paymentPage
parameter.
$authRequest = $gateway->authorize([
...
'paymentPage' => false,
]);
This can be used without the user being present, so is useful for subscriptions and other repeated payments.
Replace purchase
in place of authorize
.
The required amount can be captured using this request:
$captureRequest = $gateway->capture([
'transactionId' => $yourMerchantTransactionId,
'amount' => Money::EUR(123),
'currency' => 'EUR',
'description' => 'Capture reason is required',
'transactionReference' => 'original authorize transaction reference',
]);
$captureRersponse = $captureRequest->send();
// Check if successful:
$captureRersponse->isSuccessful();
// Some other details:
$captureRersponse->getCode();
$captureRersponse->getMessage();
$captureRersponse->getTransactionReference();
A refund of the full or a partial amount can be done using the refund
message.
It is used in exactly the same way as the capture
message.
A transaction can be completely voided like this:
$voidRequest = $gateway->capture([
'transactionReference' => 'original authorize transaction reference',
]);
$voidResponse = $voidRequest->send();
// Check if successful:
$captureRersponse->isSuccessful();
The Direct Debit payment type works in a very similar way to the Credit Card payment type. The main differences are:
- The bank account is identified by an IBAN or a sort code/bank code/BMZ and account number (SCAN).
- When fetching the saved "cardReference", details you get back include
ibanMasked
. - Running an authorize or payment without a paymentform, you can supply IBAN, SCAN or cardReference.
A simple authorize will look like this:
$gateway->setPaymentType(Gateway::PAYMENT_TYPE_DIRECTDEBIT);
$authRequest = $gateway->authorize([
'transactionId' => $yourMerchantTransactionId,
'amount' => Money::EUR(456),
'currency' => 'EUR', // Optional if the amount is Money
'description' => 'Mandatory reason for the transaction',
'language' => 'en',
'returnUrl' => 'url to bring the user back to the merchant site',
'notifyUrl' => 'url for the gateway to send direct notifications',
'mobile' => false,
// Parameters specific to Direct Debit, all optional:
'mandateReference' => '...',
'mandateSignedOn' => '...',
'mandateReceiverName' => '...',
'mandateSequence' => '...',
]);
The mandateSignedOn
is a date in the forma YYYY-MM-DD
.
A DateTime
or derived object can ve supplied instead, which includes Carbon\Carbon
objects.
The Direct Debit payment type supports saving the details of the collected bank details
as a cardReference
. Triggering the saving is done by turning on creatCard
like this:
$authRequest = $gateway->authorize([
...
'createCard' => true,
]);
The cardReference
can be fetched in the same way as the Credit Card payment type.
The payment page redirect can be turned off to support offline payment, without the user being present:
$authRequest = $gateway->authorize([
...
'paymentPage' => false,
]);
When making an offline payment, one of the following must be supplied:
- cardReference
- IBAN
- SCAN
$authRequest = $gateway->authorize([
...
'cardReference' => '13b5ca34a8389774690154bcc0da0a8e',
// or
'iban' => 'DE87123456781234567890',
// or
'accountHolder' => 'Name',
'bankCode' => '12345678',
'bankAccount' => '1234567890',
]);
These operate in exactly the same way as for Credit Card payments.
The PayPal payment type supports only one request type, purchase
.
A simple purchase will look like this:
$gateway->setPaymentType(Gateway::PAYMENT_TYPE_PAYPAL);
$authRequest = $gateway->purchase([
'transactionId' => $yourMerchantTransactionId,
'amount' => Money::EUR(789),
'currency' => 'EUR',
'description' => 'Mandatory reason for the transaction',
'returnUrl' => 'url to bring the user back to the merchant site',
'notifyUrl' => 'url for the gateway to send direct notifications',
]);
The response should be a redirect to the remote gateway.
On return from the gateway, the result can be accessed using the
$response -> $gateway->complete()->send()
message like for previous payment types.
The back-channel notification handler will be sent the usual details too.
This payment type only works for payments in Euros, and only for issuing banks that have registered with the service (over 1400 to date).
As well as making payments, there are a number of supporting API methods.
This method returns a list of issuing banks that are regisered for this service. The list would normally be used to present to the end user so they can choose their personal bank.
$gateway->setPaymentType(Gateway::PAYMENT_TYPE_GIROPAY);
$request = $gateway->getIssuers();
$response = $request->send();
// The list of named banks is indexed by their BIC.
if ($response->isSuccessful()) {
$bankList = $response->getIssuerArray();
var_dump($bankList);
}
// array(1407) {
// ["BELADEBEXXX"]=>
// string(38) "Landesbank Berlin - Berliner Sparkasse"
// ["BEVODEBBXXX"]=>
// string(18) "Berliner Volksbank"
// ["GENODEF1P01"]=>
// string(27) "PSD Bank Berlin-Brandenburg"
// ["WELADED1WBB"]=>
// string(9) "Weberbank"
// ...
// }
Once an issuing bank is chosen, its capabilities can be checked. This tests whether it supports Giropay, or Giropay+ID, or both.
This list can also be retrieved on the front end only using the Bank Selection Widget. There is no direct support for the widget in this driver.
$request = $gateway->getBankStatus([
'bic' => 'TESTDETT421',
]);
$response = $request->send();
// Both return boolean.
$supportsGiropay = $response->hasGiropay();
$supportsGiropayId = $response->hasGiropayId();
There is no authorize
capability, just purchase
.
$request = $gateway->purchase([
'transactionId' => $transactionId,
'amount' => Money::EUR(123),
'currency' => 'EUR',
'description' => 'Transaction ' . $transactionId,
'returnUrl' => 'url to bring the user back to the merchant site',
'notifyUrl' => 'url for the gateway to send direct notifications',
'bic' => 'TESTDETT421', // mandatory
'info1Label' => 'My Label 1',
'info1Text' => 'My Text 1',
]);
The result will be a redirect to the gateway or bank.
On return, the usual completePurchase
and acceptNotification
messages will provide
the result of the transaction attempt.
The final result includes the following methods to inspect additional details:
$notifyResponse->getResultAvs();
$notifyResponse->getObvName();
$notifyResponse->isAgeVerificartionSuccessful();
Details of the sender can be fetched given a successful transaction.
$request = $gateway->getSender([
'transactionReference' => '6b65a235-e7c1-464f-b238-ea4ea0bc647f',
]);
$response = $request->send();
Details include:
$response->getAccountHolder();
// string(17) "Stefan Adlerhorst"
$response->getIban();
// string(22) "DE46940594210000012345"
$response->getBic();
// string(11) "TESTDETT421"
Use the Giropay-ID
payment type to just perform age verification without
making a payment. You can leave out the amount, currency and description, as
none of those are sent to the gateway.
$gateway->setPaymentType(Gateway::PAYMENT_TYPE_GIROPAY_ID);
This is the only payment type that accepts a shopping cart details and
a CreditCard
object for shipping details.
Capabilities of this payment type include authorize
and purchase
.
An authorization transaction can be further processed though capture
and void
. A purchase transaction can accept a refund
.
The gateway requires cart item prices to be in minor units. Since Omnipay 2.x (or 3.x at this time) does not define the units cart items use, some assumptions will be made and conversions performed as follows (all these formats are treated as the same amount, namely 123 minor units, such as €1.23):
Money\Money::EUR(123)
- String '1.23'
- String '123'
- Integer 123
- Float 1.23
If no currency is set explicitly with setCurrency()
then it will be taken from the amount
if using a Money\Money
object.
To avoid ambiguity, we recommend you use Money\Money
for all ItemBag
price
amounts.
This payment type offers the customer all payment methods available from the merchant rather than displaying them separately. The payment page allows the customer to select the payment method they wish to use and then the selected payment is initialized accordingly.
This method returns a list of possible GiroCockpit projects. The list contains the following elements:
- Project Id
- Project Name
- Paymethod Number (see Payment methods)
- Mode (TEST or LIVE)
$gateway->setPaymentType(Gateway::PAYMENT_TYPE_PAYMENTPAGE);
$request = $gateway->getProjects();
$response = $request->send();
if ($response->isSuccessful()) {
$projects = $response->getProjects();
var_dump($projects);
}
// array(5) {
// [0]=>
// array(4) {
// ["id"]=>
// string(5) "37570"
// ["name"]=>
// string(11) "Giropay One"
// ["paymethod"]=>
// string(1) "1"
// ["mode"]=>
// string(4) "TEST"
// }
// ...
// }
The Payment Page's cancelUrl
differs to the rest of the payment types as it does not
return the transaction cancelled details.
If the user follows the cacnel URL from this payment method, it seems the transaction is
not actually cancelled, but is left to time out instead, at which point your merchant
site will be sent a cancellation notification.
In summary, you must not call completeAuthorise
when returning to the merchant site
from the Payment Page payment type.
This payment type works currently only with bank accounts in Germany and Austria.
Bluecode only supports purchase (sale) and refund operations. There is not authorize and/or void, like with credit cards.
Issue a purchase transaction:
$gateway->setPaymentType(Gateway::PAYMENT_TYPE_BLUECODE);
$purchaseRequest = $gateway->purchase([
'transactionId' => $yourMerchantTransactionId,
'amount' => 4.56,
'currency' => 'EUR', // or any other valid currency code
'description' => 'Reason for the transaction',
'returnUrl' => 'url to bring the user back to the marchant site',
'notifyUrl' => 'url for the gateway to send direct notifications',
]);
Issue a refund
$gateway->setPaymentType(Gateway::PAYMENT_TYPE_BLUECODE);
$refundRequest = $gateway->refund([
'transactionId' => $yourMerchantTransactionId,
'amount' => 4.56,
'currency' => 'EUR', // or any other valid currency code
'description' => 'Reason for the transaction',
'transactionReference' => 'original purchase transaction reference'
]);