Guide

Guide React Native (Expo) pour déclencher le flux YKNPG (démo de développement).

Guide React Native (Expo) pour déclencher le flux YKNPG (démo de développement).

Note sécurité

  • Les variables env publiques Expo sont embarquées dans l'app ; utilisez un proxy backend en production pour garder le jeton bearer secret. Ce qui suit sert aux tests locaux.

Pré-requis

  • Node.js 18+, Expo CLI (npm install -g expo-cli).
  1. Créer l'app
  • expo init demo-rn --template blank
  • cd demo-rn
  • npm install axios
  1. Ajouter l'environnement
  • Fichier : .env
EXPO_PUBLIC_YKNPG_API_TOKEN=remplacez-par-votre-jeton
EXPO_PUBLIC_YKNPG_BASE_URL=https://yknpg.ngoul.com/api/v1

(Expo charge automatiquement EXPO_PUBLIC_*.)

  1. Créer un helper API
  • Fichier : api.js
import axios from "axios";
import Constants from "expo-constants";

const baseURL =
  Constants.expoConfig?.extra?.expoPublicYknpgBaseUrl ||
  process.env.EXPO_PUBLIC_YKNPG_BASE_URL ||
  "https://yknpg.ngoul.com/api/v1";

const client = axios.create({
  baseURL,
  headers: { Authorization: `Bearer ${process.env.EXPO_PUBLIC_YKNPG_API_TOKEN}` },
  timeout: 10000,
});

export async function runTransaction(amount, phone) {
  const payload = {
    amount,
    provider: "ORANGE_MONEY",
    user_infos: { number: phone },
    callback_url: "http://example.com",
    callback_method: "POST",
    your_message: "pay this",
    your_order_ref: "demo-1",
    provider_fees_on_customer: true,
  };
  const { data: created } = await client.post("/transactions/", payload);
  const { data: paid } = await client.post(`/transactions/${created.uuid}/pay/`);
  let status = paid.status;
  while (status === "new" || status === "paying") {
    await new Promise((r) => setTimeout(r, 5000));
    const { data } = await client.get(`/transactions/${created.uuid}/`);
    status = data.status;
  }
  return { created, paid, finalStatus: status };
}
  1. Mettre à jour l'app
  • Fichier : App.js
import { useState } from "react";
import { Button, SafeAreaView, Text, TextInput, View, StyleSheet } from "react-native";
import { runTransaction } from "./api";

export default function App() {
  const [phone, setPhone] = useState("");
  const [amount, setAmount] = useState("1000");
  const [loading, setLoading] = useState(false);
  const [output, setOutput] = useState("");

  const submit = async () => {
    setLoading(true);
    setOutput("");
    try {
      const res = await runTransaction(Number(amount), phone);
      setOutput(
        `Gateway: ${res.created.instructions}\nPost-pay: ${res.paid.instructions}\nFinal status: ${res.finalStatus}`
      );
    } catch (e) {
      setOutput(e.response?.data || e.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    <SafeAreaView style={styles.container}>
      <Text style={styles.title}>Start payment</Text>
      <TextInput style={styles.input} placeholder="Phone" value={phone} onChangeText={setPhone} />
      <TextInput
        style={styles.input}
        placeholder="Amount"
        value={amount}
        onChangeText={setAmount}
        keyboardType="numeric"
      />
      <Button title={loading ? "Processing..." : "Pay"} onPress={submit} disabled={loading} />
      <View style={{ marginTop: 16 }}>
        <Text>{output}</Text>
      </View>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, padding: 24, gap: 12 },
  title: { fontSize: 24, fontWeight: "600" },
  input: { borderWidth: 1, borderColor: "#ccc", padding: 10, borderRadius: 6 },
});
  1. Exécuter
  • npm start
  • Lancer sur un simulateur ou un appareil ; tester le formulaire.

Remarques

  • Remplacez les appels directs à l'API par un appel à votre backend sécurisé avant la mise en production.