# Sur votre site web

Utiliser The Wallet Crew **SDK cinto** pour placer un **Ajouter à Wallet** bouton sur n'importe quel site web. Le SDK détecte l'appareil et affiche automatiquement le bon appel à l'action.

Sur iOS, il affiche **Ajouter à Apple Wallet**. Sur Android, il affiche **Ajouter à Google Wallet**. Sur ordinateur, il peut rediriger vers une page de carte hébergée ou prendre en charge une solution de repli basée sur QR.

<details>

<summary><strong>Exemples concrets</strong></summary>

* Une page de compte de fidélité affiche un bouton pour la carte du client connecté.
* Une zone de cartes-cadeaux affiche un bouton par carte-cadeau active.
* Une page de billetterie affiche un bouton par billet, et non un bouton par commande.

</details>

<figure><img src="/files/939286487e1320de549d7e7e2986f656f7a77ebd" alt="Add to Wallet button embedded on a website with device-specific rendering."><figcaption><p>La même intégration adapte le bouton à iOS, Android et ordinateur.</p></figcaption></figure>

## Fonctionnement de l'intégration sur site web

L'intégration est simple. Une page charge le SDK cinto, puis affiche un bouton qui résout une carte.

Cette carte peut être résolue de deux façons :

* avec un connu `passId`
* avec `externalIdentifiers` et un HMAC facultatif

### Chaque carte doit être unique

Ce point est crucial. Une carte de Wallet n'est **pas** un actif partagé.

Chaque carte doit représenter un client, une carte, un billet ou une instance de droit d'accès. Le bouton affiché sur une page doit résoudre uniquement la carte qui appartient au contexte actuel.

Par exemple :

* une page de carte de fidélité doit résoudre la carte du client actuel
* une liste de billets doit résoudre une carte distincte par billet
* une liste de cartes-cadeaux doit résoudre une carte distincte par carte-cadeau

{% hint style="warning" %}
Ne réutilisez jamais la même valeur d'identifiant statique pour chaque client. Si le même `customerId`, l'identifiant de billet ou la valeur de recherche de carte est codé en dur pour tous les visiteurs, la même carte peut être renvoyée à tout le monde.
{% endhint %}

Lorsque `externalIdentifiers` sont utilisés, la valeur de l'identifiant doit être suffisamment unique pour résoudre **exactement une carte**. Si une recherche renvoie plusieurs cartes, la stratégie d'identifiant n'est pas assez spécifique pour une distribution sur site web.

### Ce qui change selon l'appareil

Le SDK affiche automatiquement le comportement correct :

* **iOS :** télécharge la carte Apple Wallet
* **Android :** ouvre le processus d'enregistrement Google Wallet
* **Ordinateur :** redirige vers une page de carte hébergée

Ce comportement par défaut peut être remplacé si nécessaire avec `platform`.

#### Exemple de rendu

**iOS**

<img src="/files/f44e6c06303205ebaf8435263f3c1a805c4d1432" alt="Bouton Ajouter à Apple Wallet affiché sur iPhone." width="250">

**Android**

<img src="/files/476257cfb2d84dd4a0dc54c86bdf5715b60464c5" alt="Bouton Ajouter à Google Wallet affiché sur Android." width="250">

**Ordinateur**

<img src="/files/7e2200ad72c34a16b7104b4a1282e5ce4f70d79e" alt="Rendu de repli sur ordinateur pour Ajouter à Wallet." width="250">

La solution de repli sur ordinateur ouvre une page de carte hébergée telle que :

![Page de carte hébergée utilisée comme solution de repli sur ordinateur pour la distribution sur site web.](/files/e1046ed5f7208e511111ed2e25c144a6538f8e55)

{% hint style="info" %}
Le comportement sur ordinateur peut être personnalisé pour afficher un code QR au lieu d'un bouton standard.
{% endhint %}

## Choisissez comment le bouton résout la carte

Le principal choix d'implémentation est la méthode de résolution de la carte.

Utilisez `passId` lorsque le backend connaît déjà la carte exacte. Utilisez `externalIdentifiers` lorsque le site web a accès à un identifiant métier stable et que la carte doit être résolue dynamiquement.

### Commencez avec `tenantId` et `environment`

Deux valeurs du SDK sont particulièrement importantes :

* `tenantId`
* `environment`

`tenantId` est requis. Il s'agit du nom du tenant dans le système The Wallet Crew. Dans les exemples de cette page, `molia` est le `tenantId`.

`environment` est l'URL de base publique utilisée par le SDK.

Utilisez ces valeurs comme suit :

* **Production :** `https://<customDomain>` le générique `https://app.neostore.cloud` peut aussi être utilisé lorsqu'aucun domaine personnalisé n'a été configuré
* **Test / QA :** `https://app-qa.neostore.cloud`

{% hint style="info" %}
Si `environment` est omis, le SDK utilise `https://app.neostore.cloud`. Ce paramètre par défaut est valide en production.
{% endhint %}

### Option 1 — Résoudre avec `passId`

C'est l'option la plus simple. Elle fonctionne mieux lorsque le backend connaît déjà la carte exacte à afficher.

{% tabs %}
{% tab title="JavaScript natif" %}

```html
<script type="text/javascript">
(function (n, e, o) {
var s=n.createElement("script");s.src="https://sdk.neostore.cloud/scripts/"+e+"/cinto@1";s.async=1;
s.onload=function(){neostore.cinto.initialize(e,o)};n.body.appendChild(s);
})(document, "molia", {});
</script>

<div data-neostore-addToWalletButton data-neostore-passId="KlnqcxVLA9pS4ol5"></div>
```

{% endtab %}

{% tab title="module npm" %}

```bash
npm install @neostore/cinto
```

```jsx
import { AddToWalletButton } from "@neostore/cinto";

const btn = new AddToWalletButton("molia", {
    language: "fr",
    passId: "KlnqcxVLA9pS4ol5",
});

btn.render(document.getElementById("btn"));
```

{% endtab %}
{% endtabs %}

### Option 2 — Résoudre avec `externalIdentifiers`

Cette option est utile lorsque la page connaît un identifiant métier stable, comme un identifiant de fidélité, un identifiant CRM ou un identifiant de billet, mais ne connaît pas le `passId` encore.

L'identifiant doit appartenir au client ou à l'objet actuel. Il ne doit pas s'agir d'une constante partagée.

Lorsque HMAC est utilisé, la signature doit être calculée côté serveur avec l'un des secrets de The Wallet Crew.

Par exemple, pour un `customerId` de `SC103010` et un secret de `I1M8emrrJSns4Hnuibbm45eWfLQMosPGKSp1JzKsCrXeWmhjE8lZhxC2tfSRX5IJ`, la valeur HMAC est :

`8c5a9ebdd9b4ac8d2307cc34192f0faed441ef724c043162f0618784173d4d93`

Outil de référence : [CyberChef](https://gchq.github.io/CyberChef/#recipe=HMAC\({'option':'UTF8','string':'I1M8emrrJSns4Hnuibbm45eWfLQMosPGKSp1JzKsCrXeWmhjE8lZhxC2tfSRX5IJ'},'SHA256'\)\&input=U0MxMDMwMTA)

{% hint style="warning" %}
Le secret HMAC doit rester côté serveur. Il ne doit jamais être exposé dans le code du navigateur.
{% endhint %}

#### Attributs de données

```html
<script type="text/javascript">
(function (n, e, o) {
var s=n.createElement("script");s.src="https://sdk.neostore.cloud/scripts/"+e+"/cinto@1";s.async=1;
s.onload=function(){neostore.cinto.initialize(e,o)};n.body.appendChild(s);
})(document, "molia", { language: "fr" });
</script>

<div data-neostore-addToWalletButton
     data-neostore-passType="user"
     data-neostore-externalIdentifiers-y2.customer_Id-value="SC103010"
     data-neostore-externalIdentifiers-y2.customer_Id-hmac="cbbcfc5xxxxx"
</div>
```

#### Utilisation du composant

```jsx
import { AddToWalletButton } from "@neostore/cinto";

const btn = new AddToWalletButton("molia", {
    language: "fr",
    passType: "user",
    externalIdentifiers: {
        "y2.customerId": {
            value: "SC103010",
            hmac: "cbbcfc5xxxxx",
        },
    },
});

btn.render(document.getElementById("btn"));
```

#### Casse des clés d'identifiant en HTML

Les navigateurs mettent les noms d'attribut HTML en minuscules. Pour conserver une majuscule dans une clé d'identifiant, faites précéder le caractère de `_` dans le nom de l'attribut.

Exemple :

* `y2.customer_Id` devient `y2.customerId`

Cette règle ne concerne que le nom de l'attribut HTML. Elle ne modifie pas la valeur signée.

## Comportements et options courants

### Détection de la plateforme

Lorsque `data-neostore-addToWalletButton` est utilisé, le composant sélectionne automatiquement la bonne plateforme :

* `ordinateur`
* `apple`
* `google`

Pour imposer une plateforme, définissez `data-neostore-platform="desktop"` ou utilisez l' `platform` option dans le composant.

### Détection de la langue

Le SDK utilise la langue du navigateur par défaut. Si la langue n'est pas disponible, il revient à l'anglais.

Pour imposer une langue :

* attributs de données : `data-neostore-language="fr"`
* option du composant : `language: "fr"`

Exemple JavaScript natif

```html
<script type="text/javascript">
(function (n, e, o) {
var s=n.createElement("script");s.src="https://sdk.neostore.cloud/scripts/"+e+"/cinto@1";s.async=1;
s.onload=function(){neostore.cinto.initialize(e,o)};n.body.appendChild(s);
})(document, "molia", { language: "fr" });
</script>

<div data-neostore-addToWalletButton data-neostore-passId="KlnqcxVLA9pS4ol5"></div>
```

### Options complètes

Voici la liste complète des options disponibles.

```typescript
export interface Options {
    /**
     * URL de base publique de l'environnement.
     * Utilisez "https://app-qa.neostore.cloud" pour les tests.
     * Utilisez "https://app.neostore.cloud" pour la production.
     * Un domaine personnalisé du tenant peut également être utilisé.
     * @default: "https://app.neostore.cloud"
     */
    environment: string;
    /**
     * Nom du tenant dans le système The Wallet Crew.
     * Cette valeur est requise.
     * Exemple : "molia"
     */
    tenantId: string;
    /**
     * Nom de la disposition de carte pour rediriger l'utilisateur lorsqu'il est sur ordinateur
     * @default: undefined // la disposition de carte par défaut du modèle de carte sera utilisée
     */
    passLayoutName: string;
    /**
     * Code langue ISO 639 à utiliser pour afficher le bouton. Lorsqu'il est omis, la langue sera détectée automatiquement selon les paramètres du navigateur.
     * Si la valeur ne correspond à aucune option disponible, les paramètres du navigateur seront utilisés, sinon l'anglais sera utilisé.
     * @default: undefined
     */
    language?: string;
    /**
     * Identifiant de la carte à afficher ou promesse de celle-ci
     */
    passId: string;
    /**
     * Plateforme à utiliser pour afficher le bouton. Lorsqu'elle est omise, la plateforme sera détectée automatiquement selon l'agent utilisateur.
     * Les valeurs possibles sont : "apple", "google" ou "desktop"
     *
     * @default: undefined
     **/
    platform?: Platform;
    /**
     * Identifiants externes à utiliser pour obtenir le passId
     */
    externalIdentifiers?: Record<string, { value: string; hmac?: string }>;
    /**
     * Type de carte à utiliser pour obtenir le passId
     * Requis lorsque externalIdentifiers est défini
     */
    passType?: string;
    
    /**
     * Source utilisée à des fins d'analyse
     */
    source?: {
        /**
         * liste de balises à associer à ce téléchargement. utm_source et utm_campaign seront automatiquement agrégés à cette liste
         */
        tags?: Array<string>;
        /**
         * média à associer à ce téléchargement. utm_medium sera utilisé si aucune valeur n'est spécifiée
         */
        medium?: string;
        /**
         * origine à associer à ce téléchargement. l'URL actuelle (sans la requête) sera utilisée si aucune valeur n'est spécifiée
         */
        origin?: string;
    };

    /**
     * Fonction de rappel appelée lorsque le bouton est cliqué
     */
    onClick?: (e: MouseEvent, data: { options: Partial<Options>; platform: Platform }) => void;

    /**
     * Fonction de rappel lorsqu'une erreur se produit
     *
     */
    onError?: (error: string) => void;
}

```

### Style

La structure rendue est :

* un conteneur fourni par le site web
  * un lien avec sélecteur `.neostore-link`
    * une image avec des sélecteurs `.neostore-img` et `.neostore-link-{{ platform }}`

Les ressources des boutons Apple et Google suivent les consignes de chaque fournisseur :

* [Consignes Apple](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/)
* [Consignes Google](https://developers.google.com/wallet/generic/resources/brand-guidelines)

## Personnalisation pour ordinateur

Sur ordinateur, le résultat le plus important est l’URL de la Carte hébergée. Cette URL peut être utilisée pour afficher un code QR à la place du bouton de redirection par défaut.

```html
<script src="https://cdn.rawgit.com/davidshimjs/qrcodejs/gh-pages/qrcode.min.js"></script>

<div id="qrcode"></div>
<script type="module">
    import { AddToWalletButton } from "https://sdk.neostore.cloud/scripts/molia/cinto@1/cinto.mjs";

    const button = new AddToWalletButton("molia", {
        passId: "KlnqcxVLA9pS4ol5"
    });

    const url = await button.getPassPageUrl();
    new QRCode(document.getElementById("qrcode"), url);
</script>
```

## Ajouter des informations d’analyse

Le bouton peut envoyer trois valeurs source qui seront visibles dans le `Carte:Installé` événement, le tableau de bord et l’API Insights.

* `étiquettes`: liste des étiquettes source. `utm_source` et `utm_campaign` sont ajoutés automatiquement.
* `média`: étiquette de canal telle que `ecomm` ou `compte`.
* `origine`: URL de la page source. Par défaut, l’URL de la page actuelle est utilisée sans paramètres de requête.

Toutes les valeurs sont facultatives.

```html
<div data-neostore-addToWalletButton
     data-neostore-src-tags="tag1,tag2"
     data-neostore-src-medium="ecomm"
     data-neostore-src-origin="originA"
</div>
```

## Récupérer `passId` lorsque la Carte existe déjà

Lorsque la Carte existe déjà, le backend du site web peut d’abord la rechercher, puis afficher le bouton avec le `passId`.

{% stepper %}
{% step %}

### Créer une clé d’API

Créez une clé d’API dans la console d’administration avec `tenant.Carte:read`.

Voir : [Clé d’API](/docs/fr/configurer/platform/api-key.md)
{% endstep %}

{% step %}

### Interrogez le point de terminaison des cartes

Utilisez la clé d’identifiant configurée pour rechercher la Carte.

Exemple :

```bash
curl --globoff -X GET \\
  'https://app.neostore.cloud/api/<tenantId>/passes?pageIndex=0&pageSize=10&filter[0].field=identifiers.y2.customerId&filter[0].operator=equals&filter[0].value=04101234' \
  -H 'accept: application/json' \
  -H 'X-API-KEY: <apiKey>'
```

Résultat attendu :

```json
[
  {
    "id": "KlnqcxVLAxxxxxx",
    "passType": "user",
    "identifiers": {
      "y2.customerId": "04101234"
    }
  }
]
```

{% endstep %}

{% step %}

### Valider l'unicité

La recherche ne doit renvoyer qu'une seule Carte.

Si zéro Carte est renvoyée, la Carte n'existe pas encore. Si plusieurs Cartes sont renvoyées, l'identifiant n'est pas assez unique pour la distribution sur le site web.
{% endstep %}

{% step %}

### Afficher le bouton avec `passId`

Une fois le `id` connu, utilisez-le comme le `passId` dans le bouton du site web.
{% endstep %}
{% endstepper %}

## Exemple d'intégration tierce

<details>

<summary><strong>Exemple de wrapper React</strong></summary>

```tsx
import { AddToWalletButton } from "@neostore/cinto";

const CintoMobileAddToWallet = React.forwardRef<
    HTMLButtonElement,
    BoxProps & {
        passId?: string;
    }
>(({ passId, ...props }, buttonRef) => {
    const localRef = useRef<HTMLButtonElement>(null);
    buttonRef = buttonRef || localRef;

    const ctaRef = useRef<HTMLDivElement>(null);
    const cintoButtonRef = useRef<AddToWalletButton>();

    useEffect(() => {
        cintoButtonRef.current = passId
            ? new AddToWalletButton(tenantId, {
                  passId,
              })
            : undefined;
        ctaRef.current && cintoButtonRef.current?.render(ctaRef.current);
        if (passId && cintoButtonRef.current) {
            cintoButtonRef.current?.perform();
        }
    }, [passId, tenantId]);

    return (
        <Box {...props}>
            <div ref={ctaRef} />
        </Box>
    );
});

export default CintoMobileAddToWallet;
```

</details>

## FAQ

<details>

<summary><strong>Le même bouton doit-il être réutilisé pour tous les clients ?</strong></summary>

Non. Le composant visuel peut être réutilisé, mais la Carte résolue doit changer en fonction du contexte actuel du client, du billet ou de la carte cadeau.

</details>

<details>

<summary><strong>Faut-il utiliser `passId` ou `externalIdentifiers` ?</strong></summary>

Utilisez `passId` lorsque le backend connaît déjà la carte exacte. Utilisez `externalIdentifiers` lorsque la page possède un identifiant stable et que la Carte doit être résolue dynamiquement.

</details>

<details>

<summary><strong>Peut-on afficher plusieurs boutons sur la même page ?</strong></summary>

Oui. C'est courant pour les listes de billets et de cartes cadeaux. Chargez le SDK une seule fois, puis affichez un bouton par Carte.

</details>

<details>

<summary><strong>La version bureau peut-elle afficher un code QR à la place d'une redirection standard ?</strong></summary>

Oui. L'URL de la Carte hébergée peut être utilisée pour afficher un code QR ou un autre CTA spécifique au bureau.

</details>

<details>

<summary><strong>Quand faut-il utiliser plutôt une intégration d’application native ?</strong></summary>

Utilisez une intégration native lorsque le flux Wallet démarre dans une application iOS ou Android. Pour ce modèle, voir [Dans votre application mobile](/docs/fr/inscrire/on-your-mobile-app.md).

</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/inscrire/on-your-website.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.
