Amazon FPS for digital goods

One of the advantages of implementing Amazon Flexible Payments for digital goods transactions is that the workflow is basically the same for physical or digital goods. Using the FPS Co-Branded UI, your customers submit their payment to the Amazon processor and are returned to a URL that was specified when the transaction started. In the case of physical goods, this is usually a receipt or thank you page. For digital goods, we would serve up the media download right away. Flexible Payment Services was discussed in Chapter 4, From Payment to Porch: An Order Pipeline.

Amazon offers another API, however, that may be of interest to digital content merchants. The FPS Aggregated Payments API is designed to aggregate many small transactions into a single, combined transaction. This has many advantages, but the most important is to reduce transaction charges.

An aggregated payment system is designed for applications that sell many different products to the same customer within a short period of time. FPS Aggregated Payments allows the developer to control many of these parameters. It also supports prepaid instruments that work like gift cards or prepaid debit cards and allow the customer to purchase from our application against an amount they pay up-front.

Here are some simple examples of services where this sort of payment processing is useful: single-song music sales, games with point or item purchases, and Facebook or other social media applications.

The Aggregated Payments API has many of the features of the standard FPS service, like refunds and instant payment notification. It also supports using either the prepaid or postpaid aggregation.

Prepaid payments

The prepaid version of the API follows the same pattern as Amazon FPS. Customers are initially driven to a Co-branded UI page via a Pay with Amazon link. Here they submit their payment information, select a prepayment amount, and so on. Upon completion, the user is returned to our application along with some information from Amazon. We capture this information and allow the user to browse and purchase.

When we make a sale, our application must communicate that fact with Amazon FPS, including the information we captured after the customer's prepayment. With future sales, we continue the process, updating FPS with the new purchase information. Customers can check their balance from the Amazon Payments website and FPS takes care of tracking transactions and balances.

Obtaining a prepaid token

Let's examine this process from the development side. The first step is to generate a special URL where we will send the customer to authorize payment of the prepaid amount. This requires the usual FPS steps of generating a query string and signing it using the HMAC-SHA256 function. The following code constructs this URL:

CBUI_ENDPOINT='https://authorize.payments-sandbox.amazon.com/cobranded-ui/actions/start'

def sign_aws_request(params, hostheader, url_path='/',  
                                 http_method="GET"):
    import hmac, hashlib
    import base64
    import urllib
    keys = params.keys()
    keys.sort()
    sign_string = '%s
%s
%s
' % (http_method, hostheader, url_path) 
    for key in keys:
        sign_string += '%s=%s&' % (urllib.quote(key),
        urllib.quote(params[key]).replace('/', '%2F'))
        sign_string = sign_string[:-1]
        digest = hmac.new(settings.AWS_SECRET_KEY,
        sign_string, digestmod=hashlib.sha256).digest().strip() 
    return base64.b64encode(digest)

def get_prepaid_token(ref_sender, ref_funding, amount, return_url):
     query_dict = {'callerKey': settings.AWS_ACCESS_KEY,
                          'callerReferenceFunding': ref_funding,
                          'callerReferenceSender': ref_sender,
                          'FundingAmount': str(amount),
                          'pipelineName': 'SetupPrepaid',
                          'returnURL': return_url,
                          'version': '2009-01-09',
                          'SignatureVersion': '2',
                          'SignatureMethod': 'HmacSHA256'}
    signature = sign_aws_request(query_dict,
                 'authorize.payments-sandbox.amazon.com', 
                 url_path='/cobranded-ui/actions/start')
    query_dict.update({'signature': signature})
    cbui_url = CBUI_ENDPOINT + '?' + urllib.urlencode(query_dict)
    return cbui_url

The URL returned from the get_prepaid_token function will be used as the href attribute in our Pay Now link or button. This function needs four arguments. The amount and return_url arguments are almost self explanatory. Amount is the dollar amount we will allow the customer to prepay. The return_url is a string representation of a URL in our application to return after the customer has authorized payment. This URL is important because it will receive the response data from the API request, which our application must process.

The remaining arguments, ref_sender and ref_funding, are somewhat mysterious. The FPS documentation explains them like this:

  • callerReferenceSender: This is a unique identifier that you supply to specify this payment token and the sender in your records
  • callerReferenceFunding: This is a unique identifier that you supply to specify this payment token and its funding in your records

These are required arguments and are used to relate the user funding activities in our application with the transaction in Amazon's FPS. Both should be unique to all of our prepaid requests. We could achieve this by appending an order ID number to the Django username, using a hash of order and amount information, or through many other methods.

Upon successfully generating an authorization URL, we can embed it as a link in our application's templates. Customers clicking the link to initiate a prepaid transaction will be directed to Amazon's Co-Branded User Interface (CBUI). This is an Amazon-hosted page that first prompts the user to log in to their Amazon Payments account and then presents them with an authorization screen like the one that follows:

Obtaining a prepaid token

This page simply verifies the customer's payment method, how much they're prepaying and some other billing details. By clicking the Confirm button, the user is returned to our application via the return_url parameter discussed previously. No money has changed hands at this point, to do that our application must fund the prepaid request.

To better understand what happens next, we'll outline the entire aggregated payments process for prepaid instruments. We've just seen what obtaining authorization in step 1 looks like. The remaining steps are as follows:

  1. Obtain authorization from customer using CBUI.
  2. Our application receives prepaid token at return_url.
  3. Prior to use, our application funds the prepaid instrument using the token from step 2.
  4. The customer makes a purchase.
  5. Our application makes a Pay request to the FPS API.
  6. The customer's prepaid balance is reduced by the amount of purchase.

Steps 4 through 6 will repeat until the customer's prepaid balance reaches zero. At that time, if the customer plans to make more purchases, we will need to authorize a new prepaid instrument. The full amount the customer has prepaid is deposited to our application's Amazon Payments account upon funding in step 3. No money actually exchanges hands at this point; the Pay requests are simply bookkeeping to manage the status of the customer's prepayment.

We should note, too, that the customer cannot see their prepaid balance from the Amazon Payments site itself. Only our application can retrieve their current balance, so this becomes an important piece of functionality. Fortunately, it is relatively easy to obtain balances for display in our application, as we'll see shortly.

If this sounds complicated, that's because it is. These series of steps are necessary, however, to secure the transaction to Amazon's standards. Aggregated payments are very recent innovations and diligence in the security of financial information is extremely important. Implementing an equivalent system from scratch would be quite a task, which is why the Aggregate Payments API is so powerful.

Upon redirection to our return URL, Amazon FPS will include several pieces of information about the authorization. The most important among these is the funding token, sent in the HTTP GET parameter called fundingTokenID. This ID will be used in funding the prepaid instrument.

The response data also includes another important element, the prepaidInstrumentId. This represents the customer's prepaid instrument. It may help to think of this as the customer's "gift card" that we will be loading with funds. This instrument ID is used during funding and later on during Pay requests.

The final important response value is prepaidSenderTokenID. We will need this to actually use the prepaid balance when the customer makes a purchase in our application.

Funding the prepaid token

Funding the prepaid request requires us to make an API call back to the FPS service. We pass in the fundingTokenId sent back from the authorization request, as well as the prepaidInstrumentId, the amount we will be funding, and a CallerReference value that uniquely identifies this funding request.

To construct the REST request URL for the funding operation, we can use the following Python code:

def aws_timestamp():
    return strftime("%Y-%m-%dT%H:%M:%S.000Z", gmtime())

def fund_prepaid_token(funding_token_id, prepaid_id, caller_ref, amount):
    timestamp = aws_timestamp()
    params={'Action': 'FundPrepaid',
                  'AWSAccessKeyId': settings.AWS_ACCESS_KEY,
                  'SignatureVersion': '2',
                  'SignatureMethod': 'HmacSHA256',
                  'Version': '2009-01-09',
                  'Timestamp': timestamp,
                  'FundingAmount': str(amount),
                  'PrepaidInstrumentId': prepaid_id,
                  'SenderTokenId': funding_token_id,
                  'CallerReference': caller_ref}
    signature = sign_aws_request(params, 'fps.sandbox.amazon.com')
    params.update({'signature': signature})
    fps_url = FPS_ENDPOINT + '?' + urllib.urlencode(params)
    return fps_url

We will sign the query parameters just as we did for the Co-branded UI request, except we will be using a different endpoint and thus different host header. The sign_aws_request Python function can be used to sign all of our FPS requests:

def sign_aws_request(params, hostheader, url_path='/',   
                                  http_method="GET"):
    import hmac, hashlib
    import base64
    import urllib

    keys = params.keys()
    keys.sort()
    sign_string = '%s
%s
%s
' % (http_method, hostheader, url_path) 
    for key in keys:
        sign_string += '%s=%s&' % (urllib.quote(key),
                                               urllib.quote(params[key]).replace('/', '%2F'))
        sign_string = sign_string[:-1]

         digest = hmac.new(settings.AWS_SECRET_KEY,
                      sign_string, digestmod=hashlib.sha256).digest().strip()
    return base64.b64encode(digest)

Let's examine the fund_prepaid_token function in more depth. The important request parameters are Action, PrepaidInstrumentId, SenderTokenId, and CallerReference. The Action parameter is used in all FPS requests to specify what our request is attempting to do. We can think of it as the function we want to run against the services API. In this case we're calling FundPrepaid.

PrepaidInstrumentId is a unique identifier for the payment instrument (the customer's "gift card") that we will be funding. The value for this parameter was provided in the response from the prepaid token authorization request we made in the previous section. The response value was sent as the prepaidInstrumentID parameter (note the lower case). FPS generates this value internally during the initial authorization request.

S enderTokenId was also sent back to us in the response step of the previous section as the fundingTokenID parameter. This value is a key to funding the prepaid instrument and is required in all FundPrepaid requests. This token represents the balance amount between when the customer authorizes funds and before their prepaid instrument is funded. Without this value we could not fund the "gift card".

Finally, the last parameter is CallerReference. This is an important value that we will need to store for future reference. It could be analogous to an order ID or other unique reference number in our application. When we receive a response to our funding request, it will include a transaction ID, which we will want to associate with the corresponding CallerReference value. We will build Django models to store all of this information later in the chapter.

If for some reason our funding request fails, due to a network outage or other anomalies, and we do not receive a transaction ID, we can use the CallerReference value to submit the request again within seven days. This works by submitting the exact same request, including the other parameters, as we did initially. If the other parameters differ, FPS will return a duplication error.

Unlike the Co-branded UI request for authorization we issued earlier, no return_url parameter is needed. This is because our application will be processing the response without any user involvement and can read the response values directly.

FundPrepaid requests only return two values, the transaction ID and a transaction status. Status messages are one of five values: Cancelled, Failure, Pending, Reserved or Success. A Success value means we can allow the customer to proceed and begin purchasing against their prepaid balance, while we make Pay requests for each purchase.

Prepaid pay requests

Now that we've obtained the customer's permission and their payment method using the Co-branded UI authorization request, and funded their prepaid instrument, the next step is to make payments against the prepaid balance at the time of purchase.

When our customer finds a digital good to buy, we want to deduct the purchase amount from their prepaid instrument. To do this we perform another FPS API call, this time to the Pay action. We need to include three important parameters in this call: SenderTokenID, TransactionAmount, and CallerReference.

  • SenderTokenID is the token we received during the authorization process where it was returned as the prepaidSenderTokenID parameter in the API response. This represents the customer's prepaid token.
  • TransactionAmount is the purchase amount for the good we'll be selling. If the amount charged exceeds the balance available in the prepaid instrument, the API request will fail and will include errors data that describes the failure condition.
  • CallerReference is a new unique identifier that we will need to store to track this Pay request. As with other FPS requests, if there is a network failure we can resend the Pay request using the exact parameters as the initial attempt for up to seven days.

For successful Pay requests, the response information will include the usual data, namely TransactionId and TransactionStatus. We can inspect these values to determine the success or failure of our payment attempt. If successful we can direct the customer to their purchased content, and their prepaid balance will be reduced by the amount of the purchase.

We can generate Pay requests for the FPS API using the following Python function:


def make_payment(sender_token_id, transaction_amount, caller_reference):
    timestamp = aws_timestamp()
    params={'Action': 'Pay',
                  'AWSAccessKeyId': settings.AWS_ACCESS_KEY,
                  'SignatureVersion': '2',
                  'SignatureMethod': 'HmacSHA256',
                  'Version': '2009-01-09',
                  'Timestamp': timestamp,
                  'TransactionAmount': str(transaction_amount),
                  'CallerReference': caller_reference,
                  'SenderTokenId': sender_token_id}
    signature = sign_aws_request(params, 'fps.sandbox.amazon.com')
    params.update({'signature': signature})
    fps_url = FPS_ENDPOINT + '?' + urllib.urlencode(params)
    return fps_url

We will use the URL returned from make_payment to submit our request and await the API's response.

Checking prepaid balances

The FPS API action to check prepaid balances is called GetPrepaidBalance. It requires a signal parameter, PrepaidInstrumentId. This value is the unique identifier for the prepaid instrument and originated as the prepaidInstrumentID response value during the Co-branded UI authorization step.

This is not the same value used for Pay requests, SenderTokenId, though the two IDs play similar roles. This one cannot be used for the prepaid balance.

The following Python function will ready a GetPrepaidBalance FPS API call and return it as a URL where we can submit our request:

def get_prepaid_balance(prepaid_instrument_id):
    timestamp = aws_timestamp()
    params={'Action': 'PrepaidBalance',
                  'AWSAccessKeyId': settings.AWS_ACCESS_KEY,
                  'SignatureVersion': '2',
                  'SignatureMethod': 'HmacSHA256',
                  'Version': '2009-01-09',
                  'Timestamp': timestamp,
                  'PrepaidInstrumentId': prepaid_instrument_id}
    signature = sign_aws_request(params, 'fps.sandbox.amazon.com')
    params.update({'signature': signature})
    fps_url = FPS_ENDPOINT + '?' + urllib.urlencode(params)
    return fps_url

Postpaid payments

The postpaid API works slightly differently than the prepaid equivalent. The overall process is the same but the API calls and their necessary parameters differ. The postpaid approach also has different financial implications.

As we mentioned in our discussion of the Aggregated Payments API, the goal is to combine many smaller purchases into one large purchase to reduce transaction fees. The prepaid approach does this by charging the customer up front. Postpaid works like a type of credit system, where we initially grant the customer a limited purchase amount. As they buy from our application, we issue Pay requests that accrue against the customer's limit.

The customer can purchase as much as they like up to the limit we initially grant. When they reach the limit they are unable to make additional purchases until their debt balance is settled. We can also settle debts at an agreed to interval, every day or week, for example.

When the debt is settled, the balance is transferred from the customer's payment method, selected during the authorization step, into our Amazon Payments account. Our application must settle the debt by calling the SettleDebt FPS API function. We do this whenever we detect that the balance has reached its maximum or is at the agreed upon interval.

Obtaining a postpaid token

The overall process of using the Postpaid API mirrors the steps we took for the Prepaid API. To obtain the Postpaid Token we begin by constructing a URL to use in our Pay Now buttons. This is the Co-branded UI where the customer reviews the terms of the postpaid transaction, configures, and then authorizes payment.

There are a variety of customizations in this step, including setting usage limits and expiration dates for the credit we'll be extending to the customer. For our purposes, we will keep it simple and implement a basic postpaid credit account that never expires.

We need to supply four parameters to the CBUI authorization system to begin a postpaid transaction: callerReferenceSender, callerReferenceSettlement, creditLimit, and globalAmountLimit.

The callerReferenceSender and callerReferenceSettlement parameters are unique identifiers for this postpaid transaction. The first is intended to associate the customer and the token, while the second associates the token and its settlement. Our application should generate unique values for these parameters according to some consistent method, as discussed in the prepaid section.

The next two parameters control the terms of the credit. We set a maximum credit amount using the creditLimit parameter. This is equivalent to a credit limit on a credit card: the customer cannot spend beyond this amount without settling the transaction. The second value, globalAmountLimit, is the maximum charge the customer can incur against their credit limit in our purchase.

These two parameters give our application flexibility in how we handle credit. For a service that is processing many small transactions, we may wish to set a relatively high creditLimit, but restrict the amount of any one-time purchase, so that if the customer fails to pay, we limit our losses. Other times it may make sense to set these two values equivalent to each other.

The following Python function generates a Postpaid CBUI URL:

def get_postpaid_token(ref_sender, ref_settlement, credit_limit,  
                       global_limit, return_url):
    params = {'callerKey': settings.AWS_ACCESS_KEY,
                    'callerReferenceSettlement': ref_settlement,
                    'callerReferenceSender': ref_sender,
                    'creditLimit': str(credit_limit),
                    'globalAmountLimit': str(global_limit),
                    'returnURL': return_url,
                    'pipelineName': 'SetupPostpaid',
                    'SignatureVersion': '2',
                    'SignatureMethod': 'HmacSHA256',
                    'Version': '2009-01-09'}
    signature = sign_aws_request(params,
                              'authorize.payments-sandbox.amazon.com', 
                               url_path='/cobranded-ui/actions/start')
    params.update({'signature': signature})
    cbui_url = CBUI_ENDPOINT + '?' + urllib.urlencode(params)
    return cbui_url

This function uses the same AWS signing code we used for Prepaid API calls.

Our return_url will again capture the response data the FPS API sends when redirecting the user back to our site. The response values include: creditInstrumentID, creditSenderTokenID, and settlementTokenID.

The creditInstrumentID acts as a unique identifier for the postpaid instrument. As with the Prepaid API, this value is not used for making payments against the instrument, but can be used to obtain information and present it to the customer, such as debt balances. It can also be used when writing off debt from a customer's credit balance.

The creditSenderTokenID value is used to make Pay requests against the credit instrument.

The settlementTokenID value is used during the settlement process as a parameter to the SettleDebt FPS function.

Again, we will need these values for later operations.

Postpaid pay requets

Unlike in the Prepaid API, postpaid instruments do not need to be funded before they can be used. Instead we can begin issuing Pay requests immediately after obtaining the Postpaid Token. When the user makes a purchase, our application can record it and issue the Pay API call. If the Pay fails, the customer may have reached their credit limit or attempted to purchase something more than their global limit allows. Our application could check for these conditions and if necessary begin settlement.

The Pay request is identical to that used in the Prepaid API. We will use the creditSenderTokenID value returned during the authorization step as the value for SenderTokenID. This way our make_payment function will also allow us to make postpaid credit Pay requests:

def make_payment(sender_token_id, transaction_amount, caller_reference):
    timestamp = aws_timestamp()
    params={'Action': 'Pay',
                  'AWSAccessKeyId': settings.AWS_ACCESS_KEY,
                  'SignatureVersion': '2',
                  'SignatureMethod': 'HmacSHA256',
                  'Version': '2009-01-09',
                  'Timestamp': timestamp,
                  'TransactionAmount': str(transaction_amount),
                  'CallerReference': caller_reference,
                  'SenderTokenId': sender_token_id}
    signature = sign_aws_request(params, 'fps.sandbox.amazon.com')
    params.update({'signature': signature})
    fps_url = FPS_ENDPOINT + '?' + urllib.urlencode(params)
    return fps_url

Our application can now connect to the URL returned from this function and in so doing, submit the Pay request.

Settling debts

As discussed, when the customer reaches their credit limit or at some agreed upon interval (over night, for example), we must settle the debt. We do this by issuing a call to the FPS SettleDebt function.

The SettleDebt action takes three parameters: CallerReference, CreditInstrumentId, and SenderTokenId. These are similar to the parameters we've already seen.

As before, CallerReference is a unique identifier for this settlement transaction that we will want to store in the database for potential future reference. It can be any value as long as it is unique.

The CreditInstrumentId was sent back after the Co-branded UI authorization step. It originated as the creditInstrumentID in that response data. It represents a unique identifier for our customer's credit instrument.

Lastly is the SenderTokenId. This was also sent back to the authorization step. It originated in the response data as the settlementTokenID value.

We can generate the SettleDebt API request call using the following Python function:

def settle_debt(credit_instrument_id, sender_token_id, caller_reference):
    timestamp = aws_timestamp()
    params={'Action': 'SettleDebt',
                  'AWSAccessKeyId': settings.AWS_ACCESS_KEY,
                  'SignatureVersion': '2',
                  'SignatureMethod': 'HmacSHA256',
                  'Version': '2009-01-09',
                  'Timestamp': timestamp,
                  'CallerReference': caller_reference,
                  'CreditInstrumentId': credit_instrument_id,
                  'SenderTokenId': sender_token_id}
    signature = sign_aws_request(params, 'fps.sandbox.amazon.com')
    params.update({'signature': signature})
    fps_url = FPS_ENDPOINT + '?' + urllib.urlencode(params)
    return fps_url

Our application can use the URL value returned by this function to submit the SettleDebt request.

Writing off debt

Sometimes, perhaps due to a download problem or our own sense of generosity, we may want to relieve a customer of some amount of debt. This is different from a refund, though it may appear like a refund to the user.

Writing off debt simply reduces the debt balance for a credit instrument. To do this we use the WriteOffDebt FPS API action. This call requires three parameters: AdjustmentAmount, CallerReference, and CreditInstrumentId.

  • AdjustmentAmount represents the amount of debt we intend to write off. This is a unique parameter in that it cannot simply be expressed as a dollar amount, but has a special format that includes currency.
  • CallerReference is a unique identifier used as a reference in our application to this WriteOffDebt call.
  • The CreditInstrumentId, as we have seen, is a unique identifier for the credit instrument from which we will be writing off debt. This was provided as a response value during the authorization step where we obtained the postpaid token.

We can initiate a WriteOffDebt call using the following Python function:

def write_off_debt(adjustment_amount, credit_instrument_id, 
                             caller_reference,
                             currency_code='USD'):
     timestamp = aws_timestamp()
     params={'Action': 'SettleDebt',
                   'AWSAccessKeyId': settings.AWS_ACCESS_KEY,
                   'SignatureVersion': '2',
                   'SignatureMethod': 'HmacSHA256',
                   'Version': '2009-01-09',
                   'Timestamp': timestamp,
                   'CallerReference': caller_reference,
                   'CreditInstrumentId': credit_instrument_id,
                   'AdjustmentAmount.CurrencyCode': currency_code,
                   'AdjustmentAmount.Value': adjustment_amount}
    signature = sign_aws_request(params, 'fps.sandbox.amazon.com')
    params.update({'signature': signature})
    fps_url = FPS_ENDPOINT + '?' + urllib.urlencode(params)
    return fps_url

Notice how we specified both a value and currency code for the AdjustmentAmount parameter. This is a requirement of the FPS API for the WriteOffDebt call.

As usual the response data includes a TransactionId and status code, similar to the other FPS API calls that we have seen.

Getting debt balances

Just like balances for prepaid instruments, customers are unable to see their current debt balance from the Amazon Payments service. We provide this functionality for them by making a call to the GetDebtBalance API function.

The GetDebtBalance call can also be useful to determine an amount to write off for an entire debt, if necessary.

GetDebtBalance takes a single parameter, CreditInstrumentId, a unique identifier for the credit instrument we're inspecting. This value was returned in the response data after the initial authorization step. We can initiate the GetDebtBalance call with the following Python function:

def get_debt_balance(credit_instrument_id):
    timestamp = aws_timestamp()
    params={'Action': 'PrepaidBalance',
                  'AWSAccessKeyId': settings.AWS_ACCESS_KEY,
                  'SignatureVersion': '2',
                  'SignatureMethod': 'HmacSHA256',
                  'Version': '2009-01-09',
                  'Timestamp': timestamp,
                  'CreditInstrumentId': credit_instrument_id}
    signature = sign_aws_request(params, 'fps.sandbox.amazon.com')
    params.update({'signature': signature})
    fps_url = FPS_ENDPOINT + '?' + urllib.urlencode(params)
    return fps_url

Django integration

Now we can begin integrating aggregated payments into our Django application. Because of the numerous variables to keep track of, we will need to retain our reference values. Since we're building in Django, a Model subclass seems appropriate.

But what values need to be stored? There are a variety of IDs, tokens and the like, do we need all of them? It turns out that every important value we'll need can be retrieved, if necessary, using the CallerReference value we include in each of our requests. In addition, Amazon recommends storing all TransactionID values returned from FPS service calls and associating them with the correct CallerReference.

For the most part, the FPS response values we need will be used right away. Our storing these reference values is mostly a back-up plan in case we run into problems. It is also a good idea to store the request ID value, which is returned with every request sent to Amazon web services. This is for troubleshooting purposes, in case there is a problem and then AWS requires the request ID.

A Django model to persist this information may seem quite simple. But with only these two reference values, we have no way to relate the FPS transactions back to our application's order tracking. For this we need a relationship with our Order model.

class TokenReference(models.Model):
    order = models.ForeignKey(Order)
    funding_reference = models.CharField(max_length=128) 
    sender_reference = models.CharField(max_length=128) 
    transaction_id = models.CharField(max_length=35)

This makes sense because we will need to track orders for digital goods just like traditional sales.

View implementation

Our view code will be responsible for tracking the reference values stored in the TokenReference model. It is likely that we will want to redirect the user to the CBUI site ourselves, instead of providing a direct link, so that we can capture the reference information in our Django model.

To do this, we'll create a cbui_redirect view and wire our Pay Now button links to use it. It will take a dollar amount, which is the amount the customer will authorize for prepaid or postpaid credit.

def sender_reference(user):
    return '%s_%s' % (user.username, datetime.now())

def funding_reference(order):
    return '%s' % order.pk

def make_order(user, amount):
    # Create an Order object for this user's aggregated payments purchase
    return Order(customer=user, total_price=amount,
                       status_code=get_status_code("NEW"))

def cbui_redirect(request, amount=25.00, pay_type='prepaid'):
    order = make_order(request.user, amount) 
    caller_sender_reference = sender_reference(request.user)   
    caller_funding_reference = funding_reference(order)
    TokenReference.objects.create(order=order,
                         sender_reference=caller_sender_reference,   
                         funding_reference=caller_funding_reference)

    if pay_type is 'prepaid':
        redirect_url = get_prepaid_token(
                                  caller_sender_reference,
                                  caller_funding_reference,
                                  amount,
                                  reverse('cbui_return'))
    elif pay_type is 'postpaid':
        redirect_url = get_postpaid_token(
                                  caller_sender_reference,
                                  caller_funding_reference,
                                  amount,
                                  reverse('cbui_return'))
    else:
        raise ValueError
return HttpResponseRedirect(redirect_url)

The purpose of this view is to:

  1. Create a new Order object for this aggregated payment request.
  2. Generate unique reference numbers to identify the request to Amazon.
  3. Redirect the user's browser to the Amazon Co-Branded UI page to finalize authorization.

This view also references a cbui_return view, which would be the view to handle the user's return from FPS's CBUI. It is likely that some additional order management is required in both these views. We could possibly stick a copy of the customer's order in the session object so that subsequent steps can look up the appropriate TokenReference object by the Order ID.

View implementations for FPS Aggregated Payments are complicated by the amount of information we need to pass around between our own view code and FPS API calls. Particularly problematic is the response data we receive in support of our returnURL value, when we sent the user to the CBUI. This includes the fundingTokenID and prepaidInstrumentID values.

There are a variety of possibilities: we could create another Django model to store the token information and relate it back to the user and/or order. This approach would require the security of our database to be strong, because anyone with access to this token information and our AWS_SECRET_KEY could potentially cause harm.

Another potential optimization would be to create an aggregated payments version of our shopping cart. This could include token information assigned to the shopping cart itself, which would make it easy to manage the customer's balance as they make purchases.

Amazon's Web Services and Flexible Payment Services in particular are generally very large, sometimes unwieldy APIs. They also suffer documentation problems, probably due to their complexity. But the examples we've begun in this chapter should be enough to get started implementing aggregated payments in your own applications. For more information, the full FPS Aggregated Payments documentation is available from: http://aws.amazon.com/documentation/fps/.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset