Transaction Request

The Gateway API expects an HTTP POST request with XML Payload and an Authorization header containing a Hash HMAC signature (see Signing Requests below).

The destination URL is: https://gateway.tillpayments.com/transaction

Basic Scheme

<?xml version="1.0" encoding="utf-8"?>
<transaction xmlns="https://gateway.tillpayments.com/Schema/V2/Transaction">
  <username>YOUR_USERNAME</username>
  <password>SHA1 HASHED PASSWORD</password>
  <debit>
    <transactionId>Your Transaction ID</transactionId>
    <customer>
      <!-- refer to Transaction Data for all available fields -->
      <identification>Customer ID</identification>
      <billingCountry>2-letter country code of your customer</billingCountry>
      <email>email address of your customer</email>
      <ipAddress>127.0.0.1</ipAddress>
    </customer>
    <extraData key="some_key">value_here</extraData>
    <amount>9.99</amount>
    <currency>EUR</currency>
    <description>Transaction Description</description>
    <successUrl>https://link.to/your/payment-successful-page</successUrl>
    <cancelUrl>https://link.to/your/payment-canceled-page</cancelUrl>
    <errorUrl>https://link.to/your/payment-failed-page</errorUrl>
    <callbackUrl>https://link.to/your/notification-handler</callbackUrl>
    <withRegister>false</withRegister>
  </debit>
</transaction>
$username = 'Your Username';
$password = 'Your password';
$apiKey = 'Connector API Key';
$sharedSecret = 'Connector Shared Secret';

$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$debit = new \PaymentGateway\Client\Transaction\Debit();
$debit
  ->setTransactionId('Your transaction ID')
  ->setAmount(9.99)
  ->setCurrency('EUR')
  ->setDescription('Your Description')
  ->setSuccessUrl('https://link.to/your/payment-successful-page')
  ->setCancelUrl('https://link.to/your/payment-canceled-page')
  ->setErrorUrl('https://link.to/your/payment-failed-page')
  ->setCallbackUrl('https://link.to/your/notification-handler');

$customer = new \PaymentGateway\Client\Data\Customer();
$customer
  ->setFirstName('John')
  ->setLastName('Smith')
  ->setIdentification('The User ID')
  ->setBillingCountry('AT')
  ->setEmail('email_address@of_your_customer.com')
  ->setIpAddress('127.0.0.1');

$debit->setCustomer($customer);

$result = $client->debit($debit);

The examples show the basic data most connector requires. Depending on the connector type more data could be necessary. Please refer to the Connector Types documentation for concrete requirements.

To see all available fields please refer to Transaction Data.

For some languages we already provide a ready-to-use client implementation on GitHub.

Debit

<?xml version="1.0" encoding="utf-8"?>
<transaction xmlns="https://gateway.tillpayments.com/Schema/V2/Transaction">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <debit>
    <transactionId>transaction-00001</transactionId>
    <customer>
      <identification>1111</identification>
      <firstName>John</firstName>
      <lastName>Smith</lastName>
      <billingCountry>AT</billingCountry>
      <email>[email protected]</email>
      <ipAddress>123.123.123.123</ipAddress>
    </customer>
    <extraData key="some_key">value_here</extraData>
    <merchantMetaData>my-category-1</merchantMetaData>
    <amount>4.99</amount>
    <currency>EUR</currency>
    <description>Transaction Description</description>
    <successUrl>https://link.to/your/payment-successful-page</successUrl>
    <cancelUrl>https://link.to/your/payment-canceled-page</cancelUrl>
    <errorUrl>https://link.to/your/payment-failed-page</errorUrl>
    <callbackUrl>https://link.to/your/notification-handler</callbackUrl>
    <withRegister>false</withRegister>
    <transactionIndicator>SINGLE</transactionIndicator>
  </debit>
</transaction>
<?php
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$debit = new \PaymentGateway\Client\Transaction\Debit();
$debit
  ->setTransactionId('transaction-00001')
  ->setAmount(4.99)
  ->setCurrency('EUR')
  ->setDescription('Transaction Description')
  ->setSuccessUrl('https://link.to/your/payment-successful-page')
  ->setCancelUrl('https://link.to/your/payment-canceled-page')
  ->setErrorUrl('https://link.to/your/payment-failed-page')
  ->setCallbackUrl('https://link.to/your/notification-handler');

$customer = new \PaymentGateway\Client\Data\Customer();
$customer
  ->setFirstName('John')
  ->setLastName('Smith')
  ->setIdentification('1111')
  ->setBillingCountry('AT')
  ->setEmail('[email protected]')
  ->setIpAddress('123.123.123.123');

$debit->setCustomer($customer);

$result = $client->debit($debit);
curl https://gateway.tillpayments.com/transaction \
  -d "PUT_XML_HERE" \
  -H "Authorization: Gateway ConnectorKey:Signature" \
  -H "Content-Type: text/xml"

A Debit performs a complete customer-to-merchant payment

Recurring Debits (and Preauthorizations)

<?xml version="1.0" encoding="utf-8"?>
<transaction xmlns="https://gateway.tillpayments.com/Schema/V2/Transaction">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <debit>
    <transactionId>transaction-00002</transactionId>
    <customer>
      <identification>1111</identification>
      <firstName>John</firstName>
      <lastName>Smith</lastName>
      <billingCountry>AT</billingCountry>
      <email>[email protected]</email>
      <ipAddress>123.123.123.123</ipAddress>
    </customer>
    <referenceTransactionId>ID-FROM-FIRST-TRANSACTION</referenceTransactionId>
    <amount>4.99</amount>
    <currency>EUR</currency>
    <description>Transaction Description</description>
    <successUrl>https://link.to/your/payment-successful-page</successUrl>
    <cancelUrl>https://link.to/your/payment-canceled-page</cancelUrl>
    <errorUrl>https://link.to/your/payment-failed-page</errorUrl>
    <callbackUrl>https://link.to/your/notification-handler</callbackUrl>
    <transactionIndicator>RECURRING</transactionIndicator> <!-- or CARDONFILE -->
  </debit>
</transaction>

For recurring charges the initial transaction must either be a Register, or a Debit resp. Preauthorize with the withRegister flag set to true.

You must store the returned referenceId and use for recurring transactions in the field referencedTransactionId.

Debits with payment.js Integration

<?xml version="1.0" encoding="utf-8"?>
<transaction xmlns="https://gateway.tillpayments.com/Schema/V2/Transaction">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <debit>
    <transactionToken>ix::abcdefghijklmnopqrstuvw</transactionToken>
    <transactionId>transaction-00001</transactionId>
    <customer>
      <identification>1111</identification>
      <firstName>John</firstName>
      <lastName>Smith</lastName>
      <billingCountry>AT</billingCountry>
      <email>[email protected]</email>
      <ipAddress>123.123.123.123</ipAddress>
    </customer>
    <amount>4.99</amount>
    <currency>EUR</currency>
    <description>Transaction Description</description>
    <successUrl>https://link.to/your/payment-successful-page</successUrl>
    <cancelUrl>https://link.to/your/payment-canceled-page</cancelUrl>
    <errorUrl>https://link.to/your/payment-failed-page</errorUrl>
    <callbackUrl>https://link.to/your/notification-handler</callbackUrl>
    <withRegister>false</withRegister>
    <transactionIndicator>SINGLE</transactionIndicator> <!-- or INITIAL, if withRegister = true -->
  </debit>
</transaction>

If you've integrated the payment.js Javascript Library, you must put the token acquired with the tokenize call inside the transactionToken element.

Preauthorize

<?xml version="1.0" encoding="utf-8"?>
<transaction xmlns="https://gateway.tillpayments.com/Schema/V2/Transaction">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <preauthorize>
    <transactionId>transaction-00001</transactionId>
    <customer>
      <identification>1111</identification>
      <firstName>John</firstName>
      <lastName>Smith</lastName>
      <billingCountry>AT</billingCountry>
      <email>[email protected]</email>
      <ipAddress>123.123.123.123</ipAddress>
    </customer>
    <merchantMetaData>my-category-1</merchantMetaData>
    <amount>4.99</amount>
    <currency>EUR</currency>
    <description>Transaction Description</description>
    <successUrl>https://link.to/your/payment-successful-page</successUrl>
    <cancelUrl>https://link.to/your/payment-canceled-page</cancelUrl>
    <errorUrl>https://link.to/your/payment-failed-page</errorUrl>
    <callbackUrl>https://link.to/your/notification-handler</callbackUrl>
    <withRegister>false</withRegister>
  </preauthorize>
</transaction>
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$preAuth = new \PaymentGateway\Client\Transaction\Preauthorize();
$preAuth
  ->setTransactionId('transaction-00001')
  ->setAmount(4.99)
  ->setCurrency('EUR')
  ->setDescription('Transaction Description')
  ->setSuccessUrl('https://link.to/your/payment-successful-page')
  ->setCancelUrl('https://link.to/your/payment-canceled-page')
  ->setErrorUrl('https://link.to/your/payment-failed-page')
  ->setCallbackUrl('https://link.to/your/notification-handler');

$customer = new \PaymentGateway\Client\Data\Customer();
$customer
  ->setFirstName('John')
  ->setLastName('Smith')
  ->setIdentification('1111')
  ->setBillingCountry('AT')
  ->setEmail('[email protected]')
  ->setIpAddress('123.123.123.123');

$preAuth->setCustomer($customer);

$result = $client->preauthorize($preAuth);

A Preauthorize reserves the payment amount on the customer's payment instrument.

Depending on the payment method you have up to 7 days until you must Capture the transaction before the authorization expires.

Capture

<?xml version="1.0" encoding="utf-8"?>
<transaction xmlns="https://gateway.tillpayments.com/Schema/V2/Transaction">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <capture>
    <transactionId>transaction-00002</transactionId>
    <referenceTransactionId>uuid_of_preauthorize_transaction</referenceTransactionId>
    <amount>4.99</amount>
    <currency>EUR</currency>
  </capture>
</transaction>
<?php
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$capture = new \PaymentGateway\Client\Transaction\Capture();
$capture
  ->setTransactionId('transaction-00002')
  ->setAmount(4.99)
  ->setCurrency('EUR')
  ->setReferenceTransactionId('UUID_of_Preauthorize_Transaction');

$result = $client->capture($capture);

A Capture completes the payment which was previously authorized with the Preauthorize method.

Depending on the payment method you can even capture only a partial amount of the authorized amount.

Void

<?xml version="1.0" encoding="utf-8"?>
<transaction xmlns="https://gateway.tillpayments.com/Schema/V2/Transaction">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <void>
    <transactionId>transaction-00002</transactionId>
    <referenceTransactionId>uuid_of_preauthorize_transaction</referenceTransactionId>
  </void>
</transaction>
<?php
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$void = new \PaymentGateway\Client\Transaction\VoidTransaction();
$void
  ->setTransactionId('transaction-00002')
  ->setReferenceTransactionId('UUID_of_Preauthorize_Transaction');

$result = $client->void($void);

A Void cancels a previously performed authorization made with the Preauthorize method.

Refund

<?xml version="1.0" encoding="utf-8"?>
<transaction xmlns="https://gateway.tillpayments.com/Schema/V2/Transaction">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <refund>
    <transactionId>transaction-00002</transactionId>
    <referenceTransactionId>uuid_of_debit_or_capture_transaction</referenceTransactionId>
    <amount>4.99</amount>
    <currency>EUR</currency>
  </refund>
</transaction>
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$refund = new \PaymentGateway\Client\Transaction\Refund();
$refund
  ->setTransactionId('transaction-00002')
  ->setAmount(4.99)
  ->setCurrency('EUR')
  ->setReferenceTransactionId('uuid_of_debit_or_capture_transaction');

$result = $client->refund($refund);

A Refund reverses a payment which was previously performed with Debit or Capture.

Depending on the payment method you can even refund only a partial amount of the original transaction amount.

Payout

<?xml version="1.0" encoding="utf-8"?>
<transaction xmlns="https://gateway.tillpayments.com/Schema/V2/Transaction">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <payout>
    <transactionId>transaction-00001</transactionId>
    <referenceTransactionId>ID-FROM-FIRST-TRANSACTION</referenceTransactionId> <!-- this is optionally, but maybe required for certain methods -->
    <customer>
      <identification>1111</identification>
      <firstName>John</firstName>
      <lastName>Smith</lastName>
      <billingCountry>AT</billingCountry>
      <email>[email protected]</email>
      <ipAddress>123.123.123.123</ipAddress>
    </customer>
    <amount>4.99</amount>
    <currency>EUR</currency>
    <description>Transaction Description</description>
  </payout>
</transaction>
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$payout = new \PaymentGateway\Client\Transaction\Payout();
$payout
  ->setTransactionId('transaction-00001')
  ->setAmount(4.99)
  ->setCurrency('EUR')
  ->setDescription('Transaction Description');

$customer = new \PaymentGateway\Client\Data\Customer();
$customer
  ->setFirstName('John')
  ->setLastName('Smith')
  ->setIdentification('1111')
  ->setBillingCountry('AT')
  ->setEmail('[email protected]')
  ->setIpAddress('123.123.123.123');

$payout->setCustomer($customer);

$result = $client->payout($payout);

A Payout credits the customer's account with the given amount.

Depending on the connector, either referenceUuid or cardData will be required.

Register

<?xml version="1.0" encoding="utf-8"?>
<transaction xmlns="https://gateway.tillpayments.com/Schema/V2/Transaction">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <register>
    <transactionId>transaction-00001</transactionId>
    <customer>
      <identification>1111</identification>
      <firstName>John</firstName>
      <lastName>Smith</lastName>
      <billingCountry>AT</billingCountry>
      <email>[email protected]</email>
      <ipAddress>123.123.123.123</ipAddress>
    </customer>
    <description>Transaction Description</description>
    <successUrl>https://link.to/your/payment-successful-page</successUrl>
    <cancelUrl>https://link.to/your/payment-canceled-page</cancelUrl>
    <errorUrl>https://link.to/your/payment-failed-page</errorUrl>
    <callbackUrl>https://link.to/your/notification-handler</callbackUrl>
  </register>
</transaction>
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$register = new \PaymentGateway\Client\Transaction\Register();
$register
  ->setTransactionId('transaction-00001')
  ->setDescription('Transaction Description')
  ->setSuccessUrl('https://link.to/your/payment-successful-page')
  ->setCancelUrl('https://link.to/your/payment-canceled-page')
  ->setErrorUrl('https://link.to/your/payment-failed-page')
  ->setCallbackUrl('https://link.to/your/notification-handler');

$customer = new \PaymentGateway\Client\Data\Customer();
$customer
  ->setFirstName('John')
  ->setLastName('Smith')
  ->setIdentification('1111')
  ->setBillingCountry('AT')
  ->setEmail('[email protected]')
  ->setIpAddress('123.123.123.123');

$register->setCustomer($customer);

$result = $client->register($register);

Registers a customer's payment instrument for future charges (Debits or Preauthorizations)

Deregister

<?xml version="1.0" encoding="utf-8"?>
<transaction xmlns="https://gateway.tillpayments.com/Schema/V2/Transaction">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <deregister>
    <transactionId>transaction-00002</transactionId>
    <referenceTransactionId>uuid_of_preauthorize_transaction</referenceTransactionId>
  </deregister>
</transaction>
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$deregister = new \PaymentGateway\Client\Transaction\Deregister();
$deregister
  ->setTransactionId('transaction-00002')
  ->setReferenceTransactionId('UUID_of_Register_Transaction');

$result = $client->deregister($deregister);

A Deregister deletes a previously registered payment instrument using Register.

Debit with starting a Schedule

<!-- Request -->
<?xml version="1.0" encoding="utf-8"?>
<transaction xmlns="https://gateway.tillpayments.com/Schema/V2/Transaction">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <language>en</language>
  <debit>
    <transactionId>transaction-00001</transactionId>
    <customer>
      <identification>1111</identification>
      <firstName>John</firstName>
      <lastName>Smith</lastName>
      <billingCountry>AT</billingCountry>
      <email>[email protected]</email>
      <ipAddress>123.123.123.123</ipAddress>
    </customer>
    <amount>9.99</amount>
    <currency>EUR</currency>
    <description>Transaction Description</description>
    <successUrl>https://link.to/your/payment-successful-page</successUrl>
    <cancelUrl>https://link.to/your/payment-canceled-page</cancelUrl>
    <errorUrl>https://link.to/your/payment-failed-page</errorUrl>
    <callbackUrl>https://link.to/your/notification-handler</callbackUrl>
    <withRegister>true</withRegister>
    <startSchedule>
      <amount>4.99</amount>
      <currency>EUR</currency>
      <periodLength>1</periodLength>
      <periodUnit>MONTH</periodUnit>
      <startDateTime>2018-06-05 10:54:51 UTC</startDateTime>
    </startSchedule>
  </debit>
</transaction>
<!-- Response -->
<?xml version="1.0" encoding="utf-8"?>
<result xmlns="https://gateway.tillpayments.com/Schema/V2/Result">
  <success>true</success>
  <referenceId>12345678901234567890</referenceId>
  <purchaseId>20170101-12345678901234567890</purchaseId>
  <registrationId>aab69791ddedcaeae4ae</registrationId>
  <returnType>FINISHED</returnType>
  <scheduleId>SC-7FF3-37B8-0F27-8BCA-5B3D-90DB</scheduleId>
  <scheduleStatus>ACTIVE</scheduleStatus>
  <scheduledAt>2018-07-05 16:22:06 UTC</scheduledAt>
</result>
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$debit = new \PaymentGateway\Client\Transaction\Debit();
$debit
  ->setTransactionId('transaction-00001')
  ->setAmount(4.99)
  ->setCurrency('EUR')
  ->setDescription('Transaction Description')
  ->setSuccessUrl('https://link.to/your/payment-successful-page')
  ->setCancelUrl('https://link.to/your/payment-canceled-page')
  ->setErrorUrl('https://link.to/your/payment-failed-page')
  ->setCallbackUrl('https://link.to/your/notification-handler');

$customer = new \PaymentGateway\Client\Data\Customer();
$customer
  ->setFirstName('John')
  ->setLastName('Smith')
  ->setIdentification('1111')
  ->setBillingCountry('AT')
  ->setEmail('[email protected]')
  ->setIpAddress('123.123.123.123');

$debit->setCustomer($customer);

$debit->setWithRegister(true);

$scheduleData = new  \PaymentGateway\Client\Schedule\ScheduleData();

$scheduleData->setAmount(5.99);
$scheduleData->setCurrency('EUR');
$scheduleData->setPeriodLength(1);
$scheduleData->setPeriodUnit('MONTH');

$firstPeriodIsTrialPeriod = true;
$trialPeriodLength = '10 days';
$startDateTime = \new DateTime('+' . $trialPeriodLength);

if ($firstPeriodIsTrialPeriod) {
  $scheduleData->setStartDateTime($startDateTime);
}

$debit->setSchedule($scheduleData);

$result = $client->debit($debit);

You can start a transaction with a schedule on the fly, the transaction must be either a Register, a Debit with-register or a Preauthorize with-register.

The field startDateTime is optional and can be used to set a differing length for the first period (e.g. as trial period).

If your customer is already registered, and you can provide the registrationId, then it is recommended to use the Schedule API instead (see Schedule API).

Transaction Response

As response to the API call the gateway answers with a Result XML with the status and further instructions.

Generally there are 4 possible results:

FINISHED

<?xml version="1.0" encoding="utf-8"?>
<result xmlns="https://gateway.tillpayments.com/Schema/V2/Result">
  <success>true</success>
  <referenceId>12345678901234567890</referenceId>
  <purchaseId>20170101-12345678901234567890</purchaseId>
  <returnType>FINISHED</returnType>
</result>
$result = $client->debit($debit);

if ($result->getReturnType() == \PaymentGateway\Client\Transaction\Result::RETURN_TYPE_FINISHED) {
  //transaction was successful
  $uuid = $result->getReferenceId();
  //proceed with your checkout process
}

The transaction completed and was processed successfully. You can deliver the ordered goods.

ERROR

<?xml version="1.0" encoding="utf-8"?>
<result xmlns="https://gateway.tillpayments.com/Schema/V2/Result">
  <success>false</success>
  <referenceId>12345678901234567890</referenceId>
  <purchaseId>20170101-12345678901234567890</purchaseId>
  <returnType>ERROR</returnType>
  <errors>
    <error>
      <message>Card number invalid</message>
      <code>2008</code>
      <adapterMessage>Invalid card number</adapterMessage>
      <adapterCode>200</adapterCode>
    </error>
  </errors>
</result>
$result = $client->debit($debit);

if ($result->getReturnType() == \PaymentGateway\Client\Transaction\Result::RETURN_TYPE_ERROR) {
  //transaction failed
  $error = $result->getFirstError();
    $errorMessage = $error->getMessage();
    $errorCode = $error->getCode();
  //if reasonable tell your customer to choose a different payment method
}

The transaction failed or was declined. See the error code and message for further details.

You will find the native error message and code from the payment provider/acquiring bank in the fields adapterMessage and adapterCode.

REDIRECT

<result xmlns="https://gateway.tillpayments.com/Schema/V2/Result">
  <success>true</success>
  <referenceId>12345678901234567890</referenceId>
  <purchaseId>20170101-12345678901234567890</purchaseId>
  <returnType>REDIRECT</returnType>
  <redirectUrl>https://gateway.tillpayments.com/redirect/12345678901234567890/ABCDEF01234567890ABCDEF01234567890=</redirectUrl>
</result>
$result = $client->debit($debit);

if ($result->getReturnType() == \PaymentGateway\Client\Transaction\Result::RETURN_TYPE_REDIRECT) {
  //transaction needs redirection
  $uuid = $result->getReferenceId();
    $redirectUrl = $result->getRedirectUrl();
    header('Location: '.$redirectUrl);
    exit;
}

You must redirect the user to the URL defined in redirectUrl to proceed with the transaction. Afterwards the user will be back redirected to your shop (one of the URLs you defined in the API call in successUrl, cancelUrl or errorUrl). In parallel the gateway sends a status notification to you callbackUrl with the final result.

PENDING

<?xml version="1.0" encoding="utf-8"?>
<result xmlns="https://gateway.tillpayments.com/Schema/V2/Result">
  <success>true</success>
  <referenceId>12345678901234567890</referenceId>
  <purchaseId>20170101-12345678901234567890</purchaseId>
  <returnType>PENDING</returnType>
</result>
$result = $client->debit($debit);

if ($result->getReturnType() == \PaymentGateway\Client\Transaction\Result::RETURN_TYPE_PENDING) {
  //transaction is pending
  $uuid = $result->getReferenceId();
  //wait for the postback notification for the final result
}

The transaction was accepted for processing, but is not yet completed. You will receive a status notification to the URL you defined in callbackUrl once it reaches a final state.

Depending on the payment method, this can take from seconds up to several days.

Response with Schedule

<?xml version="1.0" encoding="utf-8"?>
<result xmlns="https://gateway.tillpayments.com/Schema/V2/Result">
  <success>true</success>
  <referenceId>12345678901234567890</referenceId>
  <purchaseId>20170101-12345678901234567890</purchaseId>
  <registrationId>aab69791ddedcaeae4ae</registrationId>
  <returnType>FINISHED</returnType>
  <scheduleId>SC-7AA3-37B8-0F27-8BCA-5B3D-90DB</scheduleId>
  <scheduleStatus>ACTIVE</scheduleStatus>
  <scheduledAt>2018-07-05 16:22:06 UTC</scheduledAt>
</result>

If you have started a Schedule please store the received scheduleId for further schedule handling, the scheduleId is required for operating with the Schedule API (see Schedule API).

Postback Notifications

The Gateway sends you an asynchronous notification once a transaction reaches its final state. Per default, the format of the notification will be in the same format as your request.

A typical success notification looks like this (the element returnData can differ depending on the payment method):

<?xml version="1.0" encoding="utf-8"?>
<callback xmlns="https://gateway.tillpayments.com/Schema/V2/Callback">
  <result>OK</result>
  <referenceId>edcba123456789012345</referenceId>
  <transactionId>YOUR_TRANSACTION_ID</transactionId>
  <purchaseId>20170120-edcba123456789012345</purchaseId>
  <transactionType>DEBIT</transactionType>
  <merchantMetaData>YOUR_OPTIONAL_META_DATA</merchantMetaData>
  <amount>4.99</amount>
  <currency>USD</currency>
  <returnData type="creditcardData">
    <creditcardData>
      <type>visa</type>
      <cardHolder>Max Mustermann</cardHolder>
      <expiryMonth>10</expiryMonth>
      <expiryYear>2020</expiryYear>
      <firstSixDigits>411111</firstSixDigits>
      <lastFourDigits>1111</lastFourDigits>
      <fingerprint>ABCXYZ...</fingerprint>
      <threeDSecure>MANDATORY</threeDSecure>
      <eci>05</eci>
      <binBrand>VISA</binBrand>
      <binBank>Issuing Bank</binBank>
      <binCountry>AT</binCountry>
    </creditcardData>
  </returnData>
  <customerData>
    <identification>1111</identification>
    <firstName>John</firstName>
    <lastName>Smith</lastName>
    <billingCountry>AT</billingCountry>
    <email>[email protected]</email>
    <ipAddress>123.123.123.123</ipAddress>
  </customerData>
</callback>

This is an example for an error notification:

<?xml version="1.0" encoding="utf-8"?>
<callback xmlns="https://gateway.tillpayments.com/Schema/V2/Callback">
  <result>ERROR</result>
  <referenceId>edcba123456789012345</referenceId>
  <transactionId>YOUR_TRANSACTION_ID</transactionId>
  <purchaseId>20170120-edcba123456789012345</purchaseId>
  <transactionType>DEBIT</transactionType>
  <merchantMetaData>YOUR_OPTIONAL_META_DATA</merchantMetaData>
  <amount>4.99</amount>
  <currency>USD</currency>
  <errors>
    <error>
      <message>Card invalid</message>
      <code>2008</code>
      <adapterMessage>Invalid Card Entered</adapterMessage>
      <adapterCode>100.000.100</adapterCode>
    </error>
  </errors>
  <returnData type="creditcardData">
    <creditcardData>
      <type>visa</type>
      <country>AT</country>
      <cardHolder>Max Mustermann</cardHolder>
      <expiryMonth>10</expiryMonth>
      <expiryYear>2020</expiryYear>
      <firstSixDigits>411111</firstSixDigits>
      <lastFourDigits>1111</lastFourDigits>
    </creditcardData>
  </returnData>
  <customerData>
    <identification>1111</identification>
    <firstName>John</firstName>
    <lastName>Smith</lastName>
    <billingCountry>AT</billingCountry>
    <email>[email protected]</email>
    <ipAddress>123.123.123.123</ipAddress>
  </customerData>
</callback>

Result Codes

The result tag will either contain "OK" or "ERROR". In case of error the XML contains an errors element with further information.

<?xml version="1.0" encoding="utf-8"?>
<callback xmlns="https://gateway.tillpayments.com/Schema/V2/Callback">
  <result>OK</result>
  <referenceId>edcba123456789012345</referenceId>
  <transactionId>YOUR_TRANSACTION_ID</transactionId>
  <purchaseId>20170120-edcba123456789012345</purchaseId>
  <transactionType>DEBIT</transactionType>
  <merchantMetaData>YOUR_OPTIONAL_META_DATA</merchantMetaData>
  <amount>4.99</amount>
  <currency>USD</currency>
  <errors>
    <error>
      <message>Card declined</message>
      <code>2003</code>
      <adapterMessage>Card declined by authorisation System</adapterMessage>
      <adapterCode>301.110</adapterCode>
    </error>
  </errors>
</callback>

Data Verification

To prove the authenticity of the notification the Gateway signs every request with the same shared secret as used for signing your requests.

You should verify the signature by calculating it on your system and compare it to the given one.

The mechanism is the same as described in Signature, but instead of defining the various values (request URI, date, etc.), you must take them out of the HTTP request you received from us. You should also verify that the Date header is within a reasonable deviation of the current timestamp (e.g. 60 seconds)

Additional data

If you need additional information to process the notification for your shop order, you can use the optional field merchantMetaData, or you can provide that data as GET parameters in the callbackUrl you define.

E.g. https://www.merchant.com/notification-url?someKey=someValue&anything=else

Chargeback Notifications

If a transaction gets charged back by the customer, the Gateway will send you a notification to the URL from the original transaction (i.e. the Debit or Capture transaction).

The notification XML will then contain an element chargebackData with further information

<?xml version="1.0" encoding="utf-8"?>
<callback xmlns="https://gateway.tillpayments.com/Schema/V2/Callback">
  <result>OK</result>
  <referenceId>edcba123456789012345</referenceId>
  <transactionId>auto-generated-id</transactionId>
  <purchaseId>20170120-edcba123456789012345</purchaseId>
  <transactionType>CHARGEBACK</transactionType>
  <amount>9.99</amount>
  <currency>EUR</currency>
  <chargebackData>
    <originalReferenceId>abcdef123456123456</originalReferenceId>
    <originalTransactionId>YOUR_TRANSACTION_ID</originalTransactionId>
    <amount>9.99</amount>
    <currency>EUR</currency>
    <reason>customer_chargeback</reason>
    <chargebackDateTime>2017-02-10T04:36:09Z</chargebackDateTime>
  </chargebackData>
</callback>

You must confirm the notification in the same manner as normal status notifications with status code 200 and text "OK" in the response's payload.

Chargeback Reversal Notification

As a follow-up on chargebacks there can be a chargeback reversal. Again the Gateway will send you a notification to the URL of the original transaction.

For this kind of notification the XML contains an element chargebackReversalData with information to the original transaction and the chargeback transaction

<?xml version="1.0" encoding="utf-8"?>
<callback xmlns="https://gateway.tillpayments.com/Schema/V2/Callback">
  <result>OK</result>
  <referenceId>b5c36138ada44ca09d45</referenceId>
  <transactionId>auto-generated-id</transactionId>
  <purchaseId>20170120-edcba123456789012345</purchaseId>
  <transactionType>CHARGEBACK-REVERSAL</transactionType>
  <amount>9.99</amount>
  <currency>EUR</currency>
  <chargebackReversalData>
    <originalReferenceId>abcdef123456123456</originalReferenceId>
    <originalTransactionId>YOUR_TRANSACTION_ID</originalTransactionId>
    <chargebackReferenceId>edcba123456789012345</chargebackReferenceId>
    <amount>9.99</amount>
    <currency>EUR</currency>
    <reason>dispute_won</reason>
    <reversalDateTime>2017-03-26T11:27:15Z</reversalDateTime>
  </chargebackReversalData>
</callback>

Transaction Data

Note: For conditional fields, please refer to the corresponding adapter specific documentation.

Field Required Description
Root-level
username true API Username given to you
password true API Password given to you, hashed with SHA-1 in 10 rounds (see Password Hashing below)
transaction tag true it must be one of the following types:
debit, preauthorize, capture, void, refund, register, deregister, payout
Transaction-level
transactionId true your transaction id, must be unique
additionalId1 false any additional ID if required by adapter
additionalId2 false any additional ID if required by adapter
customer false customer element (see below)
extraData false extra parameters if required by adapter
merchantMetaData false Can be filled with any string you want, with a maximum length of 255 characters. The value of that field has no influence at all on the transaction processing, but will be just returned to you in any postback notification, and will also be included in data exports. Hint: If you want to put in different types of information, we would recommend to separate them by a character, which would not occur in the data value itself, e.g. a pipe character. Example: "anyValue1|anotherValue2"
referenceTransactionId conditionally UUID of reference transaction (for recurring debits, refunds, capture/voids, deregister)
referenceCustomerId false reference customer ID if required by adapter
referenceId2 false any additional ID if required by adapter
referenceId3 false any additional ID if required by adapter
referenceId4 false any additional ID if required by adapter
amount conditionally Amount of transaction, decimals separated by a "." (dot)
currency conditionally 3-letter currency code for amount
description conditionally Transaction subject
successUrl conditionally the URL to your shop, to which the user gets redirected, after the payment succeeded (or the payment status is yet unknown)
cancelUrl conditionally the URL to your shop, to which the user gets redirected, after the payment was cancelled by the user
errorUrl conditionally the URL to your shop, to which the user gets redirected, after the payment failed
callbackUrl true the URL to your endpoint, to which the Gateway sends the status notification
withRegister false this flag enables storing of the customer's payment instrument for recurring transactions
transactionIndicator false this marks the type of evt. recurring or card-on-file transactions (refer to Recurring transactions )

Customer Data

The customer element can be one of two different customer types:

For details, refer to the Transaction XML definition

Field Description
Customer-level
identification Unique customer identification (i.e. User ID, up to 36 characters)
firstName First name of customer
lastName Last name of customer
birthDate Birth date
gender either M for male or F for female
billingAddress1 Street address line 1
billingAddress2 Street address line 2
billingCity City
billingPostcode Postal code / ZIP code
billingState State
billingCountry 2-letter country code
billingPhone Phone number
shippingFirstName Shipping address first name
shippingLastName Shipping address last name
shippingCompany Shipping address company name
shippingAddress1 Street address line 1
shippingAddress2 Street address line 2
shippingCity City
shippingPostcode Postal code / ZIP code
shippingState State
shippingCountry 2-letter country code
shippingPhone Phone number
company Company name of the customer
email Customer's E-Mail address
emailVerified Flag if you verified the email address (for example via verification email)
ipAddress IP address of the customer
extraData key/value array with additional customer data (if required by the connector)
nationalId The national ID (e.g. social insurance number) for a customer
IbanCustomer
iban IBAN bank account number
bic BIC bank identifier code
mandateId SEPA mandate identification
mandateDate Date of the SEPA mandate

3D-Secure 2.0 Data

As explained in 3D Secure 2.0 Authentication you should provide as many data as you have to apply for the 3D Secure 2.0 frictionless flow.

Any data field listed shall be provided within an extraData element.

Field & Description
3ds:channel

Indicates the type of channel interface being used to initiate the transaction
01 -> App-based
02 -> Browser
03 -> 3DS Requestor Initiated
3ds:authenticationIndicator

Indicates the type of Authentication request. This data element provides additional information to the ACS to determine the best approach for handling an authentication request.
01 -> Payment transaction
02 -> Recurring transaction
03 -> Installment transaction
04 -> Add card
05 -> Maintain card
06 -> Cardholder verification as part of EMV token ID&V
3ds:cardholderAuthenticationMethod

Mechanism used by the Cardholder to authenticate to the 3DS Requestor.
01 -> No 3DS Requestor authentication occurred (i.e. cardholder "logged in" as guest)
02 -> Login to the cardholder account at the 3DS Requestor system using 3DS Requestor's own credentials
03 -> Login to the cardholder account at the 3DS Requestor system using federated ID
04 -> Login to the cardholder account at the 3DS Requestor system using issuer credentials
05 -> Login to the cardholder account at the 3DS Requestor system using third-party authentication
06 -> Login to the cardholder account at the 3DS Requestor system using FIDO Authenticator
3ds:cardholderAuthenticationDateTime

Date and time in UTC of the cardholder authentication. Format: YYYY-MM-DD HH:mm
Example: 2019-05-12 18:34
3ds:cardHolderAuthenticationData

Data that documents and supports a specific authentication process. In the current version of the specification, this data element is not defined in detail, however the intention is that for each 3DS Requestor Authentication Method, this field carry data that the ACS can use to verify the authentication process.
3ds:challengeIndicator

Indicates whether a challenge is requested for this transaction. For example: For 01-PA, a 3DS Requestor may have concerns about the transaction, and request a challenge.
01 -> No preference
02 -> No challenge requested
03 -> Challenge requested: 3DS Requestor Preference
04 -> Challenge requested: Mandate
3ds:priorReference

This data element provides additional information to the ACS to determine the best approach for handling a request. The field is limited to 36 characters containing ACS Transaction ID for a prior authenticated transaction (for example, the first recurring transaction that was authenticated with the cardholder).
3ds:priorAuthenticationMethod

Mechanism used by the Cardholder to previously authenticate to the 3DS Requestor.
01 -> Frictionless authentication occurred by ACS
02 -> Cardholder challenge occurred by ACS
03 -> AVS verified
04 -> Other issuer methods
3ds:priorAuthenticationDateTime

Date and time in UTC of the prior authentication. Format: YYYY-MM-DD HH:mm
Example: 2019-05-12 18:34
3ds:priorAuthenticationData

Data that documents and supports a specfic authentication porcess. In the current version of the specification this data element is not defined in detail, however the intention is that for each 3DS Requestor Authentication Method, this field carry data that the ACS can use to verify the authentication process. In future versions of the application, these details are expected to be included. Field is limited to maximum 2048 characters.
3ds:cardholderAccountType

Indicates the type of account. For example, for a multi-account card product.
01 -> Not applicable
02 -> Credit
03 -> Debit
04 -> JCB specific value for Prepaid
3ds:cardholderAccountAgeIndicator

Length of time that the cardholder has had the account with the 3DS Requestor.
01 -> No account (guest check-out)
02 -> During this transaction
03 -> Less than 30 days
04 -> 30 - 60 days
05 -> More than 60 days
3ds:cardholderAccountDate

Date that the cardholder opened the account with the 3DS Requestor. Format: YYYY-MM-DD
Example: 2019-05-12
3ds:cardholderAccountChangeIndicator

Length of time since the cardholder’s account information with the 3DS Requestor waslast changed. Includes Billing or Shipping address, new payment account, or new user(s) added.
01 -> Changed during this transaction
02 -> Less than 30 days
03 -> 30 - 60 days
04 -> More than 60 days
3ds:cardholderAccountLastChange

Date that the cardholder’s account with the 3DS Requestor was last changed. Including Billing or Shipping address, new payment account, or new user(s) added. Format: YYYY-MM-DD
Example: 2019-05-12
3ds:cardholderAccountPasswordChangeIndicator

Length of time since the cardholder’s account with the 3DS Requestor had a password change or account reset.
01 -> No change
02 -> Changed during this transaction
03 -> Less than 30 days
04 -> 30 - 60 days
05 -> More than 60 days
3ds:cardholderAccountLastPasswordChange

Date that cardholder’s account with the 3DS Requestor had a password change or account reset. Format: YYYY-MM-DD
Example: 2019-05-12
3ds:shippingAddressUsageIndicator

Indicates when the shipping address used for this transaction was first used with the 3DS Requestor.
01 -> This transaction
02 -> Less than 30 days
03 -> 30 - 60 days
04 -> More than 60 days.
3ds:shippingAddressFirstUsage

Date when the shipping address used for this transaction was first used with the 3DS Requestor. Format: YYYY-MM-DD
Example: 2019-05-12
3ds:transactionActivityDay

Number of transactions (successful and abandoned) for this cardholder account with the 3DS Requestor across all payment accounts in the previous 24 hours.
3ds:transactionActivityYear

Number of transactions (successful and abandoned) for this cardholder account with the 3DS Requestor across all payment accounts in the previous year.
3ds:addCardAttemptsDay

Number of Add Card attempts in the last 24 hours.
3ds:purchaseCountSixMonths

Number of purchases with this cardholder account during the previous six months.
3ds:suspiciousAccountActivityIndicator

Indicates whether the 3DS Requestor has experienced suspicious activity (including previous fraud) on the cardholder account.
01 -> No suspicious activity has been observed
02 -> Suspicious activity has been observed
3ds:shippingNameEqualIndicator

Indicates if the Cardholder Name on the account is identical to the shipping Name used for this transaction.
01 -> Account Name identical to shipping Name
02 -> Account Name different than shipping Name
3ds:paymentAccountAgeIndicator

Indicates the length of time that the payment account was enrolled in the cardholder’s account with the 3DS Requestor.
01 -> No account (guest check-out)
02 -> During this transaction
03 -> Less than 30 days
04 -> 30 - 60 days
05 -> More than 60 days
3ds:paymentAccountAgeDate

Date that the payment account was enrolled in the cardholder’s account with the 3DS Requestor. Format: YYYY-MM-DD
Example: 2019-05-12
3ds:billingAddressLine3

Line 3 of customer's billing address
3ds:shippingAddressLine3

Line 3 of customer's shipping address
3ds:billingShippingAddressMatch

Indicates whether the Cardholder Shipping Address and Cardholder Billing Address are the same.
Y -> Shipping Address matches Billing Address
N -> Shipping Address does not match Billing Address
3ds:homePhoneCountryPrefix

Country Code of the home phone, limited to 1-3 characters
3ds:homePhoneNumber

subscriber section of the number, limited to maximum 15 characters.
3ds:mobilePhoneCountryPrefix

Country Code of the mobile phone, limited to 1-3 characters
3ds:mobilePhoneNumber

subscriber section of the number, limited to maximum 15 characters.
3ds:workPhoneCountryPrefix

Country Code of the work phone, limited to 1-3 characters
3ds:workPhoneNumber

subscriber section of the number, limited to maximum 15 characters.
3ds:purchaseInstalData

Indicates the maximum number of authorisations permitted for instalment payments. The field is limited to maximum 3 characters and value shall be greater than 1. The fields is required if the Merchant and Cardholder have agreed to installment payments, i.e. if 3DS Requestor Authentication Indicator = 03. Omitted if not an installment payment authentication.
3ds:shipIndicator

Indicates shipping method chosen for the transaction. Merchants must choose the Shipping Indicator code that most accurately describes the cardholder's specific transaction. If one or more items are included in the sale, use the Shipping Indicator code for the physical goods, or if all digital goods, use the code that describes the most expensive item.
01 -> Ship to cardholder's billing address
02 -> Ship to another verified address on file with merchant
03 -> Ship to address that is different than the cardholder's billing address
04 -> "Ship to Store" / Pick-up at local store (Store address shall be populated in shipping address fields)
05 -> Digital goods (includes online services, electronic gift cards and redemption codes)
06 -> Travel and Event tickets, not shipped
07 -> Other (for example, Gaming, digital services not shipped, emedia subscriptions, etc.)
3ds:deliveryTimeframe

Indicates the merchandise delivery timeframe.
01 -> Electronic Delivery
02 -> Same day shipping
03 -> Overnight shipping
04 -> Two-day or more shipping
3ds:deliveryEmailAddress

For electronic delivery, the email address to which the merchandise was delivered.
3ds:reorderItemsIndicator

Indicates whether the cardholder is reordering previously purchased merchandise.
01 -> First time ordered
02 -> Reordered
3ds:preOrderPurchaseIndicator

Indicates whether Cardholder is placing an order for merchandise with a future availability or release date.
01 -> Merchandise available
02 -> Future availability
3ds:preOrderDate

For a pre-ordered purchase, the expected date that the merchandise will be available.
Format: YYYY-MM-DD
3ds:giftCardAmount

For prepaid or gift card purchase, the purchase amount total of prepaid or gift card(s) in major units (for example, USD 123.45 is 123).
3ds:giftCardCurrency

For prepaid or gift card purchase, the currency code of the card
3ds:giftCardCount

For prepaid or gift card purchase, total count of individual prepaid or gift cards/codes purchased. Field is limited to 2 characters.
3ds:purchaseDate

Date and time of the purchase, expressed in UTC. Format: YYYY-MM-DD HH:mm:ss
**Note: if omitted we put in today's date
3ds:recurringExpiry

Date after which no further authorizations shall be performed. This field is required for 01-PA and for 02-NPA, if 3DS Requestor Authentication Indicator = 02 or 03.
Format: YYYY-MM-DD
3ds:recurringFrequency

Indicates the minimum number of days between authorizations. The field is limited to maximum 4 characters. This field is required if 3DS Requestor Authentication Indicator = 02 or 03.
3ds:transType

Identifies the type of transaction being authenticated. The values are derived from ISO 8583.
01 -> Goods / Service purchase
03 -> Check Acceptance
10 -> Account Funding
11 -> Quasi-Cash Transaction
28 -> Prepaid activation and Loan
3ds:exemptionIndicator

Requests an SCA exemption for this transaction. Possible values are:
01 -> Low Value Transaction (amount under 30 EUR)
02 -> Low Risk Transaction
03 -> Whitelisted transaction, merchant is added as "Trusted Beneficiary" by cardholder
04 -> Secure Corporate Payment
05 -> Recurring or Merchant-initiated transaction
06 -> Mail or Telephone Order
07 -> Anonymous payment card
3ds:browserChallengeWindowSize

Dimensions of the challenge window that has been displayed to the Cardholder. The ACS shall reply with content that is formatted to appropriately render in this window to provide the best possible user experience.
01 -> 250 x 400
02 -> 390 x 400
03 -> 500 x 600
04 -> 600 x 400
05 -> Full screen

3D-Secure 2.0 Device Data

For 3DS v2, the device data below are mandatory. Transaction will not succeed if either all browser or all SDK parameters are provided.

Browser Data

The following fields are filled automatically by the Gateway if you are using hosted payment pages or payment.js integration. For any other integration flow you will need to provide them:

Key & Description
3ds:browserAcceptHeader

Exact content of the HTTP accept headers as sent to the 3DS Requestor from the Cardholder's browser
3ds:browserIpAddress

IP address of the browser as returned by the HTTP headers to the 3DS Requestor.
- IPv4 address is represented in the dotted decimal format of 4 sets of decimal numbers separated by dots. The decimal number in each and every set is in the range 0 - 255. Example: 1.12.123.255
- IPv6 address is represented as eight groups of four hexadecimal digits, each group representing 16 bits (two octets). The groups are separated by colons (:). Example: 2011:0db8:85a3:0101:0101:8a2e:0370:7334
3ds:browserJavaEnabled

Boolean that represents the ability of the cardholder browser to execute Java. Value is returned from the navigator.javaEnabled property.
3ds:browserLanguage

Value representing the browser language as defined in IETF BCP47. The value is limited to 1-8 characters. Value is returned from navigator.language property.
3ds:browserColorDepth

Value representing the bit depth of the colour palette for displaying images, in bits per pixel. Obtained from Cardholder browser using the screen.colorDepth property.
1 -> 1 bit
4 -> 4 bits
8 -> 8 bits
15 -> 15 bits
16 -> 16 bits
24 -> 24 bits
32 -> 32 bits
48 -> 48 bits
3ds:browserScreenHeight

Total height of the Cardholder's screen in pixels. Value is returned from the screen.height property.
3ds:browserScreenWidth

Total width of the Cardholder's screen in pixels. Value is returned from the screen.width property.
3ds:browserTimezone

Time difference between UTC time and the Cardholder browser local time, in minutes. The field is limited to 1-5 characters where the value is returned from the getTimezoneOffset() method.
3ds:browserUserAgent

Exact content of the HTTP user-agent header. The field is limited to maximum 2048 characters.

SDK Data

Key & Description
3ds:sdkInterface

Specifies all of the SDK Interface types that the device supports for displaying specific challenge user interfaces within the SDK. Accepted values are:
01 -> Native
02 -> HTML
03 -> Both
3ds:sdkUiType

Contains a comma-separated list of all UI types that the device supports for displaying specific challenge user interfaces within the SDK. Accepted values for each UI type are:
01 -> Text
02 -> Single select
03 -> Multi select
04 -> OOB
05 -> Html Other (valid only for HTML UI)
E.g. 01,02,05
3ds:sdkAppID

Universally unique ID created upon all installations and updates of the 3DS Requestor App on a Customer Device.
3ds:sdkEncData

JWE Object as defined 3DS Specs Section 6.2.2.1 containing data encrypted by the SDK for the DS to decrypt.
3ds:sdkEphemPubKey

Public key component of the ephemeral key pair generated by the 3DS SDK and used to establish session keys between the 3DS SDK and ACS
The value should be a JSON string containing the keys kty, crv, x, y, e.g. {"kty":"EC","crv":"P-256","x":"...","y":"..."}
3ds:sdkMaxTimeout

Indicates the maximum amount of time (in minutes) for all exchanges. The field shall have value greater than or equal to 05.
3ds:sdkReferenceNumber

Identifies the vendor and version of the 3DS SDK that is integrated in a 3DS Requestor App, assigned by EMVCo when the 3DS SDK is approved. The field is limited to 32 characters.
3ds:sdkTransID

Universally unique transaction identifier assigned by the 3DS SDK to identify a single transaction.

Status Request

<!-- Status Request with the UUID -->
<?xml version="1.0" encoding="utf-8"?>
<status xmlns="https://gateway.tillpayments.com/Schema/V2/Status">
  <username>YOUR_USERNAME</username>
  <password>SHA1 HASHED PASSWORD</password>
  <transactionUuid>aa85fdb3c5f2048bd77f</transactionUuid>
</status>

<!-- Status Request with the merchantTransactionId -->
<?xml version="1.0" encoding="utf-8"?>
<status xmlns="https://gateway.tillpayments.com/Schema/V2/Status">
  <username>YOUR_USERNAME</username>
  <password>SHA1 HASHED PASSWORD</password>
  <merchantTransactionId>20181127103341</merchantTransactionId>
</status>

<!-- Status Result -->
<?xml version="1.0" encoding="utf-8"?>
<statusResult xmlns="https://gateway.tillpayments.com/Schema/V2/StatusResult">
  <operationSuccess>true</operationSuccess>
  <transactionStatus>SUCCESS</transactionStatus>
  <transactionUuid>aa85fdb3c5f2048bd77f</transactionUuid>
  <merchantTransactionId>20181127103341</merchantTransactionId>
  <purchaseId>20181127-aa85fdb3c5f2048bd77f</purchaseId>
  <transactionType>DEBIT</transactionType>
  <paymentMethod>Bitcoin</paymentMethod>
  <amount>9.99</amount>
  <currency>EUR</currency>
  <customerData>
    <firstName>Max</firstName>
    <lastName>Mustermann</lastName>
    <company>Test Company</company>
    <email>[email protected]</email>
    <emailVerified>false</emailVerified>
    <ipAddress>127.0.0.1</ipAddress>
  </customerData>
</statusResult>

<!-- Status Result with Error -->
<?xml version="1.0" encoding="utf-8"?>
<statusResult xmlns="https://gateway.tillpayments.com/Schema/V2/StatusResult">
  <operationSuccess>false</operationSuccess>
  <errors>
    <error>
      <message>Transaction not found</message>
      <code>8001</code>
    </error>
  </errors>
</statusResult>
$username = 'Your Username';
$password = 'Your password';
$apiKey = 'Connector API Key';
$sharedSecret = 'Connector Shared Secret';

$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);
$statusRequestData = new \PaymentGateway\Client\StatusApi\StatusRequestData();

// use either the UUID or your merchantTransactionId but not both
// $statusRequestData->setTransactionUuid($transactionUuid);
$statusRequestData->setMerchantTransactionId($merchantTransactionId);

$statusResult = $client->sendStatusRequest($statusRequestData);

The Status Request expects (similar to the Transaction Request) an HTTP POST request with XML Payload and the Authentication header (see Signing Requests below).

The destination URL is: https://gateway.tillpayments.com/status

In addition to the Generic Error Codes please consider the Specific Error Codes for the Status API Call.

Scheduler Request

The Schedule Gateway API expects (similar to the Transaction API) an HTTP POST request with XML Payload and an Authentication header containing a Hash HMAC signature (see Signing Requests below).

The destination URL is: https://gateway.tillpayments.com/schedule

Please read the general Scheduler documentation first, to get an understanding of the different actions and states.

In addition to the Generic Error Codes please consider the Specific Error Codes for the Scheduler API Call.

startSchedule

<!-- Request -->
<?xml version="1.0" encoding="utf-8"?>
<schedule xmlns="https://gateway.tillpayments.com/Schema/V2/Schedule">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <startSchedule>
    <registrationId>theReferenceTransactionIdFromYourRegister</registrationId>
    <amount>4.99</amount>
    <currency>EUR</currency>
    <periodLength>1</periodLength>
    <periodUnit>MONTH</periodUnit>
    <startDateTime>2018-06-05 14:26:11 UTC</startDateTime>
  </startSchedule>
</schedule>
<!-- Response -->
<?xml version="1.0" encoding="utf-8"?>
<scheduleResult xmlns="https://gateway.tillpayments.com/Schema/V2/ScheduleResult">
  <operationSuccess>true</operationSuccess>
  <scheduleId>SC-B747-8636-D03F-1DB2-18F8-A4F1</scheduleId>
  <oldStatus>NON-EXISTING</oldStatus>
  <newStatus>ACTIVE</newStatus>
  <scheduledAt>2019-07-05 16:11:21 UTC</scheduledAt>
</scheduleResult>
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$scheduleData = new  \PaymentGateway\Client\Schedule\ScheduleData();

$scheduleData->setAmount(5.99);
$scheduleData->setCurrency('EUR');
$scheduleData->setPeriodLength(1);
$scheduleData->setPeriodUnit('MONTH');
$startDateTime = new \DateTime('+ 1 month');
$scheduleData->setStartDateTime($startDateTime);

$scheduleResult = $client->startSchedule($scheduleData);

if ($scheduleResult->getOperationSuccess() && $scheduleResult->getNewStatus() == ScheduleResult::STATUS_ACTIVE) {
    //operation was successful
    $scheduleId = $scheduleResult->getScheduleId();
} else {
    $errors = $scheduleResult->getErrors();
}

Starting a schedule via Schedule API requires the registrationId of an existing transaction from type Register (or Debit-with-register or Preauthorize-with-register).

If the customer is not already registered, please use the Transaction Request API, where you can start a schedule on the fly (see Debit with starting a schedule).

updateSchedule

<!-- Request -->
<?xml version="1.0" encoding="utf-8"?>
<schedule xmlns="https://gateway.tillpayments.com/Schema/V2/Schedule">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <updateSchedule>
    <scheduleId>theScheduleIdYouHaveReceivedInTheStartScheduleResult</scheduleId>
    <registrationId>theReferenceTransactionIdFromYourRegister</registrationId>
    <amount>4.99</amount>
    <currency>EUR</currency>
    <periodLength>1</periodLength>
    <periodUnit>MONTH</periodUnit>
    <startDateTime>2018-06-05 14:26:11 UTC</startDateTime>
  </updateSchedule>
</schedule>
<!-- Response -->
<?xml version="1.0" encoding="utf-8"?>
<scheduleResult xmlns="https://gateway.tillpayments.com/Schema/V2/ScheduleResult">
  <operationSuccess>true</operationSuccess>
  <scheduleId>SC-B747-8636-D03F-1DB2-18F8-A4F1</scheduleId>
  <oldStatus>ACTIVE</oldStatus>
  <newStatus>ACTIVE</newStatus>
  <scheduledAt>2019-07-05 16:11:21 UTC</scheduledAt>
</scheduleResult>
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$scheduleData = new  \PaymentGateway\Client\Schedule\ScheduleData();

$scheduleData->setScheduleId($scheduleId); // the scheduleId you have received in the Result of the startSchedule - Call
$scheduleData->setAmount(5.99);
$scheduleData->setCurrency('EUR');
$scheduleData->setPeriodLength(1);
$scheduleData->setPeriodUnit('MONTH');
$startDateTime = new \DateTime('+ 1 month');
$scheduleData->setStartDateTime($startDateTime);

$scheduleResult = $client->startSchedule($scheduleData);

if ($scheduleResult->getOperationSuccess() && $scheduleResult->getNewStatus() == ScheduleResult::STATUS_ACTIVE) {
    //operation was successful
    $scheduleId = $scheduleResult->getScheduleId();
} else {
    $errors = $scheduleResult->getErrors();
}

You can update the information of a schedule.

Note: Only the fields you submit will be updated. So if you're not sending e.g. amount and currency, the amount will stay the same, only the next due date and the interval will be changed.

showSchedule

<!-- Request -->
<?xml version="1.0" encoding="utf-8"?>
<schedule xmlns="https://gateway.tillpayments.com/Schema/V2/Schedule">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <showSchedule>
    <scheduleId>theScheduleIdYouHaveReceivedInTheStartScheduleResult</scheduleId>
  </showSchedule>
</schedule>
<!-- Response -->
<?xml version="1.0" encoding="utf-8"?>
<scheduleResult xmlns="https://gateway.tillpayments.com/Schema/V2/ScheduleResult">
  <operationSuccess>true</operationSuccess>
  <scheduleId>theScheduleIdYouHaveReceivedInTheStartScheduleResult</scheduleId>
  <oldStatus>ACTIVE</oldStatus>
  <newStatus>ACTIVE</newStatus>
  <scheduledAt>2019-07-05 16:11:21 UTC</scheduledAt>
</scheduleResult>
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$scheduleData = new  \PaymentGateway\Client\Schedule\ScheduleData();

$scheduleData->setScheduleId($scheduleId); // the scheduleId you have received in the Result of the startSchedule - Call

$scheduleResult = $client->showSchedule($scheduleData);

if ($scheduleResult->getOperationSuccess()) {
    $currentStatus = $scheduleResult->getNewStatus();
} else {
    $errors = $scheduleResult->getErrors();
}

You can retrieve status information about the requested Schedule.

pauseSchedule

<!-- Request -->
<?xml version="1.0" encoding="utf-8"?>
<schedule xmlns="https://gateway.tillpayments.com/Schema/V2/Schedule">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <pauseSchedule>
    <scheduleId>theScheduleIdYouHaveReceivedInTheStartScheduleResult</scheduleId>
  </pauseSchedule>
</schedule>
<!-- Response -->
<?xml version="1.0" encoding="utf-8"?>
<scheduleResult xmlns="https://gateway.tillpayments.com/Schema/V2/ScheduleResult">
  <operationSuccess>true</operationSuccess>
  <scheduleId>theScheduleIdYouHaveReceivedInTheStartScheduleResult</scheduleId>
  <oldStatus>ACTIVE</oldStatus>
  <newStatus>PAUSED</newStatus>
</scheduleResult>
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$scheduleData = new  \PaymentGateway\Client\Schedule\ScheduleData();

$scheduleData->setScheduleId($scheduleId); // the scheduleId you have received in the Result of the startSchedule - Call

$scheduleResult = $client->pauseSchedule($scheduleData);

if ($scheduleResult->getOperationSuccess() && $scheduleResult->getNewStatus() == ScheduleResult::STATUS_PAUSED) {
    //operation was successful
} else {
    $errors = $scheduleResult->getErrors();
}

You can pause an active Schedule. A paused Schedule does not perform payments until you continue the schedule.

continueSchedule

<!-- Request -->
<?xml version="1.0" encoding="utf-8"?>
<schedule xmlns="https://gateway.tillpayments.com/Schema/V2/Schedule">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <continueSchedule>
    <scheduleId>theScheduleIdYouHaveReceivedInTheStartScheduleResult</scheduleId>
    <continueDateTime>2019-06-05 14:26:11 UTC</continueDateTime>
  </continueSchedule>
</schedule>
<!-- Response -->
<?xml version="1.0" encoding="utf-8"?>
<scheduleResult xmlns="https://gateway.tillpayments.com/Schema/V2/ScheduleResult">
  <operationSuccess>true</operationSuccess>
  <scheduleId>theScheduleIdYouHaveReceivedInTheStartScheduleResult</scheduleId>
  <oldStatus>PAUSED</oldStatus>
  <newStatus>ACTIVE</newStatus>
  <scheduledAt>2019-07-05 16:11:21 UTC</scheduledAt>
</scheduleResult>
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$scheduleData = new  \PaymentGateway\Client\Schedule\ScheduleData();

$scheduleData->setScheduleId($scheduleId); // the scheduleId you have received in the Result of the startSchedule - Call
$continueDateTime = new \DateTime('+ 10 days');
$scheduleData->setContinueDateTime($continueDateTime);

$scheduleResult = $client->continueSchedule($scheduleData);

if ($scheduleResult->getOperationSuccess() && $scheduleResult->getNewStatus() == ScheduleResult::STATUS_ACTIVE) {
    //operation was successful
} else {
    $errors = $scheduleResult->getErrors();
}

You can continue a paused Schedule.

cancelSchedule

<!-- Request -->
<?xml version="1.0" encoding="utf-8"?>
<schedule xmlns="https://gateway.tillpayments.com/Schema/V2/Schedule">
  <username>API_USER</username>
  <password>5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8</password>
  <cancelSchedule>
    <scheduleId>theScheduleIdYouHaveReceivedInTheStartScheduleResult</scheduleId>
  </cancelSchedule>
</schedule>
<!-- Response -->
<?xml version="1.0" encoding="utf-8"?>
<scheduleResult xmlns="https://gateway.tillpayments.com/Schema/V2/ScheduleResult">
  <operationSuccess>true</operationSuccess>
  <scheduleId>theScheduleIdYouHaveReceivedInTheStartScheduleResult</scheduleId>
  <oldStatus>ACTIVE</oldStatus>
  <newStatus>CANCELLED</newStatus>
</scheduleResult>
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$scheduleData = new  \PaymentGateway\Client\Schedule\ScheduleData();

$scheduleData->setScheduleId($scheduleId); // the scheduleId you have received in the Result of the startSchedule - Call

$scheduleResult = $client->cancelSchedule($scheduleData);

if ($scheduleResult->getOperationSuccess() && $scheduleResult->getNewStatus() == ScheduleResult::STATUS_CANCELLED) {
    //operation was successful
} else {
    $errors = $scheduleResult->getErrors();
}

You can cancel a Schedule.

Options Request

Some adapters can provide additional information for your payment integration, for example a bank list for EPS transactions. This allows you to show the bank selection already on your shop checkout site.

See the adapter specific page for additional information about available Options request methods.

Request

An Options request is generated analogue to a normal transaction request, i.e. it needs the same credentials and request signing method.

The destination URL is: https://gateway.tillpayments.com/options

<?xml version="1.0" encoding="utf-8"?>
<options xmlns="https://gateway.tillpayments.com/Schema/V2/Options">
  <username>API_USERNAME</username>
  <password>API_PASSWORD (SHA1 HASHED)</password>
  <request>
    <identifier>epsBankList</identifier>
  </request>
</options>
$username = 'Your Username';
$password = 'Your password';
$apiKey = 'Connector API Key';
$sharedSecret = 'Connector Shared Secret';

$client = new \PaymentGateway\Client\Client($username, $password, $apiKey, $sharedSecret);

$bankList = $client->getOptions('epsBankList');

Response

If successful the response contains a list of parameter elements with key/value pairs.

<?xml version="1.0" encoding="utf-8"?>
<options xmlns="https://gateway.tillpayments.com/Schema/V2/Options">
  <response>
    <success>true</success>
    <parameter name="HAABAT2KXXX">Austrian Anadi Bank AG</parameter>
    <parameter name="VRBKAT21XXX">VR-Bank Braunau</parameter>
    <parameter name="VKBLAT2LXXX">Volkskreditbank AG</parameter>
    <parameter name="SPADATW1XXX">Sparda Bank Wien</parameter>
    <!-- ... -->
  </response>
</options>
$bankList = $client->getOptions('epsBankList');
print_r($bankList);
/*
  Array
  (
    [HAABAT2KXXX] => Austrian Anadi Bank AG
    [VRBKAT21XXX] => VR-Bank Braunau
    [VKBLAT2LXXX] => Volkskreditbank AG
    [SPADATW1XXX] => Sparda Bank Wien
    ...
  )
*/

Authentication (Password Hashing)

Within the transaction request XML you pass username and password given by your integration engineer.

The plaintext password must be hashed with SHA1 hashing algorithm. The result shall be passed in lower case letters.

$password = 'myPassword';
$password = sha1($password);
var pass = "myPassword";
var sha1 = SHA1.Create();
var hash = sha1.ComputeHash(System.Text.Encoding.ASCII.GetBytes(pass));
pass = this.ByteToString(hash).ToLower(); //see function below

protected string ByteToString(byte[] buff)
{
  StringBuilder sb = new StringBuilder();
  for (int i = 0; i < buff.Length; i++)
  {
    sb.Append(buff[i].ToString("X2"));
  }
  return sb.ToString();
}
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

String password = 'myPassword';

MessageDigest md;
try {
  md = MessageDigest.getInstance("SHA-1");
} catch( NoSuchAlgorithmException e ) {
  // should never happen since MessageDigest doc says SHA-1 must be on every JVM
  throw new RuntimeException("couldn't get SHA-1 digest", e);
}
byte[] digest = password.getBytes(StandardCharsets.UTF_8);
md.reset();
digest = Hex.hex(md.digest(digest)).getBytes(StandardCharsets.UTF_8);

password = new String(digest, StandardCharsets.UTF_8);

Signing Requests

Generating the Signature

Every request to the Transaction API must be signed with your shared secret.

The signature is generated via Hash HMAC method, using SHA2-512 as hashing algorithm and is expected to be BASE64 encoded.

$method = 'POST';
$xml = '...'; //see Transaction Request chapter
$contentType = 'text/xml; charset=utf-8';
$date = new \DateTime('now', new \DateTimeZone('UTC'));
$timestamp = $date->format('D, d M Y H:i:s T');
$additionals = '';
$requestUri = '/transaction';

$signatureMessage = join("\n", [$method, hash("sha512", $xml), $contentType, $timestamp, $additionals, $requestUri]);

$digest = hash_hmac('sha512', $signatureMessage, 'THE_SHARED_SECRET', true);
$signature = base64_encode($digest);
var sharedSecret = "SHARED_SECRET";
var method = "POST";
var bodySHA512 = MakeSHA512Hash(transactionXml);
var contentType = "text/xml; charset=utf-8";
var date = new DateTime();
var timestamp = date.ToUniversalTime().ToString("r");
var additionals = "";
var requestUri = "/transaction";

var signatureMessage = method + "\n" + bodySHA512 + "\n" + contentType + "\n" + timestamp + "\n" + additionals + "\n" + requestUri;

var hmacSha512 = new HMACSHA512(Encoding.UTF8.GetBytes(sharedSecret));
var hash = hmacSha512.ComputeHash(Encoding.UTF8.GetBytes(signatureMessage));

var signature = System.Convert.ToBase64String(hash); //this is what we need now

public string MakeSHA512Hash(string content) {
  SHA512 sha512 = new SHA512Managed();
  byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
  byte[] hash = sha512.ComputeHash(inputBytes);

  StringBuilder sb = new StringBuilder();
  for (int i = 0; i < hash.Length; i++) {
    sb.Append(hash[i].ToString("X2"));
  }
  return sb.ToString();
}
// No Java example yet

The signature message is built by concatenating the following data with a line break \n

Afterwards you build the HMAC digest with SHA512 of this message with the shared secret as key. The digest should be generated in binary (not hexadecimal) and then base64 encoded.

Passing the Signature

curl \
-d "PUT_XML_HERE" \
-H "Authorization: Gateway THE_API_KEY:Signature" \
-H "Content-Type: text/xml" \
"https://gateway.tillpayments.com/transaction"
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
  'Authorization: Gateway THE_API_KEY:'.$signature,
  'Date: '.$timestamp, //from above
  'Content-Type: '.$contentType
);
var apiKey = 'YOUR_API_KEY';
var request = (HttpWebRequest)WebRequest.Create("https://gateway.tillpayments.com/transaction");

//values from above
request.Method = method;
request.ContentType = contentType;
request.ContentLength = transactionXml.Length;

request.Date = now;
request.Headers.Add("Authorization: Gateway " + apiKey + ":" + signature);
// No Java example yet

The generated signature must be passed in the request header Authorization, alongside with the application name ("Gateway") and your API key for the desired connector.

E.g.: Authorization: Gateway API_KEY:generatedSignature

(Replace "API_KEY" and "generatedSignature" with the appropriate values)

Now you can send the request.

Signature Testing Tool

Use this tool to verify the correctness of your signature generation.

Signature parameters
API-Key
Shared Secret
Method
Content
Content-Type
Timestamp (format)
Endpoint
Signature output
Expected -Hash of payload
Method
Content-Type
Timestamp
Request-URI
Hash HMAC Input (based on your request)
Do note the line breaks!
Expected signature
= data hashed using HMAC (SHA512), and the resulting binary encoded using Base64
Expected headers

External Risk Scripts

Kount

<?xml version="1.0" encoding="utf-8"?>
<transaction xmlns="https://gateway.tillpayments.com/Schema/V2/Transaction">
  <username>YOUR_USERNAME</username>
  <password>SHA1 HASHED PASSWORD</password>
  <debit>
    <transactionId>Your Transaction ID</transactionId>
    <customer>
      <identification>Customer ID</identification>
      <firstName>Prename</firstName>
      <lastName>Surname</lastName>
      <company>Company Name</company>
      <email>Valid Email Address</email>
      <ipAddress>IP4 Address</ipAddress> <!-- Kount requires a valid IP4 address -->
    </customer>
    <extraData key="KOUNT_SITE">Your Kount Site configured in Kount</extraData> <!-- required -->
    <extraData key="KOUNT_SESSION_ID">unique kountSessionId</extraData> <!-- required when PaymentJS is not used -->
    <extraData key="KOUNT_UDF[YOUR_USER_DEFINED_FIELD_1]">test</extraData> <!-- optional -->
    <extraData key="KOUNT_UDF[YOUR_USER_DEFINED_FIELD_2]">test</extraData> <!-- optional -->

    <extraData key="KOUNT_TOTAL_AMOUNT">4.80</extraData> <!-- optional - if amount to evaluate differs from transaction amount -->
    <extraData key="KOUNT_CURRENCY">EUR</extraData> <!-- optional - if currency to evaluate differs from transaction currency -->

    <!--  at least one item beginning with index = 0 is required or otherwise use alternative way described below -->
    <extraData key="KOUNT_PROD_TYPE[0]">Item Type</extraData> <!-- e.g. item category -->
    <extraData key="KOUNT_PROD_ITEM[0]">Item Name</extraData>
    <extraData key="KOUNT_PROD_DESC[0]">Item Description</extraData>
    <extraData key="KOUNT_PROD_QUANT[0]">1</extraData> <!-- quantity -->
    <extraData key="KOUNT_PROD_PRICE[0]">4.80</extraData> <!-- price in same currency like transaction currency -->

    <amount>4.80</amount>
    <currency>EUR</currency>
    <description>Transaction Description</description>
    <successUrl>https://link.to/your/payment-successful-page</successUrl>
    <cancelUrl>https://link.to/your/payment-canceled-page</cancelUrl>
    <errorUrl>https://link.to/your/payment-failed-page</errorUrl>
    <callbackUrl>https://link.to/your/notification-handler</callbackUrl>

    <!-- alternative way for item data (not available for type register):
    <items>
      <item>
        <extraData key="KOUNT_PROD_TYPE">The Item Type</extraData>
        <extraData key="KOUNT_PROD_ITEM">Item Name</extraData>
        <extraData key="KOUNT_PROD_DESC">Item Description</extraData>
        <extraData key="KOUNT_PROD_QUANT">1</extraData>
        <extraData key="KOUNT_PROD_PRICE">4.80</extraData>
      </item>
    </items> -->

    <withRegister>false</withRegister>
  </debit>
</transaction>
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey);

$debit = new Debit();
$debit->setTransactionId($merchantTransactionId)
  ->setAmount(4.80)
  ->setCurrency('EUR')
  ->setDescription('One pair of shoes')
  ->setCustomer($customer)
  ->addExtraData('KOUNT_SITE', 'your_value_for_site') // required
  //->addExtraData('KOUNT_SESSION_ID', 'unique kountSessionId') // required when PaymentJS is not used
  //->addExtraData('KOUNT_UDF[YOUR_USER_DEFINED_FIELD_1]', 'test') // optional
  //->addExtraData('KOUNT_UDF[YOUR_USER_DEFINED_FIELD_2]', 'test') // optional

  //->addExtraData('KOUNT_TOTAL_AMOUNT', 4.80) // optional - if amount to evaluate differs from transaction amount
  //->addExtraData('KOUNT_CURRENCY', 'EUR') // optional - if currency to evaluate differs from transaction currency

  //->addExtraData('KOUNT_UDF[YOUR_USER_DEFINED_FIELD_2]', 'test') // optional
  ->setCallbackUrl('https://myhost.com/path/to/my/callbackHandler')
  ->setSuccessUrl('https://myhost.com/checkout/successPage')
  ->setErrorUrl('https://myhost.com/checkout/errorPage')

  // at least one item beginning with index = 0 is required or otherwise use alternative way described below
  ->addExtraData('KOUNT_PROD_TYPE[0]', 'Item Type') // e.g. item category
  ->addExtraData('KOUNT_PROD_ITEM[0]', 'Item Name')
  ->addExtraData('KOUNT_PROD_DESC[0]', 'Item Description')
  ->addExtraData('KOUNT_PROD_QUANT[0]', '1') // quantity
  ->addExtraData('KOUNT_PROD_PRICE[0]', '4.80') // price in same currency like transaction currency

/* alternative way for item data (not possible with type register):
$item = new \PaymentGateway\Client\Data\Item();
$item->addExtraData('KOUNT_PROD_TYPE', 'Item Type')
  ->addExtraData('KOUNT_PROD_ITEM', 'Item Name')
  ->addExtraData('KOUNT_PROD_DESC', 'Item Description')
  ->addExtraData('KOUNT_PROD_QUANT', '1')
  ->addExtraData('KOUNT_PROD_PRICE', '4.80');

$debit->addItem($item); */

$result = $client->debit($debit);

When using the External Risk Check Kount at least one item and the parameter Site are required. If the PaymentJS is not used the Parameter SessionId is additionally required.

For more details please see the XML explanation.

Forter

<?xml version="1.0" encoding="utf-8"?>
<transaction xmlns="https://gateway.tillpayments.com/Schema/V2/Transaction">
  <username>YOUR_USERNAME</username>
  <password>SHA1 HASHED PASSWORD</password>
  <debit>
    <transactionId>Your Transaction ID</transactionId>
    <customer>
      <identification>Customer ID</identification>
      <firstName>John</firstName>
      <lastName>Smith</lastName>
      <email>[email protected]</email>
      <gender>MALE</gender>
      <birthDate></birthDate>
      <ipAddress>IP4 Address</ipAddress> <!-- Forter requires a valid IP4 address -->
      <billingAddress1>235 Montgomery st.</billingAddress1> <!-- required -->
      <billingCity>San Francisco</billingCity><!-- required -->
      <billingCountry>US</billingCountry><!-- required -->
      <billingAddress2>street 2</billingAddress2> <!-- conditional Unit-level address -->
      <billingPostcode>94104</billingPostcode><!-- conditional Zipcode -->
      <billingState>CA</billingState><!-- conditional Top-level administrative subdivision - state/province/department/etc. Can be either abbreviated format or full name (NY/New York) -->
      <billingPhone>15557654321</billingPhone><!-- conditional Phone number including all country and local access codes -->

      <shippingAddress1>235 Montgomery st.</shippingAddress1> <!-- required -->
      <shippingCity>San Francisco</shippingCity><!-- required -->
      <shippingCountry>US</shippingCountry><!-- required -->
      <shippingAddress2>street 2</shippingAddress2> <!-- conditional Unit-level address -->
      <shippingPostcode>94104</shippingPostcode><!-- conditional Zipcode -->
      <shippingState>CA</shippingState><!-- conditional Top-level administrative subdivision - state/province/department/etc. Can be either abbreviated format or full name (NY/New York) -->
      <shippingPhone>15557654321</shippingPhone><!-- conditional Phone number including all country and local access codes -->

      <extraData key="FORTER_CUSTOMER_PAST_ORDERS_COUNT">0</extraData> <!-- optional Integer -->
      <extraData key="FORTER_CUSTOMER_PAST_ORDERS_SUM_USD">0.00</extraData> <!-- optional decmimal -->
      <extraData key="FORTER_CUSTOMER_LAST_LOGINIP">203.12.55.12</extraData> <!-- optional Possible values are: "HOME", "BUSINESS", "OTHER" -->
      <extraData key="FORTER_CUSTOMER_REGISTRATION_IP">203.12.55.12</extraData> <!-- optional Possible values are: "HOME", "BUSINESS", "OTHER" -->

      <extraData key="FORTER_CUSTOMER_BILLING_ADDRESS_TYPE">HOME</extraData> <!-- conditional Possible values are: "HOME", "BUSINESS", "OTHER" -->
      <extraData key="FORTER_CUSTOMER_BILLING_CREATION_TIME">1448549922</extraData> <!-- conditional Time item was first entered by customer in seconds since unix epoch (UTC, Jan 1, 1970) -->
      <extraData key="FORTER_CUSTOMER_BILLING_REMOVAL_TIME">1448895522</extraData> <!-- conditional Time item was removed by customer in seconds since unix epoch (UTC, Jan 1, 1970) -->
      <extraData key="FORTER_CUSTOMER_BILLING_SUGGESTED_CORRECT_ADDRESS">true</extraData> <!-- conditional True if customer selected a corrected address suggested by merchant (For example in cases where customer entered wrong zipcode) -->

      <!-- Verification Documents -->
      <extraData key="FORTER_CUSTOMER_BILLING_VERIFICATION_DOCUMENT_TYPE">Passport</extraData> <!-- required ype of document (Passport, ID, Driving license) Maximum length is 35 characters. -->
      <extraData key="FORTER_CUSTOMER_BILLING_VERIFICATION_DOCUMENT_SOURCE">UPLOADED_FILE</extraData> <!-- required Source of document (e.g. uploaded file, captured by camera, typed in by customer, etc.) Possible values are: "CAMERA_CAPTURED", "UPLOADED_FILE", "TYPED", "OTHER" -->
      <extraData key="FORTER_CUSTOMER_BILLING_VERIFICATION_NATIONALITY">US</extraData> <!-- conditional Document holder's nationality -->
      <extraData key="FORTER_CUSTOMER_BILLING_VERIFICATION_DOCUMENT_ISSUING_STATE">NY</extraData> <!-- conditional Document issuing state or region -->
      <extraData key="FORTER_CUSTOMER_BILLING_VERIFICATION_DOCUMENT_NUMBER">20439190</extraData> <!-- conditional Official document's number (e.g. passport number, driving license number, etc.) -->
      <extraData key="FORTER_CUSTOMER_BILLING_VERIFICATION_DOCUMENT_FIRSTNAME">John</extraData> <!-- conditional First name as appears on the document -->
      <extraData key="FORTER_CUSTOMER_BILLING_VERIFICATION_DOCUMENT_LASTNAME">Smith</extraData> <!-- conditional Last name as appears on the document -->
      <extraData key="FORTER_CUSTOMER_BILLING_VERIFICATION_DOCUMENT_DATEOFBIRTH">true</extraData> <!-- conditional Date of birth as appears on the document. Use YYYY-MM-DD format. -->
      <extraData key="FORTER_CUSTOMER_BILLING_VERIFICATION_DOCUMENT_EXPIRATION">true</extraData> <!-- conditional Document's exipration date. Use YYYY-MM-DD format. -->
      <extraData key="FORTER_CUSTOMER_BILLING_VERIFICATION_DOCUMENT_PAYLOAD">{}}</extraData> <!-- conditional JSON Response payload received from 3rd party document verification -->

      <extraData key="FORTER_CUSTOMER_SHIPPING_VERIFICATION_DOCUMENT_TYPE">Passport</extraData> <!-- required ype of document (Passport, ID, Driving license) Maximum length is 35 characters. -->
      <extraData key="FORTER_CUSTOMER_SHIPPING_VERIFICATION_DOCUMENT_SOURCE">UPLOADED_FILE</extraData> <!-- required Source of document (e.g. uploaded file, captured by camera, typed in by customer, etc.) Possible values are: "CAMERA_CAPTURED", "UPLOADED_FILE", "TYPED", "OTHER" -->
      <extraData key="FORTER_CUSTOMER_SHIPPING_VERIFICATION_NATIONALITY">US</extraData> <!-- conditional Document holder's nationality -->
      <extraData key="FORTER_CUSTOMER_SHIPPING_VERIFICATION_DOCUMENT_ISSUING_STATE">NY</extraData> <!-- conditional Document issuing state or region -->
      <extraData key="FORTER_CUSTOMER_SHIPPING_VERIFICATION_DOCUMENT_NUMBER">20439190</extraData> <!-- conditional Official document's number (e.g. passport number, driving license number, etc.) -->
      <extraData key="FORTER_CUSTOMER_SHIPPING_VERIFICATION_DOCUMENT_FIRSTNAME">John</extraData> <!-- conditional First name as appears on the document -->
      <extraData key="FORTER_CUSTOMER_SHIPPING_VERIFICATION_DOCUMENT_LASTNAME">Smith</extraData> <!-- conditional Last name as appears on the document -->
      <extraData key="FORTER_CUSTOMER_SHIPPING_VERIFICATION_DOCUMENT_DATEOFBIRTH">true</extraData> <!-- conditional Date of birth as appears on the document. Use YYYY-MM-DD format. -->
      <extraData key="FORTER_CUSTOMER_SHIPPING_VERIFICATION_DOCUMENT_EXPIRATION">true</extraData> <!-- conditional Document's exipration date. Use YYYY-MM-DD format. -->
      <extraData key="FORTER_CUSTOMER_SHIPPING_VERIFICATION_DOCUMENT_PAYLOAD">{}}</extraData> <!-- conditional JSON Response payload received from 3rd party document verification -->
    </customer>

    <!-- Order & ConnectionInformation -->
    <extraData key="FORTER_TYPE">WEB</extraData> <!-- optional, default WEB. Platform order was made through. Possible Values: "WEB", "PHONE", "MOBILE", "IOS", "ANDROID", "WAP", "STORE", "MAIL_ORDER", "AUTOMATIC_RENEWAL_OR_INSTALLMENT_PAYMENT", "UNKNOWN" -->
    <extraData key="FORTER_TOKEN">2315688945984</extraData> <!-- conditional Forter token cookie from request headers. Maximum length is 128 characters. -->
    <extraData key="FORTER_USER_AGENT">Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36</extraData> <!-- required when PaymentJS is not used, Customer's User agent. Maximum length is 4096 characters. -->
    <extraData key="FORTER_CHECKOUT_TIME">1415273168</extraData> <!-- optional will use current timestamp if not provided. The time when the buyer completed the checkout process in the merchant website in SECONDS since unix epoch (Jan 1, 1970). -->
    <extraData key="FORTER_MOBILE_UID">6429751237891</extraData> <!-- optional - mobile UID. The device identifier such as IMEI in android or identifier for vendor in iOS. This should match the deviceId sent via the mobile events API (for mobile transactions only) Maximum length is 128 characters. -->
    <extraData key="FORTER_MERCHANT_DEVICE_IDENTIFIER">HGJ7512345H3</extraData> <!-- conditional - A unique device identifier generated by merchant -->
    <extraData key="FORTER_MOBILE_APP_VERSION">2.9</extraData> <!-- conditional - The version of the merchant application which is running on the user's device -->
    <extraData key="FORTER_MOBILE_OS_TYPE">Android</extraData> <!-- conditional - The operating system running on the user's device (relevant for native app only) -->
    <extraData key="FORTER_MOBILE_DEVICE_BRAND">Samsung</extraData> <!-- conditional - The user's device brand (relevant for native app only) -->
    <extraData key="FORTER_MOBILE_DEVICE_MODEL">Galaxy 3</extraData> <!-- conditional - The model of the user's device (relevant for native app only) -->
    <extraData key="FORTER_FULL_HEADERS_JSON">"{"method":"GET / HTTP/1.1", "Host": "forter.com", "Connection": "keep-alive", "Accept": ...}"</extraData> <!-- conditional - A unique device identifier generated by merchant -->

    <!-- Delivery -->
    <extraData key="FORTER_DELIVERY_DETAILS_DELIVERY_TYPE">DIGITAL</extraData> <!-- optional default DIGITAL - Type of delivery: PHYSICAL for any type of shipped goods. DIGITAL for non-shipped goods (services, gift cards etc.) Example: PHYSICAL Possible values are: "DIGITAL", "PHYSICAL", "HYBRID" -->
    <extraData key="FORTER_DELIVERY_DETAILS_DELIVERY_METHOD">Galaxy</extraData> <!-- optional default EMAIL - Delivery method chosen by customer such as postal service, email, in game transfer, etc. Example: USPS - Ground Mail  -->
    <extraData key="FORTER_DELIVERY_DETAILS_DELAYED_DELIVERY_DATE">2018-10-12</extraData> <!-- conditional - Use if customer chose to deliver the item at a later date (to arrive in time for a holiday, a birthday, etc.). Use YYYY-MM-DD format. -->
    <extraData key="FORTER_DELIVERY_DETAILS_CARRIER">DHL</extraData> <!-- optional - -->
    <extraData key="FORTER_DELIVERY_DETAILS_DELIVERY_PRICE_AMOUNT">5.00</extraData> <!-- conditional - same currency as transaction currency is assumed -->
    <extraData key="FORTER_DELIVERY_DETAILS_TRACKING_EXTRA_CHARGE_AMOUNT">1.00</extraData> <!-- conditional - same currency as transaction currency is assumed -->
    <extraData key="FORTER_DELIVERY_DETAILS_EXPECTED_DELIVERY_DATE">2018-10-14</extraData> <!-- conditional - Date delivery is expected to arrive at destination. Use YYYY-MM-DD -->
    <extraData key="FORTER_DELIVERY_DETAILS_LEAVE_OUTSIDE">1</extraData> <!-- optional - 1 if customer chose to allow shipment to be left outside or at a building lobby or reception area. 1|0-->
    <extraData key="FORTER_DELIVERY_DETAILS_SMS_UPDATES">0</extraData> <!-- optional - 1 if customer asked to receive SMS updates regarding delivery. 1|0-->
    <extraData key="FORTER_DELIVERY_DETAILS_WAIT_TO_SHIP_TOGETHER">0</extraData> <!-- conditional - 1 if customer asked to try and bundle shipments together to save costs. 1|0-->
    <extraData key="FORTER_DELIVERY_DETAILS_DELIVERY_COMMENTS">Please call before arriving, Thanks!</extraData> <!-- conditional - Any comments or requests customer had for delivery -->

    <!-- Payment -->
    <extraData key="FORTER_IS_MERCHANT_OF_RECORD">1</extraData> <!-- conditional - 1 if the Forter account owner is also the merchant of record-->
    <extraData key="FORTER_PAYMENT_METHOD_NICKNAME">My Work Card</extraData> <!-- conditional - Nickname assigned to this payment method by the user -->
    <extraData key="FORTER_PAYMENT_CREDIT_USED_AMOUNT">1.00</extraData> <!-- conditional - Store credit used to pay for purchase -->
    <extraData key="FORTER_IS_DEFAULT_PAYMENT_METHOD">1</extraData> <!-- conditional - 1 if this payment instrument is the default set by the customer. 0|1 -->
    <extraData key="FORTER_NUMBER_OF_INSTALLMENTS">12</extraData> <!-- conditional - Number of payments if customer chose to pay in several installments. integer -->
    <extraData key="FORTER_DELAYED_CHARGE">0</extraData> <!-- conditional - 1 if customer chose to pay at a later date. False if customer chose to pay in several installments as long as first payment is immediate. 1|0 -->
    <extraData key="FORTER_DELAYED_CHARGE_DATE">2015-12-01</extraData> <!-- conditional - Date customer is due to pay. Use YYYY-MM-DD format. -->

    <!-- Additional Identifiers -->
    <extraData key="FORTER_PAYMENT_GATEWAY_ID">SDS34653246346</extraData> <!-- conditional - Transaction identifier provided by the payment gateway -->
    <extraData key="FORTER_MERCHANT_ID">eh629dK9</extraData> <!-- conditional - Merchant unique identifier -->
    <extraData key="FORTER_MERCHANT_DOMAIN">HandbagsExpressDiscounts.com</extraData> <!-- conditional - Use if merchant operates several sites (such as a regular site and a related discount brand) -->
    <extraData key="FORTER_MERCHANT_NAME">Handbags Express Discounts</extraData> <!-- conditional - Use if merchant operates several sites (such as a regular site and a related discount brand) -->
    <extraData key="FORTER_SITE_LOCALIZATION_COUNTRY">FR</extraData> <!-- conditional - Use if site has multiple localized versions -->
    <extraData key="FORTER_SITE_LOCALIZATION_LANGUAGE">EN</extraData> <!-- conditional - Site interface language chosen by customer, 2-letter ISO-639-1 language code -->
    <extraData key="FORTER_SITE_LOCALIZATION_CURRENCY">USD</extraData> <!-- conditional - Currency chosen by customer as default, 3-letter ISO-4217 format currency code -->

    <!-- Items: if no items are provided directly, one will be submitted by default with the required data -->
    <extraData key="FORTER_ITEM_DEFAULT_QUANTITY">1</extraData> <!-- optional defaults to 1-->
    <extraData key="FORTER_ITEM_DEFAULT_TYPE">NON_TANGIBLE</extraData> <!-- optional default to NON_TANGIBLE - Tangible if physical item, non-tangible if any other product Example: TANGIBLE Possible values are: "TANGIBLE", "NON_TANGIBLE" -->
    <extraData key="FORTER_ITEM_DEFAULT_CREATED_TIME">1415273168</extraData> <!-- conditional - Time item was added to cart by customer in seconds since unix epoch (UTC, Jan 1, 1970) -->
    <extraData key="FORTER_ITEM_DEFAULT_SPECIFIC_DATA_JSON">{"personalCustomization":false, ....}</extraData> <!-- conditional - JSON with the format described here: https://portal.forter.com/app/developer/api/api/data-objects/ItemSpecificData -->

    <!-- Items: if provided as items (not available for type register) -->
    <items>
      <item>
        <identification>342S5453Gy</identification><!-- optional - Unique item ID. Use only if two identical items have different IDs. For example, two identical pairs of shoes should have different unique item IDs. -->
        <name>White GenericBrand handba</name><!-- optional - if not set transaction.description will be used -->
        <quantity>1</quantity><!-- optional default 1 -->
        <price>1.00</price><!-- required Final amount due for item, after all discounts and promotions -->
        <extraData key="FORTER_ITEM_TYPE">NON_TANGIBLE</extraData><!-- optional default to NON_TANGIBLE - Tangible if physical item, non-tangible if any other product Example: TANGIBLE Possible values are: "TANGIBLE", "NON_TANGIBLE" -->
        <extraData key="FORTER_ITEM_PRODUCTID">Unique identifier for item that is common to all identical items (such as SKU, ISBN, etc.)</extraData>
        <extraData key="FORTER_ITEM_PRODUCTID_TYPE">SKU</extraData><!-- optional - Type of product ID used (SKU/ISBN/UPC/etc.) -->
        <extraData key="FORTER_ITEM_CATEGORY">Item Category</extraData><!-- optional -->
        <extraData key="FORTER_ITEM_COUPON_CODE_USED">FATHERSDAY2015</extraData><!-- optional - The coupon code used -->
        <extraData key="FORTER_ITEM_DISCOUNT_TYPE">COUPON</extraData><!-- optional - Discount type -->
        <extraData key="FORTER_ITEM_SPECIFIC_DATA_JSON">{"personalCustomization":false, ....}</extraData><!-- conditional - JSON with the format described here: https://portal.forter.com/app/developer/api/api/data-objects/ItemSpecificData -->
        <extraData key="FORTER_ITEM_CREATED_TIME">{"personalCustomization":false, ....}</extraData><!-- conditional - JSON with the format described here: https://portal.forter.com/app/developer/api/api/data-objects/ItemSpecificData -->
      </item>
    </items>

    <amount>4.80</amount>
    <currency>EUR</currency>
    <description>Transaction Description</description>
    <successUrl>https://link.to/your/payment-successful-page</successUrl>
    <cancelUrl>https://link.to/your/payment-canceled-page</cancelUrl>
    <errorUrl>https://link.to/your/payment-failed-page</errorUrl>
    <callbackUrl>https://link.to/your/notification-handler</callbackUrl>

    <withRegister>false</withRegister>
  </debit>
</transaction>
$client = new \PaymentGateway\Client\Client($username, $password, $apiKey);

$customer = new Customer();
$customer->setFirstName('John')
  ->setLastName('Smith')
  ->setEmail('[email protected]')
  ->setBillingAddress1('235 Montgomery st.')
  ->setBillingPostcode('94104')
  ->setBillingCity('San Francisco')
  ->setBillingState('CA')
  ->setBillingCountry('US')
  ->addExtraData('FORTER_CUSTOMER_BILLING_CREATION_TIME', 1448549922);

$debit = new Debit();
$debit->setTransactionId($merchantTransactionId)
  ->setAmount(4.80)
  ->setCurrency('EUR')
  ->setDescription('One pair of shoes')
  ->setCustomer($customer)
  ->addExtraData('FORTER_TOKEN', 'forterCookieToken') // required when PaymentJS is not used
  ->addExtraData('FORTER_USER_AGENT', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36') // required when PaymentJS is not used (this will be retrieved from 3ds data per default)

  ->setCallbackUrl('https://myhost.com/path/to/my/callbackHandler')
  ->setSuccessUrl('https://myhost.com/checkout/successPage')
  ->setErrorUrl('https://myhost.com/checkout/errorPage')

/* alternative way for item data (not possible with type register):
$item = new \PaymentGateway\Client\Data\Item();
$item->setName('Item Name')
  ->setPrice(4.80)
  ->setQuantity(1)
  ->setDescription('Item Description)
  ->addExtraData('FORTER_ITEM_TYPE', 'TANGIBLE')
  ->addExtraData('FORTER_ITEM_CATEGORY', 'FOOD')
$debit->addItem($item); */

$result = $client->debit($debit);

For more details please see the XML explanation.