Order Fulfillment

After the user completes the purchase flow, you need to check the payment status, complete the order if the payment was successful, and inform user that they have received the product they purchased.
There are two primary methods through which you are notified of the outcome of the purchase, and a further method by which you can verify payment information. To illustrate this, take a look at the diagram below, and read the description of each phase in the corresponding table underneath the diagram.
Payment Flow Diagram
PhaseExplanation
Order IdentificationOptional1. Client sends information to the Developer Server about the upcoming purchase, so it can be identified by the developer later in the fulfillment process.
2. Developer Server generates a unique request_id and persists it along with the information sent by the client, to be reconciled later (see step 10).
Payment Invocation3. Client invokes the payment flow by launching the Pay Dialog.
4. Optional If using Dynamic Pricing, Facebook requests a price for the product for the given user.
5. Optional The Developer Server responds with price for given product-user pair.
6. Facebook responds to Client payment flow invocation by rendering the Pay Dialog.
Order Placement7. User follows Pay Dialog flow and completes purchase of product.
8. Facebook invokes JavaScript callback on Client, passing encrypted payment verification payload as a signed_request. Facebook also notifies Developer Server of payment via Realtime Update (see step 12).
Order Fulfillment9. The Client sends the signed_request to the Developer Server for verification.
10. The Developer Server verifies the payment by decoding the signed request from the Client and using the payment verification payload in one of the following two ways:
  1. Using the request_id parameter to compare the purchase details against the persisted data from step 1
  2. Making a call to Facebook Graph API to confirm the payment details are as expected
11. The Developer Server responds confirming that the order was confirmed and verified.
Asynchronous Confirmation12. The Developer Server receives payment confirmation via Realtime Update, and persists it as a backup payment verification method.

Order identification

Before an order is initiated, it may be useful to identify it via a developer-generated ID. To help with this, Facebook supports passing in an optional Request ID parameter when using the JavaScript SDK to render the Pay Dialog. It is the developer's responsibility to ensure that IDs provided are unique.
When generating a Request ID, the developer should store information about the upcoming purchase along with the ID, including the product being purchased and the user making the purchase. This information can be supplied by the UI component that initiates the payment flow, and can then be used later in the payment flow to verify that the purchase was not manipulated in between the client and server, or to retrieve a payment via a call to the Graph API in instances where the Payment ID isn't known.
In the payment flow diagram above, steps 1 and 2 illustrate obtaining a Request ID in advance of launching the Pay Dialog. This sequence is important, as the Request ID cannot be added to a purchase later in the flow. Therefore, when using Request IDs, the Client must wait until an ID has been generated before launching the Pay Dialog.

Payment invocation

The payment flow for a given product is initiated via a call to the Pay Dialog, optionally including the Request ID described above.
If the developer is using Dynamic Pricing, Facebook will not know what price to display in the dialog until a dynamic price request has been made to the developer's Payment Callback URL. This request adds to the total round-trip time for a payment, and should be avoided by using Static Pricing wherever possible. The Dynamic Pricing flow is shown in steps 4 and 5 in the payment flow diagram above.
When Facebook handles the Pay Dialog call, it renders a modal dialog box that shows the user information about the product they're about to purchase. This is referenced in step 6 in the payment flow diagram.

Order placement

The user follows the Pay Dialog flow to confirm their purchase of the product. This confirmation is sent back to Facebook, where the payment will be processed (step 7 above). When this happens, Facebook confirms the purchase status in two ways:
  1. A payment verification payload is passed to the JavaScript callback specified when launching thePay Dialog.
  2. A payment ID is passed to the Realtime Update callback URL specified in the App Dashboard.
The payment verification payload passed to the JavaScript callback contains a Payment ID, some details about the payment and a signed_request containing an encrypted version of the payload.
Here is an example:
{
  "payment_id": 335633293233538,
  "amount": "0.69",
  "currency": "GBP",
  "quantity": "1",
  "request_id": "60046727",
  "status": "completed",
  "signed_request": "i0bS5X...ZWQifQ"
}
All payments have a status field. There are three possible values:
NameExplanation
initiatedAn initiated payment designates the payment was only initiated and has not yet completed. You should not fulfill an order with this status. You may see initiatedstate for certain payment methods which require a long time to settle, for example, those which require a user to fill in a form online, print out a receipt and go to the bank offline to pay.
completedcompleted status means the payment was successfully completed. You should fulfill orders with this status.
failedThis designates a failed payment. You should not fulfill an order with this status.
There are circumstances where the JavaScript callback may not be triggered. For example, a user may close their browser before they close the Pay Dialog, or before the payment process completes. In these instances, the Realtime Update for Payments provides a valuable backup confirmation.
Once you subscribe to receive Realtime Updates for Payment objects, your specified callback URL will receive an object, or array of objects, each containing a payment ID and a list of changed fields.
Here is an example:
{
  "object": "payments",
  "entry": [
    {
      "id": "296989303750203",
      "time": 1347996346,
      "changed_fields": [
        "actions"
      ]
    }
  ]
}
Realtime Updates will not be sent until the developer subscribes to the actions anddisputes fields for the payment object. Please see Realtime Updates for Payments for more information.
A realtime update will only be sent for payments that have a status of completed or failed. Payments that are in the initiated state will not result in realtime updates being sent.
Unlike other Realtime Updates, payment object updates are never batched. You will always receive a new update for each transaction. However, due to the way updates are delivered, they should be handled asynchronously, and should not block the client-side fulfillment flow.
Check the documentation for more information about Realtime Updates for Payments.

Order fulfillment

When the Client receives order confirmation via the JavaScript callback, they should do some verification before fulfilling the order. This is necessary to avoid instances where the payment flow has been manipulated on the client before fulfillment.
The most secure way to verify an order is to use the signed_request parameter from the JavaScript callback, as this has been encoded using the App Secret and cannot be manipulated by the client. By passing this to your Developer Server, and parsing it server-side, you get trusted information about the details of the payment in a synchronous manner, which you can use to verify the payment before fulfilling. This is shown in step 9 in the payment flow diagram.
Here is a sample of a decoded signed_request:
{
   "algorithm":"HMAC-SHA256",
   "amount":"5.00",
   "currency":"USD",
   "issued_at":1387285426,
   "payment_id":495869157196092,
   "quantity":"1",
   "request_id":"60046727",
   "status":"completed"
}
With a decoded signed_request, you will now be able to verify the payment, as shown in step 10 in the diagram. You can verify the payment in one of two ways:

1. Verification via Request ID

If using Request IDs, you can match the payment information from the signed_request with the information stored when generating the Request ID. By checking that the product and price are as expected, you'll know whether the payment is is OK to fulfill.
By using this method, you can avoid making a blocking call to the Graph API to retrieve details about the purchase, as you can match the information in the signed_request with information you recorded in the order identification phase.
If you want to retrieve information about the purchase at a later date using the request_id, you can use the following Graph API request:
GET https://graph.facebook.com/USER_ID/payment_transactions
      ?request_id=YOUR_REQUEST_ID
      &access_token=APP_ACCESS_TOKEN

2. Verification via Graph API

If not using Request IDs, you can make a call to the Graph API to confirm that the payment details match what you expected to see from the purchase flow. To verify that a purchase was completed successfully, make a Graph API call based on the Payment ID with an app access token. For example:
GET https://graph.facebook.com/PAYMENT_ID?access_token=APP_ACCESS_TOKEN
You'll see a response in the following format:
{
  "id": "335633293233538", 
  "user": : {
    "name": "Connor Treacy",
    "id": "696580152"
  }, 
  "application": {
    "name": "Friend Smash", 
    "namespace": "friendsmashsample", 
    "id": "577408975624572"
  }, 
  "actions": [
    {
      "type": "charge", 
      "status": "completed", 
      "currency": "GBP", 
      "amount": "0.69", 
      "time_created": "2013-08-23T14:37:22+0000", 
      "time_updated": "2013-08-23T14:37:24+0000"
    }
  ], 
  "refundable_amount": {
    "currency": "GBP", 
    "amount": "0.69"
  }, 
  "items": [
    {
      "type": "IN_APP_PURCHASE", 
      "product": "http://www.friendsmash.com/og/friend_smash_coin.html", 
      "quantity": 1
    }
  ], 
  "country": "GB", 
  "created_time": "2013-08-23T14:37:22+0000", 
  "test": 1, 
  "fraud_status": "UNKNOWN", 
  "payout_foreign_exchange_rate": 1.540539495
}
In the actions array, there should be an element where the type field is set to charge, and a statusof completed. This indicates the payment has been successfully completed. Before fulfilling the order, it is important that you also confirm the amount in the actions array and the product in the itemsarray, to make sure the purchase was authentic. If these details don't match what you expected to see, it's possible that the payment request was manipulated at the client-side, so you can either reject it or fulfill only the products indicated in the items array.
Once a payment has been verified using either of the above methods, the Developer Server can then respond to the Client and confirm that it should fulfill the order by granting the user the item they purchased (step 11 above).

Asynchronous confirmation

Supporting asynchronous order fulfillment is a mandatory requirement of Facebook Payments.
Please see Realtime Updates for Payments for more information.
You can get additional confirmation of a successful payment by subscribing to Realtime Updates for Payments and specifying a callback URL. Whenever there's a change in the actions field of a payment made in your app, Facebook will notify the specified callback. This tells you that a new action has been taken on a payment_id, whether it's been chargedrefunded, or disputed. You can check the current status of the payment by querying the Payment Graph API to verify the order state.
If you haven't seen the payment_id before then this is likely a new charge. Conversely, if you have already seen this payment_id in your application, than the order has been refunded or disputed. Whatever the state, you are expected to handle the order accordingly in your game, either by granting the in-game item upon successful charge or retracting an item after a refund or dispute. Keep in mind that a payment can be updated after it's marked completed, for instance when Facebook directly updates it with a refund, chargeback or chargeback reversal.
The updates sent to your callback will take the form:
{
  "object": "payments",
  "entry": [
    {
      "id": "296989303750203",
      "time": 1347996346,
      "changed_fields": [
        "actions"
      ]
    }
  ]
}
For more information, please see Realtime Updates for Payments.

Next steps

A user should now be able to purchase and obtain items within your app. As part of providing a complete sales service, you also are responsible for handling user disputes and refunds, detailed in the next section.
Was this document helpful?