A PCI-compliant way to use Shoppable's Checkout API to collect credit card details in your web application.
Introduction
This is a PCI-compliant way to use Shoppable's Checkout API to collect credit card details in your web application. If your company is not PCI DSS Compliant and you plan to use Shoppable's Universal Checkout API, you are er use this PCfI wrapper for privacy and security.
Prerequisites
You need to get your client token and api secret keys from your Shoppable Customer Success Team member.
Supported Browsers:
- Chrome 38+
- Safari 10.1+
- Firefox 29+
- Edge 15+
- Opera 25+
Front End Integration
Please include the following script on all pages of your website. This is necessary
<script src="https://cdn.shoppable.com/checkout/shoppable.js" id="shoppable-checkout-script"></script>
Calling the Checkout Function:
a window level initializeCheckout function will be available as soon as script loads into browsers memory. Signature of the function is as follows. All arguments are mandatory.
window.initializeCheckout({
publicToken: <<public_token>>,
parentElement = '#checkout-container' // a DOM element or css selector '#checkout-container',
amount = 5000, //in smallest currency unit, e.g., cents for USD
enabledComponents = [], //Array of elements to show user. Allowed values "express", "card", "address"
onSuccess = function (paymentToken) {}, // a callback function that accepts one argument (successObject see below) and will be fired once after the user successfully completes the payment
onError = function (error) {}, // a callback function that accepts one argument (errorObject see below). This function can be called none or multiple times depending on the users payment method
appearance = {} // appearance object to modify the look and feel of the payment ui. Please refer to Stripe's Elements Appearance API
});
parentElement:string | HTMLElement: you can either pass an css selector or an DOMElement for this parameter. Contents of the element will be replaced with payment method
amount: Integer: pass the amount to be charged in smallest currency for US it will ben cents. If the total order amount is $13.25 than you should be passing 1325 as integer.
enabledComponents: string[]: an array of strings to determine which components will be provided to collect the payment. Each member of the array can have one of the three options
express: component will provide available express checkout options on the browser. If the payment methods such as Apple Pay, Google Pay or Link supported on the user's browser
card: a credit card payment form will be displayed to user.
address: an address form will be displayed to collect shipping address. If you dont want to collect shipping address from shopper
function onSuccess(paymentObject): This function will be called if the shopper completes the payment process successfully and a paymentObject will be passed as argument. Please see the sample paymentObject as reference
{
paymentToken:string // a token that needs to be passed to backend. You will be sending this to checkout API
}
function onError(error: checkoutError) will be used as a callback function for errors during the payment processing step. This callback function can be called none or multiple times during the payment process. Please see the sample errorObject for reference
{
type:string, // possible values "parameter", "payment", "unexpected"
message:string
}
appearance: Object: appearance object to modify the look and feel of the payment ui. Please refer to Stripe's Elements Appearance API
Backend Integration
Headers
Please include the following header in the request to be authenticated. You can contact your CSM representative for required tokens
"Authorization": “Bearer <Bearer token that will be provided by shoppable>”,
"x-shoppable-secret": “<Shoppable Secret will be provided by shoppable>”
"Content-Type": "application/json"
Request
POST https://cloud.shoppable.com/v6/checkout
Request Payload
{
cartDetails: {
email: {type: String, required: true},
sendConfirmationEmail: {type:Boolean, required: true},
substitutionOptIn: {type: Boolean, required: true},
marketingOptIn: {type: Boolean, required: true},
lineItems: [
{
id: {type: String, required: true, length: 39},
price: { type: Double, required: true },
quantity: { type: Integer, required: true }
}
]
},
shippingDetails: {
firstName: {type:String, required: true},
lastName: {type:String, required: true},
address1: {type:String, required: true},
address2: {type:String, required: true},
city: {type:String, required: true},
state: {type:String, required: true, length:2},
country: {type:String, required: true, length:2},
zipCode: {type:String, required: true, length:5},
phoneNumber: {type:String, required: true, length:9}
},
billingDetails: {
firstName: {type:String, required: true},
lastName: {type:String, required: true},
address1: {type:String, required: true},
address2: {type:String, required: true},
city: {type:String, required: true},
state: {type:String, required: true, length:2},
country: {type:String, required: true, length:2},
zipCode: {type:String, required: true, length:5}
},
paymentToken: {type:String, required: true}
}
Notes:
- Please validate the addresses before sending them to the API. As address validation requires user interaction we expect you to validate the address (via USPS, or Google APIs) before sending to us. Our previous experience shows that not validated addresses cause more cancellations as the retailer will not accept the order.
- If one of the line item will go out of stock order will not be accepted with oos product id in the response.
- If at least one of the item’s price goes up at the time of we receive the order we will reject the order request. And you will get the product id in the response
- If product price goes down we will accept the order and process it with the new (low) price
- Country is defaulted to US as of now
- State must be an actual 2 letter state abbreviation.
- Zip code must be 5 digit only.
Response
Success HTTP 200 - All good and order successfully created
{
orderNumber:"R##########"
}
Bad Request HTTP 400 - Bad Request
{
type:"request",
message: "", // check message for detailed information
outOfStockItems: [],
itemsWithPriceChange: []
}
Bad Request HTTP 402 - Payment Needed
{
type:"payment",
message: "", // check message for detailed information
outOfStockItems: [],
itemsWithPriceChange: []
}
Not Found HTTP 404 - Product out of stock or price changed
{
type:"catalog",
message: "", // check message for detailed information
outOfStockItems: [], // itemIds that are out of stock will be listed here
itemsWithPriceChange: [] // itemIds that has price change will be listed here
}
Internal Server Error 500 - On rare case something went wrong on Shoppable's end.
{
type:"unexpected",
message: "", // check message for detailed information
outOfStockItems: [], // itemIds that are out of stock will be listed here
itemsWithPriceChange: [] // itemIds that has price change will be listed here
}
Security Best Practices
You must include script file on every page of your website for better fraud detection.
Also you must handle paymentToken carefully and never make a checkout API request from your front end.
Testing
For testing and development purposes a staging environment available. You can access CSM team for your staging credentials. Also please use the below endpoints for:
Script src: https://cdn.staging.shoppable.com/checkout/shoppable.js
Checkout API endpoint: https://cloud.staging.shoppable.com/v6/checkout
To do tests for different payment issue scenarios, please refer to Stripe's testing page for test cards and respective scenarios.