# Frontend JS

**Step 1:** Include our JS in your HTML page

Add the following code just before the closing body tag on your checkout page:

```html
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://gateway.breathepay.co.uk/sdk/web/v1/js/hostedfields.min.js"></script>
```

**Step 2:** Display the hosted payment fields with BreathePay

Add the following HTML form where you want to display the hosted payment field:

```html
<form id="card-element" method="post" novalidate="novalidate" lang="en" >
    <input id="cardDetails">
</form>
```

Add a submit button that we'll use to submit the payments form later (place this outside of the above form):

```html
<button type="button" id="submitButton">Pay Now</button>
```

Add a hidden form that will be used to submit the required information to your backend

```html
<form id="paymentForm" action="YOUR_CHECKOUT_URL" method="post" style="opacity: 0;"> 
    <input type="text" id="token" name="paymentToken">
    <input type="text" id="browserInfo" name="browserInfo">
</form>
```

**Step 3:** Add your own Javascript file that gathers the required information and submits it to your backend

```html
<script src="/js/checkout.js"></script>
```

<pre class="language-javascript"><code class="lang-javascript"><strong>//checkout.js
</strong><strong>var form;
</strong>var cardelem;
var paymentForm;

var browserInfo;
var token;

document.addEventListener('DOMContentLoaded', function() {
    setupCardForm();
});

function setupCardForm() {
  cardelem = document.getElementById('card-element');
  paymentForm = document.getElementById('paymentForm');

  var submit = document.getElementById('submitButton');

  browserInfo = document.getElementById('browserInfo');
  token = document.getElementById('token');

  //Set up and display the hosted payment field using the BreathePay JS File
  if(cardelem &#x26;&#x26; submit) {
    form = new window.hostedFields.classes.Form(cardelem, {
        "autoSetup":true,
        "autoSubmit":true,
        "tokenise":".add-to-token",
        "stylesheets":"#hostedfield-stylesheet",
        "fields":{
          "any":{
            "nativeEvents":true
          },
          "cardDetails":{
            "selector":"#cardDetails",
            "style":"font: 400 16px Helvetica, sans-serif;",
            "placeholder": "0000 0000 0000 0000|00/00|000"
          }
        },
        "classes":{"invalid":"error"},
        "merchantID": 'YOUR_MERCHANT_ID'
    });
    
    //Listed for the submit button click to gather information
    submit.addEventListener('click', getCardDetails);
  }
}

function getCardDetails() {
  form.validate().then(function(valid) {
  
    //Use the BreathePay JS File to validate customer payment information
    if(valid) {
      //Sends the customer payment information to the BreathePay API and returns a payment token
      form.getPaymentDetails().then(function(details) {
        if(details.success) {
        
          //Set the payment token for use in your backend 
          token.value = details.paymentToken;
          
          //Get the users browser info and attaches that to the frontend form
          browserInfo.value = JSON.stringify(getBrowserInfo());
          
          //Submit the frontend form
          paymentForm.submit();
        } else {
          var error = details.defaultErrorMessage;
          //Could not get payment token from BreathePay API, display your error message
        }
      });
    } else {
      //Display your error message
    }
  });
}

//Get the required browser information used to securely make payments
function getBrowserInfo() {
  let browserInfo = {};

  var screen_width = (window &#x26;&#x26; window.screen ? window.screen.width : '0');
  var screen_height = (window &#x26;&#x26; window.screen ? window.screen.height : '0');
  var screen_depth = (window &#x26;&#x26; window.screen ? window.screen.colorDepth : '0');
  var identity = (window &#x26;&#x26; window.navigator ? window.navigator.userAgent : '');
  var language = (window &#x26;&#x26; window.navigator ? (window.navigator.language ? window.navigator.language : window.navigator.browserLanguage) : '');
  var timezone = (new Date()).getTimezoneOffset();
  var java = (window &#x26;&#x26; window.navigator ? navigator.javaEnabled() : false);

  browserInfo.deviceIdentity = identity;
  browserInfo.deviceTimeZone = timezone;
  browserInfo.deviceCapabilities = 'javascript' + (java ? ',java' : '');
  browserInfo.deviceAcceptLanguage = language;
  browserInfo.deviceScreenResolution = screen_width + 'x' + screen_height + 'x' + screen_depth;

  return browserInfo;
}
</code></pre>

**Step 4:** Add a custom style sheet for your payment fields

Add a CSS file and link to it in the HEAD section of your HTML page

```html
<link rel="stylesheet" id="hostedfield-stylehseet" type="text/css" href="/css/breathepay/style.css" />
```

Add custom CSS styling to your stylesheet:

```css
iframe {
  max-height: 42px;
}

.hostedfield-wrapper {
  width: 100%;
  padding: 4px 16px;
  border-radius: 4px;
  background-color: var(--input-background-colour);
  border: none;

  box-shadow: var(--input-box-shadow);
  -webkit-box-shadow: var(--input-box-shadow);
  -moz-box-shadow: var(--input-box-shadow);

  font: 600 16px Helvetica, sans-serif;
}

.cardDetails {
  font: 600 16px Helvetica, sans-serif !important;
}

#cardDetails-hostedfield {
  font: 600 16px Helvetica, sans-serif !important;
}

.hf-invalid {
  border: 1px solid red;
}

.hostedform {
  background-color: black;
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://breathepay.gitbook.io/breathepay-developer-docs/payments-api/frontend-js.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
