Multiple payment methods

This technical manual is for integrating a payment component using multiple payment methods.

1. Add the HTML elements

  1. Add the component's CSS to the <head> of your checkout page:

    <link rel="stylesheet" href="https://testpay.multisafepay.com/sdk/components/v2/components.css">
    
  2. Add the component's script to the bottom of the <body> of your checkout page:

    <script src="https://testpay.multisafepay.com/sdk/components/v2/components.js"></script>
    
  3. Add the DOM element for the component's UI in the <body> of your checkout page:

<div id="MultiSafepayPayment"></div>

Choose your payment button

Decide if you want to:

  • Generate a button with the component (see Step 2 below). Recommended.

  • Use an existing button, e.g. if your checkout already includes one.

  • Create your own button:

    <button id="payment-button"></button>
    

2. Initialize the component

Generate an API token

Payment components require a MultiSafepay API token. See API reference – Generate an API token.

Tip! To keep your API key private, request the token from your own server.

Construct the component object

  1. Initialize an orderData object containing information about the customer's order collected during the checkout process:

    const orderData = {
        currency: 'EUR',
        amount: 10000,
        customer: {
            locale: 'en',
            country: 'NL'
        },    
        payment_options: {
            settings: {
                connect: {
                    group_cards: true,
                    qr: {
                        enabled: true,
                        autoload: false
                   }
                }
            }
        },
    };
    
    Properties
    | Key | Required | Value | |------------------------------------------|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | amount | Yes | The value of the order.
    Format: Number without decimal points, e.g., 100 euro is formatted as `10000`. | | currency | Yes | The currency of the order.
    Format: ISO-4217 , e.g., `EUR`. | | customer.country | No | The customer's country code. Used to validate the availability of the payment method.
    Format: ISO-3166-1 alpha-2 , e.g., `NL`. | | customer.locale | No | The customer's language. Sets the language of the payment component UI.
    Format: ISO 639
    Supported languages: `en`, `es`, `fr`, `it`, `nl`. | | customer.reference | Yes, for recurring payments | Your unique customer reference.
    (\*currently not supported for QR payments.) | | payment_options.settings.connect.group_cards | No | Groups all card payment methods as a single option in the list of payment methods.
    Format: Boolean
    Default: `false`. | | payment_options.settings.connect.qr | No | Allows QR code to be rendered for iDEAL and Bancontact: `enabled`.
    `autoload` allows automatic display of QR code, and subsequent redirect for these methods. Default: `true`. | | recurring.model | Yes, for recurring payments | The [recurring model](/docs/recurring-payments/). | | template.settings.embed_mode | No | A template designed to blend in seamlessly with your ecommerce platform.
    Format: Boolean. |
    How to process recurring payments

Recurring payments is a solution that lets you store a customer’s payment details as a secure, encrypted token.

Upon subsequent payments, customers can select their stored payment details and pay with a single click.

To process recurring payments in your payment component:

  • Add the cardOnFile recurring model

    • Make List tokens request from your server and provide atokens

      const orderData = {
          currency: 'EUR',
          amount: 10000,
          customer: {
              locale: 'en',
              country: 'NL'
          },
          template : {
              settings: {
              embed_mode: true
          }
       }
      };
      const recurringData = {
      "model": "cardOnFile",
      "tokens": [
          {
              "token": "AvqeOjgdm8A",
              "code": "IDEAL",
              "display": "xxxxxxxxxNL81PSTB0000012345",
              "bin": null,
              "name_holder": "Schilder",
              "expiry_date": "",
              "expired": 0,
              "last4": null,
              "model": "cardOnFile"
          },
          {
              "token": "BcEWsknWsYg",
              "code": "MASTERCARD",
              "display": "Card xxxx xxxx xxxx 4444",
              "bin": 555555,
              "name_holder": "Holder",
              "expiry_date": 2412,
              "expired": 0,
              "last4": 4444,
              "model": "cardOnFile"
          }
       ]
      };
      

Success

Your payment component now automatically renders a checkbox where customers can choose whether they would like to store their payment details for future visits.

Recurring payments are supported for all card payments.

📘 Note: To test card details, see Test payment details – Credit and debit cards.

To use recurring payments in your payment component, you need to enable recurring payments for your account. If you haven't already, email [[email protected]](mailto:[email protected])

📘 Note: We use the orderData object to ensure the payment methods are enabled, e.g. for the currency, country, and order value.

  1. Construct a PaymentComponent object in the test environment using the order object and your API token:

    PaymentComponent = new MultiSafepay({
        env: 'test',
        apiToken: apiToken,
        order: orderData
    });
    

Initialize the component

Initialize the component using:

Payment component button
PaymentComponent.init('dropin', {
   container: '#MultiSafepayPayment',
    onGetQR: function (state) {      
        console.log('onGetQR', state);
    },
    onError: function (state) {      
        console.log('onError', state);
    },
    onEvent: function (state) {
        console.log('onEvent', state);
    },
    onSubmit: function (state) {
        if(PaymentComponent.hasErrors()) {
            let errors = PaymentComponent.getErrors();
            console.log(errors);
            return;
        }

        // Send state.paymentData to your server (createOrder)
        // Create an order from your server
        // Return the response from your server to the client-side
        // With the response, redirect the customer or log an error

        createOrder(PaymentComponent.getPaymentData()).then(response => {
            console.log(response);
            if(response.success) {
                PaymentComponent.init('redirection', {
                    order: response.data

            }
        });
    },    
    onValidation: function (state) {
     console.log('onValidation', state);
    },  
    onSelect: function (state) { 
        console.log('onSelect', state);
    },
    onLoad: function (state) {
        console.log('onLoad', state);
    }
});
Own or existing button
PaymentComponent.init('dropin', {
    container: '#MultiSafepayPayment',
    onSelect: state => {
        console.log('onSelect', state);
    }, 
    onError: state => {
        console.log('onError', state);
    },
    onLoad: state => {
        console.log('onLoad', state);
    }
});

In the method call, create event handlers for the following events:

Events
EventEvent Handler
onErrorOccurs when there is an error in the payment component.
onGetQROccurs when the QR is rendered in the payment component.
Example:
```javascript
onGetQR: e => {
createOrder(e.orderData).then(response => {
PaymentComponent.setQR({
order: response.data
});
});
},
onLoadOccurs when the payment component UI is rendered.
onSelectOccurs when the customer selects an issuer with iDEAL.
onSubmitOccurs when the customer clicks the payment button (when using the button generated by the component).
onValidationOccurs when form validation changes. Can be used to disable the payment button until all fields are validated.

The PaymentComponent has the following methods:

Methods
MethodDescription
getErrorsReturns error messages or codes.
hasErrorsReturns a boolean value about whether errors were registered.
getOrderDataReturns an object containing a payment_data object and the full order configuration.
getPaymentDataReturns a payment_data object with a payload containing the customer's payment details, used to create orders, and the gateway.
setQR()Returns a boolean to set up the QR code. Requires argument orderData.
If orderData is not sent, the payment will not be associated with the order.

3. Create an order

Handle the interaction

Tip! This step only applies if using your own or an existing payment button.

  1. Assign the button element to a variable:

    const paymentButton = document.querySelector('#payment-button');
    

The payment_data includes the following parameters:

  {
    "payment_data": {
    "gateway": "CREDITCARD",
    "payload": "xxxxxxxx",
    "tokenize": true
  }};
Parameters
KeyRequiredDescription
gatewayYesThe unique gateway_id to redirect the customer to the specific payment method.
payloadYesInformation required to process the payment.
Note: Do not edit or modify the payload or otherwise the payment fails.
tokenizeOptionalFor recurring payments.
If a customer selects to either save their cardholder data for future visits or use an existing token, apayment_data.tokenize parameter is added.

Note: When payment_data.tokenize is set to trueyou need to append customer.reference to the order data.

  1. Create an event handler for the payment button:
  • When the customer clicks the payment button, call the component's getPaymentData() method.
  • Send the response to your server and create an order.
  • Return the reponse from your server to the client-side to redirect the customer.

Redirect the customer

You need to fetch the property payment_url, which will then - depending on the result - redirect the customer to the correct page. This may be for 3ds required cards towards the authentication step, or for frictionless / not required 3ds, towards the success page.
The handling of the payment_url lies on your side.

The component's redirection handler redirects the customer to the relevant page:

  • If customer actions are required to complete the payment (e.g. by completing 3D Secure or iDEAL issuer authentication), the customer is redirected to the relevant page. If successful, the customer is then redirected to the redirect_url, i.e. the "success page".
  • If no customer action is required to complete the payment, the customer is redirected to the redirect_url, i.e. the "success page".
  • If the customer chooses to pay by bank transfer, the component displays the banking details needed for customers to complete payment.
  • If a QR code is available for customers to complete payment on their mobile device, the component displays the QR code.

Avoid duplicate orders

When using your own payment button, if the customer clicks it again before they are redirected, this can create duplicate orders.

To avoid duplicate orders, disable the button until you have attempted to create an order.

Then, check response.success:

  • If true, don't re-enable the button, and proceed with the redirect.

  • If false, re-enable the button for the customer to try again.

    paymentButton.addEventListener('click', e => {
        paymentButton.addAttribute('disabled');
        if (PaymentComponent.hasErrors()) {
            let errors = PaymentComponent.getErrors();
            console.log(errors);
            return false;
        }
        createOrder(PaymentComponent.getPaymentData()).then(response => {
            if(!response || !response.success) {
                paymentButton.disabled = false;
                console.log(response);
            } else {
                PaymentComponent.init('redirection', {
                    order: response.data
                });
            }
        });
    });
    

Create an order

Create an order from your server, appending the payment_data collected from the payment component UI to the order data.

See API reference – Create order > Payment component.

4. Go live

To test the payment methods, see Testing payment methods.

When you're ready to process real payments, make the following changes:

  1. In Step 1: Add the elements, replace the test JavaScript library with the live JavaScript library:

    <script src="https://pay.multisafepay.com/sdk/components/v2/components.js"></script>
    

    Next, replace the test CSS file with the live CSS file:

    <link rel="stylesheet" href="https://pay.multisafepay.com/sdk/components/v2/components.css">
    
  2. In Step 2: Construct the component object, change the environment from test to live:

    PaymentComponent = new MultiSafepay({
        env: 'live',
        apiToken: apiToken,
        order: orderData
    });
    
  3. In Step 3: Create an order, change the test endpoint to the live endpoint:

    https://api.multisafepay.com/v1/json/orders
    

💬

Support

Email [email protected]

Top of page