Pass a Secure Request

Pass encrypted payloads to FastSpring.

You can use the Store Builder Library (SBL) to pass sensitive information in an encrypted format. This is necessary to hide information that customers should not have access to. To secure the information, follow the steps below:

FastSpring will decrypt the payload and apply the information to the associated order session.

Set Up Encryption

🚧

This step is only necessary for initial setup. If you have set up encryption before, you can skip this step.

  1. Navigate to Integrations > Store Builder Library.
  2. Copy the Access Key. You will use this key and data-access-key to initialize the SBL.
  3. Create a Private/Public certificate pair.
    • Private: Create a 2048-bit RSA private key. Do not share this key. You will use the private key PEM file privatekey.pem to create your secureKey.
    • Public: Create a 2048-bit RSA public key. Only share this key with FastSpring. FastSpring will use your public key PEM file publiccert.pem to decrypt your payload.
  4. Under File Upload, click Choose File. Select the file containing your public certificate.
  5. Click Save.

Create a Session Object

Create a session object containing all of the information which you would like to encrypt. The required fields will vary depending on the information collected.

<script>
var fscSession = {
    'reset': true,
    'products' : [
                    {
                        'path':'example-product',
                        'quantity': 1
                    }
    ],
    'coupon': 'YOUR10OFF'
}
</script>
<script
    id="fsc-api"
    src="https://d1f8f9xcsvx3ha.cloudfront.net/sbl/0.8.7/fastspring-builder.min.js"" type="text/javascript"

Locally Encrypt the Session Object

After you create the session object, locally encrypt the data. This varies depending on the programming language you are using. FastSpring will use your secureKey string and publiccert.pem to decrypt your securePayload string.

Java

  1. Create a 16-byte aesKey for each payload.
final KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(128); final SecretKey secretKey = keyGenerator.generateKey() ; final byte[] aesKey = secretKey.getEncoded() ;
  1. Use the random 16-byte AES key to create the securePayload string from your unencryptedString. This is typically a Base64 string, but it can be a raw byte.
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. Use your privateKey PEM string to encrypt your aesKey to create your secureKey string.
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 uses your secureKey string and publiccert.pem to decrypt your securePayload string.

PHP

  1. Create a 16 byte AES key for each payload.
$aesKey = openssl_random_pseudo_bytes(16) ; # or urandom() or any other random byte generator
  1. Use the random 16-byte AES key to create the securePayload string from your unencryptedString. This is typically a Base64 string, but it can be a raw byte.
$cipherText = openssl_encrypt($unencryptedString, "AES-128-ECB", $aesKey, OPENSSL_RAW_DATA) ;
$securePayload = base64_encode($cipherText) ;
  1. Encrypt your AES key with the privatekey.pem file. This creates your secureKey string.
$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 secureKey string and publiccert.pem to decrypt your securePayload string.

Pass a Preferred Payment Method

You can set a preferred payment method by passing two properties into the fastspring.builder.secure() function:

FieldData TypeDescription
paymentMethodstringSpecifies the payment method you want to pre-select for your customer.
hideOtherPaymentMethodsbooleanHides other payment methods. Use if you want your customers to pay only using your pre-selected payment method.

The following example sets paymentMethod to paypal and hideOtherPaymentMethods to true. Customers would only see PayPal as a payment method during checkout:

 fastspring.builder.secure(
	{
		"contact": {
			"email":"[email protected]",
			"firstName":"John",
			"lastName":"Doe"
		},
		"items": 
		[
			{
				"product": "example-product",
				"quantity": 1,
				"pricing": {
					"price": {
					"USD": 19.00
					}
				}
			}
		],
		"paymentMethod": "paypal",
		"hideOtherPaymentMethods": true
	}
);

Pass the Encrypted Payload

There are 2 ways to pass the encrypted payload:

  • fscSession: Apply the data when the page loads.
<script>
var fscSession = {
	'secure': {
		'payload': securedData, // string of encrypted data passed from the server
		'key': secureKey // secure key passed from the server
	}
}
</script>
<!-- placing the session object before the Library is initialized ensures that the data will be sent with the very first request -->
<script
	id="fsc-api"
	src="https://d1f8f9xcsvx3ha.cloudfront.net/sbl/0.8.7/fastspring-builder.min.js"" type="text/javascript" 
...
  • fastspring.builder.secure(): Send the request.
<script>
    fastspring.builder.secure(securedData, secureKey);
</script>

Pass a Secure Request in Test Mode

If you are placing a test order, you do not need to encrypt private information. This allows you to troubleshoot and adapt each payload and encryption.

<script>
    Fastspring.builder.secure(nonEncryptedJSON, '');
</script>

Accepted Fields

The following tables display the fields which can be securely encrypted. Required fields will vary depending on what you include in your JSON string.

Contact Information

FieldData TypeDescription
contact objectCustomer contact information. This is required if you pass accountCustomKey.

The SBL does not prompt the customer to enter this information at checkout.
   firstName stringCustomer’s first name. Required when passing contact information.
   lastName stringCustomer’s last name. Required when passing contact information.
   email stringCustomer’s email address. Required when passing contact information.
   company stringCustomer’s company name. Required if the storefront requires it.
addressobjectCustomer address information.
   addressLine1 stringLine 1 of the customer’s mailing address. Required if the order includes physical fulfillments.
   addressLine2 stringLine 2 of the customer’s mailing address.
   city stringThe city in the customer’s address. Required if the order includes physical fulfillments.
   region string2-character ISO region code of the associated US state. Required if the order includes physical fulfillments, and the recipient resides in the US.
   postalCode stringCustomer’s postal code. Required for credit card transactions.
   phoneNumber stringCustomer’s phone number. Required if the storefront requires it.
   country string2-character ISO country code. Required if the order includes physical fulfillments.
accountCustomKey stringThe Account ID in your system. If you pass this string, the contact object is required.
account stringFastSpring-generated Account ID (optional).
taxId stringThe customer’s VAT ID or GST ID. FastSpring will validate it in conjunction with the IP address country. If valid, tax exemption is applied. This field is optional.

Example Request Payload

{
    contact: {                        // customer details - optional unless you pass accountCustomKey (below); if customer contact info is passed, customer will not be prompted to provide it during checkout
        firstName: "firstName"        // customer first name - required when passing contact info
        lastName: "lastName"          // customer last name - required when passing contact info
        email: "[email protected]" // customer email address - required when passing contact info
        company: "Acme Inc"           // customer company (optional unless required by Storefront settings)
        addressLine1: "Address Line 1"// customer address line 1 (optional unless order includes physical product or 'Force phsyical address collection' is enabled in Storefront settings)
        addressLine2: "Address Line 2"// customer address line 2 (optional)
        city: "City"            // customer city (optional unless order includes physical product or 'Force physical address collection' is enabled in Storefront settings)
        region: "California"          // customer region (e.g. state for US customers, recommend two-character ISO region code)(optional unless order includes physical product or 'Force physical address collection' is enabled in Storefront settings)
        postalCode: "93101"      // customer postal code (required for credit card transactions)
        phoneNumber: "800-555-1212"     // customer phone number (optional unless required by Store settings)
        country: "US"         // customer country - two-character ISO country code (optional unless order includes physical product or 'Force physical address collection' enabled in Storefront settings)
    },
    accountCustomKey: "123abc",   // optional account ID from your system; if you pass this then the contact object above is required
    account: "x2345adsdadq0zzz",            // FastSpring-generated customer account ID (optional)
    taxId: "234958723945",              // optional GST ID or VAT ID for the customer; will be validated in conjunction with the country (detected via geo IP location or set as part of the contact object); if the ID is valid, it will be applied to the session and no GST or VAT will be applied to the order
}

Product Information

FieldData TypeDescription
items objectLists the product information for each product in the session.
product stringProduct ID that is added to the cart.
quantity integerQuantity of the product being added to the cart.
pricing objectIf you pass a “pricing” object, define all applicable pricing options.
trial integerNumber of free trial days. Required for subscriptions.
interval stringBilling frequency. "adhoc", "day", "week", "month", or "year".
   intervalLength integerNumber of billings per intervalLength period.
   intervalCount integerNumber of billings until subscription expires. Input null for unlimited billings.
quantityBehavior stringDisplay and behavior of the quantity field. "allow", "lock", or "hide" the quantity field from customers at checkout.
quantityDefault integerDefault product quantity. Required if you do not pass the quantity string above.
price objectPrice of the product. You can pass multiple currencies.
Example: { “USD”: 5.0, “EUR”: 4.0 }.
   discountType stringType of discount to be applied to the product. "percent" or "amount".
   quantityDiscounts objectSpecify the quantity required to receive a product discount. Then, enter the discount amount or percent.
Example (percent): { 2: 10.0 }
Example (amount): { 2: {“USD”,5.0} }
    discountReason objectCustomer-facing reason for the discount.
Example: {“en”: “English Text”, “de”: “German Text” }
    discountDuration integerNumber of subscription billings to which the discount applies.
    dateLimitsEnabled booleanAllows a date range in which the discount is valid.
    startDate stringEarliest date that the discount applies.
    endDate stringExpiration date of the discount.
    startTime stringEarliest time that the discount applies. Specify in UTC.
    endTime stringDiscount expiration time. Specify in UTC.
   reminder_enabled booleanEnable or disable subscription payment reminder notifications.
   reminder_value stringInterval unit for subscription payment reminder email messages . "day", "week", "month", or "year".
   reminder_count integerNumber of interval units prior to the next billing date when subscription payment reminder email messages will be sent.
   payment_overdue booleanEnable or disable subscription payment overdue notifications.
   overdue_interval_value integerinterval unit for subscription payment overdue notification email messages.
   overdue_interval_count integerTotal number of subscription payment overdue notifications that FastSpring sends prior to canceling the subscription.
   overdue_interval_amount integerNumber of overdue_interval units between each subscription payment overdue notification message.
cancellation_interval_count integerNumber of cancellation_interval units prior to subscription cancellation.
   cancellation_interval_value stringInterval unit for subscription cancellation (subscription only). "day", "week", "month", or "year".
display objectCustomer-facing product display name.
Example: {“en”: “English Display”, “de”: “German Display” }
description objectCustomer-facing product description.
Example: {“en”: “English Description”, “de”: “German Description” }
image stringURL of the product icon image.
selected booleanControl whether or not the selected product appears in the cart.
removeable booleanControl whether or not customers can remove the item from their cart.
attributes objectProduct attributes.
sku stringProduct SKU ID
tags objectOrder tags.

Example Request Payload

{
    items: [
        {
            product: "product-path",                                                  // id of the product you are adding to cart
            quantity: 1,                                                // quantity of the current product to be added to the cart; ignored if "quantityBehavior" = "lock" or "hide"; in that case, use "quantityDefault" instead
            pricing: {                                                          // keep in mind - when you pass the "pricing" object for an item you need to define all possible pricing options, including, for example, subscription-related fields where applicable.
                trial: 30,                                               // number of free trial days for a subscription (required for subscription only)
                interval: "month",           // interval unit for scheduled billings; "adhoc" = managed / ad hoc subscription (required for subscription only)
                intervalLength: 1,                                      // number of interval units per billing (e.g. if interval = "MONTH", and intervalLength = 1, billings will occur once per month)(required for subscription only)
                intervalCount: null,                                       // total number of billings; pass null for unlimited / until cancellation subscription (required for subscription only)
                quantityBehavior: "allow",                   // "allow" = quantity can be edited, "lock" = quantity is displayed in the checkout but not editable, "hide" = quantity is hidden and not editable (optional, default is allow)
                quantityDefault: 1,                                     // default quantity for the product (only needed when "quantityBehavior" = "lock" or "hide", or if you do NOT pass quantity above)
                price: {                                                        // multiple currencies can be passed
                   "USD": 5.0,
                   "EUR": 4.0
                },
                discountType: "percent",                           // optional product-level discount type
                quantityDiscounts: {                                            // optional volume-based discount settings; specify quantity required to receive discount per unit followed by discount percentage or amount
                    1: {                                                // ex. if discountType = "PERCENT", 10: 25.00 results in 11+ units each receiving a 25% discount; for a simple discount use 0: 10.00 to give a 10% discount off everything
                       "USD": 5.0,             // ex. if discountType = "AMOUNT",  5: {"USD": 5.0} results in 6+ units each receiving a discount of $5 USD; multiple currencies supported
                       "EUR": 4.0
                    }
                },
                discountReason: {                                               // reason for the discount, which can optionally be displayed to customers; specified language must be enabled in Store settings
                    "DE": "German text",
                },
                discountDuration: 1,                                    // number of subscription billings to which the discount will apply (subscription only); e.g. 1 = first billing only, 2 = first and second billings, etc.
                dateLimitsEnabled: true,                                   // controls whether or not the discount is valid only during a certain date range
                startDate:"2023-01-01" ,                               // earliest date on which the discount applies
                endDate: "2023-12-31",                                 // discount end / expiration date
                startTime: "00:00",                               // time on the earliest date when discount becomes available; specify time in UTC
                endTime: "23:59",                                 // time on the end / expiration date when discount is no longer available; specify time in UTC
                reminder_enabled: true,                                    // controls whether or not payment reminder email messages are enabled for the product (subscription only)
                reminder_value:  "day",                        // interval unit for payment reminder email messages (subscription only)
                reminder_count: 1,                                      // number of interval units prior to the next billing date when payment reminder email messages will be sent (subscription only)
                payment_overdue: true,                                     // controls whether or not payment overdue notification email messages are enabled for the product (subscription only)
                overdue_interval_value: "day",  // interval unit for payment overdue notification email messages (subscription only)
                overdue_interval_count: 1,                              // total number of payment overdue notification messages to send (subscription only)
                overdue_interval_amount: 3,                             // number of overdue_interval units between each payment overdue notification message (subscription only)
                cancellation_interval_count: 1,                         // number of cancellation_interval units prior to subscription cancellation (subscription only)
                cancellation_interval_value:  "day",  // interval unit for subscription cancellation (subscription only)
            },
            display: {                                                          // customer-visible product display name or title
                "DE": "German text",           // multiple languages supported, language must be enabled in Store settings
            },
            description: {                                                      // customer-visible product description
                "values": {
                    "full": {
                        "values": {
                             "en": "English description",  // multiple languages supported, language must be enabled in Store settings
                        }
                    }
                }
            },
            image: "www.example.com/image",                                                    // product icon image file URL
            selected: true,                                                // controls whether or not product is currently selected / in the cart
            removable: true,                                               // controls whether or not product can be removed from the cart by the customer
            attributes: {
                key: "value",                                                  // optional product attributes (maximum of approximately 400,000 characters)
            },
            sku: "internal-product-sku-1234"                                                       // optional product SKU ID (e.g. to match your internal SKU or product ID)
        },
    ],
    tags: {                                                                     // optional order tags (maximum approximately 4,000 characters)
 
        key: "value",
    }
}