Skip to content

حزم SDK للهاتف المحمول (المفاتيح العامة فقط) ​

تعرض حزم SDK للهاتف المحمول صفحة الدفع المستضافة من SOAMTAR داخل تطبيقك وتخبرك بكيفية انتهائها. لا تُنشئ هذه الحزم أي دفعة ولا تحتفظ بأي مفتاح سرّي: فهي تقبل المفاتيح العامة فقط (pk_test_… / pk_live_…) وترفض مفاتيح sk_….

المنصةالحزمةنقاط الدخول الرئيسية
iOS (Swift)SoamtarSDK (Swift Package) 1.0.1SoamtarCheckoutView، SoamtarCheckoutViewController
Android (Kotlin)com.soamtar:soamtar-android:1.1.0Soamtar.checkoutIntent()، SoamtarCheckoutActivity
Fluttersoamtar_sdk 1.0.1المكوّن SoamtarCheckout
React Native@soamtar/react-native 1.1.0المكوّن <Checkout />

التثبيت

لم تُنشر أي من هذه الحزم بعد في سجل عام: ثبّتها من مستودع SOAMTAR إلى حين نشرها.

آلية العمل ​

  1. يرسل التطبيق الطلب إلى خادمك الخلفي.
  2. يُنشئ خادمك الخلفي الدفعة باستخدام مفتاحه السرّي (POST/v1/payments) مع success_url وfailed_url، ثم يعيد data.payment_url (https://app.so-amtar.com/pay/checkout/{id}) إلى التطبيق.
  3. يفتح التطبيق payment_url عبر الحزمة. يُدخل الدافع رقم Orange Money الخاص به (+232 متبوعًا بـ 8 أرقام) ويوافق على الطلب على هاتفه برمز PIN الخاص بـ Orange Money. لا يمر رمز PIN أبدًا عبر تطبيقك.
  4. تعيد صفحة النتيجة المستضافة التوجيه إلى success_url أو failed_url. تتوقف الحزمة عند هذا الانتقال وتستدعي الدالة الخاصة بك.
  5. يؤكد خادمك الخلفي الحالة النهائية (webhook payment.success أو GET/v1/payments/{id}) قبل تسليم الطلب.

استدعاء الحزمة ليس إثباتًا للدفع

onSuccess / STATUS_SUCCESS يعني فقط أن WebView وصل إلى success_url. وحده webhook موثَّق أو قراءة من الـ API بمفتاحك السرّي يؤكد الطلب.

طلب الخادم الخلفي (مثال) ​

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"
  }'

أرسل payment_url إلى التطبيق مع نفس success_url / failed_url: تحتاجها الحزم لاكتشاف نهاية عملية الدفع. مع مفاتيح sk_test_ تمر الدفعة عبر المحاكاة على نفس المضيف.

استخدم مسارين مختلفين لـ success_url وfailed_url

تطابق حزم SDK الأربع التنقّل مع عناوين العودة تطابقًا تامًا في المخطط والمضيف والمسار. تُتجاهل سلسلة الاستعلام والجزء (fragment)، ولا تكون المطابقة أبدًا بالبادئة. يُفحص failed_url أولًا: إذا تشارك العنوانان المسار نفسه (مثل https://shop.example/return?status=ok وhttps://shop.example/return?status=ko)، فستُبلَّغ كل المدفوعات على أنها فاشلة. استخدم مسارين مختلفين، مثل /orders/42/paid و/orders/42/failed.

iOS (Swift) ​

المتطلبات: iOS 14+، Swift 5.7+، Xcode 14+.

التثبيت (Swift Package Manager) ​

في Xcode: File → Add Package Dependencies…، الرابط https://github.com/soamtar/soamtar-ios-sdk، المنتج SoamtarSDK. أو في Package.swift:

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

الإعداد (اختياري) ​

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 ​

الرمزالوصف
Soamtar.shared.configure(publicKey:baseURL:)يحفظ المفتاح العام. القيمة الافتراضية لـ baseURL هي https://app.so-amtar.com.
Soamtar.validatePublicKey(_:) throwsيرمي SoamtarError.invalidPublicKey إذا لم يبدأ المفتاح بـ pk_test_ / pk_live_.
Soamtar.shared.isCheckoutURL(_:) -> Booltrue لصفحة HTTPS من الشكل …/pay/checkout/{id} على المضيف المُعدّ.
SoamtarReturnURLs(success:failure:)قيم success_url / failed_url الخاصة بك؛ تقارن outcome(for:) البروتوكول والمضيف والمسار.
SoamtarCheckoutView(paymentUrl:returnURLs:onSuccess:onFailure:)صفحة دفع SwiftUI (WKWebView). يتلقى كل استدعاء الـ URL الذي تم الوصول إليه.
SoamtarCheckoutViewController(…)صفحة دفع UIKit، بنفس المعاملات.
SoamtarMoney.format(_:currency:)Decimal أو نص عشري ← "Le 1,250.00".

Android (Kotlin) ​

المتطلبات: Android API 21+، Kotlin 1.8+. يصرّح ملف manifest الخاص بالمكتبة بإذن INTERNET وبنشاط صفحة الدفع.

التثبيت ​

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

التهيئة ​

kotlin
import com.soamtar.sdk.Soamtar

Soamtar.init("pk_test_your_public_key")
// أي مفتاح غير pk_test_… / pk_live_… يرمي IllegalArgumentException.

فتح صفحة الدفع (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)
)

مع الواجهة القديمة onActivityResult:

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

الحالات المُعادة ​

الثابتالمعنى
SoamtarCheckoutActivity.STATUS_SUCCESSأعادت الصفحة المستضافة التوجيه إلى success_url
SoamtarCheckoutActivity.STATUS_FAILEDأعادت الصفحة المستضافة التوجيه إلى failed_url (فشل أو انتهاء صلاحية أو إلغاء)
SoamtarCheckoutActivity.STATUS_CANCELLEDأغلق الدافع صفحة الدفع قبل أي إعادة توجيه

يجب أن يكون payment_url رابط HTTPS على مضيف SOAMTAR (app.so-amtar.com). بدون successUrl / failedUrl يبقى الدافع على صفحة نتيجة SOAMTAR ويعيد النشاط STATUS_CANCELLED عند إغلاقها.

تتوقف صفحة الدفع عندما يكون للتنقّل المخطط والمضيف والمسار نفسها لـ failedUrl أو successUrl (مع تجاهل الاستعلام والجزء، ودون مطابقة بالبادئة أبدًا)؛ ويُفحص failedUrl أولًا.

عرض مبلغ ​

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 ​

المتطلبات: Dart 3.0+، Flutter 3.10+، webview_flutter 4.0+.

التثبيت ​

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

Android: أضف <uses-permission android:name="android.permission.INTERNET"/> إلى android/app/src/main/AndroidManifest.xml. iOS: لا حاجة لأي إعداد.

الاستخدام ​

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),
      ),
    );
  }
}

عرض مبلغ:

dart
SoamtarMoney.format('1250.00');                    // "Le 1,250.00"
SoamtarMoney.formatMinorUnits(BigInt.from(15000)); // "Le 150.00"
الرمزملاحظات
SoamtarClient(String publicKey, {Uri? baseUrl})pk_test_ / pk_live_ فقط. المضيف الافتراضي https://app.so-amtar.com. تتحقق isCheckoutUrl(url) من HTTPS والمضيف و/pay/checkout/….
SoamtarCheckout({paymentUrl, returnUrls, onSuccess, onFailure})مكوّن WebView؛ يطلق استدعاءً واحدًا مرة واحدة فقط.
SoamtarReturnUrls({success, failure})resultFor(uri) ← SoamtarCheckoutResult.success / .failure / null.
SoamtarMoney.format / formatMinorUnitsنص عشري أو سنتات صحيحة ← "Le 1,250.00" (بدون double أبدًا).

React Native ​

التثبيت ​

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

الاستخدام ​

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

const soamtar = new Client('pk_test_...'); // throws on a sk_ key

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)}
    />
  );
}
الخاصيةالوصف
paymentUrl (إلزامية)payment_url المُعاد من POST/v1/payments. يجب أن يكون https.
successUrlقيمة success_url التي أرسلتها. الوصول إليها يستدعي onSuccess(url) مرة واحدة.
failureUrlقيمة failed_url التي أرسلتها. الوصول إليها يستدعي onFailure(url) مرة واحدة.
onResult(url)تم الوصول إلى صفحة نتيجة SOAMTAR (/pay/result/{id}): أُرسلت الدفعة وجارٍ تأكيدها.
onError(message)رابط غير صالح أو انتقال محظور أو خطأ في تحميل WebView.
loaderColorلون مؤشر التحميل (الافتراضي #FF7900).

يوفّر Client أيضًا isTestMode (true مع مفاتيح pk_test_). داخل صفحة الدفع تُحمَّل صفحات https، وتُحظر روابط http: وjavascript: وdata:، وتُسلَّم البروتوكولات الأخرى (مثل tel:) إلى نظام التشغيل.

أمان الهاتف المحمول ​

  • المفاتيح العامة فقط: ترفض جميع الحزم المفاتيح السرّية (sk_…) التي يمكن استخراجها من ملف APK/IPA.
  • عرض ويب معزول: تعمل صفحة الدفع داخل WKWebView / WebView عبر HTTPS فقط. يؤكد الدافع برمز PIN الخاص بـ Orange Money على هاتفه؛ لا يمر رمز PIN أبدًا عبر تطبيقك.
  • لا تخزين: لا تحتفظ الحزم بأي بيانات على الجهاز.
  • تأكيد من جهة الخادم: التطبيق مجرد طبقة عرض لمعاملة أُنشئت وتأكدت على خادمك.

SOAMTAR Payment API Documentation.