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).
- Créer l'app
expo init demo-rn --template blankcd demo-rnnpm install axios
- 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_*.)
- 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 };
}
- 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 },
});
- 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.