Direct Delivery and Automatic Notification System
In the early days of the SL Exchange virtual goods sales website, the authors of the site implemented a feature that came to be known as “Automatic Notification System” or ANS for short. Details about every sale made through the website were bundled into a single transaction and forwarded to either an outside website or an In-World object.
SL Exchange then changed their name to XStreet SL, at which point Linden Lab purchased it and then retired it in favor of their new SL Marketplace. After the release of the SL Marketplace, they continued to support the ANS feature and even enhanced it some by redefining some of the values provided and reusing some that had fallen into disuse.
Now that Linden Lab has released their Direct Delivery service, the ANS feature has again been modified to support the same functionality and to ensure its viability into the future.
Who Should Read This Document
If you are a Merchant already using ANS as it exists for support of sales made through the Magic Box, then you will want to read this document to learn how it has been changed and what you will need to do in order to support the new format and features of ANS.
If you are a Merchant that is either not familiar with ANS or is not currently using it but you would like more control over your sales and customer data, you should read this document to learn how it might help you track sales, support your customers, compile marketing and advertising data and give you better information about your business.
ANS Overview
The ANS feature of the SL Marketplace forwards information about every sale made on the SL Marketplace to an outside website. A program or web page on the receiving site is responsible for accepting the information, called an ANS Transaction Record, and processing it in whatever fashion is desired. That program or web page is called the “ANS Processor”.
In order to make use of the ANS Transaction Record, you must be capable of writing and hosting the ANS Processor yourself; Linden Lab does not provide this service. If you are not able to do the programming yourself but you wish to utilize the information provided by ANS, you may wish to contact one of the third parties that offers ANS Processing Services[1].
Versions of ANS
There are two different versions of ANS presently supported by the SL Marketplace. One version called “ANS/XS” supports sales delivered only from a Magic Box. It is sent by the old XStreet SL website and has been in use by the SL Marketplace. The other version called “ANS/SLM” supports sales delivered via Magic Boxes or Direct Delivery and is sent by the SL Marketplace. Most of the information provided by the two versions is identical; however, there are key differences that are important to understand.
ANS/XS – ANS for XStreet SL
The ANS Transaction Record sent by the XStreet SL website defines the item delivered and specific details about the product on the SL Marketplace. The transaction record also includes information needed to verify that the record is correct and represents a valid sale. ANS/XS is capable of sending the ANS Transaction Record to either an external website or to an In-World Object. Note that the ANS Transaction Record is sent only for sales delivered by a Magic Box.
ANS/SLM – ANS for the SL Marketplace
The ANS Transaction Record sent from the SL Marketplace website contains the same basic information. However, the method of validating an ANS/SLM transaction varies significantly from that used for ANS/XS. Furthermore, the ANS/SLM version will only send an ANS Transaction Record to an external website; it does not support sending the record to an In-World Object. The ANS/SLM Transaction Record is sent for every sale regardless of the delivery method, Magic Box or Direct Delivery.
Basic ANS Transaction Record
The basic ANS Transaction Record contains the following information. Note that the order of the fields is not important; your ANS Processor should be capable of accepting the fields in any order provided.
Field Name | Description | Type | Size | Comments |
---|---|---|---|---|
Currency | The type of currency used for the purchase. | varchar | 10 | Always "SLL" |
Type | The type of transaction | varchar | 50 | "Purchase", or "Redelivery" |
PaymentGross | The total amount of the purchase price paid | varchar | 12 | |
PaymentFee | The commission fee charged by the SL Marketplace | varchar | 12 | |
PayerName | The Purchaser’s Account Name | varchar | 100 | Note 5 |
PayerKey | The Purchaser’s Avatar UUID | varchar | 36 | |
ReceiverName | The Receiver’s Account Name | varchar | 100 | Note 5 |
ReceiverKey | The Receiver’s Avatar UUID | varchar | 36 | |
MerchantName | The Merchant’s Account Name | varchar | 100 | Note 5 |
MerchantKey | The Merchant’s Avatar UUID | varchar | 36 | |
TransactionID | SL Marketplace Order Number | bigint | 20 | |
ItemID | SL Marketplace Product ID Number | int | 10 | Note 1 |
ItemName | SL Marketplace Product Name | varchar | 100 | Note 2 |
InventoryName | Magic Box Contents Object Name | varchar | 100 | Note 3 |
Location | SL Marketplace Order Line Item ID Number | varchar | 40 | Note 4 |
Note 1: Every product listed on the SL Marketplace is assigned a unique Product ID Number. You can determine a product’s ID Number by examining the URL of the Product’s Listing page. The Product ID Number is the last part of the URL.
Note 2: This is the Item Name as shown on the Product’s Listing Page on the SL Marketplace.
Note 3: This is the name of the Inventory Object or the Top-Level Folder delivered when the Product is purchased. In the case of ANS/XS it will always be the name of the Object contained within the Contents of the Magic Box. For ANS/SLM it is the name of the Object (if delivered from a Magic Box) or the Top-Level Folder (if delivered via Direct Delivery).
Note 4: Orders on the SL Marketplace may contain up to 10 separate items, each detailed on a separate line. The Line Item ID Number uniquely identifies the specific line item within the Order.
Note 5: The Account Name is either two words for older "Legacy" names or one word for newer single-word accounts; the last name "Resident" is not included for single-word account names.
ANS/XS Specific Fields
When a product is delivered from a Magic Box, there is one additional field included that will contain important data as follows:
Field Name | Description | Type | Size | Comments |
---|---|---|---|---|
VerifyKey | Transaction Specific Verification Key | varchar | 100 |
, The VerifyKey field will contain a 32-character string that is supplied to the XStreetSL.com website for verification. If the ANS Transaction is valid, the XStreetSL.com website will return “SUCCESS”; otherwise, it will return “FAILURE”.
In order to verify each transaction, your ANS/XS Processor must perform an HTTP GET to the following URL:
https://www.xstreetsl.com/ans.php?VerifyKey=<VerifyKey> |
You must include the 32-character string supplied in the VerifyKey field as part of the URL as shown above.
ANS/SLM Specific Fields
When a product is delivered from the SL Marketplace, the VerifyKey field is included but it will always be empty and thus can be disregarded. Additionally, the Region field contains the hard-coded text “SLM”. This field can be used to verify that the source of the ANS Transaction is the SL Marketplace.
Field Name | Description | Type | Size | Comments |
---|---|---|---|---|
VerifyKey | Transaction Specific Verification Key | varchar | 100 | Always empty |
Region | Website Identifier | varchar | 100 | Always "SLM" |
Validating an ANS/SLM Transaction Record
Included in the HTTP Headers sent to your ANS/SLM Processor is a 40-character Verification Hash that can be used to compare against the 40-character SHA1 Hash calculated by your ANS/SLM Processor. The Verification Hash calculated by the SL Marketplace is provided in the X-ANS-Verify-Hash header field and can be read by accessing the “HTTP_X_ANS_VERIFY_HASH” header[2]. In addition to the Verification Hash, your processor must also know your Merchant-specific Salt Code.
When you set the URL of your ANS/SLM Processor in the Merchant ANS Configuration, a Salt Code will be generated and displayed[where?] . You must note the Salt Code and program it into your ANS/SLM Processor (or add it to your Third-Party Merchant Configuration). Once the Salt Code is known, you can calculate the Verification Hash and compare it against the Verification Hash provided in the X-ANS-Verify-Hash header.
PHP Example
Here is an example PHP snippet that retrieves the proper HTTP Header containing the Verification Hash provided by the SL Marketplace then uses the ANS Transaction Record and the Salt Code to calculate and compare to the Verification Hash.
<?php
$myDDHash = $_SERVER['HTTP_X_ANS_VERIFY_HASH'];
$myDDSalt = <Your Salt Code Here>;
$myCalcHash = sha1($_SERVER['QUERY_STRING'] . $myDDSalt);
if ($myDDHash == $myCalcHash) {
echo "Valid ANS Transaction";
} else {
echo "Invalid ANS Transaction";
}
C# Example
Here's a corresponding .NET Framework 3.5/C# example:
// ANS Validation - Antonius Frentis
string calcHash;
string saltCode = "Your Salt Code Here";
string serverHash = Request.Headers["X-ANS-Verify-Hash"];
calcHash = FormsAuthentication.HashPasswordForStoringInConfigFile(Request.Url.Query.Remove(0,1) + saltCode, "SHA1").ToLowerInvariant();
if (calcHash == serverHash)
{
// Valid ANS Transaction
}
else
{
// Invalid ANS Transaction
}
Python Example
Here is an example in Python to process the information sent and to check the verification hash. Note that the salt is hardcoded in the code, and it is provided simply as an example of how to process the fields and verify the message using Python.
Note that the code is assuming a UNIX environment. If you are in a Linux environment the location of the Python shell will likely have to be changed to be consistent with your system.
#!/usr/local/bin/python
import os
import sys
import cgi
import hashlib
# Open the file to write the information to and post the http header
fp = open("/tmp/ans.txt","w")
print("Content-Type: text/html\n\n");
# Print out the verification hash
try:
fp.write("Verify: {0}\n".format(os.environ['HTTP_X_ANS_VERIFY_HASH']))
except KeyError:
print("Error - no verification string sent")
fp.close()
sys.exit()
# Check to see if the query string is consistent with the verification
# hash
mySalt = "1234567890abcdef" # This is the salt given to us in the marketplace
checkHash = hashlib.sha1()
try:
checkHash.update(os.environ['QUERY_STRING'])
except KeyError:
print("Error - no query string sent")
fp.close()
sys.exit()
checkHash.update(mySalt)
fp.write("Query string hash: {0}\n".format(checkHash.hexdigest()))
# Now print out all of the form fields
formValues = cgi.FieldStorage()
fp.write("\n\nForm fields:\n")
for a in formValues:
fp.write("{0}: {1}\n".format(a,formValues.getfirst(a)))
# Finally print out the uuid of the account that the item was sent to.
try:
fp.write("The uuid of the person who received this item is {0}\n".format(\
formValues.getfirst('ReceiverKey')))
except KeyError:
fp.write("There was no receiver listed.\n")
fp.flush()
fp.close()
The python code above will create a file /tmp/ans.txt which will resemble the following text:
Verify: db10b66eafefe87e8484b0e9547ae28ce3763e86 Query string hash: db10b66eafefe87e8484b0e9547ae28ce3763e86 Form fields: ItemID: 5555555 ReceiverName: buyer resident MerchantName: seller resident MerchantKey: 111222333444555666 ReceiverKey: 777888999000aaabbb InventoryName: Gift Card For You Type: Purchase Region: SLM PaymentFee: 6 Currency: SLL PaymentGross: 125 Location: 1234567890 PayerKey: 777888999000aaabbb TransactionID: 998877665544 ItemName: Gift Card For You PayerName: buyer resident The uuid of the person who received this item is 777888999000aaabbb |
- ↑ Probably only Casper at this time (— Gwyneth Llewelyn, May 2023)
- ↑ The confusion between the two styles of writing the name of this HTTP header has mostly to do with the way Apache/mod_php reinterprets the headers; it might not apply on different programming languages systems and/or different ways of running the PHP interpreter with the webserver (e.g. PHP-FPM). — Gwyneth Llewelyn, May 2023