Accessing the Library from Javascript

Last modified May 15, 2019

This article applies to Contextual Commerce. (Looking for Classic Commerce documentation?)

An advanced alternative to using HTML Markup directives is to access the Store Builder Library directly from Javascript utilizing available public methods.

The Flow

Store Builder Library is a wrapper around a set of private APIs allowing vendors to manipulate the cart contents for a given visitor. All calls made to the Library will be converted into API requests and published to the backend expecting a response with current cart contents and order parameters – the "order object". Given sophisticated cart population logic, various cross-sell and upsell scenarios, and other features of the platform, each request might result in significant changes to the order object. Therefore, we recommend that you rely on the most current data after each request and avoid caching responses. 

All requests to the Library are made in the form of the "Session Object" which will be converted to the internal API directives. The Session Object can be used for passing order details to the Store without requiring the use of a secure payload.

Live Interactive Examples

Check out our interactive, hands-on examples at https://www.fastspringexamples.com/#methods.


Understanding the Session Object

The Session Object is a standard Javascript object which contains directives for the Library. 

The Session object might contain the following fields:

  • coupon – String, must contain a valid coupon. If empty string is passed coupon (if any was previously applied) will be removed from the cart. 
  • products – Array of objects, each object representing a valid product. Must contain at least product ID and quantity. To place product in the cart pass any non-zero quantity, to remove product from the cart pass quantity as 0. Example: {'path' : 'arkanoid', 'quantity': 1}. The product object might also contain a complete product definition when used as part of the secure payload. See Passing Sensitive Data with Secure Requests for more information.
  • checkout – Accepts "true" or SessionID string which you have obtained after pre-creating a session using the server API. If "true" is passed the visitor will be redirected to checkout after performing other operations. If Session ID is passed as a parameter all other fields will be ignored and visitor will be redirected to checkout.
  • clean – Boolean. If set to "true" the session will be cleaned for the visitor after redirecting to checkout. This parameter only makes sense if "data-continuous" is set to "true" when initializing the Library. The intention of this behavior is to make sure that the customer will return to the "clean" cart after attempting a checkout. 
  • reset – Boolean. If set to "true" resets the session, but does this immediately when called, before all other actions.
  • secure – String (for Live storefronts) OR Object (for test storefronts). Contains secure payload, see "Passing Sensitive Data with Secure Requests for details. 
  • tags – Any valid Javascript object. Any data can be passed using tags and it will be made available to vendor via webhooks and server events. For example, tags can be used in secure payloads if you want to change a product's price for a specific customer or for price A/B testing. For more information on tags see Passing and capturing custom order tags and product attributes.
  • language – A string representing two-letter language code to force a different checkout language
  • country – A string representing two-letter country code to force a different checkout country
  • paymentContact – object representing "tentatively" known visitor details. Applies "tentatively" known (unconfirmed) customer information to the order but will not hide input fields during checkout process. To pass "known" and "confirmed" information refer to Passing Sensitive Data with Secure Requests. The structure of this object is: 

    Example of the paymentContact object
    {  
       "email":"email",
       "firstName":"firstName",
       "lastName":"lastName",
       "company":"company",
       "addressLine1":"addressLine1",
       "addressLine2":"addressLine2",
       "city":"city",
       "region":"region",
       "country":"country",
       "postalCode":"postalCode",
       "phoneNumber":"phoneNumber"
    }
  • recipient - object representing "tentatively" known gift recipient details. Applies "tentatively" known (uncofirmed) recipient information to the order, and automatically selects the Gift Purchase check box, but will not hide input fields during the checkout process. To pass "known" and "confirmed" recipient information, refer to Passing Sensitive Data with Secure Requests. The structure of this object is:

    Example of the recipient object
    {
    	"email": "recipient@fastspring.com",
    	"firstName": "firstName",
    	"lastName": "lastName",
    	"address": {
    		"addressLine1": "Address Line 1",
    		"city": "City",
    		"region": "California",
    		"postalCode": "93101",
    		"country": "US"
    	},
    	"memo": "Happy Birthday!"
    }

Once created, the Session Object is usually passed to the Library by utilizing the fastspring.builder.push() method:

var s = {
	'reset': true, // reset the cart and session (will remove everything added to the cart or passed to the session prior to this)
	'products' : [
					{
						'path':'arkanoid',
						'quantity': 1 // add product "arkanoid" to the cart with quantity "1".
					}
	],
	'coupon': 'YOUR10OFF', // apply coupon to the order
	'checkout': true // once all of the above is done redirect to checkout
}

fastspring.builder.push(s); // call Library "Push" method to apply the Session Object. 

Initializing the Library with the Session Object

The Library will make a first request to the FastSpring backend immediately when initialized. Sometimes your website flow requires you to pass data to the Library before the first request is even made. 

To allow this behavior you can place a Session Object into the variable named "fscSession" before initializing the Library:

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

If you define the "fscSession" variable before the API is loaded, its contents are executed with the first priority. In this example, the session will be reset (breaking continuous mode), the "arkanoid" product will be added to cart, and a coupon will be applied immediately when loading the API.

Public Methods Exposed by the Library

After the Library is loaded, your webpage can access it using public methods.

The core method is called fastspring.builder.push(payload);

fastspring.builder.push takes a Session Object payload as input and applies data to the session. 

var s = {
	'products' : [
					{
						'path':'arkanoid',
						'quantity': 1
					}
	],
	'coupon': 'YOUR10OFF',
	'checkout': true
}

fastspring.builder.push(s);

Tip

In addition to "checkout": true, you can optionally pass "paymentMethod":"paypal" to attempt to skip the Storefront and send the customer directly to PayPal.

Each call to fastspring.builder.push() method will usually result in an updated order data obtained from FastSpring backend. If you registered callback functions when initializing the Library your functions will be called with corresponding data on each request made allowing you to create a tight integration between platforms. See Getting Started with Store Builder Library for more information.

Additional Public Methods

In addition to fastspring.builder.push() Library exposes a number of public methods. All of them are easy-to-use wrappers around fastspring.builder.push(). 

  • fastspring.builder.checkout() – Expects either no input or a session ID obtained after pre-creating a session using the server API.
  • fastspring.builder.payment("paypal") – Launches the checkout and attempts to skip the Storefront and send the customer directly to PayPal.
  • fastspring.builder.promo(code) – Takes coupon code as input, applies it to the cart.
  • fastspring.builder.postalCode() - Takes the customer's postal code as input, and applies it to the session for the purpose of calculating sales tax (when the order country is United States). This allows you to display sales tax amounts for U.S. orders on your page prior to checkout.
  • fastspring.builder.taxId(id) - Takes the customer's GST ID or VAT ID as input, attempts to validate it in conjunction with the customer's country (detected via geo IP location or set by fastspring.builder.country()). If the ID is validated successfully, it is applied to the session and no VAT or GST will be applied. 
  • fastspring.builder.update(productId,qty) – Takes product ID and quantity as input, updates specified product's quantity in the cart. Example: ('product-path',1)
  • fastspring.builder.add(productId) – Takes product ID as input, adds product to cart.
  • fastspring.builder.remove(productId) – Takes product ID as input, removes product from the cart.
  • fastspring.builder.tag({"key":"value","key2":"value2"}) – Takes one or more key and value pairs as input, applies tag(s) to the session.
    Note:  The key and value pairs must be supplied using valid JSON formatting, as in the example here.
    Note:
     The sum of the number of characters supplied for the key and the value must not exceed approximately 4,000 characters. 
  • fastspring.builder.reset() – No input, resets the cart immediately.
  • fastspring.builder.clean() – No input, resets the cart after redirecting to checkout.
  • fastspring.builder.secure(securePayload, secureKey) – Takes secure payload (encrypted or plain text, depending on the storefront state) and secure key as input, applies secure payload to the current session. See Passing Sensitive Data with Secure Requests.
  • fastspring.builder.authenticate(securePayload, secureKey) – Takes secure payload (encrypted or plain text, depending on the storefront state) and secure key as input and if payload contains customer id redirects customer to the account/subscription management page.
  • fastspring.builder.recognize({paymentContact object}) – Applies "tentatively" known (unconfirmed) customer information to the order but will not hide input fields during the checkout process. See paymentContact object above for object definition.
    To pass "known" and "confirmed" information refer to Passing Sensitive Data with Secure Requests.
  • fastspring.builder.recognizeRecipients({recipient object}) - Applies "tentatively" known (unconfirmed) gift recipient information to the order but will not hide input fields during the checkout process. See recipient object above for object definition.
    To pass "known" and "confirmed" information, refer to Passing Sensitive Data with Secure Requests. This method requires SBL version 0.7.7 or greater.
  • fastspring.builder.country(countryCode) – Change checkout country to the "countryCode" (where countryCode is a two-letter country code – "US", "DE", ...)
  • fastspring.builder.language(language) – Change checkout language to "language" (where language is a two-letter language code – "es", "de", ...)

Public Methods Callback Function

All public methods accept an additional parameter – callback function. This function will be called after the specific request was made. Unlike generic "data-data-callback" which is called once for a request chain (meaning that if multiple consequent requests are made only last request will return order object) callback functions passed to public methods will be called with the order object resulted from the call giving you more flexibility around integration. 

 fastspring.builder.add("arkanoid", function(data){
 
	console.log("Added 'arkanoid' and it resulted in the following order object", data);
 
});

Callback function is always passed as the last parameter. 

fastspring.builder.checkout() method does not accept callback function as a parameter due to its "finite" nature.

Errors

Some requests might result in errors received from server. All errors are fatal – if an error is encountered processing stops and error is returned. The easiest way to handle errors is to declare "error callback" function when initializing the Library.

In case of an error the body of the response will contain one of the following "codes":

General Session Related

  • session-payload-invalid – Couldn't understand the data in the "session" parameter.
  • session-expired – Serialized session data has expired.
  • empty-session – Tried to finalize / checkout a session with no items.
  • path-not-found – Couldn't find the product variation referenced in session data.
  • envelope-invalid – Error parsing secure payload

Adding a Product

  • quantity-invalid – Passed a bad quantity value.
  • not-removable – Product is not allowed to be removed from the session.
  • path-not-found – Couldn't find the product variation.

Field Validation

Starting with Store Builder Library (SBL) version 0.7.9, the payload of the order object response includes an array named fields, which provides up-to-date validation details regarding certain fields of the order session data. The field validation data can also optionally be provided to your dedicated script via the data-validation-callback.

The following order session fields are validated:

  • firstName (validation only checks whether or not this is present)
  • lastName (validation only checks whether or not this is present)
  • country
  • email
  • postalCode (validation only occurs when country = "US")
  • taxId
  • language
  • coupon
  • account

Each object in the fields array may consist of the following items:

NameTypeDescription
fieldNamestringthe name of the current field in the array
requiredBooleanindicates whether the field is required to process an order
providedBooleanindicates whether or not you have provided value for the current field
transportstringonly appears when provided is true;
indicates the method of submitting the session data via SBL:
"secure" for secure payloads; otherwise, "recognize"
validBooleanonly appears when provided is true;
indicates whether or not the provided value is valid
errorobjectonly appears when valid is false
error.codestringerror code regarding the current field
error.messagestringverbose error message regarding the current field


Error Codes and Messages

error.codeerror.message
country-invalidCountry Code is not Valid*
email-invalidEmail is not Valid
postalcode-invalidPostal Code is not Valid
taxid-invalidTax ID is not Valid
language-invalidLanguage passed is not Valid
coupon-invalidCoupon Code is not Valid
account-invalidAccount ID is not Valid

Note

*If an invalid country is passed via fastspring.builder.push(), fastspring.builder.recognize(), or fastspring.builder.secure(), the invalid value will be discarded and geo IP will be used to set the order country. However, fastspring.builder.country() can result in this field validation error.
Example of the "fields" array
   "fields":[  
      {  
         "fieldName":"firstName",
         "required":true,
         "provided":true,
         "transport":"recognize",
         "valid":true
      },
      {  
         "fieldName":"lastName",
         "required":true,
         "provided":true,
         "transport":"recognize",
         "valid":true
      },
      {  
         "fieldName":"country",
         "required":true,
         "provided":true,
         "transport":"recognize",
         "valid":true
      },
      {  
         "fieldName":"email",
         "required":true,
         "provided":true,
         "transport":"recognize",
         "valid":true
      },
      {  
         "fieldName":"postalCode",
         "required":true,
         "provided":true,
         "transport":"recognize",
         "valid":false,
         "error":{  
            "code":"postalcode-invalid",
            "display":"Postal Code is not Valid"
         }
      },
      {  
         "fieldName":"taxId",
         "required":false,
         "provided":false
      },
      {  
         "fieldName":"language",
         "required":false,
         "provided":false
      },
      {  
         "fieldName":"coupon",
         "required":false,
         "provided":false
      },
      {  
         "fieldName":"account",
         "required":false,
         "provided":false
      }
   ],  

Order Object Response Fields

{  
   "currency":"USD",
   "country":"US",
   "taxExemptionAllowed":false,                    // based on "country", indicates whether or not it is possible to supply an ID (e.g. VAT ID, GST ID) and remove tax from the order
   "taxExempt":false,                              // indicates whether or not the current order is exempt from tax
   "total":"$6.17",                                // order total without tax
   "totalValue":6.17,                              // order total value (without the currency symbol), without tax
   "tax":"$0.45",                                  // total amount of VAT or sales tax
   "taxValue":0.45,
   "totalWithTax":"$6.62",                         // this price will be charged; it accounts for quantity, discounts and unit price.
   "totalWithTaxValue":6.62,                       // order total with tax but without the currency symbol
   "discountTotal":"$6.17",                        // total discount for the order
   "discountTotalValue":6.17,
   "discountTotalPercent":"50%",
   "discountTotalPercentValue":50.0,
   "taxPriceType":"added",                         // "included" or "added"; indicates whether tax is included in the subtotal or added to the subtotal
   "taxType":"US",                                 // "US" (US state/local sales tax) | "VAT" (Value Added Tax, e.g. in the EU) | "GST" (Goods and Services Tax, e.g. in Australia) | "JP" (Japan's Consumption Tax)
   "taxRate":"7.25%",                              // the tax rate applied to the current order if taxExempt is false, expressed as a percentage; "0%" if unknown (e.g. country / postal code have not been supplied)
   "groups":[  
      {  
         "items":[              
            {  
               "selected":true,                    // indicates whether the item is in the order
               "path":"nest",                      // internal product id / product path
               "pid":"nest",                       // internal product id (backward compatibility)
               "quantity":1,                       // quantity of the item
               "price":"$12.34",                   
               "priceValue":12.34,
               "priceTotal":"$12.34",              // quantity multiplied by item's unit price
               "priceTotalValue":12.34,
               "unitPrice":"$6.17",                // unit price of the item
               "unitPriceValue":6.17,
               "unitDiscount":"$6.17",
               "unitDiscountValue":6.17,
               "discountPercent":"50%",
               "discountPercentValue":50.0,
               "discountTotal":"$6.17",
               "discountTotalValue":6.17,
               "total":"$6.17",                    
               "totalValue":6.17,
               "priceWithoutTax":"$6.17",          // when net pricing is enabled, this string indicates the price of the current item without applicable tax
               "priceValueWithoutTax":6.17,        // when net pricing is enabled, the numeric value of the price before tax (with no currency symbol)
               "quantityEditable":true,            // indicates whether or not visitor is allowed to change the quantity of the item
               "removable":true,                   // indicates whether or not visitor is allowed to remove the item from the cart
               "image":"https://d8y8nchqlnmka.cloudfront.net/VTetZH1kQD8/r7kju5MHTRQ/nest-box.png",
               "display":"Nest",                   // product display name; show this to the visitor
               "sku":"furious14",
               "description":{  
                  "summary":"<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>",
                  "full":"<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vel mi quam. Etiam non purus et est volutpat aliquet. Sed a urna nec nisi scelerisque maximus. Aenean vitae cursus augue. Phasellus eu finibus ex. Morbi auctor nec leo vel suscipit. Sed non condimentum elit.</p>",
                  "action":"Buy Now"
               },
               "pricing":{  
                  "quantity":"allow"               // allow: visitor is allowed to change quantity. lock: visitor is shown quantity, but can't change. hide: visitor can't see quantity  
               },
               "discount":{  
                  "reason":"Halloween Special!",
                  "coupon":"HALFOFF",
                  "data":{  
                     "tiers":[  

                     ],
                     "discountPath":null,
                     "discountDuration":null,
                     "percentValue":50.0
                  }
               },
               "groups":[                          // if item contains upsells, options, choose-one and choose-many configuration parameters they will appear here; the format is the same as the parent item.  

               ],
               "productFormat":"digital",
               "priceWithoutTaxAndDiscounts":"$12.34",   // when net pricing is enabled, this string indicates the unit price of the current item, before tax and any coupon discounts
               "priceValueWithoutTaxAndDiscounts":12.34, // when net pricing is enabled, the numeric value of the unit price of the current item, before tax and any coupon discounts (without the currency symbol)
               "product":"nest",
               "variation":"nest",
               "attributes":{  
                  "ProductAttributeKey1":"ProductAttributeValue1",
                  "ProductAttributeKey2":"ProductAttributeValue2"
               }
            }
         ],
         "driver":"furiousfalcon-popup-furiousfalcon",  // explains why the group is present in the response; may list a product path if the group is a cross-sell group for a specific product, or may list the Storefront URL if the group is associated with the Storefront
         "required":false,
         "type":"add",
         "selections":true                         // indicates whether or not this group of items contains selected items
      },
      {  
         "display":"Customers also purchased...",  // some group items will have their own display names; this means that items in the group have a header (note:  this line has been added to the example for illustrative purposes)
         "items":[  
            {  
               "selected":false,
               "path":"SystemExtension.eds",
               "pid":"SystemExtension.eds",
               "quantity":1,
               "price":"$4.95",
               "priceValue":4.95,
               "priceTotal":"$4.95",
               "priceTotalValue":4.95,
               "unitPrice":"$4.95",
               "unitPriceValue":4.95,
               "unitDiscountValue":0.0,
               "discountPercentValue":0.0,
               "discountTotal":"$0.00",
               "discountTotalValue":0.0,
               "total":"$4.95",
               "totalValue":4.95,
               "priceWithoutTax":"$4.95",
               "priceValueWithoutTax":4.95,
               "quantityEditable":false,
               "removable":true,
               "image":"https://d8y8nchqlnmka.cloudfront.net/VTetZH1kQD8/vedymJXwSBY/download-icon-small.jpg",
               "display":"Extended Download Service",
               "description":{  
                  "summary":"<p><strong>Extend the availability of your download today!</strong> By default, all file downloads are available for seven days from the date of the purchase. However, if you purchase EDS, all products in this order that have file downloads will be downloadable from FastSpring for one year from the date of your purchase.</p>"
               },
               "pricing":{  
                  "quantity":"hide"
               },
               "groups":[  

               ],
               "priceWithoutTaxAndDiscounts":"$4.95",
               "priceValueWithoutTaxAndDiscounts":4.95,
               "product":"SystemExtension.eds",
               "variation":"SystemExtension.eds"
            }
         ],
         "driver":"furiousfalcon-popup-furiousfalcon",
         "required":false,
         "type":"add",
         "selections":false
      }
   ],
   "coupons":[                                     // coupon applied to the order  
      "HALFOFF"
   ],
   "payments":[                                    // list of payment options available for this order; currently the selected payment method cannot be pre-populated via SBL  

   ],
   "fields":[                                      // see Errors:  Field Validation above  
      {  
         "fieldName":"firstName",
         "required":true,
         "provided":false
      },
      {  
         "fieldName":"lastName",
         "required":true,
         "provided":false
      },
      {  
         "fieldName":"country",
         "required":true,
         "provided":false
      },
      {  
         "fieldName":"email",
         "required":true,
         "provided":false
      },
      {  
         "fieldName":"postalCode",
         "required":true,
         "provided":true,
         "transport":"recognize",
         "valid":true
      },
      {  
         "fieldName":"taxId",
         "required":false,
         "provided":false
      },
      {  
         "fieldName":"language",
         "required":false,
         "provided":false
      },
      {  
         "fieldName":"coupon",
         "required":false,
         "provided":true,
         "transport":"recognize",
         "valid":true
      },
      {  
         "fieldName":"account",
         "required":false,
         "provided":false
      }
   ],
   "gift":false,
   "postalCode":"68512",
   "availablePaymentMethods":[                     // array listing which payment methods are currently available based on session detail such as cart contents and order country
      "wire",
      "paypal",
      "card",
      "purchaseorder",
      "amazon"
   ],
   "language":"en",                                // current session language (based on browser default or user selection)
   "expires":1550961521056,                        // expiration date of the current session
   "messages":[  
   ],
   "selections":true,
   "tags":{                                        // order-level custom tags
      "key1":"value1"
   },
   "creationTime":0,
   "serial":"H4sIAAAAAAAAAJWURbKE2BZFB0RUoIk0qoG7a9LD3S7wkKjB_5zCb54dp7W22KCsgF_te7fM_NhV8-Ef2VH9gyEog2AY-t_HgNSpbxvJ7Kg6ru2QOTVkmceo4nziSaKewXIuKfD8Ye3wtj-AnxWbQFUoLBRqkV0wEUdzd29qPGmYYCUtrtwwgjUz4V5aDbNnLnsTXSkH1IIS0IKv-t_nOxushE7dxQF_WWgbjSbxGm52V1hB6baDrEOfv4PS_CNGJNP7DbdCk57TbTBnUaD2pG_DTQBo_bcuSO4G_ldT4u4OnyvKLZksi1YUOdOVeP4YbbvXGYEdK44-cdD2O7vThChWMqTzKNz077biJ4peXxUvEAgixmtGxE13hCNKW1MzXYO72JvYQDWjYrOHeGBAWil3C3m8keAU7_gdqTqo28iHYHyym1XRIidKagjivHjvDpqfWsldaRayAmb5ujCWcsZdS7WaquFAUo1Ias051PBo0r4rlglcCQjOnn9xt7dcvlXTa-riakbVDoNuWCT76OHZ4mrEBeYcYUJ8OzrxJijNX7Q_P1UiXYCNvk8_f1mMNqaVoW_DbTWomx18f2xtWWdAcH45ZIbhSj4aBaXgNjhouFz9w7YU_j_4-yjOEq5zxWoZL9ZmR5KE_XHDC10ZyeC4T09G2gL3_TysAZrP5XEvraGLsGpn-AsAtmZsUicqcFWG617DPQ2uejRJlETHodyweHS7JnCPI3ZiwT8PvgEKHfWQ0AxutpddWCd7LpDipzsonRU7Lz9ne98QGZMJbiZO6LuhWj0w1dyXw1HCNQ6mQ2IvvPAuOv2cdIOQlGwvJplZLSMG_csJVgsFXev2cbuHJfMjKh70RS0EHqTSsUWPMhqIeQZJkryjKdB4TJQPd-CvwRo7GxDb1xKU9Phm-ydZSUGfBNZTbk6DGhGPBDxMOkAp-0y2EUWzU1XN1tJoc6_TawRou1JOnOSJzB_acsJkYcUzu_2VL6VGwbWCSSSu0gGDFjfjiwNF633hTLsCPLdeF7rmhXUXoAjBQyTjdIpEF35d_tq6jR8EYTr7aEjeLBHpdCbIOjzSSbyYPlaCm3lOeB7V3qVP1CTcbHIGrQBM7zncZuOiBvwDn_3gGXCUrXvA4sukx_UHueU8UY9qrcVyqjIjyrHcbxQRs_Zv7sxRdbSwnXh5llGS9IoJIeSXNQQMF1Ify1LOlkD77rGPCiEmBOH43IG-6Oge0qhXW1Ofsl53SY2qsKTEfUJQHTvW5XX3XEFVGPhDxb-bxlDD4TeNmiNGJl23rp0fNj2YFOP7CsglUptgoXRZABqxjZySIllAngOO9Zcr03UMRIyxlzuTgi7_lf0u0wp3UTwlhzr58FRxU7LuOQ7bHPDj77DvTJptfDaH-AOs4mZeXNhjN6i9Rfo2hk3L6FtcwzGqyllp9l30HTXOMc9SUvskAhHG03yGdHqHlOQgYp_1Ql6BeBP1at3yDIlJP83cIoFwHfZTNZobljT_IDpQ0fTMpSUvXN4i3n3q92QXVDAbXgANjhoiB_aQyngaagaeAz2ojFX24hs8n2hUD1OU220aU3lPJA1PRTR9MH9rv6PogJovgQNVLETLWPBiN1hYqZSwqBWmceSghMJWW0RY9G_rQo0s2-NzXQO2C0frUkmR--wuzR51NyyET-NsSChFQyN6h6Yzc743hkcq1QWb4tNuWf0BXFfo7oc1JySThqppcnxRP5DRZmS7-1kcIslK1XR1Vj2uOe4Mk9VpRtLXjHtNpIt6i14JSGZpvjVYLEekO9eKng_EWSYqRGKkVZBsUkVYpXhHwc6iL7Lwoie_oeNRUOO2HvQFV7GDyFyzs9hsIFqXEo2LIDqsZJPZApz6k1FKX61WMkTdVX-uG-HQNlUukW6fcQzHeb6hc8IJ0CG3Qu_7y2ToLIc3-czdjBP--6h3_phveaf5nOpyXQUxM0ui_Md51gR2hHqEeMiFrZQun_mQSGCahDI0CstT70PizaD0btD6zZMQ1Tfqjf1ex_6xK_kWfa-LS_6xBo3bCZ3hAM3ayVjVmnn5QS7MnDiH4v2mOLUl47w1mtPe5PEbbwnvX8qhtuBUsEqGZTVq-lu7KREt2PIp_Yaqz8G201oZpvVyMK8ukb-ljqgnGxc2ZjJo_iJC1yb5V58TSYbwllDw3ygE4wkLt0jiti7q0Z_tAmvcldeYy82j4i4ZDKVhhuLSBvTHDfIN5nSqMSXiuGM0rXx8LPBC2H8pcpgQTb5dQ-MsaileOCIHX1XSGjLF5lbBVoAbjDj_NII4YFhtPqwr5vIqmK88_Wb7tZILSablfWMOKeOK9odn2FaMCOT0gFhrOh-QQK4O_c5RSAb2VhflY5jZRQpnq5lfWc3jJCjdTiww7ttwVWMycH5jd7I2DO70cYZiKd3WmsF3dNbfO1N70KHxtEmJxy5mUbm2Rh5ahsfiWcKICR6sSO74ibFYWsuf4bK6nf39-ZuZyC7mCEuo5qmjZlk2NfUQThuotgWHLg90aIEyt5eqId7aGUzff_8HiXdKk80JAAA"
}