Skip to content

SDK mobiles (clés publiques uniquement) ​

Les SDK mobiles affichent le checkout hébergé SOAMTAR dans votre application et vous indiquent comment il s'est terminé. Ils ne créent jamais de paiement et ne détiennent jamais de clé secrète : ils n'acceptent que des clés publiques (pk_test_… / pk_live_…) et refusent les clés sk_….

PlateformePaquetPoints d'entrée
iOS (Swift)SoamtarSDK (Swift Package) 1.0.1SoamtarCheckoutView, SoamtarCheckoutViewController
Android (Kotlin)com.soamtar:soamtar-android:1.1.0Soamtar.checkoutIntent(), SoamtarCheckoutActivity
Fluttersoamtar_sdk 1.0.1widget SoamtarCheckout
React Native@soamtar/react-native 1.1.0composant <Checkout />

Installation

Aucun de ces paquets n'est encore publié sur un registre public : installez-les depuis le dépôt SOAMTAR en attendant.

Fonctionnement ​

  1. L'application envoie la commande à votre backend.
  2. Votre backend crée le paiement avec sa clé secrète (POST/v1/payments), en indiquant votre success_url et votre failed_url, puis renvoie data.payment_url (https://app.so-amtar.com/pay/checkout/{id}) à l'application.
  3. L'application ouvre payment_url avec le SDK. Le payeur saisit son numéro Orange Money (+232 suivi de 8 chiffres) et valide la demande sur son téléphone avec son code PIN Orange Money. Le PIN ne transite jamais par votre application.
  4. La page de résultat hébergée redirige vers votre success_url ou votre failed_url. Le SDK s'arrête sur cette navigation et vous rappelle.
  5. Votre backend confirme le statut final (webhook payment.success, ou GET/v1/payments/{id}) avant de livrer la commande.

Le callback du SDK n'est pas une preuve de paiement

onSuccess / STATUS_SUCCESS signifie seulement que la WebView a atteint votre success_url. Seul un webhook vérifié ou une lecture de l'API avec votre clé secrète permet de valider une commande.

Requête côté backend (exemple) ​

bash
curl -X POST https://app.so-amtar.com/v1/payments \
  -H "Authorization: Bearer sk_test_xxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0c6f3a52-6a0e-4f43-9a0e-2a7f4b1d9e11" \
  -d '{
    "merchant_ref": "ORDER-42",
    "amount": "150.00",
    "currency": "SLE",
    "provider": "orange_money_sl",
    "success_url": "https://shop.example/orders/42/paid",
    "failed_url": "https://shop.example/orders/42/failed"
  }'

Transmettez payment_url à l'application avec les mêmes success_url / failed_url : les SDK en ont besoin pour détecter la fin du checkout. Avec une clé sk_test_, le paiement passe par la simulation, sur le même hôte.

Utilisez deux chemins différents pour success_url et failed_url

Les quatre SDK comparent la navigation à vos URL de retour exactement sur le schéma, l'hôte et le chemin. La query string et le fragment sont ignorés, et ce n'est jamais une comparaison par préfixe. failed_url est testée en premier : si les deux URL ont le même chemin (par exemple https://shop.example/return?status=ok et https://shop.example/return?status=ko), tous les paiements sont signalés en échec. Utilisez des chemins distincts, comme /orders/42/paid et /orders/42/failed.

iOS (Swift) ​

Prérequis : iOS 14+, Swift 5.7+, Xcode 14+.

Installation (Swift Package Manager) ​

Dans Xcode : File → Add Package Dependencies…, URL https://github.com/soamtar/soamtar-ios-sdk, produit SoamtarSDK. Ou dans Package.swift :

swift
.package(url: "https://github.com/soamtar/soamtar-ios-sdk", from: "1.0.1")

Configuration (facultative) ​

swift
import SoamtarSDK

Soamtar.shared.configure(publicKey: "pk_test_your_public_key")
// Anything other than pk_test_ / pk_live_ stops the app (fatalError).

SwiftUI ​

swift
import SwiftUI
import SoamtarSDK

struct PayButton: View {
    let paymentUrl: URL                 // from your backend
    @State private var showCheckout = false

    private let returnURLs = SoamtarReturnURLs(
        success: URL(string: "https://shop.example/orders/42/paid")!,
        failure: URL(string: "https://shop.example/orders/42/failed")!
    )

    var body: some View {
        Button("Pay \(SoamtarMoney.format("150.00") ?? "")") { showCheckout = true }  // "Pay Le 150.00"
            .sheet(isPresented: $showCheckout) {
                SoamtarCheckoutView(
                    paymentUrl: paymentUrl,
                    returnURLs: returnURLs,
                    onSuccess: { _ in showCheckout = false /* then confirm with your backend */ },
                    onFailure: { _ in showCheckout = false }
                )
            }
    }
}

UIKit ​

swift
let checkout = SoamtarCheckoutViewController(
    paymentUrl: paymentUrl,
    returnURLs: returnURLs,
    onSuccess: { [weak self] _ in self?.dismiss(animated: true) },
    onFailure: { [weak self] _ in self?.dismiss(animated: true) }
)
present(checkout, animated: true)

API ​

SymboleDescription
Soamtar.shared.configure(publicKey:baseURL:)Enregistre la clé publique. baseURL vaut par défaut https://app.so-amtar.com.
Soamtar.validatePublicKey(_:) throwsLève SoamtarError.invalidPublicKey si la clé ne commence pas par pk_test_ / pk_live_.
Soamtar.shared.isCheckoutURL(_:) -> Booltrue pour une page HTTPS …/pay/checkout/{id} de l'hôte configuré.
SoamtarReturnURLs(success:failure:)Vos success_url / failed_url ; outcome(for:) compare exactement schéma, hôte et chemin (query ignorée, failed_url testée en premier).
SoamtarCheckoutView(paymentUrl:returnURLs:onSuccess:onFailure:)Checkout SwiftUI (WKWebView). Chaque callback reçoit l'URL atteinte.
SoamtarCheckoutViewController(…)Checkout UIKit, mêmes paramètres.
SoamtarMoney.format(_:currency:)Decimal ou chaîne décimale → "Le 1,250.00".

Android (Kotlin) ​

Prérequis : Android API 21+, Kotlin 1.8+. Le manifeste de la bibliothèque déclare la permission INTERNET et l'activité de checkout.

Installation ​

groovy
dependencies {
    implementation 'com.soamtar:soamtar-android:1.1.0'
}

Initialisation ​

kotlin
import com.soamtar.sdk.Soamtar

Soamtar.init("pk_test_your_public_key")
// Toute clé autre que pk_test_… / pk_live_… lève IllegalArgumentException.

Ouvrir le checkout (Activity Result API) ​

kotlin
import com.soamtar.sdk.ui.SoamtarCheckoutActivity

private val checkoutLauncher = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { result ->
    when (result.data?.getStringExtra(SoamtarCheckoutActivity.RESULT_STATUS)) {
        SoamtarCheckoutActivity.STATUS_SUCCESS -> showPending("Confirming your payment…")
        SoamtarCheckoutActivity.STATUS_FAILED -> showError("Payment not completed.")
        else -> showPending("Checking your payment…") // closed by the payer
    }
    refreshOrderFromBackend() // the backend status is the source of truth
}

// paymentUrl, successUrl and failedUrl come from your backend
checkoutLauncher.launch(
    Soamtar.checkoutIntent(this, paymentUrl, successUrl = successUrl, failedUrl = failedUrl)
)

Avec l'ancienne API onActivityResult :

kotlin
Soamtar.checkout(this, paymentUrl, REQUEST_PAY, successUrl, failedUrl)

Statuts renvoyés ​

ConstanteSignification
SoamtarCheckoutActivity.STATUS_SUCCESSLa page hébergée a redirigé vers success_url
SoamtarCheckoutActivity.STATUS_FAILEDLa page hébergée a redirigé vers failed_url (échec, expiration ou annulation)
SoamtarCheckoutActivity.STATUS_CANCELLEDLe payeur a fermé le checkout avant toute redirection

payment_url doit être une URL HTTPS de l'hôte SOAMTAR (app.so-amtar.com). Sans successUrl / failedUrl, le payeur reste sur la page de résultat SOAMTAR et l'activité renvoie STATUS_CANCELLED quand il la ferme.

La navigation s'arrête quand une page a le même schéma, le même hôte et le même chemin que failedUrl ou successUrl (query et fragment ignorés, jamais par préfixe) ; failedUrl est testée en premier.

Afficher un montant ​

kotlin
SoamtarMoney.formatLe(BigDecimal("1250"))   // "Le 1,250.00"
SoamtarMoney.formatLe("150.5")              // "Le 150.50" (null)
Soamtar.formatLe("2000000.00")              // "Le 2,000,000.00"

Flutter ​

Prérequis : Dart 3.0+, Flutter 3.10+, webview_flutter 4.0+.

Installation ​

yaml
dependencies:
  soamtar_sdk:
    git:
      url: https://github.com/soamtar/soamtar_flutter_sdk
      ref: v1.0.1
bash
flutter pub get

Android : ajoutez <uses-permission android:name="android.permission.INTERNET"/> dans android/app/src/main/AndroidManifest.xml. iOS : rien à configurer.

Utilisation ​

dart
import 'package:flutter/material.dart';
import 'package:soamtar_sdk/soamtar_sdk.dart';

class PaymentPage extends StatelessWidget {
  const PaymentPage({super.key, required this.paymentUrl});

  /// `payment_url` received from your backend.
  final String paymentUrl;

  @override
  Widget build(BuildContext context) {
    final client = SoamtarClient('pk_test_your_public_key'); // ArgumentError on sk_
    if (!client.isCheckoutUrl(paymentUrl)) {
      return const Center(child: Text('Invalid payment link.'));
    }

    return Scaffold(
      appBar: AppBar(title: const Text('Pay with Orange Money')),
      body: SoamtarCheckout(
        paymentUrl: Uri.parse(paymentUrl),
        returnUrls: SoamtarReturnUrls(
          success: Uri.parse('https://shop.example/orders/42/paid'),
          failure: Uri.parse('https://shop.example/orders/42/failed'),
        ),
        onSuccess: (_) => Navigator.pop(context, true),  // then confirm with your backend
        onFailure: (_) => Navigator.pop(context, false),
      ),
    );
  }
}

Afficher un montant :

dart
SoamtarMoney.format('1250.00');                    // "Le 1,250.00"
SoamtarMoney.formatMinorUnits(BigInt.from(15000)); // "Le 150.00"
SymboleRemarques
SoamtarClient(String publicKey, {Uri? baseUrl})pk_test_ / pk_live_ uniquement. Hôte par défaut https://app.so-amtar.com. isCheckoutUrl(url) vérifie HTTPS, l'hôte et /pay/checkout/….
SoamtarCheckout({paymentUrl, returnUrls, onSuccess, onFailure})Widget WebView ; déclenche un seul callback, une seule fois.
SoamtarReturnUrls({success, failure})resultFor(uri) → SoamtarCheckoutResult.success / .failure / null (schéma, hôte et chemin exacts ; failure testé en premier).
SoamtarMoney.format / formatMinorUnitsChaîne décimale ou centimes entiers → "Le 1,250.00" (jamais de double).

React Native ​

Installation ​

bash
npm install @soamtar/react-native react-native-webview

Utilisation ​

jsx
import { Client, Checkout } from '@soamtar/react-native';

const soamtar = new Client('pk_test_...'); // erreur si ce n'est pas pk_test_… / pk_live_…

export function PayScreen({ navigation, route }) {
  // payment_url returned by your backend (must be https)
  const paymentUrl = soamtar.getCheckoutUrl(route.params.paymentUrl);

  return (
    <Checkout
      paymentUrl={paymentUrl}
      successUrl="https://shop.example/orders/42/paid"
      failureUrl="https://shop.example/orders/42/failed"
      onSuccess={() => navigation.replace('OrderStatus', { orderId: route.params.orderId })}
      onFailure={() => navigation.replace('PaymentFailed')}
      onError={(message) => console.warn(message)}
    />
  );
}
PropDescription
paymentUrl (obligatoire)payment_url renvoyée par POST/v1/payments. Doit être en https.
successUrlLa success_url envoyée. L'atteindre (même schéma, hôte avec port et chemin ; query ignorée) appelle onSuccess(url) une fois.
failureUrlLa failed_url envoyée. Testée avant successUrl. L'atteindre appelle onFailure(url) une fois.
onResult(url)La page de résultat SOAMTAR (/pay/result/{id}) est atteinte : le paiement a été soumis et est en cours de confirmation.
onError(message)URL invalide, navigation bloquée ou erreur de chargement de la WebView.
loaderColorCouleur du spinner (par défaut #FF7900).

Client expose aussi isTestMode (true pour une clé pk_test_). Dans le checkout, les pages https se chargent, les URL http:, javascript: et data: sont bloquées, et les autres schémas (comme tel:) sont confiés au système d'exploitation.

Sécurité mobile ​

  • Clés publiques uniquement : tous les SDK n'acceptent que les clés pk_test_… / pk_live_… et refusent les clés secrètes (sk_…), qui pourraient être extraites de l'APK/IPA.
  • Vue web isolée : la page de paiement s'exécute dans une WKWebView / WebView, en HTTPS uniquement. Le payeur confirme avec son code PIN Orange Money sur son propre téléphone ; le PIN ne passe jamais par votre application.
  • Aucun stockage : les SDK ne conservent aucune donnée sur l'appareil.
  • Confirmation côté serveur : l'application n'est qu'une couche d'affichage pour une transaction créée et confirmée sur votre serveur.

SOAMTAR Payment API Documentation.