Le paiement direct
Votre formulaire, votre écran : votre serveur envoie le numéro du payeur, Payiz lance la demande, le payeur valide sur son téléphone. Personne ne quitte votre application.
Quand le choisir
Les trois créent le même paiement : mêmes frais, mêmes webhooks, même reçu. Vous pouvez les mêler — le lien pour vos ventes sur les réseaux, le direct dans votre application.
Le parcours
- 1Votre écran recueille le numéro et l’opérateur
- 2Votre serveur appelle Payiz avec sa clé secrète
- 3Le payeur valide sur son téléphone, avec son code
- 4Le webhook vous dit que c’est payé, ou pourquoi non
Lancer la demande
Un seul appel : le paiement, et le numéro qui le paie. La clé porte le geste Paiements · lancer, et l’appel un en-tête Idempotency-Key, obligatoire : tirez-le de votre commande, deux clics donnent alors un seul paiement.
curl https://api.payiz.app/v1/payments \
-H "Authorization: Bearer sk_test_…" \
-H "Idempotency-Key: cmd-42" \
-H "Content-Type: application/json" \
-d '{
"amount": 10000,
"currency": "XOF",
"reference": "cmd-42",
"payer": {
"phone": "+2290197000000",
"operator": "mtn"
}
}'La réponse arrive tout de suite ; en voici l’essentiel. Le paiement est processing : la demande est partie, le payeur ne l’a pas encore validée.
{
"object": "payment",
"id": "pay_01j9x3kq7m4tzv8qhw2n",
"amount": 10000,
"currency": "XOF",
"status": "processing",
"reference": "cmd-42",
"latest_attempt": {
"object": "payment_attempt",
"id": "tnt_01j9x4a2b7c5d8e3f6g1h0jk",
"status": "pending",
"source": "api",
"phone": "+229 01 •• •• 34 56",
"operator": "mtn",
"failure_code": null,
"payer_message": "Validez le paiement de 10 000 F CFA sur votre téléphone. Si rien n’arrive, vérifiez votre solde et votre réseau, puis réessayez."
},
"payment_url": "https://pay.payiz.app/pay_01j9x3kq7m4tzv8qhw2n",
"livemode": false
}operator, Payiz le déduit du numéro. Quand plusieurs opérateurs sont possibles, l’appel échoue avec operator_required et la liste des candidats dans details.operators : proposez-les au payeur. GET /v1/payment_methods vous donne les opérateurs, leurs logos et leurs bornes.Afficher la consigne
Pendant l’attente, dites au payeur quoi faire, et laissez-lui changer de numéro.
payer_message est écrit pour le payeur : la consigne pendant l’attente, puis l’issue. Vous pouvez aussi écrire le vôtre à partir de failure_code.Attendre l’issue
Le webhook fait foi. payment.succeeded dit que l’argent est arrivé ; payment.attempt_failed dit pourquoi la demande n’a pas abouti. Ne concluez jamais sur la réponse immédiate.
{
"id": "evt_01j9x3p5hd2m8nq6tb0c",
"type": "payment.attempt_failed",
"livemode": false,
"data": {
"object": {
"object": "payment",
"id": "pay_01j9x3kq7m4tzv8qhw2n",
"status": "requires_payment",
"latest_attempt": {
"status": "failed",
"failure_code": "insufficient_funds",
"payer_message": "Le solde ne suffit pas. Rechargez, ou payez avec un autre numéro."
}
}
}
}Sans webhook, relisez le paiement avec GET /v1/payments/{id} : latest_attempt y porte la même raison.
Relancer
Après un échec, le paiement reste payable jusqu’à expires_at. Relancez sur le même paiement, avec le même numéro ou un autre : jamais deux demandes à la fois — une demande qui attend encore répond attempt_in_progress.
curl https://api.payiz.app/v1/payments/pay_01j9x3kq7m4tzv8qhw2n/attempts \
-H "Authorization: Bearer sk_test_…" \
-H "Idempotency-Key: cmd-42-relance-1" \
-H "Content-Type: application/json" \
-d '{"phone":"+2290196000000","operator":"moov"}'Les raisons d’un échec
Un code stable dans failure_code, et une phrase prête dans payer_message.
| failure_code | Ce qui s’est passé | Ce que votre écran propose |
|---|---|---|
| insufficient_funds | Solde insuffisant | Un autre numéro, ou relancer plus tard |
| payer_declined | Le payeur refuse | Relancer s’il le demande |
| timeout | Pas de validation à temps | Relancer |
| invalid_phone | Numéro inconnu | Corriger le numéro |
| operator_limit | Plafond de l’opérateur | Un autre numéro ou un autre montant |
| operator_unavailable | Opérateur injoignable | Réessayer plus tard, ou un autre opérateur |
| declined | Refusé | Ne pas insister |
| unknown | Autre réponse | Relancer |
Bonnes habitudes
- La clé secrète vit sur votre serveur. Votre application parle à votre serveur, jamais à Payiz.
- Restreignez la clé aux adresses IP de vos serveurs.
- Une Idempotency-Key tirée de la commande : un rejeu ne relance jamais le téléphone.
- Livrez sur payment.succeeded, et sur rien d’autre.
- Une demande à la fois : attendez son issue avant de relancer.
Passer au réel
En test, tous les espaces peuvent lancer des demandes : les deux derniers chiffres du numéro choisissent l’issue (voir Tester). En réel, le direct s’ouvre avec votre palier, et votre espace vous dit s’il l’est ; Passer au réel dit le reste.