Updated July 23 1998

Digital Commerce API

An Educom/IMS working paper
by Brad Cox, Ph.D.

Figure

This describes the API of the first three levels of the digital commerce architecture in this figure. This document concentrates on defining an API sufficient to support implementation efforts during 1998. The resulting prototype will provide an experimental framework for considering technocentric and sociocentric design issues including hardware-based metering, encryption, and rules of just conduct. These will be addressed in subsequent versions.

Terminology

This section summarizes prior sections of this report by identifying the essential elements of the invocation metering and superdistribution backoffice system.

Back office
Initially, deployment will be restricted to small trusted markets (companies and universities) and the back office will be a server managed by a localized (undistributed) enterprise analogous to a local bank. When deployment extends to untrusted markets, the back office becomes analogous to a banking franchise such as Visa with many local branch offices. Each backoffice serves its local customer base while coordinating global issues such as ID uniqueness with the franchise as a whole.

Meter
A meter encapsulates a cache of invocation records and the BID of the back office that will handle billing for that instance. The meter exposes five method calls that products invoke to record invocations. During the prototype stage, deployment will be restricted to trusted markets (corporations and universities) and software-based meters will be used. For deployment to untrusted markets (internet as a whole), the meter will be hardware protected. The ideal (most tamper-resistant) location is within the CPU chip, but several less secure interim packaging options are imaginable, some of which are discussed here.

Person, Customer, Consumer, Producer
A Person is a legally responsible entity such as an individual, student, corporation, university, or government. A Person becomes a Customer by registering as such with the superdistribution backoffice. A Consumer is a Customer that is recognized as a customer in good standing by their back office. A Producer is a Consumer who has registered a product for sale via invocation metering. The relationship between these terms is shown in this Venn diagram:

The registration process begins with an SSL-protected browser-based interaction between the customer and the back office. The customer fills in web forms with the information the back office needs to handle financial transactions for that customer and agrees to legally binding rules of just conduct.

The only difference between consumers (such as students) and producers (such as courseware providers) is that producers, in addition to being consumers, have registered a digital product for invocation-based revenue collection. The metering infrastructure empowers every customer to consume and produce digital goods and supports both roles via the same CID.

Product
Digital product is a generic name for executable computer code of any granularity that uses the invocation-metering infrastructure for revenue collection. Examples are courseware, digital books, computer applications, subroutines, or methods; any object whose state information is accessible only via executable code that is an intrinsic part of the object. Note that passive data elements such as HTML pages, text files, or GIF images are not protectable via invocation metering unless they are enclosed in executable wrappers.

Customers develop products as usual, the only difference being that an invocation meter is present in the development and testing machine. This is to enable (and charge for) the use of sub components by the tools used by the developer, subcomponents used by the product under test, and to support meter calls from the product itself. Development stage products will typically be tested under a special PID used only for product testing. Other PIDs will be used for post-development versions to reflect that their use is covered by different terms and conditions.

PIDs are issued to producers during a web-based interaction with the back office server at the developer's the local branch. The producer (owner) provides the information that the back office needs to establish ownership (CID) and agrees to rules of just conduct. The same interaction provides the TACA (Terms And Conditions Algorithm) that the back office will use to convert invocation counts to monetary amounts due. A successful interaction concludes with the back office issuing a globally unique (franchise-wide) PID that the owner hard-codes into all meter calls made by this product.

Notice that PIDs uniquely identify a backoffice record and that each record contains precisely one TACA. If a given version of a digital property is to be marketed with different terms and conditions, this will be handled by requesting a distinct PID for each one.

Terms and Conditions Algorithm (TACAs)
TACAs are executable programs that the back office invokes to transform an invocation record stream into monetary amounts. They are managed exclusively by the back office server. They only appear elsewhere (on clients) during product development and testing. In particular, digital products do not "contain" them. Rather, a product identifies itself to the back office via its PID and the back office uses this to locate the corresponding TACA. TACAs are discussed in more detail elsewhere.

This document will use this shorthand for the concepts described above.

BID: BackofficeID
This identifies the back office that this meter will report to. This will be an ordinary URL during prototyping. BID subclasses may be added to support communication methods over time (dialup connections, etc.).

MID: Meter ID
Uniquely identifies the meter and is traceable to the customer who is legally responsible for misuse of that meter according to rules of just conduct that this customer agreed to when the meter was issued by the local back office. The MID plays no direct role in the revenue distribution process because it identifies a machine's owner as distinct from the person who is using software on that machine. It is maintained primarily because knowing who registered the meter may prove useful in rare cases such as fraud detection and prosecution.

CID: CustomerID
Uniquely identifies a back office micro account and thereby the entity (person or corporation) who is financially responsible for this account.

PID: ProductID
A string that uniquely identifies a digital product, and thereby the micro account that the back office will credit or debit in response to uses of, and by, other products by this product. The prototype implementation generates PIDs by appending a numeral to the user-supplied product name to ensure that all PIDs are unique.

These are all implemented as synonyms for ID. ID is a synonym for the Java String type. There are no restrictions on ID length or content except that each ID must uniquely identify a valid record in the franchise-wide database.

Error Reporting

All calls that cannot be completed will respond as follows:

<methodResponse>
 <fault>
  <value>
   <struct>
    <member>
     <name>faultCode</name>
      <value><int>4</int></value>
    </member>
    <member>
     <name>faultString</name>
      <value><string>Too many parameters.</string></value>
    </member>
  </struct>
 </value>
 </fault>
</methodResponse>

Session to Meter Interfaces

These calls identify the current user, e.g. the top-level account from which revenue will be drawn. These are called by the IMS Session creation/tear down logic. It is a violation of the rules of just conduct to call them otherwise.

public boolean Meter.login(CID ID){}

<methodCall>
 <methodName>login</methodName>
 <params>
  <param>
   <value>
    <string>CID</string>
   </value>
  </param>
 </params>
</methodCall>
<methodResponse>
 <params>
  <param>
   <value><bool>ok</bool></value>
  </param>
 </params>
</methodResponse>
CustomerID (CID) identifies the microaccount to be charged for subsequent transactions. The call returns true if the cid identifies a customer in good standing in the backoffice database, false if not.

public void logout(CID id){}

<methodCall>
 <methodName>logout</methodName>
 <params>
  <param>
   <value>
    <string>CID</string>
   </value>
  </param>
 </params>
</methodCall>
<methodResponse>
</methodResponse>
This signifies completion of the session that will be charged to this microaccount. Query() will return false until a subsequent Login call initiates a new session by establishing which account will be charged.

These calls are issued by digital property of any granularity to record uses of the property that issues these calls, as identified by PID.

void Meter.query(PID id)
throws requestDenied {}

<methodCall>
 <methodName>query</methodName>
 <params>
  <param>
   <value>
    <string>PID</string>
   </value>
  </param>
 </params>
</methodCall>
<methodResponse>
 <params>
  <param>
   <value><bool>ok</bool></value>
  </param>
 </params>
</methodResponse>
Reports whether this use will be allowed. The meter determines this by determining the CID of the party who will be charged for this use (from the enclosing login or query() record in the cache). It determines the account status from the hashtable that was returned by the backoffice and stored in the cache during the prior send operation. The call returns true if CID is a customer in good standing (as of the last send operation). It returns false if no meter is available or if the account of the owner of the calling object was marked "deny service" during the last upload cycle (non-payment, fraud, etc) (see the send method).

void Meter.commit(PID id) {}

<methodCall>
 <methodName>commit</methodName>
 <params>
  <param>
   <value>
    <string>PID</string>
   </value>
  </param>
 </params>
</methodCall>
<methodResponse>
</methodResponse>
Commits a usage of product PID into the cache. The backoffice will use PID's TACA to compute the charge. It will debit this charge against the micro-account of the CID derived from the immediately enclosing call. If the immediately enclosing call is a login(CID cid), the derived cid is the cid in the login call. If a query(), the derived CID is the CID of the owner of the PID in the query() call.

The backoffice credits this charge to the micro-account of PID's owner.

public void Meter.flush() {}

<methodCall>
 <methodName>flush</methodName>
 </params>
</methodCall>
<methodResponse>
</methodResponse>
Sends the cache to the back office and downloads a fresh reading of the account status of each CID in the current cache from the backoffice server.

This call should not be used routinely. It is for the benefit of products with such high value that their owner cannot rely on the normal upload cycle, which relies on cached account status information that can be as much as a month old.

Typically, the cache manages its upload cycle automatically, either as the cache fills or according to timing parameters that the backoffice preprogrammed into the meter. High-value products may decide to update the customer's account status before accepting another transaction. Calling flush() provides explicit control over flush frequency.

Backoffice to Meter Interfaces

The meter communicates with the backoffice via these interfaces. It is a violation of the rules of just conduct to use these calls otherwise.

public class MeterReading
{
	final static byte LOGIN = '{';
	final static byte LOGOUT = '}';
	final static byte QUERY = '(';
	final static byte COMMIT = ')';

	public byte CODE;
	public PID pid;
};
private java.util.Hashtable Meter.send(
     MID mid, 
     MeterReading[] meterReadings,
) {}
<methodCall>
 <methodName>send</methodName>
 <params>
  <param>
   <array>
    <struct>
     <member>
      <name>PID</name>
      <value><string>id</string></value>
     </member>
     <member>
      <name>code</name>
      <value><char>c</char></value>
     </member>
    </struct>
   </array>
  </param>
 </params>
</methodCall>
<methodResponse>
 <params>
  <param>
   <array>
    <struct>
     <member>
      <name>CID</name>
      <value><string>id</string></value>
     </member>
     <member>
      <name>status</name>
      <value><bool>s</bool></value>
     </member>
    </struct>
   </array>
  </param>
 </params>
</methodResponse>
This is called by the flush method to transmit the meter's cache to the backoffice and download account status information. The MeterReadings argument contains the cached meter readings.

Returns a hashtable whose keys are the CIDs of all records in this batch of cache and whose values are booleans. The meter stored this table internally to provide values for subsequent
query calls.

Utility Meter Interfaces

public int Meter.getCacheLevel() {}

<methodCall>
 <methodName>getCacheLevel</methodName>
</methodCall>
<methodResponse>
 <params>
  <param>
   <value><int>level</int></value>
  </param>
 </params>
</methodResponse>
Returns the cache level. The cache level is incremented by login() and query() calls and decremented by logout() and commit() calls.

public int Meter.getCacheCapacity() {}

<methodCall>
 <methodName>getCacheCapacity</methodName>
</methodCall>
<methodResponse>
 <params>
  <param>
   <value><int>capacity</int></value>
  </param>
 </params>
</methodResponse>
Returns the cache capacity established when the cache was instantiated.

public long Meter.getAccountBalance() {}

<methodCall>
 <methodName>getAccountBalance</methodName>
</methodCall>
<methodResponse>
 <params>
  <param>
   <value><i4>level</i4></value>
  </param>
 </params>
</methodResponse>
Flushes the cache to the backoffice. Returns the balance in the microaccount of the CID of the enclosing login() call; e.g. the account balance of the current user. Balances are maintained and reported in U.S. cents as 32 bit numbers.

Scenarios

HtmlPage
A string containing html markup. Such strings are computed by the backoffice web server and delivered to the browser for display to the user.

BID
The backoffice ID is configured into the meter by the backoffice to specify the backoffice this meter will connect to. Thus, BID.WebServer denotes a query to the web server of the backoffice that provided the meter that is installed on this person's computer.

1: Person registers as a Customer (example)

Person's browser presents the URL of BID's entry page to the backoffice's web server. The server returns a string containing an html page with forms the person can use to register a new account:

The specified backoffice (BID) examines the user-specified information and, if acceptable, returns an html page that discloses the globally-unique CID that will uniquely identify this customer from here on.

The backoffice may refuse the request for several reasons. It indicates this by throwing a Refused exception with a string containing an html page that describes the reason for the refusal and a telephone number to call to resolve the problem.

Question: This call is written as if accuracy of this information can be determined in real time. If not, this call will have to be revised to support delayed responses, perhaps via email.

Response: On the Register and Edit methods: Presumably you are asking how the back-office should confirm the operation. Since waiting on a separate thread for a delayed response is kind of a drag, especially for non-threaded environments, some call-back/send-back scenario is in order. One way is to for now call this an asynchronous method invocation and push it to the environment to deal with ( i.e., we declare the method as synchronous, and any delay handling, for a slow back-office or an off-line client, must be handled by some run-time service outside of us. That way, somebody creative could create an ansynch method invoke service that uses all sorts of things for its actual transport mechanism. ). Another way is to declare the asynchronous nature outright and provide a callback/notification URI member. It is then up to the back-office to determine the nature of the URI and make the appropriate call ( i.e., if it is a mailto: it sends the confirmation message ( a basic one defined by us ) via e-mail, if it is an iiop:// it sends the confirmation message as a CORBA method invoke ( again a basic one designed by us ). This problem is certainly not unique to your work, so it will be good for anyone involved to brainstorm and watch for other industry solutions.

2: Customer initiates a session (example)

The person types their identifier and password into the page that initiates an IMS session.

The server returns an html page whose content depends on the contents of the id and password provided. If the id isn't recognized by this backoffice, or if the password is incorrect, or if the cid field contains a valid email address, the server interprets the command as a request to email the correct cid and password to the customer.

In other words, if the person provides a correct identifier and password, the person is logged in and thereafter recognized as a specific customer. If the identifier is correct but the password is not, or if the identifier provided is an email address in the backoffice's database, the system interprets this as a sign that this person has either forgotten their identifier, password or both, or is a cracker trying to break into the account. The server handles such cases by emailing the correct identifier and password to the email address that was recorded when the account was established, thereby notifying the customer of possible fraudulent use of their account.

The response to a correct identifier and password is an editable form via which the customer can propose updates to their registration information. The form contains two sections, one for updating registration information and the other a listing of all products owned by this customer. The form contains buttons for submitting registration information changes and for registering products for this customer.

3: Customer registers a product (example)

The customer view/edit page lists all products owned by this person and provides a button for registering new products.

Note: The type, TACA, is not defined because I do not know how to declare "compiled and executable bytecodes of a function of three arguments returning a financial amount.

Response: On the TACA data type issue. What you are asking for is to have the calling routine pass an object, by value that supports the TACA interface. Who cares how many other interfaces it supports, as long as the Superdistribution Backoffice can instantiate the object and manipulate it via the TACA interface. Since Java passes natively by value, this is not a big deal. Therefore, the interface would look something like this:

The string returned by the addProduct() method is an html page. This page is generated by the server to communicate the PID (Product ID) that the backoffice assigned to this product. The page also explains how to code this PID into the query() and commit() calls of their product's executable code with the usual cautions re: rules of just conduct.

Question: Is the product description useful? May be better to gather a narrative description of the TACA or possibly the URL of the product itself. The latter would have to involve a delay because the user will only learn the PID to encode into their product from the server's response to the addProduct() message.

Response: Unresolved

4: Producer delivers a product (example)

The superdistribution backoffice plays no role with respect to how products are delivered to consumers. The producer is free to deliver products by any means that are capable of transmitting executable code: floppy disks, internet or sneakernet exchanges between students. Such "informal distributions" are not only supported but (if the producer desires) explicitly encouraged. With superdistribution, revenue collection occurs when digital products are used as distinct from when they are acquired.

5: Consumer uses a product (example)

The session begins with session initiatiation (step 2) and ends with session termination (step #x below). Session initiation stores the current customer's ID in the cache as a login(CID) record.

Software usage commences exactly as in traditional (pay to acquire) systems. The metering logic is involved only in software constructed for pay-to-invoke revenue collection. This is signified by query(PID) and commit(PID) calls immediately surrounding the parts of a software product for which usage is to be charged.

According to the rules of just conduct, the product owner is legally responsible to accurately disclose terms and conditions (e.g. prices) in the free part of each product (readme files, splash screens, etc). The user reads the price, decides to continue, and clicks the UI feature (buttons, etc) to indicate acceptance of the terms and conditions. The software tells the meter that a chargeable event is beginning by calling query(PID pid), where pid is the product id that the owner coded into this property.

Notice that the CID to be charged is not explicitly coded in such calls. This is always determined implicitly, by the Meter and not the property, from either the PID of the enclosing Meter.query(PID) call or the CID of the enclosing Meter.login(CID), whichever is nearest. The meter consults the cached Hashtable (returned by the most recent Meter.send() operation) and determines whether further invocations should be allowed by this customer. If so, the call returns normally. If not the call throws a requestDenied exception.

The product continues executing as usual. If the product calls invocation-metered subcomponents, these will issue further Meter.query() and Meter.commit() calls. The backoffice will charge these to the owner of the PID in the enclosing Meter.query(). The customer identified in the top-level Meter.login(CID cid) call is only charged for products they invoke directly.

When the product successfully delivers the service that the user requested, it communicates this fact to the backoffice by issuing a Meter.commit() call

The meter records the commit call into its invocation cache and the product returns control to the user.

6: Meter sends cache to backoffice (example)

When the cache fills (or other triggering criteria that the backoffice installed in the meter, such as a trigger to initiate monthly uploads independently of usage level), the meter initiates a connection to its backoffice, uploads its cache contents, and downloads a Hashtable with the current account status (allow vs. deny further service) for each of the CIDs in the cache.

The backoffice establishes a loop over the array of MeterReadings as described in the Multigranular Property section of this document. Briefly, this loop invokes the TACA for the PID that is encoded inside each reading. Each TACA transforms its invocation record into a monetary amount. The enclosing loop debits this amount from the enclosing microaccount (e.g. the account of the customer who invoked this property), crediting that amount to the microaccount of the registered owner of the current PID.

Question: See responses to previous questions re: asynchronous calls. This call is drafted under the assumption that this computation can be done in real-time, along with prudent journaling, backups and so forth. If prototyping shows that the uploaded information must be buffered and processed later, this API will have to be changed so that the updated account status HashTable is downloaded as a separate call.

7: Customer views account (example)

During any current session, the customer can view (and to some extent, to modify, limited by policy matters TBD), their account by simply revisiting the screen that was described above under Step 2: Customer initiates session. The top-level screen provides customer account information (address, telephone number, credit card information) as editable forms, lists any products owned by this, and the customer's current microaccount balance.

The same form provides a Transactions Details button that brings up a separate page, analogous to a monthly credit card statement, that details each credit and debit within this billing cycle.

8: Customer ends session (example)

Session-terminating logic is defined elsewhere in the IMS standard. This logic calls

This records a logoff record in the cache.

© Copyright 1998 by Educom/IMS