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.
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.
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 recordscallerReferenceFunding
: This is a unique identifier that you supply to specify this payment token and its funding in your recordsThese 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:
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:
return_url
.Pay
request to the FPS API.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 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.
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.
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
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.
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.
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.
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.
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.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.
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
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.
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:
Order
object for this aggregated payment request.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/.