Amazon Flexible Payment Service

Amazon FPS, is a service that allows for building very flexible payment systems. The service can be classified as a part Gateway and part Integration (offsite processor). This is because the customer is redirected to the Amazon site where he authorizes the payment and after this the customer is redirected back to the merchant site with a token that is used by the merchant to transact with the customer. In plain offsite processors, the authorization and transaction take place in one shot almost simultaneously.

Since the service isn’t conventional (though very flexible), implementing FPS in merchant takes a couple of steps more.

The documentation for the service is available at Amazon FPS Docs.

Note

This integration has a dependency on boto, a popular AWS library for python.

Settings attributes required for this integration are:

  • AWS_ACCESS_KEY: The Amazon AWS access key available from the user’s AWS dashboard.
  • AWS_SECRET_ACCESS_KEY: The Amazon AWS secret access key also available from the user’s dashboard. Shouldn’t be distributed to anyone.

Settings attributes:

MERCHANT_TEST_MODE = True
MERCHANT_SETTINGS = {
    "amazon_fps": {
        "AWS_ACCESS_KEY": "???",
        "AWS_SECRET_ACCESS_KEY": "???"
    }
}

Here are the methods and attributes implemented on the AmazonFpsIntegration class:

  • __init__(options = {}): The constructor takes a dictionary of options that are used to initialize the underlying FPSConnection that is bundled with boto.
  • service_url: A property that returns the API Endpoint depending on whether the the integration is in test_mode or not.
  • link_url: A property that returns the link which redirects the customer to the Amazon Payments site to authorize the transaction.
  • purchase(amount, options={}): The method that charges a customer right away for the amount amount after receiving a successful token from Amazon. The options dictionary is generated from the return_url on successful redirect from the Amazon payments page. This method returns a dictionary with two items, status representing the status and response representing the response as described by boto.fps.response.FPSResponse.
  • authorize(amount, options={}): Similar to the purchase method except that it reserves the payment and doesn’t not charge until a capture (settle) is not called. The response is the same as that of purchase.
  • capture(amount, options={}): Captures funds from an authorized transaction. The response is the same as the above two methods.
  • credit(amount, options={}): Refunds a part of full amount of the transaction.
  • void(identification, options={}): Cancel/Null an authorized transaction.
  • fps_ipn_handler: A method that handles the asynchronous HTTP POST request from the Amazon IPN and saves into the AmazonFPSResponse model.
  • fps_return_url: This method verifies the source of the return URL from Amazon and directs to the transaction.
  • transaction: This is the main method that charges/authorizes funds from the customer. This method has to be subclassed to implement the logic for the transaction on return from the Amazon Payments page.

Example

In any app that is present in the settings.INSTALLED_APPS, subclass the AmazonFpsIntegration and implement the transaction method. The file should be available under <app>/integrations/<integration_name>_integration.py:

class FpsIntegration(AmazonFpsIntegration):
    # The class name is based on the filename.
    # So if the files exists in <app>/integrations/fps_integration.py
    # then the class name should be FpsIntegration
    def transaction(self, request):
        # Logic to decide if the user should
        # be charged immediately or funds
        # authorized and then redirect the user
        # Below is an example:
        resp = self.purchase(10, {...})
        if resp["status"] == "Success":
           return HttpResponseRedirect("/success/")
        return HttpResponseRedirect("/failure/")

In urls.py:

from billing import get_integration
amazon_fps = get_integration("fps")
urlpatterns += patterns('',
  (r'^amazon_fps/', include(amazon_fps.urls)),
  # You'll have to register /amazon_fps/fps-notify-handler/ in the
  # Amazon FPS admin dashboard for the notification URL
)

In views.py:

from billing import get_integration
def productPage(request):
   amazon_fps = get_integration("fps")
   url_scheme = "http"
   if request.is_secure():
       url_scheme = "https"
   domain = RequestSite(request).domain
   fields = {"transactionAmount": "100",
             "pipelineName": "SingleUse",
             "paymentReason": "Merchant Test",
             "paymentPage": request.build_absolute_uri(),
             # Send the correct url where the redirect should happen
             "returnURL": "%s://%s%s" % (url_scheme,
                                         domain,
                                         reverse("fps_return_url")),
            }
    # You might want to save the fields["callerReference"] that
    # is auto-generated in the db or session to uniquely identify
    # this user (or use the user id as the callerReference) because
    # amazon passes this callerReference back in the return URL.
    amazon_fps.add_fields(fields)
    return render_to_response("some_template.html",
                              {"fps": amazon_fps},
                              context_instance=RequestContext(request))

In some_template.html:

{% load render_integration from billing_tags %}
{% render_integration fps %}

The above template renders the following code:

<p><a href="https://authorize.payments-sandbox.amazon.com/cobranded-ui/actions/start?callerKey=AKIAI74UIJQ37QS6XLTA&callerReference=5d37ac69-82ac-4bb1-98a4-18c3f9ff15f4&paymentReason=Merchant%20Test&pipelineName=SingleUse&returnURL=http%3A%2F%2Fmerchant.agiliq.com%2Ffps%2Ffps-return-url%2F&signature=wh9PSXAyKfPKizPL%2FRdrYbb24XsoE0efrtMGQBBSs3k%3D&signatureMethod=HmacSHA256&signatureVersion=2&transactionAmount=100"><img src="http://g-ecx.images-amazon.com/images/G/01/cba/b/p3.gif" alt="Amazon Payments" /></a>