Checkout Web SDK
Include stylesheet and SmartPay JavaScript Library
Include SmartPay Stylesheet
The SmartPay Stylesheet Generator is used for customizing SmartPay to match the brand's styling requirements. Contact your dedicated Product Solution Specialist to grant you the access. The Stylesheet generator can be accessed here: https://smartpay.cons.stylesheet.jpmmps.com.
The SmartPay Stylesheet (smartpay-style.css) file must be hosted on your server.
Please make sure that SmartPay is allowed to access resources related to the SmartPay Stylesheet (e.g. fonts) by configuring cross-origin resource sharing in your webserver (Access-Control-Allow-Origin
).
SmartPay Widget Components are rendered using SmartPay CSS classes. This assumes that the SmartPay Stylesheets are already loaded by the merchant site. The styles can be downloaded from the resource links above.
There is no support right now for more granular styling.
Include SmartPay WebSDK
<script src="https://.../smp-bundle.js" type="text/javascript"></script>
Please check Sandbox vs. Production page for latest url.
Render SmartPay Widget
Create containers
<div id="selector-container"></div>
<div id="selection-container"></div> <!-- optional -->
<div id="button-container"></div> <!-- optional -->
<div id="registration-continue-button-container"></div> <!-- optional -->
<div id="payment-continue-button-container"></div> <!-- optional -->
Container | Description | Mandatory |
---|---|---|
selector-container | Root container where the payment options selector will be rendered. In multipage integration, it is mandatory only for the first initialization, until the payment option is selected. | Yes |
selection-container | Root element of the container where the current selected payment option information will be rendered. Use this container if you want to display the selected payment option on a confirmation page. | No |
button-container | Html-container where the submit button will be rendered. Use this container if you need to extract the button outside the smp-panel. | No |
registration-continue-button-container | Html-container for rendering the button which triggers the Guest Payment flow. It uses a localization label "button:continue-guest". | No |
payment-continue-button-container | Html-container for rendering the button which triggers the registration of a new payment option. It uses a localization label "button:continue-registration". | No |
Initialize widget instance
Loading the bundle will initialize the SmartPay app instance and attach it to the window object.
const app = window.SmpLibrary.SmartPayAppInstance;
Render widget on single page
void renderWidget ( options );
Calling 'renderWidget' function will trigger the SmartPay widget to load the valid payment methods for the given payment checkout token and render it into the provided container(s).
// Simple CIT
app.renderWidget({
paymentCheckoutToken: checkoutToken,
container: "smp-panel",
successHandler: function(data) { ... },
errorHandler: function(errorCode, error) { ... },
paypalButtonStyle: {
layout: 'vertical',
color: 'blue',
shape: 'rect',
label: 'paypal'
}
});
// MIT and detailed CIT (optional)
app.renderWidget({
subscriptionCheckoutToken: checkoutToken,
container: "smp-panel",
successHandler: function(data) { ... },
errorHandler: function(errorCode, error) { ... },
onBeforeSubmit: function(data) { ... },
onBeforeDeleteSpo: function(data) { ... },
paypalButtonStyle: {
layout: 'vertical',
color: 'blue',
shape: 'rect',
label: 'paypal'
}
});
Render widget on multi page
void renderMultiPageWidget ( options );
renderMultiPageWidget description
Calling 'renderMultiPageWidget' function on any page of your multi-step payment journey will trigger the SmartPay widget to render the valid component into the provided container(s). There are three main components that can be rendered separately:
- Available payment methods selector
- Current selected payment method
- Buttons
renderMultiPageWidget sample
// Checkout Page. Render Selector
app.renderMultiPageWidget({
paymentCheckoutToken: checkoutToken,
container: "smp-panel",
successHandler: function(data) { ... },
errorHandler: function(errorCode, error) { ... }
});
// Overview Page. Render Selection
app.renderMultiPageWidget({
paymentCheckoutToken: checkoutToken,
selectedPaymentDiv: "selection-container",
errorHandler: function(errorCode, error) { ... }
});
// Confirmation Page. Render Button
app.renderMultiPageWidget({
paymentCheckoutToken: checkoutToken,
submitButtonDiv: "button-container",
successHandler: function(data) { ... },
errorHandler: function(errorCode, error) { ... },
onBeforeSubmit: function(data) { return true; }
});
Configuration Options
Both rendering methods require the configuration object containing the parameters reflecting your rendering choice.
Field | Description | Data Type | Mandatory |
---|---|---|---|
paymentCheckoutToken | Use the checkoutToken received in your checkout API response. | string | Yes, if 'subscriptionCheckoutToken' is not provided |
subscriptionCheckoutToken | Alternatively to 'paymentCheckoutToken', provide checkoutToken received as part of the response of Create Subscription Checkout API. | string | Yes, if 'paymentCheckoutToken' is not provided |
container | HTML element id of the selector-container. In multipage scenario, it is mandatory only for the first initialization, until the payment option is selected. | string | Yes |
selectedPaymentDiv | HTML element id of the selection-container. | string | No |
submitButtonDiv | HTML element id of the button-container. | string | No |
guestPaymentContinueButtonContainer | Id of the html element used as a container for rendering the button which triggers the Guest Payment flow. It uses a localization label "button:continue-guest". | string | No |
registrationContinueButtonContainer | Id of the html element used as a container for rendering the button which triggers the registration of a new payment option. It uses a localization label "button:continue-registration". | string | No |
successHandler | Use this function to trigger any logic to be executed upon the transaction having been successfully processed. | function | Yes |
errorHandler | Use this function to trigger any logic to be executed upon the transaction having been unsuccessfully processed. | function | Yes |
onBeforeSubmit | Optional function to handle additional checks before payment gets started. Callback is triggered by end-user click on 'Confirm' button on the widget and desired payment method is selected. | function | No |
onBeforeDeleteSpo | Optionally function to handle additional checks before selected stored payment option gets deleted. Callback is triggered by end-user clicks 'Delete' button near the stored payment option he decided to remove. | function | No |
paypalButtonStyle | Optional object which contains json property with certain parameters to customize PayPal button look and feel. | object | No |
onSelectionChanged | Optional function to return selected payment option. Callback is triggered by end-user selecting a payment option on the widget. | function | No |
deleteSpoEnabled | When false specified, hides 'Delete' button for stored option. Otherwise, if true passed or undefined, then 'Delete' stored option button is available. | boolean | No |
defaultSpoEnabled | When 'false' specified, makes 'Set Default' button for stored option invisible. If 'true' passed or undefined, then button shown for stored payment option. | boolean | No |
disableSubmitButton | When set to "true" the submit button (CONTINUE PAYMENT/REGISTRATION, PAY) will be always displayed as disabled in Single Page mode, when the corresponding action is forbidden. This option does not affect the widget behaviour in multipage mode. When set to "false" or not submitted, the submit button will be hidden, when the corresponding action is forbidden | boolean | No |
onWidgetRendered | Whenever the widget is successfully loaded, this JS callback will be visible in the console log. | function | No |
See Web SDK Handler for further details on the available functions.
"paypalButtonStyles" expects a JSON object, which can be created using the documentation provided on the official Paypal Developer Portal.
"onWidgetRendered" Optional Callback
The "onWidgetRendered" callback is an optional JavaScript function that signals when the SmartPay widget has been successfully loaded and rendered in the user's browser. This callback is particularly useful for enhancing the integration's reliability on slower connections, ensuring that merchants are informed when the widget is ready.
Upon each successful render of the SmartPay widget, the "onWidgetRendered" callback is triggered. This callback is logged and returned to the merchant's website, confirming that the widget is operational. In scenarios where there might be network delays or slow connections, merchants can leverage this callback to implement additional UI elements, such as a loading icon or message, to inform users that the transaction process is still ongoing.
To view the "onWidgetRendered" callback information in the Event Log within the SDK Testing Tool, ensure that the "Handle onWidgetRendered callback" checkbox is enabled. This will allow you to monitor and verify the callback during the testing phase.
For further details on how to handle the "onWidgetRendered" callback, refer to the Widget Rendered Handler.
Visual Indication for Expired Widget Session
When the checkout session in the SmartPay widget expires, the widget notifies the merchant's front-end using a JavaScript callback which allows the merchant to handle the session expiration in their application. If the merchant does not handle this event, the widget will automatically grey out all buttons, making them non-clickable, preventing any further interactions with the expired session. Additionally, the widget calculates the session’s expiration time based on its creation date, and an error callback is sent to the merchant’s system when the checkout session or transaction ID expires with the errorCode = ERROR_CHECKOUT_TIMEOUT
. This behavior prevents users from interacting with an expired session and avoids potential errors during checkout. The expiration time is now available as a new property (checkoutExpirationTime
) in the response of the GET UI Configuration API.
Introduce success handling
When payment data has been submitted and process by payment provider, user journey is completed. SmartPay widget notifies merchant's web-site about it via 'successHandler' callback function which needs to be provided.
Once received, actual transaction status should be check via getPaymentStatus API. To differentiate between regular payment completed and payment option registered, use 'kind' value provided in data object.
function successHandler(data){
if (data.kind === "CALLBACK"){
// process payment completed
// Requests transaction status via Get Payment Status API
}
if (data.kind === "ADD_METHOD_CALLBACK"){
// optionally process payment option registration.
// Note: there is no any payment processed yet, no need to check status.
}
}
app.renderWidget({
paymentCheckoutToken: checkoutToken,
container: "smp-panel",
successHandler: successHandler
});
Introduce error handling
Errors in the SmartPay Widget need to be handled through the callback function provided into the renderWidget method. The errorCode parameter contains the actual error code as per the table below. The second parameter of the callback provides the exact message of the error, to be used in debugging and as reference for our customer support.
function errorHandler(code, message) {
console.error(code + ': ' + message);
// handle the error
// Requests transaction status via Get Payment Status API
}
app.renderWidget({
paymentCheckoutToken: checkoutToken,
container: "smp-panel",
successHandler: successHandler,
errorHandler: errorHandler
});
Error code | Description | Consumer to select another payment method and retry |
---|---|---|
ERROR_INIT_PAYMENT | Error on payment initialization, consumer need to choose a different payment option. | Yes |
ERR_CONFIG | Error while loading payment methods configuration or widget. | No |
ERROR_INVALID_INPUT | Invalid configuration passed to renderWidget method. | No |
ERR_PAYMENT_CALLBACK | Payment failed during Authorization or Capturing. This is a hard failure, recreation of transaction is required. | No |
ERROR_INIT_STORE_PAYMENT_OPTION | Error while storing payment option, consumer need to choose a different payment option. | Yes |
ERROR | Any other unhandled error. | No |
ERROR_CHECKOUT_TIMEOUT | checkoutToken or transactionId is expired. Refer here for more details. | No |
Please associate the transactionId
, checkoutToken
and possible error messages with your business transaction / order inside your systems and make it available to your support / operation staff. It will be valuable input for any ticket to our support team.
In rare cases your main page is not receiving any callback due to your consumer leaving the journey by closing the page.
Depending on your consumers interactions, the following scenarios are possible:
- Consumer closed child page and continues journey on main page with clicking again on "Confirm / Pay now":
- If the previous attempt was unsuccessful, the payment can be completed normally.
- If the previous attempt was successful, you receive the callback "service error: {"message":{"message":"There's already an active payment associated with transactionId [xyz]"}}". This message needs to be handled similar to any other callback using Get Transaction Status API
- Consumer leaves entire journey and is also not returning to main page:
- If you do not use auto-capture, no further actions needed.
- If you use auto-capture, please use Get Transaction Status API to verify that no payment was made.
Introduce payment option management for MIT and guest
This callback is being triggered, when a payment method has been selected by the end-customer in the SmartPay widget and he/she clicks on 'Confirm' button. It provides the stored payment option reference, which is to be used in MIT process.
Promise<boolean> | boolean onBeforeSubmit ( data )
SmartPay widget will provide 'data' object into the callback function as an argument. Depending on the selection which end-user made in selector area, the 'data' object can have two sets of data described in tables below.
Stored payment option selected
Parameter | Details |
---|---|
data | - |
transactionId | Checkout token associated with the transaction, if any. |
name | Display name of the payment option which has been stored. |
code | Code of the payment option which has been stored. |
carrierNumber | Masked carrier number of the payment instrument which has been stored. E.g.: 401288****1881 |
isDefault | Flag showing whether the stored payment option was chosen by the consumer to be the default one. |
reference | Stored payment option reference, to be used as input for MIT authorize API method. |
isExpired | In case of CC, shows whether the card is expired or not. |
expiryDate | When stored payment option belong to 'CC' group, this value provides the expiration date of the card. For non-CC payment methods value is empty string. Format: MM/YYYY |
storedPaymentOptionData | Contains payment method specific information used for storing the payment option. Currently used for SEPA only. |
mandateReference | SEPA mandate reference. |
mandateSignedDate | Mandate signature date, format: YYYY-MM-DD |
mandateSignedTime | Mandate signature time, format: HHmmss |
Guest payment option selected
Parameter | Details | |
---|---|---|
data | - | - |
transactionId | Checkout token associated with the transaction. | |
name | Display name of the payment option which has been selected. | |
code | Code of the payment option which has been selected. |
Return value
Return value type: Promise<boolean> | boolean
Return value description: If callback function returns true, the the payment need to be continued. If callback function returns false or non-boolean value or undefined, the the payment need to be prevented.
Complete integration sample
(function () {
// process payment completed unsuccessfully or not started
function errorHandler(errorCode, error) {
// handle failed payment here
console.error({code: errorCode, message: error});
}
// process payment completed successfully
function successHandler(data) {
console.log(JSON.stringify(data));
if (data.kind === "CALLBACK"){
// process payment completed
// Requests transaction status via Get Payment Status API
}
if (data.kind === "ADD_METHOD_CALLBACK"){
// optionally process SPO registration.
// Note: there is no any payment processed yet, no need to check status.
}
}
function tryRenderPaymentForm(checkoutToken) {
app.renderWidget({
paymentCheckoutToken: checkoutToken,
container: "selector-container",
submitButtonDiv: "button-container",
selectedPaymentDiv: "selection-container",
successHandler: successHandler,
errorHandler: errorHandler,
onBeforeSubmit: function(data) { return true; },
onBeforeDeleteSpo: function(data) { return true; },
onWidgetRendered: function(data) { return true; }
});
return true;
}
// Loading the bundle will initialize the SmartPay app
// instance and attach it to the window object.
const app = window.SmpLibrary.SmartPayAppInstance;
document.getElementById("checkout-button").addEventListener("click", function (e) {
if (e.target) {
// provide here paymentCheckoutToken received from back-end
tryRenderPaymentForm(checkoutToken);
}
});
})();