academe/omnipay-mpay24

mPAY24 driver for Omnipay v3

1.1.5 2020-07-30 16:46 UTC

This package is auto-updated.

Last update: 2021-10-29 02:38:05 UTC


README

Latest Stable Version Total Downloads Latest Unstable Version License

Table of Contents

mPAY24 Driver for Omnipay v3

There are two main front ends to initiate a payment: paymentPage and seamless.

The paymentPage (also known as the redirect method) handles payments completely offsite, while seamless keeps the user on site for most of the time, only going off site for 3D Secure or remote service authentication and authorisation.

Both intiation types use the same direct server (known as backend2backend) API methods.

Seamless Payment Initiation

This intiation method handles a number of payment types, some requiring additional PCI checks to use. The most comming credit card method will be token based, with a token being created at the back end first, and a URL related to that token being used to provide an iframe-based credit card form. An example of how this can work is shown below, but there are other ways it can be done, with additional front-end functionality to choose payment types.

Create Token

First a token is created on the back end. This token will need to be saved for the next stage, either in the session or passed through the order form.

use Omnipay\Omnipay;

$gateway = Omnipay::create('Mpay24_Seamless');

$gateway->setMerchantId('12345');
$gateway->setPassword('AB1234cd56');
$gateway->setTestMode(true);

$request = $gateway->token([
    'language' => 'en',
    //'customerId' => 'foo',
    //'profileId' => 'bar',
    //'style' => 'fizz',
]);

$response = $request->send();

if (! $response->isSuccessful()) {
    // Token could not be generated.
    echo '<p>Error: '.$response->getReturnCode().'</p>';
    exit;
}

This gives us a token and an iframe URL:

$response->getRedirectUrl();
$response->getToken();

The payment form can be created as follows, assuming /pay as the next enpoint in your flow. The iframe will contain the rendered credit card form. Add whatever additional customer or order details you want to the form. The iframe will be submitted with the form, but won't itself make any changes to your form; the credit card details go straight to the mPAY24 gateway. With this example, the submit bitton will remain disabled until the credit card details in the iframe have been completed.

The token does not need to go through the form, but could be carried forward through the session instead.

<?php

<iframe src="<?php echo $response->getRedirectUrl(); ?>" frameBorder="0" width="500"></iframe>

<form action="/pay" method="POST">
  <input name="token" type="hidden" value="<?php echo $response->getToken(); ?>" />
  <button id="paybutton" name="type" value="TOKEN" type="submit" disabled="true">Pay with creditcard</button>
  <button name="type" value="PAYPAL" type="submit">Pay with paypal</button>
</form>

<script>
  window.addEventListener("message", checkValid, false);
  function checkValid(form) {
    var data = JSON.parse(form.data);
    if (data.valid === "true") {
      document.getElementById("paybutton").disabled=false;
    }
  }
</script>

The /pay endpoint handles the actual payment.

The above form does not redirect the user to a payment page. Instead, it sends the card details to the gateway, with the token as a key. So in the next step, the gateway will already have the card details and the merchant site will just use the pre-generated token to reference them when completing the payment.

Payment Using Token

use Omnipay\Omnipay;
use Omnipay\Common\CreditCard;

$gateway = Omnipay::create('Mpay24_Seamless');

$gateway->setMerchantId('12345');
$gateway->setPassword('AB1234cd56');
$gateway->setTestMode(true);

$card = new CreditCard([
    'name' => 'Fred Bloggs',
    //
    'billingName' => 'Fred Billing',
    'billingAddress1' => 'Street 1',
    'billingAddress2' => 'Street 2',
    'billingCity' => 'City',
    'billingPostcode' => 'Postcode',
    'billingCountry' => 'GB',
    //
    'shippingName' => 'Fred Shipping',
    'shippingAddress1' => 'Street 1',
    'shippingAddress2' => 'Street 2',
    'shippingCity' => 'City',
    'shippingPostcode' => 'Postcode',
    'shippingCountry' => 'GB',
]);

$request = $gateway->purchase([
    'paymentType' => 'TOKEN', // or PAYPAL etc. e.g $_POST['type'] in this example.
    'amount' => '9.98',
    'currency' => 'EUR',
    'token' => $token, // e.g. $_POST['token']
    'transactionId' => $transactionId,
    'description' => 'Test Order',
    'returnUrl' => 'https://example.com/complete/success',
    'errorUrl' => 'https://example.com/complete/error',
    'notifyUrl' => 'https://example.com/notify',
    'language' => 'en',
    'card' => $card,
]);

$response = $request->send();

If the payment request is succcessful, then a redirect is likely to be needed to complete 3D Secure actions, Paypal or bank authentication and so on:

if (! $response->isSuccessful() && $response->isRedirect()) {
    $response->redirect();
    exit;
}

Seamless Complete Payment

After 3D Secure is completed, you will be returned to your /complete endpoint where you need to fetch the results of the transation:

use Omnipay\Omnipay;

$gateway = Omnipay::create('Mpay24_Seamless');

$gateway->setMerchantId('12345');
$gateway->setPassword('AB1234cd56');
$gateway->setTestMode(true);

$request = $gateway->completePurchase([
    // Will be in $_GET['TID'], but don't trust that; store it in the session.
    'transactionId' => $transactionId,
]);

$response = $request->send();

The $response will contain the normal Omnipay statuses and messages to define the result.

Note: your complete endpoint will be given the transaction result when redirected from the gateway. This result is not signed, and so can be easily manipulated by an end user. For this reason, this driver fetches the result from the gateway (a "pull" notification) to ensure no untrusted user data becomes a part of the process.

Payment Page

The payment page sends the user to the payment gateway to make a payment. The user will have a single payment type chosen for them, or can choose from a range of payment types offered, from a list filtered by the merchant site.

Purchase (redirect)

use Omnipay\Omnipay;
use Omnipay\Common\CreditCard;

$gateway = Omnipay::create('Mpay24_PaymentPage');

$gateway->setMerchantId('12345');
$gateway->setPassword('AB1234cd56');
$gateway->setTestMode(true);

$request = $gateway->purchase([
    'amount' => '9.98',
    'currency' => 'EUR',
    'token' => $token, // e.g. $_POST['token']
    'transactionId' => $transactionId,
    'description' => 'Test Order',
    'returnUrl' => 'https://example.com/complete/success',
    'errorUrl' => 'https://example.com/complete/error',
    'notifyUrl' => 'https://example.com/notify',
    'language' => 'en',
    'card' => $card, // Names, addresses
    'items' => $items,
]);

$response = $request->send();

If all is accepted, the $response object will be a redirect to the payment page.

To restrict the user to a single payment method, add the paymentType and brand. Example:

    'paymentType' => 'CC',
    'brand' => 'VISA',

Alternatively a range of payment methods can be supplied as a JSON string:

    'paymentMethods' => [
      ["paymentType" => "CC", "brand" => "VISA"],
      ["paymentType" => "CC", "brand" => "MASTERCARD"],
      ["paymentType" => "PAYPAL", "brand" => "PAYPAL"],
    ],

    // Or you can supply 'paymentMethods' as a JSON string.

For some payment types the brand is mandatory and for some it is optional. Examples:

  • paymentType "CC" and brand "VISA" will offer a visa card payment type only.
  • paymentType "CC" and no brand will offer a choice of all credit card types available.
  • No paymentType and no brand will offer a choice from all payment types available.

Payment Page Complete Payment

The transaction is completed in exactly the same way as for the seamless payments.

Payment Page Recurring Profiles

The gateway supports two types of profile: a single recurring payment profile for a customer, and up to 20 interactive profiles for each customer. The Payment Page API will support only ONE of these profile types at a time. This driver presently support ONLY recurrent payment profiles for Payment Page.

To create or update a customer's recurring payment profile, when making a purchase, set the createCard flag and provide a cardReference:

'createCard' => true,
'cardReference' => 'card-12345',

On completing the payment, you can check if the customer recurring profile was created or updated by checking the profile status:

$profileWasCreatedOrUpdates = $completeResult->isProfileChanged();

If this returns true, then it means the payment details for the current transaction have been saved against the customer ID. Use the customer ID as though it were a card reference when making a backend payment.

A customer ID can be used to make a recurring payment (an offline payment) liek this:

$gateway = Omnipay::create('Mpay24_Backend');

// Set the usual merchant ID and test mode flags.

$request = $gateway->purchase([
    'amount' => '9.99',
    'currency' => 'EUR',
    'transactionId' => 'new-transaction-id',
    'description' => 'Recurring Payment Description',
    'card' => [
        'name' => 'Customer Name',
    ],
    'notifyUrl' => 'https://omnipay.acadweb.co.uk/mpay24/notify.php?foo=bar&fee=fah', // mandatory
    'language' => 'de',
    'cardReference' => 'card-12345',
]);

This will return the details of the successful payment, or error details if not successful.

Notification Handler

The notification handler will accept notification server requests, and provide the status, amounts, payment methods actually used, transactionReference.

$request = $gateway->acceptNotification();

// $request->getTransactionId();
// $request->getTransactionReference();
// $request->getTransactionStatus();
// $request->getMoney();
// $request->isSuccessful();
// $request->getData();