Payment form SDK
SmartPay offers a lightweight Web SDK that provides a simple solution to collect credit card data. The integration is similar to the regular Checkout WebSDK, i.e. renderWidget method triggers seamless credit card data collection form rendering and accepts the following options:
- html-container id
- js-callbacks: success/error
- styling options
Payment Form SDK supports custom styling and all payment flows: guest payment, storing a new payment option and CIT-stored payment.
In case of CIT-Stored payments, stored payment option selection should be provided by integrator.
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.
<link href="smartpay-style.css" rel="stylesheet">
The SmartPay Stylesheet file must be hosted on your server.
Please make sure SmartPay can 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. Contact your Product Solution Specialist for the SmartPay Frontend Library.
Include SmartPay WebSDK
<script src="https://.../light-sdk/smp-bundle.js" type="text/javascript"></script>
Please check Sandbox vs. Production page for latest URL.
Render SmartPay Widget
Create containers
<div id="main-container"></div>
Loading the bundle will initialize the SmartPay app instance and attach it to the window object.
const app = window.SmpLibrary.SmartPayAppInstance;
Render widget
void renderWidget ( options );
Calling 'renderWidget' function will trigger the SmartPay to render the credit card payment form for the given payment checkout token into the provided container(s).
// Guest CIT
app.renderWidget({
paymentCheckoutToken: '<payment checkout token here>',
container: '<html container id here>',
paymentFormOnly: true,
purpose: 'PAYMENT_TRANSACTION',
paymentOptionCode: 'CC',
successHandler: function (data) {...},
errorHandler: function (errorCode, error) {...}
});
// Card-on-File Registration for MIT
app.renderWidget({
subscriptionCheckoutToken: '<subscription checkout token here>',
container: '<html container id here>',
paymentFormOnly: true,
purpose: 'REGISTRATION',
paymentOptionCode: 'CC',
successHandler: function (data) {...},
errorHandler: function (errorCode, error) {...}
});
// CIT-Stored (one-click payment)
app.renderWidget({
paymentCheckoutToken: '<payment checkout token here>',
container: '<html container id here>',
paymentFormOnly: true,
purpose: 'PAYMENT_TRANSACTION',
storedPaymentOptionReference: '<stored card on file reference here>'
successHandler: function (data) {...},
errorHandler: function (errorCode, error) {...}
});
Configuration Options
The rendering method requires 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, provide paymentOptionCode |
subscriptionCheckoutToken | Alternatively to 'paymentCheckoutToken', provide subscriptionCheckoutToken received as part of the response of Create Subscription Checkout API to register new payment card. | string | Yes, if 'paymentCheckoutToken' is not provided, and purpose is Registration |
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 |
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 |
paymentFormOnly | The parameter shows if the payment selector page should be rendered or not. | boolean | No |
paymentOptionCode | The payment option code associated with the payment option chosen by the customer. Possible values:
| enum | Conditional (required if:
|
storedPaymentOptionReference | The stored payment reference showing the registered payment option. Only for payment to distinguish between 'guest' and 'CIT Stored flow' | string | Conditional (required if: purpose=PAYMENT_TRANSACTION and paymentOptionCode=null and paymentFormOnly=true) |
purpose | Indicates the purpose of the checkout. Possible values:
| enum | Conditional (required if paymentFormOnly=true) |
Introduce success handling
When payment data has been submitted and processed by payment provider, the user journey is completed. SmartPay widget notifies merchant's website about it via 'successHandler' callback function which needs to be provided.
Once received, the actual transaction status should be checked 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
// Request transaction status via Get Payment Status API
// Link: https://documentation.jpmmps.com/docs/smartpay/get-payment-status-api/
}
if (data.kind === "ADD_METHOD_CALLBACK"){
// Process Card-on-File registration completed
// Request updated payment options list via 'Get Payment Options' API.
// Link: https://documentation.jpmmps.com/docs/smartpay/payment-option-management-apis/get-payment-options/
// Note: there is no any payment processed yet, no need to check status.
}
}
// Render payment form for Card-on-File Registration for MIT
app.renderWidget({
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
// Request transaction status via Get Payment Status API
// Link: https://documentation.jpmmps.com/docs/smartpay/get-payment-status-api/
}
app.renderWidget({
...
...
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.
Complete integration sample
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://sdk.cons.smartpay.jpmmps.com/light-sdk/smp-bundle.js"></script>
<link rel="stylesheet" type="text/css" href="https://your-domain.com/style.css" class="none_scoped">
<meta charset="UTF-8">
<title>Light SDK integration</title>
</head>
<body>
<div style="display: flex;justify-content: center;margin-top: 12px">
<div style="display: flex;flex-direction: column;width: 80%">
<div style="display:flex"><label for="checkoutTokenId" style="margin-right: 4px">CheckoutToken</label><input
type="text"
id="checkoutTokenId"
style="width: 100%">
</div>
<input type="button" style="margin: 6px 0 6px 0" onclick="renderForm()" value="Render payment form">
<div id="main-container"></div>
</div>
</div>
</body>
<script>
function renderForm() {
const app = window.SmpLibrary.SmartPayAppInstance;
app.renderWidget({
paymentCheckoutToken: document.getElementById('checkoutTokenId').value,
container: 'main-container',
purpose: 'PAYMENT_TRANSACTION',
paymentOptionCode: 'CC',
successHandler: function (data) {
// Cleanup payment form container
if (data.kind === 'CALLBACK') {
// process payment completed
// Requests transaction status via Get Payment Status API
console.log(data);
}
if (data.kind === 'ADD_METHOD_CALLBACK') {
// optionally process payment option registration.
// Note: there is no any payment processed yet, no need to check status.
console.log(data);
}
},
errorHandler: function (errorCode, error) {
// Cleanup payment form container
// Requests transaction status via Get Payment Status API
console.error(errorCode, error);
},
paymentFormOnly: true,
});
}
</script>
</html>