After the player completes the purchase flow, you must check the payment status, complete the order if the payment was successful and inform them that they've received the item. |
There are 2 primary methods through which you're notified of the outcome of the purchase, and a further method by which you can verify payment information. To illustrate this flow, look at the diagram below and read the description of each phase in the corresponding table underneath the diagram.
Phase | Explanation |
---|---|
Order Identification Optional | 1. Client sends information to the Developer Server about the upcoming purchase, so it can be identified later in the fulfillment process. 2. Developer Server generates a unique |
3. 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. | |
7. User follows Pay Dialog flow and completes purchase of product. 8. Facebook invokes JavaScript callback on Client, passing encrypted payment verification payload as a | |
9. The Client sends the 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 2 ways:
11. The Developer Server responds confirming that the order was confirmed and verified. | |
12. The Developer Server receives payment confirmation via Webhooks, and persists it as a backup verification method. |
Before an order is initiated, it is useful to identify it via a developer-generated ID. We therefore support passing in an optional request_id
parameter when invoking the Pay Dialog. This ID must be alpha-numeric, no greater than 256 characters in length and must be unique for each order made within your app. The request_id
is associated to the order being completed.
When generating a Request ID, the developer must store information about the upcoming purchase along with the ID, including the product being purchased and the user. This information can then be used later in the payment flow to verify that the purchase wasn't 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 before launching the Pay Dialog. This sequence is important, as the request_id
can't 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.
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 won't know what price to display in the dialog until a dynamic price request has been made to the developer's Payment Callback URL. The Dynamic Pricing flow is shown in steps 4 and 5 in the payment flow diagram above.
When we receive the Pay Dialog call, we will render a modal dialog box that shows the consumer information about the product they're about to purchase. This step is referenced in step 6 in the payment flow diagram.
The player 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 2 ways:
The payment verification payload passed to the JavaScript callback containing 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 3 possible values:
Name | Explanation |
---|---|
| An |
| A |
| This designates a |
There are circumstances where the JavaScript callback may not be triggered. For example, a player might close their browser before they close the Pay Dialog, or before the payment process completes. In these instances, Webhooks for Payments provide a valuable backup confirmation.
When the Client receives order confirmation via the JavaScript callback, you must do some verification before fulfilling the order. This step 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 can't be manipulated by the client. By passing this to your 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 step 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 2 ways:
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. 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 later, 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
If not using Request IDs, you can call the Graph API on your server 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 should specify the fields that you would like to see in the response. In this example, we are requesting the following fields: id, user, application, actions, refundable_amount, items, country, created_time, payout_foreign_exchange_rate.
GET https://graph.facebook.com/PAYMENT_ID?access_token=APP_ACCESS_TOKEN&fields=id,user,application,actions,refundable_amount,items,country,created_time,payout_foreign_exchange_rate
You'll see a response in the following format:
{ "id": "995633853233538", "user": : { "name": "Marco Alvarez", "id": "500535225" }, "application": { "name": "Friend Smash", "namespace": "friendsmashsample", "id": "577408975624572" }, "actions": [ { "type": "charge", "status": "completed", "currency": "MXN", "amount": "17.50", "time_created": "2015-11-23T14:37:22+0000", "time_updated": "2015-11-23T14:37:24+0000" } ], "refundable_amount": { "currency": "MXN", "amount": "17.50" }, "items": [ { "type": "IN_APP_PURCHASE", "product": "http://www.friendsmash.com/og/friend_smash_coin.html", "quantity": 1 } ], "country": "MX", "created_time": "2015-11-23T14:37:22+0000", "payout_foreign_exchange_rate": 0.0571 }
In the actions
array, there should be an parameter where the type
field is set to charge
, and a status
of completed
. These fields indicate that the payment has been successfully completed. Before fulfilling the order, it's important that you also confirm the amount
in the actions
array and the product
in the items
array, to make sure that 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).
There are some cases in which the user
property of the payment
object will be omitted when you query the Graph API, for example when the player de-activates their Facebook account. Please make sure that your code is built to handle null or empty values for this property.
After the person has finished entering their payment details in the purchase flow, Facebook will return details of the order via the JavaScript callback. This callback is invoked as the purchase flow ends, without necessarily waiting for the transaction to complete. Such transactions may complete asynchronously. As an example, there are payment methods supported by Facebook where the consumer is required to print an order completion form and physically deposit it at their bank. These methods can take hours or even days to complete.
Additionally, there are other circumstances in which the JavaScript callback method of order fulfillment can't be exclusively relied upon. For example, when a person's connectivity to your app is unreliable, the callback may never be triggered. This can happen if the consumer loses connection to the internet mid-flow, or closes their browser.
Therefore, whenever there's a change in the actions field of a payment made in your app, Facebook will notify you about it with on the specified webhooks subscription callback. This notification lets you know that a new action has been taken on a payment id
, whether it's been charged, refunded or disputed. You can check the current status of the payment by querying the payment object on the 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 app, 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.