Frontend Integration of Credit Card Iframe

To integrate credit card payment into your custom checkout you need to use our credit card iframe ( https://cc.secupay.com/ ). Your page needs a button to establish the communication to our iframe, to make the user submit the form, and to respond on iframe height changes or returned data. When the data is valid, you will use it to create a Payment Container in a later step.

This is an example implementation, that helps you to understand this:

HTML
<!DOCTYPE html>
<html>
<head>
<title>CC Iframe Example</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
body {
font-family: sans-serif;
}
</style>
</head>
<body>
<h1>CC Iframe Example</h1>
<div style="max-width: 700px">
<iframe id="iframe" src="https://cc.secupay.com" width="100%" height="400px" style="border: 1px dashed lightblue;"></iframe>
</div>
<form>
<button id="submit-button" type="button">Confirm</button>
</form>
<script>
 
const IFRAME_ORIGIN = 'https://cc.secupay.com';
const iframeElement = document.getElementById('iframe');
const iframeContentWindow = iframeElement.contentWindow;
 
/**
* Set iframe parameters
*/
window.addEventListener('load', function (e) {
console.info('init CC iframe');
// Set owner (optional)
iframeContentWindow.postMessage(
{
action: "set-owner",
owner: "Max Mustermann"
},
IFRAME_ORIGIN
);
 
// Set theme
iframeContentWindow.postMessage(
{
action: "set-theme",
theme: 1, // 0 = secupay, 1 = custom
},
IFRAME_ORIGIN
);
 
 // Set language (optional)
iframeContentWindow.postMessage(
{
action: "set-lang",
lang: "en"
},
IFRAME_ORIGIN
);
}, false);
 
/**
* Respond on iframe messages
*/
window.addEventListener('message', function (e) {
 
// Check origin
if (e.origin !== IFRAME_ORIGIN) {
console.warn('bad origin ' + e.origin);
return;
}
 
switch(e.data.action) {
// Iframe height changed. This is raised on load, and after validation.
case 'cc-iframe-height':
console.info('new iframe height ' + e.data.documentHeight);
iframeElement.height = e.data.documentHeight + 'px';
break;
// Iframe sends data. These may be valid or not.
case 'prepared-cc-data':
console.info('credit card data', e.data.data);
break;
default:
console.warn('unknown message ' + e.data.action, e.data);
break;
}
}, false);
 
/**
* Handle submit button
*/
document.getElementById('submit-button').addEventListener('click', function () {
console.info('clicked button');
// Make CC iframe validate the form, and send back the data
iframeContentWindow.postMessage({ action: "get-cc-data" }, IFRAME_ORIGIN);
});
 
</script>
</body>
</html>

(Download: test_cc_iframe.html)

This is what it looks like in your browser:

images/download/attachments/97380224/image2021-1-5_15-45-5.png

On a small mobile device:

images/download/thumbnails/97380224/image2021-1-5_15-45-33.png

The thin dashed border around the iframe is only used to visualize the iframe border, and the change of dimensions while you play with it.

In line 23-25 of our HTML we have defined a symbolic constant for the iframe origin, and two fix objects to access the iframe and its content window more conveniently. The iframe origin needs to be passed to authorize the cross-origin communication, or to validate the message origin.

You can display the form in a compact view and omit the card holder field by adding some URL parameters to the iframe URL:

Iframe URL

Display

https://cc.secupay.com

traditional view

https://cc.secupay.com?view=compact&owner=true

compact mode with field for card holder

https://cc.secupay.com?view=compact&owner=false

compact mode without field for card holder

You cannot omit the card holder in the traditional view.

After this we register three important handlers:

  • to initialize the CC iframe with a few data after it is loaded (lines 27-59);

  • to respond on CC iframe messages (lines 61-89);

  • to respond on our button and forward it to the CC iframe (lines 91-99).

The handler to initialize the iframe is called at the beginning. We pre-fill the name of the card holder with "Max Mustermann", change the theme, and set the language to English (en). All three are optional.

Action

Parameter

Value

set-owner

owner

String with owner name, for instance "Max Mustermann"

set-theme

theme

  • 0 for secupay default

  • 1 for only underlined form elements

set-lang

lang

  • de German

  • en English

You can also post these values later, but with the exception of set-lang this doesn't make much sense .

The handler to respond on iframe messages (lines 61-89) first checks for the correct origin. After this it responds to the two types of messages that can occur:

  • cc-iframe-height asks the main window to change the iframe height. It is up to you to do this more softly.

  • prepared-cc-data asks the main window to process the iframe data. You would check whether everything is OK. If so, you would use the data to create the Payment Container.

Here is an example JSON structure of the returned data. It is taken from e.data.data at line 82 of our above example, and it shows a VISA card for Max Mustermann, valid thru 12/2025:

JSON
{
"owner": {
"value": "Max Mustermann",
"isValid": true,
"errorMessage": ""
},
"cardNumber": {
"value": "4111XXXXXXXX1111",
"isValid": true,
"company": "VISA",
"errorMessage": ""
},
"expDate": {
"value": "12/25",
"isValid": true,
"errorMessage": ""
},
"encryptedData": {
// ...
},
"allFieldsAreValid": true
}

You will never receive the plain card number nor the CVC code.

Usually you would only check whether allFieldsAreValid is true (last line of the JSON above). If so, you can go on with the payment authorization. If not you would wait for the user to correct his data, and press the submit button again.

Here an example with validation errors:

JSON
{
"owner": {
"value": "Max Mustermann",
"isValid": true,
"errorMessage": ""
},
"cardNumber": {
"value": "4111XXXXXXXX1112",
"isValid": false,
"company": "",
"errorMessage": "This is not a valid card number"
},
"expDate": {
   "value": "12/25",
"isValid": true,
"errorMessage": ""
},
"encryptedData": {
// ...
},
"allFieldsAreValid": false
}

Here a typical series of events:

images/download/attachments/97380224/image2021-3-23_14-20-46.png

The best way to understand how this works, is to take the HTML example above, run it in your browser, and observe the JavaScript console.