Secure Payloads

Pass sensitive customer or pricing data securely using an encrypted payload

Secure payloads

Use secure payloads to prefill customer details, pricing, or other sensitive data in your Store Builder checkout. This method encrypts the payload on your server using a signed key pair and passes it to FastSpring using fscSession or fastspring.builder.secure(). FastSpring decrypts the payload at runtime and applies it to the session.

Note: Secure payloads are typically used to lock fields like name, email, price, or tax ID. This method is ideal for passing verified customer data that should not be editable during checkout.

Why use secure payloads?

Secure sensitive values that should not be visible or editable at checkout:

  • Lock contact fields: Prevent buyers from modifying name, email, or address
  • Apply validated IDs: Include tax IDs or account IDs without exposing them
  • Restrict payment methods: Pre-select and enforce a specific payment option

What this guide covers

This guide explains how to:

  • Set up encryption for secure payloads
  • Create and encrypt a secure session payload
  • Pass the payload using fscSession or fastspring.builder.secure()
  • Work with secure test payloads in development
  • Understand accepted fields and payload structure

Set up encryption

Before you can pass a secure payload to your store checkout, you need to complete a one-time encryption setup in your FastSpring account.

  1. In the FastSpring App, go to Developer Tools > Store Builder Library.

  2. Copy your Access Key. You will use this in the data-access-key attribute when initializing Store Builder.

  3. Generate a 2048 bit RSA key pair.

    • Create a private key and save it as privatekey.pem. Keep this file secure and do not share it. You will use it on your server to encrypt the payload and generate the secureKey.
    • Create a public key and save it as publiccert.pem. Share this with FastSpring only. FastSpring will use it to decrypt your payload at checkout.

    If you haven’t done this before, check out resources on generating RSA key pairs in your preferred language or tooling (like OpenSSL or Node crypto). Make sure your key length is 2048 bits.

  4. Upload your publiccert.pem file using the File Upload section.

  5. Click Save.

    You will use the private key to encrypt session data on your server and generate the secure payload. FastSpring will use the public key to decrypt it at checkout.


Create and encrypt your payload

After setting up encryption, you can create a secure payload on your server and pass it into Store Builder. A secure payload is a JSON object containing session data that is encrypted using your private key. FastSpring uses your uploaded public key to decrypt the payload at checkout.

Only supported fields should be included in your payload. Fields like reset and checkout are not valid in secure session objects.

The exact implementation depends on your backend language, but the core process is the same across platforms.

Example payload before encryption

Here’s a basic example of what your unencrypted session data might look like before you encrypt it. This is the structure you will stringify and encrypt to create your securePayload.

{
  "contact": {
    "firstName": "Jane",
    "lastName": "Smith",
    "email": "[email protected]",
    "country": "DE"
  },
  "items": [
      {
        "product": "example-product",
        "quantity": 1,
        "pricing": {
          "price": {
          "USD": 19.00
          }
        }
      }
	]
}

Tip: You can include address fields inside the contact object or as a top-level address object. If your store requires physical address collection, make sure it is enabled in your store settings.

How to encrypt the payload

You will generate the securePayload and secureKey in your backend using your private key. The logic is the same regardless of language:

  • Encrypt the payload with a randomly generated AES key
  • Encrypt that AES key using your private RSA key (privatekey.pem)
  • Pass both encrypted values to Store Builder at checkout

Java

Follow these steps to create your secure payload in Java:

  1. Generate a 16-byte AES key
    You will use this key to encrypt your session data before passing it to FastSpring.
final KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
final SecretKey secretKey = keyGenerator.generateKey();
final byte[] aesKey = secretKey.getEncoded();
  1. Encrypt the payload using AES-128-ECB with PKCS5 padding
    This creates your securePayload string, which contains the encrypted session data.
final SecretKeySpec secretKeySpec = new SecretKeySpec(aesKey, "AES");
final Cipher encryptCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
final byte[] cleartext = unencryptedString.getBytes("UTF-8");
final byte[] ciphertext = encryptCipher.doFinal(cleartext);
final String securePayload = Base64.getEncoder().encodeToString(ciphertext);
  1. Encrypt the AES key using your private RSA key
    Use the privatekey.pem file you created during the encryption setup step. This creates the secureKey.
final org.bouncycastle.openssl.PEMReader pemReader =
    new org.bouncycastle.openssl.PEMReader(new StringReader(privateKeyPEM));
final KeyPair keyPair = (KeyPair) pemReader.readObject();
pemReader.close();

final PrivateKey privateKey = keyPair.getPrivate();
final Cipher clientPrivateCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
clientPrivateCipher.init(Cipher.ENCRYPT_MODE, privateKey);

final byte[] aesKeyEncrypted = clientPrivateCipher.doFinal(aesKey);
final String secureKey = Base64.getEncoder().encodeToString(aesKeyEncrypted);

FastSpring will use your uploaded publiccert.pem to decrypt the secureKey and unlock the securePayload at checkout.

PHP

Follow these steps to create your secure payload in PHP:

  1. Generate a 16-byte AES key
    You will use this key to encrypt the session data before passing it to FastSpring.
$aesKey = openssl_random_pseudo_bytes(16);
  1. Encrypt the payload using AES-128-ECB
    This creates the securePayload string, which contains the encrypted session data.
$cipherText = openssl_encrypt($unencryptedString, "AES-128-ECB", $aesKey, OPENSSL_RAW_DATA);
$securePayload = base64_encode($cipherText);
  1. Encrypt the AES key using your private RSA key
    Use the privatekey.pem file you created during the encryption setup step. This creates the secureKey.
$privateKeyFileName = realpath("privatekey.pem");
$privateKey = openssl_pkey_get_private("file://$privateKeyFileName");
openssl_private_encrypt($aesKey, $aesKeyEncrypted, $privateKey);
$secureKey = base64_encode($aesKeyEncrypted);

FastSpring will use your uploaded publiccert.pem to decrypt the secureKey and unlock the securePayload at checkout.


Pass the secure payload

Once you've created your securePayload and secureKey, you can pass them to Store Builder using either fscSession or fastspring.builder.secure().

Use fscSession before Store Builder loads

Apply the encrypted data when the page loads by defining fscSession before Store Builder initializes.

<script>
var fscSession = {
  secure: {
    payload: securePayload, // encrypted payload string generated on your server
    key: secureKey          // encrypted AES key string passed from your backend
  }
};
</script>

<!-- Define the session object before loading the Store Builder script -->
<script
  id="fsc-api"
  src="https://sbl.onfastspring.com/sbl/1.0.3/fastspring-builder.min.js"
  type="text/javascript"
  data-storefront="your-storefront-url"
  data-access-key="your-access-key">
</script>

Use fastspring.builder.secure() after Store Builder loads

You can also pass the secure payload dynamically using fastspring.builder.secure() after the script has initialized.

<script>
    fastspring.builder.secure(securedData, secureKey);
</script>

This method is helpful when your payload is generated on the fly or fetched from your backend after the page loads.

Test with unencrypted payloads (development only)

If you are placing a test order, you can pass private information unencrypted for testing purposes only. This allows you to troubleshoot and adapt your payload and encryption logic before going live.

<script>
    fastspring.builder.secure(nonEncryptedJSON, "");
</script>

Accepted fields

The following fields are supported in secure payloads. Field requirements may vary depending on your store settings and the data you pass. Address fields can be included either inside the contact object or as a separate top-level address object.

If your store requires physical address collection, make sure that option is enabled in your store settings.

Contact information

These fields allow you to include customer and account information in your secure payload. You can structure address fields inside the contact object or as a top-level address object.

Field Type Description
contact object Customer contact information. Required if you pass accountCustomKey. Fields inside contact will not be editable at checkout.
address object Optional top-level object for address fields. Can be used instead of nesting address inside contact.
contact.firstName string Customer’s first name. Required when passing contact.
contact.lastName string Customer’s last name. Required when passing contact.
contact.email string Customer’s email address. Required when passing contact. This must be a valid email format. Invalid emails will trigger validation errors.
contact.company string Customer’s company name. Required if your store settings require it.
contact.addressLine1 or address.addressLine1 string Address line 1. Required for physical products or if address collection is enabled.
contact.addressLine2 or address.addressLine2 string Address line 2 (optional).
contact.city or address.city string City. Required for physical products or address collection.
contact.region or address.region string Region or state (2-letter ISO). Required for US-based physical orders.
contact.postalCode or address.postalCode string Postal code. Required for credit card transactions.
contact.phoneNumber or address.phoneNumber string Phone number. Required if your store settings require it.
contact.country or address.country string Two-letter ISO country code. Required for physical products or tax purposes.
accountCustomKey string Account ID from your system. Requires contact to be passed.
account string FastSpring-generated account ID (optional).
taxId string VAT ID or GST ID. FastSpring will validate this against the customer’s IP or contact country.

Example: Contact and account fields

Here’s a full example showing how to pass contact information, tax ID, and account identifiers in a secure payload. Fields shown here are optional unless otherwise noted in the Contact information table.

{
  "contact": {
    "firstName": "Jane",
    "lastName": "Doe",
    "email": "[email protected]",
    "company": "Example Co.",
    "addressLine1": "456 Example Ave",
    "addressLine2": "Suite 789",
    "city": "San Francisco",
    "region": "CA",
    "postalCode": "94107",
    "phoneNumber": "555-123-4567",
    "country": "US"
  },
  "accountCustomKey": "external-id-456",
  "account": "fs-account-id-abc123",
  "taxId": "GB123456789"
}

Payment method settings

You can pre-select a preferred payment method and optionally hide all other options from the buyer during checkout.

Field Type Description
paymentMethod string Pre-selects a specific payment method for the customer.
hideOtherPaymentMethods boolean If true, only the selected payment method is shown at checkout.

Example: Pre-select a payment method

Here’s a short example that pre-selects PayPal and hides all other payment methods during checkout.

{
  "contact": {
    "firstName": "Jane",
    "lastName": "Doe",
    "email": "[email protected]",
    "country": "US"
  },
  "items": [
			{
				"product": "example-product",
				"quantity": 1,
				"pricing": {
					"price": {
					"USD": 19.00
					}
				}
			}
	  ]
  "paymentMethod": "paypal",
  "hideOtherPaymentMethods": true
}

Be sure the selected payment method is enabled in your store settings. Otherwise, it will be ignored at checkout.

Product information

These fields define the products added to the cart using the items array. You can specify quantities, pricing, trial periods, display settings, and more.

Field Type Description
items array A list of product objects to add to the cart. Each item represents one product and its configuration.
items.product string The product path or ID from your FastSpring store.
items.quantity integer The number of units added to the cart. Ignored if quantityBehavior is set to lock or hide.
items.pricing.price object Product price by currency. Example: { "USD": 19.00, "EUR": 17.00 }.
items.pricing.trial integer Number of free trial days for subscriptions.
items.pricing.interval string Billing frequency for subscriptions. Accepts adhoc, day, week, month, or year.
items.pricing.intervalLength integer Number of units per billing interval. For example, 1 = every month, 3 = every 3 months.
items.pricing.intervalCount integer Total number of billings before the subscription ends. Use null for ongoing subscriptions.
items.pricing.quantityBehavior string Controls how quantity is displayed at checkout. Options: allow, lock, or hide.
items.pricing.quantityDefault integer Default quantity shown at checkout. Required if you don’t pass quantity above or if quantityBehavior is lock or hide.
items.display object Localized display name for the product. Example: { "en": "Product Name" }.
items.description object Localized product description. Requires language keys enabled in your store settings.
items.image string URL for the product image shown during checkout.
items.selected boolean Determines whether the product appears pre-selected in the cart.
items.removable boolean Allows or prevents the customer from removing the product at checkout.
items.sku string Internal SKU or product identifier used by your system.
items.attributes object Optional product attributes. Useful for tracking, integrations, or custom logic.
tags object Optional key-value pairs added at the order level. Accessible in webhooks and server integrations.

Example: Full product payload structure

Here’s a complete example of a secure payload with detailed product configuration, including subscription settings, pricing, display content, and optional metadata.

{
  "items": [
    {
      "product": "product-path",
      "quantity": 1,
      "pricing": {
        "trial": 30,
        "interval": "month",
        "intervalLength": 1,
        "intervalCount": null,
        "quantityBehavior": "allow",
        "quantityDefault": 1,
        "price": {
          "USD": 5.0,
          "EUR": 4.0
        },
        "discountType": "percent",
        "quantityDiscounts": {
          "1": {
            "USD": 5.0,
            "EUR": 4.0
          }
        },
        "discountReason": {
          "DE": "German text"
        },
        "discountDuration": 1,
        "dateLimitsEnabled": true,
        "startDate": "2025-01-01",
        "endDate": "2025-12-31",
        "startTime": "00:00",
        "endTime": "23:59",
        "reminder_enabled": true,
        "reminder_value": "day",
        "reminder_count": 1,
        "payment_overdue": true,
        "overdue_interval_value": "day",
        "overdue_interval_count": 1,
        "overdue_interval_amount": 3,
        "cancellation_interval_count": 1,
        "cancellation_interval_value": "day"
      },
      "display": {
        "DE": "German text"
      },
      "description": {
        "values": {
          "full": {
            "values": {
              "en": "English description"
            }
          }
        }
      },
      "image": "https://example.com/image.png",
      "selected": true,
      "removable": true,
      "attributes": {
        "key": "value"
      },
      "sku": "internal-product-sku-1234"
    }
  ],
  "tags": {
    "key": "value"
  }
}

Tip: This example includes supported fields for subscriptions, pricing rules, and product display. You can simplify the structure based on your needs. Not all fields are required, so only include what applies to your product.


FAQs

Do I need to encrypt every session?

No. Use encryption only when you are passing sensitive information that should not be visible or editable by the customer. For example, when locking in verified contact information, fixed pricing, or a validated tax ID. If you do not need to restrict any fields, you can use a standard session object without encryption.

Can I reuse secure payloads across sessions?

No. Secure payloads are designed for one-time use per session. You should generate a new payload for each checkout to ensure the data remains accurate, valid, and secure.

Can I include fields that aren’t listed in the accepted fields table?

No. Fields not listed in the accepted fields table will be ignored. FastSpring will only process supported fields, so it's important to match the structure and field names exactly. If you're unsure about a specific field, test it in development mode or contact support for guidance.

What happens if I pass address fields in both contact and address?

FastSpring will prioritize fields in the contact object. Use either contact or address, but not both. Duplicating fields between them may cause unexpected behavior.