Skip to main content

Installation

Quick Install

This button


can be inserted into your web page and styled with the javascript and css snippets below:

Sample page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Test Page</title>
</head>
<body>
BOPP in action
<div id="bopp_button">
<div id="bopp_msg"></div>
<div id="bopp"></div>
</div>
</body>
<script type="text/javascript">

const sdk_url = "https://bopp.io/public/scripts/sdk.js";
const merchantKey = "insert your merchant key here"

//The below two lines are required
const orderTotal = 12.12;
const orderReference = "Cheetah food";

//The below settings are optional...
//You can leave them empty or find more information about these settings here: https://bopp.io
const buttonLookAndFeel = "DarkWide";
const onsuccessurl = "https://www.sample.com/success";
const oncancelurl = "https://www.sample.com/cancel";
const onfailureurl = "https://www.sample.com/failure";
const onsuccessposturl = "https://www.sample.com/listener";

const bopp_msg_alert_default_style = {

};


const buttonMsgContainer = document.getElementById("bopp_msg");

const script = document.createElement("script");
script.src = sdk_url;
script.type = "text/javascript";
script.addEventListener("load", () => {
const boppButton = BoppButton({
key: merchantKey,
container: document.getElementById("bopp"),
buttonStyle: buttonLookAndFeel,
});

boppButton.setAmount(parseFloat(orderTotal), "GBP");
boppButton.setPaymentReference(orderReference);

if (onsuccessurl.length > 0) {
boppButton.setSuccessRedirectUrl(onsuccessurl);
}
if (oncancelurl.length > 0) {
boppButton.setCancelRedirectUrl(oncancelurl);
}
if (onfailureurl.length > 0) {
boppButton.setFailRedirectUrl(onfailureurl);
}
if (onsuccessposturl.length > 0) {
boppButton.setOnSuccessPost(onsuccessposturl);
}

function showMessage(msg, success) {
if (success) {
buttonMsgContainer.innerHTML(
"The payment is successful! <br/> <b>Payment Instruction ID: " +
msg +
"</b>"
);
buttonMsgContainer.classList.add("bopp_msg_success");
return;
}
var reason = "";
if (msg.length) {
reason = "<br>Reason: " + msg;
}

buttonMsgContainer.innerHTML("The payment attempt failed!" + reason);
buttonMsgContainer.classList.add("bopp_msg_failure");
}

boppButton.setCallback(
//This is the callback function that will be called when the payment is successful
function (instId, signature) {
showMessage(instId, true);
},
function (error) {
//This is the callback function that will be called when the payment is canceled due to a non-technical issue (the payer cancels, the banks rejects, limit reached and etc.)
var reason = "";
if (error && error.hasOwnProperty("message")) {
reason = error.message;
}
showMessage(reason, false);
},
function (error) {
//This is the callback function that will be called when the payment has failed due to a technical issue (technical issue with the backend, the bank is down and etc.)
var reason = "";
if (error && error.hasOwnProperty("message")) {
reason = error.message;
}
showMessage(reason, false);
}
);

boppButton.setEnabled(true);
});

document.head.appendChild(script);

</script>
<style type="text/css">
#bopp_msg {
color: "white";
padding: "5px";
border-radius: "5px";
}

.bopp_msg_success{
background-color: "red"
}

.bopp_msg_failure{
background-color: "green"
}
</style>
</html>

Sign Up for Sandbox

To sign up to the Sandbox and get a developer API Key, you will need to give us your Name and email address. You will receive an API for the Sandbox environment via email. This will allow you to test your BOPP Checkout implementation.

Start accepting live payments

Once you are ready to accept payments on your site using BOPP Checkout, sign up for a BOPP Account. With this you will be able to access the BOPP Dashboard and generate a live API Key for your site and BOPP Checkout, you will also be able to revoke API Keys when no longer needed and review all transactions.

Installation Explained

  1. To start working with BOPP Checkout, you need to source the SDK by adding a script tag to the hosting page.
<script type="text/javascript" src="https://bopp.io/public/scripts/sdk.js"></script>
  1. Then you need to add a DOM element container with id 'bopp' that will host the BOPP Checkout:
<div id='bopp'></div>
  1. The BOPP Checkout is initialised by calling the BoppButton function which takes two required parameters:
  • The Key is the API key which is created in the BOPP Dashboard, it permissions the button to issue the payment request.
  • The container is the DOM element you created in the previous step:
const boppButton = BoppButton({
key: 'Copied Key',
container: document.getElementById('bopp')
});

Note: If you don't pass at least one of the parameters, an error is generated.

  1. You can use .setOnSuccessPost(url) to request that the SDK POSTs a message to the given URL endpoint on completion of a successful payment.

You will need to set CORS for your endpoint to use the following headers:

    Access-Control-Allow-Origin : https://bopp.io
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers : Origin, Content-Type, XMLHttpRequest, user-agent, accept, x-requested-with

The POST message will contain in the body the following parameters:

    paymentInstructionId : The system ID for the payment instruction 
reference : The reference passed to the bank associated with the payment instruction
amount : The amount padding
signature : EdDSA / JSON Web Key signature

The signature can be verified by getting the BOPP public key, which is in JSON Web Key format and using and EdDSA supporting library from https://jwt.io/libraries

  1. Using .setSuccessRedirectUrl, .setFailRedirectUrl, .setCancelRedirectUrl you are able to set the redirect URL on the Payers side, for a particular payment which will be called when the payment is finished, it should be string value. These settings are Optional. This means that the Payer will be taken to the redirect URL on payment completion, this original page hosting the BOPP Button will remain open and receive the payment complete message.
   boppButton.setSuccessRedirectUrl(SuccessRedirectUrl);
boppButton.setFailRedirectUrl(FailRedirectUrl);
boppButton.setCancelRedirectUrl(CancelRedirectUrl);

The RedirectUrl will be called with the parameter instructionId= appended. This will have a String value that represents the ID for the PaymentInstruction.

If a redirect is set, the BOPP screen at the end of the payment process will immediately redirect to the supplied URL. Otherwise the payment process will follow the default flow ending on the BOPP Payment Results Screen.

  1. Before the BOPP Checkout is clicked by the user you will need to set the parameters for the payment processing. This is also done by setting methods on the boppButton object.

Below is a list of the available methods:

MethodParametersDescription
setPaymentReferencereference (string)sets a value which will be used as a payment reference on the payment instructions set to the Payer application and then used in their banking interactions
setAmountamount (number), currency (String)Is the amount requested when the BOPP Checkout is clicked
boppButton.setPaymentReference("OrderNumber");
boppButton.setAmount(10.00, "GBP");

Once set-up, a user can click on the BOPP Checkout that will cause a paylink to be generated. It will also cause an overlay dialogue to be shown to the user. This overlay will allow the user to scan a QR code to complete the payment on a separate device, or continue on the existing device. This in turn will cause the user's banking application to load from where they can complete the payment.

During this payment processing the BOPP Checkout opens a server connection to listen for status updates from the various components completing the payment processing. After the payment is complete, the BOPP Checkout SDK will call the status callback that was previously registered via the .setCallback method.

  1. The button can be enabled / disabled using the setEnabled parameter with a boolean value.
boppButton.setEnabled(true);

The button is enabled by default.

  1. You can pass internal reference string. You can use this string to manage your application logic, this param isn't visible to user. And will returns in onPaymentSuccess and onPaymentFailed callbacks.
boppButton.setInternalReference("some#string");

Callbacks

To get the status of a payment and be able to respond to any error messages returned you can attach a callback to the boppButton variable that you have declared.

The .setCallback method will accept four parameters, onPaymentSuccess, onPaymentFailed, onError and onPaymentStatusChange.

boppButton.setCallback(onPaymentSuccess, onPaymentFailed, onError, onPaymentStatusChange);

onPaymentSuccess will be called when the payment is finished successfully it contains result object with properties:

  • reference: string - payent internal reference
  • amount: string - payment amount
  • instructionId: string - payment instruction id
  • internalReference: string - internal reference which is not visible to user and can be used for applicaion logic
function onPaymentSuccess(result) {}`

onPaymentFailed will be called when the payment fails, it contains an error object with properties:

  • code: string - error code
  • message: string - error message
  • internalReference: string - internal reference which is not visible to user and can be used for applicaion logic
function onPaymentFailed(result) {}`

Error codes:

CodeMessageDescription
301Failed to create paylinkTriggered if failed to initiate payment
302Not definedTriggered if failed to initiate payment according to server error
302Payment cancelledTriggered if payment cancelled on payer's side
303Not definedTriggered if failed to initiate payment due to server not responding
304Limit reachedTriggered if limit reached for particular account

onError will be called when an error occurs. The function will be passed two parameters, the error code and associated message. See the table below for more details on the possible errors.

CodeMessageDescription
100Not definedAPI key is incorrect or does not exist
101Amount and currency is requiredTriggered when amount or currency not passed in setAmount function
201Order number should be string typeTriggered when payment reference is not a string passed to setPaymentReference function
201Order number should be less that 19 charactersTriggered when payment reference passed to setPaymentReference function is more than 18 characters
201Order number should not contain special charactersTriggered when payment reference passed to setPaymentReference function contains special characters, in this case order number will be set as 'BOPP Transaction'
202Amount should be number typeTriggered when amount is not a number passed to setAmount function
203Currency should be string typeTriggered when currency is not a string passed to setAmount function
204Should be boolean valueTriggered when value is not a boolean passed to setEnabled function
401Redirect url should be string typeTriggered when redirect url is not a string passed to setSuccessRedirectUrl, setFailRedirectUrl, setCancelRedirectUrl functions
501Failed to find instruction idPayment finished succesfully but filed to get payment instruction id, success callback will be called without instruction id
function onPaymentSuccess () {
//Payment succeeded
}

function onPaymentFailed () {
//Handle a payment failure
}

function onError (error) {
console.log(error);
}

boppButton.setCallback(onPaymentSuccess, onPaymentFailed, onError);

When the error occurs, BOPP Checkout will call the previously passed ' onError' function in which it passes 2 parameters: code (which is the error code essentially) and message (short error description). For instance:

.onError({ code: '200', message: 'order number should be string type' })

onPaymentStatusChange will be called when payment status changed and passes strin parameter. All statuses described in table below

StatusDescription
InitiatedQR code was generated
ConnectingToBankStarted connecting to bank
PaymentInProcessStarted payment process
PaymentCompletedPayment was successful
PaymentFailedPayment was not successful
AbortedPayer has closed modal

Managing Page Level Bank Interactions

Communication between your payment page and the Bank which is handling the users payment needs to be done via top level page redirection. For security reasons banks do not allow embedded components (e.g. Iframes) to initiate open banking interactions. They also require a pre-registration of the redirect page they will call back to upon payment authorization.

By default these interactions are initiated on a separate browser tab, so that we can undertake this redirect handshake on our own domain.

If you want to streamline the user's interactions with your page Bopp button has an extension API which allows you to handle this interaction directly from your own page.

To achieve this you need to perform the following operations.

  1. Initiate the bopp button as described above
  2. Call the setBankCallback method on the button API to the page you want to receive the bank call back on
  3. Register a callback using setOnAuthUrl so we can pass you the bank's authorization url when it is ready for processing
  4. Upon receipt of the bank's authorization url in your callback, you should redirect your top level page location to the supplied url
  5. The bank will now process the payment for the paying user and then redirect back to the url you supplied in step 2.
  6. On your redirected callback page back you need to pass locator for the page to the bopp button sdk by calling the processBankCallbackUrl. It will then parse the parameters from the bank, complete the payment and call the completion callbacks outlined above to indicate success or failure.

Details of the functions you need to invoke to operate this flow are described below:

MethodParametersDescription
setBankCallbackUrlurlSets the callback URL for your page return which will be appended to the bank authorization to initiate the return processing from the payers bank
setOnAuthUrlfunction(url)Identifies the callback function which will get invoked by the bopp button sdk to initiate transfer to the bank for payment processing
processBankCallbackUrlurlInitiates the completion of the bank payment flow between the BOPP button sdk and the payers bank using the authorization parameters returned by the bank. Some banks use '#' and some use '?' to pass these parameters.

Usage examples:

boppButton.setBankCallbackUrl("https://example.com/callback");

// where auth url is e.g. https://democonsentapp.netlify.app/democonsentapp?arg=https://bopp.dev/ucb?code=accept&state=7meEXh892V4BMOJ9DJ4bKK5P-21PnAq-consentid
// democonsentapp.netlify.app will be replaced with the banks open banking access api endpoint

boppButton.setOnAuthUrl(function (authUrl) {
window.location = authUrl
});

// where the url is e.g.
// https://example.com/callback#code=accept&id_token=jvfsnvfkunkfu2433&state=7mZMu5w8p1vkiJjJpxCWtdGN-5zvbbilUr7GwOVu7uHZCRVASciJyctDmbHAsQ5smWC-consentid

boppButton.processBankCallbackUrl(window.location)

Setting Callback Parameters

The example callback URL above is a plain URL https://example.com/callback. If this URL has '?' query parameters, for example https://example.com/callback?param0=val0&param1=val1 set on it these will be passed back to the caller on the bank not redirect.

The interaction between the bank and the bopp network uses the fragment element in the URL (after the #), which will not be sent to the backend server by the browser on redirect but the parameters passed into the boppButton.setBankCallbackUrl will be.

Some banks apply limits to the length of the data they are prepared to receive on the encoded auth url they process. So it may be necessary to limit the length of data being passed. A typical limit we have seen in testing is 1024 bytes, but a number like 256 bytes may be a safer length constraint.

Styling

BOPP Button is provided in 4 possible styles: DarkWide, DarkShort, LightWide, LightShort. If buttonStyle parameter is not passed, the default style will be 'DarkWide'. You can also set a Custom style where you can supply your own button design.

DarkWide
DarkShort
LightWide
LightShort
Parameter for the init function of the button should be:
const boppButton = BoppButton({
key: 'cri:BDeMFufilAUaeAsc1aP1uMzFStttl5m2',
container: boppBtn,
buttonStyle: 'DarkShort'
});

Removing payer Launch screen

To remove payer launch screen and immediately proceed with payment, set the showPayerLaunchScreen function parameter to 'false'.

boppButton.showPayerLaunchScreen(false)

Custom Button Styling

To use custom button styling, set the buttonStyle parameter in the init function to 'Custom'.

buttonStyle: 'Custom'

Anything inside the <div> tag that has been assigned as the BOPP container will act as a button to launch the payment flow.

You can assign a callback that will allow you to modify the Button according the status of the payment process.

boppButton.setCallback(onPaymentStatusChange);

There are 5 possible status that can be returned:

  • Initiated,
  • ConnectingToBank,
  • PaymentInProcess,
  • PaymentCompleted,
  • PaymentFailed,
  • Abort
function onPaymentStatusChange(status) {
console.log(status);
bopp.innerHTML = getButtonForStep(status);
}

function getButtonForStep(status) {
const desktop = window.screen.width > 1000;
if(!desktop) {
if(status === 'Initiated') {
return `<div style="background-color: #3bfee1; padding: 5px">
<p>Button for step=Initiated</p>
</div>`;
} else if(status === 'ConnectingToBank') {
return `<div style="background-color: blue; padding: 5px">
<p>Button for step=connecting to bank</p>
</div>`;
} else if(status === 'PaymentInProcess') {
return `<div style='background-color: #ee00ff; padding: 5px'>
<p>Button for step=Payment In Process</p>
</div>`;
} else if(status === 'PaymentCompleted') {
return `<div style='background-color: #FEE600; padding: 5px'>
<p>Button for step=Payment Completed</p>
</div>`;
} else if(status === 'PaymentFailed') {
return `<div style='background-color: coral; padding: 5px'>
<p>Button for step=Payment Failed</p>
</div>`;
} else {
return bopp.innerHTML;
}
}
}

In the example above, the desktop value

const desktop = window.screen.width > 1000;

is used to determine if the page is being viewed on a mobile device or desktop. By default, on the desktop the button does not change through the payment process as that is communicated on the payment overlay, whilst on mobile we update the button.

Errors

The errors fall into three categories, missing parameters when creating a button object in the page, mismatched types when the parameter type is not sent or passed correctly and errors associated with the Paylink Processing. The errors, reporting number and messages are listed below.

ErrorMessageDescription
100Not definedAPI key is incorrect or does not exist
101Amount and currency is requiredTriggered when amount or currency not passed in setAmount function
201Order number should be string typeTriggered when payment reference is not a string passed to setPaymentReference function
202Amount should be number typeTriggered when amount is not a number passed to setAmount function
203Currency should be string typeTriggered when currency is not a string passed to setAmount function
204Should be boolean valueTriggered when value is not a boolean passed to setEnabled function
301Failed to create paylinkTriggered if failed to initiate payment
302Not definedTriggered if failed to initiate payment according to server error
302Payment cancelledTriggered if payment cancelled on payer side
303Not definedTriggered if failed to initiate payment according to server not responding
304Limit reachedTriggered if limit reached for particular account