# Hooks d’installation et de désinstallation de Carte

Il est possible de créer un **connecteur personnalisé** dans **The Wallet Crew** pour appeler une API externe chaque fois qu'une carte est **installée** ou **désinstallée** sur Apple Wallet ou Google Wallet.

Cela permet aux marques de **synchroniser le statut d'installation** avec des systèmes externes tels qu'un CRM, un outil d'analyse ou une plateforme d'automatisation marketing.

<details>

<summary>Exemples concrets</summary>

* Une marque de vente au détail met à jour un champ CRM comme `hasWalletCarte=true` juste après l'installation. Elle cesse ensuite d'envoyer des rappels « ajouter au Wallet ».
* Une marque de billetterie enregistre les installations et les désinstallations dans sa pile BI. Elle suit l'adoption par événement, canal et type d'appareil.
* Une marque déclenche un parcours de bienvenue après l'installation. Elle utilise `registrationSource` pour segmenter par campagne UTM.
* Une marque détecte des pics inhabituels de désinstallations après une mauvaise version. Elle revient rapidement en arrière et communique de manière proactive.

</details>

### Hooks d'exécution

La plateforme expose les hooks suivants sur le `runtime.wallet.carteUpdater` end-point :

* **`OnCarteInstalled`** → Déclenché lorsqu'une carte est ajoutée à Apple/Google Wallet
* **`OnCarteUninstalled`** → Déclenché lorsqu'une carte est retirée d'Apple/Google Wallet

Les deux méthodes reçoivent les mêmes paramètres :

| Paramètre               | Type                                     | Description                                                         |
| ----------------------- | ---------------------------------------- | ------------------------------------------------------------------- |
| `carteId`               | `chaîne`                                 | Identifiant unique de la carte                                      |
| `typeDeCarte`           | `chaîne`                                 | Type de carte (fidélité, carte-cadeau, billet d'événement… )        |
| `identifiants`          | `Record<string, any>`                    | Identifiants clé/valeur définis sur la carte (par ex. `customerId`) |
| `appareil`              | `"apple"` ou `"google"`                  | plateforme Wallet                                                   |
| `additionalInformation` | `AdditionalCarteInstallationInformation` | Inclut les statistiques d'inscription                               |

### Exemple d'implémentation

Des scripts peuvent être placés dans le `server/scripts` dossier sous la configuration avancée.

```js
const API_URL = 'https://partner';
import { getSecret } from 'neo/secrets';

/** 
 * @typedef {Object} RegistrationInformation 
 * @property {number} activeRegistrationCount - Nombre d'inscriptions actives. 
 * @property {number} totalRegistrationCount - Nombre total d'inscriptions. 
 **/ 

/**
 * @typedef {Object} RegistrationSource
 * @property {string[]} tags - liste des balises spécifiées par l'intégration SDK
 * @property {string} medium - moyen spécifié par l'intégration SDK ou utm_medium
 * @property {string} origin  - URL à partir de laquelle la carte est installée - peut être remplacée par l'intégration SDK
 * @property {string} userAgent - UserAgent facultatif utilisé pour installer la carte
 */

/** 
 * @typedef {Object} AdditionalCarteInstallationInformation
 * @property {RegistrationInformation} registrationInformation - Statistiques d'inscription. 
 * @property {RegistrationSource} registrationSource - Source de l'installation lorsqu'elle est disponible 
 */

/** méthodes déclenchées lorsqu'une carte est installée 
 * @param {string} carteId - identifiant unique de la carte
 * @param {string} typeDeCarte - type de la carte actuelle
 * @param {Record<string, any>} identifiers - paires clé-valeur des identifiants de la carte
 * @param {"apple"|"google"} device - nom de l'appareil
 * @param {AdditionalCarteInstallationInformation} additionalInformation - additionalInformation liée à cette installation de carte */
 async function onCarteInstalled(carteId, typeDeCarte, identifiers, device, additionalInformation) {
     await onCarteInstallationStatusChanged(carteId, typeDeCarte, identifiers, device, true);
} 

/** méthodes déclenchées lorsqu'une carte est désinstallée 
 * @param {string} carteId - identifiant unique de la carte 
 * @param {string} typeDeCarte - type de la carte actuelle
 * @param {Record<string, any>} identifiers - paires clé-valeur des identifiants de la carte
 * @param {"apple"|"google"} device - nom de l'appareil 
 * @param {AdditionalCarteInstallationInformation} additionalInformation - additionalInformation liée à cette installation de carte 
 */ 
async function onCarteUninstalled(carteId, typeDeCarte, identifiers, device, additionalInformation) { 
    await onCarteInstallationStatusChanged(carteId, typeDeCarte, identifiers, device, false); 
} 

async function onCarteInstallationStatusChanged(carteId, typeDeCarte, identifiers, device, isInstalled) {
  const customerId = identifiers["customerId"]; // ou tout autre identifiant externe
  const API_SECRET = await getSecret('PARTNER-API-SECRET');

  // ⚠️ Note : fetch n'est pas standard ici. Il utilise des options en PascalCase et un Body basé sur un objet.
  await fetch(API_URL + '/wallet/installation', {
    Method: "POST",
    Headers: {
      "Content-Type": "application/x-www-form-urlencoded",
      "X-API-KEY": API_SECRET
    },
    Body: {
      customerId,
      isInstalled,
      appareil
    },
    ThrowOnError: false
  });
}

export default function (context) {
  context.register('runtime.wallet.carteUpdater', {
    OnCarteInstalled: onCarteInstalled,
    OnCarteUninstalled: onCarteUninstalled
  });
}
```

### Exemple minimal

Pour les tests ou la journalisation uniquement :

```js
async function onCarteInstalled(carteId, typeDeCarte, identifiers, device) {
  console.log(`Carte ${carteId} installée sur ${device}`);
}

async function onCarteUninstalled(carteId, typeDeCarte, identifiers, device) {
  console.log(`Carte ${carteId} désinstallée de ${device}`);
}

export default function (context) {
  context.register('runtime.wallet.carteUpdater', {
    OnCarteInstalled: onCarteInstalled,
    OnCarteUninstalled: onCarteUninstalled
  });
}
```

### Quand les événements sont-ils déclenchés ?

* **`OnCarteInstalled`** → déclenché lorsqu'un utilisateur ajoute avec succès une carte à Apple ou Google Wallet.
* **`OnCarteUninstalled`** → déclenché lorsqu'un utilisateur retire la carte de son wallet.
* Les événements sont fiables : la plateforme garantit une livraison correcte même en cas de forte charge.

### Remarques

* `fetch` est **n'est pas le fetch standard du navigateur** — il accepte des options en PascalCase (`Method`, `Headers`, `Body`, `ThrowOnError`).
* L'authentification est flexible : vous pouvez utiliser des clés API (via `getSecret`) ou OAuth avec le `fetch`.
* Il n'existe aucune restriction de plateforme : l'exécution est sûre et entièrement gérée.

### FAQ

<details>

<summary>Ces événements sont-ils en temps réel ?</summary>

Ils se déclenchent lorsque la carte est ajoutée ou supprimée dans le wallet. En pratique, vous devez les considérer comme quasi temps réel. Concevez toujours votre API pour qu'elle soit idempotente, afin que les tentatives de réessai ne créent pas de doublons.

</details>

<details>

<summary>Que se passe-t-il si mon API est indisponible ?</summary>

Le code de votre connecteur contrôle l'appel. Vous devez gérer les timeouts et les erreurs avec élégance. Si le système externe est critique, implémentez des tentatives et une stratégie de file d'attente des messages en échec de votre côté.

</details>

<details>

<summary>Puis-je l'utiliser pour déclencher des e-mails ou des campagnes push ?</summary>

Oui. Le schéma le plus courant consiste à appeler votre plateforme d'automatisation marketing (directement ou via votre backend) et à déclencher un parcours lors de l'installation. Utilisez les événements de désinstallation pour arrêter ou adapter les communications.

</details>

<details>

<summary>Qu'est-ce qui est inclus dans <code>additionalInformation</code>?</summary>

Cela peut inclure des statistiques d'inscription et, lorsqu'elles sont disponibles, la source de l'installation. Utilisez-le pour mesurer l'adoption et attribuer les installations à une campagne ou à une intégration SDK.

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.thewalletcrew.io/connectors/fr/custom-connector/installation-changed-extensibility.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
