# ViewPay-React-Native : Guide de démarrage

Ce document a pour objectif de vous guider dans la mise en place du SDK ViewPay dans votre application React Native.
Pour rappel, Viewpay est une solution de micro-paiement par l'attention publicitaire, qui permet à l'utilisateur de débloquer un contenu premium en regardant une publicité. Viewpay a pour vocation d'être une alternative à d'autres options pour débloquer un contenu premium, et ne doit pas être installé comme seule option d'un paywall.

Voici un exemple de déblocage d'article avec Viewpay :

![sample](https://github.com/TechViewpay/ViewPay-iOS/blob/master/DocImages/parcours_vp_mobile3.png?raw=true)

## Prérequis

- Node.js
- Une application React Native (>= 0.71)

## Installation du SDK

Dans le répertoire du projet dans lequel vous voulez intégrer Viewpay, installez le module :
```cmd
npm install viewpay-react-native
```

Le SDK s'appuie sur des `peerDependencies` que votre application doit fournir. `react` et `react-native` sont déjà présents dans tout projet React Native ; il reste à installer :
```cmd
npm install react-native-webview @react-native-async-storage/async-storage
```
> `axios` est embarqué comme dépendance du SDK : il est installé automatiquement, vous n'avez pas à l'ajouter.

Pour iOS, mettez à jour les pods :
```cmd
cd ios
pod install
```

Pour Android, les dépendances Gradle sont récupérées au build. Si besoin de builder manuellement :
```cmd
cd android
./gradlew build
```

## Utilisation du SDK

Dans le fichier `.tsx` où vous voulez intégrer Viewpay, importez les composants :
```typescript
import Viewpay from 'viewpay-react-native';
import { ButtonVP, ViewpayHandle } from 'viewpay-react-native';
```

Vous pouvez ensuite utiliser le composant `Viewpay`. Les paramètres marqués d'un `*` sont obligatoires.

### Composant 1 : Viewpay
```tsx
<Viewpay
    siteId="1672e275c4ee7f34"
    readyVP={ready}
    checkVideoErrorVP={checkVideoError}
    checkVideoSuccesVP={checkVideoOk}
    closeAdsVP={closeAdsVP}
    completeAdsVP={completedVP}
    errorVP={onErrorVP}
    withLog={false}
    ref={ref}
/>
```

#### Paramètres
 - siteId * (string) : id de l'éditeur, fourni par Viewpay.
 - readyVP * (function) : callback appelé lorsque ViewPay est prêt.
 - errorVP * (function) : callback appelé lorsque Viewpay rencontre une erreur pendant le parcours (`code`, `message`).
 - checkVideoErrorVP (function) : callback appelé lorsque le checkVideo répond KO (aucune publicité disponible).
 - checkVideoSuccesVP (function) : callback appelé lorsque le checkVideo répond OK (au moins une publicité disponible).
 - closeAdsVP (function) : callback appelé lorsque le cadre ViewPay est fermé.
 - completeAdsVP (function) : callback appelé lorsque le parcours est terminé et que le contenu peut être débloqué.
 - withLog (boolean) : active l'affichage des logs de test, `false` par défaut.
 - ref : référence pour appeler les fonctions utilitaires de ViewPay (voir Composant 3).

#### Métadonnées article & consentement (optionnel)
Si votre application en dispose, passez ces props : elles sont transmises au serveur Viewpay pour le reporting d'article, le filtrage brand safety et le consentement RGPD (macros de diffusion programmatique).
```tsx
<Viewpay
    siteId="1672e275c4ee7f34"
    readyVP={ready}
    checkVideoErrorVP={checkVideoError}
    checkVideoSuccesVP={checkVideoOk}
    closeAdsVP={closeAdsVP}
    completeAdsVP={completedVP}
    errorVP={onErrorVP}
    articleId={article.id}
    articleTitle={article.title}
    articleUrl={article.url}
    consentString={cmp.tcString}
    gdprApplies={cmp.gdprApplies}
    ref={ref}
/>
```
 - articleId (string) : identifiant de l'article courant. Sert au reporting (clé de déduplication côté serveur) ; fournissez une valeur **stable et unique par article**.
 - articleTitle (string) : titre de l'article courant. Sert au reporting et au filtrage sémantique (brand safety).
 - articleUrl (string) : URL de l'article courant. Sert au filtrage sémantique (brand safety).
 - consentString (string) : chaîne de consentement IAB TCF v2 issue de votre CMP. Nécessaire à la monétisation programmatique.
 - gdprApplies (boolean) : indique si le RGPD s'applique à l'utilisateur (issu de votre CMP).

### Composant 2 : ButtonVP
```tsx
<ButtonVP onPress={runOpenCadre} />
```
#### Paramètres
 - onPress * (function) : fonction appelée lors du clic.

### Composant 3 : ViewpayHandle
`ViewpayHandle` est le type de la `ref` ; il expose les fonctions utilitaires du SDK.
```tsx
const ref = useRef<ViewpayHandle>(null);

const runCheckVideo = () => {
    ref.current?.checkVideo();
};

const runOpenCadre = () => {
    ref.current?.openCadre();
};

<Viewpay
    siteId="1672e275c4ee7f34"
    readyVP={ready}
    checkVideoErrorVP={checkVideoError}
    checkVideoSuccesVP={checkVideoOk}
    closeAdsVP={closeAdsVP}
    completeAdsVP={completedVP}
    errorVP={onErrorVP}
    withLog={false}
    ref={ref}
/>
```

Fonctions exposées :
 - checkVideo() : vérifie la disponibilité d'au moins une publicité.
 - openCadre() : présente la publicité (cadre plein écran).
 - getCappingRestant() : retourne l'état du capping mensuel.

## Vérifier la disponibilité de campagnes
Le callback `readyVP` est appelé lorsque le SDK ViewPay est prêt. La fonction `ref.current.checkVideo()` doit alors être appelée : elle vérifie la disponibilité d'au moins une vidéo publicitaire.
Si des publicités sont disponibles, le callback `checkVideoSuccesVP()` est appelé ; sinon c'est `checkVideoErrorVP()`.

## Présenter la publicité
À partir du résultat du checkVideo, vous savez si des publicités sont disponibles pour valider la transaction via ViewPay.
Pour présenter la publicité, appelez `ref.current.openCadre()`. Le callback `completeAdsVP()` est appelé une fois le parcours terminé (contenu débloquable).

## Récupération de l'état du capping
`ref.current.getCappingRestant()` retourne un tableau de deux valeurs : l'index `0` est le nombre de vues déjà effectuées sur le mois, l'index `1` est le nombre de vues maximum autorisé. Vous pouvez l'appeler par exemple dans `readyVP` (état initial) et dans `completeAdsVP` (après une vue) pour afficher la progression.

## Exemple
```tsx
import React, { useRef, useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import Viewpay from 'viewpay-react-native';
import { ButtonVP, ViewpayHandle } from 'viewpay-react-native';

const ExempleComposant = () => {
    const ref = useRef<ViewpayHandle>(null);

    const [isCompleted, setCompleted] = useState(false);
    const [isNoAds, setNoAds] = useState(false);
    const [existAds, setExistAds] = useState(false);
    const [capping, setCapping] = useState('');

    // Fonctions utilitaires du SDK
    const runCheckVideo = () => ref.current?.checkVideo();
    const runOpenCadre = () => ref.current?.openCadre();

    // Callbacks
    const ready = () => {
        console.log('SDK Viewpay prêt !');
        runCheckVideo();
        ref.current?.getCappingRestant().then((value: number[]) => {
            setCapping(value[0] + '/' + value[1]);
        });
    };

    const checkVideoError = () => {
        console.log('Aucune publicité disponible');
        setNoAds(true);
    };

    const checkVideoOk = () => {
        console.log('Publicités disponibles');
        setExistAds(true);
        runOpenCadre();
    };

    const closeAdsVP = () => {
        console.log('Fermeture de ViewPay');
    };

    const completedVP = () => {
        console.log('Transaction effectuée avec succès');
        ref.current?.getCappingRestant().then((value: number[]) => {
            setCapping(value[0] + '/' + value[1]);
            setCompleted(true);
        });
    };

    const onErrorVP = (code: number, message: string) => {
        console.log('Erreur ViewPay code ' + code + ' : ' + message);
    };

    return (
        <View style={styles.sectionContainer}>
            <Text style={styles.sectionTitle}>Capping : {capping}</Text>
            <Text style={styles.sectionTitle}>
                La Guerre en Ukraine : Conflit Persistant et Perspectives d'Espoir
            </Text>

            <Text style={styles.sectionDescription}>
                Depuis plusieurs années, la situation en Ukraine continue de captiver
                l'attention du monde entier alors que le pays lutte contre un conflit armé.
            </Text>

            <Viewpay
                siteId="1672e275c4ee7f34"
                readyVP={ready}
                checkVideoErrorVP={checkVideoError}
                checkVideoSuccesVP={checkVideoOk}
                closeAdsVP={closeAdsVP}
                completeAdsVP={completedVP}
                errorVP={onErrorVP}
                withLog={false}
                ref={ref}
            />

            {!isCompleted && existAds && <ButtonVP onPress={runOpenCadre} />}

            {isNoAds && (
                <Text style={styles.sectionDescription}>Aucune publicité disponible</Text>
            )}

            {isCompleted && (
                <Text style={styles.sectionDescription}>
                    Contenu premium débloqué : les Ukrainiens ont dû faire face à des défis
                    humanitaires sans précédent, tout en tentant de préserver leur souveraineté.
                </Text>
            )}
        </View>
    );
};

const styles = StyleSheet.create({
    sectionContainer: {
        marginTop: 32,
        paddingHorizontal: 24,
    },
    sectionTitle: {
        fontSize: 24,
        fontWeight: '600',
    },
    sectionDescription: {
        marginTop: 8,
        fontSize: 18,
        fontWeight: '400',
    },
});

export default ExempleComposant;
```
