Interacting with FPS

The purpose of FPS is to transfer money between different Amazon Payments account holders. This fact makes it more difficult to develop and test FPS applications than the other services we explore in this book because it involves dealing with real money.

To allow developers to create FPS applications without risking disastrous side-effects from bugs or misunderstandings, Amazon provides two distinct FPS environments: production and sandbox. You can interact with one environment or the other by using the appropriate environment endpoint URIs.

Production Environment

The production environment is the real deal. Transactions performed in this environment will transfer money between official Amazon Payments accounts, draw on credit card or bank accounts, incur transaction fees, and experience all the real-world delays inherent in dealing with external financial systems. To perform test transactions in this environment, you will need third-party customers, clients, or colleagues who are willing to help you out by transferring their money.

Amazon recommends that developers avoid running their application in the FPS production environment until it has been thoroughly tested and proven in the sandbox, and we are inclined to agree. The code and examples in this chapter will only use the sandbox environment.

Table 10-5 shows the URI endpoints to access the different components of the production environment.

Sandbox environment

The sandbox environment is a fully-functional FPS system for development and testing that does not transfer real money or incur real transaction fees. The sandbox makes it possible to test all aspects of FPS, from API operations and third-party CBUI pipeline requests, to account management using fake accounts. Here are some of the key sandbox features you can use of to test your application’s interaction with FPS and assess the experience from the perspective of your customers:

Table 10-6 shows the URI endpoints to access the different components of the sandbox environment. These URIs are similar to the production URIs, except that they all contain the word “sandbox.”

The sandbox environment includes some special features that can help in testing your FPS application. To begin with, transaction times in the sandbox sometimes differ from what you would experience in the real world.

In the sandbox you can simulate the error conditions caused by a customer’s faulty Amazon Payments account by using the following predefined sender payment instruction tokens in a transaction.

Error ConditionSender Token
Email address not verifiedJ5B1P2Q4VIA2V3ZB475M6MQFSK9EZDARCCFV4UV7VTDB9ZVX6LEE3XRXFHTBEXI1
Suspended accountH7PSM2Z9A53NVQFId834IIFM1G8JI1RKQUTK1MPAGMFZASSGFDV3RCDU4ZMNFIK4
Closed accountZ1VR1HA7R7LXXSM7243F34ACQDPEZMLD8V5QSSE4GU654MCZLIHICW8MTXC1TLF9

You can simulate the error conditions caused by a recipient’s faulty Amazon Payments accounts by using the following pre-defined recipient payment instruction tokens.

Error ConditionRecipient Token
Email address not verifiedJ4B1S2L4V7AEV3RBB7596ZQFXKUEZ9AHCCHV3UVVV7DBFZKX6IEP3XNXQHTTECIC
Suspended accountH5PS82X9AC31VQPIQ83BILFMBGGJI1RAQURKPMP9GLFZNS1GFQVVRCTUFZM4FFKT
Closed accountZ5VRRHX7RZL4XS57Z43H32ACPDAEZ4LC8V3QFSEAG365TM3ZLIHXCWXM1XCKTDF5

Finally, you can simulate transaction errors by using transfer amount values that follow one of the following formatting patterns:

Error ConditionAmount Format
Temporary Decline (will succeed when retried twice)Contains “.6”, for example: 25.65, 0.6
FailureContains “.7” or “.8”, for example: 25.75, 0.8

The FPS web service API is made available through two interfaces: Query and SOAP. In this book we will use the Query API.

The FPS implementation presented in this chapter uses the Query API functionality implemented in the AWS Ruby module. The AWS module includes the methods we presented in Query API Implementation” in Chapter 2: these perform authentication, transmission, and response checking of Query API requests.

Amazon uses version identifiers to label different versions of most of their service APIs. By assigning each API version its own identifier, Amazon can continue to develop and change the APIs without without breaking AWS client implementations that use the older versions. The most recent FPS API version available for use in this book was 2007-01-08.

In this chapter we will gradually build up a complete implementation class called FPS, which you can use to interact with the FPS service. Example 10-1 defines a basic Ruby code stub that defines the FPS class, to which we will add API implementation methods as we proceed through the Chapter 10, Chapter 11 and Chapter 12. Save this code to a file named FPS.rb in the same directory as the AWS module file AWS.rb, defined in Chapter 2.

This class will rely on the communication library implementation defined in the AWS module, which it includes as a mixin module. A mixin is a feature of Ruby that makes the variables and methods defined in a module available to a class.

The FPS class defines four constant values: the ENDPOINT_URI constant defines a URI that will be used as the target for FPS service requests; the PIPELINE_URI represents the target for requests to the FPS CBUI Pipeline web site; the API_VERSION and SIGNATURE_VERSION constants define which API and Signature versions this implementation is compatible with; and the HTTP_METHOD constant defines whether the class will use POST or GET request messages by default.

The FPS Query API interface represents errors differently from the other Query-based service interfaces discussed in this book. When an FPS API operation fails, instead of returning an HTTP response message with an HTTP error code and further details in the response body, it returns an HTTP 200 success message with an XML error document.

To recognize when an error has occurred, we must therefore parse the contents of every response message received from the FPS service to determine whether or not an operation has succeeded. We cannot rely on the HTTP status code to give us a hint.

The XML error messages returned by the service will always include four elements; these are listed in Table 10-7.

To make it easier for our FPS client implementation to detect errors, we will define an extra method specifically for this service that will perform query requests and check the resulting XML document for errors. Example 10-2 defines the method do_fps_query, which uses the standard AWS do_query method to send a request to the service and then performs the extra work of parsing the result document and checking its status. If the operation did not succeed, the method raises an FpsServiceError.

Because the structure of an XML error message returned by FPS is different from the structure of errors from other the other AWS services, we will use a specialized error class to interpret these errors. Example 10-3 defines a class called FpsServiceError that extends Ruby’s default RuntimeError object to store the additional error response information made available by FPS.

This class is initialized with an XML document from which it retrieves the value of the four common elements in an FPS XML error response document. These values are made accessible from outside the class through the code, reason, type, and retriable accessors.

FPS API transaction operations are idempotent. This means that even if a particular API transaction request message is sent to the service multiple times, it will only ever be acted upon once. This feature is very important in a financial service because it removes the risk that network or application glitches will result in transactions being repeated by mistake. When FPS receives a transaction request message with parameters that are identical to a message it has already received, it will do nothing but return the original response message to the client.

To make each of your transaction requests unique, the API operations require that you provide a caller reference value of up to 50 characters that uniquely identifies each request. This string reference value should be generated by your application in a way that ensures it will always be unique. Your application may be able to use an order code as a unique reference value for each transaction or a sequence number from a database. This feature allows your application to obtain response information for requests when the original response failed to arrive due to networking problems.