Payments Disputes

How to handle disputed payments

There are occasional times when a costumer will wish to revoke a payment made in your app or game. As a developer, you're responsible for efficiently responding to such requests, providing a trustworthy and fair service to your customers.

Facebook's payments platform offers a mechanism for being alerted when a costumer disputes a transaction and suggests best practices for handling such disputes. Handling consumer disputes is a mandatory requirement of Facebook Payments.

Facebook's Dispute Philosophy

Facebook's philosophy regarding payment disputes is that we'll provide primary support for cases in which the costumer requests a full refund of the payment or contends a transaction directly with their funding provider (ex, a credit card company or PayPal). However, when they have an in-app purchasing issue, or don't receive a purchased item or currency, they'll be routed directly to the developer. In the latter case, the developer is best equipped to satisfy the dispute, typically by issuing more or replacement in-app items, refunding the payment or providing clarification.

As part of Facebook’s commitment to ensuring a positive experience for players, developers that accept payments are required to offer timely responses to any disputed transactions within their apps. Developers must either use the Disputes or Refunds API to inform Facebook of the outcome of each dispute that occurs within their product. Facebook reserves the right to auto-refund any dispute not handled by the developer after 72 hours.

How Users Dispute a Transaction

The dispute resolution process is designed to provide the player and the developer with an easy way to communicate regarding a contended payment. The user is provided with links to dispute a transaction in multiple places, all of which link to the Facebook Payments Support area of the Facebook Help Center. The payment dispute flow is either presented as a standalone web page, or as an overlay on top of your app.

The methods of invoking the dispute flow are enumerated below:

  1. In-App Dispute Flow
Report
Select the I'm having a Payment Issue option
  1. User Payment Settings on Facebook
Payments Settings
  1. User Payment Settings via Receipt Email
Receipt Email

Regardless of how the Facebook Payments Support flow is initiated, consumers are prompted to identify their issue by answering a series of multiple choice questions. Depending on the costumer's selection, they're directed to the appropriate contact, either Facebook or the developer. Facebook will only contact the developer via webhooks updates for the cases when a costumer has an in-app purchasing issue, or doesn't receive a purchased item. Not every disputed transaction will generate an update.

Resolving a Dispute

After the costumer has initiated a dispute, a webhooks update is sent to the developer with the corresponding payment_id for the disputed transaction. The developer can then query the Graph API to retrieve additional information regarding the transaction, including the user's email address, and their specified reason for initiating the dispute. It is then the developer's responsibility to use this information to communicate with the user and reach an agreed solution. This process is illustrated below:

As illustrated in the diagram above, once a dispute has been created by the user, Facebook will add additional information to the Graph API return data associated with the disputed payment_id. These additional fields are combined under a disputes array as follows:

Parameter Description

disputes/user_comment

The free text reason for the dispute entered by the user.

disputes/time_created

The time in PST at which the user created the dispute.

disputes/user_email

The user's preferred email address.

disputes/status

The current status of the dispute.

disputes/reason

Dispute resolution outcome’ (pending, refunded_in_cash, granted_replacement_item, denied_refund, banned_user)

A full sample response from the Graph API for a disputed transaction is below:

{
  "id": "519180411528475", 
  "user": {
    "name": "Marco Alvarez", 
    "id": "500535225"
  }, 
  "application": {
    "name": "Friend Smash", 
    "namespace": "friendsmashsample", 
    "id": "241431489326925"
  }, 
  "actions": [
    {
      "type": "charge", 
      "status": "completed", 
      "currency": "EUR", 
      "amount": "0.80", 
      "time_created": "2014-02-12T00:49:38+0000", 
      "time_updated": "2014-02-12T00:49:38+0000"
    }
  ], 
  "refundable_amount": {
    "currency": "EUR", 
    "amount": "0.80"
  }, 
  "items": [
    {
      "type": "IN_APP_PURCHASE", 
      "product": "https://ancient-savannah-6416.herokuapp.com/opengraph/coin.html", 
      "quantity": 10
    }
  ], 
  "country": "US", 
  "request_id": "ISgQj4vGrrnmhGyABL5IaRmeUAoYlL2BrMoMOnmbsFj7AxrNurHej3jeZZS3710k", 
  "created_time": "2014-02-12T00:49:38+0000", 
  "payout_foreign_exchange_rate": 1.343826, 
  "disputes": [
    {
      "user_comment": "I didn't get my Friend Smash coin! Please help!", 
      "time_created": "2014-02-12T01:37:27+0000", 
      "user_email": "email@domain.com", 
      "status": "pending", 
      "reason": "pending"
    }
  ]
}

After reviewing the user-provided reason for the dispute and optionally their transaction history and any additional correspondence, you must take one of the following actions to signal the outcome of the dispute to Facebook:

  1. Settle the dispute by issuing a complete or partial refund
  2. Resolve the dispute by taking one of three defined actions other than issuing a refund, e.g. by rewarding the player with in-game items

The status field of a dispute has two states: pending, after the consumer has disputed the transaction and is waiting on the developer to resolve it and resolved, after Facebook or the developer have settled the dispute. Facebook will only consider a dispute as being settled if one of the actions above has been taken by the developer for each disputed payment, otherwise Facebook will issue an auto-refund within 72 hours of the dispute being issued.

After a dispute is settled, Facebook recommends, as a best practice, to communicate with the user the outcome of the dispute and any associated actions taken. You can choose to do this via the provided user email address and/or in-app messaging. This will ensure the best experience for people using your app.

Issuing a complete or partial refund

If a dispute justifies a refund, you can award one using the transactions's ID and making a post to the /PAYMENT_ID/refunds with an ~app access token~ and the amount to be refunded. You can read more about refunding payments on the Transaction Updates doc. The dispute status will automatically be set to resolved with the refunded_in_cash reason.

A payment doesn't necessarily have to be disputed by the consumer for you to be able to refund it. If a user contacts you directly, you can issue a refund for the payment as long as the refundable_amount is greater than the amount you're trying to refund. This functionality is also helpful when you are testing your app.

Updating a Dispute's Status

There are several cases where settling a dispute does not require the developer to issue a monetary refund to the customer. For these special cases, Facebook provides a Payment Dispute API, for settling a dispute and communicating the outcome with both the customer and Facebook. It also acts as a historical log of actions taken on each disputed transaction.

After resolving a dispute, in order to update the status of a dispute, make an HTTP POST call to the Graph API endpoint /PAYMENT_ID/dispute with an app access token, and the following parameters:

Name Description Type

reason

The reason you are settling this dispute. This is a required parameter and must be one of the following constants: GRANTED_REPLACEMENT_ITEM, DENIED_REFUND, BANNED_USER. Providing any value other than those enumerated here will result in an error.

string

The response from the Graph API will be true on success, or an error code otherwise. The developer is allowed to update this field after it has been settled if they need to change the resolution reason.

After you've updated the dispute's status you can verify it by querying the Graph API on the /payment_idendpoint. Below is an example Graph API response for a payment transaction that has been resolved by the developer with a GRANTED_REPLACEMENT_ITEM reason:

{
  "id": "519180411528475", 
  "user": {
    "name": "Marco Alvarez", 
    "id": "500535225"
  }, 
  "application": {
    "name": "Friend Smash! Dev", 
    "namespace": "fsmashdev", 
    "id": "241431489326925"
  }, 
  "actions": [
    {
      "type": "charge", 
      "status": "completed", 
      "currency": "EUR", 
      "amount": "0.80", 
      "time_created": "2014-02-12T00:49:38+0000", 
      "time_updated": "2014-02-12T00:49:38+0000"
    }
  ], 
  "refundable_amount": {
    "currency": "EUR", 
    "amount": "0.80"
  }, 
  "items": [
    {
      "type": "IN_APP_PURCHASE", 
      "product": "https://ancient-savannah-6416.herokuapp.com/opengraph/coin.html", 
      "quantity": 10
    }
  ], 
  "country": "US", 
  "request_id": "ISgQj4vGrrnmhGyABL5IaRmeUAoYlL2BrMoMOnmbsFj7AxrNurHej3jeZZS3710k", 
  "created_time": "2014-02-12T00:49:38+0000", 
  "payout_foreign_exchange_rate": 1.343826, 
  "disputes": [
    {
      "user_comment": "I didn't get my Friend Smash coin! Please help!", 
      "time_created": "2014-02-12T01:37:27+0000", 
      "user_email": "mail@domain.com", 
      "status": "resolved", 
      "reason": "granted_replacement_item"
    }
  ]
}

For complete details on how the payment object is changed after a dispute is updated, please refer to the Payment Graph API reference doc.

Facebook-Initiated Refunds and Effect on Developer Revenue

In the examples above, the developer has been primarily responsible for handling a user dispute. There are however, circumstances in which Facebook will assume the primary point of contact for the user, typically in the case of user-confusion or fraud complaints.

Below is a simple description of how we classify refunds:

  • Non-fraud dispute: User request for monetary refund related to mistaken purchase or misuse of financial instrument by family or friend.
  • Malicious fraud charge dispute: Unauthorized purchase associated with a stolen financial instrument or compromised account.

For all non-fraud disputes, Facebook reviews a user's refund request on a case-by-case basis. Typically, non-fraud refund requests are as a result of user confusion, where the purchase was made accidentally due to a misunderstanding of the purchase flow. Our qualitative investigation examines factors including previous orders, spending frequency, and account level details. Facebook will refund the charges only if the user's reason for the dispute is deemed appropriate to receive a full reversal. Facebook monitors refund rates to protect against users who might attempt to defraud developers or Facebook by abusing the dispute resolution process.

For fraudulent charges made using a user's payment instrument brought to the attention of Facebook, we will always seek to fully refund a user as quickly as possible. Doing so prevents a user having to resort to a chargeback, and builds trust with honest users who may fall victim to fraud. If Facebook determines that the dispute is valid and that the user should be refunded, we will recover the cost of such a provision from the developer. Facebook does this by deducting the refunded amount from the next payout made to the developer at the end of the twice-monthly payout cycle. We will only do this for transactions disputed within 90 days of the the original transaction date.

As with disputes, you will be notified via a realtime update when Facebook refunds an order. Also, as before, additional information will be added to the Graph API return data for the payment. Rather than an additionaldisputes array, there will be a refund object added to the actions array, signifying the payment has been refunded.

If there is reason for concern, please reach out to us via our Help Center and we will work with you to investigate your individual app or use-case.

Below is an example Graph API response for a payment transaction refunded by Facebook:

{
   "id": "3603105474213890",
   "user": {
      "name": "Marco Alvarez",
      "id": "500535225"
   },
   "application": {
      "name": "Friend Smash",
      "namespace": "friendsmashsample",
      "id": "241431489326925"
   },
   "actions": [
      {
         "type": "charge",
         "status": "completed",
         "currency": "USD",
         "amount": "0.99",
         "time_created": "2013-03-22T21:18:54+0000",
         "time_updated": "2013-03-22T21:18:55+0000"
      },
      {
         "type": "refund",
         "status": "completed",
         "currency": "USD",
         "amount": "0.99",
         "time_created": "2013-03-23T21:18:54+0000",
         "time_updated": "2013-03-23T21:18:55+0000"
      }
   ],
   "refundable_amount": {
      "currency": "USD",
      "amount": "0.00"
   },
   "items": [
      {
         "type": "IN_APP_PURCHASE",
         "product": "http://www.friendsmash.com/og/friend_smash_bomb.html",
         "quantity": 1
      }
   ],
   "country": "US",
   "created_time": "2013-03-22T21:18:54+0000",
   "payout_foreign_exchange_rate": 1,
   "disputes": [
    {
      "user_comment": "I want my money back!", 
      "time_created": "2013-03-23T01:37:27+0000", 
      "user_email": "mail@domain.com", 
      "status": "resolved", 
      "reason": "refunded_by_facebook"
    }
  ]
}