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 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 ServicesProbably only Casper at this time (— , May 2023).
== 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:
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 Hash calculated by your ANS/SLM Processor. The Verification Hash calculated by the SL Marketplace is provided in the header field and can be read by accessing the “” headerThe 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). — , May 2023. In addition to the Verification Hash, your processor must also know your Merchant-specific Salt Code.
. 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 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 which will resemble the following text:
Category:Marketplace