1. Reprendre les ventes en attente
toutes les 5 minutes
pour chaque vente EN_COURS depuis plus de 15 minutes
vente ← GET /v1/ventes/{uuid}
si NON_TROUVEE → renvoyer la même vente, même uuid
sinon → traiter(vente.statut)
const BASE_URL = process.env.UMEME_BASE_URL;
const entetes = { Authorization: `Bearer ${process.env.UMEME_CLE}` };
// commandes : votre stockage ; traiter : la fonction qui applique un statut.
export async function reprendre(commandes, traiter) {
const enAttente = await commandes.enCoursDepuis(15 * 60 * 1000);
for (const commande of enAttente) {
const reponse = await fetch(`${BASE_URL}/ventes/${commande.uuid}`, { headers: entetes });
if (reponse.status === 404) {
// NON_TROUVEE : la vente n'est jamais arrivée, elle repart avec le même uuid.
await commandes.renvoyer(commande);
continue;
}
traiter(await reponse.json());
}
}
// Toutes les 5 minutes.
export function planifier(commandes, traiter) {
return setInterval(() => reprendre(commandes, traiter), 5 * 60 * 1000);
}
import axios from "axios";
const umeme = axios.create({
baseURL: process.env.UMEME_BASE_URL,
headers: { Authorization: `Bearer ${process.env.UMEME_CLE}` },
timeout: 30000,
validateStatus: (statut) => statut < 500,
});
// commandes : votre stockage ; traiter : la fonction qui applique un statut.
export async function reprendre(commandes, traiter) {
const enAttente = await commandes.enCoursDepuis(15 * 60 * 1000);
for (const commande of enAttente) {
const { status, data } = await umeme.get(`/ventes/${commande.uuid}`);
if (status === 404) {
// NON_TROUVEE : la vente n'est jamais arrivée, elle repart avec le même uuid.
await commandes.renvoyer(commande);
continue;
}
traiter(data);
}
}
// Toutes les 5 minutes.
export function planifier(commandes, traiter) {
return setInterval(() => reprendre(commandes, traiter), 5 * 60 * 1000);
}
import os
import time
import requests
BASE_URL = os.environ["UMEME_BASE_URL"]
ENTETES = {"Authorization": f"Bearer {os.environ['UMEME_CLE']}"}
# commandes : votre stockage ; traiter : la fonction qui applique un statut.
def reprendre(commandes, traiter):
for commande in commandes.en_cours_depuis(minutes=15):
reponse = requests.get(f"{BASE_URL}/ventes/{commande['uuid']}", headers=ENTETES, timeout=30)
if reponse.status_code == 404:
# NON_TROUVEE : la vente n'est jamais arrivée, elle repart avec le même uuid.
commandes.renvoyer(commande)
continue
traiter(reponse.json())
# Toutes les 5 minutes.
def planifier(commandes, traiter):
while True:
reprendre(commandes, traiter)
time.sleep(5 * 60)
<?php
use GuzzleHttp\Client;
// $commandes : votre stockage ; $traiter : la fonction qui applique un statut.
// À lancer toutes les 5 minutes, par exemple depuis le planificateur de Laravel ou cron.
function reprendre(Commandes $commandes, callable $traiter): void
{
$umeme = new Client([
'base_uri' => getenv('UMEME_BASE_URL') . '/',
'headers' => ['Authorization' => 'Bearer ' . getenv('UMEME_CLE')],
'timeout' => 30,
'http_errors' => false,
]);
foreach ($commandes->enCoursDepuis(15) as $commande) {
$reponse = $umeme->get('ventes/' . $commande['uuid']);
if ($reponse->getStatusCode() === 404) {
// NON_TROUVEE : la vente n'est jamais arrivée, elle repart avec le même uuid.
$commandes->renvoyer($commande);
continue;
}
$traiter(json_decode($reponse->getBody(), true));
}
}
static final HttpClient CLIENT = HttpClient.newHttpClient();
// commandes : votre stockage ; traiter : la fonction qui applique un statut.
static void reprendre(Commandes commandes, Consumer<String> traiter) throws Exception {
for (var commande : commandes.enCoursDepuis(Duration.ofMinutes(15))) {
var requete = HttpRequest.newBuilder(URI.create(System.getenv("UMEME_BASE_URL") + "/ventes/" + commande.uuid()))
.header("Authorization", "Bearer " + System.getenv("UMEME_CLE"))
.timeout(Duration.ofSeconds(30))
.GET()
.build();
var reponse = CLIENT.send(requete, HttpResponse.BodyHandlers.ofString());
if (reponse.statusCode() == 404) {
// NON_TROUVEE : la vente n'est jamais arrivée, elle repart avec le même uuid.
commandes.renvoyer(commande);
continue;
}
traiter.accept(reponse.body());
}
}
// Toutes les 5 minutes.
static void planifier(Commandes commandes, Consumer<String> traiter) {
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
try {
reprendre(commandes, traiter);
} catch (Exception e) {
// Le prochain passage reprendra les mêmes ventes.
}
}, 0, 5, TimeUnit.MINUTES);
}
UUID="94a223fe-fb34-47f2-aaa5-b80c4bf8a8eb"
curl "$UMEME_BASE_URL/ventes/$UUID" \
-H "Authorization: Bearer $UMEME_CLE"
// Node.js 18 et plus : fetch est intégré.
const baseUrl = process.env.UMEME_BASE_URL;
const uuid = "94a223fe-fb34-47f2-aaa5-b80c4bf8a8eb";
const reponse = await fetch(`${baseUrl}/ventes/${uuid}`, {
headers: {
Authorization: `Bearer ${process.env.UMEME_CLE}`,
},
});
const donnees = await reponse.json();
// npm install axios
import axios from "axios";
const umeme = axios.create({
baseURL: process.env.UMEME_BASE_URL,
headers: { Authorization: `Bearer ${process.env.UMEME_CLE}` },
timeout: 30000,
});
const uuid = "94a223fe-fb34-47f2-aaa5-b80c4bf8a8eb";
const { data } = await umeme.get(`/ventes/${uuid}`);
import os
import requests
BASE_URL = os.environ["UMEME_BASE_URL"]
ENTETES = {"Authorization": f"Bearer {os.environ['UMEME_CLE']}"}
uuid = "94a223fe-fb34-47f2-aaa5-b80c4bf8a8eb"
reponse = requests.get(
f"{BASE_URL}/ventes/{uuid}",
headers=ENTETES,
timeout=30,
)
donnees = reponse.json()
// composer require guzzlehttp/guzzle
$client = new GuzzleHttp\Client([
'base_uri' => getenv('UMEME_BASE_URL') . '/',
'headers' => ['Authorization' => 'Bearer ' . getenv('UMEME_CLE')],
'timeout' => 30,
]);
$uuid = '94a223fe-fb34-47f2-aaa5-b80c4bf8a8eb';
$reponse = $client->get("ventes/{$uuid}");
$donnees = json_decode($reponse->getBody(), true);
// Java 15 et plus : java.net.http et blocs de texte.
var baseUrl = System.getenv("UMEME_BASE_URL");
var client = HttpClient.newHttpClient();
var uuid = "94a223fe-fb34-47f2-aaa5-b80c4bf8a8eb";
var requete = HttpRequest.newBuilder(URI.create(baseUrl + "/ventes/" + uuid))
.header("Authorization", "Bearer " + System.getenv("UMEME_CLE"))
.GET()
.build();
var reponse = client.send(requete, HttpResponse.BodyHandlers.ofString());
2. Lire la réponse
| Réponse | Ce que vous faites |
|---|---|
REUSSIE, ECHOUEE | Appliquer le statut, comme pour un rappel |
EN_COURS | Attendre le prochain passage |
EN_RECONCILIATION | Attendre : Umeme vérifie. Ne pas relancer |
404 NON_TROUVEE | La vente n’existe pas : renvoyez-la, avec le même uuid |
3. Rapprocher le portefeuille
Une fois par jour, comparez vos ventes au relevéGET /v1/portefeuille/mouvements : chaque vente acceptée y a un débit, chaque échec un remboursement, et chaque ligne donne le solde après le mouvement. Voir Recharger et suivre son portefeuille.
Consultez une même vente au plus toutes les 30 secondes : au-delà, vous risquez
429 TROP_DE_REQUETES.
