# 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 retail 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 enregistre les installations et désinstallations dans sa stack BI. Elle surveille 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>

### Runtime Hooks

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 retiré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>`                   | Paires clé/valeur d'identifiants définies sur la Carte (par ex. `customerId`) |
| `device`                | `"apple"` ou `"google"`                 | Plateforme Wallet                                                             |
| `additionalInformation` | `AdditionalPassInstallationInformation` | Inclut des statistiques d'enregistrement                                      |

### 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 - Enregistrements actifs. 
 * @property {number} totalRegistrationCount - Enregistrements totaux. 
 **/ 

/**
 * @typedef {Object} RegistrationSource
 * @property {string[]} tags - liste des tags spécifiés par l'intégration SDK
 * @property {string} medium - medium spécifié par l'intégration SDK ou utm_medium
 * @property {string} origin  - URL d'où la Carte est installée - pourrait être remplacée par l'intégration SDK
 * @property {string} userAgent - UserAgent optionnel utilisé pour installer la Carte
 */

/** 
 * @typedef {Object} AdditionalPassInstallationInformation
 * @property {RegistrationInformation} registrationInformation - Statistiques d'enregistrement. 
 * @property {RegistrationSource} registrationSource - Source de l'installation lorsque 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 courante
 * @param {Record<string, any>} identifiers - paires clé/valeur des identifiants de la Carte
 * @param {"apple"|"google"} device - nom de l'appareil
 * @param {AdditionalPassInstallationInformation} additionalInformation - additionalInformation lié à 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 courante
 * @param {Record<string, any>} identifiers - paires clé/valeur des identifiants de la Carte
 * @param {"apple"|"google"} device - nom de l'appareil 
 * @param {AdditionalPassInstallationInformation} additionalInformation - additionalInformation lié à 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 uniquement la journalisation :

```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 depuis ${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 retire la Carte de son wallet.
* Les événements sont fiables : la plateforme garantit une livraison correcte même en cas de forte charge.

### Notes

* `fetch` est **pas le fetch standard du navigateur** — il accepte des options en PascalCase (`Méthode`, `En-têtes`, `Corps`, `ThrowOnError`).
* L'authentification est flexible : vous pouvez utiliser des clés API (via `getSecret`) ou OAuth avec le `fetch`.
* Il n'y a pas de restrictions 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 réessais ne créent pas de doublons.

</details>

<details>

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

Votre code de connecteur contrôle l'appel. Vous devez gérer les délais d'attente et les erreurs de manière élégante. Si le système externe est critique, implémentez des réessais et une stratégie de dead-letter 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 est d'appeler votre plateforme d'automatisation marketing (directement ou via votre backend) et de 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>

Il peut inclure des statistiques d'enregistrement et, lorsque disponible, la source de l'installation. Utilisez-le pour mesurer l'adoption et attribuer les installations à une campagne ou une intégration SDK.

</details>
