> For the complete documentation index, see [llms.txt](https://docs.sensepass.com/sensepay/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sensepass.com/sensepay/transaction-api/sdk-and-iframes/javascript-ui-sdk/api/express-sdk.md).

# Express SDK

### Quick demo

Check out our demo page to see the flow in action.

{% embed url="<https://js.sandbox.sensepass.com/sp-ecom-express-sdk.html>" %}

{% hint style="info" %}
This is a checkout page example with the Express SDK with the billing & shipping information filled and the order is ready to place.

The payment options responded with the customer's information used to speed up the checkout process.
{% endhint %}

<p align="center"><img src="/files/pa31KVSkTwXXhoc9zdaA" alt=""></p>

***

### Configuration

{% hint style="info" %}
You can copy-paste the (relevant) following HTML code to your checkout page to get going.

* Note that the current widget configuration is set up to use the mock client-id - and replace it with yours.
  {% endhint %}

{% code lineNumbers="true" expandable="true" %}

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>SensePass Express SDK</title>
    <!--Set the SDK script-->
    <script src="https://js.sensepass.com/scripts/sensepass-front-end-express@1.0.0.sdk.js"></script>
</head>
<body>
    <!--Set the SDK element-->
    <sp-ecom-sdk-express></sp-ecom-sdk-express>

    <script>
        // Wait for the custom element to be defined
        customElements.whenDefined('sp-ecom-sdk-express').then(() => {
            const widget = document.querySelector('sp-ecom-sdk-express');
            
            // Initialize the widget with your configuration
            widget.props = {
                clientId: "SensePassSDKGeneralClientId", // location's client-id
                amount: "12.58",
                currency: "USD",
                logs: true, // enable SDK console logs
                methodType: "manual_capture", // or "authorize" | "tokenize"
                mode: "sandbox", // or "production"
                cssUrl: "https://js.sensepass.com/express-sdk.css", // download to customize your own css
                // Event handlers
                onReady: (detail) => console.log('SDK Ready:', detail),
                onShow: (detail) => console.log('Payment Shown:', detail),
                onPay: (detail) => console.log('Payment Data:', detail), // finalize the payment in your backend (commit request)
                onError: (detail) => console.error('Payment Error:', detail)
            };
        });
    </script>
</body>
</html>
```

{% endcode %}

***

### Payment Data

{% hint style="info" %}
Example of a response after paying with Google Pay
{% endhint %}

{% code lineNumbers="true" expandable="true" %}

```json
{
  "code": 27,
  "method": "googlepay",
  "timestamp": "2020-02-20T20:20:20.202Z",
  "transactionNumber": "1c3ff55c9d299cddbcc6d6fd929c63c1628bc25be2ab2c4c0cf87db9",
  "billingInformation": {
    "fullName": "Card Holder Name",
    "firstName": "Card",
    "lastName": "Holder Name",
    "addressLine1": "1600 Amphitheatre Parkway",
    "addressLine2": "",
    "city": "Mountain View",
    "state": "CA",
    "postalCode": "94043",
    "country": "US",
    "email": "john.doe@gmail.com"
  },
  "shippingInformation": {
    "fullName": "US User",
    "firstName": "US",
    "lastName": "User",
    "addressLine1": "1600 Amphitheatre Parkway1",
    "addressLine2": "",
    "city": "Mountain View",
    "state": "CA",
    "postalCode": "94043",
    "country": "US",
    "email": "john.doe@gmail.com"
  }
}
```

{% endcode %}

### Customization

{% hint style="info" %}
This code sample demonstrates how to customize the appearance of the Express Widget's payment buttons. Save & link this file in your HTML *after* the widget's script to ensure styles are applied.

The widget's internal CSS provides basic styling. This file allows you to override and enhance it.

Key selectors:

* .payment-btn: The main button element.
* .payment-logo: The  tag for the payment method logo.
* .payment-label: The tag for the payment method text label.

You can also target specific payment methods using the `part` attribute:

* \[part="paypal"]
* \[part="applepay"]
* \[part="googlepay"]
  {% endhint %}

{% code lineNumbers="true" expandable="true" %}

```css
/* Logo-only style with light background for visibility */
.payment-btn {
    position: relative;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    padding: 12px 20px;
    min-height: 48px;
    background-color: #ffffff;
    border: 1px solid #e0e0e0;
    border-radius: 6px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
    transition: all 0.2s ease;
}

.payment-logo {
    height: 24px;
    width: auto;
    max-width: 120px;
    object-fit: contain;
}

/* Hide the text label to show logo only */
.payment-label {
    display: none;
}

/* Hover state */
.payment-btn:hover:not([disabled]) {
    border-color: #c0c0c0;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    background-color: #f9f9f9;
}

/* Disabled state */
.payment-btn[disabled] {
    opacity: 0.5;
    cursor: not-allowed;
    background-color: #f5f5f5;
}

/* Show spinner overlay when button is not clickable (canPay = false) - initialization loading */
.payment-btn:not([data-can-pay="true"]) {
    position: relative;
}

.payment-btn:not([data-can-pay="true"])::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(255, 255, 255, 0.5);
    z-index: 10;
    border-radius: inherit;
}

.payment-btn:not([data-can-pay="true"])::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 24px;
    height: 24px;
    margin: -12px 0 0 -12px;
    border: 3px solid #e0e0e0;
    border-top: 3px solid #007bff;
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
    z-index: 11;
}

/* Payment processing state - different visual treatment */
.payment-btn[data-processing="true"] {
    position: relative;
    background-color: white;
    cursor: not-allowed;
    opacity: 1;
}

/* Disabled state when other payment is processing */
.payment-btn[data-other-processing="true"] {
    opacity: 0.5;
    cursor: not-allowed;
}

.payment-btn[data-processing="true"]::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: transparent;
    backdrop-filter: blur(3px);
    z-index: 10;
    border-radius: inherit;
}

/* Add green spinner for processing state */
.payment-btn[data-processing="true"]::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 24px;
    height: 24px;
    margin: -12px 0 0 -12px;
    border: 3px solid #e0e0e0;
    border-top: 3px solid #28a745;
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
    z-index: 12;
}

/* Spinner keyframes */
@keyframes spin {
    0% {
        transform: rotate(0deg);
    }
    100% {
        transform: rotate(360deg);
    }
}

/* Pulse animation for processing state */
@keyframes pulse {
    0%, 100% {
        opacity: 0.1;
    }
    50% {
        opacity: 0.3;
    }
}

/* Bright pulse animation for processing state */
@keyframes pulseBright {
    0%, 100% {
        opacity: 0.6;
    }
    50% {
        opacity: 1;
    }
}


/* Optional: Specific styling for individual payment methods */

/* PayPal - slightly smaller logo */
[part="paypal"] .payment-logo {
    background-color: #ffffff;
}

/* Apple Pay - ensure good contrast */
[part="applepay"] {
    background-color: #ffffff;
}

/* Google Pay - ensure good contrast */
[part="googlepay"] {
    padding-top: 8px;
    padding-bottom: 8px;
}

[part="googlepay"] .payment-logo {
    height: 32px;
}

```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.sensepass.com/sensepay/transaction-api/sdk-and-iframes/javascript-ui-sdk/api/express-sdk.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
