---
title: "Sincronizar transacciones de stores personalizados"
description: "Sincroniza transacciones de stores personalizados con Adapty para gestionar accesos y hacer seguimiento de ingresos."
---

Si vendes suscripciones o compras in-app a través de **stores personalizadas** como Amazon Appstore, Microsoft Store o tu propia plataforma de pago, puedes sincronizar esas transacciones con Adapty para gestionar automáticamente los niveles de acceso y hacer seguimiento de los ingresos en tu analítica.

En esta guía aprenderás a conectar las compras de stores personalizadas con Adapty usando el SDK y la API.

#### Ejemplo de uso \{#sample-use-case\}
Supongamos que distribuyes tu app en Amazon Appstore, o que tienes tu propia tienda web para ventas directas. Cuando un usuario completa una compra en estas plataformas, quieres:
- Concederle acceso automáticamente a las funciones premium de tu app móvil
- Registrar la transacción en los análisis de Adapty junto con los ingresos de App Store y Google Play
- Activar integraciones y webhooks igual que con cualquier otra suscripción

Eso es exactamente lo que esta integración te permite conseguir.
## Paso 1. Identifica a los usuarios \{#step-1-identify-users\}

Adapty usa `customer_user_id` para identificar usuarios entre plataformas.

Necesitas crear este ID una sola vez y pasárselo tanto al SDK como a tu backend web. Cuando tus usuarios se registren por primera vez desde la app, puedes pasar su customer user ID durante la activación del SDK, o si ya activaste el SDK de Adapty antes del registro, usa el método `identify` para crear un nuevo perfil y asignarle un customer user ID.
:::important
Si identificas nuevos usuarios después de la activación del SDK, el SDK creará primero un perfil anónimo (no puede funcionar sin uno). Cuando llames a `identify` con un customer user ID, se creará un nuevo perfil.

Este comportamiento es normal y no afectará a la precisión de los análisis. Lee más [aquí](ios-quickstart-identify).
:::
<Tabs groupId="current-os" queryString>
<TabItem value="swift" label="iOS" default>
```swift showLineNumbers
do {
    try await Adapty.identify("YOUR_USER_ID") // Unique for each user
} catch {
    // handle the error
}
```
</TabItem>
<TabItem value="swift-callback" label="iOS (Swift-Callback)" default>
```swift showLineNumbers
// User IDs must be unique for each user
Adapty.identify("YOUR_USER_ID") { error in
    if let error {
        // handle the error
    }
}
```
</TabItem>
<TabItem value="android" label="Android (Kotlin)" default>
```kotlin showLineNumbers
Adapty.identify("YOUR_USER_ID") { error -> // Unique for each user
    if (error == null) {
        // successful identify
    }
}
```
</TabItem>
<TabItem value="java" label="Android (Java)" default>
```java showLineNumbers
// User IDs must be unique for each user
Adapty.identify("YOUR_USER_ID", error -> {
    if (error == null) {
        // successful identify
    }
});
```
</TabItem>
<TabItem value="react-native" label="React Native" default>
```typescript showLineNumbers
try {
    await adapty.identify("YOUR_USER_ID"); // Unique for each user
    // successfully identified
} catch (error) {
    // handle the error
}
```
</TabItem>
<TabItem value="flutter" label="Flutter" default>
```dart showLineNumbers
try {
  await Adapty().identify(customerUserId); // Unique for each user
} on AdaptyError catch (adaptyError) {
  // handle the error
} catch (e) {
}
```
</TabItem>

<TabItem value="unity" label="Unity" default>
```csharp showLineNumbers
Adapty.Identify("YOUR_USER_ID", (error) => { // Unique for each user
  if(error == null) {
    // successful identify
  }
});
```
</TabItem>
<TabItem value="kmp" label="Kotlin Multiplatform" default>
```kotlin showLineNumbers
Adapty.identify("YOUR_USER_ID") // Unique for each user
    .onSuccess {
        // successful identify
    }
    .onError { error ->
        // handle the error
    }
```
</TabItem>

<TabItem value="capacitor" label="Capacitor" default>
```typescript showLineNumbers
try {
  await adapty.identify({ customerUserId: "YOUR_USER_ID" });
  // successfully identified
} catch (error) {
  // handle the error
}
```
</TabItem>
</Tabs>
## Paso 2. Crea productos en una store personalizada en el Adapty Dashboard \{#step-2-create-products-in-a-custom-store-in-adapty-dashboard\}

Para que Adapty relacione las transacciones de la store personalizada con tus productos, debes añadir los productos y configurar los detalles de la store personalizada para cada uno.

1. Ve a [**Products**](https://app.adapty.io/settings/general) desde el menú lateral del Adapty Dashboard y haz clic en **Create product**. O haz clic en un producto existente para editarlo.
2. Asegúrate de haber seleccionado el [nivel de acceso](access-level) que quieres conceder a los usuarios que compren el producto.
3. Haz clic en **+** y selecciona **Add a custom store**.
4. Haz clic en **Create new custom store**.

5. Dale un nombre a tu store (por ejemplo, "Amazon Appstore", "Microsoft Store" o "Web Store") y un ID. Haz clic en **Create custom store**.

6. Luego, haz clic en **Save changes** para vincular el producto al store personalizado.
7. Introduce el **Store product ID** del producto para asociarlo con algún producto de ese store. Después, haz clic en **Save**.

## Paso 3. Sincroniza las transacciones mediante la API \{#step-3-sync-transactions-via-api\}

Cuando se completa una compra en tu store personalizado, debes sincronizarla con Adapty mediante la API de servidor.

Esta llamada a la API:
- Registra la transacción en Adapty
- Otorga el nivel de acceso correspondiente al usuario
- Activa las integraciones y webhooks que hayas configurado
- Hace que la transacción aparezca en tus analíticas

Consulta la referencia completa del método [aquí](api-adapty/operations/setTransaction).
```bash
curl --request POST \
  --url https://api.adapty.io/api/v2/server-side-api/purchase/set/transaction/ \
  --header 'Accept: application/json' \
  --header 'Authorization: Api-Key YOUR_SECRET_API_KEY' \
  --header 'Content-Type: application/json' \
  --header 'adapty-customer-user-id: YOUR_CUSTOMER_USER_ID' \
  --data '{
  "purchase_type": "PRODUCT_PERIOD",
  "store": "YOUR_CUSTOM_STORE",
  "environment": "production",
  "store_product_id": "YOUR_STORE_PRODUCT_ID",
  "store_transaction_id": "STORE_TRANSACTION_ID",
  "store_original_transaction_id": "ORIGINAL_TRANSACTION_ID",
  "price": {
    "country": "COUNTRY_CODE",
    "currency": "CURRENCY_CODE",
    "value": "YOUR_PRICE"
  },
  "purchased_at": "2024-01-15T10:30:00Z"
}'
```
:::important
Parámetros importantes:
- **store**: El ID de tu store personalizado del Paso 2
- **store_product_id**: El ID de producto del store del Paso 2
- **store_transaction_id**: Un identificador único para esta transacción
- **purchased_at**: Marca de tiempo en formato ISO 8601 de cuándo se realizó la compra
- **price**: El importe pagado por el usuario
:::
## Paso 4. Verificar el acceso en la app \{#step-4-verify-access-in-the-app\}

Una vez sincronizada la transacción, el perfil del usuario se actualizará automáticamente con el nuevo nivel de acceso.

Cuando el usuario abra tu app, obtén su perfil para comprobar el estado de su suscripción y desbloquear las funciones premium.

<Tabs groupId="current-os" queryString>
<TabItem value="swift" label="iOS" default>

```swift showLineNumbers
do {
    let profile = try await Adapty.getProfile()

    if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false {
        // grant access to premium features
    }
} catch {
// handle the error
}
```

</TabItem>
<TabItem value="swift-callback" label="iOS (Swift-Callback)" default>

```swift showLineNumbers
Adapty.getProfile { result in
    if let profile = try? result.get() {
        // check the access
        if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false {
            // grant access to premium features
        }
    }
}
```

</TabItem>

<TabItem value="android" label="Android (Kotlin)" default>
```kotlin showLineNumbers
Adapty.getProfile { result ->
    when (result) {
        is AdaptyResult.Success -> {
            val profile = result.value
            // check the access
            if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) {
                // grant access to premium features
            }
        }
        is AdaptyResult.Error -> {
            val error = result.error
            // handle the error
        }
    }
}
```

</TabItem>

<TabItem value="java" label="Android (Java)" default>
```java showLineNumbers
Adapty.getProfile(result -> {
    if (result instanceof AdaptyResult.Success) {
        AdaptyProfile profile = ((AdaptyResult.Success<AdaptyProfile>) result).getValue();
        // check the access
        if (profile.getAccessLevels().get("YOUR_ACCESS_LEVEL") != null && profile.getAccessLevels().get("YOUR_ACCESS_LEVEL").getIsActive()) {
            // grant access to premium features
        }

    } else if (result instanceof AdaptyResult.Error) {
        AdaptyError error = ((AdaptyResult.Error) result).getError();
        // handle the error
    }
});
```
</TabItem>
<TabItem value="react-native" label="React Native" default>

```typescript showLineNumbers
try {
    const profile = await adapty.getProfile();
    // check the access
    if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive) {
        // grant access to premium features
    }
} catch (error) {
  // handle the error
}
```
</TabItem>

<TabItem value="flutter" label="Flutter" default>
```dart showLineNumbers
try {
  final profile = await Adapty().getProfile();
  // check the access
  if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false) {
      // grant access to premium features
  }
} on AdaptyError catch (adaptyError) {
  // handle the error
} catch (e) {
}
```
</TabItem>

<TabItem value="unity" label="Unity" default>
```csharp showLineNumbers
Adapty.GetProfile((profile, error) => {
  if (error != null) {
    // handle the error
    return;
  }

  // check the access
  if (profile.AccessLevels["YOUR_ACCESS_LEVEL"]?.IsActive ?? false) {
      // grant access to premium features
  }
});
```
</TabItem>

<TabItem value="kmp" label="Kotlin Multiplatform" default>
```kotlin showLineNumbers
Adapty.getProfile()
    .onSuccess { profile ->
        // check the access
        if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) {
            // grant access to premium features
        }
    }
    .onError { error ->
        // handle the error
    }
```
</TabItem>

<TabItem value="capacitor" label="Capacitor" default>
```typescript showLineNumbers
try {
  const profile = await adapty.getProfile();
  // check the access
  if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive) {
      // grant access to premium features
  }
} catch (error) {
  // handle the error
}
```

</TabItem>
</Tabs>