Skip to content

Getting Started

High level overview of the checkout process is described in Checkout Flow. Here, let's deep dive into steps required to integrate with AltaPay Checkout solution.

Available integrations

Currently, AltaPay Checkout solution is providing two ways to integrate with it:

JS SDK

Our JS SDK offers the simplest way to integrate with AltaPay Checkout solution. It is a lightweight library that can be easily integrated into any website. It is a wrapper around our REST API, helping you to create a checkout flow in a few lines of code.

For more detailed information about the JS SDK, see JS SDK documentation.

REST API

Checkout API is a REST API that allows you to create a checkout flow on your backend using standard HTTP requests.

For more detailed endpoint descriptions and structure of requests/responses, see OpenAPI Specification of Checkout API.

Authentication

Start with authentication before you proceed with further steps either with JS SDK or REST API.

Checkout API authentication should be done on the Merchant's backend with same basic authentication credentials, that used for AltaPay Gateway authentication:

AUTH=$(echo -ne "$USERNAME:$PASSWORD" | base64)

curl \
  --header "Content-Type: application/json" \
  --header "Authorization: Basic $AUTH" \
  --request POST \
  https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/authenticate

Response will be a JSON with token field, that contains JSON Web Token.

{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJBbHRhUGF5IElzc3VlciIsInVwbiI6ImNoZWNrb3V0X2FwaSIsImdyb3VwcyI6WyJTZXNzaW9uVXBkYXRlIiwiRXhlY3V0ZVBheW1lbnQiLCJMaXN0UGF5bWVudE1ldGhvZHMiXSwiYXV0aElkIjoiZjE5YjkxZDctZDVmZS00NzFlLTkwM2EtM2JiYTk0Y2FhYzQ4IiwiaWF0IjoxNjcwOTQyMzk5LCJleHAiOjE2NzA5NDQxOTksImp0aSI6IjVhY2ZjNTgwLWQ2NjAtNDFmMS05NTJmLTBkY2ZjODRiZWM5OCJ9.XUq8AvEEEeURB-tUF2sIzUj7RdirjWJWC1NvGJsyucI0AteOxyWqnJ4zJzTe0BM61vm9Fuu6czsPhh2OqhMdolYmnDsMBDQgoIDhasr5-TukKkIWUJWIfZXsbjJHd8o8-cT70lciDO4pZhp3a16kG-mn6gtY_ezLkcbOtlExv7R0XiLy4qV5vZt1Q6mBPeyy0nEeMhjsud5ZkKMWjqLAh3LqQP2V5_W5UiGo1EPE9P-qNTDUpQolREyWaNbhQwPoverjaGq-xxTNikpJLPAwux4ytmDhAnyt_L7QlAmltRyKegIQIyKpKCKs62cOz7yj7sad_aROefH2jFgEDf6Eqg"
}

This token will be used to initialize Checkout API session for customer.

Token holds authentication information along with all the parameters required for specific user to communicate with Checkout API including environment that the user is associated with. This allows to connect to test environment without code changes, by just using test user credentials for authentication. All information about the environment will be included inside the token.

Note

For every customer session a new token should be generated.

To learn more about different access level and authentication please visit authentication guidelines.

Checkout session initialization

In order to start working with JS SDK, you need to load AltaPaySDK.js to your page.

<script type="module" src="https://{checkout-api-url}.altapaysecure.com/checkout/v1/js/AltaPaySDK.js"></script>

Checkout session nitialization can be done after the customer's checkout page is loaded.

You have 2 options for initializing the session:

  1. Provide only the token and let JS SDK to create a new session for you

    // Initialize only with the token
    Altapay.init('<token>');
    

  2. Provide both token and sessionId to use session that was created on your backend side or continue with the existing session

    // Initialize with both token and sessionId
    Altapay.init('<token>', '<sessionId>');
    

An example code snippet initializing a new session is shown below:

var paymentSession = null;
window.onload = function() {
    paymentSession = Altapay.init('eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJBbHRhUGF5IElzc3VlciIsInVwbiI6ImNoZWNrb3V0X2FwaSIsImdyb3VwcyI6WyJTZXNzaW9uVXBkYXRlIiwiRXhlY3V0ZVBheW1lbnQiLCJMaXN0UGF5bWVudE1ldGhvZHMiXSwiYXV0aElkIjoiZjE5YjkxZDctZDVmZS00NzFlLTkwM2EtM2JiYTk0Y2FhYzQ4IiwiaWF0IjoxNjcwOTQyMzk5LCJleHAiOjE2NzA5NDQxOTksImp0aSI6IjVhY2ZjNTgwLWQ2NjAtNDFmMS05NTJmLTBkY2ZjODRiZWM5OCJ9.XUq8AvEEEeURB-tUF2sIzUj7RdirjWJWC1NvGJsyucI0AteOxyWqnJ4zJzTe0BM61vm9Fuu6czsPhh2OqhMdolYmnDsMBDQgoIDhasr5-TukKkIWUJWIfZXsbjJHd8o8-cT70lciDO4pZhp3a16kG-mn6gtY_ezLkcbOtlExv7R0XiLy4qV5vZt1Q6mBPeyy0nEeMhjsud5ZkKMWjqLAh3LqQP2V5_W5UiGo1EPE9P-qNTDUpQolREyWaNbhQwPoverjaGq-xxTNikpJLPAwux4ytmDhAnyt_L7QlAmltRyKegIQIyKpKCKs62cOz7yj7sad_aROefH2jFgEDf6Eqg');
}

In order to initialize a session on Merchant's backend side, you need to make a POST request on /checkout/v1/api/session endpoint with JWT token in the header.

curl \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer $TOKEN" \
  --request POST \
  https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session

Result will be a JSON with sessionId field, that we will use further to identify our session:

{
    "sessionId": "f19b91d7-d5fe-471e-903a-3bba94caac48",
    "context": { ... },
    "order": { ... },
    "callbacks": { ... }
}

Please refer to the /checkout/v1/api/session endpoint in OpenAPI specification for more details.

Note

You may use PUT to update the session. Bear in mind that some payment methods allows to keep only 1 active session per order ID. If you change the order's details and amount while processing after the payment has starded (i.e. the consumer going back to the browser and changing the basket) we recommend that you create a new session with the new order and order ID.

Filling in checkout session details

After paymentSession is created, it should be configured with order and customer details

paymentSession.setOrder(
    AltaPayFactory.getOrder(
        'testOrderId',
        AltaPayFactory.getAmount(30098.52, 'DKK'),
        [
            AltaPayFactory.getOrderLine('123981239', 'MSI GeForce RTX 4090 SUPRIM X 24G', 1, 28010.50),
            AltaPayFactory.getOrderLine('123981240', 'Delivery', 1, 2078.02)
        ],
        AltaPayFactory.getCustomer(
            'John',
            'Doe',
            'example@email.com',
            '+4560020030',
            AltaPayFactory.getAddress('Vesterbrogade 65', 'Copenhagen', 'DK', '2860'),
            AltaPayFactory.getAddress('Gyngemose Parkvej 50', 'Søborg', 'DK', '2860')
        )
    )
);

After session is created, it should be configured with order and customer details. To do that, you need to make a PUT request on /checkout/v1/api/session/{sessionId} endpoint with JWT token in the header providing all the details in the body.

Example below contains all the necessary data including callbacks which are described in the next section.

curl --location --request PUT 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    "order": {
        "orderId": "testOrderId",
        "amount": {
            "value": 30098.52,
            "currency": "DKK"
        },
        "orderLines": [
            {
                "itemId": "123981239",
                "description": "Chaos Emerald",
                "quantity": 1,
                "unitPrice": 28020.5
            },
            {
                "itemId": "123981240",
                "description": "Delivery",
                "quantity": 1,
                "unitPrice": 2078.02
            }
        ],
        "customer": {
            "firstName": "John",
            "lastName": "Doe",
            "email": "test@example.com",
            "billingAddress": {
                "street": "Gyngemose Parkvej 50",
                "city": "Soeborg",
                "country": "DK",
                "zipCode": "2860"
            },
            "shippingAddress": {
                "street": "Gyngemose Parkvej 50",
                "city": "Soeborg",
                "country": "DK",
                "zipCode": "2860"
            }
        }
    },
    "context": {
        "browser": {
            "agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
            "language": "en-GB",
            "resolution": "2560x1440",
            "deviceId": "5eb63bbbe01eeed093cb22bb8f5acdc3"
        }
    },
    "callbacks": {
        "success": {
            "type": "FUNCTION"
        },
        "failure": {
            "type": "FUNCTION"
        },
        "redirect": "https://testbank.pensio.com/checkoutShop/redirect",
        "notification": "https://testbank.pensio.com/eCommerce/testshop/url_notification"
    }
}'

All the session details are saved on AltaPay side, so you can refer to them both using JS SDK and REST API.

Please refer to the PUT /checkout/v1/api/session/{sessionId} endpoint OpenAPI specification for more details.

Note

If you are using the plain REST API without our JS SDK, you must provide information about the browser page opened by the customer in the session.context.browser section. This information is required for some payment methods to work correctly (for example ApplePay). For fraud detection purposes, you also need to provide device information, especially the identifier of the customer's device used for processing payments. See the example in the next section for the expected structure.

For more information about the order and customer details, please visit Order and Customer Details

Checkout session configuration

A configuration can be added to the checkout session which is used when checkout solution creates the payment. It's optional (in that case 'paymentType' will be 'PAYMENT', and 'autoCapture' = false).

Parameter name Description Mandatory
paymentType Define the type of the request. It can be PAYMENT or AGREEMENT NO ('PAYMENT' is default)
agreement Define the Agreement Parameters. It needs to be set if paymentType = AGREEMENT. If paymentType = AGREEMENT then at least agreement.agreementType needs to be set, otherwise optional
autoCapture Flag indicating if the transaction should be captured directly. By default, the transaction is authorized, but not yet captured. If agreement.initialAmount is set and funds should be captured during the agreement setup
ccToken Credit Card Token, it can be used to prefill credit card forms. It is provided by AltaPay - A MarketPay Company on successful payments if terminal is set up to use them NO. Requires additional setup on gateway to be used - contact support.
shopName Optional and advanced parameter. It is the internal configuration's Shop name, used to limit the payment methods to the ones related with the given shop. It is generally used by larger merchants to filter available payment methods to be only relevant ones. If you require this parameter, please contact AltaPay Support, as it must match the internal configuration of the integration. NO
country Country code, used to filter payment methods based on a given code. Must be ISO 3166-1 alpha-2 code. If order.customer.billingAddress is not set.
language The language of the payment page to be displayed to the customer. Should be defined as ISO 639-1 alpha-2 code, e.g. en, da, de, etc.
kThe default value is en.
NO
paymentDisplayType Indicates how to display the payment. Possible values:
- SCRIPT - payment form will be displayed in place if possible
- REDIRECT - payment form will be displayed on separate page after redirection
Defaults to SCRIPT if not provided.
NO
paymentDisplayComponent ID of HTML element where the payment form will be injected
Methods that requires a redirect to their systems will not be injected in this element,
but rather redirect will be performed instead when initiate payment is triggered.
NO
payment Define the Payment Configuration Parameters NO

Agreement Parameters

Parameter name Description Mandatory
agreementType Indicates the type of agreement. Possible values: RECURRING, UNSCHEDULED. Needs to be set if paymentType = AGREEMENT. if paymentType = AGREEMENT
expirationDate The date when the agreement expires. It must have the format yyyy-MM-dd'T'HH:mm:ss'Z' so be compatible with ISO 8601 and expressed in UTC. Example: 2024-12-15T12:20:30Z. NO
frequency It is a value representing the frequency between the charge agreement requests made by the merchant. Possible values: FLEXIBLE, DAILY, WEEKLY, BIWEEKLY, MONTHLY, QUARTERLY, YEARLY. NO
nextChargeDate The date of the first charge agreement request made by the merchant. It must have the format yyyy-MM-dd'T'HH:mm:ss'Z' so be compatible with ISO 8601 and expressed in UTC. Example: 2024-12-15T12:20:30Z. NO
agreementManagementUrl This is a link to a page on the merchant side where the customer can manage the agreement. NO
autoReserve Flag indicating if the agreement setup should automatically be reserved. It is used together with autoCapture flag to indicate the subscription behaviour (authType). See below table for possible combinations. if initialAmount is set and funds should be reserved during the agreement setup
unscheduledType It indicates the type of the unscheduled agreement. Possible values: INCREMENTAL, RESUBMISSION, DELAYED_CHARGES, REAUTHORISATION, NO_SHOW, CHARGE. If agreementType = UNSCHEDULED and at least one of: autoCapture, agreement.autoReserve is set to true
fallbackToPayment Flag indicating if the agreement should fallback to regular payment if payment method does not support agreements. NO
name Short name displayed to customer when accepting the agreement. if paymentType = AGREEMENT
description Description of the agreement to be accepted by the customer. if paymentType = AGREEMENT
amount Amount of money that is meant to be charged as a part of agreement. if paymentType = AGREEMENT
initialAmount Amount of money to be charged when setting up the agreement if first payment differs from other payments within the agreement. if paymentType = AGREEMENT and there will be a payment made/funds reserved (so either autoCapture or autoReserve must be also set)

Payment Configuration Parameters

Parameter name Description Mandatory
dynamicDescriptor The description that appears on the user's bank statement. This is normally set in the terminal configuration, but it can be overridden per payment using this parameter.

Format: {string(25)}*{string(13)} — the first part (up to 25 chars) is the business name, followed by * and an identifier (up to 13 chars). The identifier supports templating.

Valid templates:
  • %orderId
  • %paymentId
  • %currency.numeric
  • %currency.alpha
  • %customer.ip
  • %customer.email
  • %customer.phone
  • %customer.username

Example: CompCo*%orderIdCompCo*123

⚠️ The resolved value (after templating) must stay within 13 characters. If exceeded, behavior depends on the terminal’s descriptor policy.
⚠️ Only available for processing with Shift4 Acquirer.
NO

Mapping between Altapay gateway authType and checkout session configuration:

authType autoCapture agreement.autoReserve
subscription false (or not present) false (or not present)
subscriptionAndReserve false (or not present) true
subscriptionAndCharge true true (or not present)

To learn more about agreements please visit agreements section of our gateway documentation.

After paymentSession is created, it can be configured using the ConfigurationBuilder before making a payment.

Example for paymentType = PAYMENT

.setConfiguration(
    AltaPayFactory.getConfigurationBuilder()
        .setTypePayment('PAYMENT')
        .setAutoCapture(true)
        .setCcToken('U3kSorzbIP11kgMwTqs7F3lhZlfpf4F6NWvz5fo0OGLKUGO9OviTppM4mIWaOBRlbI8Sr8pWK1U3ZP1rEXAOJA==+1')
        .setShopName('Candy shop')
        .setCountry('DK')
        .setLanguage('en')
        .setPaymentDisplayType('REDIRECT')
        .build()
        )
)
Example for paymentType = AGREEMENT (subscription authType = 'subscription')

.setConfiguration(
    AltaPayFactory.getConfigurationBuilder()
        .setTypePayment('AGREEMENT')
        .setAgreement(AltaPayFactory
                .getAgreementBuilder()
                .setAgreementType('RECURRING')
                .setExpirationDate('2024-12-15T12:20:30Z')
                .setFrequency('MONTHLY')
                .setNextChargeDate('2023-12-15T12:20:30Z')
                .setAgreementManagementURL('http://agreement.example.shop.com')
                .setAutoReserve(false) //or not set
                .setName('some name to be dispayed to customer when accepting the agreement')
                .setDescription('some description of the agreement to be accepted by the customer')
                .setAmount(99.99)
                .build()
        )
        .setAutoCapture(false) //or not set
        .setShopName('Candy shop')
        .setCountry('DK')
        .setLanguage('en')
        .build()
        )
)
Example for agreement with authType = 'subscriptionAndReserve'

.setConfiguration(
    AltaPayFactory.getConfigurationBuilder()
        .setTypePayment('AGREEMENT')
        .setAgreement(AltaPayFactory
                .getAgreementBuilder()
                .setAgreementType('RECURRING')
                .setExpirationDate('2024-12-15T12:20:30Z')
                .setFrequency('MONTHLY')
                .setNextChargeDate('2023-12-15T12:20:30Z')
                .setAgreementManagementURL('http://agreement.example.shop.com')
                .setAutoReserve(true)
                .setName('some name to be dispayed to customer when accepting the agreement')
                .setDescription('some description of the agreement to be accepted by the customer')
                .setAmount(99.99)
                .build()
        )
        .setAutoCapture(false) //or not set
        .setShopName('Candy shop')
        .setCountry('DK')
        .setLanguage('en')
        .build()
        )
)
Example for agreement with authType = 'subscriptionAndCharge'

.setConfiguration(
    AltaPayFactory.getConfigurationBuilder()
        .setTypePayment('AGREEMENT')
        .setAgreement(AltaPayFactory
                .getAgreementBuilder()
                .setAgreementType('RECURRING')
                .setExpirationDate('2024-12-15T12:20:30Z')
                .setFrequency('MONTHLY')
                .setNextChargeDate('2023-12-15T12:20:30Z')
                .setAgreementManagementURL('http://agreement.example.shop.com')
                .setAutoReserve(true) //or not set
                .setName('some name to be dispayed to customer when accepting the agreement')
                .setDescription('some description of the agreement to be accepted by the customer')
                .setAmount(99.99)
                .build()
        )
        .setAutoCapture(true)
        .setShopName('Candy shop')
        .setCountry('DK')
        .setLanguage('en')
        .build()
        )
)
Example for unscheduled agreement with authType = 'subscriptionAndCharge'

.setConfiguration(
    AltaPayFactory.getConfigurationBuilder()
        .setTypePayment('AGREEMENT')
        .setAgreement(AltaPayFactory
                .getAgreementBuilder()
                .setAgreementType('UNSCHEDULED')
                .setExpirationDate('2024-12-15T12:20:30Z')
                .setFrequency('MONTHLY')
                .setNextChargeDate('2023-12-15T12:20:30Z')
                .setAgreementManagementURL('http://agreement.example.shop.com')
                .setAutoReserve(false) //or not set
                .setUnscheduledType("CHARGE") //some value needs to be set here
                .setName('some name to be dispayed to customer when accepting the agreement')
                .setDescription('some description of the agreement to be accepted by the customer')
                .setAmount(99.99)
                .build()
        )
        .setAutoCapture(true)
        .setShopName('Candy shop')
        .setCountry('DK')
        .setLanguage('en')
        .build()
        )
)
Example for paymentType = AGREEMENT with fallbackToPayment flag

.setConfiguration(
    AltaPayFactory.getConfigurationBuilder()
        .setTypePayment('AGREEMENT')
        .setAgreement(AltaPayFactory
                .getAgreementBuilder()
                .setAgreementType('RECURRING')
                .setExpirationDate('2024-12-15T12:20:30Z')
                .setFrequency('MONTHLY')
                .setNextChargeDate('2023-12-15T12:20:30Z')
                .setAgreementManagementURL('http://agreement.example.shop.com')
                .setAutoReserve(false) //or not set
                .setFallbackToPayment(true)
                .setName('some name to be dispayed to customer when accepting the agreement')
                .setDescription('some description of the agreement to be accepted by the customer')
                .setAmount(99.99)
                .build()
        )
        .setAutoCapture(false) //or not set
        .setShopName('Candy shop')
        .setCountry('DK')
        .setLanguage('en')
        .build()
        )
)
Example for recurring agreement with authType = 'subscriptionAndCharge' and initialAmount e.g. customer pays for an monthly subscription: 99.99 + mobile phone: 500 (which is one-time payment)

.setConfiguration(
    AltaPayFactory.getConfigurationBuilder()
        .setTypePayment('AGREEMENT')
        .setAgreement(AltaPayFactory
                .getAgreementBuilder()
                .setAgreementType('RECURRING')
                .setExpirationDate('2024-12-15T12:20:30Z')
                .setFrequency('MONTHLY')
                .setNextChargeDate('2023-12-15T12:20:30Z')
                .setAgreementManagementURL('http://agreement.example.shop.com')
                .setAutoReserve(false) //or not set
                .setName('some name to be dispayed to customer when accepting the agreement')
                .setDescription('some description of the agreement to be accepted by the customer')
                .setAmount(99.99)
                .initialAmount(599.99)
                .build()
        )
        .setAutoCapture(true)
        .setShopName('Candy shop')
        .setCountry('DK')
        .setLanguage('en')
        .build()
        )
)

After session is created, it can be configured with some necessary configurations used when the payment is created. To do that, you need to make a PUT request on /checkout/v1/api/session/{sessionId} endpoint with JWT token in the header providing all the details in the body.

curl --location --request PUT 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    "configuration": {
        "paymentType": "PAYMENT",
        "autoCapture": false,
        "ccToken": "U3kSorzbIP11kgMwTqs7F3lhZlfpf4F6NWvz5fo0OGLKUGO9OviTppM4mIWaOBRlbI8Sr8pWK1U3ZP1rEXAOJA==+1",
        "shopName" : "Candy shop",
        "country" : "DK",
        "language" : "en"
    }
}'

or

curl --location --request PUT 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    "configuration": {
        "paymentType": "AGREEMENT",
        "agreement" : {
             "agreementType" : "RECURRING",
             "expirationDate" : "2024-12-15T12:20:30Z",
             "frequency" : "MONTHLY",
             "nextChargeDate" : "2023-12-15T12:20:30Z",
             "agreementManagementUrl" : "http://agreement.example.shop.com",
             "name" : "some name to be dispayed to customer when accepting the agreement",
             "description" : "some description of the agreement to be accepted by the customer",
             "amount" : 99.99
        },
        "autoCapture": false,
        "shopName" : "Candy shop",
        "country" : "DK",
        "language" : "en"
    }
}'

Example for agreement with authType = 'subscriptionAndReserve'

curl --location --request PUT 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    "configuration": {
        "paymentType": "AGREEMENT",
        "agreement" : {
             "agreementType" : "RECURRING",
             "expirationDate" : "2024-12-15T12:20:30Z",
             "frequency" : "MONTHLY",
             "nextChargeDate" : "2023-12-15T12:20:30Z",
             "agreementManagementUrl" : "http://agreement.example.shop.com",
             "autoReserve" : true,
             "name" : "some name to be dispayed to customer when accepting the agreement",
             "description" : "some description of the agreement to be accepted by the customer",
             "amount" : 99.99
        },
        "autoCapture": false,
        "shopName" : "Candy shop",
        "country" : "DK",
        "language" : "en"
    }
}'

Example for agreement with authType = 'subscriptionAndCharge'

curl --location --request PUT 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    "configuration": {
        "paymentType": "AGREEMENT",
        "agreement" : {
             "agreementType" : "RECURRING",
             "expirationDate" : "2024-12-15T12:20:30Z",
             "frequency" : "MONTHLY",
             "nextChargeDate" : "2023-12-15T12:20:30Z",
             "agreementManagementUrl" : "http://agreement.example.shop.com",
             "autoReserve" : true,
             "name" : "some name to be dispayed to customer when accepting the agreement",
             "description" : "some description of the agreement to be accepted by the customer",
             "amount" : 99.99
        },
        "autoCapture": true,
        "shopName" : "Candy shop",
        "country" : "DK",
        "language" : "en"
    }
}'

Example for unscheduled agreement with authType = 'subscriptionAndCharge'

curl --location --request PUT 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    "configuration": {
        "paymentType": "AGREEMENT",
        "agreement" : {
             "agreementType" : "UNSCHEDULED",
             "expirationDate" : "2024-12-15T12:20:30Z",
             "frequency" : "MONTHLY",
             "nextChargeDate" : "2023-12-15T12:20:30Z",
             "agreementManagementUrl" : "http://agreement.example.shop.com",
             "autoReserve" : true,
             "unscheduledType" : "CHARGE",
             "name" : "some name to be dispayed to customer when accepting the agreement",
             "description" : "some description of the agreement to be accepted by the customer",
             "amount" : 99.99
        },
        "autoCapture": true,
        "shopName" : "Candy shop",
        "country" : "DK",
        "language" : "en"
    }
}'

Example for paymentType = AGREEMENT with fallbackToPayment flag

curl --location --request PUT 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    "configuration": {
        "paymentType": "AGREEMENT",
        "agreement" : {
             "agreementType" : "RECURRING",
             "expirationDate" : "2024-12-15T12:20:30Z",
             "frequency" : "MONTHLY",
             "nextChargeDate" : "2023-12-15T12:20:30Z",
             "agreementManagementUrl" : "http://agreement.example.shop.com",
             "fallbackToPayment" : true,
             "name" : "some name to be dispayed to customer when accepting the agreement",
             "description" : "some description of the agreement to be accepted by the customer",
             "amount" : 99.99
        },
        "autoCapture": false,
        "shopName" : "Candy shop",
        "country" : "DK",
        "language" : "en"
    }
}'
Example for recurring agreement with authType = 'subscriptionAndCharge' and initialAmount e.g. customer pays for an monthly subscription: 99.99 + mobile phone: 500 (which is one-time payment)

curl --location --request PUT 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    "configuration": {
        "paymentType": "AGREEMENT",
        "agreement" : {
             "agreementType" : "RECURRING",
             "expirationDate" : "2024-12-15T12:20:30Z",
             "frequency" : "MONTHLY",
             "nextChargeDate" : "2023-12-15T12:20:30Z",
             "agreementManagementUrl" : "http://agreement.example.shop.com",
             "autoReserve" : true,
             "name" : "some name to be dispayed to customer when accepting the agreement",
             "description" : "some description of the agreement to be accepted by the customer",
             "amount" : 99.99,
             "initialAmount" : 599.99
        },
        "autoCapture": true,
        "shopName" : "Candy shop",
        "country" : "DK",
        "language" : "en"
    }
}'

Context parameters

Parameter name Description Mandatory
browser.agent Full User-Agent string from the HTTP request header. NO
browser.language Preferred language of the customer’s browser (e.g., en-GB). NO
browser.resolution Screen resolution of the customer’s device (e.g., 1920x1080). NO
browser.deviceId Stable identifier of the customer’s device used for processing the payment. NO
All the session details are saved on AltaPay side, so you can refer to them both using JS SDK and REST API.

Please refer to the PUT `/checkout/v1/api/session/{sessionId}` endpoint [OpenAPI specification](OpenAPI.md) for more details.

Configuring payment status callbacks

In order to perform further actions after payment is processed, we need to configure callbacks.

Parameter name Description Mandatory
success Action triggered once the payment succeeded. It can be a javascript function, or a HTTP callback URL.

For bank payments, the success callback is invoked when the payment status is pending. This ensures a smooth user experience, as the user's flow is considered successful.
In those cases refer to either notification callback or poll the payment status for the final result.
NO
failure Action triggered once the payment failed. It can be a javascript function, or a HTTP callback URL. YES
redirect URL to where the shopper should be taken back to after a redirection. The URL should include the protocol. NO
verifyOrder URL where checkout solution will post request to verify order just before completing the payment by the shopper. For more details see: Pre-payment order verification NO
formStyling URL where checkout solution will post request for payment form HTML and CSS. The merchant can change placeholders, if they wish. For more details, see: Configuring payment form placeholders NO
notification URL where checkout solution will post notification once the payment status changed. NO
bodyFormat Format of the HTTP callbacks we will send to your system. Accepted values:
- XML (default) we will send callbacks as urlencoded with XML content inside
- JSON we will send callbacks as application/json
Please note that we are switching towards JSON as primary data format and XML messages will be slowly deprecated in the future releases.
NO

In order to configure callbacks on Merchant's frontend side, you need to use setCallbacks method of IAltaPay session object. For creating a callback object, please use AltaPayFactory.getCallbacksBuilder.

paymentSession.setCallbacks(
    AltaPayFactory.getCallbacksBuilder()
        .setSuccess(function (altapayEvent) {
            // handle successful payment
        }) // URL can be passed here as well
        .setFailure(function (altapayEvent) {
            // handle successful payment
        }) // URL can be passed here as well
        .setRedirectUrl('https://your_host.com/redirect')
        .setNotificationUrl('https://your_host.com/redirect/notification')
        .setBodyFormat('JSON') // optional, default value 'XML'
        .build()
)

In order to configure callbacks on Merchant's backend side, you need to make a PUT request on /checkout/v1/api/session/{sessionId} endpoint with JWT token in the header and make sure that callbacks section is present in the body.

curl --location --request PUT 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    "context": { ... },
    "callbacks": {
        "success": {
            "type": "FUNCTION"
        },
        "failure": {
            "type": "FUNCTION"
        },
        "redirect": "https://testbank.pensio.com/checkoutShop/redirect",
        "notification": "https://testbank.pensio.com/eCommerce/testshop/url_notification",
        "bodyFormat": "JSON"
    },
    "order": { ...}
}'

Customize AltaPay - A MarketPay Company payment page

The merchant can dynamically style the payment page by adding html elements, images, CSS styles to the HTML form elements controlled by AltaPay - A MarketPay Company that make up the payment page.

Your customer accesses the payment page via our secure payment gateway.

You design the page, and we retrieve it from your server.

How it works

AltaPay - A MarketPay Company does a request to the endpoint where you provide the payment form styling. The POST or GET request sent back to your payment page styling endpoint has the following parameters:

Parameter name Description
shop_orderid This is the internal ID of the order in your webshop.
amount This is the payment amount..
currency This is the payment currency. It must be specified in an ISO-4217 format, either using the 3-digit numeric code, or the 3-letter character code. For more information about ISO-4217 currency codes, see https://en.wikipedia.org/wiki/ISO_4217.
language The language in which the payment form is displayed. It is specified as ISO 639-1 alpha-2 code, e.g. en, da, de, etc.

How to setup the styling payment form callback endpoint

In order to configure form styling callback on Merchant's frontend side, you need to use setCallbacks method of IAltaPay session object. For creating a callback object, please use AltaPayFactory.getCallbacksBuilder.

paymentSession.setCallbacks(
    AltaPayFactory.getCallbacksBuilder()
        ...
        .setFormStylingUrl('https://your_host.com/formStyling')
        .build()
)

In order to configure callbacks on Merchant's backend side, you need to make a PUT request on /checkout/v1/api/session/{sessionId} endpoint with JWT token in the header and make sure that callbacks section is present in the body.

curl --location --request PUT 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    "context": { ... },
    "callbacks": {
        ...
        "formStyling":"http://your-company.com/formStyling"
    },
    "order": { ... }
}'

Payment form styling requirements

If you wish to style the Content of the Payment Page, visit Settings for the Payment Page

If you wish to style the Payment Form Pop-up Window, visit Styling a floating payment window

Note

Some alternative payment methods operate using a re-direct solution. In these instances, AltaPay - A MarketPay Company takes care of all the mapping of the parameters the merchant already has integrated, reducing technical overhead.

All Javascript and other active content is stripped from its content. If the callback URL is non-secure (i.e. HTTP instead of HTTPS), all images, CSS, links, and forms are proxied by AltaPay - A MarketPay Company.

The payment page URL is retrieved via AltaPay's servers, and not directly by your customer, but cookies and UserAgent headers are relayed, and we will relay the UserAgent header if the client specifies this to us.

Payment methods rendering

When session is configured, it's possible to request a list of available payment methods. These methods come from the configured terminals of Merchant's gateway on altapaysecure.com. Session configuration and customer data is used to determine which payment methods are available. You can either:

  • delegate rendering of payment methods to IAltaPay session object on your frontend or
  • retrieve them on the backend and render them on your frontend using your own frontend code.

In order to render payment methods on Merchant's frontend side, you need to use injectPaymentMethods method of IAltaPay session object. This method accepts HTML element as a parameter, where payment methods will be rendered.

paymentSession.injectPaymentMethods(document.getElementById('payment-methods-list'));

Default HTML payment method layout

Default HTML components, generated for available payment methods, looks like this:

<div id="payment-methods-list" style="display: inline-grid;">
    <h3>Place where Checkout API will insert payment methods</h3>
    <div class="payment-method-element" id="AltaPay Checkout CreditCard Terminal">
        <div id="AltaPay Checkout CreditCard Terminal" class="logo" style="float: left; vertical-align: middle; opacity: 0.5;">
            <img src="https://{checkout-api-url}.altapaysecure.com/checkout/static/methods/logos/credit-card-logo.png" width="30px" height="30px">
        </div>
        <div style="float: left; vertical-align: middle;">
            <p>CreditCard</p>
        </div>
    </div>
    <div class="payment-method-element" id="AltaPay Checkout MobilePay Test Terminal DENMARK">
        <div id="AltaPay Checkout MobilePay Test Terminal DENMARK" class="logo" style="float: left; vertical-align: middle; opacity: 0.5;">
            <img src="https://{checkout-api-url}.altapaysecure.com/checkout/static/methods/logos/mobile-pay-logo-small.png" width="30px" height="30px">
        </div>
        <div style="float: left; vertical-align: middle;">
            <p>MobilePay</p>
        </div>
    </div>
</div>

Payment methods customization

It is also possible to change the payment methods rendering by specifying following handler:

paymentSession.onRenderPaymentMethodCallback(function (onRenderPaymentMethodEvent) {
    // the handler function you send as parameter will called automatically for every Payment Method which will be rendered 
    // onRenderPaymentMethodEvent contains necessary elements you can use to overwrite payment method rendering
    // Please refer to the [Payment Methods](PaymentMethods.md) page for more details.
    return onRenderPaymentMethodEvent.defaultPaymentMethodElement;
});

In order to render payment methods on Merchant's backend side, you need to make a GET request on /checkout/v1/api/session/{sessionId}/payment-methods endpoint with JWT token in the header.

curl --location --request GET 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}/payment-methods'

Response will contain a list of available payment methods, which you can render on your frontend.

[
    {
        "id": "AltaPay Checkout CreditCard Terminal",
        "type": "CARD",
        "description": "AltaPay Checkout CreditCard Terminal",
        "logoUrl": "https://{checkout-api-url}.altapaysecure.com/checkout/static/methods/logos/credit-card-logo.png",
        "display": "LIST",
        "onInitiatePayment": {
            "type": "URL",
            "value": "https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/payment"
        },
        "gatewayMethodIdentifier": "1e5c1b5e-1b5e-1b5e-1b5e-1b5e1b5e1b5e",
        "metadata": {
            "canIssueNewCredit": "false",
            "canUseCredit": "true",
            "configuration.paymentType": "PAYMENT",
            "shopName": "AltaPay Checkout Shop",
            "terminalName": "AltaPay Checkout CreditCard Terminal"
        }
    },
    { ... }
]

Please refer to the GET /checkout/v1/api/session/{sessionId}/payment-methods endpoint OpenAPI specification for more details.

Extra availability verification

[
    {
        "id": "99d86597-9e48-424d-988f-885c45d7b8cf",
        "type": "WALLET",
        "description": "ApplePay",
        "logoUrl": "https://{checkout-api-url}.altapaysecure.com/checkout/static/methods/logos/applepay-logo.png",
        "display": "LIST",
        "jsMethodHandler": {
            "identifier": "ApplePay",
            "data": {
                "merchantIdentifier": "<MERCHANT_ID_WITH_APPLE>",
                "operatingCountry": "<MERCHANT_OPERATING_COUNTRY>",
                "onInitiatePaymentUrl": "https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/payment",
                "supportedNetworks": [
                    "visa",
                    "mastercard",
                    "dankort"
                ]
            }
        },
        "onInitiatePayment": {
            "type": "SCRIPT"
        },
        "onRenderCheck": {
            "type": "SCRIPT"
        },
        "metadata": { ... }
    }
]

If you have onRenderCheck of type SCRIPT that means payment method will require additional verification to be executed on the frontend app in order to make sure it is applicable for customer. Common example will be ApplePay which requires user to own Apple device and open the website using Safari browser.

For web applications it means JS code must be execute. For mobile applications this will require custom code to handle this payment method.

We provide JS code that instruments such payment methods. In order to use them you need to add following script to your website:

<script src="https://{checkout-api-url}.altapaysecure.com/checkout/v1/js/methods/AltaPayMethodHandlers.js" type="module"></script>

Once JS script is part of your website you can call:

const jsHandler = window.AltaPayPaymentMethodFactory.createHandler(
                       token, 
                       sessionId, 
                       order, 
                       method
                   );
jsHandler.onRenderCheck()
         then(() => {
             // successfully validated that payment method is available for the customer to use
             // here place your code to render the payment method on the website
         })
        .catch(({ message, errorCode }) => {
             // given payment method is not available at the moment
             // here place your code to handle this case, it could be for example:
             // - logging this in your system
             // - doing nothing, you can continue with other payment methods normally
             // - rendering given payment method as inactive (greyed out with message displayed on mouse hover)
         });

To learn more about JS based payment methods please see JS SDK page.

If you want to use your own code for handling those payment methods, please follow documentation specific for given payment provider.

Please refer to the GET /checkout/v1/api/session/{sessionId}/payment-methods endpoint OpenAPI specification for more details.

For more information please visit Payment Methods page

Rendering the QR Code

Apart from in-place rendered payment methods, you can render a QR code allowing the customer to finalize the payment using their mobile device.

In order to render the QR code on Merchant's frontend side, you need to use injectQR method of IAltaPay session object. This method accepts <div> or <img> HTML element as a parameter, where payment methods will be rendered, and the URL to the page where the user will be redirected after scanning QR code.

paymentSession.injectQR(
    document.getElementById('qr-code'),
    "https://example.com/qr-page"
);

In order to retrieve the QR code for a specific session using your backend service, you need to make a POST request to /checkout/v1/api/session/{sessionId}/link endpoint with JWT token in the header.

curl --location --request POST 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}/link'

Response will contain a QR code image in base64 format, which you can render on your frontend.

For more information about QR Payments flow please see: QR Payments

Payment flow initialization

After payment method is selected and Pay button is clicked, regular payment flow is initiated.

In order to initiate payment flow directly from frontend side, you need to call initiatePayment method of IAltaPay session object.

document.getElementById('payButton').onclick = function onPayButtonClick() {
    paymentSession.initiatePayment();
}

Where 'payButton' is id of the HTML button to complete payment.

If you wish to start payment flow using our JS SDK, but you're rendering and managing payment methods selection on your own, you can specify paymentMethodId as optional parameter. By doing this you will tell AltaPay JS SDK to start payment for specific payment method.

    // remember to initiate AltaPay JS SDK for given checkout session
    const paymentSession = Altapay.init(token, sessionId);
    // your code selecting the payment method
    const selectedPaymentMethodId = selectPaymentMethod();

    paymentSession.initiatePayment({
        paymentMethodId: selectedPaymentMethodId
    });

In order to initiate payment using your own integration, you need to follow instructions received on payment method fetched from /checkout/v1/api/session/{sessionId}/payment-methods. Let's follow possible scenarios.

URL-based payment methods

{
    "id": "7ab4889b-6b91-4a56-ba10-efc97026e5e6",
    "type": "CARD",
    "description": "Credit / Debit Card",
    "logoUrl": "https://{checkout-api-url}.altapaysecure.com/checkout/static/methods/logos/credit-card-logo.png",
    "display": "LIST",
    "onInitiatePayment": {
        "type": "URL",
        "value": "https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/payment"
    },
    "metadata": { ... }
}

If onInitiatePayment is of type URL that requires to call given URL endpoint with JWT token in the header and provide paymentMethodId and sessionId in order to initiate a payment:

curl --location --request POST 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/payment' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    "paymentMethodId" : "7ab4889b-6b91-4a56-ba10-efc97026e5e6",
    "sessionId": "2171b42e-dc4e-4a56-9fca-7de6f6d60625"
}'

You will receive details of the newly started payment.

If type is SCRIPT, this means that url contains script to be executed on the page.

{
    "paymentId": "d6ff1626-a23b-4b63-bc2a-00c072bedef7",
    "shopOrderId": "5c926c8b-bbb2-4a0c-84f4-ba5bad618b0d",
    "status": "NEW",
    "type": "SCRIPT",
    "url": "https://{checkout-api-url}.altapaysecure.com/eCommerce/API/embeddedPaymentWindow?pid=9b9b479e-6476-4754-b6aa-061deb9d92f6"
}

It should be added to webpage, for example:

const scriptElement = document.createElement('script');
scriptElement.src = data.url;
document.body.appendChild(scriptElement);

If type is REDIRECT, this means that customer should be redirect to given url:

{
    "paymentId": "47c063b0-ca75-4f53-aedf-06acbb58e5c8",
    "shopOrderId": "5c926c8b-bbb2-4a0c-84f4-ba5bad618b0d",
    "status": "NEW",
    "type": "REDIRECT",
    "url": "https://{checkout-api-url}.altapaysecure.com/eCommerce/API/requestForm?pid=17c39d92-f50a-4256-b8ba-3f248adc6464"
}

Other payment types (eg. JS_HANLDER, REQUEST) are no longer supported, have been deprecated, and should not appear in the API anymore.

SCRIPT-based payment methods

[
    {
        "id": "99d86597-9e48-424d-988f-885c45d7b8cf",
        "type": "WALLET",
        "description": "ApplePay",
        "logoUrl": "https://{checkout-api-url}.altapaysecure.com/checkout/static/methods/logos/applepay-logo.png",
        "display": "LIST",
        "jsMethodHandler": {
            "identifier": "ApplePay",
            "data": {
                "merchantIdentifier": "<MERCHANT_ID_WITH_APPLE>",
                "operatingCountry": "<MERCHANT_OPERATING_COUNTRY>",
                "onInitiatePaymentUrl": "https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/payment",
                "supportedNetworks": [
                    "visa",
                    "mastercard",
                    "dankort"
                ]
            }
        },
        "onInitiatePayment": {
            "type": "SCRIPT"
        },
        "onRenderCheck": {
            "type": "SCRIPT"
        },
        "metadata": { ... }
    }
]

If you have onInitiatePayment or onRenderCheck of type SCRIPT it means that there will be local execution needed. For web applications, this implies client-side JavaScript must be executed in response to a user action. For native mobile applications, this requires custom implementation to handle the specific payment method accordingly.

We provide JS code that instruments such payment methods. In order to use them you need to add following script to your website:

<script src="https://{checkout-api-url}.altapaysecure.com/checkout/v1/js/methods/AltaPayMethodHandlers.js" type="module"/>

Once JS script is part of your website you can call:

const jsHandler = window.AltaPayPaymentMethodFactory.createHandler(
                       token, 
                       sessionId, 
                       order, 
                       method
                   );
// code rendering the payment method and handling user action
// on user clicking pay button trigger:
jsHandler.onInitiatePayment()
         .then(() => {
            // successfully initialized that payment method for the customer
            // here place your code to react on payment initiated properly
         })
          .catch(({ message, errorCode }) => {
             // given payment initialization fails or payment method not available on device
             // here place your code to handle this case, it could be for example:
             // - logging this in your system
             // - display error message to the customer and let them try again with different payment methods normally
         });

For native mobile applications integrating Apple Pay via iOS PassKit, merchant session validation is handled by the framework itself. When creating a payment through the AltaPay API, you must include the source parameter set to PASSKIT.

In this case, AltaPay registers the payment but does not perform merchant validation with Apple services — this is managed directly by the PassKit framework.

Example request for the native implementation:

curl --location --request POST 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/payment' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    "paymentMethodId" : "7ab4889b-6b91-4a56-ba10-efc97026e5e6",
    "sessionId": "2171b42e-dc4e-4a56-9fca-7de6f6d60625",
    "requestData": {
        "applePayRequestData": {
            "source": "PASSKIT"
        }
    }
}'

For comparison, the web-based integration specifies the APPLE_PAY_JS_API source and includes a validationUrl for handling merchant validation:

curl --location --request POST 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/payment' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    "paymentMethodId" : "7ab4889b-6b91-4a56-ba10-efc97026e5e6",
    "sessionId": "2171b42e-dc4e-4a56-9fca-7de6f6d60625",
    "requestData": {
        "applePayRequestData": {
            "source": "APPLE_PAY_JS_API",
            "validationUrl": "https://apple-pay-gateway.apple.com/paymentservices/startSession"
        }
    }
}'

Note

In order for some payment methods to work correctly (like ApplePay) you need to pass browser details of the page currently opened by the customer. Please see section Filling in checkout session details.

If you want to use your own code for handling those payment methods, please follow documentation specific for given payment provider.

Payment form placement

There are 3 ways to display payment form on your website:

  • popup window - AltaPay - A MarketPay Company will display payment form as modal with overlay on top of existing page (default behaviour)
  • redirected to new page - AltaPay - A MarketPay Company will open payment form in new page and redirect back to merchant's website after completing the payment
  • embedded - AltaPay - A MarketPay Company will display payment form inside HTML component defined by the merchant

Note

Keep in mind that not all payment methods are giving the flexibility described above. Flows like Klarna, PayPal or Vipps will redirect to their apps if possible. ApplePay will always open it's own system popup.

In order to configure the above you need to provide some extra parameters:

It's default behaviour and it doesn't require explicit configuration.

In order to provide explicit configuratin please set paymentDisplayType to SCRIPT. For more details please refer to configuration section.

In order to redirect to standalone payment page you need to set paymentDisplayType to REDIRECT. For more details please refer to configuration section.

In order to embed payment form into your website's HTML element you need to set paymentDisplayType to SCRIPT and provide HTML element ID as paymentDisplayComponent property. Both paymentDisplayType and paymentDisplayComponent are part of configuration section. For more details please refer to configuration section.

Additionaly, you can dynamically pass paymentDisplayComponent as configuration parameter of initiatePayment call.

When using JS SDK pass paymentDisplayComponent as part of configuration object when initiating the payment:

checkoutSession.initiatePayment({
    paymentDisplayComponent: 'id-of-your-html-element'
});

When using REST API you need to pass paymentDisplayComponent parameter with ID of your HTML element:

curl --location --request POST 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/payment' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    "paymentMethodId" : "7ab4889b-6b91-4a56-ba10-efc97026e5e6",
    "sessionId": "2171b42e-dc4e-4a56-9fca-7de6f6d60625",
    "paymentDisplayComponent": "id-of-your-html-element"
}'

Important

If the HTML element provided is not available at the time initiatePayment is called, AltaPay - A MarketPay Company will fallback to default popup window.

Pre-payment order verification

AltaPay - A MarketPay Company can callback the merchant just before a financial transaction is about to take place. This happens after the customer has typed in their card details or identified themselves with the alternative payment provider.

Merchant system can verify the order and payment information and accept or reject the payment.

Verify order callback is configured as part of Session Callbacks section.

At the Session creation and callbacks level:

paymentSession.setCallbacks(
    AltaPayFactory.getCallbacksBuilder()
        .setVerifyOrderUrl('https://your_website/order/order_id/verify')
        .setBodyFormat("JSON")
        .build()
)

As a part of session creation or update :

curl --location --request PUT 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}' \
--header 'Authorization: Bearer $TOKEN' \
--header 'Content-Type: application/json' \
--data '{
    ...
    "callbacks": {
        ...
        "verifyOrder": "https://your_website/order/order_id/verify",
        ...
    },
    ...
}'

The format of the request AltaPay - A MarketPay Company is sending is the same as for other callbacks and notifications.

We are expecting the response of 200-204 HTTP code if we should continue with the payment. Other HTTP error codes are considered as declines. You can return extra details that AltaPay - A MarketPay Company will share with customer. In order to provide details on the rejection you need to send us response in following format:

{
    "errorMessage": "Message to be displayed to the customer"
}
<?xml version="1.0"?>
<VerifyOrderResponse>
    <ErrorMessage>Message to be displayed to the customer</ErrorMessage>
</VerifyOrderResponse>

Important

You should not send any requests towards AltaPay systems for given checkout session or payment while processing our verify order request.

This might lead to race conditions and unexpected side effects. We may reject such requests without further notice.

Handling payment status changes

On JavaScript side payment status changes are handled automatically by AltaPay SDK. In order to react on them, you need to provide a callback function. REST API provides you with endpoints to fetch payment data and instrument the flow on your backend side. Please follow the sections below to learn more about different ways of retrieving and reacting to payment status changes.

For more information about how to design and secure your callback endpoints, please visit Callback Endpoints Security page.

Payment statuses

Status Description
NEW Newly created payment
SUCCEEDED Payment processed successfully
ERROR Payment exited due to technical issue. In most cases it is retryable.
FAILED Payment failed to be processed. Issuing new payment is required to retry.
PENDING Payment in the middle of processing, customer already started doing the payment.
CANCELLED Payment cancelled.
DECLINED Payment declined by the acquiring side. (For example 3DS verification
UNKNOWN Payment in unknown state, please reach out to our support.

Retrieving payment status

JavaScript will handle payment changes automatically and will call the callback function with AltaPayEvent object as a parameter. For more see section below.

In order to retrieve basic information about current active payment for given session, you need to make GET request on /checkout/v1/api/session/{sessionId} endpoint with JWT token in the header.

curl --location 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}' \
--header 'Authorization: Bearer $TOKEN'

Response will contain information about active payment:

{
    "sessionId": "d1215ba4-0789-437b-95da-dc9bffd34bd6",
    ...
    "activePayment": {
        "paymentId": "0f597b84-51f5-4833-ac68-dbbaeb46627c",
        "externalPaymentId":"1f597b84-321d-4833-ac68-daad77711edf",
        "shopOrderId": "testOrderId",
        "status": "NEW"
    }
}

Please refer to the GET /checkout/v1/api/session/{sessionId} endpoint OpenAPI specification for more details.


In order to retrieve information about all the payments related to given session, you need to make GET request on /checkout/v1/api/session/{sessionId}/payments endpoint with JWT token in the header.

curl --location 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}/payments' \
--header 'Authorization: Bearer $TOKEN'

The response will contain a list of payments related to the session:

[
    {
        "paymentId": "0f597b84-51f5-4833-ac68-dbbaeb46627c",
        "externalPaymentId":"1f597b84-321d-4833-ac68-daad77711edf",
        "shopOrderId": "testOrderId",
        "status": "NEW"
    },
    {
        "paymentId": "0f597b84-51f5-4833-ac68-dbbaeb466271",
        "externalPaymentId":"1f597b84-321d-4833-ac68-daad77711ed2",
        "shopOrderId": "testOrderId",
        "status": "NEW"
    }
]

Please refer to the GET /checkout/v1/api/session/{sessionId}/payments endpoint OpenAPI specification for more details.


In order to retrieve detailed information about the payment, you need to make GET request on /checkout/v1/api/payment/{paymentId} endpoint with JWT token in the header.

curl --location 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/payment/{paymentId}' \
--header 'Authorization: Bearer $TOKEN'

Response will contain a payment status, information how the payment was initialized and link to the payment page.

{
    "paymentId": "4c54ff94-bbc1-4f85-bcda-66d765992798",
    "externalPaymentId":"1f597b84-321d-4833-ac68-daad77711edf",
    "shopOrderId": "testOrderId",
    "status": "NEW",
    "type": "SCRIPT",
    "url": "https://{gateway-api-url}.altapaysecure.com/eCommerce/API/embeddedPaymentWindow?pid=b185d247-f189-4009-98a6-e0fa358b5327"
}

Coming soon

There will be more details about the payment status coming soon. For now if you want to fetch more details about the payment, please use the Gateway Merchant API using externalPaymentId as a reference.

Please refer to the GET /checkout/v1/api/payment/{paymentId} endpoint OpenAPI specification for more details.

Handling success or failed callback

Once the payment succeeded or failed, the AltaPay checkout solution will trigger the callback handler defined on the session. The success and failure callbacks can be either javascript functions or HTTP callback URL.

Once the payment is completed, the AltaPay checkout solution will call the javascript function with an AltaPayEvent object containing some information about the payment.

AltaPayEvent : {
    type : RENDER|PAYMENT,
    paymentId: id of the payment in checkout solution,
    shopOrderId: ID of the order,
    status: NEW|SUCCEEDED|ERROR|FAILED|PENDING|CANCELLED|DECLINED|UNKNOWN,
    errorMessage: optional error message
    errorDetails: { // optional error details
        merchantErrorMessage: more detailed error message for merchant internal use
        merchantErrorCode: technical error code
        customerErrorMessage: error message that might be shown to the customer
        customerMessageMustBeShown: indicator if error message has to be shown to the customer
    }
}

Once the payment is completed, if there is a HTTP URL callback defined, the AltaPay checkout solution will do a POST request to the endpoint specified earlier in format depending on the bodyFormat flag.

AltaPay checkout solution will send POST request as application/x-www-form-urlencoded with following paramaters:

Parameter Description
status The status of the transactions: new, error, failed, succeeded, cancelled, open, incomplete, PartialSuccess
error_message A fallback error message that is safe to display to your customers.
merchant_error_message An error message for the merchant's eyes only, but provides more detail as to what went wrong (This is only sent to the FAIL-callback page).
shop_orderid This is the internal ID of the order in your webshop.
transaction_id The ID of the transaction. This should be stored if you are going to capture/cancel the order directly from your system, for example, for capturing reservations using the captureReservation method.
type The authorisation type of the payment, for example, "payment"/"paymentAndCapture"/"subscription"
payment_status The status of the transaction, depending on the payment method, for example, preauth,recurring_confirmed, captured, etc.
masked_credit_card The masked primary account number of the credit card, which contains the maximum number of digits allowed to share with a non-PCI compliant merchant.
blacklist_token A unique token you can use for blacklisting a credit card. This token can be used to build up a black list of credit cards. The token is only returned if this is a credit card payment.
credit_card_token This is the unique credit card token value that identifies a credit card within the AltaPay Payment Gateway. This token can be used later with the Merchant API or with creditcard token ordering so that the customer does not need to enter credit card details in their next order. The token is only returned for credit card payments.
nature The payment method:Wallet, EPayment, CreditCard, BankPayment, IdealPayment, Invoice, CreditCardWallet, GiftCard, Mobile
xml Contains the XML response of the API call. This is the parameter from which to design the business logic. For detailed information about the XML response from API calls, see API Response structure (XML).
checksum If the Customer Information Shared Secret field is set under Home > Terminal Settings in the Merchant Information Interface, the checksum can be used to authenticate the origin of a request, to counter "man in the middle" attacks. The checksum is calculated based on these parameters: amount, currency, orderid, secret

AltaPay checkout solution will send POST request as application/json with request body PaymentCallback schema specified in OpenAPI specification


The AltaPay checkout solution will display the return response to the shopper.

URL callback handling:

  • URL callback responds with HTTP 3XX: The checkout solution will redirect the iFrame to the URL provided in the response. In case transactions which does not happens inside iframe(ex. ApplPay), the customer will be redirected to the URL provided in the response.

Warning

Please be aware that only HTTPS is accepted. Redirects to unsecured URLs will fail due to browsers' safety features.

Warning

Your callback url web server might be using X-Frame-Options which disallows the redirect. Make sure the header is not defined for your callbacks.

  • URL callback responds with HTTP 2XX or other: the checkout solution will display the content inside the iFrame

Important

You should not send any requests towards AltaPay systems for given checkout session or payment while processing callback request.

This might lead to race conditions and unexpected side effects. We may reject such requests without further notice.


Note

ApplePay solution support only JS callbacks or HTTP callback with 3xx response. The customer will be redirected to the URL provided in the 3xx HTTP response provided by the success/failure HTTP callback


Handling notification callbacks

The notification callback can be configured either using the JS SDK or passing it when create or update session via the Checkout REST API Whenever when the payment is created or there is change of the payment status, the AltaPay checkout solution will do a POST request to the callback URL defined on the session.

We expect the response to be 200, 202, 204 HTTP code.

Important

Notification is purely information message. We are expecting you to just acknowledge the message receival with 200, 202 or 204 HTTP code. There is no action based on your response. In case of other HTTP code than 200, 202, 204 we treat it as error and we might retry the notification.

AltaPay checkout solution will send POST request as application/x-www-form-urlencoded with following paramaters:

Parameter Description
status The status of the transactions: new, error, failed, succeeded, cancelled, open, incomplete, PartialSuccess
error_message A fallback error message that is safe to display to your customers.
merchant_error_message An error message for the merchant's eyes only, but provides more detail as to what went wrong (This is only sent to the FAIL-callback page).
shop_orderid This is the internal ID of the order in your webshop.
transaction_id The ID of the transaction. This should be stored if you are going to capture/cancel the order directly from your system, for example, for capturing reservations using the captureReservation method.
type The authorisation type of the payment, for example, "payment"/"paymentAndCapture"/"subscription"
payment_status The status of the transaction, depending on the payment method, for example, preauth,recurring_confirmed, captured, etc.
masked_credit_card The masked primary account number of the credit card, which contains the maximum number of digits allowed to share with a non-PCI compliant merchant.
blacklist_token A unique token you can use for blacklisting a credit card. This token can be used to build up a black list of credit cards. The token is only returned if this is a credit card payment.
credit_card_token This is the unique credit card token value that identifies a credit card within the AltaPay Payment Gateway. This token can be used later with the Merchant API or with creditcard token ordering so that the customer does not need to enter credit card details in their next order. The token is only returned for credit card payments.
nature The payment method:Wallet, EPayment, CreditCard, BankPayment, IdealPayment, Invoice, CreditCardWallet, GiftCard, Mobile
xml Contains the XML response of the API call. This is the parameter from which to design the business logic. For detailed information about the XML response from API calls, see API Response structure (XML).
checksum If the Customer Information Shared Secret field is set under Home > Terminal Settings in the Merchant Information Interface, the checksum can be used to authenticate the origin of a request, to counter "man in the middle" attacks. The checksum is calculated based on these parameters: amount, currency, orderid, secret

AltaPay checkout solution will send POST request as application/json with request body PaymentCallback schema specified in OpenAPI specification

Note

Optional parameters are available only when the transaction is finalised(succeeded or failed).

Handling the redirect results

Some payment methods like MobilePay and Vipps, will redirect the customer to other pages. In that cases, the AltaPay checkout session will be lost. Once the payment is completed, the shopper comes back to the redirect URL specified, but only in case there's neither success nor failure URL defined.

The returnUrl has query parameters appended to it, which helps you to load the AltaPay checkout session back on your page

Query parameter Description
sessionId The unique identifier for the shopper's payment session.
redirectData Payload to be set when load the session.

Example of redirect URL

https://your-company.com/redirect?sessionId=5c20c35e-b2e2-4f65-854f-8ec4ca8cf791&redirectData=eyJwYXltZW50SWQiOiJkYmE0MTdhOC05YzFiLTQ3MzgtYm

Extract the values from the query string parameters and create a function which load the AltaPay checkout browser session with the sessionId and the token, define again the javascript callback functions and set the redirect data. The AltaPay checkout solution triggers callbacks automatically once the payment is completed.

Altapay.init(
    "eyJ0eXAiOiJKV1QiLCJhbGcxxxxx", //authenitcation token
    "5c20c35e-b2e2-4f65-854f-8ec4ca8cf791" //session id
)
    .setCallbacks(
        AltaPayFactory.getCallbacksBuilder()
            .setSuccess(function (altapayEvent) {
                //handle payment succeeded
            })
            .setFailure(function (altapayEvent) {
                //handle payment failed
            })
            .build()
    )
    .handleRedirectData(
        "eyJwYXltZW50SWQiOiJkYmE0MTdhOC05YzFiLTQ3MzgtYm" //redirect data received in the request parameters
    );

Risk Analysis

AltaPay - A MarketPay Company offers the following providers for Risk Analysis:

  • MaxMind
  • Retail Decisions (ReD)
  • MarketPay

If the Risk Analysis is enabled on your gateway you will receive the relevant parameters on a successful PaymentCallback:

  "riskAnalysis": {
        "recommendation": string,
        "explanation": string,
        "riskScore": string
    }

Recommendation

Value Description
Accept Low risk — transaction appears safe
Challenge Medium risk — transaction warrants closer inspection, manual review
Deny High risk — transaction is likely fraudulent
Unknown Risk could not be determined

Important

The gateway does not automatically block or decline a payment based on the recommendation value. The transaction completes regardless. It is the merchant's responsibility to inspect the fraud response and act accordingly.

Explanation

A human-readable string describing the factors that contributed to the risk score. It may contain multiple lines, each describing one risk signal.

Example output for MaxMind provider:

    High risk country: Yes
    Country match: No
    Anonymous proxy: Yes
    Proxy score: 3.2

Risk Score

A numeric fraud risk score, with the scale and interpretation of values depending on the selected provider. Typically, the score ranges from 0 to 100, where higher values indicate greater risk.

Note

Special value -1 indicates that the score could not be computed (missing required attributes, provider error). In this case, the recommendation is Unknown.

For more details on setting up and using Risk Analysis, please refer to the documentation.

Frontend Error handling

When you're invoking the terminal operation on AltaPay object like injectPaymentMethods or initiatePayment, JavaScript Promise is returned indicating progress and state of the operation. You can react on the result of the operation by using then and catch methods for succesful and failed operation handling respectively.

Altapay.init('eyJ0eXAiOiJKV1QiLCJhbGcxxxxx')
    .injectPaymentMethods(document.getElementById('payment-methods-list'))
    .then((altapay) => {
        // handle successfully injected payment methods
    })
    .catch(error => {
        // handle error occured during injecting payment methods
    });

Additionally, if you setup failure callbacks for this session they will be triggered when error occurs both during payment processing and checkout session configuration. For more details around callback events see: Handling success or failed callback

Altapay
.init(authBearer, sessionID)
.setCallbacks(
    AltaPayFactory.getCallbacksBuilder()
        .setFailure(function (altapayEvent) {
            // handle failure event
        })
    .build()
);

Embedding Checkout inside the iframe

Some business scenarios requires to embed payment processing inside the isolated iframe component. In order to make it secure and compliant with all the payment methods we provide, Checkout solution needs to be aware of the website origin for which they payments are processed.

If you want to start Checkout sessions inside an iframe you need to start it in a specific way by specifying:

  • origin query parameter inside src of the iframe which represents the origin page that started embedded payment component
  • allow="payment" feature policy for the iframe containing payment component

Please see below example:

<iframe
    allow="payment"
    src="https://your_payment_service/checkout?origin=https://your_online_shop"
</iframe>

Complete example

Complete example with configuring session in the browser

<script type="module" src="https://{checkout-api-url}.altapaysecure.com/checkout/v1/js/AltaPaySDK.js"></script>
<script>
var paymentSession = null;
window.onload = function () {
    paymentSession =
        Altapay.init('eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJBbHRhUGF5IElzc3VlciIsInVwbiI6ImNoZWNrb3V0X2FwaSIsImdyb3VwcyI6WyJTZXNzaW9uVXBkYXRlIiwiRXhlY3V0ZVBheW1lbnQiLCJMaXN0UGF5bWVudE1ldGhvZHMiXSwiYXV0aElkIjoiZjE5YjkxZDctZDVmZS00NzFlLTkwM2EtM2JiYTk0Y2FhYzQ4IiwiaWF0IjoxNjcwOTQyMzk5LCJleHAiOjE2NzA5NDQxOTksImp0aSI6IjVhY2ZjNTgwLWQ2NjAtNDFmMS05NTJmLTBkY2ZjODRiZWM5OCJ9.XUq8AvEEEeURB-tUF2sIzUj7RdirjWJWC1NvGJsyucI0AteOxyWqnJ4zJzTe0BM61vm9Fuu6czsPhh2OqhMdolYmnDsMBDQgoIDhasr5-TukKkIWUJWIfZXsbjJHd8o8-cT70lciDO4pZhp3a16kG-mn6gtY_ezLkcbOtlExv7R0XiLy4qV5vZt1Q6mBPeyy0nEeMhjsud5ZkKMWjqLAh3LqQP2V5_W5UiGo1EPE9P-qNTDUpQolREyWaNbhQwPoverjaGq-xxTNikpJLPAwux4ytmDhAnyt_L7QlAmltRyKegIQIyKpKCKs62cOz7yj7sad_aROefH2jFgEDf6Eqg')
            .setCallbacks(
                AltaPayFactory.getCallbacksBuilder()
                    .setSuccess(function (altapayEvent) {
                        // handle successful payment
                    }) // URL can be passed here
                    .setFailure(function (altapayEvent) {
                        // handle successful payment
                    }) // URL can be passed here
                    .setRedirectUrl('https://your_host.com/redirect')
                    .setNotificationUrl('https://your_host.com/redirect/notification')
                    .setFormStylingUrl('https://your_host.com/redirect/notification')
                    .build()
            )
            .setOrder(AltaPayFactory.getOrder(
                    AltaPayFactory.getAmount(30098.52, 'DKK'),
                    [
                        AltaPayFactory.getOrderLine('123981239', 'MSI GeForce RTX 4090 SUPRIM X 24G', 1, 28010.50),
                        AltaPayFactory.getOrderLine('123981240', 'Delivery', 1, 2078.02)
                    ],
                    AltaPayFactory.getCustomer(
                        'John',
                        'Doe',
                        'example@email.com',
                        '+4560020030',
                        AltaPayFactory.getAddress('Vesterbrogade 65', 'Copenhagen', 'DK', '2860'),
                        AltaPayFactory.getAddress('Gyngemose Parkvej 50', 'Søborg', 'DK', '2880')
                    )
                )
            )
            .setConfiguration(
                AltaPayFactory.getConfigurationBuilder()
                    .setTypePayment()
                    .setAutoCapture(true)
                    .setShopName('Candy shop')
                    .setCountry('DK')
                    .setLanguage('en')
                    .build()
                )
            )
            .onRenderPaymentMethodCallback(function (onRenderPaymentMethodEvent) {
            // provide your custom rendering, filter out some payment methods 
            // or simply return default rendered by AltaPay - A MarketPay Company
            return onRenderPaymentMethodEvent.defaultPaymentMethodElement;
            })
            .injectPaymentMethods(document.getElementById('payment-methods-list'))
}
document.getElementById('payButton').onclick = function onPayButtonClick() {
    paymentSession.initiatePayment();
}
</script>
  1. Authenticate

    AUTH=$(echo -ne "$USERNAME:$PASSWORD" | base64)
    
    curl \
      --header "Content-Type: application/json" \
      --header "Authorization: Basic $AUTH" \
      --request POST \
      https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/authenticate
    

  2. Create checkout session

    curl \
      --header "Content-Type: application/json" \
      --header "Authorization: Bearer $TOKEN" \
      --request POST \
      https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session
    

  3. Configure your checkout session

    curl --location --request PUT 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/session/{sessionId}' \
    --header 'Authorization: Bearer $TOKEN' \
    --header 'Content-Type: application/json' \
    --data '{
        "context": {
            "browser": {
                "agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
                "language": "en-GB",
                "resolution": "2560x1440",
                "deviceId": "5eb63bbbe01eeed093cb22bb8f5acdc3"
            }
        },
        "callbacks": {
            "success": {
                "type": "FUNCTION"
            },
            "failure": {
                "type": "FUNCTION"
            },
            "notification":"http://your-company.com/notification",
            "formStyling":"http://your-company.com/formStyling"
        },
        "order": {
            "orderId": "testOrderId",
            "amount": {
                "value": 600,
                "currency": "DKK"
            },
            "orderLines": [
                {
                    "itemId": 1,
                    "description": "Garden chair",
                    "amount": 5,
                    "price": 120.00
                }
            ],
            "customer": {
                "firstName": "John",
                "lastName": "Doe",
                "email": "example@email.com",
                "phoneNumber": "+4560020030",
                "billingAddress": {
                    "street": "Vesterbrogade 65",
                    "city": "Copenhagen",
                    "country": "DK",
                    "zipCode": "4521"
                },
                "shippingAddress": {
                    "street": "Gyngemose Parkvej 50",
                    "city": "Søborg",
                    "country": "DK",
                    "zipCode": "4321"
                }
            }
        },
        "configuration": {
            "paymentType": "PAYMENT",
            "autoCapture": true,
            "shopName" : "Candy shop",
            "country" : "DK",
            "language": "en"
        }
    }'
    

  4. Retrieve payment methods available for given checkout session

    curl --location --request GET 'https://{checkout-api-url}.altapaysecure.com/checkout/v1/api/payment-methods'
    

  5. Initiate payment

    curl --location 'http://localhost/checkout/v1/api/payment' \
    --header 'Authorization: Bearer $TOKEN' \
    --header 'Content-Type: application/json' \
    --data '{
        "paymentMethodId" : "AltaPay Checkout CreditCard Terminal",
        "sessionId": "2171b42e-dc4e-4a56-9fca-7de6f6d60625"
    }'