Aller au contenu

SDKs mobiles

Une interface de paiement native pour les applications Flutter, React Native, Android et iOS.

Les SDKs mobiles de Wajub vous permettent d'encaisser des paiements Mobile Money, par carte et par portefeuille dans votre application, avec une interface de paiement prête à l'emploi. Choisissez ci-dessous le package de votre plateforme.

Choisir votre plateforme

PlateformePackageVersionVersion minimaleOuvrir l'interface avec
Flutterwajub_mobile, sur pub.dev1.1.1Flutter 3.24presentWajubCheckout(context, options)
React Native@wajub/react-native, sur npm1.1.1React Native 0.74, React 18usePayment().present(options)
Androidcom.wajub:wajub-mobile-compose, sur Maven Central1.2.1Android 7.0, API 24PaymentSheet(options) { result -> }
iOSWajubMobileUI, avec Swift Package Manager1.0.0iOS 15WajubCheckout.present(options, from:)

L'interface propose le Mobile Money, la carte et les portefeuilles en un geste. Les autres moyens de paiement, comme le virement bancaire ou la crypto, n'y sont pas proposés.

Le parcours d'un paiement

Lieu d'exécution de chaque partie
Your server                            Your app
───────────                            ────────
POST /payments with sk.
  returns authorization_token   ──▶    present({ sessionToken })
                                         │
                                         ├─ the payer picks a method and pays
                                         ├─ approval, confirmation step or payment page
                                         └─ the sheet waits for the outcome
                                             │
                                         complete · processing · failed · cancelled
webhook payment.succeeded
  fulfils the order

Le jeton est le seul identifiant détenu par l'application. Il est limité à un paiement, expire et ne permet pas de lister, de rembourser ou de lire quoi que ce soit d'autre sur votre compte. Votre clé secrète reste sur votre serveur.

Le webhook reste responsable de la livraison de la commande

Le résultat que reçoit l'application est ce que le payeur a vu, pas une preuve de paiement. Une approbation Mobile Money peut arriver après la fermeture de l'application, et un téléphone peut perdre le réseau pendant l'approbation. Utilisez le résultat pour choisir l'écran suivant, puis confirmez avec GET /payments/{id} ou le webhook payment.succeeded avant de livrer.

États

Chaque état est un écran de l'interface, et votre callback onStateChange reçoit son nom.

ÉtatCe que voit le payeur
INITIATEDLa liste des moyens de paiement
COLLECTING_DETAILSLe formulaire du moyen choisi
PROCESSINGLe formulaire, son bouton Payer occupé, ou l'écran du code de paiement pendant l'envoi du code
APPROVAL_REQUIRED« Validez le paiement sur votre téléphone »
USSD_REQUIRED« Composez ce code »
PAYER_OTP_REQUIRED« Générez votre code de paiement » : les étapes, le code à composer, le montant exact à saisir et un champ pour le code. Flutter, React Native et Android
OTP_REQUIRED, PIN_REQUIRED, PHONE_REQUIRED, BIRTHDAY_REQUIRED, ADDRESS_REQUIREDUne étape de confirmation
3DS_REQUIREDLe 3-D Secure dans le navigateur, ou en sandbox un code envoyé par e-mail
VERIFYINGL'écran de l'étape pendant la vérification de sa réponse
PENDING« Paiement en cours », avec Continuer le paiement quand une page de paiement peut être rouverte
SUCCESSL'écran de succès : montant, marchand, référence et lien vers le reçu
FAILEDL'écran d'échec, avec Réessayer quand l'erreur le permet
EXPIRED« Ce paiement a expiré »
CANCELLED« Paiement annulé »

SUCCESS, EXPIRED et CANCELLED sont définitifs. Un paiement déjà payé à l'ouverture de l'interface affiche l'écran de succès, et un paiement terminé affiche un avis et signale une erreur de chargement.

Résultats

L'appel qui présente l'interface se résout une seule fois, à sa fermeture, avec l'un de quatre résultats.

RésultatQuandQue faire
completeL'interface s'est fermée après l'écran de succès, qui se ferme seul après 3 secondes sauf indication contraire de autoCloseSuccessConfirmer sur votre serveur, puis livrer
processingL'interface s'est fermée pendant un paiement en cours. L'argent peut encore bougerAfficher un écran d'attente : votre serveur apprend l'issue par webhook
failedL'interface s'est fermée sur un échec, un paiement expiré, une erreur de chargement, ou un paiement annulé ailleursAfficher le message de l'erreur
cancelledLe payeur a touché Annuler le paiement (payer_cancelled), a fermé l'interface avant de payer (dismissed), ou l'écran qui l'a présentée a disparu avant (host_gone)Créer un nouveau paiement pour le prochain essai

L'appel ne reste jamais en suspens. Quand l'écran qui a présenté l'interface disparaît, il se résout en cancelled avant tout paiement, en processing dès qu'un paiement a commencé et en complete après un succès, et il n'annule pas le paiement. Présenter une deuxième interface pendant qu'une autre est ouverte échoue avec sheet_already_presented. Si le système tue votre application, rien ne se résout : au lancement suivant, lisez l'issue sur votre serveur.

Annuler et fermer

Le payeur ferme l'interface avec son bouton de fermeture ou d'un balayage.

Le payeurRésultatLe paiement
Touche Annuler le paiementcancelled, payer_cancelledAnnulé
Ferme l'interface avant de payer, sur l'écran du code de paiement, ou de retour sur le formulaire après un refuscancelled, dismissedAnnulé, sauf si cancelOnDismiss vaut false
La ferme sur l'écran d'échecfailed, avec l'erreur que le payeur a vueAnnulé s'il peut encore l'être, sauf si cancelOnDismiss vaut false
La ferme pendant un paiement en cours : approbation sur le téléphone, code à composer, étape de confirmation ou attenteprocessingContinue : confirmez sur votre serveur
La ferme après l'écran de succèscompletePayé

Un paiement annulé l'est pour de bon, et Wajub envoie le webhook payment.cancelled. Avec cancelOnDismiss: false, fermer avant de payer laisse le paiement ouvert : vous pouvez présenter l'interface à nouveau avec le même jeton.

L'interface n'affiche jamais un échec dont elle n'est pas sûre : elle affiche « Paiement en cours » et continue d'attendre. Fermée à ce moment, elle se résout en processing.

Mobile Money

Un seul formulaire couvre tous les opérateurs. Le payeur choisit le pays et l'opérateur et saisit le numéro, mis en forme pendant la saisie. Le préfixe du numéro présélectionne son opérateur, et un numéro qui appartient à un autre opérateur est signalé avant tout envoi. Après Payer, l'interface demande au payeur de valider le paiement sur son téléphone, ou de composer un code, et attend l'issue.

Certains opérateurs, comme Orange Money au Burkina Faso, n'acceptent un paiement qu'avec un code que le payeur génère d'abord dans le menu de l'opérateur. Sur Flutter, React Native et Android, le formulaire le signale quand Wajub le sait à l'avance ; dans tous les cas, après Payer, l'interface montre comment obtenir le code, le code à composer et le montant exact à saisir, puis prend le code. Un code que l'opérateur refuse peut être saisi de nouveau, avec les essais restants quand ils sont connus ; après trois refus, le payeur revient au formulaire pour payer autrement.

Partout où l'interface affiche un montant, sur Payer et sur chaque écran, c'est ce que paie le payeur : le montant du paiement, plus les frais Wajub quand le payeur les supporte (bearer: customer). Sur Flutter, React Native et Android, il suit le moyen ou l'opérateur que le payeur choisit.

Option mobileMoneyEffet
countryLe pays de départ, en ISO-2. Sans elle, le pays du payeur quand il est proposé
countryLockedMasque le sélecteur de pays
operatorModechoose liste les opérateurs (par défaut). detect affiche l'opérateur détecté comme un badge dans le champ du numéro

Cartes

Selon le paiement, le payeur paie par carte à l'un de ces trois endroits.

  • Le formulaire de carte de Stripe, dans l'interface. Intégré aux SDKs Flutter et Android. React Native a besoin du package facultatif @stripe/stripe-react-native, et sur iOS votre application fournit un CardCollector construit avec le SDK de Stripe. Chaque page de plateforme indique quoi ajouter.
  • Une page sécurisée du prestataire de paiement, ouverte dans le navigateur. Donnez à returnUrl un lien universel ou un lien d'application https vers votre application pour y ramener le payeur. Sans lui, le payeur revient dans votre application de lui-même, et Continuer le paiement rouvre la page.
  • Le formulaire de carte de test de Wajub, en sandbox.

En live, le numéro de carte n'est saisi que dans le formulaire de Stripe ou sur la page du prestataire.

Étapes de confirmation

Certains paiements par carte demandent une information de plus au payeur après Payer. Chaque étape a son propre écran.

ÉtatLe payeur saisit
OTP_REQUIREDLe code qu'il a reçu
PIN_REQUIREDLe code PIN de la carte
PHONE_REQUIREDUn numéro de téléphone
BIRTHDAY_REQUIREDUne date de naissance
ADDRESS_REQUIREDUne adresse de facturation
3DS_REQUIREDLe 3-D Secure dans le navigateur, ou en sandbox le code envoyé par e-mail

Une mauvaise réponse garde l'écran et affiche les tentatives restantes. Une étape qui expire ou épuise ses tentatives se termine sur l'écran d'échec.

Apparence

L'option appearance règle l'aspect de l'interface. Ses clés, préréglages et variables sont décrits dans Apparence.

  • Mode de couleur. light, dark ou auto, qui suit le téléphone.
  • Préréglages. stripe, night, flat et none.
  • Le thème de votre application. inherit: true reprend les couleurs de votre application ; chaque page de plateforme indique ce qu'il lit.
  • Branding du marchand. Ce que vous laissez vide vient du branding du marchand dans le Dashboard : logo, nom commercial et couleurs. Un marchand en marque blanche masque « Sécurisé par Wajub ».
  • Polices. Une fontFamily n'est utilisée que si votre application embarque la police.
  • Chargement. loader est un squelette ou un indicateur de chargement. readyTimeout, 15 secondes par défaut, est le temps de chargement accordé à l'interface avant qu'elle affiche une erreur avec Réessayer.

Erreurs

Chaque échec est une WajubError.

ChampUsage
typeapi_error, authentication_error, invalid_request_error, payment_error ou rate_limit_error
codeL'un des codes ci-dessous
messagePour le payeur, dans la langue de l'interface. Affichez-le tel quel
declineCodeSur un refus, le code de la banque ou de l'opérateur
retryableSi un nouvel essai peut aboutir
paramLe champ en cause
correlationIdL'identifiant de requête à citer au support de Wajub
retryAfterSecondsSur rate_limited, le temps d'attente
blockReferenceSur shield_blocked, la référence à citer au support de Wajub

React Native écrit ces champs en snake_case : decline_code, correlation_id, retry_after_seconds, block_reference.

GroupeCodesArrive dans
Chargementsession_not_found, session_terminal_expired, session_terminal_cancelled, session_terminal_failed, load_error et ready_timeout (nouvel essai possible), no_payment_methodonLoadError, puis le résultat failed
Connexionnetwork_error, timeout, server_error, rate_limited, request_failedonError
Paiementpayment_declined, insufficient_funds et les autres codes de refus (nouvel essai possible), payment_attempt_ended (nouvel essai possible, rien n'a été débité), payment_failed, payment_cancelled, session_expired, limit_exceeded, shield_blocked, merchant_not_verified, merchant_restricted, payment_method_restricted, country_restricted, currency_restricted, channel_not_accepted, unsupported_action, redirect_unavailableonError
Étapes de confirmationinvalid_otp, invalid_pin, invalid_phone, invalid_birthday, invalid_address, invalid_code (l'écran reste), otp_expired, pin_expired, phone_expired, birthday_expired, address_expired, max_attempts_exceeded, otp_attempts_exceeded (retour au formulaire), 3ds_failed, 3ds_rejected, 3ds_cancelled, 3ds_timeoutL'écran de l'étape, ou onError
Votre codesheet_already_presentedL'appel qui présente l'interface

Un code absent de cette liste, le code de refus propre à une banque par exemple, peut aussi vous parvenir : affichez message. Les erreurs de champ, un numéro de téléphone invalide par exemple, restent sur le formulaire et n'arrivent jamais dans onError.

Confidentialité

Les quatre SDKs, Flutter, React Native, Android et iOS, envoient les mêmes données. Quand le payeur paie, le SDK envoie à Wajub ce dont le paiement a besoin et, pour la prévention de la fraude, des informations de base sur l'appareil et un identifiant d'installation aléatoire, qui n'est pas l'identifiant publicitaire. Quand le payeur utilise le formulaire de carte de Stripe, le SDK de Stripe collecte aussi ce que Stripe documente pour ses propres contrôles antifraude.

Déclarez-le à côté de ce que votre application collecte elle-même.

Pour les étiquettes de confidentialité de l'App Store, déclarez-le lié à l'utilisateur, non utilisé pour le suivi, pour App Functionality, ce qui couvre le traitement du paiement et la prévention de la fraude.

App Store ConnectCe qu'envoie le SDK
Contact Info, NamePrénom et nom, ou titulaire de la carte, quand le moyen de paiement les demande
Contact Info, Email AddressQuand le paiement par carte la demande
Contact Info, Phone NumberLe numéro Mobile Money, ou un numéro de téléphone que demande un paiement par carte
Contact Info, Physical AddressAdresse, ville, code postal et pays, quand le paiement par carte les demande
Financial Info, Payment InfoLe compte Mobile Money, le jeton de carte Stripe, un code PIN de carte quand il est demandé, et les cartes de test en sandbox
Identifiers, Device IDL'identifiant d'installation aléatoire, pour la prévention de la fraude
Other DataUne date de naissance quand elle est demandée, et des informations de base sur l'appareil, pour la prévention de la fraude

Le SDK iOS embarque un manifeste de confidentialité, que Xcode intègre au rapport de confidentialité de votre application.

Pour la sécurité des données de Google Play, déclarez-le collecté pour App functionality et Fraud prevention, security, and compliance, partagé avec Wajub en tant que prestataire de paiement, chiffré en transit.

Sécurité des données de Google PlayCe qu'envoie le SDK
Personal info, NamePrénom et nom, ou titulaire de la carte, quand le moyen de paiement les demande
Personal info, Email addressQuand le paiement par carte la demande
Personal info, Phone numberLe numéro Mobile Money, ou un numéro de téléphone que demande un paiement par carte
Personal info, AddressAdresse, ville, code postal et pays, quand le paiement par carte les demande
Personal info, Other infoUne date de naissance, quand elle est demandée
Financial info, User payment infoLe compte Mobile Money, le jeton de carte Stripe, un code PIN de carte quand il est demandé, et les cartes de test en sandbox
Device or other IDsL'identifiant d'installation aléatoire et des informations de base sur l'appareil, pour la prévention de la fraude

Tests

Un paiement que votre serveur crée avec une clé de sandbox place tout le parcours en sandbox, interface comprise, et l'interface affiche un badge « Mode test ». Rien ne change dans l'application. Les numéros et cartes de test figurent dans Scénarios de test.

Que pensez-vous de ce contenu ?