# Fulfill purchases through the SDK

> Retrieve purchase information and determine purchase status for products bought by players.

> **Important:**
>
> For Payment Providers, you must specify the store name (`PaymentProvider.Name`) when you call the `UnityIAPServices` or `StoreController`. `PaymentProvider.Name` specifies  that you want to use a Direct to Consumer (D2C) provider integration and does not return the display name of the provider.

Unity IAP fetches purchase information from the store so your application can recognize and fulfill what players have bought. This ensures that your game can deliver content or entitlements to users based on their purchase history, even if they bought items outside your app or on another device.

A purchase is represented as an [`Order`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.Order.html) object. The `Order` contains all relevant details about the purchase and provides information needed to track and manage it with the store.

## Retrieve purchases

Purchases made by the user can be retrieved from the store. However, consumable products must be tracked by your application after they are consumed, because stores don't return consumables that have already been fulfilled. For non-consumable products and subscriptions, the store accurately returns these purchases when you call [`FetchPurchases`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.IPurchaseService.html#UnityEngine_Purchasing_IPurchaseService_FetchPurchases) or [`CheckEntitlement`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.IPurchaseService.html#UnityEngine_Purchasing_IPurchaseService_CheckEntitlement_UnityEngine_Purchasing_Product_).

## Determine purchase status

You can determine the status of a purchase in two ways:

* Use [`Order`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.Orders.html) to determine if the `Order` is a `PendingOrder`, `ConfirmedOrder`, `DeferredOrder` or `FailedOrder`.
* Use `CheckEntitlement` to receive [`EntitlementStatus`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.Entitlement.html#UnityEngine_Purchasing_Entitlement_Status), which returns `EntitledButNotFinished`, `EntitledUntilConsumed`, `FullyEntitled`, `NotEntitled` or `Unknown`.

### Purchase attributes

| Attribute       | Description                                              |
| --------------- | -------------------------------------------------------- |
| `transactionId` | A unique identifier for the purchase.                    |
| `product`       | The purchased product.                                   |
| `quantity`      | The quantity of the product purchased.                   |
| `receipt`       | Receipt data for validating the purchase with the store. |

### Purchase states

| State       | Description                                       |
| ----------- | ------------------------------------------------- |
| `Pending`   | The purchase has been paid but not yet fulfilled. |
| `Confirmed` | The purchase has been fulfilled and acknowledged. |
| `Failed`    | The purchase failed due to an error.              |
| `Deferred`  | The purchase is waiting for payment.              |

## Process purchases

The [`OnPurchasePending`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.IPurchaseService.html#UnityEngine_Purchasing_IPurchaseService_OnPurchasePending) callback is invoked when a purchase is made and is awaiting fulfillment. Your application should fulfill the purchase at this point, for example by unlocking local content or sending the purchase receipt to a server to update a server-side game model.

Note that `OnPurchasePending` may be called at any point following a successful initialization. If your application crashes during execution of the `OnPurchasePending` handler, then it is invoked again the next time Unity IAP initializes. Consider implementing your own de-duplication logic.

> **Note:**
>
> If you don't confirm purchases, the store sends back the purchases, and some stores may even refund it automatically to protect the users.

```cs
// Handle restore on initialization
private async void Start()
{
    // Setup, e.g. add listeners to your StoreController...
    m_StoreController.OnPurchasePending += OnPurchasePending;
    m_StoreController.OnPurchasesFetched += OnPurchasesFetched;
    await m_StoreController.Connect();

    // Fetch previous purchases (includes confirmed orders)
    m_StoreController.FetchPurchases();
}

// Handle new purchases and pending transactions
private void OnPurchasePending(PendingOrder order)
{
    ProcessPurchase(order);
}

// Handle fetched purchases (includes previously confirmed orders)
private void OnPurchasesFetched(Orders orders)
{
    foreach (var confirmedOrder in orders.ConfirmedOrders)
    {
        if (confirmedOrder.CartOrdered.Items().FirstOrDefault()?.Product.definition.type != ProductType.Consumable)
        {
            // Mark non-consumable and subscription products as entitled on fetch, as they only need to be granted once
            MarkAsEntitled(confirmedOrder.CartOrdered.Items().FirstOrDefault().Product);
        }
    }
}

// Your ProcessPurchase logic
private void ProcessPurchase(PendingOrder order)
{
    foreach (var product in order.CartOrdered.Items())
    {
        // Grant product
        GrantProduct(product);
    }
    // Confirm the order to finalize the transaction
    m_StoreController.ConfirmPurchase(order);
}
```

## Purchase acknowledgement and reliability

Unity IAP requires you to explicitly acknowledge purchases to ensure that purchases are reliably fulfilled, even during network outages or application crashes. If a purchase is paid for but not fulfilled, Unity IAP delivers the purchase to your application the next time it initializes. This process prevents purchases from being lost when the purchase flow is interrupted or when purchases are completed while the application is offline.

After successfully fulfilling a purchase, call [`ConfirmPurchase`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.IPurchaseService.html#UnityEngine_Purchasing_IPurchaseService_ConfirmPurchase_UnityEngine_Purchasing_PendingOrder_) with the relevant  `PendingOrder` to acknowledge the purchase to the store.

> **Warning:**
>
> Always acknowledge purchases. If you don't, the following can happen:
>
> * Unity IAP re-invokes `OnPurchasePending` for the order on every subsequent `FetchPurchases` call or session start until you acknowledge it. Without your own de-duplication logic, this can grant the same item more than once.
> * Some stores reverse the purchase automatically. For example, Google Play refunds an unacknowledged purchase after three days, and the Apple App Store applies similar protective logic on a less strict timeline.
> * To the player, the purchase appears to succeed and then disappear, which looks like a broken purchase.

> **Note:**
>
> For consumables, once you acknowledge the purchase, the store does not return it again. Always persist consumable rewards remotely. If you store consumable rewards locally, you risk losing data with no way to restore it.

## Acknowledge purchases persisted to the cloud

If you are saving consumable purchases to the cloud, you must call [`ConfirmPurchase`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.IPurchaseService.html#UnityEngine_Purchasing_IPurchaseService_ConfirmPurchase_UnityEngine_Purchasing_PendingOrder_) when you have successfully persisted the purchase.

When returning `Pending`, Unity IAP keeps transactions open on the underlying store until confirmed as processed. This ensures consumable purchases are not lost even if a user reinstalls your application while a consumable is pending.

## Restore purchases

Enable users to regain access to previously owned products and subscriptions when they reinstall your app or switch devices. Understand how IAP retrieves a record of entitlements and grants access:

* When a user reinstalls the application, Unity IAP restores owned products on the first `StoreController.FetchPurchases()` call.
* IAP invokes the `OnPurchasesFetched` listener with an `Orders` object that includes all purchases (all states).
* If the `PurchaseService.ProcessPendingOrdersOnPurchasesFetched` setting is set to `true`, IAP invokes the `OnPurchasePending` listener for each unfulfilled purchase.
* Subsequent `FetchPurchases()` calls in the same session don't trigger `OnPurchasePending` for orders that you have already seen in the same session.

## Use server-side validation alongside the SDK

You can make calls to the backend API while using the Unity In-App Purchases (IAP) SDK. This hybrid approach allows your server to act as the authority by validating transactions directly against Unity’s records before you reward the player. Unlike the standard backend API method, this doesn't require you to expose a public endpoint for webhooks, which can reduce your attack surface and simplify your server infrastructure.

### Client-side implementation

When a purchase is initiated, the SDK returns a `PendingOrder` object. Extract the `OrderInfo.TransactionId` and pass it to your backend.

### Backend authentication

> **Important:**
>
> To make calls to the Unity IAP API, your backend must authenticate as a [Service Account](/cloud/accounts/create-service-account.md).

Use the Key ID and Secret Key from your Service Account to perform a Token Exchange to receive a stateless Bearer token. For more information, refer to how to [Authenticate an API using a stateless token](https://services.docs.unity.com/docs/service-account-auth/#authenticate-an-api-using-a-stateless-token).

Refer to the following token exchange endpoint:

```http
POST https://services.api.unity.com/auth/v1/token-exchange?projectId={projectId}&environmentId={envId}
```

### Validate the order

Once your backend has a Bearer token, query the Unity IAP Order service with the following request:

```http
GET https://iap.services.api.unity.com/v1/projects/{projectId}/environments/{envId}/orders/{orderId}
```

The `orderId` is the same as the `TransactionId` in the previous step.
Refer to the following important response fields:

* `status` must be `paid` before you grant the items.
* `paymentProviderResourceId` contains the underlying Stripe Checkout Session ID, if you need it to cross-reference in the Stripe Dashboard.

### Fulfill and complete the order

Refer to the following workflow to complete orders with server authority:

1. Verify that the status is paid and the productSku matches the expected item.
2. Update your player's database with the new entitlement.
3. After the backend returns a success code to the client, use one of the following methods to finalize the transaction in the Unity IAP system:
   * [Update the order directly with the API](https://staging.docs.unity.com/en-us/iap/payment-providers/implement-backend.md#update-an-order)
   * Make the client call `m_StoreController.ConfirmPurchase(order)`.

For more information, refer to the section on how to [Mark orders as fulfilled through the API](./implement-backend.md#mark-orders-as-fulfilled-via-api).

## Next steps

This page is part of a workflow to set up Direct to Consumer (D2C) payment providers with IAP. To continue this workflow, choose one of the following options:

[Integrate D2C payment providers](./workflow.md#fulfill-purchases-through-the-sdk): Return to the Integrate D2C payment providers with IAP workflow page.
[Test Stripe](./test-stripe.md): Proceed to the next step in the workflow to set up your D2C payment provider.
