The Payment API
(JSR 229) is an optional package that defines the architecture
of a specification for creating Java ME applications to
handle payment transactions. This API is designed to work with both
MIDP and IMP
(Information Module Profile). Although primarily meant for
providing access to application features against payment, the
methodology of making a payment defined in this API can be used for
other kinds of applications, too. In this article, we shall restrict
ourselves to the MIDP environment and shall examine an application
that uses JSR 229 to extend a loan in a micro-credit
environment.
I have used the LG SDK 1.2 for the Java ME Platform
(referred to as the LGSDK from now on) to develop this example.
While there are a number of SDKs available, I found the LGSDK very
convenient to use because of its simple application signing
mechanism and its range of valid certificates. The LGSDK is a
free download and can be easily installed.
The LGSDK will need a JDK (version 1.6 or later) that provides
the overall Java environment. If you don't already have one on
your computer, you can get the latest version at the Java SE
Downloads page of the Sun Developer Network.
The
final specification document of JSR 229 has very detailed
information on this API and is a very useful reference document. It
would be a good idea to download this document too.
The Payment API
The package javax.microedition.payment contains the
class, the interfaces, and the exceptions of the payment API. The
two interfaces are:
TransactionRecord
TransactionListener
The only class in the package is:
In addition to the interfaces and the class listed above, the
package contains the following exceptions:
TransactionModuleException
TransactionListenerException
TransactionFeatureException
TransactionPayloadException
The TransactionRecord Interface
The TransactionRecord interface defines the
structure of an object to represent a payment transaction. The
fields of this interface represent the possible results of a
transaction: SUCCESSFUL, FAILED, and REJECTED. Information about
the transaction can be retrieved by using the various methods of
this interface, as we shall see when we analyze the example
code.
The TransactionListener Interface
This interface defines a listener that receives the result of
processing a transaction. The only method of this interface is
processed(TransactionRecord record). Once a payment
transaction is completed, the processed method is
called and the transaction record that was generated is passed to
it. It is mandatory for a developer to set a transaction listener.
If such a listener is not set, a
TransactionListenerException is thrown whenever an
action is taken that would necessitate a callback to the
processed method.
The TransactionModule Class
The TransactionModule class provides the interface
between the user (that is, the application) and the module (the
payment module) that actually carries out the transaction. The
constructor for this class is responsible for checking that all
information required to handle payment transactions is available.
In case any relevant information is found to be missing, a
TransactionModuleException is thrown.
The methods of this class are listed below:
setListener: Sets a listener for receiving the
result of a transaction. If the TransactionListener
object passed as a parameter for this method is null,
the current listener will be removed.
process: Initiates a payment transaction. There
are two versions of this method. One of the versions takes an
optional payload that can be transmitted as a part of the
payment transaction. The maximum size of the payload is 132 bytes.
If the payload size exceeds the 132-byte limit, a
TransactionPayloadException is thrown. The
process method does not wait for the transaction to be
completed and returns immediately after passing the parameters to
the payment module.
getPastTransactions: Returns an array of
TransactionRecord objects covering past transactions.
The parameter for this method specifies the maximum number of
records to be returned.
deliverMissedTransactions: Requests that the payment
module generate transaction records for all missed transactions
for passing on to the application through the
processed method of the registered listener. A
transaction is missed if payment action is initiated but the
result is not conveyed to the application. This might happen if the
application shuts down or the device crashes after a transaction
has been initiated but before the result was returned to the
listener.
The Exceptions
The payment API does not have a general exception of the form
TransactionException. This is a deliberate design
decision to ensure that a developer handles each type of exception
individually.
The following list shows the situations that cause the
exceptions to be thrown:
TransactionModuleException: Thrown if any error
related to the payment module occurs.
TransactionListenerException: Thrown if any
action is taken that requires a callback to the
processed method of TransactionListener
but there is no registered listener.
TransactionFeatureException: Thrown if a feature
not specified in an application's resource file is used by an
application.
TransactionPayloadException: Thrown if the
payload size exceeds the 132-byte limit.
The Microcredit Environment
Wikipedia defines "microcredit" as "the extension of very small
loans (microloans) to those in poverty designed to spur
entrepreneurship." In the current context, microcredit has been
made internationally known primarily through the efforts of Grameen
Bank in Bangladesh. Microloans essentially target people who are
extremely poor, are not able to furnish collateral, and cannot
meet the required criteria for accessing normal financing channels.
Microcredit enables individuals with such handicaps to build an
asset base and emerge from extreme poverty. Microcredit has now
moved out of Bangladesh and is available in many other countries.
Recently, Grameen Bank has opened a branch in New York and has
started offering small loans.
A Look at the Example
Today microcredit is widely patronized even by individuals who
want to help alleviate poverty. The example in this article shows
how a JSR 229-based application can be used by individual lenders.
In a live application, information about various projects would be
downloaded from a server and the loan selection page would list all
eligible projects and possible loan amounts. This is where our
demo takes off. In Figure 1, we can see the screen for selecting
the project and the loan amount.

Figure 1. Selecting project and
loan amount
Once a project and the loan amount are selected, and the Next
command is selected from the menu, the application asks the user to
confirm the selection. This is the screen we see in Figure 2
below.

Figure 2. Confirming the
selections
This screen offers an opportunity to correct any errors in
selection. A confirmation here will show another screen to select
the mode of payment and finally initiate or reject the payment
transaction. This screen is displayed by the API and its contents
cannot be altered by the application. As we have already noted, JSR
229 was designed to meet the requirements of applications with
payment-enabled features. Accordingly, the API asks whether the
user would like to buy a specific feature. This can
be seen in Figure 3.

Figure 3. Initiating
payment
In order to maintain compatibility with the terminology used by
the API, the transaction in our application is used for purchasing
a loan voucher. This is why the UI shown in Figure 2 asks the user to confirm the purchase of a
loan voucher. The result of the transaction, however, would be a
payment for a loan to the specified project.
Executing the Yes command will initiate the payment transaction.
The screenshot of Figure 4 shows the Alert that is displayed when
the transaction is successful.

Figure 4. A successful
transaction
The menu for the first screen shown here (Figure 1) has two commands. We have already seen the
result of executing the Next command. If the History command is
executed, the record for the last transaction is printed to the
console. This is shown in Figure 5.

Figure 5. Details of last
transaction
Project Settings
Project settings play a very important role in building
applications using the payment API. This is because much of the
information required for a payment transaction gets packaged into
the provisioning files -- that is, the JAD file and the JAR
manifest. The required information can be passed into these files
by selecting Settings -> Payment on the LGSDK console and filling
in the relevant fields.
Figure 6 shows the general entries that are mandatory. In the
Version field, enter 1.0 or 1.1. Values for other fields can be
filled in as shown. The significance of these values will be
discussed when we talk about updates.

Figure 6. The General
Settings
The next set of values to be entered link the features defined
in the application with those predefined in the API. This will be
explained in section on code analysis. Figure 7
shows the entries for our example. Features can be added or removed
by clicking on the corresponding buttons.

Figure 7. Setting
features
Finally, we need to provide information about the payment
service providers. A payment service provider (PSP) is
responsible for making the actual payment to the designated receiver of
the payment. The preferred mode of payment defined in the payment
API is Premium Priced SMS (PPSMS). In this payment mode, a payment
is made by sending an SMS to the provider and the value of the
payment is determined by the content of the SMS or by the number to
which the SMS is sent. In our example we have two providers, as
shown in Figure 8.

Figure 8. The list of
payment service providers
Names can be added to or removed from the list by using the Add
or Remove button. The Edit
button is used to enter the details for a provider. Figure 9 shows the dialog that opens for entering
provider information.

Figure 9.
Provider information
The Payment Specific Info shown here are the applicable Mobile Country
Code (MCC) and the Mobile Network Code (MNC) for the provider.
The Price Info shown here contains the payment amount for each tag,
along with other optional information. The number of tags here is
equal to the number of features in Figure
7. The final specification document for the API includes
detailed information on all the fields for the settings described
above.
The MIDlet Code
It's time now to look at the code that does the payment-specific
work. The declaration of the features comes first. The number of
features is the same as the possible values that the loan amount
can take. In this example the loan amount is a multiple of $10.00, with the minimum value being $10.00 and the maximum being
$50.00. In the listing below, FEATURE_LOAN1 has the value 0,
which links the feature to Pay-Feature-0 (Figure 7) and then to Pay-<provider>-Tag-0
(Figure 9). So FEATURE_LOAN1 now
corresponds to an amount of $10.00.
//definition of feature to pay for
private static final int FEATURE_LOAN1 = 0;
private static final int FEATURE_LOAN2 = 1;
private static final int FEATURE_LOAN3 = 2;
private static final int FEATURE_LOAN4 = 3;
private static final int FEATURE_LOAN5 = 4;
The activities related to making the payment are all performed
within the commandAction method of the MIDlet. When we
confirm our selections (Figure 2), the
PAY_COMMAND is executed and the corresponding code is listed below.
Note that the payload (payloadString converted to
byte[]) is used to specify the selected project.
if (cmd == PAY_COMMAND)
{
String payloadString;
int featureID;
//set payloadString depending on
//index of selected project
switch (projIndex)
{
case 1:
payloadString = "Project A";
break;
case 2:
payloadString = "Project B";
break;
case 3:
payloadString = "Project C";
break;
default:
payloadString = "Project A";
}
//set featureID depending on
//index of selected amount
switch (amtIndex)
{
case 1:
featureID = FEATURE_LOAN1;
break;
case 2:
featureID = FEATURE_LOAN2;
break;
case 3:
featureID = FEATURE_LOAN3;
break;
case 4:
featureID = FEATURE_LOAN4;
break;
case 5:
featureID = FEATURE_LOAN5;
break;
default:
featureID = FEATURE_LOAN1;
}
try
{
//ask TransactionModule instance
//to process the payment
txnModule.process(featureID,
"Loan Approval", "You can buy a Loan Voucher for " +
payloadString, payloadString.getBytes());
}
catch(Exception e)
{
System.out.println(e.toString());
}
}
When we call the process method, the API shows its
own confirmation screen (Figure 3). If we choose
to go ahead with the transaction, the payment is committed and the
processed method is called back into by the payment
module. Here we check what the result was and accordingly show an
alert. The listing for the processed method is given
below. Note that selForm is the form for Figure 1.
public void processed(TransactionRecord tRecord)
{
//get the result (state) of the transaction
//and show alert accordingly
switch (tRecord.getState())
{
case
TransactionRecord.TRANSACTION_SUCCESSFUL:
//Show success alert with feature info
final Alert successAlert =
new Alert("PayMIDlet", "Payment successful\r\nThank you",
null, AlertType.INFO);
successAlert.setTimeout(2000);
display.setCurrent(successAlert, selForm);
break;
case
TransactionRecord.TRANSACTION_REJECTED:
//show reject alert with feature info
final Alert rejectAlert =
new Alert("PayMIDlet", "Payment rejected",
null, AlertType.INFO);
rejectAlert.setTimeout(2000);
display.setCurrent(rejectAlert, selForm);
break;
case
TransactionRecord.TRANSACTION_FAILED:
//show fail alert with feature info
final Alert failAlert =
new Alert("PayMIDlet", "Transaction failed",
null, AlertType.INFO);
failAlert.setTimeout(2000);
display.setCurrent(failAlert, selForm);
}
}
After a transaction is completed, the corresponding record is
saved by the API. Such past records can be accessed by the
application to get a history of transactions. Selecting the History
command on the screen corresponding to Figure
1 results in the following code being executed to display the
last transaction, as shown in Figure 5.
if (cmd == HISTORY_COMMAND)
{
//get record for last transaction
//this is the first and only element
//of the returned array
TransactionRecord hRecord =
txnModule.getPastTransactions(1)[0];
if(hRecord != null)
{
String result = "";
String start = "a loan of ";
String end = "on";
String time = "";
Date hDate = new Date();
//get the result and
//set the beginning
//of the string to be shown
//accordingly
switch (hRecord.getState())
{
case
TransactionRecord.TRANSACTION_SUCCESSFUL:
result = "Suceeded -- ";
break;
case
TransactionRecord.TRANSACTION_FAILED:
result = "Failed -- ";
break;
case
TransactionRecord.TRANSACTION_REJECTED:
result = "Rejected -- ";
}
//get the feature and form the middle
//part of the string accordingly
switch (hRecord.getFeatureID())
{
case FEATURE_LOAN1:
result += start + "USD 10.00 "
+ end + " ";
break;
case FEATURE_LOAN2:
result += start + "USD 20.00 "
+ end + " ";
break;
case FEATURE_LOAN3:
result += start + "USD 30.00 "
+ end + " ";
break;
case FEATURE_LOAN4:
result += start + "USD 40.00 "
+ end + " ";
break;
case FEATURE_LOAN5:
result += start + "USD 50.00 "
+ end + " ";
}
//get the time stamp for the transaction
hDate.setTime(hRecord.getFinishedTimestamp());
time = hDate.toString();
//form and display the entire string
System.out.println(result +
time.substring(0, time.lastIndexOf(':')));
}
}
The getPastTransactions method of
TransactionModule has been used to get the history.
Only the latest record is returned, as the parameter used with the
method is 1. The transaction record does not include the payload
and, therefore, we cannot obtain the name of the project for a past
transaction. One way of solving this problem would be to have the
processed method create a separate record store to
save the payload. The unique ID of a transaction could be
used as a key to link a transaction record to the corresponding
payload.
Running the MIDlet
In addition to the settings shown earlier, you need to select
JSR 229 in the API Selection dialog, as shown in Figure 10.

Figure 10. API selection
We are now ready to build the project. Load the source file for
the MIDlet -- PayMIDlet -- into the src folder
of the project and click the Package icon. You should now have the
JAD and JAR files for the project in the bin folder.
Before running the MIDlet, some more work needs to be done. So
far we have entered settings for the project. We now have to enter
some settings for the platform (the emulator) on which the MIDlet
will run. The first of these sets the MCC and the MNC so that they
match the entries for the providers. Select
Edit -> Preferences -> Payment on the LGSDK menu and you will get a
dialog as shown in Figure 11. Enter the values shown.

Figure 11. Payment
preferences
The second platform preference to be set will define the
security policy. Select Edit -> Preferences -> Security to get the
dialog and enter the values shown in Figure 12.

Figure 12. Security
preferences
The payment API can run only if the MIDlet is trusted. To confer that status on PayMIDlet, it has to be
signed in accordance with the platform security preference that has
been set. Click on the Sign icon and the dialog shown in Figure 13
will open. Click on Sign Application and you are done.

Figure 13. Signing the
MIDlet
To run the MIDlet, click "Run via OTA" (OTA is "over-the-air provisioning") and follow the
prompts.
Getting Updates
JSR 229 allows the price and provisioning information to be
updated from a specified URL and the corresponding settings must be
entered even if, as in this case, we don't need to use this
facility. Referring to Figure 6, the entry
for Update Stamp specifies the date from which the payment data
becomes effective. The Update URL also has to be specified, although
it can be a dummy URL as shown here. The final specification
document contains elaborate information on the update feature.
Conclusion
We have seen here how to use the Payment API (JSR 229) for
applications that use payment-enabled features and also to address
general-purpose payment requirements. We used as a specific example
an application that enables lenders to provide microcredit for
specific projects. The final specification
document for the API contains very detailed explanations, examples, and information on all aspects of JSR 229. Please refer to
this document for a more comprehensive understanding of the
API.
- src.zip: source code for the demo
application.
References
Biswajit Sarkar is an electrical engineer with a specialization in programmable industrial automation.