Next Commerce

Bankcard

Bankcard is the core payment method on the Admin API. Cards are charged by passing payment_method: card_token with a tokenized card in payment_details. Tokenizing the card with our iFrame payment form keeps sensitive card data off your servers and reduces your PCI compliance scope.

This guide covers the full bankcard flow:

Order payment payload

Bankcard orders set payment_method to card_token and pass the tokenized card (and any optional fields) in payment_details:

Bankcard Payment Detail
"payment_method": "card_token",
"payment_details": {
    "card_token": "<card token>",        // from the iFrame (see below)
    "save_card": true,                    // retain card for future charges (default true)
    "statement_descriptor": "BRANDNAME",  // optional, up to 22 chars
    "payment_gateway": 12,                // optional, route to a specific gateway
    "payment_gateway_group": 3,           // optional, route to a gateway group
    "payment_return_url": "<url>"         // required for 3DS (see below)
}
FieldTypeDescription
card_tokenstringTokenized card produced by the iFrame payment form.
save_cardbooleanRetain the card for future charges (subscriptions, one-click upsells). Defaults to true.
statement_descriptorstringCustom bank-statement descriptor (≤ 22 alphanumeric chars, spaces, and & , . - #).
payment_gatewayintegerOptional — charge a specific gateway by id. See Gateway routing.
payment_gateway_groupintegerOptional — charge a gateway group by id. See Gateway routing.
payment_return_urlstring (uri)Required for 3DS — your endpoint that receives the final order data. See 3D Secure.

For the complete order request (lines, user, addresses, shipping), see the External Checkout Flow guide. This guide focuses on the bankcard-specific payment detail.

Gateway Routing

By default, bankcard charges route through your store's configured payment gateway. For stores with more than one gateway, you can optionally pin a charge to a specific gateway or gateway group by passing one of these fields in payment_details:

FieldTypeRoutes to
payment_gatewayintegerA single gateway by its id.
payment_gateway_groupintegerA gateway group by its id — the platform selects a member gateway.
Route to a specific gateway or group
"payment_method": "card_token",
"payment_details": {
    "card_token": "<card token>",
    "payment_gateway": 12          // OR "payment_gateway_group": 3
}

Pass either payment_gateway or payment_gateway_group — not both. If neither is provided, the store's default routing is used.

Get gateway and group ids

The ids are integers from the Payments API:

A gateway group also exposes its supported available_currencies, available_payment_methods, and card_types, so you can pick the right group for a given order.

When to route

Most stores let the platform route automatically. Pass an explicit gateway or group when you need to:

  • Load balance — distribute volume across multiple gateways/processors.
  • Region or currency routing — send orders to the gateway that supports a given currency or market.
  • Failover — direct traffic to a backup gateway, or use a group so a soft-declined charge can be re-attempted on another gateway in the group.

Group membership, distribution weighting, and soft-decline re-attempt behavior are configured per gateway in your store dashboard — the API selects among what's already configured.

Card Tokenization (iFrame)

Custom off-site checkouts can reduce their PCI compliance scope by leveraging our iFrame payment form to tokenize credit cards before submitting them on the Admin API.

View a fully functional Demo to see all of the concepts in action. The demo source code is also available on Github.

The iframe payment form is a pure JS library that provides managed fields for the card number and security code to safely collect sensitive credit card information. The fields can be styled to match your external checkout HTML pages for a seamless end-user experience.

We have partnered with Spreedly for all bankcard payments; this guide leverages their iFrame payment documentation and how to use the iFrame JS with our platform.

Setup

Before you get started, grab your Payments Environment Key from your store dashboard (Settings > Payments) — we'll use this to map the iFrame to your store's payment environment.

Card tokenization steps

  1. Add a payment form with card fields (name, card number, expiration, and cvv).
  2. Add Spreedly JS and initialize the iFrame on managed fields.
  3. Style the iFrame form fields to match your design.
  4. Tokenize the card with a form submit handler.
  5. Retrieve the card token.
Example Payment Form HTML

<form id="payment-form" action="https://yoursite.com/checkout"
  onsubmit='submitPaymentForm(); return false;'>

  <label for="full_name">Cardholder Name</label>
  <input type="text" id="full_name" name="full_name"><br/>

  <label>Card Number</label>
  <div id="bankcard-number" style="width:225px; height:35px; border: 2px solid"></div><br/>

  <label for="month">Expiration Date</label>
  <input type="text" id="month" name="month" maxlength="2">
  <input type="text" id="year" name="year" maxlength="4"><br/>

  <label>CVV</label>
  <div id="bankcard-cvv" style="width:60px; height:35px; border: 2px solid "></div><br/>

  <input id="submit-button" type="submit" value="Pay Now" disabled>

</form>

After you have the form on your page, initialize the iFrame fields on card number and cvv.

Add JS and Configure

<script src="https://core.spreedly.com/iframe/iframe-v1.min.js"></script>
<script>
Spreedly.init("<STORE PAYMENT ENVIRONMENT KEY>", {
  "numberEl": "bankcard-number",
  "cvvEl": "bankcard-cvv"
});
</script>

Note how the numberEl and cvvEl map to div element ids in the form to render the managed fields.

Style iFrame Fields

For the best end-user experience, customize the iFrame form fields so they blend in with your native form fields.

Example form customization
// example styles for iframe fields, accepts any style that can be applied with JS
var style = 'color: #212529; font-size: 1rem; line-height: 1.5; font-weight: 400; \
width: calc(100% - 20px); height: calc(100% - 2px); position: absolute;';

// set placeholders and styles for iframe fields to make UI style
Spreedly.on("ready", function () {
    Spreedly.setFieldType('text');
    Spreedly.setPlaceholder('cvv', "CVV");
    Spreedly.setPlaceholder('number', "Card Number");
    Spreedly.setNumberFormat('prettyFormat');
    Spreedly.setStyle('cvv', style);
    Spreedly.setStyle('number', style);

    submitBtn.removeAttribute('disabled');
});

Tokenize Card

Tokenize the card with your form submission handler. The tokenizeCreditCard method requires that the requiredFields are passed as an object for form validation.

Tokenize Card on Form Submit

function submitPaymentForm() {
    var requiredFields = {};
    // Get required, non-sensitive, values from host page form
    requiredFields["full_name"] = document.getElementById("full_name").value;
    requiredFields["month"] = document.getElementById("month").value;
    requiredFields["year"] = document.getElementById("year").value;
    // tokenize the card
    Spreedly.tokenizeCreditCard(requiredFields);
}

Retrieve Card Token

When a card has been tokenized, the paymentMethod event is fired that includes the generated payment method token as well as the details of the payment method record. Use the token from your custom checkout backend to send to the Admin API when creating the order.

Retrieve Card Token

Spreedly.on('paymentMethod', function (token, pmData) {
    // create your own handler to capture the token and send to your backend
    console.log(token);
    console.log(pmData);
});

Error Handling

When a card fails validation, the errors event is fired which includes an array of objects with attribute, key, and message fields describing the errors for each field.

Error Handling

Spreedly.on('errors', function(errors) {
  // add your own error handler to show errors to users so they can fix them
  for (var i=0; i < errors.length; i++) {
    var error = errors[i];
    console.log(error);
  };
});
Example Errors
[
  {
    "attribute":"first_name",
    "key":"errors.blank",
    "message":"First name can't be blank"
  }, {
    "attribute":"last_name",
    "key":"errors.blank",
    "message":"Last name can't be blank"
  }
]

Customizing the iFrame Fields

The iFrame fields can be customized to match your site styles. See the demo for a full example.

setFieldType

Set the input type of the iFrame fields. This is useful when you want different keyboards to display on mobile devices.

By default, the iFrame fields are set to type=number, which displays the numerical keyboard in most browsers on most mobile devices. However, behavior does vary by browser. If you'd like to manually control the input field type you can do so with setFieldType.

Arguments

NameDescription
fieldThe iFrame field to set the placeholder. Can be one of number or cvv.
typeThe input field type. Can be one of number, text or tel.
setFieldType
Spreedly.on('ready', function() {
  Spreedly.setFieldType("number", "tel");
});

setNumberFormat

Set the card number format. If set to prettyFormat, the card number value will include spaces in the credit card number as they appear on a physical card. The number field must be set to type text or tel for pretty formatting to take effect.

Arguments

FormatUser InputDisplay
prettyFormat41111111111111114111 1111 1111 1111
plainFormat (default)41111111111111114111111111111111
maskedFormat4111111111111111****************
setNumberFormat
// Pretty format
Spreedly.on('ready', function() {
  Spreedly.setFieldType("number", "text");
  Spreedly.setNumberFormat("prettyFormat");
});

// Masked format
Spreedly.on('ready', function() {
  Spreedly.setFieldType("cvv", "text");
  Spreedly.setFieldType("number", "text");
  Spreedly.setNumberFormat("maskedFormat");
});

setPlaceholder

Style iFrame fields' placeholder text if page design requires so.

Arguments

NameDescription
fieldThe iFrame field to set the placeholder. Can be one of number or cvv.
placeholderThe placeholder text value.
setPlaceholder
Spreedly.on('ready', function() {
  Spreedly.setPlaceholder("number", "Card");
  Spreedly.setPlaceholder("cvv", "CVV");
});

setStyle

Style iFrame fields using CSS. More than one invocation of setStyle can be used per field to organize and better structure styling directives.

Arguments

NameDescription
fieldThe iFrame field to set the placeholder. Can be one of number or cvv.
cssThe CSS to apply. Should be vanilla CSS, -moz-appearance, or -webkit-appearance. All CSS properties should be constructed as a single string.
setStyle
Spreedly.on("ready", function() {
  Spreedly.setStyle("number", "width:225px;  height:35px;");
  Spreedly.setStyle("number", "font-size: 20px; text-align: center");
  Spreedly.setStyle("cvv", "width:60px;  height:35px;");
});

Importing external fonts or images is not supported due to CORS restrictions.

transferFocus

Set the cursor focus to one of the iFrame fields. This is useful if you want to load your form with the card number field already in focus, or auto-focus a field that contains an input error.

transferFocus
Spreedly.transferFocus("number");

Arguments

NameDescription
fieldThe iFrame field to set the placeholder. Can be one of number or cvv.

toggleAutoComplete

Toggle autocomplete functionality for card number and cvv fields. By default, the autocomplete attribute is enabled, so the first call of this function will disable autocomplete.

toggleAutoComplete
Spreedly.toggleAutoComplete();

3D Secure (3DS2)

3DS2 payments are fully supported via the Admin API to process the customer through an authentication flow, with the final transaction information and results provided back to your application.

Your store must have a 3DS2-enabled gateway to process 3DS2 transactions.

API payment redirect flow

Below is a high-level overview of the user flow when creating orders on the Admin API that utilize the payment method redirect flow.

Payment ProviderStoreExternal CheckoutUserPayment ProviderStoreExternal CheckoutUserUser initiates payment1Create order/redirect to "payment_complete_url"2User completes payment3Store processes payment4Store POSTs order data to "payment_return_url"5Receive data/show order details6

Create the order

When creating an order using a 3DS2-enabled gateway, use payment_method=card_token and provide a payment_return_url. The payment_return_url is your endpoint that will receive a POST request containing the final order data.

Payment Details for Order with 3DS2 Payment
"payment_method": "card_token",
"payment_details": {
    "card_token": "<card token>",
    "payment_return_url": "<external checkout url>",
    "payment_gateway": 12,             // optional
    "payment_gateway_group": 3         // optional
}

You can optionally provide a payment_gateway or payment_gateway_group (see Gateway routing) to authenticate against a specific gateway configured in the store.

Redirect to the payment complete URL

The order response provides a payment_complete_url. Redirect the customer to this URL to complete the payment authentication.

Response with Payment Complete URL
{
    "reference_transaction_id": null,
    "payment_complete_url": "https://<domain>/payments/3ds-auth/?token=<transaction token>"
}

Receive order data

After the customer has completed their payment, they will be redirected to your application with a POST request containing data in the response key comprising all of the order information as a string. See examples below.

Order data structure follows Admin Order API and is application/x-www-form-urlencoded in a variable called response. If the order data is an empty dictionary , it means payment collection was unsuccessful and the order was not created.

Example Parsing of Order Data
import json

def order_receiver_view(request):
    data = json.loads(request.POST.get("response"))
    ...
    return HttpResponse(status=201)

On this page