# 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 l’état 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 distribution met à jour un champ CRM comme `hasWalletPass=true` juste après l’installation. Elle cesse ensuite d’envoyer des rappels « ajouter au Wallet ».
* Une marque de billetterie consigne les installations et les désinstallations dans sa stack 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ésinstallation 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.passUpdater` endpoint :

* **`OnPassInstalled`** → Déclenché lorsqu’une carte est ajoutée à Apple/Google Wallet
* **`OnPassUninstalled`** → Déclenché lorsqu’une carte est supprimée d’Apple/Google Wallet

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

| Paramètre               | Type                                    | Description                                                         |
| ----------------------- | --------------------------------------- | ------------------------------------------------------------------- |
| `passId`                | `string`                                | Identifiant unique de la carte                                      |
| `passType`              | `string`                                | Type de carte (fidélité, carte-cadeau, billet d’événement… )        |
| `identifiers`           | `Record<string, any>`                   | Identifiants clé/valeur définis sur la carte (par ex. `customerId`) |
| `device`                | `"apple"` ou `"google"`                 | Plateforme Wallet                                                   |
| `additionalInformation` | `AdditionalPassInstallationInformation` | Inclut les statistiques d’inscription                               |

### Exemple d’implémentation

Les 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 tags spécifiés par l’intégration SDK
 * @property {string} medium - support 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 - User-Agent facultatif utilisé pour installer la carte
 */

/** 
 * @typedef {Object} AdditionalPassInstallationInformation
 * @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} passId - identifiant unique de la carte
 * @param {string} passType - type de carte de la carte actuelle
 * @param {Record<string, any>} identifiers - paires clé-valeur d’identifiants de la carte
 * @param {"apple"|"google"} device - nom de l’appareil
 * @param {AdditionalPassInstallationInformation} additionalInformation - informations supplémentaires liées à cette installation de carte */
 async function onPassInstalled(passId, passType, identifiers, device, additionalInformation) {
     await onPassInstallationStatusChanged(passId, passType, identifiers, device, true);
} 

/** méthodes déclenchées lorsqu’une carte est désinstallée 
 * @param {string} passId - identifiant unique de la carte 
 * @param {string} passType - type de carte de la carte actuelle
 * @param {Record<string, any>} identifiers - paires clé-valeur d’identifiants de la carte
 * @param {"apple"|"google"} device - nom de l’appareil 
 * @param {AdditionalPassInstallationInformation} additionalInformation - informations supplémentaires liées à cette installation de carte 
 */ 
async function onPassUninstalled(passId, passType, identifiers, device, additionalInformation) { 
    await onPassInstallationStatusChanged(passId, passType, identifiers, device, false); 
} 

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

  // ⚠️ Remarque : 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,
      device
    },
    ThrowOnError: false
  });
}

export default function (context) {
  context.register('runtime.wallet.passUpdater', {
    OnPassInstalled: onPassInstalled,
    OnPassUninstalled: onPassUninstalled
  });
}
```

### Exemple minimal

Pour les tests ou la journalisation uniquement :

```js
async function onPassInstalled(passId, passType, identifiers, device) {
  console.log(`Carte ${passId} installée sur ${device}`);
}

async function onPassUninstalled(passId, passType, identifiers, device) {
  console.log(`Carte ${passId} désinstallée de ${device}`);
}

export default function (context) {
  context.register('runtime.wallet.passUpdater', {
    OnPassInstalled: onPassInstalled,
    OnPassUninstalled: onPassUninstalled
  });
}
```

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

* **`OnPassInstalled`** → déclenché lorsqu’un utilisateur ajoute avec succès une carte à Apple ou Google Wallet.
* **`OnPassUninstalled`** → déclenché lorsqu’un utilisateur supprime 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 **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 personnalisable `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 reprise 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 de reprise et une stratégie de file d’attente de rebond de votre côté.

</details>

<details>

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

Oui. Le modèle le plus courant consiste à appeler votre plateforme d’automatisation marketing (directement ou via votre backend) et à déclencher un parcours à 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 les statistiques d’inscription et, lorsqu’elles sont disponibles, la source d’installation. Utilisez-les 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/docs/fr/connecter/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.
